github.com/Finschia/finschia-sdk@v0.48.1/x/slashing/simulation/operations.go (about) 1 package simulation 2 3 import ( 4 "errors" 5 "math/rand" 6 7 "github.com/Finschia/finschia-sdk/baseapp" 8 "github.com/Finschia/finschia-sdk/codec" 9 "github.com/Finschia/finschia-sdk/simapp/helpers" 10 simappparams "github.com/Finschia/finschia-sdk/simapp/params" 11 sdk "github.com/Finschia/finschia-sdk/types" 12 simtypes "github.com/Finschia/finschia-sdk/types/simulation" 13 "github.com/Finschia/finschia-sdk/x/simulation" 14 "github.com/Finschia/finschia-sdk/x/slashing/keeper" 15 "github.com/Finschia/finschia-sdk/x/slashing/types" 16 stakingkeeper "github.com/Finschia/finschia-sdk/x/staking/keeper" 17 ) 18 19 // nolint: gosec 20 // Simulation operation weights constants 21 const ( 22 OpWeightMsgUnjail = "op_weight_msg_unjail" //nolint:gosec 23 ) 24 25 // WeightedOperations returns all the operations from the module with their respective weights 26 func WeightedOperations( 27 appParams simtypes.AppParams, cdc codec.JSONCodec, ak types.AccountKeeper, 28 bk types.BankKeeper, k keeper.Keeper, sk types.StakingKeeper, 29 ) simulation.WeightedOperations { 30 var weightMsgUnjail int 31 appParams.GetOrGenerate(cdc, OpWeightMsgUnjail, &weightMsgUnjail, nil, 32 func(_ *rand.Rand) { 33 weightMsgUnjail = simappparams.DefaultWeightMsgUnjail 34 }, 35 ) 36 37 return simulation.WeightedOperations{ 38 simulation.NewWeightedOperation( 39 weightMsgUnjail, 40 SimulateMsgUnjail(ak, bk, k, sk.(stakingkeeper.Keeper)), 41 ), 42 } 43 } 44 45 // SimulateMsgUnjail generates a MsgUnjail with random values 46 func SimulateMsgUnjail(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper, sk stakingkeeper.Keeper) simtypes.Operation { 47 return func( 48 r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, 49 accs []simtypes.Account, chainID string, 50 ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { 51 validator, ok := stakingkeeper.RandomValidator(r, sk, ctx) 52 if !ok { 53 return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgUnjail, "validator is not ok"), nil, nil // skip 54 } 55 56 simAccount, found := simtypes.FindAccount(accs, sdk.AccAddress(validator.GetOperator())) 57 if !found { 58 return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgUnjail, "unable to find account"), nil, nil // skip 59 } 60 61 if !validator.IsJailed() { 62 // TODO: due to this condition this message is almost, if not always, skipped ! 63 return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgUnjail, "validator is not jailed"), nil, nil 64 } 65 66 consAddr, err := validator.GetConsAddr() 67 if err != nil { 68 return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgUnjail, "unable to get validator consensus key"), nil, err 69 } 70 info, found := k.GetValidatorSigningInfo(ctx, consAddr) 71 if !found { 72 return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgUnjail, "unable to find validator signing info"), nil, nil // skip 73 } 74 75 selfDel := sk.Delegation(ctx, simAccount.Address, validator.GetOperator()) 76 if selfDel == nil { 77 return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgUnjail, "self delegation is nil"), nil, nil // skip 78 } 79 80 account := ak.GetAccount(ctx, sdk.AccAddress(validator.GetOperator())) 81 spendable := bk.SpendableCoins(ctx, account.GetAddress()) 82 83 fees, err := simtypes.RandomFees(r, ctx, spendable) 84 if err != nil { 85 return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgUnjail, "unable to generate fees"), nil, err 86 } 87 88 msg := types.NewMsgUnjail(validator.GetOperator()) 89 90 txGen := simappparams.MakeTestEncodingConfig().TxConfig 91 tx, err := helpers.GenSignedMockTx( 92 r, 93 txGen, 94 []sdk.Msg{msg}, 95 fees, 96 helpers.DefaultGenTxGas, 97 chainID, 98 []uint64{account.GetAccountNumber()}, 99 []uint64{account.GetSequence()}, 100 simAccount.PrivKey, 101 ) 102 if err != nil { 103 return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to generate mock tx"), nil, err 104 } 105 106 _, res, err := app.Deliver(txGen.TxEncoder(), tx) 107 108 // result should fail if: 109 // - validator cannot be unjailed due to tombstone 110 // - validator is still in jailed period 111 // - self delegation too low 112 if info.Tombstoned || 113 ctx.BlockHeader().Time.Before(info.JailedUntil) || 114 validator.TokensFromShares(selfDel.GetShares()).TruncateInt().LT(validator.GetMinSelfDelegation()) { 115 if res != nil && err == nil { 116 if info.Tombstoned { 117 return simtypes.NewOperationMsg(msg, true, "", nil), nil, errors.New("validator should not have been unjailed if validator tombstoned") 118 } 119 if ctx.BlockHeader().Time.Before(info.JailedUntil) { 120 return simtypes.NewOperationMsg(msg, true, "", nil), nil, errors.New("validator unjailed while validator still in jail period") 121 } 122 if validator.TokensFromShares(selfDel.GetShares()).TruncateInt().LT(validator.GetMinSelfDelegation()) { 123 return simtypes.NewOperationMsg(msg, true, "", nil), nil, errors.New("validator unjailed even though self-delegation too low") 124 } 125 } 126 // msg failed as expected 127 return simtypes.NewOperationMsg(msg, false, "", nil), nil, nil 128 } 129 130 if err != nil { 131 return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err 132 } 133 134 return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil 135 } 136 }