refactor(distribution)!: use collections for ValidatorCurrentRewards (#16459)

Co-authored-by: unknown unknown <unknown@unknown>
This commit is contained in:
testinginprod 2023-06-09 11:19:37 +02:00 committed by GitHub
parent bf8053cdfc
commit 2d1d68d3fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 56 additions and 90 deletions

View File

@ -38,6 +38,13 @@ Ref: https://keepachangelog.com/en/1.0.0/
## [Unreleased]
### API Breaking
* (x/distribution) [#16440](https://github.com/cosmos/cosmos-sdk/pull/16440) use collections for `DelegatorWithdrawAddresState`:
* remove `Keeper`: `SetDelegatorWithdrawAddr`, `DeleteDelegatorWithdrawAddr`, `IterateDelegatorWithdrawAddrs`.
* (x/distribution) [#16459](https://github.com/cosmos/cosmos-sdk/pull/16459) use collections for `ValidatorCurrentRewards` state management:
* remove `Keeper`: `IterateValidatorCurrentRewards`, `GetValidatorCurrentRewards`, `SetValidatorCurrentRewards`, `DeleteValidatorCurrentRewards`
## [v0.50.0-alpha.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.50.0-alpha.0) - 2023-06-07
### Features
@ -255,8 +262,6 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (sims) [#16052](https://github.com/cosmos/cosmos-sdk/pull/16062) `GetOrGenerate` no longer requires a codec argument is now 4-arity instead of 5-arity.
* (baseapp) [#16342](https://github.com/cosmos/cosmos-sdk/pull/16342) NewContext was renamed to NewContextLegacy. The replacement (NewContext) now does not take a header, instead you should set the header via `WithHeaderInfo` or `WithBlockHeight`. Note that `WithBlockHeight` will soon be depreacted and its recommneded to use `WithHeaderInfo`
* (x/auth) [#16112](https://github.com/cosmos/cosmos-sdk/issues/16112) `helpers.AddGenesisAccount` has been moved to `x/genutil` to remove the cyclic dependency between `x/auth` and `x/genutil`.
* (x/distribution) [#16440](https://github.com/cosmos/cosmos-sdk/pull/16440) use collections for `DelegatorWithdrawAddresState`:
* remove `Keeper`: `SetDelegatorWithdrawAddr`, `DeleteDelegatorWithdrawAddr`, `IterateDelegatorWithdrawAddrs`.
### Client Breaking Changes

View File

@ -517,7 +517,7 @@ func TestGRPCDelegationRewards(t *testing.T) {
assert.NilError(t, f.distrKeeper.SetValidatorHistoricalRewards(f.sdkCtx, validator.GetOperator(), 2, historicalRewards))
// setup current rewards and outstanding rewards
currentRewards := types.NewValidatorCurrentRewards(decCoins, 3)
assert.NilError(t, f.distrKeeper.SetValidatorCurrentRewards(f.sdkCtx, f.valAddr, currentRewards))
assert.NilError(t, f.distrKeeper.ValidatorCurrentRewards.Set(f.sdkCtx, f.valAddr, currentRewards))
assert.NilError(t, f.distrKeeper.SetValidatorOutstandingRewards(f.sdkCtx, f.valAddr, types.ValidatorOutstandingRewards{Rewards: decCoins}))
expRes := &types.QueryDelegationRewardsResponse{

View File

@ -197,7 +197,7 @@ func TestMsgWithdrawDelegatorReward(t *testing.T) {
require.NoError(t, err)
// setup current rewards and outstanding rewards
currentRewards := distrtypes.NewValidatorCurrentRewards(decCoins, 3)
err = f.distrKeeper.SetValidatorCurrentRewards(f.sdkCtx, f.valAddr, currentRewards)
err = f.distrKeeper.ValidatorCurrentRewards.Set(f.sdkCtx, f.valAddr, currentRewards)
require.NoError(t, err)
err = f.distrKeeper.SetValidatorOutstandingRewards(f.sdkCtx, f.valAddr, distrtypes.ValidatorOutstandingRewards{Rewards: valCommission})
require.NoError(t, err)

View File

@ -2,7 +2,9 @@ package keeper
import (
"context"
"errors"
"cosmossdk.io/collections"
"cosmossdk.io/math"
abci "github.com/cometbft/cometbft/abci/types"
@ -105,13 +107,14 @@ func (k Keeper) AllocateTokensToValidator(ctx context.Context, val stakingtypes.
}
// update current rewards
currentRewards, err := k.GetValidatorCurrentRewards(ctx, val.GetOperator())
if err != nil {
currentRewards, err := k.ValidatorCurrentRewards.Get(ctx, val.GetOperator())
// if the rewards do not exist it's fine, we will just add to zero.
if err != nil && !errors.Is(err, collections.ErrNotFound) {
return err
}
currentRewards.Rewards = currentRewards.Rewards.Add(shared...)
err = k.SetValidatorCurrentRewards(ctx, val.GetOperator(), currentRewards)
err = k.ValidatorCurrentRewards.Set(ctx, val.GetOperator(), currentRewards)
if err != nil {
return err
}

View File

@ -4,6 +4,7 @@ import (
"testing"
"time"
"cosmossdk.io/collections"
"cosmossdk.io/math"
abci "github.com/cometbft/cometbft/abci/types"
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
@ -70,7 +71,7 @@ func TestAllocateTokensToValidatorWithCommission(t *testing.T) {
require.Equal(t, expected, valCommission.Commission)
// check current rewards
currentRewards, err := distrKeeper.GetValidatorCurrentRewards(ctx, val.GetOperator())
currentRewards, err := distrKeeper.ValidatorCurrentRewards.Get(ctx, val.GetOperator())
require.NoError(t, err)
require.Equal(t, expected, currentRewards.Rewards)
}
@ -149,13 +150,11 @@ func TestAllocateTokensToManyValidators(t *testing.T) {
require.NoError(t, err)
require.True(t, val1Commission.Commission.IsZero())
val0CurrentRewards, err := distrKeeper.GetValidatorCurrentRewards(ctx, valAddr0)
require.NoError(t, err)
require.True(t, val0CurrentRewards.Rewards.IsZero())
_, err = distrKeeper.ValidatorCurrentRewards.Get(ctx, valAddr0)
require.ErrorIs(t, err, collections.ErrNotFound) // require no rewards
val1CurrentRewards, err := distrKeeper.GetValidatorCurrentRewards(ctx, valAddr1)
require.NoError(t, err)
require.True(t, val1CurrentRewards.Rewards.IsZero())
_, err = distrKeeper.ValidatorCurrentRewards.Get(ctx, valAddr1)
require.ErrorIs(t, err, collections.ErrNotFound) // require no rewards
// allocate tokens as if both had voted and second was proposer
fees := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(100)))
@ -197,12 +196,12 @@ func TestAllocateTokensToManyValidators(t *testing.T) {
require.True(t, val1Commission.Commission.IsZero())
// just staking.proportional for first proposer less commission = (0.5 * 98%) * 100 / 2 = 24.50
val0CurrentRewards, err = distrKeeper.GetValidatorCurrentRewards(ctx, valAddr0)
val0CurrentRewards, err := distrKeeper.ValidatorCurrentRewards.Get(ctx, valAddr0)
require.NoError(t, err)
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: math.LegacyNewDecWithPrec(2450, 2)}}, val0CurrentRewards.Rewards)
// proposer reward + staking.proportional for second proposer = (0.5 * (98%)) * 100 = 49
val1CurrentRewards, err = distrKeeper.GetValidatorCurrentRewards(ctx, valAddr1)
val1CurrentRewards, err := distrKeeper.ValidatorCurrentRewards.Get(ctx, valAddr1)
require.NoError(t, err)
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: math.LegacyNewDecWithPrec(490, 1)}}, val1CurrentRewards.Rewards)
}
@ -292,13 +291,11 @@ func TestAllocateTokensTruncation(t *testing.T) {
require.NoError(t, err)
require.True(t, val1Commission.Commission.IsZero())
val0CurrentRewards, err := distrKeeper.GetValidatorCurrentRewards(ctx, valAddr0)
require.NoError(t, err)
require.True(t, val0CurrentRewards.Rewards.IsZero())
_, err = distrKeeper.ValidatorCurrentRewards.Get(ctx, valAddr0)
require.ErrorIs(t, err, collections.ErrNotFound) // require no rewards
val1CurrentRewards, err := distrKeeper.GetValidatorCurrentRewards(ctx, valAddr1)
require.NoError(t, err)
require.True(t, val1CurrentRewards.Rewards.IsZero())
_, err = distrKeeper.ValidatorCurrentRewards.Get(ctx, valAddr1)
require.ErrorIs(t, err, collections.ErrNotFound) // require no rewards
// allocate tokens as if both had voted and second was proposer
fees := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(634195840)))

View File

@ -14,7 +14,7 @@ import (
// initialize starting info for a new delegation
func (k Keeper) initializeDelegation(ctx context.Context, val sdk.ValAddress, del sdk.AccAddress) error {
// period has already been incremented - we want to store the period ended by this delegation action
valCurrentRewards, err := k.GetValidatorCurrentRewards(ctx, val)
valCurrentRewards, err := k.ValidatorCurrentRewards.Get(ctx, val)
if err != nil {
return err
}

View File

@ -84,7 +84,7 @@ func (k Keeper) InitGenesis(ctx sdk.Context, data types.GenesisState) {
if err != nil {
panic(err)
}
err = k.SetValidatorCurrentRewards(ctx, valAddr, cur.Rewards)
err = k.ValidatorCurrentRewards.Set(ctx, valAddr, cur.Rewards)
if err != nil {
panic(err)
}
@ -198,15 +198,18 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState {
)
cur := make([]types.ValidatorCurrentRewardsRecord, 0)
k.IterateValidatorCurrentRewards(ctx,
func(val sdk.ValAddress, rewards types.ValidatorCurrentRewards) (stop bool) {
err = k.ValidatorCurrentRewards.Walk(ctx, nil,
func(val sdk.ValAddress, rewards types.ValidatorCurrentRewards) (stop bool, err error) {
cur = append(cur, types.ValidatorCurrentRewardsRecord{
ValidatorAddress: val.String(),
Rewards: rewards,
})
return false
return false, nil
},
)
if err != nil && !errors.Is(err, collections.ErrInvalidIterator) {
panic(err)
}
dels := make([]types.DelegatorStartingInfoRecord, 0)
k.IterateDelegatorStartingInfos(ctx,

View File

@ -108,7 +108,7 @@ func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, _ sdk.ConsAddress, valAddr
h.k.DeleteValidatorHistoricalRewards(ctx, valAddr)
// clear current rewards
err = h.k.DeleteValidatorCurrentRewards(ctx, valAddr)
err = h.k.ValidatorCurrentRewards.Remove(ctx, valAddr)
if err != nil {
return err
}

View File

@ -31,6 +31,7 @@ type Keeper struct {
Params collections.Item[types.Params]
FeePool collections.Item[types.FeePool]
DelegatorsWithdrawAddress collections.Map[sdk.AccAddress, sdk.AccAddress]
ValidatorCurrentRewards collections.Map[sdk.ValAddress, types.ValidatorCurrentRewards]
feeCollectorName string // name of the FeeCollector ModuleAccount
}
@ -64,6 +65,13 @@ func NewKeeper(
sdk.LengthPrefixedAddressKey(sdk.AccAddressKey), // nolint: staticcheck // sdk.LengthPrefixedAddressKey is needed to retain state compatibility
collcodec.KeyToValueCodec(sdk.AccAddressKey),
),
ValidatorCurrentRewards: collections.NewMap(
sb,
types.ValidatorCurrentRewardsPrefix,
"validators_current_rewards",
sdk.LengthPrefixedAddressKey(sdk.ValAddressKey), // nolint: staticcheck // sdk.LengthPrefixedAddressKey is needed to retain state compatibility
codec.CollValue[types.ValidatorCurrentRewards](cdc),
),
}
schema, err := sb.Build()

View File

@ -179,50 +179,6 @@ func (k Keeper) GetValidatorHistoricalReferenceCount(ctx context.Context) (count
return
}
// get current rewards for a validator
func (k Keeper) GetValidatorCurrentRewards(ctx context.Context, val sdk.ValAddress) (rewards types.ValidatorCurrentRewards, err error) {
store := k.storeService.OpenKVStore(ctx)
b, err := store.Get(types.GetValidatorCurrentRewardsKey(val))
if err != nil {
return
}
err = k.cdc.Unmarshal(b, &rewards)
return
}
// set current rewards for a validator
func (k Keeper) SetValidatorCurrentRewards(ctx context.Context, val sdk.ValAddress, rewards types.ValidatorCurrentRewards) error {
store := k.storeService.OpenKVStore(ctx)
b, err := k.cdc.Marshal(&rewards)
if err != nil {
return err
}
return store.Set(types.GetValidatorCurrentRewardsKey(val), b)
}
// delete current rewards for a validator
func (k Keeper) DeleteValidatorCurrentRewards(ctx context.Context, val sdk.ValAddress) error {
store := k.storeService.OpenKVStore(ctx)
return store.Delete(types.GetValidatorCurrentRewardsKey(val))
}
// iterate over current rewards
func (k Keeper) IterateValidatorCurrentRewards(ctx context.Context, handler func(val sdk.ValAddress, rewards types.ValidatorCurrentRewards) (stop bool)) {
store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
iter := storetypes.KVStorePrefixIterator(store, types.ValidatorCurrentRewardsPrefix)
defer iter.Close()
for ; iter.Valid(); iter.Next() {
var rewards types.ValidatorCurrentRewards
k.cdc.MustUnmarshal(iter.Value(), &rewards)
addr := types.GetValidatorCurrentRewardsAddress(iter.Key())
if handler(addr, rewards) {
break
}
}
}
// get accumulated commission for a validator
func (k Keeper) GetValidatorAccumulatedCommission(ctx context.Context, val sdk.ValAddress) (commission types.ValidatorAccumulatedCommission, err error) {
store := k.storeService.OpenKVStore(ctx)

View File

@ -4,7 +4,9 @@ import (
"context"
"fmt"
"cosmossdk.io/collections"
"cosmossdk.io/math"
"github.com/pkg/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -21,7 +23,7 @@ func (k Keeper) initializeValidator(ctx context.Context, val stakingtypes.Valida
}
// set current rewards (starting at period 1)
err = k.SetValidatorCurrentRewards(ctx, val.GetOperator(), types.NewValidatorCurrentRewards(sdk.DecCoins{}, 1))
err = k.ValidatorCurrentRewards.Set(ctx, val.GetOperator(), types.NewValidatorCurrentRewards(sdk.DecCoins{}, 1))
if err != nil {
return err
}
@ -40,8 +42,8 @@ func (k Keeper) initializeValidator(ctx context.Context, val stakingtypes.Valida
// increment validator period, returning the period just ended
func (k Keeper) IncrementValidatorPeriod(ctx context.Context, val stakingtypes.ValidatorI) (uint64, error) {
// fetch current rewards
rewards, err := k.GetValidatorCurrentRewards(ctx, val.GetOperator())
if err != nil {
rewards, err := k.ValidatorCurrentRewards.Get(ctx, val.GetOperator())
if err != nil && !errors.Is(err, collections.ErrNotFound) {
return 0, err
}
@ -100,7 +102,7 @@ func (k Keeper) IncrementValidatorPeriod(ctx context.Context, val stakingtypes.V
}
// set current rewards, incrementing period by 1
err = k.SetValidatorCurrentRewards(ctx, val.GetOperator(), types.NewValidatorCurrentRewards(sdk.DecCoins{}, rewards.Period+1))
err = k.ValidatorCurrentRewards.Set(ctx, val.GetOperator(), types.NewValidatorCurrentRewards(sdk.DecCoins{}, rewards.Period+1))
if err != nil {
return 0, err
}

View File

@ -68,7 +68,7 @@ func TestStoreMigration(t *testing.T) {
{
"ValidatorCurrentRewards",
v1.GetValidatorCurrentRewardsKey(valAddr),
types.GetValidatorCurrentRewardsKey(valAddr),
append(types.ValidatorCurrentRewardsPrefix, address.MustLengthPrefix(valAddr.Bytes())...),
},
{
"ValidatorAccumulatedCommission",

View File

@ -36,7 +36,6 @@ func TestDecodeDistributionStore(t *testing.T) {
outstanding := types.ValidatorOutstandingRewards{Rewards: decCoins}
commission := types.ValidatorAccumulatedCommission{Commission: decCoins}
historicalRewards := types.NewValidatorHistoricalRewards(decCoins, 100)
currentRewards := types.NewValidatorCurrentRewards(decCoins, 5)
slashEvent := types.NewValidatorSlashEvent(10, math.LegacyOneDec())
kvPairs := kv.Pairs{
@ -46,7 +45,6 @@ func TestDecodeDistributionStore(t *testing.T) {
{Key: types.GetValidatorOutstandingRewardsKey(valAddr1), Value: cdc.MustMarshal(&outstanding)},
{Key: types.GetDelegatorStartingInfoKey(valAddr1, delAddr1), Value: cdc.MustMarshal(&info)},
{Key: types.GetValidatorHistoricalRewardsKey(valAddr1, 100), Value: cdc.MustMarshal(&historicalRewards)},
{Key: types.GetValidatorCurrentRewardsKey(valAddr1), Value: cdc.MustMarshal(&currentRewards)},
{Key: types.GetValidatorAccumulatedCommissionKey(valAddr1), Value: cdc.MustMarshal(&commission)},
{Key: types.GetValidatorSlashEventKeyPrefix(valAddr1, 13), Value: cdc.MustMarshal(&slashEvent)},
{Key: []byte{0x99}, Value: []byte{0x99}},
@ -62,7 +60,6 @@ func TestDecodeDistributionStore(t *testing.T) {
{"ValidatorOutstandingRewards", fmt.Sprintf("%v\n%v", outstanding, outstanding)},
{"DelegatorStartingInfo", fmt.Sprintf("%v\n%v", info, info)},
{"ValidatorHistoricalRewards", fmt.Sprintf("%v\n%v", historicalRewards, historicalRewards)},
{"ValidatorCurrentRewards", fmt.Sprintf("%v\n%v", currentRewards, currentRewards)},
{"ValidatorAccumulatedCommission", fmt.Sprintf("%v\n%v", commission, commission)},
{"ValidatorSlashEvent", fmt.Sprintf("%v\n%v", slashEvent, slashEvent)},
{"other", ""},

View File

@ -309,10 +309,10 @@ func (suite *SimTestSuite) getTestingValidator(accounts []simtypes.Account, comm
func (suite *SimTestSuite) setupValidatorRewards(valAddress sdk.ValAddress) {
decCoins := sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, math.LegacyOneDec())}
historicalRewards := types.NewValidatorHistoricalRewards(decCoins, 2)
suite.distrKeeper.SetValidatorHistoricalRewards(suite.ctx, valAddress, 2, historicalRewards)
suite.Require().NoError(suite.distrKeeper.SetValidatorHistoricalRewards(suite.ctx, valAddress, 2, historicalRewards))
// setup current revards
currentRewards := types.NewValidatorCurrentRewards(decCoins, 3)
suite.distrKeeper.SetValidatorCurrentRewards(suite.ctx, valAddress, currentRewards)
suite.Require().NoError(suite.distrKeeper.ValidatorCurrentRewards.Set(suite.ctx, valAddress, currentRewards))
}
func TestSimTestSuite(t *testing.T) {

View File

@ -50,7 +50,7 @@ var (
DelegatorWithdrawAddrPrefix = collections.NewPrefix(3) // key for delegator withdraw address
DelegatorStartingInfoPrefix = []byte{0x04} // key for delegator starting info
ValidatorHistoricalRewardsPrefix = []byte{0x05} // key for historical validators rewards / stake
ValidatorHistoricalRewardsPrefix = collections.NewPrefix(5) // key for historical validators rewards / stake
ValidatorCurrentRewardsPrefix = []byte{0x06} // key for current validator rewards
ValidatorAccumulatedCommissionPrefix = []byte{0x07} // key for accumulated validator commission
ValidatorSlashEventPrefix = []byte{0x08} // key for validator slash fraction
@ -177,11 +177,6 @@ func GetValidatorHistoricalRewardsKey(v sdk.ValAddress, k uint64) []byte {
return append(append(ValidatorHistoricalRewardsPrefix, address.MustLengthPrefix(v.Bytes())...), b...)
}
// GetValidatorCurrentRewardsKey creates the key for a validator's current rewards.
func GetValidatorCurrentRewardsKey(v sdk.ValAddress) []byte {
return append(ValidatorCurrentRewardsPrefix, address.MustLengthPrefix(v.Bytes())...)
}
// GetValidatorAccumulatedCommissionKey creates the key for a validator's current commission.
func GetValidatorAccumulatedCommissionKey(v sdk.ValAddress) []byte {
return append(ValidatorAccumulatedCommissionPrefix, address.MustLengthPrefix(v.Bytes())...)

View File

@ -388,10 +388,10 @@ func (s *SimTestSuite) getTestingValidator(ctx sdk.Context, commission types.Com
func (s *SimTestSuite) setupValidatorRewards(ctx sdk.Context, valAddress sdk.ValAddress) {
decCoins := sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, math.LegacyOneDec())}
historicalRewards := distrtypes.NewValidatorHistoricalRewards(decCoins, 2)
s.distrKeeper.SetValidatorHistoricalRewards(ctx, valAddress, 2, historicalRewards)
s.Require().NoError(s.distrKeeper.SetValidatorHistoricalRewards(ctx, valAddress, 2, historicalRewards))
// setup current revards
currentRewards := distrtypes.NewValidatorCurrentRewards(decCoins, 3)
s.distrKeeper.SetValidatorCurrentRewards(ctx, valAddress, currentRewards)
s.Require().NoError(s.distrKeeper.ValidatorCurrentRewards.Set(ctx, valAddress, currentRewards))
}
func TestSimTestSuite(t *testing.T) {