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  }