Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(x/staking): migrate historicalInfo to use collections #17063

Merged
merged 21 commits into from
Jul 25, 2023
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ Ref: https://keepachangelog.com/en/1.0.0/

### API Breaking Changes

* (x/slashing) [17063](https://github.com/cosmos/cosmos-sdk/pull/17063) Use collections for `HistoricalInfo`:
* remove `Keeper`: `GetHistoricalInfo`, `SetHistoricalInfo`,
* (x/staking) [17062](https://github.com/cosmos/cosmos-sdk/pull/17062) Use collections for `ValidatorUpdates`:
* remove `Keeper`: `SetValidatorUpdates`, `GetValidatorUpdates`
* (x/slashing) [17023](https://github.com/cosmos/cosmos-sdk/pull/17023) Use collections for `ValidatorSigningInfo`:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -669,10 +669,10 @@ func TestGRPCHistoricalInfo(t *testing.T) {

height := rapid.Int64Min(0).Draw(rt, "height")

assert.NilError(t, f.stakingKeeper.SetHistoricalInfo(
assert.NilError(t, f.stakingKeeper.HistoricalInfo.Set(
f.ctx,
height,
&historicalInfo,
stakingtypes.GetHistoricalInfoKeyWithoutPrefix(height),
historicalInfo,
))

req := &stakingtypes.QueryHistoricalInfoRequest{
Expand All @@ -693,10 +693,10 @@ func TestGRPCHistoricalInfo(t *testing.T) {

height := int64(127)

assert.NilError(t, f.stakingKeeper.SetHistoricalInfo(
assert.NilError(t, f.stakingKeeper.HistoricalInfo.Set(
f.ctx,
height,
&historicalInfo,
stakingtypes.GetHistoricalInfoKeyWithoutPrefix(height),
historicalInfo,
))

req := &stakingtypes.QueryHistoricalInfoRequest{
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/staking/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func createValidatorAccs(t *testing.T, f *fixture) ([]sdk.AccAddress, []types.Va
sortedVals := make([]types.Validator, len(validators))
copy(sortedVals, validators)
hi := types.NewHistoricalInfo(header, sortedVals, f.stakingKeeper.PowerReduction(f.sdkCtx))
assert.NilError(t, f.stakingKeeper.SetHistoricalInfo(f.sdkCtx, 5, &hi))
assert.NilError(t, f.stakingKeeper.HistoricalInfo.Set(f.sdkCtx, types.GetHistoricalInfoKeyWithoutPrefix(5), hi))
atheeshp marked this conversation as resolved.
Show resolved Hide resolved

return addrs, validators
}
Expand Down
2 changes: 1 addition & 1 deletion x/staking/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ func (k Querier) HistoricalInfo(ctx context.Context, req *types.QueryHistoricalI
return nil, status.Error(codes.InvalidArgument, "height cannot be negative")
}

hi, err := k.GetHistoricalInfo(ctx, req.Height)
hi, err := k.Keeper.GetHistoricalInfo(ctx, req.Height)
if err != nil {
return nil, status.Errorf(codes.NotFound, "historical info for height %d not found", req.Height)
}
Expand Down
73 changes: 30 additions & 43 deletions x/staking/keeper/historical_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,14 @@ import (
"context"
"errors"

"cosmossdk.io/collections"
errorsmod "cosmossdk.io/errors"
storetypes "cosmossdk.io/store/types"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)

// GetHistoricalInfo gets the historical info at a given height
func (k Keeper) GetHistoricalInfo(ctx context.Context, height int64) (types.HistoricalInfo, error) {
store := k.storeService.OpenKVStore(ctx)
key := types.GetHistoricalInfoKey(height)

value, err := store.Get(key)
if err != nil {
return types.HistoricalInfo{}, err
}

if value == nil {
return types.HistoricalInfo{}, types.ErrNoHistoricalInfo
}

return types.UnmarshalHistoricalInfo(k.cdc, value)
}

// SetHistoricalInfo sets the historical info at a given height
func (k Keeper) SetHistoricalInfo(ctx context.Context, height int64, hi *types.HistoricalInfo) error {
store := k.storeService.OpenKVStore(ctx)
key := types.GetHistoricalInfoKey(height)
value, err := k.cdc.Marshal(hi)
if err != nil {
return err
}
return store.Set(key, value)
}

// DeleteHistoricalInfo deletes the historical info at a given height
func (k Keeper) DeleteHistoricalInfo(ctx context.Context, height int64) error {
store := k.storeService.OpenKVStore(ctx)
key := types.GetHistoricalInfoKey(height)

return store.Delete(key)
}

// IterateHistoricalInfo provides an iterator over all stored HistoricalInfo
// objects. For each HistoricalInfo object, cb will be called. If the cb returns
// true, the iterator will break and close.
Expand Down Expand Up @@ -73,12 +39,33 @@ func (k Keeper) IterateHistoricalInfo(ctx context.Context, cb func(types.Histori
// GetAllHistoricalInfo returns all stored HistoricalInfo objects.
func (k Keeper) GetAllHistoricalInfo(ctx context.Context) ([]types.HistoricalInfo, error) {
var infos []types.HistoricalInfo
err := k.IterateHistoricalInfo(ctx, func(histInfo types.HistoricalInfo) bool {
infos = append(infos, histInfo)
return false
err := k.HistoricalInfo.Walk(ctx, nil, func(key []byte, info types.HistoricalInfo) (stop bool, err error) {
infos = append(infos, info)
return false, nil
})

return infos, err
if err != nil && !errorsmod.IsOf(err, collections.ErrInvalidIterator) {
return nil, err
}

return infos, nil
}

// GetHistoricalInfo gets the historical info at a given height
func (k Keeper) GetHistoricalInfo(ctx context.Context, height int64) (types.HistoricalInfo, error) {
store := k.storeService.OpenKVStore(ctx)
key := types.GetHistoricalInfoKey(height)

value, err := store.Get(key)
if err != nil {
return types.HistoricalInfo{}, err
}

if value == nil {
return types.HistoricalInfo{}, types.ErrNoHistoricalInfo
}

return types.UnmarshalHistoricalInfo(k.cdc, value)
}

// TrackHistoricalInfo saves the latest historical-info and deletes the oldest
Expand Down Expand Up @@ -106,7 +93,7 @@ func (k Keeper) TrackHistoricalInfo(ctx context.Context) error {
}
return err
}
if err = k.DeleteHistoricalInfo(ctx, i); err != nil {
if err = k.HistoricalInfo.Remove(ctx, types.GetHistoricalInfoKeyWithoutPrefix(i)); err != nil {
return err
}
}
Expand All @@ -123,7 +110,7 @@ func (k Keeper) TrackHistoricalInfo(ctx context.Context) error {
}

historicalEntry := types.NewHistoricalInfo(sdkCtx.BlockHeader(), lastVals, k.PowerReduction(ctx))

err = k.HistoricalInfo.Set(ctx, types.GetHistoricalInfoKeyWithoutPrefix(sdkCtx.BlockHeight()), historicalEntry)
// Set latest HistoricalInfo at current height
return k.SetHistoricalInfo(ctx, sdkCtx.BlockHeight(), &historicalEntry)
return err
}
14 changes: 7 additions & 7 deletions x/staking/keeper/historical_info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,17 @@ func (s *KeeperTestSuite) TestHistoricalInfo() {
}

hi := stakingtypes.NewHistoricalInfo(ctx.BlockHeader(), validators, keeper.PowerReduction(ctx))
require.NoError(keeper.SetHistoricalInfo(ctx, 2, &hi))
require.NoError(keeper.HistoricalInfo.Set(ctx, stakingtypes.GetHistoricalInfoKeyWithoutPrefix(2), hi))

recv, err := keeper.GetHistoricalInfo(ctx, 2)
require.NoError(err, "HistoricalInfo not found after set")
require.NoError(err, "HistoricalInfo found after set")
require.Equal(hi, recv, "HistoricalInfo not equal")
require.True(IsValSetSorted(recv.Valset, keeper.PowerReduction(ctx)), "HistoricalInfo validators is not sorted")

require.NoError(keeper.DeleteHistoricalInfo(ctx, 2))
require.NoError(keeper.HistoricalInfo.Remove(ctx, stakingtypes.GetHistoricalInfoKeyWithoutPrefix(2)))

recv, err = keeper.GetHistoricalInfo(ctx, 2)
require.ErrorIs(err, stakingtypes.ErrNoHistoricalInfo, "HistoricalInfo found after delete")
require.ErrorIs(err, stakingtypes.ErrNoHistoricalInfo, "HistoricalInfo not found after delete")
require.Equal(stakingtypes.HistoricalInfo{}, recv, "HistoricalInfo is not empty")
}

Expand Down Expand Up @@ -74,8 +74,8 @@ func (s *KeeperTestSuite) TestTrackHistoricalInfo() {
}
hi4 := stakingtypes.NewHistoricalInfo(h4, valSet, keeper.PowerReduction(ctx))
hi5 := stakingtypes.NewHistoricalInfo(h5, valSet, keeper.PowerReduction(ctx))
require.NoError(keeper.SetHistoricalInfo(ctx, 4, &hi4))
require.NoError(keeper.SetHistoricalInfo(ctx, 5, &hi5))
require.NoError(keeper.HistoricalInfo.Set(ctx, stakingtypes.GetHistoricalInfoKeyWithoutPrefix(4), hi4))
require.NoError(keeper.HistoricalInfo.Set(ctx, stakingtypes.GetHistoricalInfoKeyWithoutPrefix(5), hi5))
recv, err := keeper.GetHistoricalInfo(ctx, 4)
require.NoError(err)
require.Equal(hi4, recv)
Expand Down Expand Up @@ -147,7 +147,7 @@ func (s *KeeperTestSuite) TestGetAllHistoricalInfo() {
expHistInfos := []stakingtypes.HistoricalInfo{hist1, hist2, hist3}

for i, hi := range expHistInfos {
require.NoError(keeper.SetHistoricalInfo(ctx, int64(9+i), &hi)) //nolint:gosec // G601: Implicit memory aliasing in for loop.
require.NoError(keeper.HistoricalInfo.Set(ctx, stakingtypes.GetHistoricalInfoKeyWithoutPrefix(int64(9+i)), hi))
}

infos, err := keeper.GetAllHistoricalInfo(ctx)
Expand Down
2 changes: 2 additions & 0 deletions x/staking/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type Keeper struct {
consensusAddressCodec addresscodec.Codec

Schema collections.Schema
HistoricalInfo collections.Map[[]byte, types.HistoricalInfo]
atheeshp marked this conversation as resolved.
Show resolved Hide resolved
LastTotalPower collections.Item[math.Int]
ValidatorUpdates collections.Item[types.ValidatorUpdates]
}
Expand Down Expand Up @@ -76,6 +77,7 @@ func NewKeeper(
validatorAddressCodec: validatorAddressCodec,
consensusAddressCodec: consensusAddressCodec,
LastTotalPower: collections.NewItem(sb, types.LastTotalPowerKey, "last_total_power", sdk.IntValue),
HistoricalInfo: collections.NewMap(sb, types.HistoricalInfoKey, "historical_info", collections.BytesKey, codec.CollValue[types.HistoricalInfo](cdc)),
ValidatorUpdates: collections.NewItem(sb, types.ValidatorUpdatesKey, "validator_updates", codec.CollValue[types.ValidatorUpdates](cdc)),
}

Expand Down
11 changes: 9 additions & 2 deletions x/staking/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ var (
RedelegationQueueKey = []byte{0x42} // prefix for the timestamps in redelegations queue
ValidatorQueueKey = []byte{0x43} // prefix for the timestamps in validator queue

HistoricalInfoKey = []byte{0x50} // prefix for the historical info
ValidatorUpdatesKey = collections.NewPrefix(97) // prefix for the end block validator updates key
HistoricalInfoKey = collections.NewPrefix(0x50) // prefix for the historical info
atheeshp marked this conversation as resolved.
Show resolved Hide resolved
ValidatorUpdatesKey = collections.NewPrefix(97) // prefix for the end block validator updates key

ParamsKey = []byte{0x51} // prefix for parameters for module x/staking

Expand Down Expand Up @@ -419,6 +419,13 @@ func GetREDsByDelToValDstIndexKey(delAddr sdk.AccAddress, valDstAddr sdk.ValAddr
return append(GetREDsToValDstIndexKey(valDstAddr), address.MustLengthPrefix(delAddr)...)
}

// GetHistoricalInfoKey returns a key prefix for indexing HistoricalInfo objects.
func GetHistoricalInfoKeyWithoutPrefix(height int64) []byte {
atheeshp marked this conversation as resolved.
Show resolved Hide resolved
heightBytes := make([]byte, 8)
binary.BigEndian.PutUint64(heightBytes, uint64(height))
return heightBytes
}

// GetHistoricalInfoKey returns a key prefix for indexing HistoricalInfo objects.
func GetHistoricalInfoKey(height int64) []byte {
heightBytes := make([]byte, 8)
Expand Down