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  }