github.com/cosmos/cosmos-sdk@v0.50.10/x/genutil/gentx_test.go (about) 1 package genutil_test 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "math/rand" 8 "testing" 9 "time" 10 11 "github.com/golang/mock/gomock" 12 "github.com/stretchr/testify/suite" 13 14 "cosmossdk.io/core/genesis" 15 "cosmossdk.io/math" 16 storetypes "cosmossdk.io/store/types" 17 18 "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" 19 "github.com/cosmos/cosmos-sdk/testutil" 20 simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" 21 sdk "github.com/cosmos/cosmos-sdk/types" 22 moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" 23 banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" 24 "github.com/cosmos/cosmos-sdk/x/genutil" 25 genutiltestutil "github.com/cosmos/cosmos-sdk/x/genutil/testutil" 26 "github.com/cosmos/cosmos-sdk/x/genutil/types" 27 stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 28 ) 29 30 var ( 31 priv1 = secp256k1.GenPrivKey() 32 priv2 = secp256k1.GenPrivKey() 33 pk1 = priv1.PubKey() 34 pk2 = priv2.PubKey() 35 addr1 = sdk.AccAddress(pk1.Address()) 36 addr2 = sdk.AccAddress(pk2.Address()) 37 desc = stakingtypes.NewDescription("testname", "", "", "", "") 38 comm = stakingtypes.CommissionRates{} 39 ) 40 41 // GenTxTestSuite is a test suite to be used with gentx tests. 42 type GenTxTestSuite struct { 43 suite.Suite 44 45 ctx sdk.Context 46 47 stakingKeeper *genutiltestutil.MockStakingKeeper 48 encodingConfig moduletestutil.TestEncodingConfig 49 msg1, msg2 *stakingtypes.MsgCreateValidator 50 } 51 52 func (suite *GenTxTestSuite) SetupTest() { 53 suite.encodingConfig = moduletestutil.MakeTestEncodingConfig(genutil.AppModuleBasic{}) 54 key := storetypes.NewKVStoreKey("a_Store_Key") 55 tkey := storetypes.NewTransientStoreKey("a_transient_store") 56 suite.ctx = testutil.DefaultContext(key, tkey) 57 58 ctrl := gomock.NewController(suite.T()) 59 suite.stakingKeeper = genutiltestutil.NewMockStakingKeeper(ctrl) 60 61 stakingtypes.RegisterInterfaces(suite.encodingConfig.InterfaceRegistry) 62 banktypes.RegisterInterfaces(suite.encodingConfig.InterfaceRegistry) 63 64 var err error 65 amount := sdk.NewInt64Coin(sdk.DefaultBondDenom, 50) 66 one := math.OneInt() 67 suite.msg1, err = stakingtypes.NewMsgCreateValidator( 68 sdk.ValAddress(pk1.Address()).String(), pk1, amount, desc, comm, one) 69 suite.NoError(err) 70 suite.msg2, err = stakingtypes.NewMsgCreateValidator( 71 sdk.ValAddress(pk2.Address()).String(), pk1, amount, desc, comm, one) 72 suite.NoError(err) 73 } 74 75 func (suite *GenTxTestSuite) setAccountBalance(balances []banktypes.Balance) json.RawMessage { 76 bankGenesisState := banktypes.GenesisState{ 77 Params: banktypes.Params{DefaultSendEnabled: true}, 78 Balances: []banktypes.Balance{ 79 { 80 Address: "cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh", 81 Coins: sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 1000000)}, 82 }, 83 { 84 Address: "cosmos1jv65s3grqf6v6jl3dp4t6c9t9rk99cd88lyufl", 85 Coins: sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 2059726)}, 86 }, 87 { 88 Address: "cosmos1k5lndq46x9xpejdxq52q3ql3ycrphg4qxlfqn7", 89 Coins: sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 100000000000000)}, 90 }, 91 }, 92 Supply: sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)}, 93 } 94 bankGenesisState.Balances = append(bankGenesisState.Balances, balances...) 95 for _, balance := range bankGenesisState.Balances { 96 bankGenesisState.Supply.Add(balance.Coins...) 97 } 98 bankGenesis, err := suite.encodingConfig.Amino.MarshalJSON(bankGenesisState) // TODO switch this to use Marshaler 99 suite.Require().NoError(err) 100 101 return bankGenesis 102 } 103 104 func (suite *GenTxTestSuite) TestSetGenTxsInAppGenesisState() { 105 var ( 106 txBuilder = suite.encodingConfig.TxConfig.NewTxBuilder() 107 genTxs []sdk.Tx 108 ) 109 110 testCases := []struct { 111 msg string 112 malleate func() 113 expPass bool 114 }{ 115 { 116 "one genesis transaction", 117 func() { 118 err := txBuilder.SetMsgs(suite.msg1) 119 suite.Require().NoError(err) 120 tx := txBuilder.GetTx() 121 genTxs = []sdk.Tx{tx} 122 }, 123 true, 124 }, 125 { 126 "two genesis transactions", 127 func() { 128 err := txBuilder.SetMsgs(suite.msg1, suite.msg2) 129 suite.Require().NoError(err) 130 tx := txBuilder.GetTx() 131 genTxs = []sdk.Tx{tx} 132 }, 133 true, 134 }, 135 } 136 137 for _, tc := range testCases { 138 suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { 139 suite.SetupTest() 140 cdc := suite.encodingConfig.Codec 141 txJSONEncoder := suite.encodingConfig.TxConfig.TxJSONEncoder() 142 143 tc.malleate() 144 appGenesisState, err := genutil.SetGenTxsInAppGenesisState(cdc, txJSONEncoder, make(map[string]json.RawMessage), genTxs) 145 146 suite.Require().NoError(err) 147 suite.Require().NotNil(appGenesisState[types.ModuleName]) 148 149 var genesisState types.GenesisState 150 err = cdc.UnmarshalJSON(appGenesisState[types.ModuleName], &genesisState) 151 suite.Require().NoError(err) 152 suite.Require().NotNil(genesisState.GenTxs) 153 }) 154 } 155 } 156 157 func (suite *GenTxTestSuite) TestValidateAccountInGenesis() { 158 var ( 159 appGenesisState = make(map[string]json.RawMessage) 160 coins sdk.Coins 161 ) 162 163 testCases := []struct { 164 msg string 165 malleate func() 166 expPass bool 167 }{ 168 { 169 "no accounts", 170 func() { 171 coins = sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)} 172 }, 173 false, 174 }, 175 { 176 "account without balance in the genesis state", 177 func() { 178 coins = sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)} 179 balances := banktypes.Balance{ 180 Address: addr2.String(), 181 Coins: sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 50)}, 182 } 183 appGenesisState[banktypes.ModuleName] = suite.setAccountBalance([]banktypes.Balance{balances}) 184 }, 185 false, 186 }, 187 { 188 "account without enough funds of default bond denom", 189 func() { 190 coins = sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 50)} 191 balances := banktypes.Balance{ 192 Address: addr1.String(), 193 Coins: sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 25)}, 194 } 195 appGenesisState[banktypes.ModuleName] = suite.setAccountBalance([]banktypes.Balance{balances}) 196 }, 197 false, 198 }, 199 { 200 "account with enough funds of default bond denom", 201 func() { 202 coins = sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 10)} 203 balances := banktypes.Balance{ 204 Address: addr1.String(), 205 Coins: sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 25)}, 206 } 207 appGenesisState[banktypes.ModuleName] = suite.setAccountBalance([]banktypes.Balance{balances}) 208 }, 209 true, 210 }, 211 } 212 for _, tc := range testCases { 213 suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { 214 suite.SetupTest() 215 cdc := suite.encodingConfig.Codec 216 217 stakingGenesis, err := cdc.MarshalJSON(&stakingtypes.GenesisState{Params: stakingtypes.DefaultParams()}) // TODO switch this to use Marshaler 218 suite.Require().NoError(err) 219 appGenesisState[stakingtypes.ModuleName] = stakingGenesis 220 221 tc.malleate() 222 err = genutil.ValidateAccountInGenesis( 223 appGenesisState, banktypes.GenesisBalancesIterator{}, 224 addr1, coins, cdc, 225 ) 226 227 if tc.expPass { 228 suite.Require().NoError(err) 229 } else { 230 suite.Require().Error(err) 231 } 232 }) 233 } 234 } 235 236 func (suite *GenTxTestSuite) TestDeliverGenTxs() { 237 var ( 238 genTxs []json.RawMessage 239 txBuilder = suite.encodingConfig.TxConfig.NewTxBuilder() 240 ) 241 242 testCases := []struct { 243 msg string 244 malleate func() 245 deliverTxFn genesis.TxHandler 246 expPass bool 247 }{ 248 { 249 "no signature supplied", 250 func() { 251 err := txBuilder.SetMsgs(suite.msg1) 252 suite.Require().NoError(err) 253 254 genTxs = make([]json.RawMessage, 1) 255 tx, err := suite.encodingConfig.TxConfig.TxJSONEncoder()(txBuilder.GetTx()) 256 suite.Require().NoError(err) 257 genTxs[0] = tx 258 }, 259 GenesisState1{}, 260 false, 261 }, 262 { 263 "success", 264 func() { 265 r := rand.New(rand.NewSource(time.Now().UnixNano())) 266 msg := banktypes.NewMsgSend(addr1, addr2, sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 1)}) 267 tx, err := simtestutil.GenSignedMockTx( 268 r, 269 suite.encodingConfig.TxConfig, 270 []sdk.Msg{msg}, 271 sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 10)}, 272 simtestutil.DefaultGenTxGas, 273 suite.ctx.ChainID(), 274 []uint64{7}, 275 []uint64{0}, 276 priv1, 277 ) 278 suite.Require().NoError(err) 279 280 genTxs = make([]json.RawMessage, 1) 281 genTx, err := suite.encodingConfig.TxConfig.TxJSONEncoder()(tx) 282 suite.Require().NoError(err) 283 genTxs[0] = genTx 284 }, 285 GenesisState2{}, 286 true, 287 }, 288 } 289 290 for _, tc := range testCases { 291 suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { 292 suite.SetupTest() 293 294 tc.malleate() 295 296 if tc.expPass { 297 suite.stakingKeeper.EXPECT().ApplyAndReturnValidatorSetUpdates(gomock.Any()).Return(nil, nil).AnyTimes() 298 suite.Require().NotPanics(func() { 299 genutil.DeliverGenTxs( 300 suite.ctx, genTxs, suite.stakingKeeper, tc.deliverTxFn, 301 suite.encodingConfig.TxConfig, 302 ) 303 }) 304 } else { 305 _, err := genutil.DeliverGenTxs( 306 suite.ctx, genTxs, suite.stakingKeeper, tc.deliverTxFn, 307 suite.encodingConfig.TxConfig, 308 ) 309 310 suite.Require().Error(err) 311 } 312 }) 313 } 314 } 315 316 func TestGenTxTestSuite(t *testing.T) { 317 suite.Run(t, new(GenTxTestSuite)) 318 } 319 320 type GenesisState1 struct{} 321 322 func (GenesisState1) ExecuteGenesisTx(_ []byte) error { 323 return errors.New("no signatures supplied") 324 } 325 326 type GenesisState2 struct{} 327 328 func (GenesisState2) ExecuteGenesisTx(tx []byte) error { 329 return nil 330 }