Skip to content

Commit

Permalink
refactor(x/staking): Migrate UnbondingDelegationByValIndex to use col…
Browse files Browse the repository at this point in the history
…lections (#17291)

Co-authored-by: Facundo Medica <[email protected]>
  • Loading branch information
likhita-809 and facundomedica authored Aug 30, 2023
1 parent a24d707 commit 3ed40a9
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 82 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ Ref: https://keepachangelog.com/en/1.0.0/

### API Breaking Changes

* (x/staking) [#17291](https://github.com/cosmos/cosmos-sdk/pull/17291) Use collections for `UnbondingDelegationByValIndex`:
* remove from `types`: `GetUBDKeyFromValIndexKey`, `GetUBDsByValIndexKey`, `GetUBDByValIndexKey`
* (x/slashing) [#17568](https://github.com/cosmos/cosmos-sdk/pull/17568) Use collections for `ValidatorMissedBlockBitmap`:
* remove from `types`: `ValidatorMissedBlockBitmapPrefixKey`, `ValidatorMissedBlockBitmapKey`
* (x/staking) [#17481](https://github.com/cosmos/cosmos-sdk/pull/17481) Use collections for `UnbondingQueue`:
Expand Down
44 changes: 22 additions & 22 deletions x/staking/keeper/delegation.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,26 +167,29 @@ func (k Keeper) GetUnbondingDelegation(ctx context.Context, delAddr sdk.AccAddre
// particular validator.
func (k Keeper) GetUnbondingDelegationsFromValidator(ctx context.Context, valAddr sdk.ValAddress) (ubds []types.UnbondingDelegation, err error) {
store := k.storeService.OpenKVStore(ctx)
prefix := types.GetUBDsByValIndexKey(valAddr)
iterator, err := store.Iterator(prefix, storetypes.PrefixEndBytes(prefix))
rng := collections.NewPrefixedPairRange[[]byte, []byte](valAddr)
err = k.UnbondingDelegationByValIndex.Walk(
ctx,
rng,
func(key collections.Pair[[]byte, []byte], value []byte) (stop bool, err error) {
valAddr := key.K1()
delAddr := key.K2()
ubdkey := types.GetUBDKey(delAddr, valAddr)
ubdValue, err := store.Get(ubdkey)
if err != nil {
return true, err
}
unbondingDelegation, err := types.UnmarshalUBD(k.cdc, ubdValue)
if err != nil {
return true, err
}
ubds = append(ubds, unbondingDelegation)
return false, nil
},
)
if err != nil {
return ubds, err
}
defer iterator.Close()

for ; iterator.Valid(); iterator.Next() {
key := types.GetUBDKeyFromValIndexKey(iterator.Key())
value, err := store.Get(key)
if err != nil {
return ubds, err
}
ubd, err := types.UnmarshalUBD(k.cdc, value)
if err != nil {
return ubds, err
}
ubds = append(ubds, ubd)
}

return ubds, nil
}

Expand Down Expand Up @@ -263,8 +266,6 @@ 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
Expand All @@ -278,12 +279,11 @@ func (k Keeper) SetUnbondingDelegation(ctx context.Context, ubd types.UnbondingD
return err
}

return store.Set(types.GetUBDByValIndexKey(delAddr, valAddr), []byte{}) // index, store empty bytes
return k.UnbondingDelegationByValIndex.Set(ctx, collections.Join(valAddr, delAddr), []byte{})
}

// RemoveUnbondingDelegation removes the unbonding delegation object and associated index.
func (k Keeper) RemoveUnbondingDelegation(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
Expand All @@ -297,7 +297,7 @@ func (k Keeper) RemoveUnbondingDelegation(ctx context.Context, ubd types.Unbondi
return err
}

return store.Delete(types.GetUBDByValIndexKey(delAddr, valAddr))
return k.UnbondingDelegationByValIndex.Remove(ctx, collections.Join(valAddr, delAddr))
}

// SetUnbondingDelegationEntry adds an entry to the unbonding delegation at
Expand Down
32 changes: 21 additions & 11 deletions x/staking/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,29 +172,39 @@ func (k Querier) ValidatorUnbondingDelegations(ctx context.Context, req *types.Q
if req.ValidatorAddr == "" {
return nil, status.Error(codes.InvalidArgument, "validator address cannot be empty")
}
var ubds types.UnbondingDelegations

valAddr, err := k.validatorAddressCodec.StringToBytes(req.ValidatorAddr)
if err != nil {
return nil, err
}

store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
srcValPrefix := types.GetUBDsByValIndexKey(valAddr)
ubdStore := prefix.NewStore(store, srcValPrefix)
pageRes, err := query.Paginate(ubdStore, req.Pagination, func(key, value []byte) error {
storeKey := types.GetUBDKeyFromValIndexKey(append(srcValPrefix, key...))
storeValue := store.Get(storeKey)
keys, pageRes, err := query.CollectionPaginate(
ctx,
k.UnbondingDelegationByValIndex,
req.Pagination,
func(key collections.Pair[[]byte, []byte], value []byte) (collections.Pair[[]byte, []byte], error) {
return key, nil
},
query.WithCollectionPaginationPairPrefix[[]byte, []byte](valAddr),
)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}

// loop over the collected keys and fetch unbonding delegations
var ubds []types.UnbondingDelegation
for _, key := range keys {
valAddr := key.K1()
delAddr := key.K2()
ubdKey := types.GetUBDKey(delAddr, valAddr)
storeValue := store.Get(ubdKey)

ubd, err := types.UnmarshalUBD(k.cdc, storeValue)
if err != nil {
return err
return nil, err
}
ubds = append(ubds, ubd)
return nil
})
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}

return &types.QueryValidatorUnbondingDelegationsResponse{
Expand Down
39 changes: 23 additions & 16 deletions x/staking/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,23 @@ type Keeper struct {
validatorAddressCodec addresscodec.Codec
consensusAddressCodec addresscodec.Codec

Schema collections.Schema
HistoricalInfo collections.Map[uint64, types.HistoricalInfo]
LastTotalPower collections.Item[math.Int]
ValidatorUpdates collections.Item[types.ValidatorUpdates]
DelegationsByValidator collections.Map[collections.Pair[sdk.ValAddress, sdk.AccAddress], []byte]
UnbondingID collections.Sequence
ValidatorByConsensusAddress collections.Map[sdk.ConsAddress, sdk.ValAddress]
UnbondingType collections.Map[uint64, uint64]
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]
UnbondingQueue collections.Map[time.Time, types.DVPairs]
Validators collections.Map[[]byte, types.Validator]
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]
Schema collections.Schema
HistoricalInfo collections.Map[uint64, types.HistoricalInfo]
LastTotalPower collections.Item[math.Int]
ValidatorUpdates collections.Item[types.ValidatorUpdates]
DelegationsByValidator collections.Map[collections.Pair[sdk.ValAddress, sdk.AccAddress], []byte]
UnbondingID collections.Sequence
ValidatorByConsensusAddress collections.Map[sdk.ConsAddress, sdk.ValAddress]
UnbondingType collections.Map[uint64, uint64]
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]
UnbondingQueue collections.Map[time.Time, types.DVPairs]
Validators collections.Map[[]byte, types.Validator]
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]
UnbondingDelegationByValIndex collections.Map[collections.Pair[[]byte, []byte], []byte]
}

// NewKeeper creates a new staking Keeper instance
Expand Down Expand Up @@ -127,6 +128,12 @@ func NewKeeper(
codec.CollValue[types.Redelegation](cdc),
),
UnbondingIndex: collections.NewMap(sb, types.UnbondingIndexKey, "unbonding_index", collections.Uint64Key, collections.BytesValue),
UnbondingDelegationByValIndex: collections.NewMap(
sb, types.UnbondingDelegationByValIndexKey,
"unbonding_delegation_by_val_index",
collections.PairKeyCodec(sdk.LengthPrefixedBytesKey, sdk.LengthPrefixedBytesKey), // sdk.LengthPrefixedBytesKey is needed to retain state compatibility
collections.BytesValue,
),
UnbondingQueue: collections.NewMap(sb, types.UnbondingQueueKey, "unbonidng_queue", sdk.TimeKey, codec.CollValue[types.DVPairs](cdc)),
// key format is: 53 | lengthPrefixedBytes(SrcValAddr) | lengthPrefixedBytes(AccAddr) | lengthPrefixedBytes(DstValAddr)
RedelegationsByValSrc: collections.NewMap(
Expand Down
9 changes: 8 additions & 1 deletion x/staking/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,13 @@ func getUBDKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte {
return append(append(unbondingDelegationKey, addresstypes.MustLengthPrefix(delAddr)...), addresstypes.MustLengthPrefix(valAddr)...)
}

// getUBDByValIndexKey creates the index-key for an unbonding delegation, stored by validator-index
// VALUE: none (key rearrangement used)
func getUBDByValIndexKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte {
unbondingDelegationByValIndexKey := []byte{0x33}
return append(append(unbondingDelegationByValIndexKey, addresstypes.MustLengthPrefix(valAddr)...), addresstypes.MustLengthPrefix(delAddr)...)
}

// getUnbondingDelegationTimeKey creates the prefix for all unbonding delegations from a delegator
func getUnbondingDelegationTimeKey(timestamp time.Time) []byte {
bz := sdk.FormatTimeBytes(timestamp)
Expand Down Expand Up @@ -275,7 +282,7 @@ func (s *KeeperTestSuite) TestUnbondingDelegationsMigrationToColls() {
}
bz := stakingtypes.MustMarshalUBD(s.cdc, ubd)
s.ctx.KVStore(s.key).Set(getUBDKey(delAddrs[i], valAddrs[i]), bz)
s.ctx.KVStore(s.key).Set(stakingtypes.GetUBDByValIndexKey(delAddrs[i], valAddrs[i]), []byte{})
s.ctx.KVStore(s.key).Set(getUBDByValIndexKey(delAddrs[i], valAddrs[i]), []byte{})
},
"d03ca412f3f6849b5148a2ca49ac2555f65f90b7fab6a289575ed337f15c0f4b",
)
Expand Down
10 changes: 7 additions & 3 deletions x/staking/migrations/v2/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
storetypes "cosmossdk.io/store/types"

"github.com/cosmos/cosmos-sdk/codec/address"
sdktestuil "github.com/cosmos/cosmos-sdk/testutil"
sdktestutil "github.com/cosmos/cosmos-sdk/testutil"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkaddress "github.com/cosmos/cosmos-sdk/types/address"
Expand All @@ -23,7 +23,7 @@ import (
func TestStoreMigration(t *testing.T) {
stakingKey := storetypes.NewKVStoreKey("staking")
tStakingKey := storetypes.NewTransientStoreKey("transient_test")
ctx := sdktestuil.DefaultContext(stakingKey, tStakingKey)
ctx := sdktestutil.DefaultContext(stakingKey, tStakingKey)
store := ctx.KVStore(stakingKey)

_, pk1, addr1 := testdata.KeyTestPubAddr()
Expand Down Expand Up @@ -81,7 +81,7 @@ func TestStoreMigration(t *testing.T) {
{
"UnbondingDelegationByValIndexKey",
v1.GetUBDByValIndexKey(addr4, valAddr1),
types.GetUBDByValIndexKey(addr4, valAddr1),
getUBDByValIndexKey(addr4, valAddr1),
},
{
"RedelegationKey",
Expand Down Expand Up @@ -141,6 +141,10 @@ func TestStoreMigration(t *testing.T) {
}
}

func getUBDByValIndexKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte {
return append(append(types.UnbondingDelegationByValIndexKey, sdkaddress.MustLengthPrefix(valAddr)...), sdkaddress.MustLengthPrefix(delAddr)...)
}

func getUnbondingDelegationTimeKey(timestamp time.Time) []byte {
bz := sdk.FormatTimeBytes(timestamp)
return append(types.UnbondingQueueKey, bz...)
Expand Down
34 changes: 5 additions & 29 deletions x/staking/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@ var (

DelegationKey = collections.NewPrefix(49) // key for a delegation
UnbondingDelegationKey = collections.NewPrefix(50) // key for an unbonding-delegation
UnbondingDelegationByValIndexKey = []byte{0x33} // prefix for each key for an unbonding-delegation, by validator operator
RedelegationKey = collections.NewPrefix(52) // key for a redelegation
RedelegationByValSrcIndexKey = collections.NewPrefix(53) // prefix for each key for an redelegation, by source validator operator
RedelegationByValDstIndexKey = collections.NewPrefix(54) // prefix for each key for an redelegation, by destination validator operator
UnbondingDelegationByValIndexKey = collections.NewPrefix(51) // prefix for each key for an unbonding-delegation, by validator operator

RedelegationKey = collections.NewPrefix(52) // key for a redelegation
RedelegationByValSrcIndexKey = collections.NewPrefix(53) // prefix for each key for an redelegation, by source validator operator
RedelegationByValDstIndexKey = collections.NewPrefix(54) // prefix for each key for an redelegation, by destination validator operator

UnbondingIDKey = collections.NewPrefix(55) // key for the counter for the incrementing id for UnbondingOperations
UnbondingIndexKey = collections.NewPrefix(56) // prefix for an index for looking up unbonding operations by their IDs
Expand Down Expand Up @@ -196,31 +197,6 @@ func GetUBDKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte {
return append(append(UnbondingDelegationKey, address.MustLengthPrefix(delAddr)...), address.MustLengthPrefix(valAddr)...)
}

// GetUBDByValIndexKey creates the index-key for an unbonding delegation, stored by validator-index
// VALUE: none (key rearrangement used)
func GetUBDByValIndexKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte {
return append(GetUBDsByValIndexKey(valAddr), address.MustLengthPrefix(delAddr)...)
}

// GetUBDKeyFromValIndexKey rearranges the ValIndexKey to get the UBDKey
func GetUBDKeyFromValIndexKey(indexKey []byte) []byte {
kv.AssertKeyAtLeastLength(indexKey, 2)
addrs := indexKey[1:] // remove prefix bytes

valAddrLen := addrs[0]
kv.AssertKeyAtLeastLength(addrs, 2+int(valAddrLen))
valAddr := addrs[1 : 1+valAddrLen]
kv.AssertKeyAtLeastLength(addrs, 3+int(valAddrLen))
delAddr := addrs[valAddrLen+2:]

return append(append(UnbondingDelegationKey, address.MustLengthPrefix(delAddr)...), address.MustLengthPrefix(valAddr)...)
}

// GetUBDsByValIndexKey creates the prefix keyspace for the indexes of unbonding delegations for a validator
func GetUBDsByValIndexKey(valAddr sdk.ValAddress) []byte {
return append(UnbondingDelegationByValIndexKey, address.MustLengthPrefix(valAddr)...)
}

// GetREDKey returns a key prefix for indexing a redelegation from a delegator
// and source validator to a destination validator.
func GetREDKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte {
Expand Down

0 comments on commit 3ed40a9

Please sign in to comment.