github.com/cosmos/cosmos-sdk@v0.50.10/x/staking/keeper/historical_info_test.go (about)

     1  package keeper_test
     2  
     3  import (
     4  	cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
     5  
     6  	"cosmossdk.io/math"
     7  
     8  	"github.com/cosmos/cosmos-sdk/x/staking/testutil"
     9  	stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
    10  )
    11  
    12  // IsValSetSorted reports whether valset is sorted.
    13  func IsValSetSorted(data []stakingtypes.Validator, powerReduction math.Int) bool {
    14  	n := len(data)
    15  	for i := n - 1; i > 0; i-- {
    16  		if stakingtypes.ValidatorsByVotingPower(data).Less(i, i-1, powerReduction) {
    17  			return false
    18  		}
    19  	}
    20  	return true
    21  }
    22  
    23  func (s *KeeperTestSuite) TestHistoricalInfo() {
    24  	ctx, keeper := s.ctx, s.stakingKeeper
    25  	require := s.Require()
    26  
    27  	_, addrVals := createValAddrs(50)
    28  
    29  	validators := make([]stakingtypes.Validator, len(addrVals))
    30  
    31  	for i, valAddr := range addrVals {
    32  		validators[i] = testutil.NewValidator(s.T(), valAddr, PKs[i])
    33  	}
    34  
    35  	hi := stakingtypes.NewHistoricalInfo(ctx.BlockHeader(), stakingtypes.Validators{Validators: validators}, keeper.PowerReduction(ctx))
    36  	require.NoError(keeper.SetHistoricalInfo(ctx, 2, &hi))
    37  
    38  	recv, err := keeper.GetHistoricalInfo(ctx, 2)
    39  	require.NoError(err, "HistoricalInfo not found after set")
    40  	require.Equal(hi, recv, "HistoricalInfo not equal")
    41  	require.True(IsValSetSorted(recv.Valset, keeper.PowerReduction(ctx)), "HistoricalInfo validators is not sorted")
    42  
    43  	require.NoError(keeper.DeleteHistoricalInfo(ctx, 2))
    44  
    45  	recv, err = keeper.GetHistoricalInfo(ctx, 2)
    46  	require.ErrorIs(err, stakingtypes.ErrNoHistoricalInfo, "HistoricalInfo found after delete")
    47  	require.Equal(stakingtypes.HistoricalInfo{}, recv, "HistoricalInfo is not empty")
    48  }
    49  
    50  func (s *KeeperTestSuite) TestTrackHistoricalInfo() {
    51  	ctx, keeper := s.ctx, s.stakingKeeper
    52  	require := s.Require()
    53  
    54  	_, addrVals := createValAddrs(50)
    55  
    56  	// set historical entries in params to 5
    57  	params := stakingtypes.DefaultParams()
    58  	params.HistoricalEntries = 5
    59  	require.NoError(keeper.SetParams(ctx, params))
    60  
    61  	// set historical info at 5, 4 which should be pruned
    62  	// and check that it has been stored
    63  	h4 := cmtproto.Header{
    64  		ChainID: "HelloChain",
    65  		Height:  4,
    66  	}
    67  	h5 := cmtproto.Header{
    68  		ChainID: "HelloChain",
    69  		Height:  5,
    70  	}
    71  	valSet := []stakingtypes.Validator{
    72  		testutil.NewValidator(s.T(), addrVals[0], PKs[0]),
    73  		testutil.NewValidator(s.T(), addrVals[1], PKs[1]),
    74  	}
    75  	hi4 := stakingtypes.NewHistoricalInfo(h4, stakingtypes.Validators{Validators: valSet}, keeper.PowerReduction(ctx))
    76  	hi5 := stakingtypes.NewHistoricalInfo(h5, stakingtypes.Validators{Validators: valSet}, keeper.PowerReduction(ctx))
    77  	require.NoError(keeper.SetHistoricalInfo(ctx, 4, &hi4))
    78  	require.NoError(keeper.SetHistoricalInfo(ctx, 5, &hi5))
    79  	recv, err := keeper.GetHistoricalInfo(ctx, 4)
    80  	require.NoError(err)
    81  	require.Equal(hi4, recv)
    82  	recv, err = keeper.GetHistoricalInfo(ctx, 5)
    83  	require.NoError(err)
    84  	require.Equal(hi5, recv)
    85  
    86  	// Set bonded validators in keeper
    87  	val1 := testutil.NewValidator(s.T(), addrVals[2], PKs[2])
    88  	val1.Status = stakingtypes.Bonded // when not bonded, consensus power is Zero
    89  	val1.Tokens = keeper.TokensFromConsensusPower(ctx, 10)
    90  	require.NoError(keeper.SetValidator(ctx, val1))
    91  	valbz, err := keeper.ValidatorAddressCodec().StringToBytes(val1.GetOperator())
    92  	require.NoError(err)
    93  	require.NoError(keeper.SetLastValidatorPower(ctx, valbz, 10))
    94  	val2 := testutil.NewValidator(s.T(), addrVals[3], PKs[3])
    95  	val1.Status = stakingtypes.Bonded
    96  	val2.Tokens = keeper.TokensFromConsensusPower(ctx, 80)
    97  	require.NoError(keeper.SetValidator(ctx, val2))
    98  	valbz, err = keeper.ValidatorAddressCodec().StringToBytes(val2.GetOperator())
    99  	require.NoError(err)
   100  	require.NoError(keeper.SetLastValidatorPower(ctx, valbz, 80))
   101  
   102  	vals := []stakingtypes.Validator{val1, val2}
   103  	require.True(IsValSetSorted(vals, keeper.PowerReduction(ctx)))
   104  
   105  	// Set Header for BeginBlock context
   106  	header := cmtproto.Header{
   107  		ChainID: "HelloChain",
   108  		Height:  10,
   109  	}
   110  	ctx = ctx.WithBlockHeader(header)
   111  
   112  	require.NoError(keeper.TrackHistoricalInfo(ctx))
   113  
   114  	// Check HistoricalInfo at height 10 is persisted
   115  	expected := stakingtypes.HistoricalInfo{
   116  		Header: header,
   117  		Valset: vals,
   118  	}
   119  	recv, err = keeper.GetHistoricalInfo(ctx, 10)
   120  	require.NoError(err, "GetHistoricalInfo failed after BeginBlock")
   121  	require.Equal(expected, recv, "GetHistoricalInfo returned unexpected result")
   122  
   123  	// Check HistoricalInfo at height 5, 4 is pruned
   124  	recv, err = keeper.GetHistoricalInfo(ctx, 4)
   125  	require.ErrorIs(err, stakingtypes.ErrNoHistoricalInfo, "GetHistoricalInfo did not prune earlier height")
   126  	require.Equal(stakingtypes.HistoricalInfo{}, recv, "GetHistoricalInfo at height 4 is not empty after prune")
   127  	recv, err = keeper.GetHistoricalInfo(ctx, 5)
   128  	require.ErrorIs(err, stakingtypes.ErrNoHistoricalInfo, "GetHistoricalInfo did not prune first prune height")
   129  	require.Equal(stakingtypes.HistoricalInfo{}, recv, "GetHistoricalInfo at height 5 is not empty after prune")
   130  }
   131  
   132  func (s *KeeperTestSuite) TestGetAllHistoricalInfo() {
   133  	ctx, keeper := s.ctx, s.stakingKeeper
   134  	require := s.Require()
   135  
   136  	_, addrVals := createValAddrs(50)
   137  
   138  	valSet := []stakingtypes.Validator{
   139  		testutil.NewValidator(s.T(), addrVals[0], PKs[0]),
   140  		testutil.NewValidator(s.T(), addrVals[1], PKs[1]),
   141  	}
   142  
   143  	header1 := cmtproto.Header{ChainID: "HelloChain", Height: 9}
   144  	header2 := cmtproto.Header{ChainID: "HelloChain", Height: 10}
   145  	header3 := cmtproto.Header{ChainID: "HelloChain", Height: 11}
   146  
   147  	hist1 := stakingtypes.HistoricalInfo{Header: header1, Valset: valSet}
   148  	hist2 := stakingtypes.HistoricalInfo{Header: header2, Valset: valSet}
   149  	hist3 := stakingtypes.HistoricalInfo{Header: header3, Valset: valSet}
   150  
   151  	expHistInfos := []stakingtypes.HistoricalInfo{hist1, hist2, hist3}
   152  
   153  	for i, hi := range expHistInfos {
   154  		require.NoError(keeper.SetHistoricalInfo(ctx, int64(9+i), &hi)) //nolint:gosec // G601: Implicit memory aliasing in for loop.
   155  	}
   156  
   157  	infos, err := keeper.GetAllHistoricalInfo(ctx)
   158  	require.NoError(err)
   159  	require.Equal(expHistInfos, infos)
   160  }