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 }