refactor(x/staking): migrate UnbondingQueue to collections (#17481)
This commit is contained in:
@@ -56,6 +56,9 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
### API Breaking Changes
|
||||
|
||||
* (x/staking) [#17481](https://github.com/cosmos/cosmos-sdk/pull/17481) Use collections for `UnbondingQueue`:
|
||||
* remove from `Keeper`: `UBDQueueIterator`
|
||||
* remove from `types`: `GetUnbondingDelegationTimeKey`
|
||||
* (x/staking) [#17123](https://github.com/cosmos/cosmos-sdk/pull/17123) Use collections for `Validators`
|
||||
* (x/staking) [#17270](https://github.com/cosmos/cosmos-sdk/pull/17270) Use collections for `UnbondingDelegation`:
|
||||
* remove from `types`: `GetUBDsKey`
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/collections"
|
||||
corestore "cosmossdk.io/core/store"
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"cosmossdk.io/math"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
@@ -347,27 +346,21 @@ func (k Keeper) SetUnbondingDelegationEntry(
|
||||
// is a slice of DVPairs corresponding to unbonding delegations that expire at a
|
||||
// certain time.
|
||||
func (k Keeper) GetUBDQueueTimeSlice(ctx context.Context, timestamp time.Time) (dvPairs []types.DVPair, err error) {
|
||||
store := k.storeService.OpenKVStore(ctx)
|
||||
|
||||
bz, err := store.Get(types.GetUnbondingDelegationTimeKey(timestamp))
|
||||
if bz == nil || err != nil {
|
||||
return []types.DVPair{}, err
|
||||
pairs, err := k.UnbondingQueue.Get(ctx, timestamp)
|
||||
if err != nil {
|
||||
if !errors.Is(err, collections.ErrNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
return []types.DVPair{}, nil
|
||||
}
|
||||
|
||||
pairs := types.DVPairs{}
|
||||
err = k.cdc.Unmarshal(bz, &pairs)
|
||||
|
||||
return pairs.Pairs, err
|
||||
}
|
||||
|
||||
// SetUBDQueueTimeSlice sets a specific unbonding queue timeslice.
|
||||
func (k Keeper) SetUBDQueueTimeSlice(ctx context.Context, timestamp time.Time, keys []types.DVPair) error {
|
||||
store := k.storeService.OpenKVStore(ctx)
|
||||
bz, err := k.cdc.Marshal(&types.DVPairs{Pairs: keys})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return store.Set(types.GetUnbondingDelegationTimeKey(timestamp), bz)
|
||||
dvPairs := types.DVPairs{Pairs: keys}
|
||||
return k.UnbondingQueue.Set(ctx, timestamp, dvPairs)
|
||||
}
|
||||
|
||||
// InsertUBDQueue inserts an unbonding delegation to the appropriate timeslice
|
||||
@@ -379,9 +372,8 @@ func (k Keeper) InsertUBDQueue(ctx context.Context, ubd types.UnbondingDelegatio
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(timeSlice) == 0 {
|
||||
if err = k.SetUBDQueueTimeSlice(ctx, completionTime, []types.DVPair{dvPair}); err != nil {
|
||||
if err := k.SetUBDQueueTimeSlice(ctx, completionTime, []types.DVPair{dvPair}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -391,38 +383,30 @@ func (k Keeper) InsertUBDQueue(ctx context.Context, ubd types.UnbondingDelegatio
|
||||
return k.SetUBDQueueTimeSlice(ctx, completionTime, timeSlice)
|
||||
}
|
||||
|
||||
// UBDQueueIterator returns all the unbonding queue timeslices from time 0 until endTime.
|
||||
func (k Keeper) UBDQueueIterator(ctx context.Context, endTime time.Time) (corestore.Iterator, error) {
|
||||
store := k.storeService.OpenKVStore(ctx)
|
||||
return store.Iterator(types.UnbondingQueueKey,
|
||||
storetypes.InclusiveEndBytes(types.GetUnbondingDelegationTimeKey(endTime)))
|
||||
}
|
||||
|
||||
// DequeueAllMatureUBDQueue returns a concatenated list of all the timeslices inclusively previous to
|
||||
// currTime, and deletes the timeslices from the queue.
|
||||
func (k Keeper) DequeueAllMatureUBDQueue(ctx context.Context, currTime time.Time) (matureUnbonds []types.DVPair, err error) {
|
||||
store := k.storeService.OpenKVStore(ctx)
|
||||
|
||||
// gets an iterator for all timeslices from time 0 until the current Blockheader time
|
||||
unbondingTimesliceIterator, err := k.UBDQueueIterator(ctx, currTime)
|
||||
// get an iterator for all timeslices from time 0 until the current Blockheader time
|
||||
iter, err := k.UnbondingQueue.Iterate(ctx, (&collections.Range[time.Time]{}).EndInclusive(currTime))
|
||||
if err != nil {
|
||||
return matureUnbonds, err
|
||||
}
|
||||
defer unbondingTimesliceIterator.Close()
|
||||
defer iter.Close()
|
||||
|
||||
for ; unbondingTimesliceIterator.Valid(); unbondingTimesliceIterator.Next() {
|
||||
timeslice := types.DVPairs{}
|
||||
value := unbondingTimesliceIterator.Value()
|
||||
if err = k.cdc.Unmarshal(value, ×lice); err != nil {
|
||||
for ; iter.Valid(); iter.Next() {
|
||||
timeslice, err := iter.Value()
|
||||
if err != nil {
|
||||
return matureUnbonds, err
|
||||
}
|
||||
|
||||
matureUnbonds = append(matureUnbonds, timeslice.Pairs...)
|
||||
|
||||
if err = store.Delete(unbondingTimesliceIterator.Key()); err != nil {
|
||||
key, err := iter.Key()
|
||||
if err != nil {
|
||||
return matureUnbonds, err
|
||||
}
|
||||
if err = k.UnbondingQueue.Remove(ctx, key); err != nil {
|
||||
return matureUnbonds, err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return matureUnbonds, nil
|
||||
|
||||
@@ -3,6 +3,7 @@ package keeper
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/collections"
|
||||
collcodec "cosmossdk.io/collections/codec"
|
||||
@@ -44,6 +45,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]
|
||||
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]
|
||||
@@ -125,6 +127,7 @@ func NewKeeper(
|
||||
codec.CollValue[types.Redelegation](cdc),
|
||||
),
|
||||
UnbondingIndex: collections.NewMap(sb, types.UnbondingIndexKey, "unbonding_index", collections.Uint64Key, 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(
|
||||
sb, types.RedelegationByValSrcIndexKey,
|
||||
|
||||
@@ -174,6 +174,13 @@ func getUBDKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte {
|
||||
return append(append(unbondingDelegationKey, addresstypes.MustLengthPrefix(delAddr)...), addresstypes.MustLengthPrefix(valAddr)...)
|
||||
}
|
||||
|
||||
// getUnbondingDelegationTimeKey creates the prefix for all unbonding delegations from a delegator
|
||||
func getUnbondingDelegationTimeKey(timestamp time.Time) []byte {
|
||||
bz := sdk.FormatTimeBytes(timestamp)
|
||||
unbondingQueueKey := []byte{0x41}
|
||||
return append(unbondingQueueKey, bz...)
|
||||
}
|
||||
|
||||
// getValidatorKey creates the key for the validator with address
|
||||
// VALUE: staking/Validator
|
||||
func getValidatorKey(operatorAddr sdk.ValAddress) []byte {
|
||||
@@ -299,8 +306,34 @@ func (s *KeeperTestSuite) TestUnbondingDelegationsMigrationToColls() {
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
func TestKeeperTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(KeeperTestSuite))
|
||||
func (s *KeeperTestSuite) TestUBDQueueMigrationToColls() {
|
||||
s.SetupTest()
|
||||
|
||||
err := testutil.DiffCollectionsMigration(
|
||||
s.ctx,
|
||||
s.key,
|
||||
100,
|
||||
func(i int64) {
|
||||
date := time.Date(2023, 8, 21, 14, 33, 1, 0, &time.Location{})
|
||||
// legacy Set method
|
||||
s.ctx.KVStore(s.key).Set(getUnbondingDelegationTimeKey(date), []byte{})
|
||||
},
|
||||
"7b8965aacc97646d6766a5a53bae397fe149d1c98fed027bea8774a18621ce6a",
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
err = testutil.DiffCollectionsMigration(
|
||||
s.ctx,
|
||||
s.key,
|
||||
100,
|
||||
func(i int64) {
|
||||
date := time.Date(2023, 8, 21, 14, 33, 1, 0, &time.Location{})
|
||||
err := s.stakingKeeper.SetUBDQueueTimeSlice(s.ctx, date, nil)
|
||||
s.Require().NoError(err)
|
||||
},
|
||||
"7b8965aacc97646d6766a5a53bae397fe149d1c98fed027bea8774a18621ce6a",
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
func (s *KeeperTestSuite) TestValidatorsMigrationToColls() {
|
||||
@@ -362,3 +395,7 @@ func (s *KeeperTestSuite) TestValidatorsMigrationToColls() {
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
func TestKeeperTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(KeeperTestSuite))
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ func TestStoreMigration(t *testing.T) {
|
||||
{
|
||||
"UnbondingQueueKey",
|
||||
v1.GetUnbondingDelegationTimeKey(now),
|
||||
types.GetUnbondingDelegationTimeKey(now),
|
||||
getUnbondingDelegationTimeKey(now),
|
||||
},
|
||||
{
|
||||
"RedelegationQueueKey",
|
||||
@@ -141,6 +141,11 @@ func TestStoreMigration(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func getUnbondingDelegationTimeKey(timestamp time.Time) []byte {
|
||||
bz := sdk.FormatTimeBytes(timestamp)
|
||||
return append(types.UnbondingQueueKey, bz...)
|
||||
}
|
||||
|
||||
func getValidatorKey(operatorAddr sdk.ValAddress) []byte {
|
||||
return append(types.ValidatorsKey, sdkaddress.MustLengthPrefix(operatorAddr)...)
|
||||
}
|
||||
|
||||
@@ -50,9 +50,9 @@ var (
|
||||
UnbondingIndexKey = collections.NewPrefix(56) // prefix for an index for looking up unbonding operations by their IDs
|
||||
UnbondingTypeKey = collections.NewPrefix(57) // prefix for an index containing the type of unbonding operations
|
||||
|
||||
UnbondingQueueKey = []byte{0x41} // prefix for the timestamps in unbonding queue
|
||||
RedelegationQueueKey = []byte{0x42} // prefix for the timestamps in redelegations queue
|
||||
ValidatorQueueKey = []byte{0x43} // prefix for the timestamps in validator queue
|
||||
UnbondingQueueKey = collections.NewPrefix(65) // prefix for the timestamps in unbonding queue
|
||||
RedelegationQueueKey = []byte{0x42} // prefix for the timestamps in redelegations queue
|
||||
ValidatorQueueKey = []byte{0x43} // prefix for the timestamps in validator queue
|
||||
|
||||
HistoricalInfoKey = collections.NewPrefix(80) // prefix for the historical info
|
||||
ValidatorUpdatesKey = collections.NewPrefix(97) // prefix for the end block validator updates key
|
||||
@@ -221,12 +221,6 @@ func GetUBDsByValIndexKey(valAddr sdk.ValAddress) []byte {
|
||||
return append(UnbondingDelegationByValIndexKey, address.MustLengthPrefix(valAddr)...)
|
||||
}
|
||||
|
||||
// GetUnbondingDelegationTimeKey creates the prefix for all unbonding delegations from a delegator
|
||||
func GetUnbondingDelegationTimeKey(timestamp time.Time) []byte {
|
||||
bz := sdk.FormatTimeBytes(timestamp)
|
||||
return append(UnbondingQueueKey, bz...)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
|
||||
Reference in New Issue
Block a user