code.vegaprotocol.io/vega@v0.79.0/cmd/vega/commands/verify/genesis_test.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package verify_test
    17  
    18  import (
    19  	"encoding/json"
    20  	"os"
    21  	"path/filepath"
    22  	"testing"
    23  
    24  	"code.vegaprotocol.io/vega/cmd/vega/commands/verify"
    25  	"code.vegaprotocol.io/vega/core/assets"
    26  	"code.vegaprotocol.io/vega/core/genesis"
    27  	"code.vegaprotocol.io/vega/core/validators"
    28  
    29  	"github.com/stretchr/testify/assert"
    30  	"github.com/stretchr/testify/require"
    31  )
    32  
    33  func TestGenesis(t *testing.T) {
    34  	t.Run("verify default genesis", testVerifyDefaultGenesis)
    35  	t.Run("verify ERC20 assets", testVerifyERC20Assets)
    36  	t.Run("verify builtin assets", testVerifyBuiltinAssets)
    37  	t.Run("verify netparams", testVerifyNetworkParams)
    38  	t.Run("verify validators", TestVerifyValidators)
    39  	t.Run("verify unknown appstate field", testUnknownAppStateField)
    40  }
    41  
    42  func testVerifyDefaultGenesis(t *testing.T) {
    43  	testFile := writeGenesisFileWithState(t, genesis.DefaultState())
    44  
    45  	cmd := verify.GenesisCmd{}
    46  	assert.NoError(t, cmd.Execute([]string{testFile}))
    47  }
    48  
    49  func testVerifyBuiltinAssets(t *testing.T) {
    50  	cmd := verify.GenesisCmd{}
    51  
    52  	// LP stake not a bignum
    53  	gs := genesis.DefaultState()
    54  	gs.Assets["FAILURE"] = assets.AssetDetails{
    55  		Quantum: "FAILURE",
    56  		Source: &assets.Source{
    57  			BuiltinAsset: &assets.BuiltinAsset{
    58  				MaxFaucetAmountMint: "100",
    59  			},
    60  		},
    61  	}
    62  
    63  	assert.Error(t, cmd.Execute([]string{writeGenesisFileWithState(t, gs)}))
    64  
    65  	// Max faucet amount not a bignum
    66  	gs = genesis.DefaultState()
    67  	gs.Assets["FAILURE"] = assets.AssetDetails{
    68  		Quantum: "100",
    69  		Source: &assets.Source{
    70  			BuiltinAsset: &assets.BuiltinAsset{
    71  				MaxFaucetAmountMint: "FAILURE",
    72  			},
    73  		},
    74  	}
    75  
    76  	assert.Error(t, cmd.Execute([]string{writeGenesisFileWithState(t, gs)}))
    77  
    78  	// Completely Valid
    79  	gs = genesis.DefaultState()
    80  	gs.Assets["FAILURE"] = assets.AssetDetails{
    81  		Quantum: "100",
    82  		Source: &assets.Source{
    83  			BuiltinAsset: &assets.BuiltinAsset{
    84  				MaxFaucetAmountMint: "100",
    85  			},
    86  		},
    87  	}
    88  
    89  	assert.NoError(t, cmd.Execute([]string{writeGenesisFileWithState(t, gs)}))
    90  }
    91  
    92  func testVerifyERC20Assets(t *testing.T) {
    93  	cmd := verify.GenesisCmd{}
    94  
    95  	// Invalid ID
    96  	gs := genesis.DefaultState()
    97  	gs.Assets["tooshort"] = assets.AssetDetails{
    98  		Quantum: "100",
    99  		Source: &assets.Source{
   100  			Erc20: &assets.Erc20{
   101  				ContractAddress: "0xBC944ba38753A6fCAdd634Be98379330dbaB3Eb8",
   102  				ChainID:         "1",
   103  			},
   104  		},
   105  	}
   106  	assert.Error(t, cmd.Execute([]string{writeGenesisFileWithState(t, gs)}))
   107  
   108  	// Invalid contract address
   109  	gs = genesis.DefaultState()
   110  	gs.Assets["b4f2726571fbe8e33b442dc92ed2d7f0d810e21835b7371a7915a365f07ccd9b"] = assets.AssetDetails{
   111  		Quantum: "100",
   112  		Source: &assets.Source{
   113  			Erc20: &assets.Erc20{
   114  				ContractAddress: "invalid",
   115  				ChainID:         "1",
   116  			},
   117  		},
   118  	}
   119  	assert.Error(t, cmd.Execute([]string{writeGenesisFileWithState(t, gs)}))
   120  
   121  	// Completely valid
   122  	gs = genesis.DefaultState()
   123  	gs.Assets["b4f2726571fbe8e33b442dc92ed2d7f0d810e21835b7371a7915a365f07ccd9b"] = assets.AssetDetails{
   124  		Quantum: "100",
   125  		Source: &assets.Source{
   126  			Erc20: &assets.Erc20{
   127  				ContractAddress: "0xF0a9b5d3a00b53362F9b73892124743BAaE526c4",
   128  				ChainID:         "1",
   129  			},
   130  		},
   131  	}
   132  
   133  	assert.NoError(t, cmd.Execute([]string{writeGenesisFileWithState(t, gs)}))
   134  }
   135  
   136  func testVerifyNetworkParams(t *testing.T) {
   137  	cmd := verify.GenesisCmd{}
   138  
   139  	// Check for invalid network parameter
   140  	gs := genesis.DefaultState()
   141  	gs.NetParams["NOTREAL"] = "something"
   142  	assert.Error(t, cmd.Execute([]string{writeGenesisFileWithState(t, gs)}))
   143  
   144  	// Check for network parameter with bad value
   145  	gs = genesis.DefaultState()
   146  	gs.NetParams["snapshot.interval.length"] = "always"
   147  	assert.Error(t, cmd.Execute([]string{writeGenesisFileWithState(t, gs)}))
   148  
   149  	// Check for invalid checkpoint overwrite network parameter
   150  	gs = genesis.DefaultState()
   151  	gs.NetParamsOverwrite = []string{"NOTREAL"}
   152  	assert.Error(t, cmd.Execute([]string{writeGenesisFileWithState(t, gs)}))
   153  }
   154  
   155  func TestVerifyValidators(t *testing.T) {
   156  	cmd := verify.GenesisCmd{}
   157  
   158  	valid := validators.ValidatorData{
   159  		ID:              "eb2374c1e8e746cb5fbda66ee69eba0c2c551bea8793afe8c5a239b9763d14bf",
   160  		VegaPubKey:      "Adf2e74b372be36f6373ea9c2c4cf496310852228c54867726dbb77528b35761",
   161  		VegaPubKeyIndex: 4,
   162  		EthereumAddress: "0xF0a9b5d3a00b53362F9b73892124743BAaE526c4",
   163  		TmPubKey:        "2D2TXGN2GD4GTCQV9sbrXw7RVb3td7S4pWq6v3wIpvI=",
   164  	}
   165  	// Valid validator information
   166  	gs := genesis.DefaultState()
   167  	gs.Validators[valid.TmPubKey] = valid
   168  	assert.NoError(t, cmd.Execute([]string{writeGenesisFileWithState(t, gs)}))
   169  
   170  	// Mismatch TM key
   171  	gs = genesis.DefaultState()
   172  	gs.Validators["WRONG"] = valid
   173  	assert.Error(t, cmd.Execute([]string{writeGenesisFileWithState(t, gs)}))
   174  
   175  	// Invalid pubkey index
   176  	gs = genesis.DefaultState()
   177  	invalid := valid
   178  	invalid.VegaPubKeyIndex = 0
   179  	gs.Validators[valid.TmPubKey] = invalid
   180  	assert.Error(t, cmd.Execute([]string{writeGenesisFileWithState(t, gs)}))
   181  
   182  	// invalid ID
   183  	gs = genesis.DefaultState()
   184  	invalid = valid
   185  	invalid.ID = "too short"
   186  	gs.Validators[valid.TmPubKey] = invalid
   187  	assert.Error(t, cmd.Execute([]string{writeGenesisFileWithState(t, gs)}))
   188  
   189  	// invalid pubkey
   190  	gs = genesis.DefaultState()
   191  	invalid = valid
   192  	invalid.VegaPubKey = "too short"
   193  	gs.Validators[valid.TmPubKey] = invalid
   194  	assert.Error(t, cmd.Execute([]string{writeGenesisFileWithState(t, gs)}))
   195  }
   196  
   197  func testUnknownAppStateField(t *testing.T) {
   198  	cmd := verify.GenesisCmd{}
   199  	gs := genesis.DefaultState()
   200  
   201  	// Marshall and unmarshal unstructured so we can add an unknown field
   202  	var unstructured map[string]interface{}
   203  	b, err := json.Marshal(gs)
   204  	require.NoError(t, err)
   205  
   206  	err = json.Unmarshal(b, &unstructured)
   207  	require.NoError(t, err)
   208  
   209  	unstructured["unknownfield"] = "unknownvalue"
   210  	n, err := json.Marshal(unstructured)
   211  	require.NoError(t, err)
   212  
   213  	testFile := filepath.Join(t.TempDir(), "genesistest.json")
   214  
   215  	genesis := struct {
   216  		AppState json.RawMessage `json:"app_state"`
   217  	}{AppState: json.RawMessage(n)}
   218  
   219  	// marshall it
   220  	file, _ := json.MarshalIndent(genesis, "", " ")
   221  	err = os.WriteFile(testFile, file, 0o644)
   222  	require.NoError(t, err)
   223  
   224  	// expected failure given unknown field
   225  	assert.Error(t, cmd.Execute([]string{testFile}))
   226  }
   227  
   228  func writeGenesisFileWithState(t *testing.T, gs genesis.State) string {
   229  	t.Helper()
   230  
   231  	genesisFilePath := filepath.Join(t.TempDir(), "genesistest.json")
   232  
   233  	genesisPayload := struct {
   234  		AppState        genesis.State `json:"app_state"`
   235  		ConsensusParams struct {
   236  			Block struct {
   237  				TimeIotaMs string `json:"time_iota_ms"`
   238  			} `json:"block"`
   239  		} `json:"consensus_params"`
   240  	}{AppState: gs}
   241  	genesisPayload.ConsensusParams.Block.TimeIotaMs = "1"
   242  
   243  	file, err := json.MarshalIndent(genesisPayload, "", " ")
   244  	require.NoError(t, err)
   245  
   246  	err = os.WriteFile(genesisFilePath, file, 0o644)
   247  	require.NoError(t, err)
   248  
   249  	return genesisFilePath
   250  }