From 4eac8bf0d93c2a6ff7453dd5d54c3695323f11a0 Mon Sep 17 00:00:00 2001 From: insumity Date: Mon, 5 Feb 2024 11:57:20 +0100 Subject: [PATCH 1/8] init commit --- .../ccv/provider/v1/tx.proto | 27 +++ x/ccv/provider/client/cli/tx.go | 87 ++++++++ x/ccv/provider/keeper/keeper.go | 140 ++++++++++++- x/ccv/provider/keeper/keeper_test.go | 191 +++++++++++++++++- x/ccv/provider/keeper/msg_server.go | 59 ++++++ x/ccv/provider/keeper/partial_set_security.go | 36 ++++ .../keeper/partial_set_security_test.go | 48 +++++ x/ccv/provider/types/codec.go | 10 +- x/ccv/provider/types/keys.go | 30 +++ x/ccv/provider/types/keys_test.go | 3 + x/ccv/provider/types/msg.go | 113 +++++++++++ x/ccv/types/events.go | 2 + 12 files changed, 743 insertions(+), 3 deletions(-) create mode 100644 x/ccv/provider/keeper/partial_set_security.go create mode 100644 x/ccv/provider/keeper/partial_set_security_test.go diff --git a/proto/interchain_security/ccv/provider/v1/tx.proto b/proto/interchain_security/ccv/provider/v1/tx.proto index 3294807015..66530dfda4 100644 --- a/proto/interchain_security/ccv/provider/v1/tx.proto +++ b/proto/interchain_security/ccv/provider/v1/tx.proto @@ -15,6 +15,8 @@ service Msg { rpc AssignConsumerKey(MsgAssignConsumerKey) returns (MsgAssignConsumerKeyResponse); rpc SubmitConsumerMisbehaviour(MsgSubmitConsumerMisbehaviour) returns (MsgSubmitConsumerMisbehaviourResponse); rpc SubmitConsumerDoubleVoting(MsgSubmitConsumerDoubleVoting) returns (MsgSubmitConsumerDoubleVotingResponse); + rpc OptIn(MsgOptIn) returns (MsgOptInResponse); + rpc OptOut(MsgOptOut) returns (MsgOptOutResponse); } message MsgAssignConsumerKey { @@ -61,3 +63,28 @@ message MsgSubmitConsumerDoubleVoting { } message MsgSubmitConsumerDoubleVotingResponse {} + +message MsgOptIn { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + // the chain id of the consumer chain to opt in to + string chain_id = 1; + // the validator address on the provider + string provider_addr = 2 [ (gogoproto.moretags) = "yaml:\"address\"" ]; + // the consensus public key to use on the consumer in json string format corresponding to proto-any, + // for example `{"@type":"/cosmos.crypto.ed25519.PubKey","key":"Ui5Gf1+mtWUdH8u3xlmzdKID+F3PK0sfXZ73GZ6q6is="}` + string consumerKey = 3; +} + +message MsgOptInResponse {} + +message MsgOptOut { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + // the chain id of the consumer chain to opt out from + string chain_id = 1; + // the validator address on the provider + string provider_addr = 2 [ (gogoproto.moretags) = "yaml:\"address\"" ]; +} + +message MsgOptOutResponse {} \ No newline at end of file diff --git a/x/ccv/provider/client/cli/tx.go b/x/ccv/provider/client/cli/tx.go index 379e55a792..6a6da64387 100644 --- a/x/ccv/provider/client/cli/tx.go +++ b/x/ccv/provider/client/cli/tx.go @@ -34,6 +34,8 @@ func GetTxCmd() *cobra.Command { cmd.AddCommand(NewAssignConsumerKeyCmd()) cmd.AddCommand(NewSubmitConsumerMisbehaviourCmd()) cmd.AddCommand(NewSubmitConsumerDoubleVotingCmd()) + cmd.AddCommand(NewOptInCmd()) + cmd.AddCommand(NewOptOutCmd()) return cmd } @@ -202,3 +204,88 @@ Example: return cmd } + +func NewOptInCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "opt-in [consumer-chain-id] [consumer-pubkey]", + Short: "opts in validator to the consumer chain, and if given uses the " + + "provided consensus public key for this consumer chain", + Args: cobra.RangeArgs(1, 2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + txf, err := tx.NewFactoryCLI(clientCtx, cmd.Flags()) + if err != nil { + return err + } + txf = txf.WithTxConfig(clientCtx.TxConfig).WithAccountRetriever(clientCtx.AccountRetriever) + + providerValAddr := clientCtx.GetFromAddress() + + var consumerPubKey types.MsgOptIn_ConsumerKey + if len(args) == 2 { + // consumer public key was provided + consumerPubKey = types.MsgOptIn_ConsumerKey{ConsumerKey: args[1]} + } else { + consumerPubKey = types.MsgOptIn_ConsumerKey{} + } + msg, err := types.NewMsgOptIn(args[0], sdk.ValAddress(providerValAddr), consumerPubKey) + + if err != nil { + return err + } + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxWithFactory(clientCtx, txf, msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + _ = cmd.MarkFlagRequired(flags.FlagFrom) + + return cmd +} + +func NewOptOutCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "opt-out [consumer-chain-id]", + Short: "opts out validator from this consumer chain", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + txf, err := tx.NewFactoryCLI(clientCtx, cmd.Flags()) + if err != nil { + return err + } + txf = txf.WithTxConfig(clientCtx.TxConfig).WithAccountRetriever(clientCtx.AccountRetriever) + + providerValAddr := clientCtx.GetFromAddress() + + msg, err := types.NewMsgOptOut(args[0], sdk.ValAddress(providerValAddr)) + if err != nil { + return err + } + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxWithFactory(clientCtx, txf, msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + _ = cmd.MarkFlagRequired(flags.FlagFrom) + + return cmd +} diff --git a/x/ccv/provider/keeper/keeper.go b/x/ccv/provider/keeper/keeper.go index 1a7fe69ee5..bd26d6b87d 100644 --- a/x/ccv/provider/keeper/keeper.go +++ b/x/ccv/provider/keeper/keeper.go @@ -1160,7 +1160,7 @@ func (k Keeper) DeleteTopN( store.Delete(types.TopNKey(chainID)) } -// GetTopN returns (N, true) if chain `chainID` has a top N associated, and (0, false) otherwise. +// GetTopN returns (N, true) if chain `chainID` has a top N associated, and (0, false) otherwise. func (k Keeper) GetTopN( ctx sdk.Context, chainID string, @@ -1184,3 +1184,141 @@ func (k Keeper) IsOptIn(ctx sdk.Context, chainID string) bool { topN, found := k.GetTopN(ctx, chainID) return !found || topN == 0 } +func (k Keeper) SetOptedIn( + ctx sdk.Context, + chainID string, + providerAddr types.ProviderConsAddress, + blockHeight uint64, +) { + store := ctx.KVStore(k.storeKey) + + // validator is considered opted in + blockHeightBytes := make([]byte, 8) + binary.BigEndian.PutUint64(blockHeightBytes, blockHeight) + + store.Set(types.OptedInKey(chainID, providerAddr), blockHeightBytes) +} + +func (k Keeper) DeleteOptedIn( + ctx sdk.Context, + chainID string, + providerAddr types.ProviderConsAddress, +) { + store := ctx.KVStore(k.storeKey) + store.Delete(types.OptedInKey(chainID, providerAddr)) +} + +func (k Keeper) IsOptedIn( + ctx sdk.Context, + chainID string, + providerAddr types.ProviderConsAddress, +) bool { + store := ctx.KVStore(k.storeKey) + return store.Get(types.OptedInKey(chainID, providerAddr)) != nil +} + +func (k Keeper) GetOptedIn( + ctx sdk.Context, + chainID string) (optedInValidators []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()), + }) + } + + return optedInValidators +} + +func (k Keeper) SetToBeOptedIn( + ctx sdk.Context, + chainID string, + providerAddr types.ProviderConsAddress, +) { + store := ctx.KVStore(k.storeKey) + store.Set(types.ToBeOptedInKey(chainID, providerAddr), []byte{}) +} + +func (k Keeper) DeleteToBeOptedIn( + ctx sdk.Context, + chainID string, + providerAddr types.ProviderConsAddress, +) { + store := ctx.KVStore(k.storeKey) + store.Delete(types.ToBeOptedInKey(chainID, providerAddr)) +} + +func (k Keeper) IsToBeOptedIn( + ctx sdk.Context, + chainID string, + providerAddr types.ProviderConsAddress, +) bool { + store := ctx.KVStore(k.storeKey) + return store.Get(types.ToBeOptedInKey(chainID, providerAddr)) != nil +} + +func (k Keeper) GetToBeOptedIn( + ctx sdk.Context, + chainID string) (addresses []types.ProviderConsAddress) { + + store := ctx.KVStore(k.storeKey) + key := types.ChainIdWithLenKey(types.ToBeOptedInBytePrefix, chainID) + iterator := sdk.KVStorePrefixIterator(store, key) + defer iterator.Close() + + for ; iterator.Valid(); iterator.Next() { + providerAddr := types.NewProviderConsAddress(iterator.Key()[len(key):]) + addresses = append(addresses, providerAddr) + } + + return addresses +} + +func (k Keeper) SetToBeOptedOut( + ctx sdk.Context, + chainID string, + providerAddr types.ProviderConsAddress, +) { + store := ctx.KVStore(k.storeKey) + store.Set(types.ToBeOptedOutKey(chainID, providerAddr), []byte{}) +} + +func (k Keeper) DeleteToBeOptedOut( + ctx sdk.Context, + chainID string, + providerAddr types.ProviderConsAddress, +) { + store := ctx.KVStore(k.storeKey) + store.Delete(types.ToBeOptedOutKey(chainID, providerAddr)) +} + +func (k Keeper) IsToBeOptedOut( + ctx sdk.Context, + chainID string, + providerAddr types.ProviderConsAddress, +) bool { + store := ctx.KVStore(k.storeKey) + return store.Get(types.ToBeOptedOutKey(chainID, providerAddr)) != nil +} + +func (k Keeper) GetToBeOptedOut( + ctx sdk.Context, + chainID string) (addresses []types.ProviderConsAddress) { + + store := ctx.KVStore(k.storeKey) + key := types.ChainIdWithLenKey(types.ToBeOptedOutBytePrefix, chainID) + iterator := sdk.KVStorePrefixIterator(store, key) + defer iterator.Close() + + for ; iterator.Valid(); iterator.Next() { + providerAddr := types.NewProviderConsAddress(iterator.Key()[len(key):]) + addresses = append(addresses, providerAddr) + } + + return addresses +} diff --git a/x/ccv/provider/keeper/keeper_test.go b/x/ccv/provider/keeper/keeper_test.go index 4dc73b7f9e..6eb28675ba 100644 --- a/x/ccv/provider/keeper/keeper_test.go +++ b/x/ccv/provider/keeper/keeper_test.go @@ -1,7 +1,9 @@ package keeper_test import ( + "bytes" "fmt" + "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper" "sort" "testing" "time" @@ -629,7 +631,7 @@ func TestGetAllProposedConsumerChainIDs(t *testing.T) { } } -// TestTopN tests `SetTopN`, `GetTopN`, `IsTopN`, and `IsOptIn` methods +// TestTopN tests the `SetTopN`, `GetTopN`, `IsTopN`, and `IsOptIn` methods func TestTopN(t *testing.T) { providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() @@ -659,3 +661,190 @@ func TestTopN(t *testing.T) { } } } + +func TestGetOptedIn(t *testing.T) { + providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) + defer ctrl.Finish() + + expectedOptedInValidators := []keeper.OptedInValidator{ + { + ProviderAddr: types.NewProviderConsAddress([]byte("providerAddr1")), + BlockHeight: 1, + }, + { + ProviderAddr: types.NewProviderConsAddress([]byte("providerAddr2")), + BlockHeight: 2, + }, + { + ProviderAddr: types.NewProviderConsAddress([]byte("providerAddr3")), + BlockHeight: 3, + }, + } + + for _, expectedOptedInValidator := range expectedOptedInValidators { + providerKeeper.SetOptedIn(ctx, "chainID", + expectedOptedInValidator.ProviderAddr, expectedOptedInValidator.BlockHeight) + } + + actualOptedInValidators := providerKeeper.GetOptedIn(ctx, "chainID") + + // sort validators first to be able to compare + sortOptedInValidators := func(optedInValidators []keeper.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) + }) + } + sortOptedInValidators(expectedOptedInValidators) + sortOptedInValidators(actualOptedInValidators) + require.Equal(t, expectedOptedInValidators, actualOptedInValidators) +} + +// TestOptedIn tests the `SetOptedIn`, `IsOptedIn`, and `RemoveOptedIn` methods +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, + } + + 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)) +} + +func TestGetToBeOptedIn(t *testing.T) { + providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) + defer ctrl.Finish() + + expectedAddresses := []types.ProviderConsAddress{ + types.NewProviderConsAddress([]byte("providerAddr1")), + types.NewProviderConsAddress([]byte("providerAddr2")), + types.NewProviderConsAddress([]byte("providerAddr3"))} + + for _, addr := range expectedAddresses { + providerKeeper.SetToBeOptedIn(ctx, "chainID", addr) + } + + actualAddresses := providerKeeper.GetToBeOptedIn(ctx, "chainID") + + // sort addresses first to be able to compare + sortAddresses := func(addresses []types.ProviderConsAddress) { + sort.Slice(addresses, func(i int, j int) bool { + a := addresses[i] + b := addresses[j] + return bytes.Compare(a.Address.Bytes(), b.Address.Bytes()) < 0 + }) + } + sortAddresses(expectedAddresses) + sortAddresses(actualAddresses) + require.Equal(t, expectedAddresses, actualAddresses) + + for _, addr := range expectedAddresses { + require.True(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", addr)) + providerKeeper.DeleteToBeOptedIn(ctx, "chainID", addr) + require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", addr)) + } +} + +func TestBeOptedIn(t *testing.T) { + providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) + defer ctrl.Finish() + + expectedAddresses := []types.ProviderConsAddress{ + types.NewProviderConsAddress([]byte("providerAddr1")), + types.NewProviderConsAddress([]byte("providerAddr2")), + types.NewProviderConsAddress([]byte("providerAddr3"))} + + for _, addr := range expectedAddresses { + providerKeeper.SetToBeOptedIn(ctx, "chainID", addr) + } + + actualAddresses := providerKeeper.GetToBeOptedIn(ctx, "chainID") + + // sort addresses first to be able to compare + sortAddresses := func(addresses []types.ProviderConsAddress) { + sort.Slice(addresses, func(i int, j int) bool { + a := addresses[i] + b := addresses[j] + return bytes.Compare(a.Address.Bytes(), b.Address.Bytes()) < 0 + }) + } + sortAddresses(expectedAddresses) + sortAddresses(actualAddresses) + require.Equal(t, expectedAddresses, actualAddresses) + + for _, addr := range expectedAddresses { + require.True(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", addr)) + providerKeeper.DeleteToBeOptedIn(ctx, "chainID", addr) + require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", addr)) + } +} + +// TestToBeOptedIn tests the `SetToBeOptedIn`, `IsToBeOptedIn`, and `DeleteToBeOptedIn` methods +func TestToBeOptedIn(t *testing.T) { + providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) + defer ctrl.Finish() + + providerAddr := types.NewProviderConsAddress([]byte("providerAddr1")) + + require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) + providerKeeper.SetToBeOptedIn(ctx, "chainID", providerAddr) + require.True(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) + providerKeeper.DeleteToBeOptedIn(ctx, "chainID", providerAddr) + require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) +} + +func TestGetToBeOptedOut(t *testing.T) { + providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) + defer ctrl.Finish() + + expectedAddresses := []types.ProviderConsAddress{ + types.NewProviderConsAddress([]byte("providerAddr1")), + types.NewProviderConsAddress([]byte("providerAddr2")), + types.NewProviderConsAddress([]byte("providerAddr3"))} + + for _, addr := range expectedAddresses { + providerKeeper.SetToBeOptedOut(ctx, "chainID", addr) + } + + actualAddresses := providerKeeper.GetToBeOptedOut(ctx, "chainID") + + // sort addresses first to be able to compare + sortAddresses := func(addresses []types.ProviderConsAddress) { + sort.Slice(addresses, func(i int, j int) bool { + a := addresses[i] + b := addresses[j] + return bytes.Compare(a.Address.Bytes(), b.Address.Bytes()) < 0 + }) + } + sortAddresses(expectedAddresses) + sortAddresses(actualAddresses) + require.Equal(t, expectedAddresses, actualAddresses) + + for _, addr := range expectedAddresses { + require.True(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", addr)) + providerKeeper.DeleteToBeOptedOut(ctx, "chainID", addr) + require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", addr)) + } +} + +// TestToBeOptedOut tests the `SetToBeOptedOut`, `IsToBeOptedOut`, and `DeleteToBeOptedOut` methods +func TestToBeOptedOut(t *testing.T) { + providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) + defer ctrl.Finish() + + providerAddr := types.NewProviderConsAddress([]byte("providerAddr1")) + + require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", providerAddr)) + providerKeeper.SetToBeOptedOut(ctx, "chainID", providerAddr) + require.True(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", providerAddr)) + providerKeeper.DeleteToBeOptedOut(ctx, "chainID", providerAddr) + require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", providerAddr)) +} diff --git a/x/ccv/provider/keeper/msg_server.go b/x/ccv/provider/keeper/msg_server.go index 9a27d1d144..7cac362a04 100644 --- a/x/ccv/provider/keeper/msg_server.go +++ b/x/ccv/provider/keeper/msg_server.go @@ -174,3 +174,62 @@ func (k msgServer) SubmitConsumerDoubleVoting(goCtx context.Context, msg *types. return &types.MsgSubmitConsumerDoubleVotingResponse{}, nil } + +func (k msgServer) OptIn(goCtx context.Context, msg *types.MsgOptIn) (*types.MsgOptInResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + valAddress, err := sdk.ConsAddressFromBech32(msg.ProviderAddr) + if err != nil { + return nil, err + } + providerAddr := types.NewProviderConsAddress(valAddress) + if err != nil { + return nil, err + } + + if msg.ConsumerKey != "" { + k.Keeper.HandleOptIn(ctx, msg.ChainId, providerAddr, &msg.ConsumerKey) + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + ccvtypes.EventTypeOptIn, + sdk.NewAttribute(types.AttributeProviderValidatorAddress, msg.ProviderAddr), + sdk.NewAttribute(types.AttributeConsumerConsensusPubKey, msg.ConsumerKey), + ), + }) + } else { + k.Keeper.HandleOptIn(ctx, msg.ChainId, providerAddr, nil) + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + ccvtypes.EventTypeOptIn, + sdk.NewAttribute(types.AttributeProviderValidatorAddress, msg.ProviderAddr), + ), + }) + } + + return &types.MsgOptInResponse{}, nil +} + +func (k msgServer) OptOut(goCtx context.Context, msg *types.MsgOptOut) (*types.MsgOptOutResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + valAddress, err := sdk.ConsAddressFromBech32(msg.ProviderAddr) + if err != nil { + return nil, err + } + providerAddr := types.NewProviderConsAddress(valAddress) + if err != nil { + return nil, err + } + + k.Keeper.HandleOptOut(ctx, msg.ChainId, providerAddr) + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + ccvtypes.EventTypeOptOut, + sdk.NewAttribute(types.AttributeProviderValidatorAddress, msg.ProviderAddr), + ), + }) + + return &types.MsgOptOutResponse{}, nil +} diff --git a/x/ccv/provider/keeper/partial_set_security.go b/x/ccv/provider/keeper/partial_set_security.go new file mode 100644 index 0000000000..1251eda372 --- /dev/null +++ b/x/ccv/provider/keeper/partial_set_security.go @@ -0,0 +1,36 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "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) { + if k.IsToBeOptedOut(ctx, chainID, providerAddr) { + // a validator to be opted in cancels out with a validator to be opted out + k.DeleteToBeOptedOut(ctx, chainID, providerAddr) + } else if !k.IsToBeOptedIn(ctx, chainID, providerAddr) && !k.IsOptedIn(ctx, chainID, providerAddr) { + // a validator can only be set for opt in if it is not opted in and not already set for opt in + k.SetToBeOptedIn(ctx, chainID, providerAddr) + } + + if consumerKey != nil { + // TODO: assign consumer key in this case + } +} + +func (k Keeper) HandleOptOut(ctx sdk.Context, chainID string, providerAddr types.ProviderConsAddress) { + if k.IsToBeOptedIn(ctx, chainID, providerAddr) { + // a validator to be opted out cancels out a validator to be opted in + k.DeleteToBeOptedIn(ctx, chainID, providerAddr) + } else if !k.IsToBeOptedOut(ctx, chainID, providerAddr) && k.IsOptedIn(ctx, chainID, providerAddr) { + // a validator can only be set for opt out if it is opted in and not already set for opt out + k.SetToBeOptedOut(ctx, chainID, providerAddr) + } +} diff --git a/x/ccv/provider/keeper/partial_set_security_test.go b/x/ccv/provider/keeper/partial_set_security_test.go new file mode 100644 index 0000000000..34e99f61f9 --- /dev/null +++ b/x/ccv/provider/keeper/partial_set_security_test.go @@ -0,0 +1,48 @@ +package keeper_test + +import ( + testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper" + "github.com/cosmos/interchain-security/v4/x/ccv/provider/types" + "github.com/stretchr/testify/require" + "testing" +) + +func TestHandleOptIn(t *testing.T) { + providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) + defer ctrl.Finish() + + providerAddr := types.NewProviderConsAddress([]byte("providerAddr")) + + // if validator (`providerAddr`) is to be opted out, then we cancel that the validator is about + // to be opted out and do not consider the validator to opt in + providerKeeper.SetToBeOptedOut(ctx, "chainID", providerAddr) + require.True(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", providerAddr)) + providerKeeper.HandleOptIn(ctx, "chainID", providerAddr, nil) + require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) + 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.HandleOptIn(ctx, "chainID", providerAddr, nil) + require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) +} + +func TestHandleOptOut(t *testing.T) { + providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) + defer ctrl.Finish() + + providerAddr := types.NewProviderConsAddress([]byte("providerAddr")) + + // if validator (`providerAddr`) is to be opted in, then we cancel that the validator is about + // to be opted out and do not consider the validator to opt out + providerKeeper.SetToBeOptedIn(ctx, "chainID", providerAddr) + require.True(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) + providerKeeper.HandleOptOut(ctx, "chainID", providerAddr) + require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", providerAddr)) + require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) + + // if validator (`providerAddr`) is not opted in, then the validator cannot be opted out + providerKeeper.DeleteOptedIn(ctx, "chainID", providerAddr) + providerKeeper.HandleOptOut(ctx, "chainID", providerAddr) + require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", providerAddr)) +} diff --git a/x/ccv/provider/types/codec.go b/x/ccv/provider/types/codec.go index 6ab621f0e1..a24121a010 100644 --- a/x/ccv/provider/types/codec.go +++ b/x/ccv/provider/types/codec.go @@ -11,7 +11,7 @@ import ( ) // RegisterLegacyAminoCodec registers the necessary x/ibc transfer interfaces and concrete types -// on the provided LegacyAmino codec. These types are used for Amino JSON serialization. +// on the provided `LegacyAmino codec. These types are used for Amino JSON serialization. func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { } @@ -45,6 +45,14 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) { (*sdk.Msg)(nil), &MsgSubmitConsumerDoubleVoting{}, ) + registry.RegisterImplementations( + (*sdk.Msg)(nil), + &MsgOptIn{}, + ) + registry.RegisterImplementations( + (*sdk.Msg)(nil), + &MsgOptOut{}, + ) registry.RegisterImplementations( (*exported.ClientMessage)(nil), &tendermint.Misbehaviour{}, diff --git a/x/ccv/provider/types/keys.go b/x/ccv/provider/types/keys.go index 47ad0417b2..0eee530bea 100644 --- a/x/ccv/provider/types/keys.go +++ b/x/ccv/provider/types/keys.go @@ -148,6 +148,18 @@ const ( // TopNBytePrefix is the byte prefix storing the mapping from a consumer chain to the N value of this chain, // that corresponds to the N% of the top validators that have to validate this consumer chain TopNBytePrefix + + // OptedInBytePrefix is the byte prefix used when storing for each consumer chain all the opted in validators + OptedInBytePrefix = 31 + + // ToBeOptedInBytePrefix is the byte prefix used when storing for each consumer chain the validators that + // are about to be opted in + ToBeOptedInBytePrefix = 32 + + // ToBeOptedOutBytePrefix is the byte prefix used when storing for each consumer chain the validators that + // are about to be opted out + ToBeOptedOutBytePrefix = 33 + // NOTE: DO NOT ADD NEW BYTE PREFIXES HERE WITHOUT ADDING THEM TO getAllKeyPrefixes() IN keys_test.go ) @@ -525,6 +537,24 @@ func TopNKey(chainID string) []byte { return ChainIdWithLenKey(TopNBytePrefix, chainID) } +// OptedInKey returns the key of consumer chain `chainID` and validator with `providerAddr` +func OptedInKey(chainID string, providerAddr ProviderConsAddress) []byte { + prefix := ChainIdWithLenKey(OptedInBytePrefix, chainID) + return append(prefix, providerAddr.ToSdkConsAddr().Bytes()...) +} + +// ToBeOptedInKey returns the key of consumer chain `chainID` and validator with `providerAddr` +func ToBeOptedInKey(chainID string, providerAddr ProviderConsAddress) []byte { + prefix := ChainIdWithLenKey(ToBeOptedInBytePrefix, chainID) + return append(prefix, providerAddr.ToSdkConsAddr().Bytes()...) +} + +// ToBeOptedOutKey returns the key of consumer chain `chainID` and validator with `providerAddr` +func ToBeOptedOutKey(chainID string, providerAddr ProviderConsAddress) []byte { + prefix := ChainIdWithLenKey(ToBeOptedOutBytePrefix, chainID) + return append(prefix, providerAddr.ToSdkConsAddr().Bytes()...) +} + // // End of generic helpers section // diff --git a/x/ccv/provider/types/keys_test.go b/x/ccv/provider/types/keys_test.go index f0f316bf75..62ca2b9fef 100644 --- a/x/ccv/provider/types/keys_test.go +++ b/x/ccv/provider/types/keys_test.go @@ -57,6 +57,9 @@ func getAllKeyPrefixes() []byte { providertypes.EquivocationEvidenceMinHeightBytePrefix, providertypes.ProposedConsumerChainByteKey, providertypes.TopNBytePrefix, + providertypes.OptedInBytePrefix, + providertypes.ToBeOptedInBytePrefix, + providertypes.ToBeOptedOutBytePrefix, } } diff --git a/x/ccv/provider/types/msg.go b/x/ccv/provider/types/msg.go index 55e6b2fae4..cc52b1f0aa 100644 --- a/x/ccv/provider/types/msg.go +++ b/x/ccv/provider/types/msg.go @@ -22,12 +22,16 @@ const ( TypeMsgAssignConsumerKey = "assign_consumer_key" TypeMsgSubmitConsumerMisbehaviour = "submit_consumer_misbehaviour" TypeMsgSubmitConsumerDoubleVoting = "submit_consumer_double_vote" + TypeMsgOptIn = "opt_in" + TypeMsgOptOut = "opt_out" ) var ( _ sdk.Msg = &MsgAssignConsumerKey{} _ sdk.Msg = &MsgSubmitConsumerMisbehaviour{} _ sdk.Msg = &MsgSubmitConsumerDoubleVoting{} + _ sdk.Msg = &MsgOptIn{} + _ sdk.Msg = &MsgOptOut{} ) // NewMsgAssignConsumerKey creates a new MsgAssignConsumerKey instance. @@ -203,3 +207,112 @@ func (msg MsgSubmitConsumerDoubleVoting) GetSigners() []sdk.AccAddress { } return []sdk.AccAddress{addr} } + +// NewMsgOptIn creates a new NewMsgOptIn instance. +func NewMsgOptIn(chainID string, providerValidatorAddress sdk.ValAddress, consumerConsensusPubKey MsgOptIn_ConsumerKey) (*MsgOptIn, error) { + return &MsgOptIn{ + ChainId: chainID, + ProviderAddr: providerValidatorAddress.String(), + XConsumerKey: &consumerConsensusPubKey, + }, nil +} + +// Route implements the sdk.Msg interface. +func (msg MsgOptIn) Route() string { return RouterKey } + +// GetSigners implements the sdk.Msg interface. It returns the address(es) that +// must sign over msg.GetSignBytes(). +func (msg MsgOptIn) GetSigners() []sdk.AccAddress { + valAddr, err := sdk.ValAddressFromBech32(msg.ProviderAddr) + if err != nil { + // same behavior as in cosmos-sdk + panic(err) + } + return []sdk.AccAddress{valAddr.Bytes()} +} + +// GetSignBytes returns the message bytes to sign over. +func (msg MsgOptIn) GetSignBytes() []byte { + bz := ccvtypes.ModuleCdc.MustMarshalJSON(&msg) + return sdk.MustSortJSON(bz) +} + +// ValidateBasic implements the sdk.Msg interface. +func (msg MsgOptIn) ValidateBasic() error { + if strings.TrimSpace(msg.ChainId) == "" { + return errorsmod.Wrapf(ErrInvalidConsumerChainID, "chainId cannot be blank") + } + // It is possible to assign keys for consumer chains that are not yet approved. + // This can only be done by a signing validator, but it is still sensible + // to limit the chainID size to prevent abuse. + if 128 < len(msg.ChainId) { + return errorsmod.Wrapf(ErrInvalidConsumerChainID, "chainId cannot exceed 128 length") + } + _, err := sdk.ValAddressFromBech32(msg.ProviderAddr) + if err != nil { + return ErrInvalidProviderAddress + } + + if _, ok := msg.XConsumerKey.(*MsgOptIn_ConsumerKey); ok { + if _, _, err := ParseConsumerKeyFromJson(msg.GetConsumerKey()); err != nil { + return ErrInvalidConsumerConsensusPubKey + } + } + return nil +} + +// NewMsgOptOut creates a new NewMsgOptIn instance. +func NewMsgOptOut(chainID string, providerValidatorAddress sdk.ValAddress) (*MsgOptOut, error) { + return &MsgOptOut{ + ChainId: chainID, + ProviderAddr: providerValidatorAddress.String(), + }, nil +} + +// Route implements the sdk.Msg interface. +func (msg MsgOptOut) Route() string { return RouterKey } + +// Type implements the sdk.Msg interface. +func (msg MsgOptIn) Type() string { + return TypeMsgOptIn +} + +// GetSigners implements the sdk.Msg interface. It returns the address(es) that +// must sign over msg.GetSignBytes(). +func (msg MsgOptOut) GetSigners() []sdk.AccAddress { + valAddr, err := sdk.ValAddressFromBech32(msg.ProviderAddr) + if err != nil { + // same behavior as in cosmos-sdk + panic(err) + } + return []sdk.AccAddress{valAddr.Bytes()} +} + +// GetSignBytes returns the message bytes to sign over. +func (msg MsgOptOut) GetSignBytes() []byte { + bz := ccvtypes.ModuleCdc.MustMarshalJSON(&msg) + return sdk.MustSortJSON(bz) +} + +// ValidateBasic implements the sdk.Msg interface. +func (msg MsgOptOut) ValidateBasic() error { + if strings.TrimSpace(msg.ChainId) == "" { + return errorsmod.Wrapf(ErrInvalidConsumerChainID, "chainId cannot be blank") + } + // It is possible to assign keys for consumer chains that are not yet approved. + // This can only be done by a signing validator, but it is still sensible + // to limit the chainID size to prevent abuse. + if 128 < len(msg.ChainId) { + return errorsmod.Wrapf(ErrInvalidConsumerChainID, "chainId cannot exceed 128 length") + } + _, err := sdk.ValAddressFromBech32(msg.ProviderAddr) + if err != nil { + return ErrInvalidProviderAddress + } + return nil +} + +// Type implements the sdk.Msg interface. +func (msg MsgOptOut) Type() string { + return TypeMsgOptOut +} diff --git a/x/ccv/types/events.go b/x/ccv/types/events.go index 4c597ded56..2fa584dd40 100644 --- a/x/ccv/types/events.go +++ b/x/ccv/types/events.go @@ -12,6 +12,8 @@ const ( EventTypeRemoveConsumerRewardDenom = "remove_consumer_reward_denom" EventTypeSubmitConsumerMisbehaviour = "submit_consumer_misbehaviour" EventTypeSubmitConsumerDoubleVoting = "submit_consumer_double_voting" + EventTypeOptIn = "opt_in" + EventTypeOptOut = "opt_out" EventTypeExecuteConsumerChainSlash = "execute_consumer_chain_slash" EventTypeFeeDistribution = "fee_distribution" EventTypeConsumerSlashRequest = "consumer_slash_request" From 8f2269f525ec7f23ffb59eac170700821ca8b89b Mon Sep 17 00:00:00 2001 From: insumity Date: Mon, 5 Feb 2024 12:05:56 +0100 Subject: [PATCH 2/8] cleaning up --- .../ccv/provider/v1/tx.proto | 5 +- x/ccv/provider/client/cli/tx.go | 6 +- x/ccv/provider/types/codec.go | 2 +- x/ccv/provider/types/keys.go | 6 +- x/ccv/provider/types/msg.go | 8 +- x/ccv/provider/types/provider.pb.go | 8 +- x/ccv/provider/types/tx.pb.go | 875 +++++++++++++++++- 7 files changed, 845 insertions(+), 65 deletions(-) diff --git a/proto/interchain_security/ccv/provider/v1/tx.proto b/proto/interchain_security/ccv/provider/v1/tx.proto index 66530dfda4..51003bdf05 100644 --- a/proto/interchain_security/ccv/provider/v1/tx.proto +++ b/proto/interchain_security/ccv/provider/v1/tx.proto @@ -71,9 +71,10 @@ message MsgOptIn { string chain_id = 1; // the validator address on the provider string provider_addr = 2 [ (gogoproto.moretags) = "yaml:\"address\"" ]; - // the consensus public key to use on the consumer in json string format corresponding to proto-any, + // (optional) the consensus public key to use on the consumer in json string format corresponding to proto-any, // for example `{"@type":"/cosmos.crypto.ed25519.PubKey","key":"Ui5Gf1+mtWUdH8u3xlmzdKID+F3PK0sfXZ73GZ6q6is="}` - string consumerKey = 3; + // we can set `consumer_key = ""` if we do not consider the `consumer_key` + string consumer_key = 3; } message MsgOptInResponse {} diff --git a/x/ccv/provider/client/cli/tx.go b/x/ccv/provider/client/cli/tx.go index 6a6da64387..2d55b602dd 100644 --- a/x/ccv/provider/client/cli/tx.go +++ b/x/ccv/provider/client/cli/tx.go @@ -225,12 +225,12 @@ func NewOptInCmd() *cobra.Command { providerValAddr := clientCtx.GetFromAddress() - var consumerPubKey types.MsgOptIn_ConsumerKey + var consumerPubKey string if len(args) == 2 { // consumer public key was provided - consumerPubKey = types.MsgOptIn_ConsumerKey{ConsumerKey: args[1]} + consumerPubKey = args[1] } else { - consumerPubKey = types.MsgOptIn_ConsumerKey{} + consumerPubKey = "" } msg, err := types.NewMsgOptIn(args[0], sdk.ValAddress(providerValAddr), consumerPubKey) diff --git a/x/ccv/provider/types/codec.go b/x/ccv/provider/types/codec.go index a24121a010..c0ab4f5aea 100644 --- a/x/ccv/provider/types/codec.go +++ b/x/ccv/provider/types/codec.go @@ -11,7 +11,7 @@ import ( ) // RegisterLegacyAminoCodec registers the necessary x/ibc transfer interfaces and concrete types -// on the provided `LegacyAmino codec. These types are used for Amino JSON serialization. +// on the provided LegacyAmino codec. These types are used for Amino JSON serialization. func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { } diff --git a/x/ccv/provider/types/keys.go b/x/ccv/provider/types/keys.go index 0eee530bea..20824454cb 100644 --- a/x/ccv/provider/types/keys.go +++ b/x/ccv/provider/types/keys.go @@ -150,15 +150,15 @@ const ( TopNBytePrefix // OptedInBytePrefix is the byte prefix used when storing for each consumer chain all the opted in validators - OptedInBytePrefix = 31 + OptedInBytePrefix // ToBeOptedInBytePrefix is the byte prefix used when storing for each consumer chain the validators that // are about to be opted in - ToBeOptedInBytePrefix = 32 + ToBeOptedInBytePrefix // ToBeOptedOutBytePrefix is the byte prefix used when storing for each consumer chain the validators that // are about to be opted out - ToBeOptedOutBytePrefix = 33 + ToBeOptedOutBytePrefix // NOTE: DO NOT ADD NEW BYTE PREFIXES HERE WITHOUT ADDING THEM TO getAllKeyPrefixes() IN keys_test.go ) diff --git a/x/ccv/provider/types/msg.go b/x/ccv/provider/types/msg.go index cc52b1f0aa..20aae43f6c 100644 --- a/x/ccv/provider/types/msg.go +++ b/x/ccv/provider/types/msg.go @@ -209,11 +209,11 @@ func (msg MsgSubmitConsumerDoubleVoting) GetSigners() []sdk.AccAddress { } // NewMsgOptIn creates a new NewMsgOptIn instance. -func NewMsgOptIn(chainID string, providerValidatorAddress sdk.ValAddress, consumerConsensusPubKey MsgOptIn_ConsumerKey) (*MsgOptIn, error) { +func NewMsgOptIn(chainID string, providerValidatorAddress sdk.ValAddress, consumerConsensusPubKey string) (*MsgOptIn, error) { return &MsgOptIn{ ChainId: chainID, ProviderAddr: providerValidatorAddress.String(), - XConsumerKey: &consumerConsensusPubKey, + ConsumerKey: consumerConsensusPubKey, }, nil } @@ -253,8 +253,8 @@ func (msg MsgOptIn) ValidateBasic() error { return ErrInvalidProviderAddress } - if _, ok := msg.XConsumerKey.(*MsgOptIn_ConsumerKey); ok { - if _, _, err := ParseConsumerKeyFromJson(msg.GetConsumerKey()); err != nil { + if msg.ConsumerKey != "" { + if _, _, err := ParseConsumerKeyFromJson(msg.ConsumerKey); err != nil { return ErrInvalidConsumerConsensusPubKey } } diff --git a/x/ccv/provider/types/provider.pb.go b/x/ccv/provider/types/provider.pb.go index edea9f4e02..fd9d63bc7e 100644 --- a/x/ccv/provider/types/provider.pb.go +++ b/x/ccv/provider/types/provider.pb.go @@ -90,10 +90,10 @@ type ConsumerAdditionProposal struct { // chain. it is most relevant for chains performing a sovereign to consumer // changeover in order to maintain the existing ibc transfer channel DistributionTransmissionChannel string `protobuf:"bytes,14,opt,name=distribution_transmission_channel,json=distributionTransmissionChannel,proto3" json:"distribution_transmission_channel,omitempty"` - // Corresponds to the percentage of validators that join under the Top N case. - // For example, 53 corresponds to a Top 53% chain, meaning that the top 53% provider validators - // have to validate the proposed consumer chain. top_N can be 0 or include any value in [50, 100]. - // A chain can join with top_N == 0 as an Opt In, or with top_N ∈ [50, 100] as a Top N chain. + // Corresponds to the percentage of validators that have to validate the chain under the Top N case. + // For example, 53 corresponds to a Top 53% chain, meaning that the top 53% provider validators by voting power + // have to validate the proposed consumer chain. top_N can either be 0 or any value in [50, 100]. + // A chain can join with top_N == 0 as an Opt In chain, or with top_N ∈ [50, 100] as a Top N chain. Top_N uint32 `protobuf:"varint,15,opt,name=top_N,json=topN,proto3" json:"top_N,omitempty"` } diff --git a/x/ccv/provider/types/tx.pb.go b/x/ccv/provider/types/tx.pb.go index f72e95acb2..647f5f49dc 100644 --- a/x/ccv/provider/types/tx.pb.go +++ b/x/ccv/provider/types/tx.pb.go @@ -270,6 +270,162 @@ func (m *MsgSubmitConsumerDoubleVotingResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgSubmitConsumerDoubleVotingResponse proto.InternalMessageInfo +type MsgOptIn struct { + // the chain id of the consumer chain to opt in to + ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + // the validator address on the provider + ProviderAddr string `protobuf:"bytes,2,opt,name=provider_addr,json=providerAddr,proto3" json:"provider_addr,omitempty" yaml:"address"` + // (optional) the consensus public key to use on the consumer in json string format corresponding to proto-any, + // for example `{"@type":"/cosmos.crypto.ed25519.PubKey","key":"Ui5Gf1+mtWUdH8u3xlmzdKID+F3PK0sfXZ73GZ6q6is="}` + // we can set `consumer_key = ""` if we do not consider the `consumer_key` + ConsumerKey string `protobuf:"bytes,3,opt,name=consumer_key,json=consumerKey,proto3" json:"consumer_key,omitempty"` +} + +func (m *MsgOptIn) Reset() { *m = MsgOptIn{} } +func (m *MsgOptIn) String() string { return proto.CompactTextString(m) } +func (*MsgOptIn) ProtoMessage() {} +func (*MsgOptIn) Descriptor() ([]byte, []int) { + return fileDescriptor_43221a4391e9fbf4, []int{6} +} +func (m *MsgOptIn) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgOptIn) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgOptIn.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgOptIn) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgOptIn.Merge(m, src) +} +func (m *MsgOptIn) XXX_Size() int { + return m.Size() +} +func (m *MsgOptIn) XXX_DiscardUnknown() { + xxx_messageInfo_MsgOptIn.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgOptIn proto.InternalMessageInfo + +type MsgOptInResponse struct { +} + +func (m *MsgOptInResponse) Reset() { *m = MsgOptInResponse{} } +func (m *MsgOptInResponse) String() string { return proto.CompactTextString(m) } +func (*MsgOptInResponse) ProtoMessage() {} +func (*MsgOptInResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_43221a4391e9fbf4, []int{7} +} +func (m *MsgOptInResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgOptInResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgOptInResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgOptInResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgOptInResponse.Merge(m, src) +} +func (m *MsgOptInResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgOptInResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgOptInResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgOptInResponse proto.InternalMessageInfo + +type MsgOptOut struct { + // the chain id of the consumer chain to opt out from + ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + // the validator address on the provider + ProviderAddr string `protobuf:"bytes,2,opt,name=provider_addr,json=providerAddr,proto3" json:"provider_addr,omitempty" yaml:"address"` +} + +func (m *MsgOptOut) Reset() { *m = MsgOptOut{} } +func (m *MsgOptOut) String() string { return proto.CompactTextString(m) } +func (*MsgOptOut) ProtoMessage() {} +func (*MsgOptOut) Descriptor() ([]byte, []int) { + return fileDescriptor_43221a4391e9fbf4, []int{8} +} +func (m *MsgOptOut) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgOptOut) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgOptOut.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgOptOut) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgOptOut.Merge(m, src) +} +func (m *MsgOptOut) XXX_Size() int { + return m.Size() +} +func (m *MsgOptOut) XXX_DiscardUnknown() { + xxx_messageInfo_MsgOptOut.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgOptOut proto.InternalMessageInfo + +type MsgOptOutResponse struct { +} + +func (m *MsgOptOutResponse) Reset() { *m = MsgOptOutResponse{} } +func (m *MsgOptOutResponse) String() string { return proto.CompactTextString(m) } +func (*MsgOptOutResponse) ProtoMessage() {} +func (*MsgOptOutResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_43221a4391e9fbf4, []int{9} +} +func (m *MsgOptOutResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgOptOutResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgOptOutResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgOptOutResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgOptOutResponse.Merge(m, src) +} +func (m *MsgOptOutResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgOptOutResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgOptOutResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgOptOutResponse proto.InternalMessageInfo + func init() { proto.RegisterType((*MsgAssignConsumerKey)(nil), "interchain_security.ccv.provider.v1.MsgAssignConsumerKey") proto.RegisterType((*MsgAssignConsumerKeyResponse)(nil), "interchain_security.ccv.provider.v1.MsgAssignConsumerKeyResponse") @@ -277,6 +433,10 @@ func init() { proto.RegisterType((*MsgSubmitConsumerMisbehaviourResponse)(nil), "interchain_security.ccv.provider.v1.MsgSubmitConsumerMisbehaviourResponse") proto.RegisterType((*MsgSubmitConsumerDoubleVoting)(nil), "interchain_security.ccv.provider.v1.MsgSubmitConsumerDoubleVoting") proto.RegisterType((*MsgSubmitConsumerDoubleVotingResponse)(nil), "interchain_security.ccv.provider.v1.MsgSubmitConsumerDoubleVotingResponse") + proto.RegisterType((*MsgOptIn)(nil), "interchain_security.ccv.provider.v1.MsgOptIn") + proto.RegisterType((*MsgOptInResponse)(nil), "interchain_security.ccv.provider.v1.MsgOptInResponse") + proto.RegisterType((*MsgOptOut)(nil), "interchain_security.ccv.provider.v1.MsgOptOut") + proto.RegisterType((*MsgOptOutResponse)(nil), "interchain_security.ccv.provider.v1.MsgOptOutResponse") } func init() { @@ -284,46 +444,50 @@ func init() { } var fileDescriptor_43221a4391e9fbf4 = []byte{ - // 610 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xcf, 0x4f, 0xd4, 0x4e, - 0x14, 0xdf, 0x42, 0xf2, 0xfd, 0xc2, 0x80, 0x26, 0x36, 0x10, 0x60, 0x83, 0x5d, 0x5d, 0xa3, 0x78, - 0xc0, 0x99, 0x80, 0x26, 0x46, 0x12, 0x0f, 0xac, 0x98, 0xf8, 0x23, 0x9b, 0x98, 0x9a, 0x60, 0xe2, - 0xc1, 0xa6, 0x9d, 0x3e, 0xba, 0x13, 0xda, 0x99, 0xcd, 0xcc, 0xb4, 0xa1, 0xff, 0x01, 0x47, 0x3d, - 0x19, 0x6f, 0xfc, 0x01, 0xfe, 0x21, 0x1e, 0x39, 0x7a, 0x32, 0x06, 0x2e, 0x9e, 0xbd, 0x78, 0x35, - 0x3b, 0x6d, 0xd9, 0x12, 0x2b, 0x10, 0xbc, 0xf5, 0xbd, 0xf7, 0x79, 0xef, 0x7d, 0x3e, 0x6f, 0x5e, - 0x1f, 0x5a, 0x65, 0x5c, 0x83, 0xa4, 0x03, 0x9f, 0x71, 0x4f, 0x01, 0x4d, 0x25, 0xd3, 0x39, 0xa1, - 0x34, 0x23, 0x43, 0x29, 0x32, 0x16, 0x82, 0x24, 0xd9, 0x1a, 0xd1, 0x7b, 0x78, 0x28, 0x85, 0x16, - 0xf6, 0xad, 0x06, 0x34, 0xa6, 0x34, 0xc3, 0x15, 0x1a, 0x67, 0x6b, 0xed, 0xb9, 0x48, 0x44, 0xc2, - 0xe0, 0xc9, 0xe8, 0xab, 0x48, 0x6d, 0x2f, 0x51, 0xa1, 0x12, 0xa1, 0xbc, 0x22, 0x50, 0x18, 0x55, - 0x28, 0x12, 0x22, 0x8a, 0x81, 0x18, 0x2b, 0x48, 0x77, 0x88, 0xcf, 0xf3, 0x32, 0x44, 0x58, 0x40, - 0x49, 0xcc, 0xa2, 0x81, 0xa6, 0x31, 0x03, 0xae, 0x15, 0xd1, 0xc0, 0x43, 0x90, 0x09, 0xe3, 0xda, - 0x30, 0x3b, 0xb1, 0xca, 0x84, 0x4e, 0x2d, 0xae, 0xf3, 0x21, 0x28, 0x02, 0x23, 0x62, 0x9c, 0x42, - 0x01, 0xe8, 0x7e, 0xb4, 0xd0, 0x5c, 0x5f, 0x45, 0x9b, 0x4a, 0xb1, 0x88, 0x3f, 0x11, 0x5c, 0xa5, - 0x09, 0xc8, 0x97, 0x90, 0xdb, 0x4b, 0x68, 0xaa, 0x10, 0xc6, 0xc2, 0x45, 0xeb, 0x86, 0x75, 0x77, - 0xda, 0xfd, 0xdf, 0xd8, 0xcf, 0x43, 0xfb, 0x21, 0xba, 0x52, 0x09, 0xf4, 0xfc, 0x30, 0x94, 0x8b, - 0x13, 0xa3, 0x78, 0xcf, 0xfe, 0xf9, 0xad, 0x73, 0x35, 0xf7, 0x93, 0x78, 0xa3, 0x3b, 0xf2, 0x82, - 0x52, 0x5d, 0x77, 0xb6, 0x02, 0x6e, 0x86, 0xa1, 0xb4, 0x6f, 0xa2, 0x59, 0x5a, 0xb6, 0xf0, 0x76, - 0x21, 0x5f, 0x9c, 0x34, 0x75, 0x67, 0xe8, 0xb8, 0xed, 0xc6, 0xd4, 0xfe, 0x41, 0xa7, 0xf5, 0xe3, - 0xa0, 0xd3, 0xea, 0x3a, 0x68, 0xb9, 0x89, 0x98, 0x0b, 0x6a, 0x28, 0xb8, 0x82, 0xee, 0x27, 0x0b, - 0x5d, 0xef, 0xab, 0xe8, 0x75, 0x1a, 0x24, 0x4c, 0x57, 0x80, 0x3e, 0x53, 0x01, 0x0c, 0xfc, 0x8c, - 0x89, 0x54, 0xda, 0xcb, 0x68, 0x5a, 0x99, 0xa8, 0x06, 0x59, 0x6a, 0x18, 0x3b, 0xec, 0x57, 0x68, - 0x36, 0xa9, 0xa1, 0x8d, 0x88, 0x99, 0xf5, 0x55, 0xcc, 0x02, 0x8a, 0xeb, 0x23, 0xc6, 0xb5, 0xa1, - 0x66, 0x6b, 0xb8, 0xde, 0xc1, 0x3d, 0x55, 0xa1, 0xc6, 0x7d, 0x05, 0xdd, 0x3e, 0x93, 0xda, 0x89, - 0x88, 0xfd, 0x89, 0x06, 0x11, 0x5b, 0x22, 0x0d, 0x62, 0xd8, 0x16, 0x9a, 0xf1, 0xe8, 0x1c, 0x11, - 0x1e, 0x5a, 0x08, 0xd3, 0x61, 0xcc, 0xa8, 0xaf, 0xc1, 0xcb, 0x84, 0x06, 0xaf, 0x7a, 0xdf, 0x52, - 0xcf, 0x4a, 0x9d, 0xbe, 0xd9, 0x00, 0xbc, 0x55, 0x25, 0x6c, 0x0b, 0x0d, 0x4f, 0x4b, 0xb8, 0x3b, - 0x1f, 0x36, 0xb9, 0xed, 0x77, 0x68, 0x81, 0xf1, 0x1d, 0xe9, 0x53, 0xcd, 0x04, 0xf7, 0x82, 0x58, - 0xd0, 0x5d, 0x6f, 0x00, 0x7e, 0x08, 0xd2, 0xbc, 0xde, 0xcc, 0xfa, 0x9d, 0xf3, 0x06, 0xf6, 0xcc, - 0xa0, 0xdd, 0xf9, 0x71, 0x99, 0xde, 0xa8, 0x4a, 0xe1, 0x3e, 0x67, 0x66, 0xf5, 0x49, 0x54, 0x33, - 0x5b, 0xff, 0x35, 0x89, 0x26, 0xfb, 0x2a, 0xb2, 0x3f, 0x58, 0xe8, 0xda, 0x9f, 0x7b, 0xfb, 0x08, - 0x5f, 0xe0, 0xa7, 0xc4, 0x4d, 0x9b, 0xd5, 0xde, 0xbc, 0x74, 0x6a, 0xc5, 0xcd, 0xfe, 0x6c, 0xa1, - 0xf6, 0x19, 0x1b, 0xd9, 0xbb, 0x68, 0x87, 0xbf, 0xd7, 0x68, 0xbf, 0xf8, 0xf7, 0x1a, 0x67, 0xd0, - 0x3d, 0xb5, 0x7b, 0x97, 0xa4, 0x5b, 0xaf, 0x71, 0x59, 0xba, 0x4d, 0x2f, 0xdf, 0x7b, 0xf3, 0xe5, - 0xc8, 0xb1, 0x0e, 0x8f, 0x1c, 0xeb, 0xfb, 0x91, 0x63, 0xbd, 0x3f, 0x76, 0x5a, 0x87, 0xc7, 0x4e, - 0xeb, 0xeb, 0xb1, 0xd3, 0x7a, 0xfb, 0x38, 0x62, 0x7a, 0x90, 0x06, 0x98, 0x8a, 0xa4, 0x3c, 0xa6, - 0x64, 0xdc, 0xf6, 0xde, 0xc9, 0x25, 0xcf, 0x1e, 0x90, 0xbd, 0xd3, 0xe7, 0xdc, 0xfc, 0x12, 0xc1, - 0x7f, 0xe6, 0x18, 0xde, 0xff, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x74, 0xf3, 0x13, 0x1f, 0xff, 0x05, - 0x00, 0x00, + // 683 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x55, 0x4d, 0x4f, 0xd4, 0x40, + 0x18, 0xde, 0x42, 0x40, 0x18, 0xd0, 0x48, 0x85, 0x00, 0x1b, 0xec, 0xea, 0x1a, 0xc5, 0x03, 0xcc, + 0x04, 0xfc, 0x8a, 0x24, 0x1e, 0x58, 0x31, 0x11, 0xcd, 0x06, 0xb3, 0x26, 0x98, 0x78, 0xb0, 0x69, + 0xa7, 0x43, 0x77, 0x42, 0x3b, 0xd3, 0xcc, 0x4c, 0x1b, 0xf6, 0x1f, 0x90, 0x78, 0xd1, 0x93, 0xf1, + 0xc6, 0x0f, 0xf0, 0x87, 0x78, 0xe4, 0xc8, 0xc9, 0x18, 0xb8, 0x78, 0xf6, 0x17, 0x98, 0x9d, 0x7e, + 0x6c, 0x89, 0x2b, 0x5f, 0xc6, 0x78, 0xeb, 0xbc, 0xef, 0x33, 0xcf, 0xf3, 0xbc, 0x6f, 0xe7, 0x9d, + 0x01, 0x0b, 0x94, 0x29, 0x22, 0x70, 0xdb, 0xa1, 0xcc, 0x96, 0x04, 0xc7, 0x82, 0xaa, 0x0e, 0xc2, + 0x38, 0x41, 0x91, 0xe0, 0x09, 0xf5, 0x88, 0x40, 0xc9, 0x12, 0x52, 0x3b, 0x30, 0x12, 0x5c, 0x71, + 0xf3, 0x56, 0x1f, 0x34, 0xc4, 0x38, 0x81, 0x39, 0x1a, 0x26, 0x4b, 0xd5, 0x49, 0x9f, 0xfb, 0x5c, + 0xe3, 0x51, 0xf7, 0x2b, 0xdd, 0x5a, 0x9d, 0xc5, 0x5c, 0x86, 0x5c, 0xda, 0x69, 0x22, 0x5d, 0xe4, + 0x29, 0x9f, 0x73, 0x3f, 0x20, 0x48, 0xaf, 0xdc, 0x78, 0x0b, 0x39, 0xac, 0x93, 0xa5, 0x10, 0x75, + 0x31, 0x0a, 0xa8, 0xdf, 0x56, 0x38, 0xa0, 0x84, 0x29, 0x89, 0x14, 0x61, 0x1e, 0x11, 0x21, 0x65, + 0x4a, 0x3b, 0x2b, 0x56, 0xd9, 0x86, 0x5a, 0x29, 0xaf, 0x3a, 0x11, 0x91, 0x88, 0x74, 0x8d, 0x31, + 0x4c, 0x52, 0x40, 0xfd, 0x93, 0x01, 0x26, 0x9b, 0xd2, 0x5f, 0x95, 0x92, 0xfa, 0xec, 0x29, 0x67, + 0x32, 0x0e, 0x89, 0x78, 0x49, 0x3a, 0xe6, 0x2c, 0x18, 0x49, 0x0b, 0xa3, 0xde, 0x8c, 0x71, 0xc3, + 0xb8, 0x3b, 0xda, 0xba, 0xa4, 0xd7, 0xeb, 0x9e, 0xf9, 0x08, 0x5c, 0xce, 0x0b, 0xb4, 0x1d, 0xcf, + 0x13, 0x33, 0x03, 0xdd, 0x7c, 0xc3, 0xfc, 0xf9, 0xad, 0x76, 0xa5, 0xe3, 0x84, 0xc1, 0x4a, 0xbd, + 0x1b, 0x25, 0x52, 0xd6, 0x5b, 0xe3, 0x39, 0x70, 0xd5, 0xf3, 0x84, 0x79, 0x13, 0x8c, 0xe3, 0x4c, + 0xc2, 0xde, 0x26, 0x9d, 0x99, 0x41, 0xcd, 0x3b, 0x86, 0x7b, 0xb2, 0x2b, 0x23, 0xbb, 0x7b, 0xb5, + 0xca, 0x8f, 0xbd, 0x5a, 0xa5, 0x6e, 0x81, 0xb9, 0x7e, 0xc6, 0x5a, 0x44, 0x46, 0x9c, 0x49, 0x52, + 0xff, 0x6c, 0x80, 0xeb, 0x4d, 0xe9, 0xbf, 0x8e, 0xdd, 0x90, 0xaa, 0x1c, 0xd0, 0xa4, 0xd2, 0x25, + 0x6d, 0x27, 0xa1, 0x3c, 0x16, 0xe6, 0x1c, 0x18, 0x95, 0x3a, 0xab, 0x88, 0xc8, 0x6a, 0xe8, 0x05, + 0xcc, 0x57, 0x60, 0x3c, 0x2c, 0xa1, 0x75, 0x11, 0x63, 0xcb, 0x0b, 0x90, 0xba, 0x18, 0x96, 0x5b, + 0x0c, 0x4b, 0x4d, 0x4d, 0x96, 0x60, 0x59, 0xa1, 0x75, 0x8c, 0xa1, 0xe4, 0x7d, 0x1e, 0xdc, 0x3e, + 0xd1, 0x5a, 0x51, 0xc4, 0xee, 0x40, 0x9f, 0x22, 0xd6, 0x78, 0xec, 0x06, 0x64, 0x93, 0x2b, 0xca, + 0xfc, 0x53, 0x8a, 0xb0, 0xc1, 0xb4, 0x17, 0x47, 0x01, 0xc5, 0x8e, 0x22, 0x76, 0xc2, 0x15, 0xb1, + 0xf3, 0xff, 0x9b, 0xd5, 0x33, 0x5f, 0xb6, 0xaf, 0x4f, 0x00, 0x5c, 0xcb, 0x37, 0x6c, 0x72, 0x45, + 0x9e, 0x65, 0xf0, 0xd6, 0x94, 0xd7, 0x2f, 0x6c, 0xbe, 0x03, 0xd3, 0x94, 0x6d, 0x09, 0x07, 0x2b, + 0xca, 0x99, 0xed, 0x06, 0x1c, 0x6f, 0xdb, 0x6d, 0xe2, 0x78, 0x44, 0xe8, 0xbf, 0x37, 0xb6, 0x7c, + 0xe7, 0xb4, 0x86, 0x3d, 0xd7, 0xe8, 0xd6, 0x54, 0x8f, 0xa6, 0xd1, 0x65, 0x49, 0xc3, 0xa7, 0xf4, + 0xac, 0xdc, 0x89, 0xa2, 0x67, 0xef, 0x0d, 0x30, 0xd2, 0x94, 0xfe, 0x46, 0xa4, 0xd6, 0xd9, 0xff, + 0x3f, 0xa6, 0x26, 0xb8, 0x9a, 0x9b, 0x29, 0x1c, 0x52, 0x30, 0x9a, 0xc6, 0x36, 0x62, 0xf5, 0x2f, + 0x1c, 0x96, 0xe4, 0xaf, 0x81, 0x89, 0x42, 0x2a, 0xd7, 0x5f, 0x3e, 0x18, 0x02, 0x83, 0x4d, 0xe9, + 0x9b, 0x1f, 0x0d, 0x30, 0xf1, 0xfb, 0x64, 0x3f, 0x86, 0x67, 0xb8, 0xb6, 0x60, 0xbf, 0xd9, 0xab, + 0xae, 0x5e, 0x78, 0x6b, 0xee, 0xcd, 0xfc, 0x62, 0x80, 0xea, 0x09, 0x33, 0xdb, 0x38, 0xab, 0xc2, + 0x9f, 0x39, 0xaa, 0x2f, 0xfe, 0x9e, 0xe3, 0x04, 0xbb, 0xc7, 0xa6, 0xf3, 0x82, 0x76, 0xcb, 0x1c, + 0x17, 0xb5, 0xdb, 0x6f, 0x36, 0xcc, 0x10, 0x0c, 0xa5, 0x73, 0xb1, 0x78, 0x56, 0x52, 0x0d, 0xaf, + 0x3e, 0x38, 0x17, 0xbc, 0x90, 0x8b, 0xc0, 0x70, 0x76, 0xca, 0xe1, 0x39, 0x08, 0x36, 0x62, 0x55, + 0x7d, 0x78, 0x3e, 0x7c, 0xae, 0xd8, 0x78, 0xf3, 0xf5, 0xd0, 0x32, 0xf6, 0x0f, 0x2d, 0xe3, 0xfb, + 0xa1, 0x65, 0x7c, 0x38, 0xb2, 0x2a, 0xfb, 0x47, 0x56, 0xe5, 0xe0, 0xc8, 0xaa, 0xbc, 0x7d, 0xe2, + 0x53, 0xd5, 0x8e, 0x5d, 0x88, 0x79, 0x98, 0xbd, 0xa7, 0xa8, 0x27, 0xb1, 0x58, 0x3c, 0xe6, 0xc9, + 0x7d, 0xb4, 0x73, 0xfc, 0x45, 0xd7, 0xb7, 0xa2, 0x3b, 0xac, 0xdf, 0xc3, 0x7b, 0xbf, 0x02, 0x00, + 0x00, 0xff, 0xff, 0x3b, 0x47, 0x43, 0x85, 0x02, 0x08, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -341,6 +505,8 @@ type MsgClient interface { AssignConsumerKey(ctx context.Context, in *MsgAssignConsumerKey, opts ...grpc.CallOption) (*MsgAssignConsumerKeyResponse, error) SubmitConsumerMisbehaviour(ctx context.Context, in *MsgSubmitConsumerMisbehaviour, opts ...grpc.CallOption) (*MsgSubmitConsumerMisbehaviourResponse, error) SubmitConsumerDoubleVoting(ctx context.Context, in *MsgSubmitConsumerDoubleVoting, opts ...grpc.CallOption) (*MsgSubmitConsumerDoubleVotingResponse, error) + OptIn(ctx context.Context, in *MsgOptIn, opts ...grpc.CallOption) (*MsgOptInResponse, error) + OptOut(ctx context.Context, in *MsgOptOut, opts ...grpc.CallOption) (*MsgOptOutResponse, error) } type msgClient struct { @@ -378,11 +544,31 @@ func (c *msgClient) SubmitConsumerDoubleVoting(ctx context.Context, in *MsgSubmi return out, nil } +func (c *msgClient) OptIn(ctx context.Context, in *MsgOptIn, opts ...grpc.CallOption) (*MsgOptInResponse, error) { + out := new(MsgOptInResponse) + err := c.cc.Invoke(ctx, "/interchain_security.ccv.provider.v1.Msg/OptIn", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) OptOut(ctx context.Context, in *MsgOptOut, opts ...grpc.CallOption) (*MsgOptOutResponse, error) { + out := new(MsgOptOutResponse) + err := c.cc.Invoke(ctx, "/interchain_security.ccv.provider.v1.Msg/OptOut", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { AssignConsumerKey(context.Context, *MsgAssignConsumerKey) (*MsgAssignConsumerKeyResponse, error) SubmitConsumerMisbehaviour(context.Context, *MsgSubmitConsumerMisbehaviour) (*MsgSubmitConsumerMisbehaviourResponse, error) SubmitConsumerDoubleVoting(context.Context, *MsgSubmitConsumerDoubleVoting) (*MsgSubmitConsumerDoubleVotingResponse, error) + OptIn(context.Context, *MsgOptIn) (*MsgOptInResponse, error) + OptOut(context.Context, *MsgOptOut) (*MsgOptOutResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -398,6 +584,12 @@ func (*UnimplementedMsgServer) SubmitConsumerMisbehaviour(ctx context.Context, r func (*UnimplementedMsgServer) SubmitConsumerDoubleVoting(ctx context.Context, req *MsgSubmitConsumerDoubleVoting) (*MsgSubmitConsumerDoubleVotingResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method SubmitConsumerDoubleVoting not implemented") } +func (*UnimplementedMsgServer) OptIn(ctx context.Context, req *MsgOptIn) (*MsgOptInResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method OptIn not implemented") +} +func (*UnimplementedMsgServer) OptOut(ctx context.Context, req *MsgOptOut) (*MsgOptOutResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method OptOut not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -457,6 +649,42 @@ func _Msg_SubmitConsumerDoubleVoting_Handler(srv interface{}, ctx context.Contex return interceptor(ctx, in, info, handler) } +func _Msg_OptIn_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgOptIn) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).OptIn(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/interchain_security.ccv.provider.v1.Msg/OptIn", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).OptIn(ctx, req.(*MsgOptIn)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_OptOut_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgOptOut) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).OptOut(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/interchain_security.ccv.provider.v1.Msg/OptOut", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).OptOut(ctx, req.(*MsgOptOut)) + } + return interceptor(ctx, in, info, handler) +} + var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "interchain_security.ccv.provider.v1.Msg", HandlerType: (*MsgServer)(nil), @@ -473,6 +701,14 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "SubmitConsumerDoubleVoting", Handler: _Msg_SubmitConsumerDoubleVoting_Handler, }, + { + MethodName: "OptIn", + Handler: _Msg_OptIn_Handler, + }, + { + MethodName: "OptOut", + Handler: _Msg_OptOut_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "interchain_security/ccv/provider/v1/tx.proto", @@ -687,6 +923,133 @@ func (m *MsgSubmitConsumerDoubleVotingResponse) MarshalToSizedBuffer(dAtA []byte return len(dAtA) - i, nil } +func (m *MsgOptIn) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgOptIn) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgOptIn) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ConsumerKey) > 0 { + i -= len(m.ConsumerKey) + copy(dAtA[i:], m.ConsumerKey) + i = encodeVarintTx(dAtA, i, uint64(len(m.ConsumerKey))) + i-- + dAtA[i] = 0x1a + } + if len(m.ProviderAddr) > 0 { + i -= len(m.ProviderAddr) + copy(dAtA[i:], m.ProviderAddr) + i = encodeVarintTx(dAtA, i, uint64(len(m.ProviderAddr))) + i-- + dAtA[i] = 0x12 + } + if len(m.ChainId) > 0 { + i -= len(m.ChainId) + copy(dAtA[i:], m.ChainId) + i = encodeVarintTx(dAtA, i, uint64(len(m.ChainId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgOptInResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgOptInResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgOptInResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgOptOut) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgOptOut) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgOptOut) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ProviderAddr) > 0 { + i -= len(m.ProviderAddr) + copy(dAtA[i:], m.ProviderAddr) + i = encodeVarintTx(dAtA, i, uint64(len(m.ProviderAddr))) + i-- + dAtA[i] = 0x12 + } + if len(m.ChainId) > 0 { + i -= len(m.ChainId) + copy(dAtA[i:], m.ChainId) + i = encodeVarintTx(dAtA, i, uint64(len(m.ChainId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgOptOutResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgOptOutResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgOptOutResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + func encodeVarintTx(dAtA []byte, offset int, v uint64) int { offset -= sovTx(v) base := offset @@ -784,14 +1147,70 @@ func (m *MsgSubmitConsumerDoubleVotingResponse) Size() (n int) { return n } -func sovTx(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozTx(x uint64) (n int) { - return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *MsgAssignConsumerKey) Unmarshal(dAtA []byte) error { - l := len(dAtA) +func (m *MsgOptIn) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ChainId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ProviderAddr) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ConsumerKey) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgOptInResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgOptOut) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ChainId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ProviderAddr) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgOptOutResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgAssignConsumerKey) Unmarshal(dAtA []byte) error { + l := len(dAtA) iNdEx := 0 for iNdEx < l { preIndex := iNdEx @@ -1358,6 +1777,366 @@ func (m *MsgSubmitConsumerDoubleVotingResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgOptIn) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgOptIn: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgOptIn: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProviderAddr", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ProviderAddr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsumerKey", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ConsumerKey = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgOptInResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgOptInResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgOptInResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgOptOut) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgOptOut: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgOptOut: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProviderAddr", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ProviderAddr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgOptOutResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgOptOutResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgOptOutResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipTx(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 From a32e8829fee3cbbe50e363a0aa91ad62117a8a1d Mon Sep 17 00:00:00 2001 From: insumity Date: Mon, 5 Feb 2024 16:34:43 +0100 Subject: [PATCH 3/8] changed cons to val address --- x/ccv/provider/keeper/keeper.go | 54 ++++---- x/ccv/provider/keeper/keeper_test.go | 117 ++++++------------ x/ccv/provider/keeper/key_assignment_test.go | 4 +- x/ccv/provider/keeper/msg_server.go | 18 +-- x/ccv/provider/keeper/partial_set_security.go | 23 ++-- .../keeper/partial_set_security_test.go | 49 ++++---- x/ccv/provider/types/keys.go | 12 +- x/ccv/provider/types/provider.pb.go | 6 +- x/ccv/provider/types/tx.pb.go | 6 +- 9 files changed, 120 insertions(+), 169 deletions(-) diff --git a/x/ccv/provider/keeper/keeper.go b/x/ccv/provider/keeper/keeper.go index bd26d6b87d..816683279d 100644 --- a/x/ccv/provider/keeper/keeper.go +++ b/x/ccv/provider/keeper/keeper.go @@ -1187,7 +1187,7 @@ func (k Keeper) IsOptIn(ctx sdk.Context, chainID string) bool { func (k Keeper) SetOptedIn( ctx sdk.Context, chainID string, - providerAddr types.ProviderConsAddress, + valAddress sdk.ValAddress, blockHeight uint64, ) { store := ctx.KVStore(k.storeKey) @@ -1196,25 +1196,25 @@ func (k Keeper) SetOptedIn( blockHeightBytes := make([]byte, 8) binary.BigEndian.PutUint64(blockHeightBytes, blockHeight) - store.Set(types.OptedInKey(chainID, providerAddr), blockHeightBytes) + store.Set(types.OptedInKey(chainID, valAddress), blockHeightBytes) } func (k Keeper) DeleteOptedIn( ctx sdk.Context, chainID string, - providerAddr types.ProviderConsAddress, + valAddress sdk.ValAddress, ) { store := ctx.KVStore(k.storeKey) - store.Delete(types.OptedInKey(chainID, providerAddr)) + store.Delete(types.OptedInKey(chainID, valAddress)) } func (k Keeper) IsOptedIn( ctx sdk.Context, chainID string, - providerAddr types.ProviderConsAddress, + valAddress sdk.ValAddress, ) bool { store := ctx.KVStore(k.storeKey) - return store.Get(types.OptedInKey(chainID, providerAddr)) != nil + return store.Get(types.OptedInKey(chainID, valAddress)) != nil } func (k Keeper) GetOptedIn( @@ -1227,8 +1227,8 @@ func (k Keeper) GetOptedIn( for ; iterator.Valid(); iterator.Next() { optedInValidators = append(optedInValidators, OptedInValidator{ - ProviderAddr: types.NewProviderConsAddress(iterator.Key()[len(key):]), - BlockHeight: binary.BigEndian.Uint64(iterator.Value()), + ValAddress: iterator.Key()[len(key):], + BlockHeight: binary.BigEndian.Uint64(iterator.Value()), }) } @@ -1238,33 +1238,33 @@ func (k Keeper) GetOptedIn( func (k Keeper) SetToBeOptedIn( ctx sdk.Context, chainID string, - providerAddr types.ProviderConsAddress, + valAddress sdk.ValAddress, ) { store := ctx.KVStore(k.storeKey) - store.Set(types.ToBeOptedInKey(chainID, providerAddr), []byte{}) + store.Set(types.ToBeOptedInKey(chainID, valAddress), []byte{}) } func (k Keeper) DeleteToBeOptedIn( ctx sdk.Context, chainID string, - providerAddr types.ProviderConsAddress, + valAddress sdk.ValAddress, ) { store := ctx.KVStore(k.storeKey) - store.Delete(types.ToBeOptedInKey(chainID, providerAddr)) + store.Delete(types.ToBeOptedInKey(chainID, valAddress)) } func (k Keeper) IsToBeOptedIn( ctx sdk.Context, chainID string, - providerAddr types.ProviderConsAddress, + valAddress sdk.ValAddress, ) bool { store := ctx.KVStore(k.storeKey) - return store.Get(types.ToBeOptedInKey(chainID, providerAddr)) != nil + return store.Get(types.ToBeOptedInKey(chainID, valAddress)) != nil } func (k Keeper) GetToBeOptedIn( ctx sdk.Context, - chainID string) (addresses []types.ProviderConsAddress) { + chainID string) (valAddresses []sdk.ValAddress) { store := ctx.KVStore(k.storeKey) key := types.ChainIdWithLenKey(types.ToBeOptedInBytePrefix, chainID) @@ -1272,43 +1272,42 @@ func (k Keeper) GetToBeOptedIn( defer iterator.Close() for ; iterator.Valid(); iterator.Next() { - providerAddr := types.NewProviderConsAddress(iterator.Key()[len(key):]) - addresses = append(addresses, providerAddr) + valAddresses = append(valAddresses, iterator.Key()[len(key):]) } - return addresses + return valAddresses } func (k Keeper) SetToBeOptedOut( ctx sdk.Context, chainID string, - providerAddr types.ProviderConsAddress, + valAddress sdk.ValAddress, ) { store := ctx.KVStore(k.storeKey) - store.Set(types.ToBeOptedOutKey(chainID, providerAddr), []byte{}) + store.Set(types.ToBeOptedOutKey(chainID, valAddress), []byte{}) } func (k Keeper) DeleteToBeOptedOut( ctx sdk.Context, chainID string, - providerAddr types.ProviderConsAddress, + valAddress sdk.ValAddress, ) { store := ctx.KVStore(k.storeKey) - store.Delete(types.ToBeOptedOutKey(chainID, providerAddr)) + store.Delete(types.ToBeOptedOutKey(chainID, valAddress)) } func (k Keeper) IsToBeOptedOut( ctx sdk.Context, chainID string, - providerAddr types.ProviderConsAddress, + valAddress sdk.ValAddress, ) bool { store := ctx.KVStore(k.storeKey) - return store.Get(types.ToBeOptedOutKey(chainID, providerAddr)) != nil + return store.Get(types.ToBeOptedOutKey(chainID, valAddress)) != nil } func (k Keeper) GetToBeOptedOut( ctx sdk.Context, - chainID string) (addresses []types.ProviderConsAddress) { + chainID string) (valAddresses []sdk.ValAddress) { store := ctx.KVStore(k.storeKey) key := types.ChainIdWithLenKey(types.ToBeOptedOutBytePrefix, chainID) @@ -1316,9 +1315,8 @@ func (k Keeper) GetToBeOptedOut( defer iterator.Close() for ; iterator.Valid(); iterator.Next() { - providerAddr := types.NewProviderConsAddress(iterator.Key()[len(key):]) - addresses = append(addresses, providerAddr) + valAddresses = append(valAddresses, iterator.Key()[len(key):]) } - return addresses + return valAddresses } diff --git a/x/ccv/provider/keeper/keeper_test.go b/x/ccv/provider/keeper/keeper_test.go index 6eb28675ba..685df27191 100644 --- a/x/ccv/provider/keeper/keeper_test.go +++ b/x/ccv/provider/keeper/keeper_test.go @@ -3,6 +3,7 @@ package keeper_test import ( "bytes" "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper" "sort" "testing" @@ -668,22 +669,22 @@ func TestGetOptedIn(t *testing.T) { expectedOptedInValidators := []keeper.OptedInValidator{ { - ProviderAddr: types.NewProviderConsAddress([]byte("providerAddr1")), - BlockHeight: 1, + ValAddress: []byte("valAddr1"), + BlockHeight: 1, }, { - ProviderAddr: types.NewProviderConsAddress([]byte("providerAddr2")), - BlockHeight: 2, + ValAddress: []byte("valAddr2"), + BlockHeight: 2, }, { - ProviderAddr: types.NewProviderConsAddress([]byte("providerAddr3")), - BlockHeight: 3, + ValAddress: []byte("valAddr3"), + BlockHeight: 3, }, } for _, expectedOptedInValidator := range expectedOptedInValidators { providerKeeper.SetOptedIn(ctx, "chainID", - expectedOptedInValidator.ProviderAddr, expectedOptedInValidator.BlockHeight) + expectedOptedInValidator.ValAddress, expectedOptedInValidator.BlockHeight) } actualOptedInValidators := providerKeeper.GetOptedIn(ctx, "chainID") @@ -694,7 +695,7 @@ func TestGetOptedIn(t *testing.T) { 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.ValAddress, b.ValAddress) < 0) }) } sortOptedInValidators(expectedOptedInValidators) @@ -708,25 +709,25 @@ func TestOptedIn(t *testing.T) { defer ctrl.Finish() optedInValidator := keeper.OptedInValidator{ - ProviderAddr: types.NewProviderConsAddress([]byte("providerAddr")), - BlockHeight: 1, + ValAddress: []byte("valAddr"), + BlockHeight: 1, } - 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", optedInValidator.ValAddress)) + providerKeeper.SetOptedIn(ctx, "chainID", optedInValidator.ValAddress, optedInValidator.BlockHeight) + require.True(t, providerKeeper.IsOptedIn(ctx, "chainID", optedInValidator.ValAddress)) + providerKeeper.DeleteOptedIn(ctx, "chainID", optedInValidator.ValAddress) + require.False(t, providerKeeper.IsOptedIn(ctx, "chainID", optedInValidator.ValAddress)) } func TestGetToBeOptedIn(t *testing.T) { providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() - expectedAddresses := []types.ProviderConsAddress{ - types.NewProviderConsAddress([]byte("providerAddr1")), - types.NewProviderConsAddress([]byte("providerAddr2")), - types.NewProviderConsAddress([]byte("providerAddr3"))} + expectedAddresses := []sdk.ValAddress{ + []byte("valAddr1"), + []byte("valAddr2"), + []byte("valAddr3")} for _, addr := range expectedAddresses { providerKeeper.SetToBeOptedIn(ctx, "chainID", addr) @@ -735,45 +736,9 @@ func TestGetToBeOptedIn(t *testing.T) { actualAddresses := providerKeeper.GetToBeOptedIn(ctx, "chainID") // sort addresses first to be able to compare - sortAddresses := func(addresses []types.ProviderConsAddress) { + sortAddresses := func(addresses []sdk.ValAddress) { sort.Slice(addresses, func(i int, j int) bool { - a := addresses[i] - b := addresses[j] - return bytes.Compare(a.Address.Bytes(), b.Address.Bytes()) < 0 - }) - } - sortAddresses(expectedAddresses) - sortAddresses(actualAddresses) - require.Equal(t, expectedAddresses, actualAddresses) - - for _, addr := range expectedAddresses { - require.True(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", addr)) - providerKeeper.DeleteToBeOptedIn(ctx, "chainID", addr) - require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", addr)) - } -} - -func TestBeOptedIn(t *testing.T) { - providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) - defer ctrl.Finish() - - expectedAddresses := []types.ProviderConsAddress{ - types.NewProviderConsAddress([]byte("providerAddr1")), - types.NewProviderConsAddress([]byte("providerAddr2")), - types.NewProviderConsAddress([]byte("providerAddr3"))} - - for _, addr := range expectedAddresses { - providerKeeper.SetToBeOptedIn(ctx, "chainID", addr) - } - - actualAddresses := providerKeeper.GetToBeOptedIn(ctx, "chainID") - - // sort addresses first to be able to compare - sortAddresses := func(addresses []types.ProviderConsAddress) { - sort.Slice(addresses, func(i int, j int) bool { - a := addresses[i] - b := addresses[j] - return bytes.Compare(a.Address.Bytes(), b.Address.Bytes()) < 0 + return bytes.Compare(addresses[i], addresses[j]) < 0 }) } sortAddresses(expectedAddresses) @@ -792,23 +757,23 @@ func TestToBeOptedIn(t *testing.T) { providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() - providerAddr := types.NewProviderConsAddress([]byte("providerAddr1")) + valAddress := []byte("valAddr1") - require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) - providerKeeper.SetToBeOptedIn(ctx, "chainID", providerAddr) - require.True(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) - providerKeeper.DeleteToBeOptedIn(ctx, "chainID", providerAddr) - require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) + require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", valAddress)) + providerKeeper.SetToBeOptedIn(ctx, "chainID", valAddress) + require.True(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", valAddress)) + providerKeeper.DeleteToBeOptedIn(ctx, "chainID", valAddress) + require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", valAddress)) } func TestGetToBeOptedOut(t *testing.T) { providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() - expectedAddresses := []types.ProviderConsAddress{ - types.NewProviderConsAddress([]byte("providerAddr1")), - types.NewProviderConsAddress([]byte("providerAddr2")), - types.NewProviderConsAddress([]byte("providerAddr3"))} + expectedAddresses := []sdk.ValAddress{ + []byte("valAddr1"), + []byte("valAddr2"), + []byte("valAddr3")} for _, addr := range expectedAddresses { providerKeeper.SetToBeOptedOut(ctx, "chainID", addr) @@ -817,11 +782,9 @@ func TestGetToBeOptedOut(t *testing.T) { actualAddresses := providerKeeper.GetToBeOptedOut(ctx, "chainID") // sort addresses first to be able to compare - sortAddresses := func(addresses []types.ProviderConsAddress) { + sortAddresses := func(addresses []sdk.ValAddress) { sort.Slice(addresses, func(i int, j int) bool { - a := addresses[i] - b := addresses[j] - return bytes.Compare(a.Address.Bytes(), b.Address.Bytes()) < 0 + return bytes.Compare(addresses[i], addresses[j]) < 0 }) } sortAddresses(expectedAddresses) @@ -840,11 +803,11 @@ func TestToBeOptedOut(t *testing.T) { providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() - providerAddr := types.NewProviderConsAddress([]byte("providerAddr1")) + valAddress := []byte("valAddr1") - require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", providerAddr)) - providerKeeper.SetToBeOptedOut(ctx, "chainID", providerAddr) - require.True(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", providerAddr)) - providerKeeper.DeleteToBeOptedOut(ctx, "chainID", providerAddr) - require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", providerAddr)) + require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", valAddress)) + providerKeeper.SetToBeOptedOut(ctx, "chainID", valAddress) + require.True(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", valAddress)) + providerKeeper.DeleteToBeOptedOut(ctx, "chainID", valAddress) + require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", valAddress)) } diff --git a/x/ccv/provider/keeper/key_assignment_test.go b/x/ccv/provider/keeper/key_assignment_test.go index 4fab08c981..272d5f1593 100644 --- a/x/ccv/provider/keeper/key_assignment_test.go +++ b/x/ccv/provider/keeper/key_assignment_test.go @@ -86,7 +86,7 @@ func TestGetAllValidatorConsumerPubKey(t *testing.T) { expectedGetAllOneConsumerOrder = append(expectedGetAllOneConsumerOrder, assignment) } } - // sorting by ValidatorConsumerPubKey.ProviderAddr + // sorting by ValidatorConsumerPubKey.ValAddress sort.Slice(expectedGetAllOneConsumerOrder, func(i, j int) bool { return bytes.Compare(expectedGetAllOneConsumerOrder[i].ProviderAddr, expectedGetAllOneConsumerOrder[j].ProviderAddr) == -1 }) @@ -228,7 +228,7 @@ func TestGetAllKeyAssignmentReplacements(t *testing.T) { ) } expectedGetAllOrder := testAssignments - // sorting by KeyAssignmentReplacement.ProviderAddr + // sorting by KeyAssignmentReplacement.ValAddress sort.Slice(expectedGetAllOrder, func(i, j int) bool { return bytes.Compare(expectedGetAllOrder[i].ProviderAddr, expectedGetAllOrder[j].ProviderAddr) == -1 }) diff --git a/x/ccv/provider/keeper/msg_server.go b/x/ccv/provider/keeper/msg_server.go index 7cac362a04..df79e5d4d7 100644 --- a/x/ccv/provider/keeper/msg_server.go +++ b/x/ccv/provider/keeper/msg_server.go @@ -178,17 +178,13 @@ func (k msgServer) SubmitConsumerDoubleVoting(goCtx context.Context, msg *types. func (k msgServer) OptIn(goCtx context.Context, msg *types.MsgOptIn) (*types.MsgOptInResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) - valAddress, err := sdk.ConsAddressFromBech32(msg.ProviderAddr) - if err != nil { - return nil, err - } - providerAddr := types.NewProviderConsAddress(valAddress) + valAddress, err := sdk.ValAddressFromBech32(msg.ProviderAddr) if err != nil { return nil, err } if msg.ConsumerKey != "" { - k.Keeper.HandleOptIn(ctx, msg.ChainId, providerAddr, &msg.ConsumerKey) + k.Keeper.HandleOptIn(ctx, msg.ChainId, valAddress, &msg.ConsumerKey) ctx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( ccvtypes.EventTypeOptIn, @@ -197,7 +193,7 @@ func (k msgServer) OptIn(goCtx context.Context, msg *types.MsgOptIn) (*types.Msg ), }) } else { - k.Keeper.HandleOptIn(ctx, msg.ChainId, providerAddr, nil) + k.Keeper.HandleOptIn(ctx, msg.ChainId, valAddress, nil) ctx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( @@ -213,16 +209,12 @@ func (k msgServer) OptIn(goCtx context.Context, msg *types.MsgOptIn) (*types.Msg func (k msgServer) OptOut(goCtx context.Context, msg *types.MsgOptOut) (*types.MsgOptOutResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) - valAddress, err := sdk.ConsAddressFromBech32(msg.ProviderAddr) - if err != nil { - return nil, err - } - providerAddr := types.NewProviderConsAddress(valAddress) + valAddress, err := sdk.ValAddressFromBech32(msg.ProviderAddr) if err != nil { return nil, err } - k.Keeper.HandleOptOut(ctx, msg.ChainId, providerAddr) + k.Keeper.HandleOptOut(ctx, msg.ChainId, valAddress) ctx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( diff --git a/x/ccv/provider/keeper/partial_set_security.go b/x/ccv/provider/keeper/partial_set_security.go index 1251eda372..0211d4681e 100644 --- a/x/ccv/provider/keeper/partial_set_security.go +++ b/x/ccv/provider/keeper/partial_set_security.go @@ -2,22 +2,21 @@ package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/interchain-security/v4/x/ccv/provider/types" ) type OptedInValidator struct { - ProviderAddr types.ProviderConsAddress + ValAddress sdk.ValAddress // block height the validator opted in at BlockHeight uint64 } -func (k Keeper) HandleOptIn(ctx sdk.Context, chainID string, providerAddr types.ProviderConsAddress, consumerKey *string) { - if k.IsToBeOptedOut(ctx, chainID, providerAddr) { +func (k Keeper) HandleOptIn(ctx sdk.Context, chainID string, valAddress sdk.ValAddress, consumerKey *string) { + if k.IsToBeOptedOut(ctx, chainID, valAddress) { // a validator to be opted in cancels out with a validator to be opted out - k.DeleteToBeOptedOut(ctx, chainID, providerAddr) - } else if !k.IsToBeOptedIn(ctx, chainID, providerAddr) && !k.IsOptedIn(ctx, chainID, providerAddr) { + k.DeleteToBeOptedOut(ctx, chainID, valAddress) + } else if !k.IsToBeOptedIn(ctx, chainID, valAddress) && !k.IsOptedIn(ctx, chainID, valAddress) { // a validator can only be set for opt in if it is not opted in and not already set for opt in - k.SetToBeOptedIn(ctx, chainID, providerAddr) + k.SetToBeOptedIn(ctx, chainID, valAddress) } if consumerKey != nil { @@ -25,12 +24,12 @@ func (k Keeper) HandleOptIn(ctx sdk.Context, chainID string, providerAddr types. } } -func (k Keeper) HandleOptOut(ctx sdk.Context, chainID string, providerAddr types.ProviderConsAddress) { - if k.IsToBeOptedIn(ctx, chainID, providerAddr) { +func (k Keeper) HandleOptOut(ctx sdk.Context, chainID string, valAddress sdk.ValAddress) { + if k.IsToBeOptedIn(ctx, chainID, valAddress) { // a validator to be opted out cancels out a validator to be opted in - k.DeleteToBeOptedIn(ctx, chainID, providerAddr) - } else if !k.IsToBeOptedOut(ctx, chainID, providerAddr) && k.IsOptedIn(ctx, chainID, providerAddr) { + k.DeleteToBeOptedIn(ctx, chainID, valAddress) + } else if !k.IsToBeOptedOut(ctx, chainID, valAddress) && k.IsOptedIn(ctx, chainID, valAddress) { // a validator can only be set for opt out if it is opted in and not already set for opt out - k.SetToBeOptedOut(ctx, chainID, providerAddr) + k.SetToBeOptedOut(ctx, chainID, valAddress) } } diff --git a/x/ccv/provider/keeper/partial_set_security_test.go b/x/ccv/provider/keeper/partial_set_security_test.go index 34e99f61f9..0bc8993270 100644 --- a/x/ccv/provider/keeper/partial_set_security_test.go +++ b/x/ccv/provider/keeper/partial_set_security_test.go @@ -2,7 +2,6 @@ package keeper_test import ( testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper" - "github.com/cosmos/interchain-security/v4/x/ccv/provider/types" "github.com/stretchr/testify/require" "testing" ) @@ -11,38 +10,38 @@ func TestHandleOptIn(t *testing.T) { providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() - providerAddr := types.NewProviderConsAddress([]byte("providerAddr")) + valAddress := []byte("valAddr") - // if validator (`providerAddr`) is to be opted out, then we cancel that the validator is about + // if validator (`valAddress`) is to be opted out, then we cancel that the validator is about // to be opted out and do not consider the validator to opt in - providerKeeper.SetToBeOptedOut(ctx, "chainID", providerAddr) - require.True(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", providerAddr)) - providerKeeper.HandleOptIn(ctx, "chainID", providerAddr, nil) - require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) - 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.HandleOptIn(ctx, "chainID", providerAddr, nil) - require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) + providerKeeper.SetToBeOptedOut(ctx, "chainID", valAddress) + require.True(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", valAddress)) + providerKeeper.HandleOptIn(ctx, "chainID", valAddress, nil) + require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", valAddress)) + require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", valAddress)) + + // if validator (`valAddress`) is already opted in, then the validator cannot be opted in + providerKeeper.SetOptedIn(ctx, "chainID", valAddress, 1) + providerKeeper.HandleOptIn(ctx, "chainID", valAddress, nil) + require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", valAddress)) } func TestHandleOptOut(t *testing.T) { providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() - providerAddr := types.NewProviderConsAddress([]byte("providerAddr")) + valAddress := []byte("valAddr") - // if validator (`providerAddr`) is to be opted in, then we cancel that the validator is about + // if validator (`valAddress`) is to be opted in, then we cancel that the validator is about // to be opted out and do not consider the validator to opt out - providerKeeper.SetToBeOptedIn(ctx, "chainID", providerAddr) - require.True(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) - providerKeeper.HandleOptOut(ctx, "chainID", providerAddr) - require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", providerAddr)) - require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) - - // if validator (`providerAddr`) is not opted in, then the validator cannot be opted out - providerKeeper.DeleteOptedIn(ctx, "chainID", providerAddr) - providerKeeper.HandleOptOut(ctx, "chainID", providerAddr) - require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", providerAddr)) + providerKeeper.SetToBeOptedIn(ctx, "chainID", valAddress) + require.True(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", valAddress)) + providerKeeper.HandleOptOut(ctx, "chainID", valAddress) + require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", valAddress)) + require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", valAddress)) + + // if validator (`valAddress`) is not opted in, then the validator cannot be opted out + providerKeeper.DeleteOptedIn(ctx, "chainID", valAddress) + providerKeeper.HandleOptOut(ctx, "chainID", valAddress) + require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", valAddress)) } diff --git a/x/ccv/provider/types/keys.go b/x/ccv/provider/types/keys.go index 20824454cb..c42cbad4b3 100644 --- a/x/ccv/provider/types/keys.go +++ b/x/ccv/provider/types/keys.go @@ -538,21 +538,21 @@ 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, valAddress sdk.ValAddress) []byte { prefix := ChainIdWithLenKey(OptedInBytePrefix, chainID) - return append(prefix, providerAddr.ToSdkConsAddr().Bytes()...) + return append(prefix, valAddress...) } // ToBeOptedInKey returns the key of consumer chain `chainID` and validator with `providerAddr` -func ToBeOptedInKey(chainID string, providerAddr ProviderConsAddress) []byte { +func ToBeOptedInKey(chainID string, valAddress sdk.ValAddress) []byte { prefix := ChainIdWithLenKey(ToBeOptedInBytePrefix, chainID) - return append(prefix, providerAddr.ToSdkConsAddr().Bytes()...) + return append(prefix, valAddress...) } // ToBeOptedOutKey returns the key of consumer chain `chainID` and validator with `providerAddr` -func ToBeOptedOutKey(chainID string, providerAddr ProviderConsAddress) []byte { +func ToBeOptedOutKey(chainID string, valAddress sdk.ValAddress) []byte { prefix := ChainIdWithLenKey(ToBeOptedOutBytePrefix, chainID) - return append(prefix, providerAddr.ToSdkConsAddr().Bytes()...) + return append(prefix, valAddress...) } // diff --git a/x/ccv/provider/types/provider.pb.go b/x/ccv/provider/types/provider.pb.go index fd9d63bc7e..89339d12ab 100644 --- a/x/ccv/provider/types/provider.pb.go +++ b/x/ccv/provider/types/provider.pb.go @@ -5813,7 +5813,7 @@ func (m *KeyAssignmentReplacement) Unmarshal(dAtA []byte) error { switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProviderAddr", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ValAddress", wireType) } var byteLen int for shift := uint(0); ; shift += 7 { @@ -5984,7 +5984,7 @@ func (m *ValidatorConsumerPubKey) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProviderAddr", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ValAddress", wireType) } var byteLen int for shift := uint(0); ; shift += 7 { @@ -6170,7 +6170,7 @@ func (m *ValidatorByConsumerAddr) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProviderAddr", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ValAddress", wireType) } var byteLen int for shift := uint(0); ; shift += 7 { diff --git a/x/ccv/provider/types/tx.pb.go b/x/ccv/provider/types/tx.pb.go index 647f5f49dc..35691c4f91 100644 --- a/x/ccv/provider/types/tx.pb.go +++ b/x/ccv/provider/types/tx.pb.go @@ -1272,7 +1272,7 @@ func (m *MsgAssignConsumerKey) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProviderAddr", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ValAddress", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1840,7 +1840,7 @@ func (m *MsgOptIn) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProviderAddr", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ValAddress", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -2036,7 +2036,7 @@ func (m *MsgOptOut) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProviderAddr", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ValAddress", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { From b0d23375efc2a8d2ad73073bddc70d9cdb322700 Mon Sep 17 00:00:00 2001 From: insumity Date: Mon, 5 Feb 2024 16:39:08 +0100 Subject: [PATCH 4/8] Revert "changed cons to val address" This reverts commit a32e8829fee3cbbe50e363a0aa91ad62117a8a1d. --- x/ccv/provider/keeper/keeper.go | 54 ++++---- x/ccv/provider/keeper/keeper_test.go | 117 ++++++++++++------ x/ccv/provider/keeper/key_assignment_test.go | 4 +- x/ccv/provider/keeper/msg_server.go | 18 ++- x/ccv/provider/keeper/partial_set_security.go | 23 ++-- .../keeper/partial_set_security_test.go | 49 ++++---- x/ccv/provider/types/keys.go | 12 +- x/ccv/provider/types/provider.pb.go | 6 +- x/ccv/provider/types/tx.pb.go | 6 +- 9 files changed, 169 insertions(+), 120 deletions(-) diff --git a/x/ccv/provider/keeper/keeper.go b/x/ccv/provider/keeper/keeper.go index 816683279d..bd26d6b87d 100644 --- a/x/ccv/provider/keeper/keeper.go +++ b/x/ccv/provider/keeper/keeper.go @@ -1187,7 +1187,7 @@ func (k Keeper) IsOptIn(ctx sdk.Context, chainID string) bool { func (k Keeper) SetOptedIn( ctx sdk.Context, chainID string, - valAddress sdk.ValAddress, + providerAddr types.ProviderConsAddress, blockHeight uint64, ) { store := ctx.KVStore(k.storeKey) @@ -1196,25 +1196,25 @@ func (k Keeper) SetOptedIn( blockHeightBytes := make([]byte, 8) binary.BigEndian.PutUint64(blockHeightBytes, blockHeight) - store.Set(types.OptedInKey(chainID, valAddress), blockHeightBytes) + store.Set(types.OptedInKey(chainID, providerAddr), blockHeightBytes) } func (k Keeper) DeleteOptedIn( ctx sdk.Context, chainID string, - valAddress sdk.ValAddress, + providerAddr types.ProviderConsAddress, ) { store := ctx.KVStore(k.storeKey) - store.Delete(types.OptedInKey(chainID, valAddress)) + store.Delete(types.OptedInKey(chainID, providerAddr)) } func (k Keeper) IsOptedIn( ctx sdk.Context, chainID string, - valAddress sdk.ValAddress, + providerAddr types.ProviderConsAddress, ) bool { store := ctx.KVStore(k.storeKey) - return store.Get(types.OptedInKey(chainID, valAddress)) != nil + return store.Get(types.OptedInKey(chainID, providerAddr)) != nil } func (k Keeper) GetOptedIn( @@ -1227,8 +1227,8 @@ func (k Keeper) GetOptedIn( for ; iterator.Valid(); iterator.Next() { optedInValidators = append(optedInValidators, OptedInValidator{ - ValAddress: iterator.Key()[len(key):], - BlockHeight: binary.BigEndian.Uint64(iterator.Value()), + ProviderAddr: types.NewProviderConsAddress(iterator.Key()[len(key):]), + BlockHeight: binary.BigEndian.Uint64(iterator.Value()), }) } @@ -1238,33 +1238,33 @@ func (k Keeper) GetOptedIn( func (k Keeper) SetToBeOptedIn( ctx sdk.Context, chainID string, - valAddress sdk.ValAddress, + providerAddr types.ProviderConsAddress, ) { store := ctx.KVStore(k.storeKey) - store.Set(types.ToBeOptedInKey(chainID, valAddress), []byte{}) + store.Set(types.ToBeOptedInKey(chainID, providerAddr), []byte{}) } func (k Keeper) DeleteToBeOptedIn( ctx sdk.Context, chainID string, - valAddress sdk.ValAddress, + providerAddr types.ProviderConsAddress, ) { store := ctx.KVStore(k.storeKey) - store.Delete(types.ToBeOptedInKey(chainID, valAddress)) + store.Delete(types.ToBeOptedInKey(chainID, providerAddr)) } func (k Keeper) IsToBeOptedIn( ctx sdk.Context, chainID string, - valAddress sdk.ValAddress, + providerAddr types.ProviderConsAddress, ) bool { store := ctx.KVStore(k.storeKey) - return store.Get(types.ToBeOptedInKey(chainID, valAddress)) != nil + return store.Get(types.ToBeOptedInKey(chainID, providerAddr)) != nil } func (k Keeper) GetToBeOptedIn( ctx sdk.Context, - chainID string) (valAddresses []sdk.ValAddress) { + chainID string) (addresses []types.ProviderConsAddress) { store := ctx.KVStore(k.storeKey) key := types.ChainIdWithLenKey(types.ToBeOptedInBytePrefix, chainID) @@ -1272,42 +1272,43 @@ func (k Keeper) GetToBeOptedIn( defer iterator.Close() for ; iterator.Valid(); iterator.Next() { - valAddresses = append(valAddresses, iterator.Key()[len(key):]) + providerAddr := types.NewProviderConsAddress(iterator.Key()[len(key):]) + addresses = append(addresses, providerAddr) } - return valAddresses + return addresses } func (k Keeper) SetToBeOptedOut( ctx sdk.Context, chainID string, - valAddress sdk.ValAddress, + providerAddr types.ProviderConsAddress, ) { store := ctx.KVStore(k.storeKey) - store.Set(types.ToBeOptedOutKey(chainID, valAddress), []byte{}) + store.Set(types.ToBeOptedOutKey(chainID, providerAddr), []byte{}) } func (k Keeper) DeleteToBeOptedOut( ctx sdk.Context, chainID string, - valAddress sdk.ValAddress, + providerAddr types.ProviderConsAddress, ) { store := ctx.KVStore(k.storeKey) - store.Delete(types.ToBeOptedOutKey(chainID, valAddress)) + store.Delete(types.ToBeOptedOutKey(chainID, providerAddr)) } func (k Keeper) IsToBeOptedOut( ctx sdk.Context, chainID string, - valAddress sdk.ValAddress, + providerAddr types.ProviderConsAddress, ) bool { store := ctx.KVStore(k.storeKey) - return store.Get(types.ToBeOptedOutKey(chainID, valAddress)) != nil + return store.Get(types.ToBeOptedOutKey(chainID, providerAddr)) != nil } func (k Keeper) GetToBeOptedOut( ctx sdk.Context, - chainID string) (valAddresses []sdk.ValAddress) { + chainID string) (addresses []types.ProviderConsAddress) { store := ctx.KVStore(k.storeKey) key := types.ChainIdWithLenKey(types.ToBeOptedOutBytePrefix, chainID) @@ -1315,8 +1316,9 @@ func (k Keeper) GetToBeOptedOut( defer iterator.Close() for ; iterator.Valid(); iterator.Next() { - valAddresses = append(valAddresses, iterator.Key()[len(key):]) + providerAddr := types.NewProviderConsAddress(iterator.Key()[len(key):]) + addresses = append(addresses, providerAddr) } - return valAddresses + return addresses } diff --git a/x/ccv/provider/keeper/keeper_test.go b/x/ccv/provider/keeper/keeper_test.go index 685df27191..6eb28675ba 100644 --- a/x/ccv/provider/keeper/keeper_test.go +++ b/x/ccv/provider/keeper/keeper_test.go @@ -3,7 +3,6 @@ package keeper_test import ( "bytes" "fmt" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper" "sort" "testing" @@ -669,22 +668,22 @@ func TestGetOptedIn(t *testing.T) { expectedOptedInValidators := []keeper.OptedInValidator{ { - ValAddress: []byte("valAddr1"), - BlockHeight: 1, + ProviderAddr: types.NewProviderConsAddress([]byte("providerAddr1")), + BlockHeight: 1, }, { - ValAddress: []byte("valAddr2"), - BlockHeight: 2, + ProviderAddr: types.NewProviderConsAddress([]byte("providerAddr2")), + BlockHeight: 2, }, { - ValAddress: []byte("valAddr3"), - BlockHeight: 3, + ProviderAddr: types.NewProviderConsAddress([]byte("providerAddr3")), + BlockHeight: 3, }, } for _, expectedOptedInValidator := range expectedOptedInValidators { providerKeeper.SetOptedIn(ctx, "chainID", - expectedOptedInValidator.ValAddress, expectedOptedInValidator.BlockHeight) + expectedOptedInValidator.ProviderAddr, expectedOptedInValidator.BlockHeight) } actualOptedInValidators := providerKeeper.GetOptedIn(ctx, "chainID") @@ -695,7 +694,7 @@ func TestGetOptedIn(t *testing.T) { a := optedInValidators[i] b := optedInValidators[j] return a.BlockHeight < b.BlockHeight || - (a.BlockHeight == b.BlockHeight && bytes.Compare(a.ValAddress, b.ValAddress) < 0) + (a.BlockHeight == b.BlockHeight && bytes.Compare(a.ProviderAddr.ToSdkConsAddr(), b.ProviderAddr.ToSdkConsAddr()) < 0) }) } sortOptedInValidators(expectedOptedInValidators) @@ -709,25 +708,25 @@ func TestOptedIn(t *testing.T) { defer ctrl.Finish() optedInValidator := keeper.OptedInValidator{ - ValAddress: []byte("valAddr"), - BlockHeight: 1, + ProviderAddr: types.NewProviderConsAddress([]byte("providerAddr")), + BlockHeight: 1, } - require.False(t, providerKeeper.IsOptedIn(ctx, "chainID", optedInValidator.ValAddress)) - providerKeeper.SetOptedIn(ctx, "chainID", optedInValidator.ValAddress, optedInValidator.BlockHeight) - require.True(t, providerKeeper.IsOptedIn(ctx, "chainID", optedInValidator.ValAddress)) - providerKeeper.DeleteOptedIn(ctx, "chainID", optedInValidator.ValAddress) - require.False(t, providerKeeper.IsOptedIn(ctx, "chainID", optedInValidator.ValAddress)) + 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)) } func TestGetToBeOptedIn(t *testing.T) { providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() - expectedAddresses := []sdk.ValAddress{ - []byte("valAddr1"), - []byte("valAddr2"), - []byte("valAddr3")} + expectedAddresses := []types.ProviderConsAddress{ + types.NewProviderConsAddress([]byte("providerAddr1")), + types.NewProviderConsAddress([]byte("providerAddr2")), + types.NewProviderConsAddress([]byte("providerAddr3"))} for _, addr := range expectedAddresses { providerKeeper.SetToBeOptedIn(ctx, "chainID", addr) @@ -736,9 +735,45 @@ func TestGetToBeOptedIn(t *testing.T) { actualAddresses := providerKeeper.GetToBeOptedIn(ctx, "chainID") // sort addresses first to be able to compare - sortAddresses := func(addresses []sdk.ValAddress) { + sortAddresses := func(addresses []types.ProviderConsAddress) { sort.Slice(addresses, func(i int, j int) bool { - return bytes.Compare(addresses[i], addresses[j]) < 0 + a := addresses[i] + b := addresses[j] + return bytes.Compare(a.Address.Bytes(), b.Address.Bytes()) < 0 + }) + } + sortAddresses(expectedAddresses) + sortAddresses(actualAddresses) + require.Equal(t, expectedAddresses, actualAddresses) + + for _, addr := range expectedAddresses { + require.True(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", addr)) + providerKeeper.DeleteToBeOptedIn(ctx, "chainID", addr) + require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", addr)) + } +} + +func TestBeOptedIn(t *testing.T) { + providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) + defer ctrl.Finish() + + expectedAddresses := []types.ProviderConsAddress{ + types.NewProviderConsAddress([]byte("providerAddr1")), + types.NewProviderConsAddress([]byte("providerAddr2")), + types.NewProviderConsAddress([]byte("providerAddr3"))} + + for _, addr := range expectedAddresses { + providerKeeper.SetToBeOptedIn(ctx, "chainID", addr) + } + + actualAddresses := providerKeeper.GetToBeOptedIn(ctx, "chainID") + + // sort addresses first to be able to compare + sortAddresses := func(addresses []types.ProviderConsAddress) { + sort.Slice(addresses, func(i int, j int) bool { + a := addresses[i] + b := addresses[j] + return bytes.Compare(a.Address.Bytes(), b.Address.Bytes()) < 0 }) } sortAddresses(expectedAddresses) @@ -757,23 +792,23 @@ func TestToBeOptedIn(t *testing.T) { providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() - valAddress := []byte("valAddr1") + providerAddr := types.NewProviderConsAddress([]byte("providerAddr1")) - require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", valAddress)) - providerKeeper.SetToBeOptedIn(ctx, "chainID", valAddress) - require.True(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", valAddress)) - providerKeeper.DeleteToBeOptedIn(ctx, "chainID", valAddress) - require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", valAddress)) + require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) + providerKeeper.SetToBeOptedIn(ctx, "chainID", providerAddr) + require.True(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) + providerKeeper.DeleteToBeOptedIn(ctx, "chainID", providerAddr) + require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) } func TestGetToBeOptedOut(t *testing.T) { providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() - expectedAddresses := []sdk.ValAddress{ - []byte("valAddr1"), - []byte("valAddr2"), - []byte("valAddr3")} + expectedAddresses := []types.ProviderConsAddress{ + types.NewProviderConsAddress([]byte("providerAddr1")), + types.NewProviderConsAddress([]byte("providerAddr2")), + types.NewProviderConsAddress([]byte("providerAddr3"))} for _, addr := range expectedAddresses { providerKeeper.SetToBeOptedOut(ctx, "chainID", addr) @@ -782,9 +817,11 @@ func TestGetToBeOptedOut(t *testing.T) { actualAddresses := providerKeeper.GetToBeOptedOut(ctx, "chainID") // sort addresses first to be able to compare - sortAddresses := func(addresses []sdk.ValAddress) { + sortAddresses := func(addresses []types.ProviderConsAddress) { sort.Slice(addresses, func(i int, j int) bool { - return bytes.Compare(addresses[i], addresses[j]) < 0 + a := addresses[i] + b := addresses[j] + return bytes.Compare(a.Address.Bytes(), b.Address.Bytes()) < 0 }) } sortAddresses(expectedAddresses) @@ -803,11 +840,11 @@ func TestToBeOptedOut(t *testing.T) { providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() - valAddress := []byte("valAddr1") + providerAddr := types.NewProviderConsAddress([]byte("providerAddr1")) - require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", valAddress)) - providerKeeper.SetToBeOptedOut(ctx, "chainID", valAddress) - require.True(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", valAddress)) - providerKeeper.DeleteToBeOptedOut(ctx, "chainID", valAddress) - require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", valAddress)) + require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", providerAddr)) + providerKeeper.SetToBeOptedOut(ctx, "chainID", providerAddr) + require.True(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", providerAddr)) + providerKeeper.DeleteToBeOptedOut(ctx, "chainID", providerAddr) + require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", providerAddr)) } diff --git a/x/ccv/provider/keeper/key_assignment_test.go b/x/ccv/provider/keeper/key_assignment_test.go index 272d5f1593..4fab08c981 100644 --- a/x/ccv/provider/keeper/key_assignment_test.go +++ b/x/ccv/provider/keeper/key_assignment_test.go @@ -86,7 +86,7 @@ func TestGetAllValidatorConsumerPubKey(t *testing.T) { expectedGetAllOneConsumerOrder = append(expectedGetAllOneConsumerOrder, assignment) } } - // sorting by ValidatorConsumerPubKey.ValAddress + // sorting by ValidatorConsumerPubKey.ProviderAddr sort.Slice(expectedGetAllOneConsumerOrder, func(i, j int) bool { return bytes.Compare(expectedGetAllOneConsumerOrder[i].ProviderAddr, expectedGetAllOneConsumerOrder[j].ProviderAddr) == -1 }) @@ -228,7 +228,7 @@ func TestGetAllKeyAssignmentReplacements(t *testing.T) { ) } expectedGetAllOrder := testAssignments - // sorting by KeyAssignmentReplacement.ValAddress + // sorting by KeyAssignmentReplacement.ProviderAddr sort.Slice(expectedGetAllOrder, func(i, j int) bool { return bytes.Compare(expectedGetAllOrder[i].ProviderAddr, expectedGetAllOrder[j].ProviderAddr) == -1 }) diff --git a/x/ccv/provider/keeper/msg_server.go b/x/ccv/provider/keeper/msg_server.go index df79e5d4d7..7cac362a04 100644 --- a/x/ccv/provider/keeper/msg_server.go +++ b/x/ccv/provider/keeper/msg_server.go @@ -178,13 +178,17 @@ func (k msgServer) SubmitConsumerDoubleVoting(goCtx context.Context, msg *types. func (k msgServer) OptIn(goCtx context.Context, msg *types.MsgOptIn) (*types.MsgOptInResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) - valAddress, err := sdk.ValAddressFromBech32(msg.ProviderAddr) + valAddress, err := sdk.ConsAddressFromBech32(msg.ProviderAddr) + if err != nil { + return nil, err + } + providerAddr := types.NewProviderConsAddress(valAddress) if err != nil { return nil, err } if msg.ConsumerKey != "" { - k.Keeper.HandleOptIn(ctx, msg.ChainId, valAddress, &msg.ConsumerKey) + k.Keeper.HandleOptIn(ctx, msg.ChainId, providerAddr, &msg.ConsumerKey) ctx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( ccvtypes.EventTypeOptIn, @@ -193,7 +197,7 @@ func (k msgServer) OptIn(goCtx context.Context, msg *types.MsgOptIn) (*types.Msg ), }) } else { - k.Keeper.HandleOptIn(ctx, msg.ChainId, valAddress, nil) + k.Keeper.HandleOptIn(ctx, msg.ChainId, providerAddr, nil) ctx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( @@ -209,12 +213,16 @@ func (k msgServer) OptIn(goCtx context.Context, msg *types.MsgOptIn) (*types.Msg func (k msgServer) OptOut(goCtx context.Context, msg *types.MsgOptOut) (*types.MsgOptOutResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) - valAddress, err := sdk.ValAddressFromBech32(msg.ProviderAddr) + valAddress, err := sdk.ConsAddressFromBech32(msg.ProviderAddr) + if err != nil { + return nil, err + } + providerAddr := types.NewProviderConsAddress(valAddress) if err != nil { return nil, err } - k.Keeper.HandleOptOut(ctx, msg.ChainId, valAddress) + k.Keeper.HandleOptOut(ctx, msg.ChainId, providerAddr) ctx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( diff --git a/x/ccv/provider/keeper/partial_set_security.go b/x/ccv/provider/keeper/partial_set_security.go index 0211d4681e..1251eda372 100644 --- a/x/ccv/provider/keeper/partial_set_security.go +++ b/x/ccv/provider/keeper/partial_set_security.go @@ -2,21 +2,22 @@ package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/interchain-security/v4/x/ccv/provider/types" ) type OptedInValidator struct { - ValAddress sdk.ValAddress + ProviderAddr types.ProviderConsAddress // block height the validator opted in at BlockHeight uint64 } -func (k Keeper) HandleOptIn(ctx sdk.Context, chainID string, valAddress sdk.ValAddress, consumerKey *string) { - if k.IsToBeOptedOut(ctx, chainID, valAddress) { +func (k Keeper) HandleOptIn(ctx sdk.Context, chainID string, providerAddr types.ProviderConsAddress, consumerKey *string) { + if k.IsToBeOptedOut(ctx, chainID, providerAddr) { // a validator to be opted in cancels out with a validator to be opted out - k.DeleteToBeOptedOut(ctx, chainID, valAddress) - } else if !k.IsToBeOptedIn(ctx, chainID, valAddress) && !k.IsOptedIn(ctx, chainID, valAddress) { + k.DeleteToBeOptedOut(ctx, chainID, providerAddr) + } else if !k.IsToBeOptedIn(ctx, chainID, providerAddr) && !k.IsOptedIn(ctx, chainID, providerAddr) { // a validator can only be set for opt in if it is not opted in and not already set for opt in - k.SetToBeOptedIn(ctx, chainID, valAddress) + k.SetToBeOptedIn(ctx, chainID, providerAddr) } if consumerKey != nil { @@ -24,12 +25,12 @@ func (k Keeper) HandleOptIn(ctx sdk.Context, chainID string, valAddress sdk.ValA } } -func (k Keeper) HandleOptOut(ctx sdk.Context, chainID string, valAddress sdk.ValAddress) { - if k.IsToBeOptedIn(ctx, chainID, valAddress) { +func (k Keeper) HandleOptOut(ctx sdk.Context, chainID string, providerAddr types.ProviderConsAddress) { + if k.IsToBeOptedIn(ctx, chainID, providerAddr) { // a validator to be opted out cancels out a validator to be opted in - k.DeleteToBeOptedIn(ctx, chainID, valAddress) - } else if !k.IsToBeOptedOut(ctx, chainID, valAddress) && k.IsOptedIn(ctx, chainID, valAddress) { + k.DeleteToBeOptedIn(ctx, chainID, providerAddr) + } else if !k.IsToBeOptedOut(ctx, chainID, providerAddr) && k.IsOptedIn(ctx, chainID, providerAddr) { // a validator can only be set for opt out if it is opted in and not already set for opt out - k.SetToBeOptedOut(ctx, chainID, valAddress) + k.SetToBeOptedOut(ctx, chainID, providerAddr) } } diff --git a/x/ccv/provider/keeper/partial_set_security_test.go b/x/ccv/provider/keeper/partial_set_security_test.go index 0bc8993270..34e99f61f9 100644 --- a/x/ccv/provider/keeper/partial_set_security_test.go +++ b/x/ccv/provider/keeper/partial_set_security_test.go @@ -2,6 +2,7 @@ package keeper_test import ( testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper" + "github.com/cosmos/interchain-security/v4/x/ccv/provider/types" "github.com/stretchr/testify/require" "testing" ) @@ -10,38 +11,38 @@ func TestHandleOptIn(t *testing.T) { providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() - valAddress := []byte("valAddr") + providerAddr := types.NewProviderConsAddress([]byte("providerAddr")) - // if validator (`valAddress`) is to be opted out, then we cancel that the validator is about + // if validator (`providerAddr`) is to be opted out, then we cancel that the validator is about // to be opted out and do not consider the validator to opt in - providerKeeper.SetToBeOptedOut(ctx, "chainID", valAddress) - require.True(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", valAddress)) - providerKeeper.HandleOptIn(ctx, "chainID", valAddress, nil) - require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", valAddress)) - require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", valAddress)) - - // if validator (`valAddress`) is already opted in, then the validator cannot be opted in - providerKeeper.SetOptedIn(ctx, "chainID", valAddress, 1) - providerKeeper.HandleOptIn(ctx, "chainID", valAddress, nil) - require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", valAddress)) + providerKeeper.SetToBeOptedOut(ctx, "chainID", providerAddr) + require.True(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", providerAddr)) + providerKeeper.HandleOptIn(ctx, "chainID", providerAddr, nil) + require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) + 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.HandleOptIn(ctx, "chainID", providerAddr, nil) + require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) } func TestHandleOptOut(t *testing.T) { providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() - valAddress := []byte("valAddr") + providerAddr := types.NewProviderConsAddress([]byte("providerAddr")) - // if validator (`valAddress`) is to be opted in, then we cancel that the validator is about + // if validator (`providerAddr`) is to be opted in, then we cancel that the validator is about // to be opted out and do not consider the validator to opt out - providerKeeper.SetToBeOptedIn(ctx, "chainID", valAddress) - require.True(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", valAddress)) - providerKeeper.HandleOptOut(ctx, "chainID", valAddress) - require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", valAddress)) - require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", valAddress)) - - // if validator (`valAddress`) is not opted in, then the validator cannot be opted out - providerKeeper.DeleteOptedIn(ctx, "chainID", valAddress) - providerKeeper.HandleOptOut(ctx, "chainID", valAddress) - require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", valAddress)) + providerKeeper.SetToBeOptedIn(ctx, "chainID", providerAddr) + require.True(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) + providerKeeper.HandleOptOut(ctx, "chainID", providerAddr) + require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", providerAddr)) + require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) + + // if validator (`providerAddr`) is not opted in, then the validator cannot be opted out + providerKeeper.DeleteOptedIn(ctx, "chainID", providerAddr) + providerKeeper.HandleOptOut(ctx, "chainID", providerAddr) + require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", providerAddr)) } diff --git a/x/ccv/provider/types/keys.go b/x/ccv/provider/types/keys.go index c42cbad4b3..20824454cb 100644 --- a/x/ccv/provider/types/keys.go +++ b/x/ccv/provider/types/keys.go @@ -538,21 +538,21 @@ func TopNKey(chainID string) []byte { } // OptedInKey returns the key of consumer chain `chainID` and validator with `providerAddr` -func OptedInKey(chainID string, valAddress sdk.ValAddress) []byte { +func OptedInKey(chainID string, providerAddr ProviderConsAddress) []byte { prefix := ChainIdWithLenKey(OptedInBytePrefix, chainID) - return append(prefix, valAddress...) + return append(prefix, providerAddr.ToSdkConsAddr().Bytes()...) } // ToBeOptedInKey returns the key of consumer chain `chainID` and validator with `providerAddr` -func ToBeOptedInKey(chainID string, valAddress sdk.ValAddress) []byte { +func ToBeOptedInKey(chainID string, providerAddr ProviderConsAddress) []byte { prefix := ChainIdWithLenKey(ToBeOptedInBytePrefix, chainID) - return append(prefix, valAddress...) + return append(prefix, providerAddr.ToSdkConsAddr().Bytes()...) } // ToBeOptedOutKey returns the key of consumer chain `chainID` and validator with `providerAddr` -func ToBeOptedOutKey(chainID string, valAddress sdk.ValAddress) []byte { +func ToBeOptedOutKey(chainID string, providerAddr ProviderConsAddress) []byte { prefix := ChainIdWithLenKey(ToBeOptedOutBytePrefix, chainID) - return append(prefix, valAddress...) + return append(prefix, providerAddr.ToSdkConsAddr().Bytes()...) } // diff --git a/x/ccv/provider/types/provider.pb.go b/x/ccv/provider/types/provider.pb.go index 89339d12ab..fd9d63bc7e 100644 --- a/x/ccv/provider/types/provider.pb.go +++ b/x/ccv/provider/types/provider.pb.go @@ -5813,7 +5813,7 @@ func (m *KeyAssignmentReplacement) Unmarshal(dAtA []byte) error { switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ValAddress", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ProviderAddr", wireType) } var byteLen int for shift := uint(0); ; shift += 7 { @@ -5984,7 +5984,7 @@ func (m *ValidatorConsumerPubKey) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ValAddress", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ProviderAddr", wireType) } var byteLen int for shift := uint(0); ; shift += 7 { @@ -6170,7 +6170,7 @@ func (m *ValidatorByConsumerAddr) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ValAddress", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ProviderAddr", wireType) } var byteLen int for shift := uint(0); ; shift += 7 { diff --git a/x/ccv/provider/types/tx.pb.go b/x/ccv/provider/types/tx.pb.go index 35691c4f91..647f5f49dc 100644 --- a/x/ccv/provider/types/tx.pb.go +++ b/x/ccv/provider/types/tx.pb.go @@ -1272,7 +1272,7 @@ func (m *MsgAssignConsumerKey) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ValAddress", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ProviderAddr", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1840,7 +1840,7 @@ func (m *MsgOptIn) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ValAddress", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ProviderAddr", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -2036,7 +2036,7 @@ func (m *MsgOptOut) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ValAddress", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ProviderAddr", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { From 32fed2189ec0f76e0988f552a0438343f9229959 Mon Sep 17 00:00:00 2001 From: insumity Date: Tue, 6 Feb 2024 14:34:09 +0100 Subject: [PATCH 5/8] Update x/ccv/provider/keeper/keeper.go Co-authored-by: Simon Noetzlin --- x/ccv/provider/keeper/keeper.go | 1 + 1 file changed, 1 insertion(+) diff --git a/x/ccv/provider/keeper/keeper.go b/x/ccv/provider/keeper/keeper.go index bd26d6b87d..ea052ec5fd 100644 --- a/x/ccv/provider/keeper/keeper.go +++ b/x/ccv/provider/keeper/keeper.go @@ -1184,6 +1184,7 @@ func (k Keeper) IsOptIn(ctx sdk.Context, chainID string) bool { topN, found := k.GetTopN(ctx, chainID) return !found || topN == 0 } + func (k Keeper) SetOptedIn( ctx sdk.Context, chainID string, From 45bf8634d22c10860cee52a96c7e8bd4a76e4071 Mon Sep 17 00:00:00 2001 From: insumity Date: Tue, 6 Feb 2024 14:43:12 +0100 Subject: [PATCH 6/8] took into account comments --- x/ccv/provider/keeper/msg_server.go | 33 ++++++++++--------- x/ccv/provider/keeper/partial_set_security.go | 23 +++++++++++-- .../keeper/partial_set_security_test.go | 14 ++++++-- 3 files changed, 49 insertions(+), 21 deletions(-) diff --git a/x/ccv/provider/keeper/msg_server.go b/x/ccv/provider/keeper/msg_server.go index 7cac362a04..c4afb9bfc3 100644 --- a/x/ccv/provider/keeper/msg_server.go +++ b/x/ccv/provider/keeper/msg_server.go @@ -188,25 +188,23 @@ func (k msgServer) OptIn(goCtx context.Context, msg *types.MsgOptIn) (*types.Msg } if msg.ConsumerKey != "" { - k.Keeper.HandleOptIn(ctx, msg.ChainId, providerAddr, &msg.ConsumerKey) - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - ccvtypes.EventTypeOptIn, - sdk.NewAttribute(types.AttributeProviderValidatorAddress, msg.ProviderAddr), - sdk.NewAttribute(types.AttributeConsumerConsensusPubKey, msg.ConsumerKey), - ), - }) + err = k.Keeper.HandleOptIn(ctx, msg.ChainId, providerAddr, &msg.ConsumerKey) } else { - k.Keeper.HandleOptIn(ctx, msg.ChainId, providerAddr, nil) + err = k.Keeper.HandleOptIn(ctx, msg.ChainId, providerAddr, nil) + } - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - ccvtypes.EventTypeOptIn, - sdk.NewAttribute(types.AttributeProviderValidatorAddress, msg.ProviderAddr), - ), - }) + if err != nil { + return nil, err } + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + ccvtypes.EventTypeOptIn, + sdk.NewAttribute(types.AttributeProviderValidatorAddress, msg.ProviderAddr), + sdk.NewAttribute(types.AttributeConsumerConsensusPubKey, msg.ConsumerKey), + ), + }) + return &types.MsgOptInResponse{}, nil } @@ -222,7 +220,10 @@ func (k msgServer) OptOut(goCtx context.Context, msg *types.MsgOptOut) (*types.M return nil, err } - k.Keeper.HandleOptOut(ctx, msg.ChainId, providerAddr) + err = k.Keeper.HandleOptOut(ctx, msg.ChainId, providerAddr) + if err != nil { + return nil, err + } ctx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( diff --git a/x/ccv/provider/keeper/partial_set_security.go b/x/ccv/provider/keeper/partial_set_security.go index 1251eda372..2cfdaa7292 100644 --- a/x/ccv/provider/keeper/partial_set_security.go +++ b/x/ccv/provider/keeper/partial_set_security.go @@ -1,6 +1,7 @@ package keeper import ( + errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/interchain-security/v4/x/ccv/provider/types" ) @@ -11,7 +12,13 @@ type OptedInValidator struct { BlockHeight uint64 } -func (k Keeper) HandleOptIn(ctx sdk.Context, chainID string, providerAddr types.ProviderConsAddress, consumerKey *string) { +func (k Keeper) HandleOptIn(ctx sdk.Context, chainID string, providerAddr types.ProviderConsAddress, consumerKey *string) error { + if !k.IsConsumerProposedOrRegistered(ctx, chainID) { + return errorsmod.Wrapf( + types.ErrUnknownConsumerChainId, + "opting in to an unknown consumer chain id: %s", chainID) + } + if k.IsToBeOptedOut(ctx, chainID, providerAddr) { // a validator to be opted in cancels out with a validator to be opted out k.DeleteToBeOptedOut(ctx, chainID, providerAddr) @@ -21,11 +28,19 @@ func (k Keeper) HandleOptIn(ctx sdk.Context, chainID string, providerAddr types. } if consumerKey != nil { - // TODO: assign consumer key in this case + // TODO (PR 1586): assign consumer key in this case } + + return nil } -func (k Keeper) HandleOptOut(ctx sdk.Context, chainID string, providerAddr types.ProviderConsAddress) { +func (k Keeper) HandleOptOut(ctx sdk.Context, chainID string, providerAddr types.ProviderConsAddress) error { + if !k.IsConsumerProposedOrRegistered(ctx, chainID) { + return errorsmod.Wrapf( + types.ErrUnknownConsumerChainId, + "opting out of an unknown consumer chain id: %s", chainID) + } + if k.IsToBeOptedIn(ctx, chainID, providerAddr) { // a validator to be opted out cancels out a validator to be opted in k.DeleteToBeOptedIn(ctx, chainID, providerAddr) @@ -33,4 +48,6 @@ func (k Keeper) HandleOptOut(ctx sdk.Context, chainID string, providerAddr types // a validator can only be set for opt out if it is opted in and not already set for opt out k.SetToBeOptedOut(ctx, chainID, providerAddr) } + + return nil } diff --git a/x/ccv/provider/keeper/partial_set_security_test.go b/x/ccv/provider/keeper/partial_set_security_test.go index 34e99f61f9..6321c5a7d6 100644 --- a/x/ccv/provider/keeper/partial_set_security_test.go +++ b/x/ccv/provider/keeper/partial_set_security_test.go @@ -13,9 +13,13 @@ func TestHandleOptIn(t *testing.T) { providerAddr := types.NewProviderConsAddress([]byte("providerAddr")) + // trying to opt in to a non-proposed and non-registered chain returns an error + require.Error(t, providerKeeper.HandleOptIn(ctx, "unknownChainID", providerAddr, nil)) + // if validator (`providerAddr`) is to be opted out, then we cancel that the validator is about // to be opted out and do not consider the validator to opt in providerKeeper.SetToBeOptedOut(ctx, "chainID", providerAddr) + providerKeeper.SetProposedConsumerChain(ctx, "chainID", 1) require.True(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", providerAddr)) providerKeeper.HandleOptIn(ctx, "chainID", providerAddr, nil) require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) @@ -33,16 +37,22 @@ func TestHandleOptOut(t *testing.T) { providerAddr := types.NewProviderConsAddress([]byte("providerAddr")) + // trying to opt out from a non-proposed and non-registered chain returns an error + require.Error(t, providerKeeper.HandleOptOut(ctx, "unknownChainID", providerAddr)) + // if validator (`providerAddr`) is to be opted in, then we cancel that the validator is about // to be opted out and do not consider the validator to opt out providerKeeper.SetToBeOptedIn(ctx, "chainID", providerAddr) + providerKeeper.SetProposedConsumerChain(ctx, "chainID", 1) require.True(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) - providerKeeper.HandleOptOut(ctx, "chainID", providerAddr) + err := providerKeeper.HandleOptOut(ctx, "chainID", providerAddr) + require.NoError(t, err) require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", providerAddr)) require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) // if validator (`providerAddr`) is not opted in, then the validator cannot be opted out providerKeeper.DeleteOptedIn(ctx, "chainID", providerAddr) - providerKeeper.HandleOptOut(ctx, "chainID", providerAddr) + err = providerKeeper.HandleOptOut(ctx, "chainID", providerAddr) + require.NoError(t, err) require.False(t, providerKeeper.IsToBeOptedOut(ctx, "chainID", providerAddr)) } From 78e12c8ee83aa6d7a4d452093664e797d0501395 Mon Sep 17 00:00:00 2001 From: insumity Date: Wed, 7 Feb 2024 10:44:09 +0100 Subject: [PATCH 7/8] added key assignment --- x/ccv/provider/keeper/key_assignment.go | 48 +++++++++++++++++ x/ccv/provider/keeper/msg_server.go | 41 +------------- x/ccv/provider/keeper/partial_set_security.go | 16 +++++- .../keeper/partial_set_security_test.go | 53 +++++++++++++++++++ 4 files changed, 117 insertions(+), 41 deletions(-) diff --git a/x/ccv/provider/keeper/key_assignment.go b/x/ccv/provider/keeper/key_assignment.go index c54d922f0f..fc864c6417 100644 --- a/x/ccv/provider/keeper/key_assignment.go +++ b/x/ccv/provider/keeper/key_assignment.go @@ -1,6 +1,7 @@ package keeper import ( + "encoding/base64" "fmt" errorsmod "cosmossdk.io/errors" @@ -15,6 +16,53 @@ import ( ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types" ) +// ParseConsumerKey parses the ED25519 PubKey`consumerKey` from a JSON string +// and constructs its corresponding `tmprotocrypto.PublicKey` +func (k Keeper) ParseConsumerKey(consumerKey string) (tmprotocrypto.PublicKey, error) { + // parse consumer key as long as it's in the right format + pkType, keyStr, err := types.ParseConsumerKeyFromJson(consumerKey) + if err != nil { + return tmprotocrypto.PublicKey{}, err + } + + // Note: the correct way to decide if a key type is supported is to check the + // consensus params. However this functionality was disabled in https://github.com/cosmos/interchain-security/pull/916 + // as a quick way to get ed25519 working, avoiding amino/proto-any marshalling issues. + + // make sure the consumer key type is supported + // cp := ctx.ConsensusParams() + // if cp != nil && cp.Validator != nil { + // if !tmstrings.StringInSlice(pkType, cp.Validator.PubKeyTypes) { + // return nil, errorsmod.Wrapf( + // stakingtypes.ErrValidatorPubKeyTypeNotSupported, + // "got: %s, expected one of: %s", pkType, cp.Validator.PubKeyTypes, + // ) + // } + // } + + // For now, only accept ed25519. + // TODO: decide what types should be supported. + if pkType != "/cosmos.crypto.ed25519.PubKey" { + return tmprotocrypto.PublicKey{}, errorsmod.Wrapf( + stakingtypes.ErrValidatorPubKeyTypeNotSupported, + "got: %s, expected: %s", pkType, "/cosmos.crypto.ed25519.PubKey", + ) + } + + pubKeyBytes, err := base64.StdEncoding.DecodeString(keyStr) + if err != nil { + return tmprotocrypto.PublicKey{}, err + } + + consumerTMPublicKey := tmprotocrypto.PublicKey{ + Sum: &tmprotocrypto.PublicKey_Ed25519{ + Ed25519: pubKeyBytes, + }, + } + + return consumerTMPublicKey, nil +} + // GetValidatorConsumerPubKey returns a validator's public key assigned for a consumer chain func (k Keeper) GetValidatorConsumerPubKey( ctx sdk.Context, diff --git a/x/ccv/provider/keeper/msg_server.go b/x/ccv/provider/keeper/msg_server.go index c4afb9bfc3..4863cd0d66 100644 --- a/x/ccv/provider/keeper/msg_server.go +++ b/x/ccv/provider/keeper/msg_server.go @@ -2,15 +2,12 @@ package keeper import ( "context" - "encoding/base64" - errorsmod "cosmossdk.io/errors" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - tmprotocrypto "github.com/cometbft/cometbft/proto/tendermint/crypto" tmtypes "github.com/cometbft/cometbft/types" "github.com/cosmos/interchain-security/v4/x/ccv/provider/types" @@ -45,47 +42,11 @@ func (k msgServer) AssignConsumerKey(goCtx context.Context, msg *types.MsgAssign return nil, stakingtypes.ErrNoValidatorFound } - // parse consumer key as long as it's in the right format - pkType, keyStr, err := types.ParseConsumerKeyFromJson(msg.ConsumerKey) - if err != nil { - return nil, err - } - - // Note: the correct way to decide if a key type is supported is to check the - // consensus params. However this functionality was disabled in https://github.com/cosmos/interchain-security/pull/916 - // as a quick way to get ed25519 working, avoiding amino/proto-any marshalling issues. - - // make sure the consumer key type is supported - // cp := ctx.ConsensusParams() - // if cp != nil && cp.Validator != nil { - // if !tmstrings.StringInSlice(pkType, cp.Validator.PubKeyTypes) { - // return nil, errorsmod.Wrapf( - // stakingtypes.ErrValidatorPubKeyTypeNotSupported, - // "got: %s, expected one of: %s", pkType, cp.Validator.PubKeyTypes, - // ) - // } - // } - - // For now, only accept ed25519. - // TODO: decide what types should be supported. - if pkType != "/cosmos.crypto.ed25519.PubKey" { - return nil, errorsmod.Wrapf( - stakingtypes.ErrValidatorPubKeyTypeNotSupported, - "got: %s, expected: %s", pkType, "/cosmos.crypto.ed25519.PubKey", - ) - } - - pubKeyBytes, err := base64.StdEncoding.DecodeString(keyStr) + consumerTMPublicKey, err := k.ParseConsumerKey(msg.ConsumerKey) if err != nil { return nil, err } - consumerTMPublicKey := tmprotocrypto.PublicKey{ - Sum: &tmprotocrypto.PublicKey_Ed25519{ - Ed25519: pubKeyBytes, - }, - } - if err := k.Keeper.AssignConsumerKey(ctx, msg.ChainId, validator, consumerTMPublicKey); err != nil { return nil, err } diff --git a/x/ccv/provider/keeper/partial_set_security.go b/x/ccv/provider/keeper/partial_set_security.go index 2cfdaa7292..8a7647cff5 100644 --- a/x/ccv/provider/keeper/partial_set_security.go +++ b/x/ccv/provider/keeper/partial_set_security.go @@ -3,6 +3,7 @@ package keeper import ( errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/cosmos/interchain-security/v4/x/ccv/provider/types" ) @@ -28,7 +29,20 @@ func (k Keeper) HandleOptIn(ctx sdk.Context, chainID string, providerAddr types. } if consumerKey != nil { - // TODO (PR 1586): assign consumer key in this case + consumerTMPublicKey, err := k.ParseConsumerKey(*consumerKey) + if err != nil { + return err + } + + validator, found := k.stakingKeeper.GetValidatorByConsAddr(ctx, providerAddr.Address) + if !found { + return stakingtypes.ErrNoValidatorFound + } + + err = k.AssignConsumerKey(ctx, chainID, validator, consumerTMPublicKey) + if err != nil { + return err + } } return nil diff --git a/x/ccv/provider/keeper/partial_set_security_test.go b/x/ccv/provider/keeper/partial_set_security_test.go index 6321c5a7d6..1ca5285790 100644 --- a/x/ccv/provider/keeper/partial_set_security_test.go +++ b/x/ccv/provider/keeper/partial_set_security_test.go @@ -1,8 +1,14 @@ package keeper_test import ( + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" testkeeper "github.com/cosmos/interchain-security/v4/testutil/keeper" "github.com/cosmos/interchain-security/v4/x/ccv/provider/types" + ccvtypes "github.com/cosmos/interchain-security/v4/x/ccv/types" + "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" "testing" ) @@ -31,6 +37,53 @@ func TestHandleOptIn(t *testing.T) { require.False(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) } +func TestHandleOptInWithConsumerKey(t *testing.T) { + providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) + defer ctrl.Finish() + + // generate a consensus public key for the provider + providerConsPubKey := ed25519.GenPrivKeyFromSecret([]byte{1}).PubKey() + consAddr := sdk.ConsAddress(providerConsPubKey.Address()) + providerAddr := types.NewProviderConsAddress(consAddr) + + calls := []*gomock.Call{ + mocks.MockStakingKeeper.EXPECT(). + GetValidatorByConsAddr(gomock.Any(), gomock.Any()). + DoAndReturn(func(ctx sdk.Context, addr sdk.ConsAddress) (stakingtypes.Validator, bool) { + if addr.Equals(providerAddr.Address) { + // Given `providerAddr`, `GetValidatorByConsAddr` returns a validator with the + // exact same `ConsensusPubkey` + pkAny, _ := codectypes.NewAnyWithValue(providerConsPubKey) + return stakingtypes.Validator{ConsensusPubkey: pkAny}, true + } else { + // for any other consensus address, we cannot find a validator + return stakingtypes.Validator{}, false + } + }).Times(2), + } + + gomock.InOrder(calls...) + providerKeeper.SetProposedConsumerChain(ctx, "chainID", 1) + + // create a sample consumer key to assign to the `providerAddr` validator + // on the consumer chain with id `chainID` + consumerKey := "{\"@type\":\"/cosmos.crypto.ed25519.PubKey\",\"key\":\"Ui5Gf1+mtWUdH8u3xlmzdKID+F3PK0sfXZ73GZ6q6is=\"}" + expectedConsumerPubKey, _ := providerKeeper.ParseConsumerKey(consumerKey) + + err := providerKeeper.HandleOptIn(ctx, "chainID", providerAddr, &consumerKey) + require.NoError(t, err) + + // assert that the consumeKey was assigned to `providerAddr` validator on chain with id `chainID` + actualConsumerPubKey, found := providerKeeper.GetValidatorConsumerPubKey(ctx, "chainID", providerAddr) + require.True(t, found) + require.Equal(t, expectedConsumerPubKey, actualConsumerPubKey) + + // assert that the `consumerAddr` to `providerAddr` association was set as well + consumerAddr, _ := ccvtypes.TMCryptoPublicKeyToConsAddr(actualConsumerPubKey) + actualProviderConsAddr, found := providerKeeper.GetValidatorByConsumerAddr(ctx, "chainID", types.NewConsumerConsAddress(consumerAddr)) + require.Equal(t, providerAddr, actualProviderConsAddr) +} + func TestHandleOptOut(t *testing.T) { providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() From 656adc23d4e128494603c8e2b72997f892160aca Mon Sep 17 00:00:00 2001 From: insumity Date: Wed, 7 Feb 2024 11:21:46 +0100 Subject: [PATCH 8/8] add contraint such that opt out only works if the chain is running --- x/ccv/provider/keeper/partial_set_security.go | 8 +++++--- x/ccv/provider/keeper/partial_set_security_test.go | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/x/ccv/provider/keeper/partial_set_security.go b/x/ccv/provider/keeper/partial_set_security.go index 8a7647cff5..e1bf9cc14f 100644 --- a/x/ccv/provider/keeper/partial_set_security.go +++ b/x/ccv/provider/keeper/partial_set_security.go @@ -17,7 +17,7 @@ func (k Keeper) HandleOptIn(ctx sdk.Context, chainID string, providerAddr types. if !k.IsConsumerProposedOrRegistered(ctx, chainID) { return errorsmod.Wrapf( types.ErrUnknownConsumerChainId, - "opting in to an unknown consumer chain id: %s", chainID) + "opting in to an unknown consumer chain, with id: %s", chainID) } if k.IsToBeOptedOut(ctx, chainID, providerAddr) { @@ -49,10 +49,12 @@ func (k Keeper) HandleOptIn(ctx sdk.Context, chainID string, providerAddr types. } func (k Keeper) HandleOptOut(ctx sdk.Context, chainID string, providerAddr types.ProviderConsAddress) error { - if !k.IsConsumerProposedOrRegistered(ctx, chainID) { + if _, found := k.GetConsumerClientId(ctx, chainID); !found { + // A validator can only opt out from a running chain. We check this by checking the consumer client id, because + // `SetConsumerClientId` is set when the chain starts in `CreateConsumerClientInCachedCtx` of `BeginBlockInit`. return errorsmod.Wrapf( types.ErrUnknownConsumerChainId, - "opting out of an unknown consumer chain id: %s", chainID) + "opting out of an unknown or not running consumer chain, with id: %s", chainID) } if k.IsToBeOptedIn(ctx, chainID, providerAddr) { diff --git a/x/ccv/provider/keeper/partial_set_security_test.go b/x/ccv/provider/keeper/partial_set_security_test.go index 1ca5285790..4831723bec 100644 --- a/x/ccv/provider/keeper/partial_set_security_test.go +++ b/x/ccv/provider/keeper/partial_set_security_test.go @@ -90,13 +90,13 @@ func TestHandleOptOut(t *testing.T) { providerAddr := types.NewProviderConsAddress([]byte("providerAddr")) - // trying to opt out from a non-proposed and non-registered chain returns an error + // trying to opt out from a not running chain returns an error require.Error(t, providerKeeper.HandleOptOut(ctx, "unknownChainID", providerAddr)) // if validator (`providerAddr`) is to be opted in, then we cancel that the validator is about // to be opted out and do not consider the validator to opt out providerKeeper.SetToBeOptedIn(ctx, "chainID", providerAddr) - providerKeeper.SetProposedConsumerChain(ctx, "chainID", 1) + providerKeeper.SetConsumerClientId(ctx, "chainID", "clientID") require.True(t, providerKeeper.IsToBeOptedIn(ctx, "chainID", providerAddr)) err := providerKeeper.HandleOptOut(ctx, "chainID", providerAddr) require.NoError(t, err)