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: change byte prefixing scheme for provider #2061

Merged
merged 7 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from 4 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
6 changes: 3 additions & 3 deletions docs/docs/adrs/adr-001-key-assignment.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ It is possible to change the keys at any time by submitting a transaction (i.e.,

- `ValidatorConsumerPubKey` - Stores the validator assigned keys for every consumer chain.
```golang
ConsumerValidatorsBytePrefix | len(chainID) | chainID | providerConsAddress -> consumerKey
0x16 | len(chainID) | chainID | providerConsAddress -> consumerKey
```
- `ValidatorByConsumerAddr` - Stores the mapping from validator addresses on consumer chains to validator addresses on the provider chain. Needed for the consumer initiated slashing sub-protocol.
```golang
ValidatorsByConsumerAddrBytePrefix | len(chainID) | chainID | consumerConsAddress -> providerConsAddress
0x17 | len(chainID) | chainID | consumerConsAddress -> providerConsAddress
```
- `ConsumerAddrsToPrune` - Stores the mapping from VSC ids to consumer validators addresses. Needed for pruning `ValidatorByConsumerAddr`.
```golang
ConsumerAddrsToPruneBytePrefix | len(chainID) | chainID | vscID -> []consumerConsAddresses
0x19 | len(chainID) | chainID | vscID -> []consumerConsAddresses
```

### Protocol overview
Expand Down
8 changes: 4 additions & 4 deletions docs/docs/adrs/adr-015-partial-set-security.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ In a future version of PSS, we intend to introduce a `ConsumerModificationPropos
We augment the provider module’s state to keep track of the `top_N` value for each consumer chain. The key to store this information would be:

```
topNBytePrefix | len(chainID) | chainID
0x21 | len(chainID) | chainID
```

To create the above key, we can use [`ChainIdWithLenKey`](https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/types/keys.go#L418).
Expand Down Expand Up @@ -116,10 +116,10 @@ Naturally, a validator can always change the consumer key on a consumer chain by
For each validator, we store a pair `(blockHeight, isOptedIn)` that contains the block height the validator opted in and whether the validator is currently opted in or not, under the key:

```
optedInBytePrefix | len(chainID) | chainID | addr
0x20 | len(chainID) | chainID | addr
```

By using a prefix iterator on `optedInBytePrefix | len(chainID) | chainID` we retrieve all the opted in validators.
By using a prefix iterator on `0x20 | len(chainID) | chainID` we retrieve all the opted in validators.

We introduce the following `Keeper` methods.

Expand Down Expand Up @@ -173,7 +173,7 @@ Additionally, a validator that belongs to the top `N%` validators cannot opt out
We also update the state of the opted-in validators when a validator has opted out by removing the opted-out validator.

Note that only opted-in validators can be punished for downtime on a consumer chain.
For this, we use historical info of all the validators that have opted in; We can examine the `blockHeight` stored under the key `optedInBytePrefix | len(chainID) | chainID | addr` to see if a validator was opted in.
For this, we use historical info of all the validators that have opted in; We can examine the `blockHeight` stored under the key `0x20 | len(chainID) | chainID | addr` to see if a validator was opted in.
This way we can jail validators for downtime knowing that indeed the validators have opted in at some point in the past.
Otherwise, we can think of a scenario where a validator `V` is down for a period of time, but before `V` gets punished for downtime, validator `V` opts out, and then we do not know whether `V` should be punished or not.

Expand Down
2 changes: 1 addition & 1 deletion x/ccv/provider/keeper/distribution.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func (k Keeper) DeleteConsumerRewardDenom(

func (k Keeper) GetAllConsumerRewardDenoms(ctx sdk.Context) (consumerRewardDenoms []string) {
store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, []byte{types.ConsumerRewardDenomsBytePrefix})
iterator := storetypes.KVStorePrefixIterator(store, []byte{types.MustGetKeyPrefix(types.ConsumerRewardDenomsKeyName)})
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
key := iterator.Key()[1:]
Expand Down
55 changes: 28 additions & 27 deletions x/ccv/provider/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,12 +235,13 @@ func (k Keeper) DeleteProposedConsumerChainInStore(ctx sdk.Context, proposalID u
// GetAllProposedConsumerChainIDs returns the proposed chainID of all gov consumerAddition proposals that are still in the voting period.
func (k Keeper) GetAllProposedConsumerChainIDs(ctx sdk.Context) []types.ProposedChain {
store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, []byte{types.ProposedConsumerChainByteKey})
bytePrefix := types.MustGetKeyPrefix(types.ProposedConsumerChainKeyName)
iterator := storetypes.KVStorePrefixIterator(store, []byte{bytePrefix})
defer iterator.Close()

proposedChains := []types.ProposedChain{}
for ; iterator.Valid(); iterator.Next() {
proposalID, err := types.ParseProposedConsumerChainKey(types.ProposedConsumerChainByteKey, iterator.Key())
proposalID, err := types.ParseProposedConsumerChainKey(bytePrefix, iterator.Key())
if err != nil {
panic(fmt.Errorf("proposed chains cannot be parsed: %w", err))
}
Expand Down Expand Up @@ -270,13 +271,13 @@ func (k Keeper) GetAllPendingConsumerChainIDs(ctx sdk.Context) []string {
// created IBC clients. Consumer chains with created clients are also referred to as registered.
//
// Note that the registered consumer chains are stored under keys with the following format:
// ChainToClientBytePrefix | chainID
// ChainToClientKey | chainID
// Thus, the returned array is in ascending order of chainIDs.
func (k Keeper) GetAllRegisteredConsumerChainIDs(ctx sdk.Context) []string {
chainIDs := []string{}

store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, []byte{types.ChainToClientBytePrefix})
iterator := storetypes.KVStorePrefixIterator(store, []byte{types.MustGetKeyPrefix(types.ChainToClientKeyName)})
defer iterator.Close()

for ; iterator.Valid(); iterator.Next() {
Expand Down Expand Up @@ -315,11 +316,11 @@ func (k Keeper) DeleteChannelToChain(ctx sdk.Context, channelID string) {
//
// Note that mapping from CCV channel IDs to consumer chainIDs
// is stored under keys with the following format:
// ChannelToChainBytePrefix | channelID
// ChannelToChainKey | channelID
// Thus, the returned array is in ascending order of channelIDs.
func (k Keeper) GetAllChannelToChains(ctx sdk.Context) (channels []types.ChannelToChain) {
store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, []byte{types.ChannelToChainBytePrefix})
iterator := storetypes.KVStorePrefixIterator(store, []byte{types.MustGetKeyPrefix(types.ChannelToChainKeyName)})
defer iterator.Close()

for ; iterator.Valid(); iterator.Next() {
Expand Down Expand Up @@ -486,11 +487,11 @@ func (k Keeper) DeleteUnbondingOp(ctx sdk.Context, id uint64) {
// is waiting on.
//
// Note that UnbondingOps are stored under keys with the following format:
// UnbondingOpBytePrefix | ID
// UnbondingOpKey | ID
// Thus, the iteration is in ascending order of IDs.
func (k Keeper) GetAllUnbondingOps(ctx sdk.Context) (ops []types.UnbondingOp) {
store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, []byte{types.UnbondingOpBytePrefix})
iterator := storetypes.KVStorePrefixIterator(store, []byte{types.MustGetKeyPrefix(types.UnbondingOpKeyName)})

defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
Expand Down Expand Up @@ -577,11 +578,11 @@ func (k Keeper) SetUnbondingOpIndex(ctx sdk.Context, chainID string, vscID uint6
// VSCMaturedPackets from a consumer with chainID.
//
// Note that the unbonding indexes for a given chainID are stored under keys with the following format:
// UnbondingOpIndexBytePrefix | len(chainID) | chainID | vscID
// UnbondingOpIndexKey | len(chainID) | chainID | vscID
// Thus, the returned array is in ascending order of vscIDs.
func (k Keeper) GetAllUnbondingOpIndexes(ctx sdk.Context, chainID string) (indexes []types.VscUnbondingOps) {
store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.UnbondingOpIndexBytePrefix, chainID))
iterator := storetypes.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.MustGetKeyPrefix(types.UnbondingOpIndexKeyName), chainID))
defer iterator.Close()

for ; iterator.Valid(); iterator.Next() {
Expand Down Expand Up @@ -776,11 +777,11 @@ func (k Keeper) GetValsetUpdateBlockHeight(ctx sdk.Context, valsetUpdateId uint6
// GetAllValsetUpdateBlockHeights gets all the block heights for all valset updates
//
// Note that the mapping from vscIDs to block heights is stored under keys with the following format:
// ValsetUpdateBlockHeightBytePrefix | vscID
// ValsetUpdateBlockHeightKey | vscID
// Thus, the returned array is in ascending order of vscIDs.
func (k Keeper) GetAllValsetUpdateBlockHeights(ctx sdk.Context) (valsetUpdateBlockHeights []types.ValsetUpdateIdToHeight) {
store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, []byte{types.ValsetUpdateBlockHeightBytePrefix})
iterator := storetypes.KVStorePrefixIterator(store, []byte{types.MustGetKeyPrefix(types.ValsetUpdateBlockHeightKeyName)})

defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
Expand Down Expand Up @@ -982,11 +983,11 @@ func (k Keeper) DeleteInitTimeoutTimestamp(ctx sdk.Context, chainID string) {
// GetAllInitTimeoutTimestamps gets all init timeout timestamps in the store.
//
// Note that the init timeout timestamps are stored under keys with the following format:
// InitTimeoutTimestampBytePrefix | chainID
// InitTimeoutTimestampKey | chainID
// Thus, the returned array is in ascending order of chainIDs (NOT in timestamp order).
func (k Keeper) GetAllInitTimeoutTimestamps(ctx sdk.Context) (initTimeoutTimestamps []types.InitTimeoutTimestamp) {
store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, []byte{types.InitTimeoutTimestampBytePrefix})
iterator := storetypes.KVStorePrefixIterator(store, []byte{types.MustGetKeyPrefix(types.InitTimeoutTimestampKeyName)})

defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
Expand Down Expand Up @@ -1046,11 +1047,11 @@ func (k Keeper) DeleteVscSendTimestamp(ctx sdk.Context, chainID string, vscID ui
// GetAllVscSendTimestamps gets an array of all the vsc send timestamps of the given chainID.
//
// Note that the vsc send timestamps of a given chainID are stored under keys with the following format:
// VscSendTimestampBytePrefix | len(chainID) | chainID | vscID
// VscSendTimestampKey | len(chainID) | chainID | vscID
// Thus, the iteration is in ascending order of vscIDs, and as a result in send timestamp order.
func (k Keeper) GetAllVscSendTimestamps(ctx sdk.Context, chainID string) (vscSendTimestamps []types.VscSendTimestamp) {
store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.VscSendTimestampBytePrefix, chainID))
iterator := storetypes.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.MustGetKeyPrefix(types.VscSendTimestampKeyName), chainID))
defer iterator.Close()

for ; iterator.Valid(); iterator.Next() {
Expand Down Expand Up @@ -1079,7 +1080,7 @@ func (k Keeper) GetAllVscSendTimestamps(ctx sdk.Context, chainID string) (vscSen
// DeleteVscSendTimestampsForConsumer deletes all VSC send timestamps for a given consumer chain
func (k Keeper) DeleteVscSendTimestampsForConsumer(ctx sdk.Context, consumerChainID string) {
store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.VscSendTimestampBytePrefix, consumerChainID))
iterator := storetypes.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.MustGetKeyPrefix(types.VscSendTimestampKeyName), consumerChainID))

defer iterator.Close()

Expand All @@ -1097,7 +1098,7 @@ func (k Keeper) DeleteVscSendTimestampsForConsumer(ctx sdk.Context, consumerChai
// GetFirstVscSendTimestamp gets the vsc send timestamp with the lowest vscID for the given chainID.
func (k Keeper) GetFirstVscSendTimestamp(ctx sdk.Context, chainID string) (vscSendTimestamp types.VscSendTimestamp, found bool) {
store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.VscSendTimestampBytePrefix, chainID))
iterator := storetypes.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.MustGetKeyPrefix(types.VscSendTimestampKeyName), chainID))
defer iterator.Close()

if iterator.Valid() {
Expand Down Expand Up @@ -1243,7 +1244,7 @@ func (k Keeper) GetAllOptedIn(
chainID string,
) (providerConsAddresses []types.ProviderConsAddress) {
store := ctx.KVStore(k.storeKey)
key := types.ChainIdWithLenKey(types.OptedInBytePrefix, chainID)
key := types.ChainIdWithLenKey(types.MustGetKeyPrefix(types.OptedInKeyName), chainID)
iterator := storetypes.KVStorePrefixIterator(store, key)
defer iterator.Close()

Expand All @@ -1260,7 +1261,7 @@ func (k Keeper) DeleteAllOptedIn(
chainID string,
) {
store := ctx.KVStore(k.storeKey)
key := types.ChainIdWithLenKey(types.OptedInBytePrefix, chainID)
key := types.ChainIdWithLenKey(types.MustGetKeyPrefix(types.OptedInKeyName), chainID)
iterator := storetypes.KVStorePrefixIterator(store, key)

var keysToDel [][]byte
Expand Down Expand Up @@ -1323,7 +1324,7 @@ func (k Keeper) GetAllCommissionRateValidators(
chainID string,
) (addresses []types.ProviderConsAddress) {
store := ctx.KVStore(k.storeKey)
key := types.ChainIdWithLenKey(types.ConsumerCommissionRatePrefix, chainID)
key := types.ChainIdWithLenKey(types.MustGetKeyPrefix(types.ConsumerCommissionRateKeyName), chainID)
iterator := storetypes.KVStorePrefixIterator(store, key)
defer iterator.Close()

Expand Down Expand Up @@ -1434,7 +1435,7 @@ func (k Keeper) GetAllowList(
chainID string,
) (providerConsAddresses []types.ProviderConsAddress) {
store := ctx.KVStore(k.storeKey)
key := types.ChainIdWithLenKey(types.AllowlistPrefix, chainID)
key := types.ChainIdWithLenKey(types.MustGetKeyPrefix(types.AllowlistKeyName), chainID)
iterator := storetypes.KVStorePrefixIterator(store, key)
defer iterator.Close()

Expand All @@ -1459,7 +1460,7 @@ func (k Keeper) IsAllowlisted(
// DeleteAllowlist deletes all allowlisted validators
func (k Keeper) DeleteAllowlist(ctx sdk.Context, chainID string) {
store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.AllowlistPrefix, chainID))
iterator := storetypes.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.MustGetKeyPrefix(types.AllowlistKeyName), chainID))
defer iterator.Close()

keysToDel := [][]byte{}
Expand All @@ -1475,7 +1476,7 @@ func (k Keeper) DeleteAllowlist(ctx sdk.Context, chainID string) {
// IsAllowlistEmpty returns `true` if no validator is allowlisted on chain `chainID`
func (k Keeper) IsAllowlistEmpty(ctx sdk.Context, chainID string) bool {
store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.AllowlistPrefix, chainID))
iterator := storetypes.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.MustGetKeyPrefix(types.AllowlistKeyName), chainID))
defer iterator.Close()

return !iterator.Valid()
Expand All @@ -1497,7 +1498,7 @@ func (k Keeper) GetDenyList(
chainID string,
) (providerConsAddresses []types.ProviderConsAddress) {
store := ctx.KVStore(k.storeKey)
key := types.ChainIdWithLenKey(types.DenylistPrefix, chainID)
key := types.ChainIdWithLenKey(types.MustGetKeyPrefix(types.DenylistKeyName), chainID)
iterator := storetypes.KVStorePrefixIterator(store, key)
defer iterator.Close()

Expand All @@ -1522,7 +1523,7 @@ func (k Keeper) IsDenylisted(
// DeleteDenylist deletes all denylisted validators
func (k Keeper) DeleteDenylist(ctx sdk.Context, chainID string) {
store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.DenylistPrefix, chainID))
iterator := storetypes.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.MustGetKeyPrefix(types.DenylistKeyName), chainID))
defer iterator.Close()

keysToDel := [][]byte{}
Expand All @@ -1538,7 +1539,7 @@ func (k Keeper) DeleteDenylist(ctx sdk.Context, chainID string) {
// IsDenylistEmpty returns `true` if no validator is denylisted on chain `chainID`
func (k Keeper) IsDenylistEmpty(ctx sdk.Context, chainID string) bool {
store := ctx.KVStore(k.storeKey)
iterator := storetypes.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.DenylistPrefix, chainID))
iterator := storetypes.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.MustGetKeyPrefix(types.DenylistKeyName), chainID))
defer iterator.Close()

return !iterator.Valid()
Expand Down
Loading
Loading