github.com/cosmos/cosmos-sdk@v0.50.10/x/slashing/simulation/operations.go (about)

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