refactor(x/staking): migrate RedelegationByValDstIndexKey key to collections (#17336)

This commit is contained in:
atheeshp 2023-08-23 10:27:47 +05:30 committed by GitHub
parent 952328a4ed
commit 76a72ceb9d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 111 additions and 93 deletions

View File

@ -522,14 +522,17 @@ func (k Keeper) GetRedelegationsFromSrcValidator(ctx context.Context, valAddr sd
// HasReceivingRedelegation checks if validator is receiving a redelegation.
func (k Keeper) HasReceivingRedelegation(ctx context.Context, delAddr sdk.AccAddress, valDstAddr sdk.ValAddress) (bool, error) {
store := k.storeService.OpenKVStore(ctx)
prefix := types.GetREDsByDelToValDstIndexKey(delAddr, valDstAddr)
iterator, err := store.Iterator(prefix, storetypes.PrefixEndBytes(prefix))
rng := collections.NewSuperPrefixedTripleRange[[]byte, []byte, []byte](valDstAddr, delAddr)
hasAtleastOneEntry := false
err := k.RedelegationsByValDst.Walk(ctx, rng, func(key collections.Triple[[]byte, []byte, []byte], value []byte) (stop bool, err error) {
hasAtleastOneEntry = true
return true, nil // returning true here to stop the iterations after 1st finding
})
if err != nil {
return false, err
}
defer iterator.Close()
return iterator.Valid(), nil
return hasAtleastOneEntry, nil
}
// HasMaxRedelegationEntries checks if the redelegation entries reached maximum limit.
@ -557,7 +560,6 @@ func (k Keeper) SetRedelegation(ctx context.Context, red types.Redelegation) err
return err
}
store := k.storeService.OpenKVStore(ctx)
valSrcAddr, err := k.validatorAddressCodec.StringToBytes(red.ValidatorSrcAddress)
if err != nil {
return err
@ -575,7 +577,7 @@ func (k Keeper) SetRedelegation(ctx context.Context, red types.Redelegation) err
return err
}
return store.Set(types.GetREDByValDstIndexKey(delegatorAddress, valSrcAddr, valDestAddr), []byte{})
return k.RedelegationsByValDst.Set(ctx, collections.Join3(valDestAddr, delegatorAddress, valSrcAddr), []byte{})
}
// SetRedelegationEntry adds an entry to the unbonding delegation at the given
@ -645,7 +647,6 @@ func (k Keeper) RemoveRedelegation(ctx context.Context, red types.Redelegation)
return err
}
store := k.storeService.OpenKVStore(ctx)
valSrcAddr, err := k.validatorAddressCodec.StringToBytes(red.ValidatorSrcAddress)
if err != nil {
return err
@ -663,7 +664,7 @@ func (k Keeper) RemoveRedelegation(ctx context.Context, red types.Redelegation)
return err
}
return store.Delete(types.GetREDByValDstIndexKey(delegatorAddress, valSrcAddr, valDestAddr))
return k.RedelegationsByValDst.Remove(ctx, collections.Join3(valDestAddr, delegatorAddress, valSrcAddr))
}
// redelegation queue timeslice operations

View File

@ -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]
RedelegationsByValDst collections.Map[collections.Triple[[]byte, []byte, []byte], []byte]
RedelegationsByValSrc collections.Map[collections.Triple[[]byte, []byte, []byte], []byte]
}
@ -110,6 +111,7 @@ func NewKeeper(
collcodec.KeyToValueCodec(sdk.ValAddressKey),
),
UnbondingType: collections.NewMap(sb, types.UnbondingTypeKey, "unbonding_type", collections.Uint64Key, collections.Uint64Value),
// key format is: 52 | lengthPrefixedBytes(AccAddr) | lengthPrefixedBytes(SrcValAddr) | lengthPrefixedBytes(DstValAddr)
Redelegations: collections.NewMap(
sb, types.RedelegationKey,
"redelegations",
@ -121,7 +123,7 @@ func NewKeeper(
codec.CollValue[types.Redelegation](cdc),
),
UnbondingIndex: collections.NewMap(sb, types.UnbondingIndexKey, "unbonding_index", collections.Uint64Key, collections.BytesValue),
// key format is: 53 | lengthPrefixedBytes(DstValAddr) | lengthPrefixedBytes(AccAddr) | lengthPrefixedBytes(SrcValAddr)
// key format is: 53 | lengthPrefixedBytes(SrcValAddr) | lengthPrefixedBytes(AccAddr) | lengthPrefixedBytes(DstValAddr)
RedelegationsByValSrc: collections.NewMap(
sb, types.RedelegationByValSrcIndexKey,
"redelegations_by_val_src",
@ -132,6 +134,17 @@ func NewKeeper(
),
collections.BytesValue,
),
// key format is: 54 | lengthPrefixedBytes(DstValAddr) | lengthPrefixedBytes(AccAddr) | lengthPrefixedBytes(SrcValAddr)
RedelegationsByValDst: collections.NewMap(
sb, types.RedelegationByValDstIndexKey,
"redelegations_by_val_dst",
collections.TripleKeyCodec(
collections.BytesKey,
collections.BytesKey,
sdk.LengthPrefixedBytesKey, // sdk.LengthPrefixedBytesKey is needed to retain state compatibility
),
collections.BytesValue,
),
}
schema, err := sb.Build()

View File

@ -113,6 +113,23 @@ func (s *KeeperTestSuite) TestLastTotalPower() {
require.True(expTotalPower.Equal(resTotalPower))
}
// getREDByValDstIndexKey creates the index-key for a redelegation, stored by destination-validator-index
// VALUE: none (key rearrangement used)
func getREDByValDstIndexKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte {
REDSToValsDstKey := getREDsToValDstIndexKey(valDstAddr)
offset := len(REDSToValsDstKey)
// key is of the form REDSToValsDstKey || delAddrLen (1 byte) || delAddr || valSrcAddrLen (1 byte) || valSrcAddr
key := make([]byte, offset+2+len(delAddr)+len(valSrcAddr))
copy(key[0:offset], REDSToValsDstKey)
key[offset] = byte(len(delAddr))
copy(key[offset+1:offset+1+len(delAddr)], delAddr.Bytes())
key[offset+1+len(delAddr)] = byte(len(valSrcAddr))
copy(key[offset+2+len(delAddr):], valSrcAddr.Bytes())
return key
}
// GetREDByValSrcIndexKey creates the index-key for a redelegation, stored by source-validator-index
// VALUE: none (key rearrangement used)
func getREDByValSrcIndexKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte {
@ -130,6 +147,13 @@ func getREDByValSrcIndexKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.V
return key
}
// GetREDsToValDstIndexKey returns a key prefix for indexing a redelegation to a
// destination (target) validator.
func getREDsToValDstIndexKey(valDstAddr sdk.ValAddress) []byte {
redelegationByValDstIndexKey := []byte{0x36}
return append(redelegationByValDstIndexKey, addresstypes.MustLengthPrefix(valDstAddr)...)
}
// GetREDsFromValSrcIndexKey returns a key prefix for indexing a redelegation to
// a source validator.
func getREDsFromValSrcIndexKey(valSrcAddr sdk.ValAddress) []byte {
@ -137,7 +161,7 @@ func getREDsFromValSrcIndexKey(valSrcAddr sdk.ValAddress) []byte {
return append(redelegationByValSrcIndexKey, addresstypes.MustLengthPrefix(valSrcAddr)...)
}
func (s *KeeperTestSuite) TestRedelegationsMigrationToColls() {
func (s *KeeperTestSuite) TestSrcRedelegationsMigrationToColls() {
s.SetupTest()
addrs, valAddrs := createValAddrs(101)
@ -169,6 +193,38 @@ func (s *KeeperTestSuite) TestRedelegationsMigrationToColls() {
s.Require().NoError(err)
}
func (s *KeeperTestSuite) TestDstRedelegationsMigrationToColls() {
s.SetupTest()
addrs, valAddrs := createValAddrs(101)
err := testutil.DiffCollectionsMigration(
s.ctx,
s.key,
100,
func(i int64) {
// legacy method to set in the state
s.ctx.KVStore(s.key).Set(getREDByValDstIndexKey(addrs[i], valAddrs[i], valAddrs[i+1]), []byte{})
},
"4beb77994beff3c8ad9cecca9ee3a74fb551356250f0b8bd3936c4e4f506443b", // this hash obtained when ran this test in main branch
)
s.Require().NoError(err)
err = testutil.DiffCollectionsMigration(
s.ctx,
s.key,
100,
func(i int64) {
// using collections
err := s.stakingKeeper.RedelegationsByValDst.Set(s.ctx, collections.Join3(valAddrs[i+1].Bytes(), addrs[i].Bytes(), valAddrs[i].Bytes()), []byte{})
s.Require().NoError(err)
},
"4beb77994beff3c8ad9cecca9ee3a74fb551356250f0b8bd3936c4e4f506443b",
)
s.Require().NoError(err)
}
func TestKeeperTestSuite(t *testing.T) {
suite.Run(t, new(KeeperTestSuite))
}

View File

@ -13,11 +13,14 @@ const (
)
var (
ValidatorsByConsAddrKey = []byte{0x22} // prefix for validators by consensus address
ValidatorsByConsAddrKey = []byte{0x22} // prefix for validators by consensus address
DelegationKey = []byte{0x31} // prefix for the delegation
RedelegationKey = []byte{0x34} // key for a redelegation
RedelegationByValDstIndexKey = []byte{0x36} // prefix for each key for an redelegation, by destination validator operator
RedelegationByValSrcIndexKey = []byte{0x35} // prefix for each key for an redelegation, by source validator operator
HistoricalInfoKey = []byte{0x50} // prefix for the historical info
HistoricalInfoKey = []byte{0x50} // prefix for the historical info
)
// GetHistoricalInfoKey returns a key prefix for indexing HistoricalInfo objects.
@ -63,6 +66,23 @@ func GetREDsKey(delAddr sdk.AccAddress) []byte {
return append(RedelegationKey, address.MustLengthPrefix(delAddr)...)
}
// GetREDByValDstIndexKey creates the index-key for a redelegation, stored by destination-validator-index
// VALUE: none (key rearrangement used)
func GetREDByValDstIndexKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte {
REDSToValsDstKey := GetREDsToValDstIndexKey(valDstAddr)
offset := len(REDSToValsDstKey)
// key is of the form REDSToValsDstKey || delAddrLen (1 byte) || delAddr || valSrcAddrLen (1 byte) || valSrcAddr
key := make([]byte, offset+2+len(delAddr)+len(valSrcAddr))
copy(key[0:offset], REDSToValsDstKey)
key[offset] = byte(len(delAddr))
copy(key[offset+1:offset+1+len(delAddr)], delAddr.Bytes())
key[offset+1+len(delAddr)] = byte(len(valSrcAddr))
copy(key[offset+2+len(delAddr):], valSrcAddr.Bytes())
return key
}
// GetREDByValSrcIndexKey creates the index-key for a redelegation, stored by source-validator-index
// VALUE: none (key rearrangement used)
func GetREDByValSrcIndexKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte {
@ -80,6 +100,12 @@ func GetREDByValSrcIndexKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.V
return key
}
// GetREDsToValDstIndexKey returns a key prefix for indexing a redelegation to a
// destination (target) validator.
func GetREDsToValDstIndexKey(valDstAddr sdk.ValAddress) []byte {
return append(RedelegationByValDstIndexKey, address.MustLengthPrefix(valDstAddr)...)
}
// GetREDsFromValSrcIndexKey returns a key prefix for indexing a redelegation to
// a source validator.
func GetREDsFromValSrcIndexKey(valSrcAddr sdk.ValAddress) []byte {

View File

@ -95,7 +95,7 @@ func TestStoreMigration(t *testing.T) {
{
"RedelegationByValDstIndexKey",
v1.GetREDByValDstIndexKey(addr4, valAddr1, valAddr2),
types.GetREDByValDstIndexKey(addr4, valAddr1, valAddr2),
v2.GetREDByValDstIndexKey(addr4, valAddr1, valAddr2),
},
{
"UnbondingQueueKey",

View File

@ -44,7 +44,7 @@ var (
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 = []byte{0x36} // prefix for each key for an redelegation, by destination 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
@ -247,41 +247,6 @@ func GetREDKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []
return key
}
// GetREDByValDstIndexKey creates the index-key for a redelegation, stored by destination-validator-index
// VALUE: none (key rearrangement used)
func GetREDByValDstIndexKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte {
REDSToValsDstKey := GetREDsToValDstIndexKey(valDstAddr)
offset := len(REDSToValsDstKey)
// key is of the form REDSToValsDstKey || delAddrLen (1 byte) || delAddr || valSrcAddrLen (1 byte) || valSrcAddr
key := make([]byte, offset+2+len(delAddr)+len(valSrcAddr))
copy(key[0:offset], REDSToValsDstKey)
key[offset] = byte(len(delAddr))
copy(key[offset+1:offset+1+len(delAddr)], delAddr.Bytes())
key[offset+1+len(delAddr)] = byte(len(valSrcAddr))
copy(key[offset+2+len(delAddr):], valSrcAddr.Bytes())
return key
}
// GetREDKeyFromValDstIndexKey rearranges the ValDstIndexKey to get the REDKey
func GetREDKeyFromValDstIndexKey(indexKey []byte) []byte {
// note that first byte is prefix byte, which we remove
kv.AssertKeyAtLeastLength(indexKey, 2)
addrs := indexKey[1:]
valDstAddrLen := addrs[0]
kv.AssertKeyAtLeastLength(addrs, int(valDstAddrLen)+2)
valDstAddr := addrs[1 : valDstAddrLen+1]
delAddrLen := addrs[valDstAddrLen+1]
kv.AssertKeyAtLeastLength(addrs, int(valDstAddrLen)+int(delAddrLen)+3)
delAddr := addrs[valDstAddrLen+2 : valDstAddrLen+2+delAddrLen]
kv.AssertKeyAtLeastLength(addrs, int(valDstAddrLen)+int(delAddrLen)+4)
valSrcAddr := addrs[valDstAddrLen+delAddrLen+3:]
return GetREDKey(delAddr, valSrcAddr, valDstAddr)
}
// GetRedelegationTimeKey returns a key prefix for indexing an unbonding
// redelegation based on a completion time.
func GetRedelegationTimeKey(timestamp time.Time) []byte {
@ -294,15 +259,3 @@ func GetRedelegationTimeKey(timestamp time.Time) []byte {
func GetREDsKey(delAddr sdk.AccAddress) []byte {
return append(RedelegationKey, address.MustLengthPrefix(delAddr)...)
}
// GetREDsToValDstIndexKey returns a key prefix for indexing a redelegation to a
// destination (target) validator.
func GetREDsToValDstIndexKey(valDstAddr sdk.ValAddress) []byte {
return append(RedelegationByValDstIndexKey, address.MustLengthPrefix(valDstAddr)...)
}
// GetREDsByDelToValDstIndexKey returns a key prefix for indexing a redelegation
// from an address to a source validator.
func GetREDsByDelToValDstIndexKey(delAddr sdk.AccAddress, valDstAddr sdk.ValAddress) []byte {
return append(GetREDsToValDstIndexKey(valDstAddr), address.MustLengthPrefix(delAddr)...)
}

View File

@ -19,11 +19,7 @@ import (
var (
keysPK1 = ed25519.GenPrivKeyFromSecret([]byte{1}).PubKey()
keysPK2 = ed25519.GenPrivKeyFromSecret([]byte{2}).PubKey()
keysPK3 = ed25519.GenPrivKeyFromSecret([]byte{3}).PubKey()
keysAddr1 = keysPK1.Address()
keysAddr2 = keysPK2.Address()
keysAddr3 = keysPK3.Address()
)
func TestGetValidatorPowerRank(t *testing.T) {
@ -52,33 +48,6 @@ func TestGetValidatorPowerRank(t *testing.T) {
}
}
func TestGetREDByValDstIndexKey(t *testing.T) {
tests := []struct {
delAddr sdk.AccAddress
valSrcAddr sdk.ValAddress
valDstAddr sdk.ValAddress
wantHex string
}{
{
sdk.AccAddress(keysAddr1), sdk.ValAddress(keysAddr1), sdk.ValAddress(keysAddr1),
"361463d771218209d8bd03c482f69dfba57310f086091463d771218209d8bd03c482f69dfba57310f086091463d771218209d8bd03c482f69dfba57310f08609",
},
{
sdk.AccAddress(keysAddr1), sdk.ValAddress(keysAddr2), sdk.ValAddress(keysAddr3),
"36143ab62f0d93849be495e21e3e9013a517038f45bd1463d771218209d8bd03c482f69dfba57310f08609145ef3b5f25c54946d4a89fc0d09d2f126614540f2",
},
{
sdk.AccAddress(keysAddr2), sdk.ValAddress(keysAddr1), sdk.ValAddress(keysAddr3),
"36143ab62f0d93849be495e21e3e9013a517038f45bd145ef3b5f25c54946d4a89fc0d09d2f126614540f21463d771218209d8bd03c482f69dfba57310f08609",
},
}
for i, tt := range tests {
got := hex.EncodeToString(types.GetREDByValDstIndexKey(tt.delAddr, tt.valSrcAddr, tt.valDstAddr))
require.Equal(t, tt.wantHex, got, "Keys did not match on test case %d", i)
}
}
func TestGetValidatorQueueKey(t *testing.T) {
ts := time.Now()
height := int64(1024)