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 1 commit
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
Next Next commit
refactor (x/staking): migrate historicalInfo to collections
  • Loading branch information
atheeshp committed Jul 19, 2023
commit a93ccdf6220d072d2aa93d0cc1969c5fbb758d0e
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.HistoricalInfo.Get(ctx, req.Height)
if err != nil {
return nil, status.Errorf(codes.NotFound, "historical info for height %d not found", req.Height)
}
Expand Down
51 changes: 8 additions & 43 deletions x/staking/keeper/historical_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,13 @@ import (
"context"
"errors"

"cosmossdk.io/collections"
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,9 +38,9 @@ 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 int64, info types.HistoricalInfo) (stop bool, err error) {
atheeshp marked this conversation as resolved.
Show resolved Hide resolved
infos = append(infos, info)
return false, nil
})

return infos, err
Expand All @@ -99,14 +64,14 @@ func (k Keeper) TrackHistoricalInfo(ctx context.Context) error {
// over the historical entries starting from the most recent version to be pruned
// and then return at the first empty entry.
for i := sdkCtx.BlockHeight() - int64(entryNum); i >= 0; i-- {
_, err := k.GetHistoricalInfo(ctx, i)
_, err := k.HistoricalInfo.Get(ctx, i)
if err != nil {
if errors.Is(err, types.ErrNoHistoricalInfo) {
if errors.Is(err, collections.ErrNotFound) {
break
}
return err
}
if err = k.DeleteHistoricalInfo(ctx, i); err != nil {
if err = k.HistoricalInfo.Remove(ctx, i); err != nil {
return err
}
}
Expand All @@ -125,5 +90,5 @@ func (k Keeper) TrackHistoricalInfo(ctx context.Context) error {
historicalEntry := types.NewHistoricalInfo(sdkCtx.BlockHeader(), lastVals, k.PowerReduction(ctx))

// Set latest HistoricalInfo at current height
return k.SetHistoricalInfo(ctx, sdkCtx.BlockHeight(), &historicalEntry)
return k.HistoricalInfo.Set(ctx, sdkCtx.BlockHeight(), historicalEntry)
}
33 changes: 17 additions & 16 deletions x/staking/keeper/historical_info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import (
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"

"cosmossdk.io/collections"
"cosmossdk.io/math"

"github.com/cosmos/cosmos-sdk/x/staking/testutil"
Expand Down Expand Up @@ -33,17 +34,17 @@
}

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

recv, err := keeper.GetHistoricalInfo(ctx, 2)
require.NoError(err, "HistoricalInfo not found after set")
recv, err := keeper.HistoricalInfo.Get(ctx, 2)
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, 2))

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

Expand Down Expand Up @@ -74,12 +75,12 @@
}
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))
recv, err := keeper.GetHistoricalInfo(ctx, 4)
require.NoError(keeper.HistoricalInfo.Set(ctx, 4, hi4))
require.NoError(keeper.HistoricalInfo.Set(ctx, 5, hi5))
recv, err := keeper.HistoricalInfo.Get(ctx, 4)
require.NoError(err)
require.Equal(hi4, recv)
recv, err = keeper.GetHistoricalInfo(ctx, 5)
recv, err = keeper.HistoricalInfo.Get(ctx, 5)
require.NoError(err)
require.Equal(hi5, recv)

Expand Down Expand Up @@ -112,16 +113,16 @@
Header: header,
Valset: vals,
}
recv, err = keeper.GetHistoricalInfo(ctx, 10)
recv, err = keeper.HistoricalInfo.Get(ctx, 10)
require.NoError(err, "GetHistoricalInfo failed after BeginBlock")
require.Equal(expected, recv, "GetHistoricalInfo returned unexpected result")

// Check HistoricalInfo at height 5, 4 is pruned
recv, err = keeper.GetHistoricalInfo(ctx, 4)
require.ErrorIs(err, stakingtypes.ErrNoHistoricalInfo, "GetHistoricalInfo did not prune earlier height")
recv, err = keeper.HistoricalInfo.Get(ctx, 4)
require.ErrorIs(err, collections.ErrNotFound, "GetHistoricalInfo did not prune earlier height")
require.Equal(stakingtypes.HistoricalInfo{}, recv, "GetHistoricalInfo at height 4 is not empty after prune")
recv, err = keeper.GetHistoricalInfo(ctx, 5)
require.ErrorIs(err, stakingtypes.ErrNoHistoricalInfo, "GetHistoricalInfo did not prune first prune height")
recv, err = keeper.HistoricalInfo.Get(ctx, 5)
require.ErrorIs(err, collections.ErrNotFound, "GetHistoricalInfo did not prune first prune height")
require.Equal(stakingtypes.HistoricalInfo{}, recv, "GetHistoricalInfo at height 5 is not empty after prune")
}

Expand All @@ -147,7 +148,7 @@
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, int64(9+i), hi)) //nolint:gosec // G601: Implicit memory aliasing in for loop.

Check failure on line 151 in x/staking/keeper/historical_info_test.go

View workflow job for this annotation

GitHub Actions / Analyze

directive `//nolint:gosec // G601: Implicit memory aliasing in for loop.` is unused for linter "gosec" (nolintlint)

Check failure on line 151 in x/staking/keeper/historical_info_test.go

View workflow job for this annotation

GitHub Actions / golangci-lint

directive `//nolint:gosec // G601: Implicit memory aliasing in for loop.` is unused for linter "gosec" (nolintlint)
}

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 @@ -36,6 +36,7 @@ type Keeper struct {

Schema collections.Schema
LastTotalPower collections.Item[math.Int]
HistoricalInfo collections.Map[int64, types.HistoricalInfo]
}

// NewKeeper creates a new staking Keeper instance
Expand Down Expand Up @@ -77,6 +78,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.Int64Key, codec.CollValue[types.HistoricalInfo](cdc)),
atheeshp marked this conversation as resolved.
Show resolved Hide resolved
}

schema, err := sb.Build()
Expand Down
1 change: 0 additions & 1 deletion x/staking/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ var (
ErrBothShareMsgsGiven = errors.Register(ModuleName, 35, "both shares amount and shares percent provided")
ErrNeitherShareMsgsGiven = errors.Register(ModuleName, 36, "neither shares amount nor shares percent provided")
ErrInvalidHistoricalInfo = errors.Register(ModuleName, 37, "invalid historical info")
ErrNoHistoricalInfo = errors.Register(ModuleName, 38, "no historical info found")
ErrEmptyValidatorPubKey = errors.Register(ModuleName, 39, "empty validator public key")
ErrCommissionLTMinRate = errors.Register(ModuleName, 40, "commission cannot be less than min rate")
ErrUnbondingNotFound = errors.Register(ModuleName, 41, "unbonding operation not found")
Expand Down
4 changes: 2 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 = []byte{0x61} // 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 = []byte{0x61} // prefix for the end block validator updates key

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

Expand Down
Loading