From c8787bc46110a870554373529f9fccd011c95ae7 Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 25 Nov 2022 18:08:00 +0000 Subject: [PATCH] Squashed commit of the following: commit aca9578ddb964845ea6636b5c74a9c0de532bcf6 Author: mpoke Date: Fri Nov 25 14:50:45 2022 +0100 fix linter commit 6d8cd10c87f00757785a56a84a4b237a9d58eaa5 Author: mpoke Date: Fri Nov 25 14:46:11 2022 +0100 adding e2e tests commit 7fbbc7663c12f1995fd92dbeb34346251cb91425 Merge: e772dfb6 095a0760 Author: Marius Poke Date: Fri Nov 25 12:04:15 2022 +0100 Merge branch 'main' into marius/key-assignment commit e772dfb6543a373d68be41165d494fe6ccc830ac Author: mpoke Date: Fri Nov 25 11:47:25 2022 +0100 fix address conversion commit 095a0760566dc795b4b840deb5cbe189891d10c0 Author: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Wed Nov 23 11:12:48 2022 -0800 Multi-consumer capable e2e tests (#475) * changes * mas * Update README.md * Update README.md * sorry for the friday night emails * Update instance_test.go * wip * wip * wip * wip * wip * wip * wip * wip * works * Update generic_setup.go * Update setup.go * smol * small * path to ccv chan setup * todos * Update setup.go * Create debug_test.go * democ * Update debug_test.go * setup all ccv channels * bump to main * another bump, missed one * fix after merge main * fixes * Update slashing.go * expired client tests * checks * fixed the stuff * smol * changes * updates * cleans * clean * todo * fixes * cleans * Update slashing.go * Update slashing.go Co-authored-by: Jehan --- tests/e2e/README.md | 1 + tests/e2e/common.go | 19 +- tests/e2e/key_assignment.go | 256 ++++++++++++++++++++++++ x/ccv/provider/keeper/key_assignment.go | 2 +- x/ccv/provider/types/errors.go | 1 + 5 files changed, 273 insertions(+), 6 deletions(-) create mode 100644 tests/e2e/key_assignment.go diff --git a/tests/e2e/README.md b/tests/e2e/README.md index 3657117adc..3cf782bce2 100644 --- a/tests/e2e/README.md +++ b/tests/e2e/README.md @@ -13,6 +13,7 @@ E2e tests are categorized into files as follows: - `stop_consumer.go` - e2e tests for the _Consumer Chain Removal_ sub-protocol - `normal_operations.go` - e2e tests for _normal operations_ of ICS enabled chains - `expired_client.go` - e2e tests for testing expired clients +- `key_assignment.go` - e2e tests for testing key assignment - `instance_test.go` - ties the e2e test structure into golang's standard test mechanism, with appropriate definitions for concrete app types and setup callback To run the e2e tests defined in this repo on any arbitrary consumer and provider implementation, copy the pattern exemplified in `instance_test.go` and `specific_setup.go` diff --git a/tests/e2e/common.go b/tests/e2e/common.go index ffd0e5473c..f0ecb629f1 100644 --- a/tests/e2e/common.go +++ b/tests/e2e/common.go @@ -189,6 +189,7 @@ func relayAllCommittedPackets( srcPortID string, srcChannelID string, expectedPackets int, + msgAndArgs ...interface{}, ) { // check that the packets are committed in state commitments := srcChain.App.GetIBCKeeper().ChannelKeeper.GetAllPacketCommitmentsAtChannel( @@ -196,18 +197,26 @@ func relayAllCommittedPackets( srcPortID, srcChannelID, ) - s.Require().Equal(expectedPackets, len(commitments), - "actual number of packet commitments does not match expectation") + s.Require().Equal( + expectedPackets, + len(commitments), + fmt.Sprintf("actual number of packet commitments does not match expectation; %s", msgAndArgs...), + ) // relay all packets from srcChain to counterparty for _, commitment := range commitments { // - get packets packet, found := srcChain.GetSentPacket(commitment.Sequence, srcChannelID) - s.Require().True(found, "did not find sent packet") - + s.Require().True( + found, + fmt.Sprintf("did not find sent packet; %s", msgAndArgs...), + ) // - relay the packet err := path.RelayPacket(packet) - s.Require().NoError(err) + s.Require().NoError( + err, + fmt.Sprintf("error while relaying packets; %s", msgAndArgs...), + ) } } diff --git a/tests/e2e/key_assignment.go b/tests/e2e/key_assignment.go new file mode 100644 index 0000000000..5987743cd4 --- /dev/null +++ b/tests/e2e/key_assignment.go @@ -0,0 +1,256 @@ +package e2e + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/cosmos/ibc-go/v3/testing/mock" + providerkeeper "github.com/cosmos/interchain-security/x/ccv/provider/keeper" + ccv "github.com/cosmos/interchain-security/x/ccv/types" + tmencoding "github.com/tendermint/tendermint/crypto/encoding" + tmprotocrypto "github.com/tendermint/tendermint/proto/tendermint/crypto" +) + +func (s *CCVTestSuite) TestKeyAssignment() { + testCases := []struct { + name string + assignFunc func(*providerkeeper.Keeper) error + expError bool + expPacketCount int + }{ + { + "assignment during channel init", func(pk *providerkeeper.Keeper) error { + // key assignment + validator, consumerKey := generateNewConsumerKey(s, 0) + err := pk.AssignConsumerKey(s.providerCtx(), s.consumerChain.ChainID, validator, consumerKey) + if err != nil { + return err + } + + // check that a VSCPacket is queued + s.providerChain.NextBlock() + pendingPackets := pk.GetPendingPackets(s.providerCtx(), s.consumerChain.ChainID) + s.Require().Len(pendingPackets, 1) + + // establish CCV channel + s.SetupCCVChannel(s.path) + + return nil + }, false, 2, + }, + { + "assignment after channel init", func(pk *providerkeeper.Keeper) error { + // establish CCV channel + s.SetupCCVChannel(s.path) + + // key assignment + validator, consumerKey := generateNewConsumerKey(s, 0) + err := pk.AssignConsumerKey(s.providerCtx(), s.consumerChain.ChainID, validator, consumerKey) + if err != nil { + return err + } + s.providerChain.NextBlock() + + return nil + }, false, 2, + }, + { + "assignment with power change", func(pk *providerkeeper.Keeper) error { + // establish CCV channel + s.SetupCCVChannel(s.path) + + // key assignment + validator, consumerKey := generateNewConsumerKey(s, 0) + err := pk.AssignConsumerKey(s.providerCtx(), s.consumerChain.ChainID, validator, consumerKey) + if err != nil { + return err + } + + // Bond some tokens on provider to change validator powers + bondAmt := sdk.NewInt(1000000) + delAddr := s.providerChain.SenderAccount.GetAddress() + delegate(s, delAddr, bondAmt) + + s.providerChain.NextBlock() + + return nil + }, false, 2, + }, + { + "double same-key assignment in same block", func(pk *providerkeeper.Keeper) error { + // establish CCV channel + s.SetupCCVChannel(s.path) + + // key assignment + validator, consumerKey := generateNewConsumerKey(s, 0) + err := pk.AssignConsumerKey(s.providerCtx(), s.consumerChain.ChainID, validator, consumerKey) + if err != nil { + return err + } + + // same key assignment + err = pk.AssignConsumerKey(s.providerCtx(), s.consumerChain.ChainID, validator, consumerKey) + if err != nil { + return err + } + s.providerChain.NextBlock() + + return nil + }, true, 2, + }, + { + "double key assignment in same block", func(pk *providerkeeper.Keeper) error { + // establish CCV channel + s.SetupCCVChannel(s.path) + + // key assignment + validator, consumerKey := generateNewConsumerKey(s, 0) + err := pk.AssignConsumerKey(s.providerCtx(), s.consumerChain.ChainID, validator, consumerKey) + if err != nil { + return err + } + + // same key assignment + validator, consumerKey = generateNewConsumerKey(s, 0) + err = pk.AssignConsumerKey(s.providerCtx(), s.consumerChain.ChainID, validator, consumerKey) + if err != nil { + return err + } + s.providerChain.NextBlock() + + return nil + }, false, 2, + }, + { + "double same-key assignment in different blocks", func(pk *providerkeeper.Keeper) error { + // establish CCV channel + s.SetupCCVChannel(s.path) + + // key assignment + validator, consumerKey := generateNewConsumerKey(s, 0) + err := pk.AssignConsumerKey(s.providerCtx(), s.consumerChain.ChainID, validator, consumerKey) + if err != nil { + return err + } + s.providerChain.NextBlock() + + // same key assignment + err = pk.AssignConsumerKey(s.providerCtx(), s.consumerChain.ChainID, validator, consumerKey) + if err != nil { + return err + } + s.providerChain.NextBlock() + + return nil + }, true, 2, + }, + { + "double key assignment in different blocks", func(pk *providerkeeper.Keeper) error { + // establish CCV channel + s.SetupCCVChannel(s.path) + + // key assignment + validator, consumerKey := generateNewConsumerKey(s, 0) + err := pk.AssignConsumerKey(s.providerCtx(), s.consumerChain.ChainID, validator, consumerKey) + if err != nil { + return err + } + s.providerChain.NextBlock() + + // same key assignment + validator, consumerKey = generateNewConsumerKey(s, 0) + err = pk.AssignConsumerKey(s.providerCtx(), s.consumerChain.ChainID, validator, consumerKey) + if err != nil { + return err + } + s.providerChain.NextBlock() + + return nil + }, false, 3, + }, + // TODO: this test should pass if we manage to change the client update mode to sequential + // { + // "key assignment for all validators in the same block", func(pk *providerkeeper.Keeper) error { + // // establish CCV channel + // s.SetupCCVChannel(s.path) + + // // key assignment + // for i, _ := range s.providerChain.Vals.Validators { + // validator, consumerKey := generateNewConsumerKey(s, i) + // err := pk.AssignConsumerKey(s.providerCtx(), s.consumerChain.ChainID, validator, consumerKey) + // if err != nil { + // return err + // } + // } + // // vscPakcketData := pk.GetPendingPackets(s.providerCtx(), s.consumerChain.ChainID) + // // s.Require().Len(vscPakcketData, 1) + // // s.Require().Len(vscPakcketData[0].ValidatorUpdates, 2*len(s.providerChain.Vals.Validators)) + + // s.providerChain.NextBlock() + + // return nil + // }, false, 2, + // }, + } + for i, tc := range testCases { + providerKeeper := s.providerApp.GetProviderKeeper() + + err := tc.assignFunc(&providerKeeper) + if tc.expError { + s.Require().Error(err, "test: "+tc.name) + } else { + s.Require().NoError(err, "test: "+tc.name) + } + + if !tc.expError { + // Bond some tokens on provider to change validator powers + bondAmt := sdk.NewInt(1000000) + delAddr := s.providerChain.SenderAccount.GetAddress() + delegate(s, delAddr, bondAmt) + + // Send CCV packet to consumer + s.providerChain.NextBlock() + + // Relay all VSC packets from provider to consumer + relayAllCommittedPackets( + s, + s.providerChain, + s.path, + ccv.ProviderPortID, + s.path.EndpointB.ChannelID, + tc.expPacketCount, + "test: "+tc.name, + ) + + // update clients + err := s.path.EndpointA.UpdateClient() + s.Require().NoError(err) + err = s.path.EndpointB.UpdateClient() + s.Require().NoError(err) + } + + if i+1 < len(testCases) { + // reset suite to reset provider client + s.SetupTest() + } + } +} + +// generateNewConsumerKey generate new consumer key for the validator with valIndex +func generateNewConsumerKey(s *CCVTestSuite, valIndex int) (stakingtypes.Validator, tmprotocrypto.PublicKey) { + // get validator + s.Require().Less(valIndex, len(s.providerChain.Vals.Validators)) + _, valAddr := s.getValByIdx(valIndex) + validator := s.getVal(s.providerCtx(), valAddr) + + // generate new PrivValidator + privVal := mock.NewPV() + tmPubKey, err := privVal.GetPubKey() + s.Require().NoError(err) + pubKey, err := tmencoding.PubKeyToProto(tmPubKey) + s.Require().NoError(err) + + // add Signer to the consumer chain + s.consumerChain.Signers[tmPubKey.Address().String()] = privVal + + return validator, pubKey +} diff --git a/x/ccv/provider/keeper/key_assignment.go b/x/ccv/provider/keeper/key_assignment.go index 0adccbbcaf..6371e44e64 100644 --- a/x/ccv/provider/keeper/key_assignment.go +++ b/x/ccv/provider/keeper/key_assignment.go @@ -394,7 +394,7 @@ func (k Keeper) AssignConsumerKey( if _, found := k.GetValidatorByConsumerAddr(ctx, chainID, consumerAddr); found { // mapping already exists; return error return sdkerrors.Wrapf( - types.ErrInvalidConsumerConsensusPubKey, "consumer key already exists", + types.ErrConsumerKeyExists, "consumer key already exists", ) } diff --git a/x/ccv/provider/types/errors.go b/x/ccv/provider/types/errors.go index 44056b13f9..cac3a9d0e1 100644 --- a/x/ccv/provider/types/errors.go +++ b/x/ccv/provider/types/errors.go @@ -15,4 +15,5 @@ var ( ErrConsumerKeyNotFound = sdkerrors.Register(ModuleName, 7, "consumer key not found") ErrNoValidatorConsumerAddress = sdkerrors.Register(ModuleName, 8, "error getting validator consumer address") ErrNoValidatorProviderAddress = sdkerrors.Register(ModuleName, 9, "error getting validator provider address") + ErrConsumerKeyExists = sdkerrors.Register(ModuleName, 10, "consumer consensus public key already exists") )