Skip to content

Commit

Permalink
refactor(x/staking): Migrate UnbondingDelegation to collections (#17270)
Browse files Browse the repository at this point in the history
  • Loading branch information
likhita-809 committed Aug 28, 2023
1 parent cc6511e commit a734071
Show file tree
Hide file tree
Showing 13 changed files with 192 additions and 163 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ Ref: https://keepachangelog.com/en/1.0.0/

### API Breaking Changes

* (x/staking) [#17270](https://github.com/cosmos/cosmos-sdk/pull/17270) Use collections for `UnbondingDelegation`:
* remove from `types`: `GetUBDsKey`
* remove from `Keeper`: `IterateUnbondingDelegations`, `IterateDelegatorUnbondingDelegations`
* (client/keys) [#17503](https://github.com/cosmos/cosmos-sdk/pull/17503) `clientkeys.NewKeyOutput`, `MkConsKeyOutput`, `MkValKeyOutput`, `MkAccKeyOutput`, `MkAccKeysOutput` now take their corresponding address codec instead of using the global SDK config.
* (x/staking) [#17336](https://github.com/cosmos/cosmos-sdk/pull/17336) Use collections for `RedelegationByValDstIndexKey`:
* remove from `types`: `GetREDByValDstIndexKey`, `GetREDsToValDstIndexKey`
Expand Down
25 changes: 15 additions & 10 deletions simapp/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"

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

servertypes "github.com/cosmos/cosmos-sdk/server/types"
Expand Down Expand Up @@ -191,16 +192,20 @@ func (app *SimApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []
}

// iterate through unbonding delegations, reset creation height
err = app.StakingKeeper.IterateUnbondingDelegations(ctx, func(_ int64, ubd stakingtypes.UnbondingDelegation) (stop bool) {
for i := range ubd.Entries {
ubd.Entries[i].CreationHeight = 0
}
err = app.StakingKeeper.SetUnbondingDelegation(ctx, ubd)
if err != nil {
panic(err)
}
return false
})
err = app.StakingKeeper.UnbondingDelegations.Walk(
ctx,
nil,
func(key collections.Pair[[]byte, []byte], ubd stakingtypes.UnbondingDelegation) (stop bool, err error) {
for i := range ubd.Entries {
ubd.Entries[i].CreationHeight = 0
}
err = app.StakingKeeper.SetUnbondingDelegation(ctx, ubd)
if err != nil {
return true, err
}
return false, err
},
)
if err != nil {
panic(err)
}
Expand Down
129 changes: 41 additions & 88 deletions x/staking/keeper/delegation.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,42 +130,38 @@ func (k Keeper) RemoveDelegation(ctx context.Context, delegation types.Delegatio
func (k Keeper) GetUnbondingDelegations(ctx context.Context, delegator sdk.AccAddress, maxRetrieve uint16) (unbondingDelegations []types.UnbondingDelegation, err error) {
unbondingDelegations = make([]types.UnbondingDelegation, maxRetrieve)

store := k.storeService.OpenKVStore(ctx)
delegatorPrefixKey := types.GetUBDsKey(delegator)
i := 0
rng := collections.NewPrefixedPairRange[[]byte, []byte](delegator)
err = k.UnbondingDelegations.Walk(
ctx,
rng,
func(key collections.Pair[[]byte, []byte], value types.UnbondingDelegation) (stop bool, err error) {
unbondingDelegations = append(unbondingDelegations, value)
i++

iterator, err := store.Iterator(delegatorPrefixKey, storetypes.PrefixEndBytes(delegatorPrefixKey))
if i >= int(maxRetrieve) {
return true, nil
}
return false, nil
},
)
if err != nil {
return unbondingDelegations, err
}
defer iterator.Close()

i := 0
for ; iterator.Valid() && i < int(maxRetrieve); iterator.Next() {
unbondingDelegation, err := types.UnmarshalUBD(k.cdc, iterator.Value())
if err != nil {
return unbondingDelegations, err
}
unbondingDelegations[i] = unbondingDelegation
i++
return nil, err
}

return unbondingDelegations[:i], nil // trim if the array length < maxRetrieve
}

// GetUnbondingDelegation returns a unbonding delegation.
func (k Keeper) GetUnbondingDelegation(ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) (ubd types.UnbondingDelegation, err error) {
store := k.storeService.OpenKVStore(ctx)
key := types.GetUBDKey(delAddr, valAddr)
value, err := store.Get(key)
ubd, err = k.UnbondingDelegations.Get(ctx, collections.Join(delAddr.Bytes(), valAddr.Bytes()))
if err != nil {
if errors.Is(err, collections.ErrNotFound) {
return ubd, types.ErrNoUnbondingDelegation
}
return ubd, err
}

if value == nil {
return ubd, types.ErrNoUnbondingDelegation
}

return types.UnmarshalUBD(k.cdc, value)
return ubd, nil
}

// GetUnbondingDelegationsFromValidator returns all unbonding delegations from a
Expand Down Expand Up @@ -195,63 +191,24 @@ func (k Keeper) GetUnbondingDelegationsFromValidator(ctx context.Context, valAdd
return ubds, nil
}

// IterateUnbondingDelegations iterates through all of the unbonding delegations.
func (k Keeper) IterateUnbondingDelegations(ctx context.Context, fn func(index int64, ubd types.UnbondingDelegation) (stop bool)) error {
store := k.storeService.OpenKVStore(ctx)
prefix := types.UnbondingDelegationKey
iterator, err := store.Iterator(prefix, storetypes.PrefixEndBytes(prefix))
if err != nil {
return err
}
defer iterator.Close()

for i := int64(0); iterator.Valid(); iterator.Next() {
ubd, err := types.UnmarshalUBD(k.cdc, iterator.Value())
if err != nil {
return err
}
if stop := fn(i, ubd); stop {
break
}
i++
}

return nil
}

// GetDelegatorUnbonding returns the total amount a delegator has unbonding.
func (k Keeper) GetDelegatorUnbonding(ctx context.Context, delegator sdk.AccAddress) (math.Int, error) {
unbonding := math.ZeroInt()
err := k.IterateDelegatorUnbondingDelegations(ctx, delegator, func(ubd types.UnbondingDelegation) bool {
for _, entry := range ubd.Entries {
unbonding = unbonding.Add(entry.Balance)
}
return false
})
return unbonding, err
}

// IterateDelegatorUnbondingDelegations iterates through a delegator's unbonding delegations.
func (k Keeper) IterateDelegatorUnbondingDelegations(ctx context.Context, delegator sdk.AccAddress, cb func(ubd types.UnbondingDelegation) (stop bool)) error {
store := k.storeService.OpenKVStore(ctx)
prefix := types.GetUBDsKey(delegator)
iterator, err := store.Iterator(prefix, storetypes.PrefixEndBytes(prefix))
rng := collections.NewPrefixedPairRange[[]byte, []byte](delegator)
err := k.UnbondingDelegations.Walk(
ctx,
rng,
func(key collections.Pair[[]byte, []byte], ubd types.UnbondingDelegation) (stop bool, err error) {
for _, entry := range ubd.Entries {
unbonding = unbonding.Add(entry.Balance)
}
return false, nil
},
)
if err != nil {
return err
return unbonding, err
}
defer iterator.Close()

for ; iterator.Valid(); iterator.Next() {
ubd, err := types.UnmarshalUBD(k.cdc, iterator.Value())
if err != nil {
return err
}
if cb(ubd) {
break
}
}

return nil
return unbonding, err
}

// GetDelegatorBonded returs the total amount a delegator has bonded.
Expand Down Expand Up @@ -307,19 +264,17 @@ func (k Keeper) HasMaxUnbondingDelegationEntries(ctx context.Context, delegatorA

// SetUnbondingDelegation sets the unbonding delegation and associated index.
func (k Keeper) SetUnbondingDelegation(ctx context.Context, ubd types.UnbondingDelegation) error {
store := k.storeService.OpenKVStore(ctx)

delAddr, err := k.authKeeper.AddressCodec().StringToBytes(ubd.DelegatorAddress)
if err != nil {
return err
}

store := k.storeService.OpenKVStore(ctx)
bz := types.MustMarshalUBD(k.cdc, ubd)
valAddr, err := k.validatorAddressCodec.StringToBytes(ubd.ValidatorAddress)
if err != nil {
return err
}
key := types.GetUBDKey(delAddr, valAddr)
err = store.Set(key, bz)
err = k.UnbondingDelegations.Set(ctx, collections.Join(delAddr, valAddr), ubd)
if err != nil {
return err
}
Expand All @@ -329,23 +284,21 @@ func (k Keeper) SetUnbondingDelegation(ctx context.Context, ubd types.UnbondingD

// RemoveUnbondingDelegation removes the unbonding delegation object and associated index.
func (k Keeper) RemoveUnbondingDelegation(ctx context.Context, ubd types.UnbondingDelegation) error {
delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(ubd.DelegatorAddress)
store := k.storeService.OpenKVStore(ctx)
delAddr, err := k.authKeeper.AddressCodec().StringToBytes(ubd.DelegatorAddress)
if err != nil {
return err
}

store := k.storeService.OpenKVStore(ctx)
addr, err := k.validatorAddressCodec.StringToBytes(ubd.ValidatorAddress)
valAddr, err := k.validatorAddressCodec.StringToBytes(ubd.ValidatorAddress)
if err != nil {
return err
}
key := types.GetUBDKey(delegatorAddress, addr)
err = store.Delete(key)
err = k.UnbondingDelegations.Remove(ctx, collections.Join(delAddr, valAddr))
if err != nil {
return err
}

return store.Delete(types.GetUBDByValIndexKey(delegatorAddress, addr))
return store.Delete(types.GetUBDByValIndexKey(delAddr, valAddr))
}

// SetUnbondingDelegationEntry adds an entry to the unbonding delegation at
Expand Down
13 changes: 9 additions & 4 deletions x/staking/keeper/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

abci "github.com/cometbft/cometbft/abci/types"

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

sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -214,10 +215,14 @@ func (k Keeper) InitGenesis(ctx context.Context, data *types.GenesisState) (res
func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState {
var unbondingDelegations []types.UnbondingDelegation

err := k.IterateUnbondingDelegations(ctx, func(_ int64, ubd types.UnbondingDelegation) (stop bool) {
unbondingDelegations = append(unbondingDelegations, ubd)
return false
})
err := k.UnbondingDelegations.Walk(
ctx,
nil,
func(key collections.Pair[[]byte, []byte], value types.UnbondingDelegation) (stop bool, err error) {
unbondingDelegations = append(unbondingDelegations, value)
return false, nil
},
)
if err != nil {
panic(err)
}
Expand Down
20 changes: 10 additions & 10 deletions x/staking/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,16 +358,16 @@ func (k Querier) DelegatorUnbondingDelegations(ctx context.Context, req *types.Q
return nil, err
}

store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
unbStore := prefix.NewStore(store, types.GetUBDsKey(delAddr))
pageRes, err := query.Paginate(unbStore, req.Pagination, func(key, value []byte) error {
unbond, err := types.UnmarshalUBD(k.cdc, value)
if err != nil {
return err
}
unbondingDelegations = append(unbondingDelegations, unbond)
return nil
})
_, pageRes, err := query.CollectionPaginate(
ctx,
k.UnbondingDelegations,
req.Pagination,
func(key collections.Pair[[]byte, []byte], value types.UnbondingDelegation) (types.UnbondingDelegation, error) {
unbondingDelegations = append(unbondingDelegations, value)
return value, nil
},
query.WithCollectionPaginationPairPrefix[[]byte, []byte](delAddr),
)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}
Expand Down
17 changes: 11 additions & 6 deletions x/staking/keeper/invariants.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"fmt"

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

sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -72,12 +73,16 @@ func ModuleAccountInvariants(k *Keeper) sdk.Invariant {
panic(err)
}

err = k.IterateUnbondingDelegations(ctx, func(_ int64, ubd types.UnbondingDelegation) bool {
for _, entry := range ubd.Entries {
notBonded = notBonded.Add(entry.Balance)
}
return false
})
err = k.UnbondingDelegations.Walk(
ctx,
nil,
func(key collections.Pair[[]byte, []byte], ubd types.UnbondingDelegation) (stop bool, err error) {
for _, entry := range ubd.Entries {
notBonded = notBonded.Add(entry.Balance)
}
return false, nil
},
)
if err != nil {
panic(err)
}
Expand Down
9 changes: 9 additions & 0 deletions x/staking/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type Keeper struct {
Redelegations collections.Map[collections.Triple[[]byte, []byte, []byte], types.Redelegation]
Delegations collections.Map[collections.Pair[sdk.AccAddress, sdk.ValAddress], types.Delegation]
UnbondingIndex collections.Map[uint64, []byte]
UnbondingDelegations collections.Map[collections.Pair[[]byte, []byte], types.UnbondingDelegation]
RedelegationsByValDst collections.Map[collections.Triple[[]byte, []byte, []byte], []byte]
RedelegationsByValSrc collections.Map[collections.Triple[[]byte, []byte, []byte], []byte]
}
Expand Down Expand Up @@ -145,6 +146,14 @@ func NewKeeper(
),
collections.BytesValue,
),
UnbondingDelegations: collections.NewMap(
sb, types.UnbondingDelegationKey,
"unbonding_delegation",
collections.PairKeyCodec(
collections.BytesKey,
sdk.LengthPrefixedBytesKey, // sdk.LengthPrefixedBytesKey is needed to retain state compatibility
),
codec.CollValue[types.UnbondingDelegation](cdc)),
}

schema, err := sb.Build()
Expand Down
Loading

0 comments on commit a734071

Please sign in to comment.