Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor!: store key (WIP) #1270

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion x/ccv/provider/keeper/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func ValidatorConsensusKeyInUse(k *Keeper, ctx sdk.Context, valAddr sdk.ValAddre

inUse := false

for _, validatorConsumerAddrs := range k.GetAllValidatorsByConsumerAddr(ctx, nil) {
for _, validatorConsumerAddrs := range k.GetValidatorsByConsumerAddr(ctx, consensusAddr) {
if sdk.ConsAddress(validatorConsumerAddrs.ConsumerAddr).Equals(consensusAddr) {
inUse = true
break
Expand Down
72 changes: 55 additions & 17 deletions x/ccv/provider/keeper/key_assignment.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package keeper

import (

Check failure on line 3 in x/ccv/provider/keeper/key_assignment.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gofumpt`-ed with `-extra` (gofumpt)

Check failure on line 3 in x/ccv/provider/keeper/key_assignment.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gofumpt`-ed with `-extra` (gofumpt)
"fmt"

errorsmod "cosmossdk.io/errors"

Check failure on line 4 in x/ccv/provider/keeper/key_assignment.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gci`-ed with --skip-generated -s standard -s default -s blank -s dot -s prefix(cosmossdk.io) -s prefix(github.com/cosmos/cosmos-sdk) -s prefix(github.com/cometbft/cometbft) -s prefix(github.com/cosmos/interchain-security) --custom-order (gci)

Check failure on line 4 in x/ccv/provider/keeper/key_assignment.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gci`-ed with --skip-generated -s standard -s default -s blank -s dot -s prefix(cosmossdk.io) -s prefix(github.com/cosmos/cosmos-sdk) -s prefix(github.com/cometbft/cometbft) -s prefix(github.com/cosmos/interchain-security) --custom-order (gci)

"fmt"

Check failure on line 5 in x/ccv/provider/keeper/key_assignment.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gci`-ed with --skip-generated -s standard -s default -s blank -s dot -s prefix(cosmossdk.io) -s prefix(github.com/cosmos/cosmos-sdk) -s prefix(github.com/cometbft/cometbft) -s prefix(github.com/cosmos/interchain-security) --custom-order (gci)

Check failure on line 5 in x/ccv/provider/keeper/key_assignment.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gci`-ed with --skip-generated -s standard -s default -s blank -s dot -s prefix(cosmossdk.io) -s prefix(github.com/cosmos/cosmos-sdk) -s prefix(github.com/cometbft/cometbft) -s prefix(github.com/cosmos/interchain-security) --custom-order (gci)
sdk "github.com/cosmos/cosmos-sdk/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"

Expand Down Expand Up @@ -135,30 +133,23 @@
store.Set(types.ValidatorsByConsumerAddrKey(chainID, consumerAddr), bz)
}

// GetValidatorsByConsumerAddrs gets all the mappings from consensus addresses
// GetValidatorsByConsumerAddr gets all the mappings from consensus addresses
// on a given consumer chain to consensus addresses on the provider chain.
// If chainID is nil, it returns all the mappings from consensus addresses on all consumer chains.
//
// Note that the mappings for a consumer chain are stored under keys with the following format:
// ValidatorsByConsumerAddrBytePrefix | len(chainID) | chainID | consumerAddress
// ValidatorsByConsumerAddrBytePrefix | consumerAddress | len(chainID) | chainID
// Thus, the returned array is
// - in ascending order of consumerAddresses, if chainID is not nil;
// - in undetermined order, if chainID is nil.
func (k Keeper) GetAllValidatorsByConsumerAddr(ctx sdk.Context, chainID *string) (validatorConsumerAddrs []types.ValidatorByConsumerAddr) {

func (k Keeper) GetValidatorsByConsumerAddr(ctx sdk.Context, consumerConsAddr sdk.ConsAddress) (validatorConsumerAddrs []types.ValidatorByConsumerAddr) {
store := ctx.KVStore(k.storeKey)
var prefix []byte
if chainID == nil {
// iterate over the mappings from consensus addresses on all consumer chains
prefix = []byte{types.ValidatorsByConsumerAddrBytePrefix}
} else {
// iterate over the mappings from consensus addresses on chainID
prefix = types.ChainIdWithLenKey(types.ValidatorsByConsumerAddrBytePrefix, *chainID)
}
prefix := types.PrefixWithLenConsAddress(types.ValidatorsByConsumerAddrBytePrefix, consumerConsAddr)
iterator := sdk.KVStorePrefixIterator(store, prefix)
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
// TODO: store chainID and consumer cons address in value bytes, marshaled as protobuf type
chainID, consumerAddrTmp, err := types.ParseChainIdAndConsAddrKey(types.ValidatorsByConsumerAddrBytePrefix, iterator.Key())
chainID, consumerAddrTmp, err := types.ParseConsAddrKeyAndChainID(types.ValidatorsByConsumerAddrBytePrefix, iterator.Key())
if err != nil {
// An error here would indicate something is very wrong,
// store keys are assumed to be correctly serialized in SetValidatorByConsumerAddr.
Expand All @@ -177,6 +168,41 @@
return validatorConsumerAddrs
}

// ValidatorsByConsumerAddrBytePrefix | consumerAddress | len(chainID) | chainID
func (k Keeper) GetAllValidatorsByConsumerAddr(ctx sdk.Context, chainID *string) (validatorConsumerAddrs []types.ValidatorByConsumerAddr) {
store := ctx.KVStore(k.storeKey)
prefix := []byte{types.ValidatorsByConsumerAddrBytePrefix}
iterator := sdk.KVStorePrefixIterator(store, prefix)
for ; iterator.Valid(); iterator.Next() {
cID, consumerAddrTmp, err := types.ParseConsAddrKeyAndChainID(types.ValidatorsByConsumerAddrBytePrefix, iterator.Key())
if err != nil {
// An error here would indicate something is very wrong,
// store keys are assumed to be correctly serialized in SetValidatorByConsumerAddr.
panic(fmt.Sprintf("failed to parse chainID and consumer address: %v", err))
}

if cID == *chainID || chainID == nil {
consumerAddr := types.NewConsumerConsAddress(consumerAddrTmp)
providerAddr := types.NewProviderConsAddress(iterator.Value())

validatorConsumerAddrs = append(validatorConsumerAddrs, types.ValidatorByConsumerAddr{
ConsumerAddr: consumerAddr.ToSdkConsAddr(),
ProviderAddr: providerAddr.ToSdkConsAddr(),
ChainId: cID,
})
}
}

return validatorConsumerAddrs
}

// DeleteValidatorByConsumerAddrLegacy deletes the mapping from a validator's consensus address on a consumer
// to the validator's consensus address on the provider
func (k Keeper) DeleteValidatorByConsumerAddrLegacy(ctx sdk.Context, chainID string, consumerAddr types.ConsumerConsAddress) {
store := ctx.KVStore(k.storeKey)
store.Delete(types.ValidatorsByConsumerAddrKeyLegacy(chainID, consumerAddr))
}

// DeleteValidatorByConsumerAddr deletes the mapping from a validator's consensus address on a consumer
// to the validator's consensus address on the provider
func (k Keeper) DeleteValidatorByConsumerAddr(ctx sdk.Context, chainID string, consumerAddr types.ConsumerConsAddress) {
Expand Down Expand Up @@ -610,10 +636,22 @@
for _, validatorConsumerAddr := range k.GetAllValidatorConsumerPubKeys(ctx, &chainID) {
providerAddr := types.NewProviderConsAddress(validatorConsumerAddr.ProviderAddr)
k.DeleteValidatorConsumerPubKey(ctx, chainID, providerAddr)

//consAddrTmp, err := ccvtypes.TMCryptoPublicKeyToConsAddr(*validatorConsumerAddr.ConsumerKey)

Check failure on line 640 in x/ccv/provider/keeper/key_assignment.go

View workflow job for this annotation

GitHub Actions / lint

commentFormatting: put a space between `//` and comment text (gocritic)

Check failure on line 640 in x/ccv/provider/keeper/key_assignment.go

View workflow job for this annotation

GitHub Actions / lint

commentFormatting: put a space between `//` and comment text (gocritic)
//if err != nil {
// // todo
// panic(err)
//}
//consumerAddr := types.NewConsumerConsAddress(consAddrTmp)
//
//k.DeleteValidatorByConsumerAddr(ctx, chainID, consumerAddr)
}

// delete ValidatorsByConsumerAddr
//// delete ValidatorsByConsumerAddr
for _, validatorConsumerAddr := range k.GetAllValidatorsByConsumerAddr(ctx, &chainID) {
if validatorConsumerAddr.ChainId != chainID {
continue
}
consumerAddr := types.NewConsumerConsAddress(validatorConsumerAddr.ConsumerAddr)
k.DeleteValidatorByConsumerAddr(ctx, chainID, consumerAddr)
}
Expand Down
2 changes: 1 addition & 1 deletion x/ccv/provider/keeper/key_assignment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ func TestValidatorByConsumerAddrCRUD(t *testing.T) {
require.NotEmpty(t, providerAddrResult, "provider address is empty")
require.Equal(t, providerAddr, providerAddrResult)

keeper.DeleteValidatorByConsumerAddr(ctx, chainID, consumerAddr)
keeper.DeleteValidatorByConsumerAddrLegacy(ctx, chainID, consumerAddr)
providerAddrResult, found = keeper.GetValidatorByConsumerAddr(ctx, chainID, consumerAddr)
require.False(t, found, "provider address was found")
require.Empty(t, providerAddrResult, "provider address not empty")
Expand Down
49 changes: 49 additions & 0 deletions x/ccv/provider/keeper/migration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package keeper

import (
"github.com/coinbase/rosetta-sdk-go/storage/errors"

Check failure on line 4 in x/ccv/provider/keeper/migration.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gci`-ed with --skip-generated -s standard -s default -s blank -s dot -s prefix(cosmossdk.io) -s prefix(github.com/cosmos/cosmos-sdk) -s prefix(github.com/cometbft/cometbft) -s prefix(github.com/cosmos/interchain-security) --custom-order (gci)

Check failure on line 4 in x/ccv/provider/keeper/migration.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gci`-ed with --skip-generated -s standard -s default -s blank -s dot -s prefix(cosmossdk.io) -s prefix(github.com/cosmos/cosmos-sdk) -s prefix(github.com/cometbft/cometbft) -s prefix(github.com/cosmos/interchain-security) --custom-order (gci)
sdk "github.com/cosmos/cosmos-sdk/types"

Check failure on line 5 in x/ccv/provider/keeper/migration.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gci`-ed with --skip-generated -s standard -s default -s blank -s dot -s prefix(cosmossdk.io) -s prefix(github.com/cosmos/cosmos-sdk) -s prefix(github.com/cometbft/cometbft) -s prefix(github.com/cosmos/interchain-security) --custom-order (gci)

Check failure on line 5 in x/ccv/provider/keeper/migration.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gci`-ed with --skip-generated -s standard -s default -s blank -s dot -s prefix(cosmossdk.io) -s prefix(github.com/cosmos/cosmos-sdk) -s prefix(github.com/cometbft/cometbft) -s prefix(github.com/cosmos/interchain-security) --custom-order (gci)
"github.com/cosmos/interchain-security/v3/x/ccv/provider/types"
)

type Migrator struct {
ccvProviderKeeper Keeper
}

func NewMigrator(ccvProviderKeeper Keeper) Migrator {
return Migrator{ccvProviderKeeper: ccvProviderKeeper}
}

func (m Migrator) Migrate2to3(ctx sdk.Context) error {
return m.ccvProviderKeeper.MigrateConsumerAddrStoreKey(ctx)
}

func (k Keeper) MigrateConsumerAddrStoreKey(ctx sdk.Context) error {
store := ctx.KVStore(k.storeKey)
var prefixCon []byte

Check failure on line 23 in x/ccv/provider/keeper/migration.go

View workflow job for this annotation

GitHub Actions / lint

S1021: should merge variable declaration with assignment on next line (gosimple)

Check failure on line 23 in x/ccv/provider/keeper/migration.go

View workflow job for this annotation

GitHub Actions / lint

S1021: should merge variable declaration with assignment on next line (gosimple)

prefixCon = []byte{types.ValidatorsByConsumerAddrBytePrefix}

iteratorCon := sdk.KVStorePrefixIterator(store, prefixCon)
defer iteratorCon.Close()
for ; iteratorCon.Valid(); iteratorCon.Next() {
// ParseChainIdAndConsAddrKey is used in other places, so it was not renamed to ParseChainIdAndConsAddrKeyLegacy
chainID, consumerAddrTmp, err := types.ParseChainIdAndConsAddrKey(types.ValidatorsByConsumerAddrBytePrefix, iteratorCon.Key())
if err != nil {
// An error here would indicate something is very wrong,
// store keys are assumed to be correctly serialized in SetValidatorByConsumerAddr.
return errors.ErrParseKeyPairFailed
}
consumerAddr := types.NewConsumerConsAddress(consumerAddrTmp)
providerAddr := types.NewProviderConsAddress(iteratorCon.Value())

// bytePrefix | len(ConsAddress) | ConsAddress | chainID
k.SetValidatorByConsumerAddr(ctx, chainID, consumerAddr, providerAddr)

// delete old kv
k.DeleteValidatorByConsumerAddrLegacy(ctx, chainID, consumerAddr)

}

return nil
}
6 changes: 5 additions & 1 deletion x/ccv/provider/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ func (AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {
func (am AppModule) RegisterServices(cfg module.Configurator) {
providertypes.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper))
providertypes.RegisterQueryServer(cfg.QueryServer(), am.keeper)
m := keeper.NewMigrator(*am.keeper)
if err := cfg.RegisterMigration(providertypes.ModuleName, 1, m.Migrate2to3); err != nil {
panic(fmt.Sprintf("failed to migrate provider from version 1 to 2: %v", err))
}
}

// InitGenesis performs genesis initialization for the provider module. It returns no validator updates.
Expand All @@ -129,7 +133,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw
}

// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 2 }
func (AppModule) ConsensusVersion() uint64 { return 3 }

// BeginBlock implements the AppModule interface
func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
Expand Down
58 changes: 53 additions & 5 deletions x/ccv/provider/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,22 +343,34 @@ func MustParseGlobalSlashEntryKey(bz []byte) (
return recvTime, chainID, ibcSeqNum
}

// ConsumerValidatorsKeyLegacy returns the key under which the
// validator assigned keys for every consumer chain are stored
// key: bytePrefix | len(chainID) | chainID | ConsAddress
func ConsumerValidatorsKeyLegacy(chainID string, addr ProviderConsAddress) []byte {
return ChainIdAndConsAddrKeyLegacy(ConsumerValidatorsBytePrefix, chainID, addr.ToSdkConsAddr())
}

// ConsumerValidatorsKey returns the key under which the
// validator assigned keys for every consumer chain are stored
// key bytePrefix | len(ConsAddress) | ConsAddress | chainID
func ConsumerValidatorsKey(chainID string, addr ProviderConsAddress) []byte {
return ChainIdAndConsAddrKey(ConsumerValidatorsBytePrefix, chainID, addr.ToSdkConsAddr())
}

// ValidatorsByConsumerAddrKey returns the key under which the mapping from validator addresses
// ValidatorsByConsumerAddrKeyLegacy returns the key under which the mapping from validator addresses
// on consumer chains to validator addresses on the provider chain is stored
func ValidatorsByConsumerAddrKeyLegacy(chainID string, addr ConsumerConsAddress) []byte {
return ChainIdAndConsAddrKeyLegacy(ValidatorsByConsumerAddrBytePrefix, chainID, addr.ToSdkConsAddr())
}

func ValidatorsByConsumerAddrKey(chainID string, addr ConsumerConsAddress) []byte {
return ChainIdAndConsAddrKey(ValidatorsByConsumerAddrBytePrefix, chainID, addr.ToSdkConsAddr())
}

// KeyAssignmentReplacementsKey returns the key under which the
// key assignments that need to be replaced in the current block are stored
func KeyAssignmentReplacementsKey(chainID string, addr ProviderConsAddress) []byte {
return ChainIdAndConsAddrKey(KeyAssignmentReplacementsBytePrefix, chainID, addr.ToSdkConsAddr())
return ChainIdAndConsAddrKeyLegacy(KeyAssignmentReplacementsBytePrefix, chainID, addr.ToSdkConsAddr())
}

// ConsumerAddrsToPruneKey returns the key under which the
Expand Down Expand Up @@ -414,6 +426,17 @@ func ChainIdWithLenKey(prefix byte, chainID string) []byte {
)
}

// PrefixWithLenConsAddress returns the key with the following format:
// bytePrefix | Address
func PrefixWithLenConsAddress(prefix byte, addr sdk.ConsAddress) []byte {
addrL := len(addr)
return ccvtypes.AppendMany(
[]byte{prefix},
sdk.Uint64ToBigEndian(uint64(addrL)),
addr,
)
}

// ParseChainIdAndTsKey returns the chain ID and time for a ChainIdAndTs key
func ParseChainIdAndTsKey(prefix byte, bz []byte) (string, time.Time, error) {
expectedPrefix := []byte{prefix}
Expand Down Expand Up @@ -455,9 +478,9 @@ func ParseChainIdAndUintIdKey(prefix byte, bz []byte) (string, uint64, error) {
return chainID, uintID, nil
}

// ChainIdAndConsAddrKey returns the key with the following format:
// ChainIdAndConsAddrKeyLegacy returns the key with the following format:
// bytePrefix | len(chainID) | chainID | ConsAddress
func ChainIdAndConsAddrKey(prefix byte, chainID string, addr sdk.ConsAddress) []byte {
func ChainIdAndConsAddrKeyLegacy(prefix byte, chainID string, addr sdk.ConsAddress) []byte {
partialKey := ChainIdWithLenKey(prefix, chainID)
return ccvtypes.AppendMany(
// Append the partialKey
Expand All @@ -467,7 +490,18 @@ func ChainIdAndConsAddrKey(prefix byte, chainID string, addr sdk.ConsAddress) []
)
}

// ParseChainIdAndConsAddrKey returns the chain ID and ConsAddress for a ChainIdAndConsAddrKey key
// ChainIdAndConsAddrKey returns the key with the following format:
// bytePrefix | ConsAddress | len(chainID) | chainID
func ChainIdAndConsAddrKey(prefix byte, chainID string, addr sdk.ConsAddress) []byte {
partialKey := PrefixWithLenConsAddress(prefix, addr)
return ccvtypes.AppendMany(
partialKey,
// Append the chainID
[]byte(chainID),
)
}

// ParseChainIdAndConsAddrKey returns the chain ID and ConsAddress for a ChainIdAndConsAddrKey key: bytePrefix | len(chainID) | chainID | ConsAddress
func ParseChainIdAndConsAddrKey(prefix byte, bz []byte) (string, sdk.ConsAddress, error) {
expectedPrefix := []byte{prefix}
prefixL := len(expectedPrefix)
Expand All @@ -480,6 +514,20 @@ func ParseChainIdAndConsAddrKey(prefix byte, bz []byte) (string, sdk.ConsAddress
return chainID, addr, nil
}

// ParseConsAddrKeyAndChainID returns the chain ID and ConsAddress for a ConsAddrKeyAndChainID key: bytePrefix | len(ConsAddress) | ConsAddress | chainID
func ParseConsAddrKeyAndChainID(prefix byte, bz []byte) (string, sdk.ConsAddress, error) {
expectedPrefix := []byte{prefix}
prefixL := len(expectedPrefix)
if prefix := bz[:prefixL]; !bytes.Equal(prefix, expectedPrefix) {
return "", nil, fmt.Errorf("invalid prefix; expected: %X, got: %X", expectedPrefix, prefix)
}
addrL := sdk.BigEndianToUint64(bz[prefixL : prefixL+8])
addr := bz[prefixL+8 : prefixL+8+int(addrL)]
chainID := string(bz[prefixL+8+int(addrL):])

return chainID, addr, nil
}

func VSCMaturedHandledThisBlockKey() []byte {
return []byte{VSCMaturedHandledThisBlockBytePrefix}
}
Expand Down
6 changes: 3 additions & 3 deletions x/ccv/provider/types/keys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ func getAllFullyDefinedKeys() [][]byte {
providertypes.ThrottledPacketDataSizeKey("chainID"),
providertypes.ThrottledPacketDataKey("chainID", 88),
providertypes.GlobalSlashEntryKey(providertypes.GlobalSlashEntry{}),
providertypes.ConsumerValidatorsKey("chainID", providertypes.NewProviderConsAddress([]byte{0x05})),
providertypes.ValidatorsByConsumerAddrKey("chainID", providertypes.NewConsumerConsAddress([]byte{0x05})),
providertypes.ConsumerValidatorsKeyLegacy("chainID", providertypes.NewProviderConsAddress([]byte{0x05})),
providertypes.ValidatorsByConsumerAddrKeyLegacy("chainID", providertypes.NewConsumerConsAddress([]byte{0x05})),
providertypes.KeyAssignmentReplacementsKey("chainID", providertypes.NewProviderConsAddress([]byte{0x05})),
providertypes.ConsumerAddrsToPruneKey("chainID", 88),
providertypes.SlashLogKey(providertypes.NewProviderConsAddress([]byte{0x05})),
Expand Down Expand Up @@ -228,7 +228,7 @@ func TestChainIdAndConsAddrAndParse(t *testing.T) {
}

for _, test := range tests {
key := providertypes.ChainIdAndConsAddrKey(test.prefix, test.chainID, test.addr)
key := providertypes.ChainIdAndConsAddrKeyLegacy(test.prefix, test.chainID, test.addr)
require.NotEmpty(t, key)
// Expected bytes = prefix + chainID length + chainID + consAddr bytes
expectedLen := 1 + 8 + len(test.chainID) + len(test.addr)
Expand Down
Loading