github.com/cosmos/cosmos-sdk@v0.50.10/x/slashing/simulation/operations_test.go (about) 1 package simulation_test 2 3 import ( 4 "fmt" 5 "math/rand" 6 "testing" 7 "time" 8 9 abci "github.com/cometbft/cometbft/abci/types" 10 cmttypes "github.com/cometbft/cometbft/types" 11 "github.com/cosmos/gogoproto/proto" 12 "github.com/stretchr/testify/suite" 13 14 "cosmossdk.io/depinject" 15 "cosmossdk.io/log" 16 "cosmossdk.io/math" 17 18 "github.com/cosmos/cosmos-sdk/client" 19 "github.com/cosmos/cosmos-sdk/codec" 20 codectypes "github.com/cosmos/cosmos-sdk/codec/types" 21 cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" 22 "github.com/cosmos/cosmos-sdk/runtime" 23 simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" 24 sdk "github.com/cosmos/cosmos-sdk/types" 25 simtypes "github.com/cosmos/cosmos-sdk/types/simulation" 26 authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" 27 bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" 28 banktestutil "github.com/cosmos/cosmos-sdk/x/bank/testutil" 29 distributionkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" 30 distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" 31 mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper" 32 minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" 33 slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" 34 "github.com/cosmos/cosmos-sdk/x/slashing/simulation" 35 "github.com/cosmos/cosmos-sdk/x/slashing/testutil" 36 "github.com/cosmos/cosmos-sdk/x/slashing/types" 37 stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" 38 stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 39 ) 40 41 type SimTestSuite struct { 42 suite.Suite 43 44 ctx sdk.Context 45 r *rand.Rand 46 accounts []simtypes.Account 47 48 app *runtime.App 49 legacyAmino *codec.LegacyAmino 50 codec codec.Codec 51 interfaceRegistry codectypes.InterfaceRegistry 52 txConfig client.TxConfig 53 accountKeeper authkeeper.AccountKeeper 54 bankKeeper bankkeeper.Keeper 55 stakingKeeper *stakingkeeper.Keeper 56 slashingKeeper slashingkeeper.Keeper 57 distrKeeper distributionkeeper.Keeper 58 mintKeeper mintkeeper.Keeper 59 } 60 61 func (suite *SimTestSuite) SetupTest() { 62 s := rand.NewSource(1) 63 suite.r = rand.New(s) 64 accounts := simtypes.RandomAccounts(suite.r, 4) 65 66 // create validator (non random as using a seed) 67 createValidator := func() (*cmttypes.ValidatorSet, error) { 68 account := accounts[0] 69 cmtPk, err := cryptocodec.ToCmtPubKeyInterface(account.PubKey) 70 if err != nil { 71 return nil, fmt.Errorf("failed to create pubkey: %w", err) 72 } 73 74 validator := cmttypes.NewValidator(cmtPk, 1) 75 76 return cmttypes.NewValidatorSet([]*cmttypes.Validator{validator}), nil 77 } 78 79 startupCfg := simtestutil.DefaultStartUpConfig() 80 startupCfg.ValidatorSet = createValidator 81 82 app, err := simtestutil.SetupWithConfiguration( 83 depinject.Configs( 84 testutil.AppConfig, 85 depinject.Supply(log.NewNopLogger()), 86 ), 87 startupCfg, 88 &suite.legacyAmino, 89 &suite.codec, 90 &suite.interfaceRegistry, 91 &suite.txConfig, 92 &suite.accountKeeper, 93 &suite.bankKeeper, 94 &suite.stakingKeeper, 95 &suite.mintKeeper, 96 &suite.slashingKeeper, 97 &suite.distrKeeper, 98 ) 99 100 suite.Require().NoError(err) 101 suite.app = app 102 suite.ctx = app.BaseApp.NewContext(false) 103 104 // remove genesis validator account 105 suite.accounts = accounts[1:] 106 107 initAmt := suite.stakingKeeper.TokensFromConsensusPower(suite.ctx, 200) 108 initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) 109 110 // add coins to the accounts 111 for _, account := range suite.accounts { 112 acc := suite.accountKeeper.NewAccountWithAddress(suite.ctx, account.Address) 113 suite.accountKeeper.SetAccount(suite.ctx, acc) 114 suite.Require().NoError(banktestutil.FundAccount(suite.ctx, suite.bankKeeper, account.Address, initCoins)) 115 } 116 117 suite.Require().NoError(suite.mintKeeper.Params.Set(suite.ctx, minttypes.DefaultParams())) 118 suite.Require().NoError(suite.mintKeeper.Minter.Set(suite.ctx, minttypes.DefaultInitialMinter())) 119 } 120 121 func TestSimTestSuite(t *testing.T) { 122 suite.Run(t, new(SimTestSuite)) 123 } 124 125 // TestWeightedOperations tests the weights of the operations. 126 func (suite *SimTestSuite) TestWeightedOperations() { 127 ctx := suite.ctx.WithChainID("test-chain") 128 appParams := make(simtypes.AppParams) 129 130 expected := []struct { 131 weight int 132 opMsgRoute string 133 opMsgName string 134 }{ 135 {simulation.DefaultWeightMsgUnjail, types.ModuleName, sdk.MsgTypeURL(&types.MsgUnjail{})}, 136 } 137 138 weightedOps := simulation.WeightedOperations(suite.interfaceRegistry, appParams, suite.codec, suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.slashingKeeper, suite.stakingKeeper) 139 for i, w := range weightedOps { 140 operationMsg, _, err := w.Op()(suite.r, suite.app.BaseApp, ctx, suite.accounts, ctx.ChainID()) 141 suite.Require().NoError(err) 142 143 // the following checks are very much dependent from the ordering of the output given 144 // by WeightedOperations. if the ordering in WeightedOperations changes some tests 145 // will fail 146 suite.Require().Equal(expected[i].weight, w.Weight(), "weight should be the same") 147 suite.Require().Equal(expected[i].opMsgRoute, operationMsg.Route, "route should be the same") 148 suite.Require().Equal(expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") 149 } 150 } 151 152 // TestSimulateMsgUnjail tests the normal scenario of a valid message of type types.MsgUnjail. 153 // Abonormal scenarios, where the message is created by an errors, are not tested here. 154 func (suite *SimTestSuite) TestSimulateMsgUnjail() { 155 blockTime := time.Now().UTC() 156 ctx := suite.ctx.WithBlockTime(blockTime) 157 158 // setup accounts[0] as validator0 159 validator0, err := getTestingValidator0(ctx, suite.stakingKeeper, suite.accounts) 160 suite.Require().NoError(err) 161 162 // setup validator0 by consensus address 163 suite.stakingKeeper.SetValidatorByConsAddr(ctx, validator0) 164 val0ConsAddress, err := validator0.GetConsAddr() 165 suite.Require().NoError(err) 166 info := types.NewValidatorSigningInfo(val0ConsAddress, int64(4), int64(3), 167 time.Unix(2, 0), false, int64(10)) 168 suite.slashingKeeper.SetValidatorSigningInfo(ctx, val0ConsAddress, info) 169 170 // put validator0 in jail 171 suite.stakingKeeper.Jail(ctx, val0ConsAddress) 172 173 // setup self delegation 174 delTokens := suite.stakingKeeper.TokensFromConsensusPower(ctx, 2) 175 validator0, issuedShares := validator0.AddTokensFromDel(delTokens) 176 val0AccAddress, err := sdk.ValAddressFromBech32(validator0.OperatorAddress) 177 suite.Require().NoError(err) 178 179 selfDelegation := stakingtypes.NewDelegation(suite.accounts[0].Address.String(), validator0.GetOperator(), issuedShares) 180 suite.Require().NoError(suite.stakingKeeper.SetDelegation(ctx, selfDelegation)) 181 suite.Require().NoError(suite.distrKeeper.SetDelegatorStartingInfo(ctx, val0AccAddress, val0AccAddress.Bytes(), distrtypes.NewDelegatorStartingInfo(2, math.LegacyOneDec(), 200))) 182 183 // begin a new block 184 suite.app.FinalizeBlock(&abci.RequestFinalizeBlock{Height: suite.app.LastBlockHeight() + 1, Hash: suite.app.LastCommitID().Hash, Time: blockTime}) 185 186 // execute operation 187 op := simulation.SimulateMsgUnjail(codec.NewProtoCodec(suite.interfaceRegistry), suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.slashingKeeper, suite.stakingKeeper) 188 operationMsg, futureOperations, err := op(suite.r, suite.app.BaseApp, ctx, suite.accounts, "") 189 suite.Require().NoError(err) 190 191 var msg types.MsgUnjail 192 err = proto.Unmarshal(operationMsg.Msg, &msg) 193 suite.Require().NoError(err) 194 suite.Require().True(operationMsg.OK) 195 suite.Require().Equal("cosmosvaloper1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7epjs3u", msg.ValidatorAddr) 196 suite.Require().Len(futureOperations, 0) 197 } 198 199 func getTestingValidator0(ctx sdk.Context, stakingKeeper *stakingkeeper.Keeper, accounts []simtypes.Account) (stakingtypes.Validator, error) { 200 commission0 := stakingtypes.NewCommission(math.LegacyZeroDec(), math.LegacyOneDec(), math.LegacyOneDec()) 201 return getTestingValidator(ctx, stakingKeeper, accounts, commission0, 0) 202 } 203 204 func getTestingValidator(ctx sdk.Context, stakingKeeper *stakingkeeper.Keeper, accounts []simtypes.Account, commission stakingtypes.Commission, n int) (stakingtypes.Validator, error) { 205 account := accounts[n] 206 valPubKey := account.ConsKey.PubKey() 207 valAddr := sdk.ValAddress(account.PubKey.Address().Bytes()) 208 validator, err := stakingtypes.NewValidator(valAddr.String(), valPubKey, stakingtypes.Description{}) 209 if err != nil { 210 return stakingtypes.Validator{}, fmt.Errorf("failed to create validator: %w", err) 211 } 212 213 validator, err = validator.SetInitialCommission(commission) 214 if err != nil { 215 return stakingtypes.Validator{}, fmt.Errorf("failed to set initial commission: %w", err) 216 } 217 218 validator.DelegatorShares = math.LegacyNewDec(100) 219 validator.Tokens = math.NewInt(1000000) 220 221 stakingKeeper.SetValidator(ctx, validator) 222 223 return validator, nil 224 }