github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/x/slashing/simulation/operations.go (about)

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