refactor(distribution)!: use collections for DelegatorStartingInfo state (#16483)

Co-authored-by: unknown unknown <unknown@unknown>
This commit is contained in:
testinginprod
2023-06-14 10:39:11 +00:00
committed by GitHub
co-authored by unknown unknown
parent bbb452f609
commit b3da8bb4e8
13 changed files with 51 additions and 132 deletions
+9 -7
View File
@@ -2,8 +2,10 @@ package keeper
import (
"context"
"errors"
"fmt"
"cosmossdk.io/collections"
"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
@@ -31,7 +33,7 @@ func (k Keeper) initializeDelegation(ctx context.Context, val sdk.ValAddress, de
// we don't store directly, so multiply delegation shares * (tokens per share)
// note: necessary to truncate so we don't allow withdrawing more rewards than owed
stake := validator.TokensFromSharesTruncated(delegation.GetShares())
return k.SetDelegatorStartingInfo(ctx, val, del, types.NewDelegatorStartingInfo(previousPeriod, stake, uint64(sdkCtx.BlockHeight())))
return k.DelegatorStartingInfo.Set(ctx, collections.Join(val, del), types.NewDelegatorStartingInfo(previousPeriod, stake, uint64(sdkCtx.BlockHeight())))
}
// calculate the rewards accrued by a delegation between two periods
@@ -71,8 +73,8 @@ func (k Keeper) calculateDelegationRewardsBetween(ctx context.Context, val staki
// calculate the total rewards accrued by a delegation
func (k Keeper) CalculateDelegationRewards(ctx context.Context, val stakingtypes.ValidatorI, del stakingtypes.DelegationI, endingPeriod uint64) (rewards sdk.DecCoins, err error) {
// fetch starting info for delegation
startingInfo, err := k.GetDelegatorStartingInfo(ctx, del.GetValidatorAddr(), del.GetDelegatorAddr())
if err != nil {
startingInfo, err := k.DelegatorStartingInfo.Get(ctx, collections.Join(del.GetValidatorAddr(), del.GetDelegatorAddr()))
if err != nil && !errors.Is(err, collections.ErrNotFound) {
return
}
@@ -167,7 +169,7 @@ func (k Keeper) CalculateDelegationRewards(ctx context.Context, val stakingtypes
func (k Keeper) withdrawDelegationRewards(ctx context.Context, val stakingtypes.ValidatorI, del stakingtypes.DelegationI) (sdk.Coins, error) {
// check existence of delegator starting info
hasInfo, err := k.HasDelegatorStartingInfo(ctx, del.GetValidatorAddr(), del.GetDelegatorAddr())
hasInfo, err := k.DelegatorStartingInfo.Has(ctx, collections.Join(del.GetValidatorAddr(), del.GetDelegatorAddr()))
if err != nil {
return nil, err
}
@@ -241,8 +243,8 @@ func (k Keeper) withdrawDelegationRewards(ctx context.Context, val stakingtypes.
}
// decrement reference count of starting period
startingInfo, err := k.GetDelegatorStartingInfo(ctx, del.GetValidatorAddr(), del.GetDelegatorAddr())
if err != nil {
startingInfo, err := k.DelegatorStartingInfo.Get(ctx, collections.Join(del.GetValidatorAddr(), del.GetDelegatorAddr()))
if err != nil && !errors.Is(err, collections.ErrNotFound) {
return nil, err
}
@@ -253,7 +255,7 @@ func (k Keeper) withdrawDelegationRewards(ctx context.Context, val stakingtypes.
}
// remove delegator starting info
err = k.DeleteDelegatorStartingInfo(ctx, del.GetValidatorAddr(), del.GetDelegatorAddr())
err = k.DelegatorStartingInfo.Remove(ctx, collections.Join(del.GetValidatorAddr(), del.GetDelegatorAddr()))
if err != nil {
return nil, err
}
+12 -11
View File
@@ -99,7 +99,7 @@ func (k Keeper) InitGenesis(ctx sdk.Context, data types.GenesisState) {
panic(err)
}
err = k.SetDelegatorStartingInfo(ctx, valAddr, delegatorAddress, del.StartingInfo)
err = k.DelegatorStartingInfo.Set(ctx, collections.Join(valAddr, sdk.AccAddress(delegatorAddress)), del.StartingInfo)
if err != nil {
panic(err)
}
@@ -212,16 +212,17 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState {
}
dels := make([]types.DelegatorStartingInfoRecord, 0)
k.IterateDelegatorStartingInfos(ctx,
func(val sdk.ValAddress, del sdk.AccAddress, info types.DelegatorStartingInfo) (stop bool) {
dels = append(dels, types.DelegatorStartingInfoRecord{
ValidatorAddress: val.String(),
DelegatorAddress: del.String(),
StartingInfo: info,
})
return false
},
)
err = k.DelegatorStartingInfo.Walk(ctx, nil, func(key collections.Pair[sdk.ValAddress, sdk.AccAddress], value types.DelegatorStartingInfo) (stop bool, err error) {
dels = append(dels, types.DelegatorStartingInfoRecord{
DelegatorAddress: key.K2().String(),
ValidatorAddress: key.K1().String(),
StartingInfo: value,
})
return false, nil
})
if err != nil && !errors.Is(err, collections.ErrInvalidIterator) {
panic(err)
}
slashes := make([]types.ValidatorSlashEventRecord, 0)
k.IterateValidatorSlashEvents(ctx,
+8
View File
@@ -32,6 +32,7 @@ type Keeper struct {
FeePool collections.Item[types.FeePool]
DelegatorsWithdrawAddress collections.Map[sdk.AccAddress, sdk.AccAddress]
ValidatorCurrentRewards collections.Map[sdk.ValAddress, types.ValidatorCurrentRewards]
DelegatorStartingInfo collections.Map[collections.Pair[sdk.ValAddress, sdk.AccAddress], types.DelegatorStartingInfo]
feeCollectorName string // name of the FeeCollector ModuleAccount
}
@@ -72,6 +73,13 @@ func NewKeeper(
sdk.LengthPrefixedAddressKey(sdk.ValAddressKey), // nolint: staticcheck // sdk.LengthPrefixedAddressKey is needed to retain state compatibility
codec.CollValue[types.ValidatorCurrentRewards](cdc),
),
DelegatorStartingInfo: collections.NewMap(
sb,
types.DelegatorStartingInfoPrefix,
"delegators_starting_info",
collections.PairKeyCodec(sdk.ValAddressKey, sdk.LengthPrefixedAddressKey(sdk.AccAddressKey)), // nolint: staticcheck // sdk.LengthPrefixedAddressKey is needed to retain state compatibility
codec.CollValue[types.DelegatorStartingInfo](cdc),
),
}
schema, err := sb.Build()
-50
View File
@@ -52,56 +52,6 @@ func (k Keeper) SetPreviousProposerConsAddr(ctx context.Context, consAddr sdk.Co
store.Set(types.ProposerKey, bz)
}
// get the starting info associated with a delegator
func (k Keeper) GetDelegatorStartingInfo(ctx context.Context, val sdk.ValAddress, del sdk.AccAddress) (period types.DelegatorStartingInfo, err error) {
store := k.storeService.OpenKVStore(ctx)
b, err := store.Get(types.GetDelegatorStartingInfoKey(val, del))
if err != nil {
return
}
err = k.cdc.Unmarshal(b, &period)
return period, err
}
// set the starting info associated with a delegator
func (k Keeper) SetDelegatorStartingInfo(ctx context.Context, val sdk.ValAddress, del sdk.AccAddress, period types.DelegatorStartingInfo) error {
store := k.storeService.OpenKVStore(ctx)
b, err := k.cdc.Marshal(&period)
if err != nil {
return err
}
return store.Set(types.GetDelegatorStartingInfoKey(val, del), b)
}
// check existence of the starting info associated with a delegator
func (k Keeper) HasDelegatorStartingInfo(ctx context.Context, val sdk.ValAddress, del sdk.AccAddress) (bool, error) {
store := k.storeService.OpenKVStore(ctx)
return store.Has(types.GetDelegatorStartingInfoKey(val, del))
}
// delete the starting info associated with a delegator
func (k Keeper) DeleteDelegatorStartingInfo(ctx context.Context, val sdk.ValAddress, del sdk.AccAddress) error {
store := k.storeService.OpenKVStore(ctx)
return store.Delete(types.GetDelegatorStartingInfoKey(val, del))
}
// iterate over delegator starting infos
func (k Keeper) IterateDelegatorStartingInfos(ctx context.Context, handler func(val sdk.ValAddress, del sdk.AccAddress, info types.DelegatorStartingInfo) (stop bool)) {
store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
iter := storetypes.KVStorePrefixIterator(store, types.DelegatorStartingInfoPrefix)
defer iter.Close()
for ; iter.Valid(); iter.Next() {
var info types.DelegatorStartingInfo
k.cdc.MustUnmarshal(iter.Value(), &info)
val, del := types.GetDelegatorStartingInfoAddresses(iter.Key())
if handler(val, del, info) {
break
}
}
}
// get historical rewards for a particular period
func (k Keeper) GetValidatorHistoricalRewards(ctx context.Context, val sdk.ValAddress, period uint64) (rewards types.ValidatorHistoricalRewards, err error) {
store := k.storeService.OpenKVStore(ctx)
+1 -1
View File
@@ -58,7 +58,7 @@ func TestStoreMigration(t *testing.T) {
{
"DelegatorStartingInfo",
v1.GetDelegatorStartingInfoKey(valAddr, addr2),
types.GetDelegatorStartingInfoKey(valAddr, addr2),
append(append(types.DelegatorStartingInfoPrefix, address.MustLengthPrefix(valAddr.Bytes())...), address.MustLengthPrefix(addr2.Bytes())...),
},
{
"ValidatorHistoricalRewards",
@@ -18,7 +18,6 @@ import (
var (
delPk1 = ed25519.GenPrivKey().PubKey()
delAddr1 = sdk.AccAddress(delPk1.Address())
valAddr1 = sdk.ValAddress(delPk1.Address())
consAddr1 = sdk.ConsAddress(delPk1.Address().Bytes())
)
@@ -32,7 +31,6 @@ func TestDecodeDistributionStore(t *testing.T) {
decCoins := sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, math.LegacyOneDec())}
feePool := types.InitialFeePool()
feePool.CommunityPool = decCoins
info := types.NewDelegatorStartingInfo(2, math.LegacyOneDec(), 200)
outstanding := types.ValidatorOutstandingRewards{Rewards: decCoins}
commission := types.ValidatorAccumulatedCommission{Commission: decCoins}
historicalRewards := types.NewValidatorHistoricalRewards(decCoins, 100)
@@ -43,7 +41,6 @@ func TestDecodeDistributionStore(t *testing.T) {
{Key: types.FeePoolKey, Value: cdc.MustMarshal(&feePool)},
{Key: types.ProposerKey, Value: consAddr1.Bytes()},
{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.GetValidatorAccumulatedCommissionKey(valAddr1), Value: cdc.MustMarshal(&commission)},
{Key: types.GetValidatorSlashEventKeyPrefix(valAddr1, 13), Value: cdc.MustMarshal(&slashEvent)},
@@ -58,7 +55,6 @@ func TestDecodeDistributionStore(t *testing.T) {
{"FeePool", fmt.Sprintf("%v\n%v", feePool, feePool)},
{"Proposer", fmt.Sprintf("%v\n%v", consAddr1, consAddr1)},
{"ValidatorOutstandingRewards", fmt.Sprintf("%v\n%v", outstanding, outstanding)},
{"DelegatorStartingInfo", fmt.Sprintf("%v\n%v", info, info)},
{"ValidatorHistoricalRewards", fmt.Sprintf("%v\n%v", historicalRewards, historicalRewards)},
{"ValidatorAccumulatedCommission", fmt.Sprintf("%v\n%v", commission, commission)},
{"ValidatorSlashEvent", fmt.Sprintf("%v\n%v", slashEvent, slashEvent)},
+4 -2
View File
@@ -4,6 +4,7 @@ import (
"math/rand"
"testing"
"cosmossdk.io/collections"
"cosmossdk.io/depinject"
"cosmossdk.io/log"
"cosmossdk.io/math"
@@ -110,14 +111,15 @@ func (suite *SimTestSuite) TestSimulateMsgWithdrawDelegatorReward() {
delegator := accounts[1]
delegation := stakingtypes.NewDelegation(delegator.Address, validator0.GetOperator(), issuedShares)
suite.stakingKeeper.SetDelegation(suite.ctx, delegation)
suite.distrKeeper.SetDelegatorStartingInfo(suite.ctx, validator0.GetOperator(), delegator.Address, types.NewDelegatorStartingInfo(2, math.LegacyOneDec(), 200))
suite.Require().NoError(suite.distrKeeper.DelegatorStartingInfo.Set(suite.ctx, collections.Join(validator0.GetOperator(), delegator.Address), types.NewDelegatorStartingInfo(2, math.LegacyOneDec(), 200)))
suite.setupValidatorRewards(validator0.GetOperator())
suite.app.FinalizeBlock(&abci.RequestFinalizeBlock{
_, err := suite.app.FinalizeBlock(&abci.RequestFinalizeBlock{
Height: suite.app.LastBlockHeight() + 1,
Hash: suite.app.LastCommitID().Hash,
})
suite.Require().NoError(err)
// execute operation
op := simulation.SimulateMsgWithdrawDelegatorReward(suite.txConfig, suite.accountKeeper, suite.bankKeeper, suite.distrKeeper, suite.stakingKeeper)
+1 -48
View File
@@ -49,7 +49,7 @@ var (
ValidatorOutstandingRewardsPrefix = []byte{0x02} // key for outstanding rewards
DelegatorWithdrawAddrPrefix = collections.NewPrefix(3) // key for delegator withdraw address
DelegatorStartingInfoPrefix = []byte{0x04} // key for delegator starting info
DelegatorStartingInfoPrefix = collections.NewPrefix(4) // key for delegator starting info
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
@@ -71,35 +71,6 @@ func GetValidatorOutstandingRewardsAddress(key []byte) (valAddr sdk.ValAddress)
return sdk.ValAddress(addr)
}
// GetDelegatorWithdrawInfoAddress creates an address from a delegator's withdraw info key.
func GetDelegatorWithdrawInfoAddress(key []byte) (delAddr sdk.AccAddress) {
// key is in the format:
// 0x03<accAddrLen (1 Byte)><accAddr_Bytes>
// Remove prefix and address length.
kv.AssertKeyAtLeastLength(key, 3)
addr := key[2:]
kv.AssertKeyLength(addr, int(key[1]))
return sdk.AccAddress(addr)
}
// GetDelegatorStartingInfoAddresses creates the addresses from a delegator starting info key.
func GetDelegatorStartingInfoAddresses(key []byte) (valAddr sdk.ValAddress, delAddr sdk.AccAddress) {
// key is in the format:
// 0x04<valAddrLen (1 Byte)><valAddr_Bytes><accAddrLen (1 Byte)><accAddr_Bytes>
kv.AssertKeyAtLeastLength(key, 2)
valAddrLen := int(key[1])
kv.AssertKeyAtLeastLength(key, 3+valAddrLen)
valAddr = sdk.ValAddress(key[2 : 2+valAddrLen])
delAddrLen := int(key[2+valAddrLen])
kv.AssertKeyAtLeastLength(key, 4+valAddrLen)
delAddr = sdk.AccAddress(key[3+valAddrLen:])
kv.AssertKeyLength(delAddr.Bytes(), delAddrLen)
return
}
// GetValidatorHistoricalRewardsAddressPeriod creates the address & period from a validator's historical rewards key.
func GetValidatorHistoricalRewardsAddressPeriod(key []byte) (valAddr sdk.ValAddress, period uint64) {
// key is in the format:
@@ -114,19 +85,6 @@ func GetValidatorHistoricalRewardsAddressPeriod(key []byte) (valAddr sdk.ValAddr
return
}
// GetValidatorCurrentRewardsAddress creates the address from a validator's current rewards key.
func GetValidatorCurrentRewardsAddress(key []byte) (valAddr sdk.ValAddress) {
// key is in the format:
// 0x06<valAddrLen (1 Byte)><valAddr_Bytes>: ValidatorCurrentRewards
// Remove prefix and address length.
kv.AssertKeyAtLeastLength(key, 3)
addr := key[2:]
kv.AssertKeyLength(addr, int(key[1]))
return sdk.ValAddress(addr)
}
// GetValidatorAccumulatedCommissionAddress creates the address from a validator's accumulated commission key.
func GetValidatorAccumulatedCommissionAddress(key []byte) (valAddr sdk.ValAddress) {
// key is in the format:
@@ -160,11 +118,6 @@ func GetValidatorOutstandingRewardsKey(valAddr sdk.ValAddress) []byte {
return append(ValidatorOutstandingRewardsPrefix, address.MustLengthPrefix(valAddr.Bytes())...)
}
// GetDelegatorStartingInfoKey creates the key for a delegator's starting info.
func GetDelegatorStartingInfoKey(v sdk.ValAddress, d sdk.AccAddress) []byte {
return append(append(DelegatorStartingInfoPrefix, address.MustLengthPrefix(v.Bytes())...), address.MustLengthPrefix(d.Bytes())...)
}
// GetValidatorHistoricalRewardsPrefix creates the prefix key for a validator's historical rewards.
func GetValidatorHistoricalRewardsPrefix(v sdk.ValAddress) []byte {
return append(ValidatorHistoricalRewardsPrefix, address.MustLengthPrefix(v.Bytes())...)