Skip to content

Commit

Permalink
feat! use protos to serialize opted-in validators (#1659)
Browse files Browse the repository at this point in the history
move OptedInValidators to proto

Co-authored-by: insumity <karolos@informal.systems>
  • Loading branch information
sainoe and insumity committed Mar 12, 2024
1 parent ab7236d commit 71315ef
Show file tree
Hide file tree
Showing 8 changed files with 501 additions and 170 deletions.
13 changes: 13 additions & 0 deletions proto/interchain_security/ccv/provider/v1/provider.proto
Original file line number Diff line number Diff line change
Expand Up @@ -326,3 +326,16 @@ message ConsumerRewardsAllocation {
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.DecCoins"
];
}

// OptedInValidator is used to store a opted-in validator
// to a consumer chain with the following mapping: (chainID, providerAddr) -> optedInValidator
message OptedInValidator {
// validator address
bytes provider_addr = 1;
// block height at which the validator opted-in
int64 block_height = 2;
// validator voting power at the block it opted-in
int64 power = 3;
// public key used by the validator on the consumer
bytes public_key = 4;
}
9 changes: 6 additions & 3 deletions x/ccv/provider/keeper/distribution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,12 @@ func TestComputeConsumerTotalVotingPower(t *testing.T) {
keeper.SetOptedIn(
ctx,
chainID,
types.NewProviderConsAddress(sdk.ConsAddress(val.Address)),
0,
types.OptedInValidator{
ProviderAddr: val.Address,
BlockHeight: ctx.BlockHeight(),
Power: val.VotingPower,
PublicKey: val.PubKey.Bytes(),
},
)

validatorsVotes = append(
Expand All @@ -65,7 +69,6 @@ func TestComputeConsumerTotalVotingPower(t *testing.T) {
}

func TestIdentifyConsumerChainIDFromIBCPacket(t *testing.T) {

var (
chainID = "consumer"
ccvChannel = "channel-0"
Expand Down
38 changes: 21 additions & 17 deletions x/ccv/provider/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -1189,16 +1189,15 @@ func (k Keeper) IsOptIn(ctx sdk.Context, chainID string) bool {
func (k Keeper) SetOptedIn(
ctx sdk.Context,
chainID string,
providerAddr types.ProviderConsAddress,
blockHeight uint64,
validator types.OptedInValidator,
) {
store := ctx.KVStore(k.storeKey)
bz, err := validator.Marshal()
if err != nil {
panic(fmt.Errorf("failed to marshal OptedInValidator: %w", err))
}

// validator is considered opted in
blockHeightBytes := make([]byte, 8)
binary.BigEndian.PutUint64(blockHeightBytes, blockHeight)

store.Set(types.OptedInKey(chainID, providerAddr), blockHeightBytes)
store.Set(types.OptedInKey(chainID, validator.ProviderAddr), bz)
}

func (k Keeper) DeleteOptedIn(
Expand All @@ -1207,7 +1206,7 @@ func (k Keeper) DeleteOptedIn(
providerAddr types.ProviderConsAddress,
) {
store := ctx.KVStore(k.storeKey)
store.Delete(types.OptedInKey(chainID, providerAddr))
store.Delete(types.OptedInKey(chainID, providerAddr.ToSdkConsAddr()))
}

func (k Keeper) IsOptedIn(
Expand All @@ -1216,22 +1215,25 @@ func (k Keeper) IsOptedIn(
providerAddr types.ProviderConsAddress,
) bool {
store := ctx.KVStore(k.storeKey)
return store.Get(types.OptedInKey(chainID, providerAddr)) != nil
return store.Get(types.OptedInKey(chainID, providerAddr.ToSdkConsAddr())) != nil
}

func (k Keeper) GetOptedIn(
// GetAllOptedIn returns all the opted-in validators on chain `chainID`
func (k Keeper) GetAllOptedIn(
ctx sdk.Context,
chainID string) (optedInValidators []OptedInValidator) {
chainID string) (optedInValidators []types.OptedInValidator) {
store := ctx.KVStore(k.storeKey)
key := types.ChainIdWithLenKey(types.OptedInBytePrefix, chainID)
iterator := sdk.KVStorePrefixIterator(store, key)
defer iterator.Close()

for ; iterator.Valid(); iterator.Next() {
optedInValidators = append(optedInValidators, OptedInValidator{
ProviderAddr: types.NewProviderConsAddress(iterator.Key()[len(key):]),
BlockHeight: binary.BigEndian.Uint64(iterator.Value()),
})
iterator.Value()
var optedInValidator types.OptedInValidator
if err := optedInValidator.Unmarshal(iterator.Value()); err != nil {
panic(fmt.Errorf("failed to unmarshal OptedInValidator: %w", err))
}
optedInValidators = append(optedInValidators, optedInValidator)
}

return optedInValidators
Expand Down Expand Up @@ -1264,7 +1266,8 @@ func (k Keeper) IsToBeOptedIn(
return store.Get(types.ToBeOptedInKey(chainID, providerAddr)) != nil
}

func (k Keeper) GetToBeOptedIn(
// GetAllToBeOptedIn returns all the to-be-opted-in validators on chain `chainID`
func (k Keeper) GetAllToBeOptedIn(
ctx sdk.Context,
chainID string) (addresses []types.ProviderConsAddress) {

Expand Down Expand Up @@ -1308,7 +1311,8 @@ func (k Keeper) IsToBeOptedOut(
return store.Get(types.ToBeOptedOutKey(chainID, providerAddr)) != nil
}

func (k Keeper) GetToBeOptedOut(
// GetAllToBeOptedOut returns all the to-be-opted-out validators on chain `chainID`
func (k Keeper) GetAllToBeOptedOut(
ctx sdk.Context,
chainID string) (addresses []types.ProviderConsAddress) {

Expand Down
56 changes: 33 additions & 23 deletions x/ccv/provider/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package keeper_test
import (
"bytes"
"fmt"
"github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper"
"sort"
"testing"
"time"
Expand Down Expand Up @@ -662,39 +661,49 @@ func TestTopN(t *testing.T) {
}
}

func TestGetOptedIn(t *testing.T) {
func TestGetAllOptedIn(t *testing.T) {
providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
defer ctrl.Finish()

expectedOptedInValidators := []keeper.OptedInValidator{
expectedOptedInValidators := []types.OptedInValidator{
{
ProviderAddr: types.NewProviderConsAddress([]byte("providerAddr1")),
ProviderAddr: []byte("providerAddr1"),
BlockHeight: 1,
Power: 2,
PublicKey: []byte{3},
},
{
ProviderAddr: types.NewProviderConsAddress([]byte("providerAddr2")),
ProviderAddr: []byte("providerAddr2"),
BlockHeight: 2,
Power: 3,
PublicKey: []byte{4},
},
{
ProviderAddr: types.NewProviderConsAddress([]byte("providerAddr3")),
ProviderAddr: []byte("providerAddr3"),
BlockHeight: 3,
Power: 4,
PublicKey: []byte{5},
},
}

for _, expectedOptedInValidator := range expectedOptedInValidators {
providerKeeper.SetOptedIn(ctx, "chainID",
expectedOptedInValidator.ProviderAddr, expectedOptedInValidator.BlockHeight)
types.OptedInValidator{
ProviderAddr: expectedOptedInValidator.ProviderAddr,
BlockHeight: expectedOptedInValidator.BlockHeight,
Power: expectedOptedInValidator.Power,
PublicKey: expectedOptedInValidator.PublicKey})
}

actualOptedInValidators := providerKeeper.GetOptedIn(ctx, "chainID")
actualOptedInValidators := providerKeeper.GetAllOptedIn(ctx, "chainID")

// sort validators first to be able to compare
sortOptedInValidators := func(optedInValidators []keeper.OptedInValidator) {
sortOptedInValidators := func(optedInValidators []types.OptedInValidator) {
sort.Slice(optedInValidators, func(i int, j int) bool {
a := optedInValidators[i]
b := optedInValidators[j]
return a.BlockHeight < b.BlockHeight ||
(a.BlockHeight == b.BlockHeight && bytes.Compare(a.ProviderAddr.ToSdkConsAddr(), b.ProviderAddr.ToSdkConsAddr()) < 0)
(a.BlockHeight == b.BlockHeight && bytes.Compare(a.ProviderAddr, b.ProviderAddr) < 0)
})
}
sortOptedInValidators(expectedOptedInValidators)
Expand All @@ -707,19 +716,20 @@ func TestOptedIn(t *testing.T) {
providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
defer ctrl.Finish()

optedInValidator := keeper.OptedInValidator{
ProviderAddr: types.NewProviderConsAddress([]byte("providerAddr")),
BlockHeight: 1,
optedInValidator := types.OptedInValidator{ProviderAddr: []byte("providerAddr"),
BlockHeight: 1,
Power: 2,
PublicKey: []byte{3},
}

require.False(t, providerKeeper.IsOptedIn(ctx, "chainID", optedInValidator.ProviderAddr))
providerKeeper.SetOptedIn(ctx, "chainID", optedInValidator.ProviderAddr, optedInValidator.BlockHeight)
require.True(t, providerKeeper.IsOptedIn(ctx, "chainID", optedInValidator.ProviderAddr))
providerKeeper.DeleteOptedIn(ctx, "chainID", optedInValidator.ProviderAddr)
require.False(t, providerKeeper.IsOptedIn(ctx, "chainID", optedInValidator.ProviderAddr))
require.False(t, providerKeeper.IsOptedIn(ctx, "chainID", types.NewProviderConsAddress(optedInValidator.ProviderAddr)))
providerKeeper.SetOptedIn(ctx, "chainID", optedInValidator)
require.True(t, providerKeeper.IsOptedIn(ctx, "chainID", types.NewProviderConsAddress(optedInValidator.ProviderAddr)))
providerKeeper.DeleteOptedIn(ctx, "chainID", types.NewProviderConsAddress(optedInValidator.ProviderAddr))
require.False(t, providerKeeper.IsOptedIn(ctx, "chainID", types.NewProviderConsAddress(optedInValidator.ProviderAddr)))
}

func TestGetToBeOptedIn(t *testing.T) {
func TestGetAllToBeOptedIn(t *testing.T) {
providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
defer ctrl.Finish()

Expand All @@ -732,7 +742,7 @@ func TestGetToBeOptedIn(t *testing.T) {
providerKeeper.SetToBeOptedIn(ctx, "chainID", addr)
}

actualAddresses := providerKeeper.GetToBeOptedIn(ctx, "chainID")
actualAddresses := providerKeeper.GetAllToBeOptedIn(ctx, "chainID")

// sort addresses first to be able to compare
sortAddresses := func(addresses []types.ProviderConsAddress) {
Expand Down Expand Up @@ -766,7 +776,7 @@ func TestBeOptedIn(t *testing.T) {
providerKeeper.SetToBeOptedIn(ctx, "chainID", addr)
}

actualAddresses := providerKeeper.GetToBeOptedIn(ctx, "chainID")
actualAddresses := providerKeeper.GetAllToBeOptedIn(ctx, "chainID")

// sort addresses first to be able to compare
sortAddresses := func(addresses []types.ProviderConsAddress) {
Expand Down Expand Up @@ -801,7 +811,7 @@ func TestToBeOptedIn(t *testing.T) {
require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr))
}

func TestGetToBeOptedOut(t *testing.T) {
func TestGetAllToBeOptedOut(t *testing.T) {
providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
defer ctrl.Finish()

Expand All @@ -814,7 +824,7 @@ func TestGetToBeOptedOut(t *testing.T) {
providerKeeper.SetToBeOptedOut(ctx, "chainID", addr)
}

actualAddresses := providerKeeper.GetToBeOptedOut(ctx, "chainID")
actualAddresses := providerKeeper.GetAllToBeOptedOut(ctx, "chainID")

// sort addresses first to be able to compare
sortAddresses := func(addresses []types.ProviderConsAddress) {
Expand Down
6 changes: 0 additions & 6 deletions x/ccv/provider/keeper/partial_set_security.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,6 @@ import (
"github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
)

type OptedInValidator struct {
ProviderAddr types.ProviderConsAddress
// block height the validator opted in at
BlockHeight uint64
}

func (k Keeper) HandleOptIn(ctx sdk.Context, chainID string, providerAddr types.ProviderConsAddress, consumerKey *string) error {
if !k.IsConsumerProposedOrRegistered(ctx, chainID) {
return errorsmod.Wrapf(
Expand Down
7 changes: 5 additions & 2 deletions x/ccv/provider/keeper/partial_set_security_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package keeper_test

import (
"testing"

codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand All @@ -10,7 +12,6 @@ import (
ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"
"testing"
)

func TestHandleOptIn(t *testing.T) {
Expand All @@ -32,7 +33,9 @@ func TestHandleOptIn(t *testing.T) {
require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", providerAddr))

// if validator (`providerAddr`) is already opted in, then the validator cannot be opted in
providerKeeper.SetOptedIn(ctx, "chainID", providerAddr, 1)

providerKeeper.SetOptedIn(ctx, "chainID",
types.OptedInValidator{ProviderAddr: providerAddr.ToSdkConsAddr(), BlockHeight: 1, Power: 1, PublicKey: []byte{1}})
providerKeeper.HandleOptIn(ctx, "chainID", providerAddr, nil)
require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr))
}
Expand Down
4 changes: 2 additions & 2 deletions x/ccv/provider/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -547,9 +547,9 @@ func TopNKey(chainID string) []byte {
}

// OptedInKey returns the key of consumer chain `chainID` and validator with `providerAddr`
func OptedInKey(chainID string, providerAddr ProviderConsAddress) []byte {
func OptedInKey(chainID string, providerAddr []byte) []byte {
prefix := ChainIdWithLenKey(OptedInBytePrefix, chainID)
return append(prefix, providerAddr.ToSdkConsAddr().Bytes()...)
return append(prefix, providerAddr...)
}

// ToBeOptedInKey returns the key of consumer chain `chainID` and validator with `providerAddr`
Expand Down
Loading

0 comments on commit 71315ef

Please sign in to comment.