refactor(x/slashing): migrate ValidatorMissedBlockBitmap to collections (#17568)
This commit is contained in:
parent
356097a6ab
commit
a24d7071c1
@ -59,6 +59,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
### API Breaking Changes
|
||||
|
||||
* (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`:
|
||||
* remove from `Keeper`: `UBDQueueIterator`
|
||||
* remove from `types`: `GetUnbondingDelegationTimeKey`
|
||||
|
||||
@ -25,11 +25,12 @@ type Keeper struct {
|
||||
|
||||
// the address capable of executing a MsgUpdateParams message. Typically, this
|
||||
// should be the x/gov module account.
|
||||
authority string
|
||||
Schema collections.Schema
|
||||
Params collections.Item[types.Params]
|
||||
ValidatorSigningInfo collections.Map[sdk.ConsAddress, types.ValidatorSigningInfo]
|
||||
AddrPubkeyRelation collections.Map[[]byte, cryptotypes.PubKey]
|
||||
authority string
|
||||
Schema collections.Schema
|
||||
Params collections.Item[types.Params]
|
||||
ValidatorSigningInfo collections.Map[sdk.ConsAddress, types.ValidatorSigningInfo]
|
||||
AddrPubkeyRelation collections.Map[[]byte, cryptotypes.PubKey]
|
||||
ValidatorMissedBlockBitmap collections.Map[collections.Pair[[]byte, uint64], []byte]
|
||||
}
|
||||
|
||||
// NewKeeper creates a slashing keeper
|
||||
@ -56,6 +57,13 @@ func NewKeeper(cdc codec.BinaryCodec, legacyAmino *codec.LegacyAmino, storeServi
|
||||
sdk.LengthPrefixedBytesKey, // sdk.LengthPrefixedBytesKey is needed to retain state compatibility
|
||||
codec.CollInterfaceValue[cryptotypes.PubKey](cdc),
|
||||
),
|
||||
ValidatorMissedBlockBitmap: collections.NewMap(
|
||||
sb,
|
||||
types.ValidatorMissedBlockBitmapKeyPrefix,
|
||||
"validator_missed_block_bitmap",
|
||||
collections.PairKeyCodec(sdk.LengthPrefixedBytesKey, collections.Uint64Key),
|
||||
collections.BytesValue,
|
||||
),
|
||||
}
|
||||
|
||||
schema, err := sb.Build()
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"testing"
|
||||
|
||||
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
|
||||
@ -18,6 +19,7 @@ import (
|
||||
sdktestutil "github.com/cosmos/cosmos-sdk/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
addresstypes "github.com/cosmos/cosmos-sdk/types/address"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
@ -36,10 +38,12 @@ type KeeperTestSuite struct {
|
||||
slashingKeeper slashingkeeper.Keeper
|
||||
queryClient slashingtypes.QueryClient
|
||||
msgServer slashingtypes.MsgServer
|
||||
key *storetypes.KVStoreKey
|
||||
}
|
||||
|
||||
func (s *KeeperTestSuite) SetupTest() {
|
||||
key := storetypes.NewKVStoreKey(slashingtypes.StoreKey)
|
||||
s.key = key
|
||||
storeService := runtime.NewKVStoreService(key)
|
||||
testCtx := sdktestutil.DefaultContextWithDB(s.T(), key, storetypes.NewTransientStoreKey("transient_test"))
|
||||
ctx := testCtx.Ctx.WithBlockHeader(cmtproto.Header{Time: cmttime.Now()})
|
||||
@ -131,6 +135,45 @@ func (s *KeeperTestSuite) TestJailAndSlashWithInfractionReason() {
|
||||
s.Require().NoError(s.slashingKeeper.Jail(s.ctx, consAddr))
|
||||
}
|
||||
|
||||
// ValidatorMissedBlockBitmapKey returns the key for a validator's missed block
|
||||
// bitmap chunk.
|
||||
func validatorMissedBlockBitmapKey(v sdk.ConsAddress, chunkIndex int64) []byte {
|
||||
bz := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(bz, uint64(chunkIndex))
|
||||
|
||||
validatorMissedBlockBitmapKeyPrefix := []byte{0x02} // Prefix for missed block bitmap
|
||||
return append(append(validatorMissedBlockBitmapKeyPrefix, addresstypes.MustLengthPrefix(v.Bytes())...), bz...)
|
||||
}
|
||||
|
||||
func (s *KeeperTestSuite) TestValidatorMissedBlockBMMigrationToColls() {
|
||||
s.SetupTest()
|
||||
|
||||
consAddr := sdk.ConsAddress(sdk.AccAddress([]byte("addr1_______________")))
|
||||
index := int64(0)
|
||||
err := sdktestutil.DiffCollectionsMigration(
|
||||
s.ctx,
|
||||
s.key,
|
||||
100,
|
||||
func(i int64) {
|
||||
s.ctx.KVStore(s.key).Set(validatorMissedBlockBitmapKey(consAddr, index), []byte{})
|
||||
},
|
||||
"7ad1f994d45ec9495ae5f990a3fba100c2cc70167a154c33fb43882dc004eafd",
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
err = sdktestutil.DiffCollectionsMigration(
|
||||
s.ctx,
|
||||
s.key,
|
||||
100,
|
||||
func(i int64) {
|
||||
err := s.slashingKeeper.SetMissedBlockBitmapChunk(s.ctx, consAddr, index, []byte{})
|
||||
s.Require().NoError(err)
|
||||
},
|
||||
"7ad1f994d45ec9495ae5f990a3fba100c2cc70167a154c33fb43882dc004eafd",
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
func TestKeeperTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(KeeperTestSuite))
|
||||
}
|
||||
|
||||
@ -2,12 +2,13 @@ package keeper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/bits-and-blooms/bitset"
|
||||
|
||||
"cosmossdk.io/errors"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
"cosmossdk.io/collections"
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/slashing/types"
|
||||
@ -25,7 +26,7 @@ func (k Keeper) HasValidatorSigningInfo(ctx context.Context, consAddr sdk.ConsAd
|
||||
func (k Keeper) JailUntil(ctx context.Context, consAddr sdk.ConsAddress, jailTime time.Time) error {
|
||||
signInfo, err := k.ValidatorSigningInfo.Get(ctx, consAddr)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "cannot jail validator that does not have any signing information")
|
||||
return errorsmod.Wrap(err, "cannot jail validator that does not have any signing information")
|
||||
}
|
||||
|
||||
signInfo.JailedUntil = jailTime
|
||||
@ -61,17 +62,25 @@ func (k Keeper) IsTombstoned(ctx context.Context, consAddr sdk.ConsAddress) bool
|
||||
// getMissedBlockBitmapChunk gets the bitmap chunk at the given chunk index for
|
||||
// a validator's missed block signing window.
|
||||
func (k Keeper) getMissedBlockBitmapChunk(ctx context.Context, addr sdk.ConsAddress, chunkIndex int64) ([]byte, error) {
|
||||
store := k.storeService.OpenKVStore(ctx)
|
||||
chunk, err := store.Get(types.ValidatorMissedBlockBitmapKey(addr, chunkIndex))
|
||||
return chunk, err
|
||||
consAddr, err := k.sk.ConsensusAddressCodec().StringToBytes(addr.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chunk, err := k.ValidatorMissedBlockBitmap.Get(ctx, collections.Join(consAddr, uint64(chunkIndex)))
|
||||
if err != nil && !errors.Is(err, collections.ErrNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
return chunk, nil
|
||||
}
|
||||
|
||||
// setMissedBlockBitmapChunk sets the bitmap chunk at the given chunk index for
|
||||
// SetMissedBlockBitmapChunk sets the bitmap chunk at the given chunk index for
|
||||
// a validator's missed block signing window.
|
||||
func (k Keeper) setMissedBlockBitmapChunk(ctx context.Context, addr sdk.ConsAddress, chunkIndex int64, chunk []byte) error {
|
||||
store := k.storeService.OpenKVStore(ctx)
|
||||
key := types.ValidatorMissedBlockBitmapKey(addr, chunkIndex)
|
||||
return store.Set(key, chunk)
|
||||
func (k Keeper) SetMissedBlockBitmapChunk(ctx context.Context, addr sdk.ConsAddress, chunkIndex int64, chunk []byte) error {
|
||||
consAddr, err := k.sk.ConsensusAddressCodec().StringToBytes(addr.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return k.ValidatorMissedBlockBitmap.Set(ctx, collections.Join(consAddr, uint64(chunkIndex)), chunk)
|
||||
}
|
||||
|
||||
// GetMissedBlockBitmapValue returns true if a validator missed signing a block
|
||||
@ -87,12 +96,12 @@ func (k Keeper) GetMissedBlockBitmapValue(ctx context.Context, addr sdk.ConsAddr
|
||||
bs := bitset.New(uint(types.MissedBlockBitmapChunkSize))
|
||||
chunk, err := k.getMissedBlockBitmapChunk(ctx, addr, chunkIndex)
|
||||
if err != nil {
|
||||
return false, errors.Wrapf(err, "failed to get bitmap chunk; index: %d", index)
|
||||
return false, errorsmod.Wrapf(err, "failed to get bitmap chunk; index: %d", index)
|
||||
}
|
||||
|
||||
if chunk != nil {
|
||||
if err := bs.UnmarshalBinary(chunk); err != nil {
|
||||
return false, errors.Wrapf(err, "failed to decode bitmap chunk; index: %d", index)
|
||||
return false, errorsmod.Wrapf(err, "failed to decode bitmap chunk; index: %d", index)
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,12 +125,12 @@ func (k Keeper) SetMissedBlockBitmapValue(ctx context.Context, addr sdk.ConsAddr
|
||||
bs := bitset.New(uint(types.MissedBlockBitmapChunkSize))
|
||||
chunk, err := k.getMissedBlockBitmapChunk(ctx, addr, chunkIndex)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get bitmap chunk; index: %d", index)
|
||||
return errorsmod.Wrapf(err, "failed to get bitmap chunk; index: %d", index)
|
||||
}
|
||||
|
||||
if chunk != nil {
|
||||
if err := bs.UnmarshalBinary(chunk); err != nil {
|
||||
return errors.Wrapf(err, "failed to decode bitmap chunk; index: %d", index)
|
||||
return errorsmod.Wrapf(err, "failed to decode bitmap chunk; index: %d", index)
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,28 +144,30 @@ func (k Keeper) SetMissedBlockBitmapValue(ctx context.Context, addr sdk.ConsAddr
|
||||
|
||||
updatedChunk, err := bs.MarshalBinary()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to encode bitmap chunk; index: %d", index)
|
||||
return errorsmod.Wrapf(err, "failed to encode bitmap chunk; index: %d", index)
|
||||
}
|
||||
|
||||
return k.setMissedBlockBitmapChunk(ctx, addr, chunkIndex, updatedChunk)
|
||||
return k.SetMissedBlockBitmapChunk(ctx, addr, chunkIndex, updatedChunk)
|
||||
}
|
||||
|
||||
// DeleteMissedBlockBitmap removes a validator's missed block bitmap from state.
|
||||
func (k Keeper) DeleteMissedBlockBitmap(ctx context.Context, addr sdk.ConsAddress) error {
|
||||
store := k.storeService.OpenKVStore(ctx)
|
||||
prefix := types.ValidatorMissedBlockBitmapPrefixKey(addr)
|
||||
iter, err := store.Iterator(prefix, storetypes.PrefixEndBytes(prefix))
|
||||
consAddr, err := k.sk.ConsensusAddressCodec().StringToBytes(addr.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer iter.Close()
|
||||
|
||||
for ; iter.Valid(); iter.Next() {
|
||||
err = store.Delete(iter.Key())
|
||||
rng := collections.NewPrefixedPairRange[[]byte, uint64](consAddr)
|
||||
err = k.ValidatorMissedBlockBitmap.Walk(ctx, rng, func(key collections.Pair[[]byte, uint64], value []byte) (bool, error) {
|
||||
err := k.ValidatorMissedBlockBitmap.Remove(ctx, key)
|
||||
if err != nil {
|
||||
return err
|
||||
return true, err
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -167,20 +178,17 @@ func (k Keeper) DeleteMissedBlockBitmap(ctx context.Context, addr sdk.ConsAddres
|
||||
// Note: A callback will only be executed over all bitmap chunks that exist in
|
||||
// state.
|
||||
func (k Keeper) IterateMissedBlockBitmap(ctx context.Context, addr sdk.ConsAddress, cb func(index int64, missed bool) (stop bool)) error {
|
||||
store := k.storeService.OpenKVStore(ctx)
|
||||
prefix := types.ValidatorMissedBlockBitmapPrefixKey(addr)
|
||||
iter, err := store.Iterator(prefix, storetypes.PrefixEndBytes(prefix))
|
||||
consAddr, err := k.sk.ConsensusAddressCodec().StringToBytes(addr.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer iter.Close()
|
||||
|
||||
var index int64
|
||||
for ; iter.Valid(); iter.Next() {
|
||||
rng := collections.NewPrefixedPairRange[[]byte, uint64](consAddr)
|
||||
err = k.ValidatorMissedBlockBitmap.Walk(ctx, rng, func(key collections.Pair[[]byte, uint64], value []byte) (bool, error) {
|
||||
bs := bitset.New(uint(types.MissedBlockBitmapChunkSize))
|
||||
|
||||
if err := bs.UnmarshalBinary(iter.Value()); err != nil {
|
||||
return errors.Wrapf(err, "failed to decode bitmap chunk; index: %v", string(iter.Key()))
|
||||
if err := bs.UnmarshalBinary(value); err != nil {
|
||||
return true, errorsmod.Wrapf(err, "failed to decode bitmap chunk; index: %v", key)
|
||||
}
|
||||
|
||||
for i := uint(0); i < types.MissedBlockBitmapChunkSize; i++ {
|
||||
@ -191,6 +199,10 @@ func (k Keeper) IterateMissedBlockBitmap(ctx context.Context, addr sdk.ConsAddre
|
||||
|
||||
index++
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -27,12 +27,10 @@ func TestDecodeStore(t *testing.T) {
|
||||
dec := simulation.NewDecodeStore(cdc)
|
||||
|
||||
info := types.NewValidatorSigningInfo(consAddr1, 0, 1, time.Now().UTC(), false, 0)
|
||||
missed := []byte{1} // we want to display the bytes for simulation diffs
|
||||
|
||||
kvPairs := kv.Pairs{
|
||||
Pairs: []kv.Pair{
|
||||
{Key: types.ValidatorSigningInfoKey(consAddr1), Value: cdc.MustMarshal(&info)},
|
||||
{Key: types.ValidatorMissedBlockBitmapKey(consAddr1, 6), Value: missed},
|
||||
{Key: []byte{0x99}, Value: []byte{0x99}}, // This test should panic
|
||||
},
|
||||
}
|
||||
@ -43,7 +41,6 @@ func TestDecodeStore(t *testing.T) {
|
||||
panics bool
|
||||
}{
|
||||
{"ValidatorSigningInfo", fmt.Sprintf("%v\n%v", info, info), false},
|
||||
{"ValidatorMissedBlockBitArray", fmt.Sprintf("missedA: %v\nmissedB: %v\n", missed, missed), false},
|
||||
{"other", "", true},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"cosmossdk.io/collections"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
@ -51,7 +49,7 @@ const (
|
||||
var (
|
||||
ParamsKey = collections.NewPrefix(0) // Prefix for params key
|
||||
ValidatorSigningInfoKeyPrefix = collections.NewPrefix(1) // Prefix for signing info
|
||||
ValidatorMissedBlockBitmapKeyPrefix = []byte{0x02} // Prefix for missed block bitmap
|
||||
ValidatorMissedBlockBitmapKeyPrefix = collections.NewPrefix(2) // Prefix for missed block bitmap
|
||||
AddrPubkeyRelationKeyPrefix = collections.NewPrefix(3) // Prefix for address-pubkey relation
|
||||
)
|
||||
|
||||
@ -59,18 +57,3 @@ var (
|
||||
func ValidatorSigningInfoKey(v sdk.ConsAddress) []byte {
|
||||
return append(ValidatorSigningInfoKeyPrefix, address.MustLengthPrefix(v.Bytes())...)
|
||||
}
|
||||
|
||||
// ValidatorMissedBlockBitmapPrefixKey returns the key prefix for a validator's
|
||||
// missed block bitmap.
|
||||
func ValidatorMissedBlockBitmapPrefixKey(v sdk.ConsAddress) []byte {
|
||||
return append(ValidatorMissedBlockBitmapKeyPrefix, address.MustLengthPrefix(v.Bytes())...)
|
||||
}
|
||||
|
||||
// ValidatorMissedBlockBitmapKey returns the key for a validator's missed block
|
||||
// bitmap chunk.
|
||||
func ValidatorMissedBlockBitmapKey(v sdk.ConsAddress, chunkIndex int64) []byte {
|
||||
bz := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(bz, uint64(chunkIndex))
|
||||
|
||||
return append(ValidatorMissedBlockBitmapPrefixKey(v), bz...)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user