refactor(x/staking): Migrate UnbondingDelegationByValIndex to use collections (#17291)

Co-authored-by: Facundo Medica <14063057+facundomedica@users.noreply.github.com>
This commit is contained in:
Likhita Polavarapu 2023-08-30 14:51:10 +05:30 committed by GitHub
parent a24d7071c1
commit 3ed40a925c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 88 additions and 82 deletions

View File

@ -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`:

View File

@ -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
}
@ -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
@ -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
@ -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

View File

@ -172,7 +172,6 @@ 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 {
@ -180,21 +179,32 @@ func (k Querier) ValidatorUnbondingDelegations(ctx context.Context, req *types.Q
}
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{

View File

@ -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
@ -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(

View File

@ -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)
@ -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",
)

View File

@ -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"
@ -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()
@ -81,7 +81,7 @@ func TestStoreMigration(t *testing.T) {
{
"UnbondingDelegationByValIndexKey",
v1.GetUBDByValIndexKey(addr4, valAddr1),
types.GetUBDByValIndexKey(addr4, valAddr1),
getUBDByValIndexKey(addr4, valAddr1),
},
{
"RedelegationKey",
@ -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...)

View File

@ -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
@ -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 {