From 00ea78b7af771647ec787610fb6aadd80cbf0f00 Mon Sep 17 00:00:00 2001 From: Shawn Marshall-Spitzbart <44221603+smarshall-spitzbart@users.noreply.github.com> Date: Thu, 20 Oct 2022 08:15:57 -0700 Subject: [PATCH] Importable e2e tests (#401) --- README.md | 4 +- app/consumer-democracy/app.go | 48 ++++++ app/consumer/app.go | 28 ++++ app/provider/app.go | 29 ++++ tests/e2e/README.md | 24 +-- .../{channel_init_test.go => channel_init.go} | 33 ++-- tests/e2e/{common_test.go => common.go} | 69 ++++---- tests/e2e/{democracy_test.go => democracy.go} | 69 ++++---- .../{distribution_test.go => distribution.go} | 12 +- tests/e2e/instance_test.go | 59 +++++++ ...perations_test.go => normal_operations.go} | 9 +- tests/e2e/{setup_test.go => setup.go} | 59 +++++-- tests/e2e/{slashing_test.go => slashing.go} | 140 +++++++++-------- ...stop_consumer_test.go => stop_consumer.go} | 44 +++--- tests/e2e/{unbonding_test.go => unbonding.go} | 34 ++-- ...valset_update_test.go => valset_update.go} | 24 +-- testutil/e2e/interfaces.go | 148 ++++++++++++++++++ 17 files changed, 601 insertions(+), 232 deletions(-) rename tests/e2e/{channel_init_test.go => channel_init.go} (63%) rename tests/e2e/{common_test.go => common.go} (82%) rename tests/e2e/{democracy_test.go => democracy.go} (83%) rename tests/e2e/{distribution_test.go => distribution.go} (89%) create mode 100644 tests/e2e/instance_test.go rename tests/e2e/{normal_operations_test.go => normal_operations.go} (89%) rename tests/e2e/{setup_test.go => setup.go} (76%) rename tests/e2e/{slashing_test.go => slashing.go} (82%) rename tests/e2e/{stop_consumer_test.go => stop_consumer.go} (70%) rename tests/e2e/{unbonding_test.go => unbonding.go} (93%) rename tests/e2e/{valset_update_test.go => valset_update.go} (78%) create mode 100644 testutil/e2e/interfaces.go diff --git a/README.md b/README.md index add4c88354..cc6d7af437 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,9 @@ Unit tests are useful for simple standalone functionality, and CRUD operations. ### End to End (e2e) Tests -[e2e-tests](./tests/e2e/) utilize the [IBC Testing Package](https://github.com/cosmos/ibc-go/tree/main/testing), and test functionality that is wider in scope than a unit test, but still able to be validated in-memory. Ie. code where advancing blocks would be useful, simulated handshakes, simulated packet relays, etc. +[e2e-tests](./tests/e2e/) utilize the [IBC Testing Package](https://github.com/cosmos/ibc-go/tree/main/testing), and test functionality that is wider in scope than a unit test, but still able to be validated in-memory. Ie. code where advancing blocks would be useful, simulated handshakes, simulated packet relays, etc. + +To run e2e tests against your own consumer/provider implementations, use [instance_test.go](./tests/e2e/instance_test.go) as an example. All you'll need to do is make sure your applications implement the necessary interfaces defined in [interfaces.go](./testutil/e2e/interfaces.go), then pass in an appropriate callback to the testing suites. ### Differential Tests (WIP) diff --git a/app/consumer-democracy/app.go b/app/consumer-democracy/app.go index 515d325d2d..f3ac4b024b 100644 --- a/app/consumer-democracy/app.go +++ b/app/consumer-democracy/app.go @@ -84,6 +84,7 @@ import ( ccvdistrclient "github.com/cosmos/cosmos-sdk/x/distribution/client" ccvdistrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" ccvdistrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + "github.com/cosmos/interchain-security/testutil/e2e" ccvdistr "github.com/cosmos/interchain-security/x/ccv/democracy/distribution" ccvstakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" @@ -757,6 +758,53 @@ func (app *App) SimulationManager() *module.SimulationManager { return app.sm } +// DemocConsumerApp interface implementations for e2e tests + +// GetConsumerKeeper implements the ConsumerApp interface. +func (app *App) GetConsumerKeeper() ibcconsumerkeeper.Keeper { + return app.ConsumerKeeper +} + +// GetE2eBankKeeper implements the ConsumerApp interface. +func (app *App) GetE2eBankKeeper() e2e.E2eBankKeeper { + return app.BankKeeper +} + +// GetE2eAccountKeeper implements the ConsumerApp interface. +func (app *App) GetE2eAccountKeeper() e2e.E2eAccountKeeper { + return app.AccountKeeper +} + +// GetE2eSlashingKeeper implements the ConsumerApp interface. +func (app *App) GetE2eSlashingKeeper() e2e.E2eSlashingKeeper { + return app.SlashingKeeper +} + +// GetE2eEvidenceKeeper implements the ConsumerApp interface. +func (app *App) GetE2eEvidenceKeeper() e2e.E2eEvidenceKeeper { + return app.EvidenceKeeper +} + +// GetE2eStakingKeeper implements the ConsumerApp interface. +func (app *App) GetE2eStakingKeeper() e2e.E2eStakingKeeper { + return app.StakingKeeper +} + +// GetE2eDistributionKeeper implements the ConsumerApp interface. +func (app *App) GetE2eDistributionKeeper() e2e.E2eDistributionKeeper { + return app.DistrKeeper +} + +// GetE2eMintKeeper implements the ConsumerApp interface. +func (app *App) GetE2eMintKeeper() e2e.E2eMintKeeper { + return app.MintKeeper +} + +// GetE2eGovKeeper implements the ConsumerApp interface. +func (app *App) GetE2eGovKeeper() e2e.E2eGovKeeper { + return app.GovKeeper +} + // TestingApp functions // GetBaseApp implements the TestingApp interface. diff --git a/app/consumer/app.go b/app/consumer/app.go index 7bf07e3851..4cd1dee606 100644 --- a/app/consumer/app.go +++ b/app/consumer/app.go @@ -77,6 +77,7 @@ import ( tmos "github.com/tendermint/tendermint/libs/os" dbm "github.com/tendermint/tm-db" + "github.com/cosmos/interchain-security/testutil/e2e" ibcconsumer "github.com/cosmos/interchain-security/x/ccv/consumer" ibcconsumerkeeper "github.com/cosmos/interchain-security/x/ccv/consumer/keeper" ibcconsumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" @@ -651,6 +652,33 @@ func (app *App) SimulationManager() *module.SimulationManager { return app.sm } +// ConsumerApp interface implementations for e2e tests + +// GetConsumerKeeper implements the ConsumerApp interface. +func (app *App) GetConsumerKeeper() ibcconsumerkeeper.Keeper { + return app.ConsumerKeeper +} + +// GetE2eBankKeeper implements the ConsumerApp interface. +func (app *App) GetE2eBankKeeper() e2e.E2eBankKeeper { + return app.BankKeeper +} + +// GetE2eAccountKeeper implements the ConsumerApp interface. +func (app *App) GetE2eAccountKeeper() e2e.E2eAccountKeeper { + return app.AccountKeeper +} + +// GetE2eSlashingKeeper implements the ConsumerApp interface. +func (app *App) GetE2eSlashingKeeper() e2e.E2eSlashingKeeper { + return app.SlashingKeeper +} + +// GetE2eEvidenceKeeper implements the ConsumerApp interface. +func (app *App) GetE2eEvidenceKeeper() e2e.E2eEvidenceKeeper { + return app.EvidenceKeeper +} + // TestingApp functions // GetBaseApp implements the TestingApp interface. diff --git a/app/provider/app.go b/app/provider/app.go index ec7ab612d4..25ec012836 100644 --- a/app/provider/app.go +++ b/app/provider/app.go @@ -106,6 +106,8 @@ import ( ibcproviderkeeper "github.com/cosmos/interchain-security/x/ccv/provider/keeper" providertypes "github.com/cosmos/interchain-security/x/ccv/provider/types" + e2e "github.com/cosmos/interchain-security/testutil/e2e" + "github.com/tendermint/spm/cosmoscmd" // unnamed import of statik for swagger UI support @@ -796,6 +798,33 @@ func (app *App) SimulationManager() *module.SimulationManager { return app.sm } +// ProviderApp interface implementations for e2e tests + +// GetProviderKeeper implements the ProviderApp interface. +func (app *App) GetProviderKeeper() ibcproviderkeeper.Keeper { + return app.ProviderKeeper +} + +// GetE2eStakingKeeper implements the ProviderApp interface. +func (app *App) GetE2eStakingKeeper() e2e.E2eStakingKeeper { + return app.StakingKeeper +} + +// GetE2eBankKeeper implements the ProviderApp interface. +func (app *App) GetE2eBankKeeper() e2e.E2eBankKeeper { + return app.BankKeeper +} + +// GetE2eSlashingKeeper implements the ProviderApp interface. +func (app *App) GetE2eSlashingKeeper() e2e.E2eSlashingKeeper { + return app.SlashingKeeper +} + +// GetE2eDistributionKeeper implements the ProviderApp interface. +func (app *App) GetE2eDistributionKeeper() e2e.E2eDistributionKeeper { + return app.DistrKeeper +} + // TestingApp functions // GetBaseApp implements the TestingApp interface. diff --git a/tests/e2e/README.md b/tests/e2e/README.md index da07797183..b8ad9d1970 100644 --- a/tests/e2e/README.md +++ b/tests/e2e/README.md @@ -1,13 +1,17 @@ -## End To End Testing + +# End To End Testing E2e tests are categorized into files as follows: -- `setup_test.go` - setup for the e2e tests -- `common_test.go` - helper functions -- `channel_init_test.go` - e2e tests for the _Channel Initialization_ sub-protocol -- `valset_update_test.go` - e2e tests for the _Validator Set Update_ sub-protocol -- `unbonding_test.go` - e2e tests for the _Completion of Unbonding Operations_ -- `slashing_test.go` - e2e tests for the _Consumer Initiated Slashing_ sub-protocol -- `distribution_test.go` - e2e tests for the _Reward Distribution_ sub-protocol -- `stop_consumer_test.go` - e2e tests for the _Consumer Chain Removal_ sub-protocol -- `normal_operations_test.go` - e2e tests for _normal operations_ of ICS enabled chains \ No newline at end of file +- `setup.go` - setup for the e2e tests +- `common.go` - helper functions +- `channel_init.go` - e2e tests for the _Channel Initialization_ sub-protocol +- `valset_update.go` - e2e tests for the _Validator Set Update_ sub-protocol +- `unbonding.go` - e2e tests for the _Completion of Unbonding Operations_ +- `slashing.go` - e2e tests for the _Consumer Initiated Slashing_ sub-protocol +- `distribution.go` - e2e tests for the _Reward Distribution_ sub-protocol +- `stop_consumer.go` - e2e tests for the _Consumer Chain Removal_ sub-protocol +- `normal_operations.go` - e2e tests for _normal operations_ of ICS enabled chains +- `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` diff --git a/tests/e2e/channel_init_test.go b/tests/e2e/channel_init.go similarity index 63% rename from tests/e2e/channel_init_test.go rename to tests/e2e/channel_init.go index c319fda16f..ac8c259054 100644 --- a/tests/e2e/channel_init_test.go +++ b/tests/e2e/channel_init.go @@ -1,16 +1,13 @@ -package e2e_test +package e2e import ( cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" - app "github.com/cosmos/interchain-security/app/consumer" - tmtypes "github.com/tendermint/tendermint/types" channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" - appConsumer "github.com/cosmos/interchain-security/app/consumer" ccv "github.com/cosmos/interchain-security/x/ccv/types" abci "github.com/tendermint/tendermint/abci/types" @@ -19,24 +16,28 @@ import ( ) func (suite *CCVTestSuite) TestConsumerGenesis() { - genesis := suite.consumerChain.App.(*app.App).ConsumerKeeper.ExportGenesis(suite.consumerChain.GetContext()) + + consumerKeeper := suite.consumerApp.GetConsumerKeeper() + + genesis := consumerKeeper.ExportGenesis(suite.consumerChain.GetContext()) suite.Require().Equal(suite.providerClient, genesis.ProviderClientState) suite.Require().Equal(suite.providerConsState, genesis.ProviderConsensusState) suite.Require().NotPanics(func() { - suite.consumerChain.App.(*app.App).ConsumerKeeper.InitGenesis(suite.consumerChain.GetContext(), genesis) + consumerKeeper.InitGenesis(suite.consumerChain.GetContext(), genesis) // reset suite to reset provider client suite.SetupTest() + consumerKeeper = suite.consumerApp.GetConsumerKeeper() }) ctx := suite.consumerChain.GetContext() - portId := suite.consumerChain.App.(*app.App).ConsumerKeeper.GetPort(ctx) + portId := consumerKeeper.GetPort(ctx) suite.Require().Equal(ccv.ConsumerPortID, portId) - clientId, ok := suite.consumerChain.App.(*app.App).ConsumerKeeper.GetProviderClientID(ctx) + clientId, ok := consumerKeeper.GetProviderClientID(ctx) suite.Require().True(ok) - clientState, ok := suite.consumerChain.App.GetIBCKeeper().ClientKeeper.GetClientState(ctx, clientId) + clientState, ok := suite.consumerApp.GetIBCKeeper().ClientKeeper.GetClientState(ctx, clientId) suite.Require().True(ok) suite.Require().Equal(genesis.ProviderClientState, clientState, "client state not set correctly after InitGenesis") @@ -66,30 +67,30 @@ func (suite *CCVTestSuite) TestConsumerGenesis() { ccv.ProviderPortID, suite.path.EndpointB.ChannelID, ccv.ConsumerPortID, suite.path.EndpointA.ChannelID, clienttypes.NewHeight(1, 0), 0) - suite.consumerChain.App.(*app.App).ConsumerKeeper.OnRecvVSCPacket(suite.consumerChain.GetContext(), packet, pd) + consumerKeeper.OnRecvVSCPacket(suite.consumerChain.GetContext(), packet, pd) valUpdates := tmtypes.TM2PB.ValidatorUpdates(suite.providerChain.Vals) - restartGenesis := suite.consumerChain.App.(*app.App).ConsumerKeeper.ExportGenesis(suite.consumerChain.GetContext()) + restartGenesis := consumerKeeper.ExportGenesis(suite.consumerChain.GetContext()) suite.Require().Equal(valUpdates, restartGenesis.InitialValSet) // ensure reset genesis is set correctly providerChannel := suite.path.EndpointA.ChannelID suite.Require().Equal(providerChannel, restartGenesis.ProviderChannelId) - maturityTime := suite.consumerChain.App.(*app.App).ConsumerKeeper.GetPacketMaturityTime(suite.consumerChain.GetContext(), 1) - unbondingPeriod, found := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetUnbondingTime(suite.consumerCtx()) + maturityTime := consumerKeeper.GetPacketMaturityTime(suite.consumerChain.GetContext(), 1) + unbondingPeriod, found := consumerKeeper.GetUnbondingTime(suite.consumerCtx()) suite.Require().True(found) suite.Require().Equal(uint64(origTime.Add(unbondingPeriod).UnixNano()), maturityTime, "maturity time is not set correctly in genesis") suite.Require().NotPanics(func() { - suite.consumerChain.App.(*app.App).ConsumerKeeper.InitGenesis(suite.consumerChain.GetContext(), restartGenesis) + consumerKeeper.InitGenesis(suite.consumerChain.GetContext(), restartGenesis) }) } // TestProviderClientMatches tests that the provider client managed by the consumer keeper matches the client keeper's client state func (suite *CCVTestSuite) TestProviderClientMatches() { - providerClientID, ok := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderClientID(suite.consumerCtx()) + providerClientID, ok := suite.consumerApp.GetConsumerKeeper().GetProviderClientID(suite.consumerCtx()) suite.Require().True(ok) - clientState, _ := suite.consumerChain.App.GetIBCKeeper().ClientKeeper.GetClientState(suite.consumerCtx(), providerClientID) + clientState, _ := suite.consumerApp.GetIBCKeeper().ClientKeeper.GetClientState(suite.consumerCtx(), providerClientID) suite.Require().Equal(suite.providerClient, clientState, "stored client state does not match genesis provider client") } diff --git a/tests/e2e/common_test.go b/tests/e2e/common.go similarity index 82% rename from tests/e2e/common_test.go rename to tests/e2e/common.go index c329f877d2..e048f57ae2 100644 --- a/tests/e2e/common_test.go +++ b/tests/e2e/common.go @@ -1,13 +1,12 @@ -package e2e_test +package e2e import ( "strings" "time" sdk "github.com/cosmos/cosmos-sdk/types" - stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - + "github.com/cosmos/interchain-security/testutil/e2e" ccv "github.com/cosmos/interchain-security/x/ccv/types" "github.com/cosmos/interchain-security/x/ccv/utils" "github.com/stretchr/testify/require" @@ -19,9 +18,6 @@ import ( commitmenttypes "github.com/cosmos/ibc-go/v3/modules/core/23-commitment/types" ibctmtypes "github.com/cosmos/ibc-go/v3/modules/light-clients/07-tendermint/types" ibctesting "github.com/cosmos/ibc-go/v3/testing" - - appConsumer "github.com/cosmos/interchain-security/app/consumer" - appProvider "github.com/cosmos/interchain-security/app/provider" ) // ChainType defines the type of chain (either provider or consumer) @@ -41,22 +37,25 @@ func (s *CCVTestSuite) consumerCtx() sdk.Context { } func (s *CCVTestSuite) providerBondDenom() string { - return s.providerChain.App.(*appProvider.App).StakingKeeper.BondDenom(s.providerCtx()) + return s.providerApp.GetE2eStakingKeeper().BondDenom(s.providerCtx()) } -func (s *CCVTestSuite) getVal(index int) (validator stakingtypes.Validator, valAddr sdk.ValAddress) { +func (s *CCVTestSuite) getValByIdx(index int) (validator stakingtypes.Validator, valAddr sdk.ValAddress) { // Choose a validator, and get its address and data structure into the correct types tmValidator := s.providerChain.Vals.Validators[index] valAddr, err := sdk.ValAddressFromHex(tmValidator.Address.String()) s.Require().NoError(err) - validator, found := s.providerChain.App.(*appProvider.App).StakingKeeper.GetValidator(s.providerCtx(), valAddr) - s.Require().True(found) + return s.getVal(s.providerCtx(), valAddr), valAddr +} - return validator, valAddr +func (s *CCVTestSuite) getVal(ctx sdk.Context, valAddr sdk.ValAddress) stakingtypes.Validator { + validator, found := s.providerApp.GetE2eStakingKeeper().GetValidator(s.providerCtx(), valAddr) + s.Require().True(found) + return validator } func getBalance(s *CCVTestSuite, providerCtx sdk.Context, delAddr sdk.AccAddress) sdk.Int { - return s.providerChain.App.(*appProvider.App).BankKeeper.GetBalance(providerCtx, delAddr, s.providerBondDenom()).Amount + return s.providerApp.GetE2eBankKeeper().GetBalance(providerCtx, delAddr, s.providerBondDenom()).Amount } // delegateAndUndelegate delegates bondAmt from delAddr to the first validator @@ -85,19 +84,17 @@ func delegateAndUndelegate(s *CCVTestSuite, delAddr sdk.AccAddress, bondAmt sdk. func delegateAndRedelegate(s *CCVTestSuite, delAddr sdk.AccAddress, srcValAddr sdk.ValAddress, dstValAddr sdk.ValAddress, amount sdk.Int) { - stakingKeeper := s.providerChain.App.(*appProvider.App).StakingKeeper - // Delegate to src validator - srcValTokensBefore := stakingKeeper.Validator(s.providerCtx(), srcValAddr).GetBondedTokens() + srcValTokensBefore := s.getVal(s.providerCtx(), srcValAddr).GetBondedTokens() _, sharesDelegated, _ := delegate(s, delAddr, amount) // Assert expected amount was bonded to src validator - srcValTokensAfter := stakingKeeper.Validator(s.providerCtx(), srcValAddr).GetBondedTokens() + srcValTokensAfter := s.getVal(s.providerCtx(), srcValAddr).GetBondedTokens() s.Require().Equal(srcValTokensAfter.Sub(srcValTokensBefore), amount) s.providerChain.NextBlock() - dstValTokensBefore := stakingKeeper.Validator(s.providerCtx(), dstValAddr).GetBondedTokens() + dstValTokensBefore := s.getVal(s.providerCtx(), dstValAddr).GetBondedTokens() // redelegate shares from src to dst validators redelegate(s, delAddr, @@ -107,20 +104,20 @@ func delegateAndRedelegate(s *CCVTestSuite, delAddr sdk.AccAddress, ) // Assert expected amount was delegated to dst val - dstValTokensAfter := stakingKeeper.Validator(s.providerCtx(), dstValAddr).GetBondedTokens() + dstValTokensAfter := s.getVal(s.providerCtx(), dstValAddr).GetBondedTokens() s.Require().Equal(dstValTokensAfter.Sub(dstValTokensBefore), amount) // Assert delegated tokens amount returned to original value for src validator - s.Require().Equal(srcValTokensBefore, stakingKeeper.Validator(s.providerCtx(), srcValAddr).GetBondedTokens()) + s.Require().Equal(srcValTokensBefore, s.getVal(s.providerCtx(), srcValAddr).GetBondedTokens()) } // delegate delegates bondAmt to the first validator func delegate(s *CCVTestSuite, delAddr sdk.AccAddress, bondAmt sdk.Int) (initBalance sdk.Int, shares sdk.Dec, valAddr sdk.ValAddress) { initBalance = getBalance(s, s.providerCtx(), delAddr) // choose a validator - validator, valAddr := s.getVal(0) + validator, valAddr := s.getValByIdx(0) // delegate bondAmt tokens on provider to change validator powers - shares, err := s.providerChain.App.(*appProvider.App).StakingKeeper.Delegate( + shares, err := s.providerApp.GetE2eStakingKeeper().Delegate( s.providerCtx(), delAddr, bondAmt, @@ -136,11 +133,11 @@ func delegate(s *CCVTestSuite, delAddr sdk.AccAddress, bondAmt sdk.Int) (initBal // undelegate unbonds an amount of delegator shares from a given validator func undelegate(s *CCVTestSuite, delAddr sdk.AccAddress, valAddr sdk.ValAddress, sharesAmount sdk.Dec) (valsetUpdateId uint64) { - _, err := s.providerChain.App.(*appProvider.App).StakingKeeper.Undelegate(s.providerCtx(), delAddr, valAddr, sharesAmount) + _, err := s.providerApp.GetE2eStakingKeeper().Undelegate(s.providerCtx(), delAddr, valAddr, sharesAmount) s.Require().NoError(err) // save the current valset update ID - valsetUpdateID := s.providerChain.App.(*appProvider.App).ProviderKeeper.GetValidatorSetUpdateId(s.providerCtx()) + valsetUpdateID := s.providerApp.GetProviderKeeper().GetValidatorSetUpdateId(s.providerCtx()) return valsetUpdateID } @@ -149,10 +146,12 @@ func undelegate(s *CCVTestSuite, delAddr sdk.AccAddress, valAddr sdk.ValAddress, // on the provider chain using delegated funds from delAddr func redelegate(s *CCVTestSuite, delAddr sdk.AccAddress, valSrcAddr sdk.ValAddress, ValDstAddr sdk.ValAddress, sharesAmount sdk.Dec) { + + stakingKeeper := s.providerApp.GetE2eStakingKeeper() ctx := s.providerCtx() // delegate bondAmt tokens on provider to change validator powers - completionTime, err := s.providerChain.App.(*appProvider.App).StakingKeeper.BeginRedelegation( + completionTime, err := stakingKeeper.BeginRedelegation( ctx, delAddr, valSrcAddr, @@ -161,7 +160,6 @@ func redelegate(s *CCVTestSuite, delAddr sdk.AccAddress, valSrcAddr sdk.ValAddre ) s.Require().NoError(err) - stakingKeeper := s.providerChain.App.(*appProvider.App).StakingKeeper providerUnbondingPeriod := stakingKeeper.UnbondingTime(ctx) valSrc, found := stakingKeeper.GetValidator(ctx, valSrcAddr) @@ -214,8 +212,8 @@ func relayAllCommittedPackets( // to be one day larger than the consumer unbonding period. func incrementTimeByUnbondingPeriod(s *CCVTestSuite, chainType ChainType) { // Get unboding period from staking keeper - providerUnbondingPeriod := s.providerChain.App.GetStakingKeeper().UnbondingTime(s.providerCtx()) - consumerUnbondingPeriod, found := s.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetUnbondingTime(s.consumerCtx()) + providerUnbondingPeriod := s.providerApp.GetStakingKeeper().UnbondingTime(s.providerCtx()) + consumerUnbondingPeriod, found := s.consumerApp.GetConsumerKeeper().GetUnbondingTime(s.consumerCtx()) s.Require().True(found) expectedUnbondingPeriod := utils.ComputeConsumerUnbondingPeriod(providerUnbondingPeriod) s.Require().Equal(expectedUnbondingPeriod+24*time.Hour, providerUnbondingPeriod, "unexpected provider unbonding period") @@ -240,13 +238,13 @@ func incrementTimeByUnbondingPeriod(s *CCVTestSuite, chainType ChainType) { } func checkStakingUnbondingOps(s *CCVTestSuite, id uint64, found bool, onHold bool) { - stakingUnbondingOp, wasFound := getStakingUnbondingDelegationEntry(s.providerCtx(), s.providerChain.App.(*appProvider.App).StakingKeeper, id) + stakingUnbondingOp, wasFound := getStakingUnbondingDelegationEntry(s.providerCtx(), s.providerApp.GetE2eStakingKeeper(), id) s.Require().True(found == wasFound) s.Require().True(onHold == (0 < stakingUnbondingOp.UnbondingOnHoldRefCount)) } func checkCCVUnbondingOp(s *CCVTestSuite, providerCtx sdk.Context, chainID string, valUpdateID uint64, found bool) { - entries, wasFound := s.providerChain.App.(*appProvider.App).ProviderKeeper.GetUnbondingOpsFromIndex(providerCtx, chainID, valUpdateID) + entries, wasFound := s.providerApp.GetProviderKeeper().GetUnbondingOpsFromIndex(providerCtx, chainID, valUpdateID) s.Require().True(found == wasFound) if found { s.Require().True(len(entries) > 0, "No unbonding ops found") @@ -260,8 +258,7 @@ func checkCCVUnbondingOp(s *CCVTestSuite, providerCtx sdk.Context, chainID strin func checkRedelegations(s *CCVTestSuite, delAddr sdk.AccAddress, expect uint16) []stakingtypes.Redelegation { - redelegations := s.providerChain.App.(*appProvider.App).StakingKeeper. - GetRedelegations(s.providerCtx(), delAddr, 2) + redelegations := s.providerApp.GetE2eStakingKeeper().GetRedelegations(s.providerCtx(), delAddr, 2) s.Require().Len(redelegations, int(expect)) return redelegations @@ -273,7 +270,7 @@ func checkRedelegationEntryCompletionTime( s.Require().Equal(expectedCompletion, entry.CompletionTime) } -func getStakingUnbondingDelegationEntry(ctx sdk.Context, k stakingkeeper.Keeper, id uint64) (stakingUnbondingOp stakingtypes.UnbondingDelegationEntry, found bool) { +func getStakingUnbondingDelegationEntry(ctx sdk.Context, k e2e.E2eStakingKeeper, id uint64) (stakingUnbondingOp stakingtypes.UnbondingDelegationEntry, found bool) { stakingUbd, found := k.GetUnbondingDelegationByUnbondingId(ctx, id) for _, entry := range stakingUbd.Entries { @@ -290,7 +287,7 @@ func getStakingUnbondingDelegationEntry(ctx sdk.Context, k stakingkeeper.Keeper, // SendEmptyVSCPacket sends a VSC packet without any changes // to ensure that the channel gets established func (suite *CCVTestSuite) SendEmptyVSCPacket() { - providerKeeper := suite.providerChain.App.(*appProvider.App).ProviderKeeper + providerKeeper := suite.providerApp.GetProviderKeeper() oldBlockTime := suite.providerChain.GetContext().BlockTime() timeout := uint64(oldBlockTime.Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()) @@ -303,7 +300,7 @@ func (suite *CCVTestSuite) SendEmptyVSCPacket() { nil, ) - seq, ok := suite.providerChain.App.(*appProvider.App).GetIBCKeeper().ChannelKeeper.GetNextSequenceSend( + seq, ok := suite.providerApp.GetIBCKeeper().ChannelKeeper.GetNextSequenceSend( suite.providerChain.GetContext(), ccv.ProviderPortID, suite.path.EndpointB.ChannelID) suite.Require().True(ok) @@ -331,7 +328,7 @@ func (suite *CCVTestSuite) commitSlashPacket(ctx sdk.Context, packetData ccv.Sla // incrementTimeBy increments the overall time by jumpPeriod func incrementTimeBy(s *CCVTestSuite, jumpPeriod time.Duration) { // Get unboding period from staking keeper - consumerUnbondingPeriod, found := s.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetUnbondingTime(s.consumerChain.GetContext()) + consumerUnbondingPeriod, found := s.consumerApp.GetConsumerKeeper().GetUnbondingTime(s.consumerChain.GetContext()) s.Require().True(found) split := 1 if jumpPeriod > consumerUnbondingPeriod/utils.TrustingPeriodFraction { @@ -350,8 +347,6 @@ func incrementTimeBy(s *CCVTestSuite, jumpPeriod time.Duration) { } } -// TODO: The two CreateCustomClient methods below can be consolidated when test suite structures are consolidated - // CreateCustomClient creates an IBC client on the endpoint // using the given unbonding period. // It will update the clientID for the endpoint if the message diff --git a/tests/e2e/democracy_test.go b/tests/e2e/democracy.go similarity index 83% rename from tests/e2e/democracy_test.go rename to tests/e2e/democracy.go index 1b5d6d8f66..a8775df91c 100644 --- a/tests/e2e/democracy_test.go +++ b/tests/e2e/democracy.go @@ -1,4 +1,4 @@ -package e2e_test +package e2e import ( "fmt" @@ -11,17 +11,13 @@ import ( ibctesting "github.com/cosmos/ibc-go/v3/testing" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" - govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" "github.com/cosmos/cosmos-sdk/x/params/types/proposal" proposaltypes "github.com/cosmos/cosmos-sdk/x/params/types/proposal" - appConsumer "github.com/cosmos/interchain-security/app/consumer-democracy" - "github.com/cosmos/interchain-security/testutil/simapp" + "github.com/cosmos/interchain-security/testutil/e2e" consumerkeeper "github.com/cosmos/interchain-security/x/ccv/consumer/keeper" consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" - "github.com/stretchr/testify/suite" ) @@ -30,28 +26,41 @@ var consumerFraction, _ = sdk.NewDecFromStr(consumerkeeper.ConsumerRedistributeF type ConsumerDemocracyTestSuite struct { suite.Suite coordinator *ibctesting.Coordinator - providerChain *ibctesting.TestChain consumerChain *ibctesting.TestChain + consumerApp e2e.DemocConsumerApp + setupCallback DemocSetupCallback } -// SetupTest sets up in-mem state for the group of tests relevant to ccv with a democracy consumer -// TODO: Make this method more generalizable to be called by any provider/consumer implementation -func (democSuite *ConsumerDemocracyTestSuite) SetupTest() { - democSuite.coordinator, democSuite.providerChain, - democSuite.consumerChain = simapp.NewProviderConsumerDemocracyCoordinator(democSuite.T()) +// NewCCVTestSuite returns a new instance of ConsumerDemocracyTestSuite, +// ready to be tested against using suite.Run(). +func NewConsumerDemocracyTestSuite(setupCallback DemocSetupCallback) *ConsumerDemocracyTestSuite { + democSuite := new(ConsumerDemocracyTestSuite) + democSuite.setupCallback = setupCallback + return democSuite } -func TestConsumerDemocracyTestSuite(t *testing.T) { - suite.Run(t, new(ConsumerDemocracyTestSuite)) +// Callback for instantiating a new coordinator, consumer test chain, and consumer app +// before every test defined on the suite. +type DemocSetupCallback func(t *testing.T) ( + coord *ibctesting.Coordinator, + consumerChain *ibctesting.TestChain, + consumerApp e2e.DemocConsumerApp, +) + +// SetupTest sets up in-mem state before every test relevant to ccv with a democracy consumer +func (suite *ConsumerDemocracyTestSuite) SetupTest() { + // Instantiate new test utils using callback + suite.coordinator, suite.consumerChain, + suite.consumerApp = suite.setupCallback(suite.T()) } func (s *ConsumerDemocracyTestSuite) TestDemocracyRewardsDistribution() { s.consumerChain.NextBlock() - stakingKeeper := s.consumerChain.App.(*appConsumer.App).StakingKeeper - authKeeper := s.consumerChain.App.(*appConsumer.App).AccountKeeper - distrKeeper := s.consumerChain.App.(*appConsumer.App).DistrKeeper - bankKeeper := s.consumerChain.App.(*appConsumer.App).BankKeeper + stakingKeeper := s.consumerApp.GetE2eStakingKeeper() + accountKeeper := s.consumerApp.GetE2eAccountKeeper() + distrKeeper := s.consumerApp.GetE2eDistributionKeeper() + bankKeeper := s.consumerApp.GetE2eBankKeeper() bondDenom := stakingKeeper.BondDenom(s.consumerCtx()) currentRepresentativesRewards := map[string]sdk.Dec{} @@ -65,7 +74,7 @@ func (s *ConsumerDemocracyTestSuite) TestDemocracyRewardsDistribution() { } distrModuleAccount := distrKeeper.GetDistributionAccount(s.consumerCtx()) - providerRedistributeAccount := authKeeper.GetModuleAccount(s.consumerCtx(), consumertypes.ConsumerToSendToProviderName) + providerRedistributeAccount := accountKeeper.GetModuleAccount(s.consumerCtx(), consumertypes.ConsumerToSendToProviderName) //balance of consumer redistribute address will always be 0 when checked between 2 NextBlock() calls currentDistrModuleAccountBalance := sdk.NewDecFromInt(bankKeeper.GetBalance(s.consumerCtx(), distrModuleAccount.GetAddress(), bondDenom).Amount) @@ -118,11 +127,11 @@ func (s *ConsumerDemocracyTestSuite) TestDemocracyRewardsDistribution() { } func (s *ConsumerDemocracyTestSuite) TestDemocracyGovernanceWhitelisting() { - govKeeper := s.consumerChain.App.(*appConsumer.App).GovKeeper - stakingKeeper := s.consumerChain.App.(*appConsumer.App).StakingKeeper - bankKeeper := s.consumerChain.App.(*appConsumer.App).BankKeeper - authKeeper := s.consumerChain.App.(*appConsumer.App).AccountKeeper - mintKeeper := s.consumerChain.App.(*appConsumer.App).MintKeeper + govKeeper := s.consumerApp.GetE2eGovKeeper() + stakingKeeper := s.consumerApp.GetE2eStakingKeeper() + bankKeeper := s.consumerApp.GetE2eBankKeeper() + accountKeeper := s.consumerApp.GetE2eAccountKeeper() + mintKeeper := s.consumerApp.GetE2eMintKeeper() newAuthParamValue := uint64(128) newMintParamValue := sdk.NewDecWithPrec(1, 1) // "0.100000000000000000" allowedChange := proposal.ParamChange{Subspace: minttypes.ModuleName, Key: "InflationMax", Value: fmt.Sprintf("\"%s\"", newMintParamValue)} @@ -145,11 +154,11 @@ func (s *ConsumerDemocracyTestSuite) TestDemocracyGovernanceWhitelisting() { s.consumerChain.CurrentHeader.Time = s.consumerChain.CurrentHeader.Time.Add(votingParams.VotingPeriod) s.consumerChain.NextBlock() //at this moment, proposal is added, but not yet executed. we are saving old param values for comparison - oldAuthParamValue := authKeeper.GetParams(s.consumerCtx()).MaxMemoCharacters + oldAuthParamValue := accountKeeper.GetParams(s.consumerCtx()).MaxMemoCharacters oldMintParamValue := mintKeeper.GetParams(s.consumerCtx()).InflationMax s.consumerChain.NextBlock() //at this moment, proposal is executed or deleted if forbidden - currentAuthParamValue := authKeeper.GetParams(s.consumerCtx()).MaxMemoCharacters + currentAuthParamValue := accountKeeper.GetParams(s.consumerCtx()).MaxMemoCharacters currentMintParamValue := mintKeeper.GetParams(s.consumerCtx()).InflationMax //check that parameters are not changed, since the proposal contained both forbidden and allowed changes s.Assert().Equal(oldAuthParamValue, currentAuthParamValue) @@ -180,9 +189,9 @@ func (s *ConsumerDemocracyTestSuite) TestDemocracyGovernanceWhitelisting() { s.Assert().NoError(err) s.consumerChain.CurrentHeader.Time = s.consumerChain.CurrentHeader.Time.Add(votingParams.VotingPeriod) s.consumerChain.NextBlock() - oldAuthParamValue = authKeeper.GetParams(s.consumerCtx()).MaxMemoCharacters + oldAuthParamValue = accountKeeper.GetParams(s.consumerCtx()).MaxMemoCharacters s.consumerChain.NextBlock() - currentAuthParamValue = authKeeper.GetParams(s.consumerCtx()).MaxMemoCharacters + currentAuthParamValue = accountKeeper.GetParams(s.consumerCtx()).MaxMemoCharacters //check that parameters are not changed, since the proposal contained forbidden changes s.Assert().Equal(oldAuthParamValue, currentAuthParamValue) s.Assert().NotEqual(newAuthParamValue, currentAuthParamValue) @@ -190,7 +199,7 @@ func (s *ConsumerDemocracyTestSuite) TestDemocracyGovernanceWhitelisting() { s.Assert().Equal(votersOldBalances, getAccountsBalances(s.consumerCtx(), bankKeeper, bondDenom, votingAccounts)) } -func submitProposalWithDepositAndVote(govKeeper govkeeper.Keeper, ctx sdk.Context, paramChange proposaltypes.ParameterChangeProposal, +func submitProposalWithDepositAndVote(govKeeper e2e.E2eGovKeeper, ctx sdk.Context, paramChange proposaltypes.ParameterChangeProposal, accounts []ibctesting.SenderAccount, depositAmount sdk.Coins) error { proposal, err := govKeeper.SubmitProposal(ctx, ¶mChange) if err != nil { @@ -210,7 +219,7 @@ func submitProposalWithDepositAndVote(govKeeper govkeeper.Keeper, ctx sdk.Contex return nil } -func getAccountsBalances(ctx sdk.Context, bankKeeper bankkeeper.Keeper, bondDenom string, accounts []ibctesting.SenderAccount) map[string]sdk.Int { +func getAccountsBalances(ctx sdk.Context, bankKeeper e2e.E2eBankKeeper, bondDenom string, accounts []ibctesting.SenderAccount) map[string]sdk.Int { accountsBalances := map[string]sdk.Int{} for _, acc := range accounts { accountsBalances[string(acc.SenderAccount.GetAddress())] = diff --git a/tests/e2e/distribution_test.go b/tests/e2e/distribution.go similarity index 89% rename from tests/e2e/distribution_test.go rename to tests/e2e/distribution.go index 5eb7b12b77..b7727b0e2a 100644 --- a/tests/e2e/distribution_test.go +++ b/tests/e2e/distribution.go @@ -1,4 +1,4 @@ -package e2e_test +package e2e import ( "strings" @@ -6,8 +6,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" transfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" - app "github.com/cosmos/interchain-security/app/consumer" - providerApp "github.com/cosmos/interchain-security/app/provider" consumerkeeper "github.com/cosmos/interchain-security/x/ccv/consumer/keeper" consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" ccv "github.com/cosmos/interchain-security/x/ccv/types" @@ -28,12 +26,12 @@ func (s *CCVTestSuite) TestRewardsDistribution() { relayAllCommittedPackets(s, s.providerChain, s.path, ccv.ProviderPortID, s.path.EndpointB.ChannelID, 1) //reward for the provider chain will be sent after each 2 blocks - consumerParams := s.consumerChain.App.(*app.App).GetSubspace(consumertypes.ModuleName) + consumerParams := s.consumerApp.GetSubspace(consumertypes.ModuleName) consumerParams.Set(s.consumerCtx(), consumertypes.KeyBlocksPerDistributionTransmission, int64(2)) s.consumerChain.NextBlock() - consumerAccountKeeper := s.consumerChain.App.(*app.App).AccountKeeper - consumerBankKeeper := s.consumerChain.App.(*app.App).BankKeeper + consumerAccountKeeper := s.consumerApp.GetE2eAccountKeeper() + consumerBankKeeper := s.consumerApp.GetE2eBankKeeper() //send coins to the fee pool which is used for reward distribution consumerFeePoolAddr := consumerAccountKeeper.GetModuleAccount(s.consumerCtx(), authtypes.FeeCollectorName).GetAddress() @@ -68,7 +66,7 @@ func (s *CCVTestSuite) TestRewardsDistribution() { relayAllCommittedPackets(s, s.consumerChain, s.transferPath, transfertypes.PortID, s.transferPath.EndpointA.ChannelID, 1) s.providerChain.NextBlock() - communityCoins := s.providerChain.App.(*providerApp.App).DistrKeeper.GetFeePoolCommunityCoins(s.providerCtx()) + communityCoins := s.providerApp.GetE2eDistributionKeeper().GetFeePoolCommunityCoins(s.providerCtx()) ibcCoinIndex := -1 for i, coin := range communityCoins { if strings.HasPrefix(coin.Denom, "ibc") { diff --git a/tests/e2e/instance_test.go b/tests/e2e/instance_test.go new file mode 100644 index 0000000000..4c6a47c39a --- /dev/null +++ b/tests/e2e/instance_test.go @@ -0,0 +1,59 @@ +package e2e_test + +import ( + "testing" + + ibctesting "github.com/cosmos/ibc-go/v3/testing" + appConsumer "github.com/cosmos/interchain-security/app/consumer" + appConsumerDemocracy "github.com/cosmos/interchain-security/app/consumer-democracy" + appProvider "github.com/cosmos/interchain-security/app/provider" + "github.com/cosmos/interchain-security/tests/e2e" + e2etestutil "github.com/cosmos/interchain-security/testutil/e2e" + "github.com/cosmos/interchain-security/testutil/simapp" + "github.com/stretchr/testify/suite" +) + +// This file can be used as an example e2e testing instance for any provider/consumer applications. +// In the case of this repo, we're testing the dummy provider/consumer applications, +// but to test any arbitrary app, you only need to replicate this file, and pass in the +// appropriate callback to the testing suites. Note that any provider/consumer applications +// must implement the interfaces defined in /testutil/e2e/interfaces.go + +// Executes the standard group of ccv tests against a consumer and provider app.go implementation. +func TestCCVTestSuite(t *testing.T) { + + ccvSuite := e2e.NewCCVTestSuite( + func(t *testing.T) ( + *ibctesting.Coordinator, + *ibctesting.TestChain, + *ibctesting.TestChain, + e2etestutil.ProviderApp, + e2etestutil.ConsumerApp, + ) { + // Here we pass the concrete types that must implement the necessary interfaces + // to be ran with e2e tests. + coord, prov, cons := simapp.NewProviderConsumerCoordinator(t) + return coord, prov, cons, prov.App.(*appProvider.App), cons.App.(*appConsumer.App) + }, + ) + suite.Run(t, ccvSuite) +} + +// TODO: Run the gov enabled consumer against the standard suite of tests: https://github.com/cosmos/interchain-security/issues/397 + +// Executes a specialized group of tests specific to a democracy consumer, against a democracy consumer app.go implementation. +func TestConsumerDemocracyTestSuite(t *testing.T) { + democSuite := e2e.NewConsumerDemocracyTestSuite( + func(t *testing.T) ( + *ibctesting.Coordinator, + *ibctesting.TestChain, + e2etestutil.DemocConsumerApp, + ) { + // Here we pass the concrete types that must implement the necessary interfaces + // to be ran with e2e tests. + coord, _, cons := simapp.NewProviderConsumerDemocracyCoordinator(t) + return coord, cons, cons.App.(*appConsumerDemocracy.App) + }, + ) + suite.Run(t, democSuite) +} diff --git a/tests/e2e/normal_operations_test.go b/tests/e2e/normal_operations.go similarity index 89% rename from tests/e2e/normal_operations_test.go rename to tests/e2e/normal_operations.go index 1c90efaf50..ede6c1e930 100644 --- a/tests/e2e/normal_operations_test.go +++ b/tests/e2e/normal_operations.go @@ -1,15 +1,14 @@ -package e2e_test +package e2e import ( "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" - appConsumer "github.com/cosmos/interchain-security/app/consumer" "github.com/cosmos/interchain-security/x/ccv/consumer/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" ) // Tests the tracking of historical info in the context of new blocks being committed -func (k CCVTestSuite) TestTrackHistoricalInfo() { - consumerKeeper := k.consumerChain.App.(*appConsumer.App).ConsumerKeeper +func (k CCVTestSuite) TestHistoricalInfo() { + consumerKeeper := k.consumerApp.GetConsumerKeeper() cCtx := k.consumerChain.GetContext // save init consumer valset length @@ -45,7 +44,7 @@ func (k CCVTestSuite) TestTrackHistoricalInfo() { Height: newHeight, } ctx := k.consumerChain.GetContext().WithBlockHeader(header) - k.consumerChain.App.(*appConsumer.App).ConsumerKeeper.TrackHistoricalInfo(ctx) + consumerKeeper.TrackHistoricalInfo(ctx) }, } diff --git a/tests/e2e/setup_test.go b/tests/e2e/setup.go similarity index 76% rename from tests/e2e/setup_test.go rename to tests/e2e/setup.go index 3fd0522729..acd1c4a917 100644 --- a/tests/e2e/setup_test.go +++ b/tests/e2e/setup.go @@ -1,4 +1,4 @@ -package e2e_test +package e2e import ( ibctmtypes "github.com/cosmos/ibc-go/v3/modules/light-clients/07-tendermint/types" @@ -6,6 +6,8 @@ import ( "bytes" "testing" + e2e "github.com/cosmos/interchain-security/testutil/e2e" + ccv "github.com/cosmos/interchain-security/x/ccv/types" "github.com/cosmos/interchain-security/x/ccv/utils" @@ -14,32 +16,55 @@ import ( channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" ibctesting "github.com/cosmos/ibc-go/v3/testing" - appConsumer "github.com/cosmos/interchain-security/app/consumer" - appProvider "github.com/cosmos/interchain-security/app/provider" - "github.com/cosmos/interchain-security/testutil/simapp" - tmtypes "github.com/tendermint/tendermint/types" "github.com/stretchr/testify/suite" ) +// CCVTestSuite is an in-mem test suite which implements the standard group of tests validating +// the e2e functionality of ccv enabled chains. +// Any method implemented for this struct will be ran when suite.Run() is called. type CCVTestSuite struct { suite.Suite coordinator *ibctesting.Coordinator providerChain *ibctesting.TestChain consumerChain *ibctesting.TestChain + providerApp e2e.ProviderApp + consumerApp e2e.ConsumerApp providerClient *ibctmtypes.ClientState providerConsState *ibctmtypes.ConsensusState path *ibctesting.Path transferPath *ibctesting.Path + setupCallback SetupCallback } -func TestCCVTestSuite(t *testing.T) { - suite.Run(t, new(CCVTestSuite)) +// NewCCVTestSuite returns a new instance of CCVTestSuite, ready to be tested against using suite.Run(). +func NewCCVTestSuite(setupCallback SetupCallback) *CCVTestSuite { + ccvSuite := new(CCVTestSuite) + ccvSuite.setupCallback = setupCallback + return ccvSuite } +// Callback for instantiating a new coordinator, provider/consumer test chains, and provider/consumer app +// before every test defined on the suite. +type SetupCallback func(t *testing.T) ( + coord *ibctesting.Coordinator, + providerChain *ibctesting.TestChain, + consumerChain *ibctesting.TestChain, + providerApp e2e.ProviderApp, + consumerApp e2e.ConsumerApp, +) + +// SetupTest sets up in-mem state before every test func (suite *CCVTestSuite) SetupTest() { - suite.coordinator, suite.providerChain, suite.consumerChain = simapp.NewProviderConsumerCoordinator(suite.T()) + + // Instantiate new test utils using callback + suite.coordinator, suite.providerChain, + suite.consumerChain, suite.providerApp, + suite.consumerApp = suite.setupCallback(suite.T()) + + providerKeeper := suite.providerApp.GetProviderKeeper() + consumerKeeper := suite.consumerApp.GetConsumerKeeper() // valsets must match providerValUpdates := tmtypes.TM2PB.ValidatorUpdates(suite.providerChain.Vals) @@ -56,7 +81,7 @@ func (suite *CCVTestSuite) SetupTest() { suite.consumerChain.NextBlock() // create consumer client on provider chain and set as consumer client for consumer chainID in provider keeper. - err := suite.providerChain.App.(*appProvider.App).ProviderKeeper.CreateConsumerClient( + err := providerKeeper.CreateConsumerClient( suite.providerCtx(), suite.consumerChain.ChainID, suite.consumerChain.LastHeader.GetHeight().(clienttypes.Height), @@ -67,12 +92,12 @@ func (suite *CCVTestSuite) SetupTest() { suite.providerChain.NextBlock() // initialize the consumer chain with the genesis state stored on the provider - consumerGenesis, found := suite.providerChain.App.(*appProvider.App).ProviderKeeper.GetConsumerGenesis( + consumerGenesis, found := providerKeeper.GetConsumerGenesis( suite.providerCtx(), suite.consumerChain.ChainID, ) suite.Require().True(found, "consumer genesis not found") - suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.InitGenesis(suite.consumerChain.GetContext(), &consumerGenesis) + consumerKeeper.InitGenesis(suite.consumerCtx(), &consumerGenesis) suite.providerClient = consumerGenesis.ProviderClientState suite.providerConsState = consumerGenesis.ProviderConsensusState @@ -81,7 +106,7 @@ func (suite *CCVTestSuite) SetupTest() { // update CCV path with correct info // - set provider endpoint's clientID - consumerClient, found := suite.providerChain.App.(*appProvider.App).ProviderKeeper.GetConsumerClientId( + consumerClient, found := providerKeeper.GetConsumerClientId( suite.providerCtx(), suite.consumerChain.ChainID, ) @@ -89,11 +114,12 @@ func (suite *CCVTestSuite) SetupTest() { suite.Require().True(found, "consumer client not found") suite.path.EndpointB.ClientID = consumerClient // - set consumer endpoint's clientID - providerClient, found := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderClientID(suite.consumerChain.GetContext()) + providerClient, found := consumerKeeper.GetProviderClientID(suite.consumerChain.GetContext()) suite.Require().True(found, "provider client not found") suite.path.EndpointA.ClientID = providerClient // - client config - providerUnbondingPeriod := suite.providerChain.App.(*appProvider.App).GetStakingKeeper().UnbondingTime(suite.providerCtx()) + + providerUnbondingPeriod := suite.providerApp.GetStakingKeeper().UnbondingTime(suite.providerCtx()) suite.path.EndpointB.ClientConfig.(*ibctesting.TendermintConfig).UnbondingPeriod = providerUnbondingPeriod suite.path.EndpointB.ClientConfig.(*ibctesting.TendermintConfig).TrustingPeriod = providerUnbondingPeriod / utils.TrustingPeriodFraction consumerUnbondingPeriod := utils.ComputeConsumerUnbondingPeriod(providerUnbondingPeriod) @@ -159,8 +185,9 @@ func (suite *CCVTestSuite) SetupTransferChannel() { // CCV channel handshake will automatically initiate transfer channel handshake on ACK // so transfer channel will be on stage INIT when CompleteSetupCCVChannel returns. - suite.transferPath.EndpointA.ChannelID = suite.consumerChain.App.(*appConsumer.App). - ConsumerKeeper.GetDistributionTransmissionChannel(suite.consumerChain.GetContext()) + suite.transferPath.EndpointA.ChannelID = + suite.consumerApp.GetConsumerKeeper().GetDistributionTransmissionChannel( + suite.consumerChain.GetContext()) // Complete TRY, ACK, CONFIRM for transfer path err := suite.transferPath.EndpointB.ChanOpenTry() diff --git a/tests/e2e/slashing_test.go b/tests/e2e/slashing.go similarity index 82% rename from tests/e2e/slashing_test.go rename to tests/e2e/slashing.go index fc462ba601..f7a6736fae 100644 --- a/tests/e2e/slashing_test.go +++ b/tests/e2e/slashing.go @@ -1,4 +1,4 @@ -package e2e_test +package e2e import ( "fmt" @@ -14,8 +14,6 @@ import ( clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" - appConsumer "github.com/cosmos/interchain-security/app/consumer" - appProvider "github.com/cosmos/interchain-security/app/provider" "github.com/cosmos/interchain-security/x/ccv/types" abci "github.com/tendermint/tendermint/abci/types" @@ -28,10 +26,10 @@ func (s *CCVTestSuite) TestSendSlashPacketDowntime() { s.SetupTransferChannel() validatorsPerChain := len(s.consumerChain.Vals.Validators) - providerStakingKeeper := s.providerChain.App.(*appProvider.App).StakingKeeper - providerSlashingKeeper := s.providerChain.App.(*appProvider.App).SlashingKeeper - - consumerKeeper := s.consumerChain.App.(*appConsumer.App).ConsumerKeeper + providerStakingKeeper := s.providerApp.GetE2eStakingKeeper() + providerSlashingKeeper := s.providerApp.GetE2eSlashingKeeper() + consumerKeeper := s.consumerApp.GetConsumerKeeper() + providerKeeper := s.providerApp.GetProviderKeeper() // get a cross-chain validator address, pubkey and balance tmVals := s.consumerChain.Vals.Validators @@ -52,7 +50,8 @@ func (s *CCVTestSuite) TestSendSlashPacketDowntime() { providerSlashingKeeper.SetValidatorSigningInfo(s.providerCtx(), consAddr, valInfo) // get valseUpdateId for current block height - valsetUpdateId := consumerKeeper.GetHeightValsetUpdateID(s.consumerCtx(), uint64(s.consumerCtx().BlockHeight())) + valsetUpdateId := consumerKeeper.GetHeightValsetUpdateID(s.consumerCtx(), + uint64(s.consumerCtx().BlockHeight())) // construct the downtime packet with the validator address and power along // with the slashing and jailing parameters @@ -65,20 +64,21 @@ func (s *CCVTestSuite) TestSendSlashPacketDowntime() { slashFraction := int64(100) packetData := types.NewSlashPacketData(validator, valsetUpdateId, stakingtypes.Downtime) timeout := uint64(oldBlockTime.Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()) - packet := channeltypes.NewPacket(packetData.GetBytes(), 1, ccv.ConsumerPortID, s.path.EndpointA.ChannelID, - ccv.ProviderPortID, s.path.EndpointB.ChannelID, clienttypes.Height{}, timeout) + packet := channeltypes.NewPacket(packetData.GetBytes(), 1, ccv.ConsumerPortID, + s.path.EndpointA.ChannelID, ccv.ProviderPortID, s.path.EndpointB.ChannelID, + clienttypes.Height{}, timeout) // Send the downtime packet through CCV err = s.path.EndpointA.SendPacket(packet) s.Require().NoError(err) // Set outstanding slashing flag - s.consumerChain.App.(*appConsumer.App).ConsumerKeeper.SetOutstandingDowntime(s.consumerCtx(), consAddr) + consumerKeeper.SetOutstandingDowntime(s.consumerCtx(), consAddr) // save next VSC packet info oldBlockTime = s.providerCtx().BlockTime() timeout = uint64(oldBlockTime.Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()) - valsetUpdateID := s.providerChain.App.(*appProvider.App).ProviderKeeper.GetValidatorSetUpdateId(s.providerCtx()) + valsetUpdateID := providerKeeper.GetValidatorSetUpdateId(s.providerCtx()) // receive the downtime packet on the provider chain; // RecvPacket() calls the provider endblocker thus sends a VSC packet to the consumer @@ -119,7 +119,7 @@ func (s *CCVTestSuite) TestSendSlashPacketDowntime() { // check that the validator is successfully jailed on provider - validatorJailed, ok := s.providerChain.App.(*appProvider.App).StakingKeeper.GetValidatorByConsAddr(s.providerCtx(), consAddr) + validatorJailed, ok := s.providerApp.GetE2eStakingKeeper().GetValidatorByConsAddr(s.providerCtx(), consAddr) s.Require().True(ok) s.Require().True(validatorJailed.Jailed) s.Require().Equal(validatorJailed.Status, stakingtypes.Unbonding) @@ -135,7 +135,7 @@ func (s *CCVTestSuite) TestSendSlashPacketDowntime() { s.Require().True(valSignInfo.JailedUntil.After(s.providerCtx().BlockHeader().Time)) // check that the outstanding slashing flag is reset on the consumer - pFlag := s.consumerChain.App.(*appConsumer.App).ConsumerKeeper.OutstandingDowntime(s.consumerCtx(), consAddr) + pFlag := consumerKeeper.OutstandingDowntime(s.consumerCtx(), consAddr) s.Require().False(pFlag) // check that slashing packet gets acknowledged @@ -149,9 +149,10 @@ func (s *CCVTestSuite) TestSendSlashPacketDoubleSign() { s.SetupTransferChannel() validatorsPerChain := len(s.consumerChain.Vals.Validators) - providerStakingKeeper := s.providerChain.App.(*appProvider.App).StakingKeeper - providerSlashingKeeper := s.providerChain.App.(*appProvider.App).SlashingKeeper - consumerKeeper := s.consumerChain.App.(*appConsumer.App).ConsumerKeeper + providerStakingKeeper := s.providerApp.GetE2eStakingKeeper() + providerSlashingKeeper := s.providerApp.GetE2eSlashingKeeper() + providerKeeper := s.providerApp.GetProviderKeeper() + consumerKeeper := s.consumerApp.GetConsumerKeeper() // get a cross-chain validator address, pubkey and balance tmVals := s.consumerChain.Vals.Validators @@ -195,7 +196,7 @@ func (s *CCVTestSuite) TestSendSlashPacketDoubleSign() { // save next VSC packet info oldBlockTime = s.providerCtx().BlockTime() timeout = uint64(oldBlockTime.Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()) - valsetUpdateID := s.providerChain.App.(*appProvider.App).ProviderKeeper.GetValidatorSetUpdateId(s.providerCtx()) + valsetUpdateID := providerKeeper.GetValidatorSetUpdateId(s.providerCtx()) // receive the downtime packet on the provider chain; // RecvPacket() calls the provider endblocker and thus sends a VSC packet to the consumer @@ -235,7 +236,7 @@ func (s *CCVTestSuite) TestSendSlashPacketDoubleSign() { s.Require().NoError(err) // check that the validator is successfully jailed on provider - validatorJailed, ok := s.providerChain.App.(*appProvider.App).StakingKeeper.GetValidatorByConsAddr(s.providerCtx(), consAddr) + validatorJailed, ok := providerStakingKeeper.GetValidatorByConsAddr(s.providerCtx(), consAddr) s.Require().True(ok) s.Require().True(validatorJailed.Jailed) s.Require().Equal(validatorJailed.Status, stakingtypes.Unbonding) @@ -256,8 +257,8 @@ func (s *CCVTestSuite) TestSendSlashPacketDoubleSign() { } func (s *CCVTestSuite) TestSlashPacketAcknowldgement() { - providerKeeper := s.providerChain.App.(*appProvider.App).ProviderKeeper - consumerKeeper := s.consumerChain.App.(*appConsumer.App).ConsumerKeeper + providerKeeper := s.providerApp.GetProviderKeeper() + consumerKeeper := s.consumerApp.GetConsumerKeeper() s.SetupCCVChannel() s.SetupTransferChannel() @@ -277,9 +278,9 @@ func (s *CCVTestSuite) TestSlashPacketAcknowldgement() { // TestHandleSlashPacketDoubleSigning tests the handling of a double-signing related slash packet, with e2e tests func (suite *CCVTestSuite) TestHandleSlashPacketDoubleSigning() { - providerKeeper := suite.providerChain.App.(*appProvider.App).ProviderKeeper - providerSlashingKeeper := suite.providerChain.App.(*appProvider.App).SlashingKeeper - providerStakingKeeper := suite.providerChain.App.(*appProvider.App).StakingKeeper + providerKeeper := suite.providerApp.GetProviderKeeper() + providerSlashingKeeper := suite.providerApp.GetE2eSlashingKeeper() + providerStakingKeeper := suite.providerApp.GetE2eStakingKeeper() tmVal := suite.providerChain.Vals.Validators[0] consAddr := sdk.ConsAddress(tmVal.Address) @@ -308,7 +309,7 @@ func (suite *CCVTestSuite) TestHandleSlashPacketDoubleSigning() { ) suite.NoError(err) - // verify that validator is jailed in the staking and slashing mdodules' states + // verify that validator is jailed in the staking and slashing modules' states suite.Require().True(providerStakingKeeper.IsValidatorJailed(suite.providerCtx(), consAddr)) signingInfo, _ := providerSlashingKeeper.GetValidatorSigningInfo(suite.providerCtx(), consAddr) @@ -318,9 +319,9 @@ func (suite *CCVTestSuite) TestHandleSlashPacketDoubleSigning() { // TestHandleSlashPacketErrors tests errors for the HandleSlashPacket method in an e2e testing setting func (suite *CCVTestSuite) TestHandleSlashPacketErrors() { - providerStakingKeeper := suite.providerChain.App.(*appProvider.App).StakingKeeper - ProviderKeeper := suite.providerChain.App.(*appProvider.App).ProviderKeeper - providerSlashingKeeper := suite.providerChain.App.(*appProvider.App).SlashingKeeper + providerStakingKeeper := suite.providerApp.GetE2eStakingKeeper() + ProviderKeeper := suite.providerApp.GetProviderKeeper() + providerSlashingKeeper := suite.providerApp.GetE2eSlashingKeeper() consumerChainID := suite.consumerChain.ChainID // sync contexts block height @@ -402,8 +403,9 @@ func (suite *CCVTestSuite) TestHandleSlashPacketErrors() { // by varying the slash packet VSC ID mapping to infraction heights // lesser, equal or greater than the undelegation entry creation height func (suite *CCVTestSuite) TestHandleSlashPacketDistribution() { - providerStakingKeeper := suite.providerChain.App.(*appProvider.App).StakingKeeper - providerKeeper := suite.providerChain.App.(*appProvider.App).ProviderKeeper + providerKeeper := suite.providerApp.GetProviderKeeper() + providerStakingKeeper := suite.providerApp.GetE2eStakingKeeper() + providerSlashingKeeper := suite.providerApp.GetE2eSlashingKeeper() // choose a validator tmValidator := suite.providerChain.Vals.Validators[0] @@ -455,7 +457,7 @@ func (suite *CCVTestSuite) TestHandleSlashPacketDistribution() { } // create validator signing info to test slashing - suite.providerChain.App.(*appProvider.App).SlashingKeeper.SetValidatorSigningInfo( + providerSlashingKeeper.SetValidatorSigningInfo( suite.providerChain.GetContext(), sdk.ConsAddress(tmValidator.Address), slashingtypes.ValidatorSigningInfo{Address: tmValidator.Address.String()}, @@ -473,7 +475,8 @@ func (suite *CCVTestSuite) TestHandleSlashPacketDistribution() { } // save unbonding balance before slashing tests - ubd, found := providerStakingKeeper.GetUnbondingDelegation(suite.providerChain.GetContext(), delAddr, valAddr) + ubd, found := providerStakingKeeper.GetUnbondingDelegation( + suite.providerChain.GetContext(), delAddr, valAddr) suite.Require().True(found) ubdBalance := ubd.Entries[0].Balance @@ -507,36 +510,40 @@ func (suite *CCVTestSuite) TestValidatorDowntime() { suite.SetupCCVChannel() suite.SendEmptyVSCPacket() + consumerKeeper := suite.consumerApp.GetConsumerKeeper() + consumerSlashingKeeper := suite.consumerApp.GetE2eSlashingKeeper() + consumerIBCKeeper := suite.consumerApp.GetIBCKeeper() + // sync suite context after CCV channel is established ctx := suite.consumerCtx() - app := suite.consumerChain.App.(*appConsumer.App) channelID := suite.path.EndpointA.ChannelID // pick a cross-chain validator - vals := app.ConsumerKeeper.GetAllCCValidator(ctx) + vals := consumerKeeper.GetAllCCValidator(ctx) consAddr := sdk.ConsAddress(vals[0].Address) // save next sequence before sending a slash packet - seq, ok := app.GetIBCKeeper().ChannelKeeper.GetNextSequenceSend(ctx, ccv.ConsumerPortID, channelID) + seq, ok := consumerIBCKeeper.ChannelKeeper.GetNextSequenceSend( + ctx, ccv.ConsumerPortID, channelID) suite.Require().True(ok) // Sign 100 blocks valPower := int64(1) - height, signedBlocksWindow := int64(0), app.SlashingKeeper.SignedBlocksWindow(ctx) + height, signedBlocksWindow := int64(0), consumerSlashingKeeper.SignedBlocksWindow(ctx) for ; height < signedBlocksWindow; height++ { ctx = ctx.WithBlockHeight(height) - app.SlashingKeeper.HandleValidatorSignature(ctx, vals[0].Address, valPower, true) + consumerSlashingKeeper.HandleValidatorSignature(ctx, vals[0].Address, valPower, true) } - missedBlockThreshold := (2 * signedBlocksWindow) - app.SlashingKeeper.MinSignedPerWindow(ctx) + missedBlockThreshold := (2 * signedBlocksWindow) - consumerSlashingKeeper.MinSignedPerWindow(ctx) ctx = suite.consumerCtx() // construct slash packet to be sent and get its commit packetData := ccv.NewSlashPacketData( abci.Validator{Address: vals[0].Address, Power: valPower}, // get the VSC ID mapping the infraction height - app.ConsumerKeeper.GetHeightValsetUpdateID(ctx, uint64(missedBlockThreshold-sdk.ValidatorUpdateDelay-1)), + consumerKeeper.GetHeightValsetUpdateID(ctx, uint64(missedBlockThreshold-sdk.ValidatorUpdateDelay-1)), stakingtypes.Downtime, ) expCommit := suite.commitSlashPacket(ctx, packetData) @@ -544,42 +551,42 @@ func (suite *CCVTestSuite) TestValidatorDowntime() { // Miss 50 blocks and expect a slash packet to be sent for ; height <= missedBlockThreshold; height++ { ctx = ctx.WithBlockHeight(height) - app.SlashingKeeper.HandleValidatorSignature(ctx, vals[0].Address, valPower, false) + consumerSlashingKeeper.HandleValidatorSignature(ctx, vals[0].Address, valPower, false) } ctx = suite.consumerCtx() // check validator signing info - res, _ := app.SlashingKeeper.GetValidatorSigningInfo(ctx, consAddr) + res, _ := consumerSlashingKeeper.GetValidatorSigningInfo(ctx, consAddr) // expect increased jail time - suite.Require().True(res.JailedUntil.Equal(ctx.BlockTime().Add(app.SlashingKeeper.DowntimeJailDuration(ctx))), "did not update validator jailed until signing info") + suite.Require().True(res.JailedUntil.Equal(ctx.BlockTime().Add(consumerSlashingKeeper.DowntimeJailDuration(ctx))), "did not update validator jailed until signing info") // expect missed block counters reseted suite.Require().Zero(res.MissedBlocksCounter, "did not reset validator missed block counter") suite.Require().Zero(res.IndexOffset) - app.SlashingKeeper.IterateValidatorMissedBlockBitArray(ctx, consAddr, func(_ int64, missed bool) bool { + consumerSlashingKeeper.IterateValidatorMissedBlockBitArray(ctx, consAddr, func(_ int64, missed bool) bool { suite.Require().True(missed) return false }) // verify that the slash packet was sent - gotCommit := app.IBCKeeper.ChannelKeeper.GetPacketCommitment(ctx, ccv.ConsumerPortID, channelID, seq) + gotCommit := consumerIBCKeeper.ChannelKeeper.GetPacketCommitment(ctx, ccv.ConsumerPortID, channelID, seq) suite.Require().NotNil(gotCommit, "did not found slash packet commitment") suite.Require().EqualValues(expCommit, gotCommit, "invalid slash packet commitment") // verify that the slash packet was sent - suite.Require().True(app.ConsumerKeeper.OutstandingDowntime(ctx, consAddr)) + suite.Require().True(consumerKeeper.OutstandingDowntime(ctx, consAddr)) // check that the outstanding slashing flag prevents the jailed validator to keep missing block for ; height < missedBlockThreshold+signedBlocksWindow; height++ { ctx = ctx.WithBlockHeight(height) - app.SlashingKeeper.HandleValidatorSignature(ctx, vals[0].Address, valPower, false) + consumerSlashingKeeper.HandleValidatorSignature(ctx, vals[0].Address, valPower, false) } - res, _ = app.SlashingKeeper.GetValidatorSigningInfo(ctx, consAddr) + res, _ = consumerSlashingKeeper.GetValidatorSigningInfo(ctx, consAddr) suite.Require().Zero(res.MissedBlocksCounter, "did not reset validator missed block counter") suite.Require().Zero(res.IndexOffset) - app.SlashingKeeper.IterateValidatorMissedBlockBitArray(ctx, consAddr, func(_ int64, missed bool) bool { + consumerSlashingKeeper.IterateValidatorMissedBlockBitArray(ctx, consAddr, func(_ int64, missed bool) bool { suite.Require().True(missed, "did not reset validator missed block bit array") return false }) @@ -595,7 +602,6 @@ func (suite *CCVTestSuite) TestValidatorDoubleSigning() { // sync suite context after CCV channel is established ctx := suite.consumerCtx() - app := suite.consumerChain.App.(*appConsumer.App) channelID := suite.path.EndpointA.ChannelID // create a validator pubkey and address @@ -616,29 +622,29 @@ func (suite *CCVTestSuite) TestValidatorDoubleSigning() { } // add validator signing-info to the store - app.SlashingKeeper.SetValidatorSigningInfo(ctx, consAddr, slashingtypes.ValidatorSigningInfo{ + suite.consumerApp.GetE2eSlashingKeeper().SetValidatorSigningInfo(ctx, consAddr, slashingtypes.ValidatorSigningInfo{ Address: consAddr.String(), Tombstoned: false, }) // save next sequence before sending a slash packet - seq, ok := app.GetIBCKeeper().ChannelKeeper.GetNextSequenceSend(ctx, ccv.ConsumerPortID, channelID) + seq, ok := suite.consumerApp.GetIBCKeeper().ChannelKeeper.GetNextSequenceSend(ctx, ccv.ConsumerPortID, channelID) suite.Require().True(ok) // construct slash packet data and get the expcted commit hash packetData := ccv.NewSlashPacketData( abci.Validator{Address: consAddr.Bytes(), Power: power}, // get VSC ID mapping to the infraction height with the TM delay substracted - app.ConsumerKeeper.GetHeightValsetUpdateID(ctx, uint64(infractionHeight-sdk.ValidatorUpdateDelay)), + suite.consumerApp.GetConsumerKeeper().GetHeightValsetUpdateID(ctx, uint64(infractionHeight-sdk.ValidatorUpdateDelay)), stakingtypes.DoubleSign, ) expCommit := suite.commitSlashPacket(ctx, packetData) // expect to send slash packet when handling double-sign evidence - app.EvidenceKeeper.HandleEquivocationEvidence(ctx, e) + suite.consumerApp.GetE2eEvidenceKeeper().HandleEquivocationEvidence(ctx, e) // check that slash packet is sent - gotCommit := app.IBCKeeper.ChannelKeeper.GetPacketCommitment(ctx, ccv.ConsumerPortID, channelID, seq) + gotCommit := suite.consumerApp.GetIBCKeeper().ChannelKeeper.GetPacketCommitment(ctx, ccv.ConsumerPortID, channelID, seq) suite.NotNil(gotCommit) suite.Require().EqualValues(expCommit, gotCommit) @@ -648,12 +654,14 @@ func (suite *CCVTestSuite) TestValidatorDoubleSigning() { func (suite *CCVTestSuite) TestSendSlashPacket() { suite.SetupCCVChannel() - app := suite.consumerChain.App.(*appConsumer.App) + consumerKeeper := suite.consumerApp.GetConsumerKeeper() + consumerIBCKeeper := suite.consumerApp.GetIBCKeeper() + ctx := suite.consumerChain.GetContext() channelID := suite.path.EndpointA.ChannelID // check that CCV channel isn't established - _, ok := app.ConsumerKeeper.GetProviderChannel(ctx) + _, ok := consumerKeeper.GetProviderChannel(ctx) suite.Require().False(ok) // expect to store 4 slash requests for downtime @@ -670,7 +678,7 @@ func (suite *CCVTestSuite) TestSendSlashPacket() { addr := ed25519.GenPrivKey().PubKey().Address() val := abci.Validator{ Address: addr} - app.ConsumerKeeper.SendSlashPacket(ctx, val, 0, infraction) + consumerKeeper.SendSlashPacket(ctx, val, 0, infraction) slashedVals = append(slashedVals, slashedVal{validator: val, infraction: infraction}) } infraction = stakingtypes.DoubleSign @@ -679,15 +687,15 @@ func (suite *CCVTestSuite) TestSendSlashPacket() { // expect to store a duplicate for each slash request // in order to test the outstanding downtime logic for _, sv := range slashedVals { - app.ConsumerKeeper.SendSlashPacket(ctx, sv.validator, 0, sv.infraction) + consumerKeeper.SendSlashPacket(ctx, sv.validator, 0, sv.infraction) } // verify that all requests are stored - requests := app.ConsumerKeeper.GetPendingSlashRequests(ctx) + requests := consumerKeeper.GetPendingSlashRequests(ctx) suite.Require().Len(requests.GetRequests(), 16) // save consumer next sequence - seq, _ := app.GetIBCKeeper().ChannelKeeper.GetNextSequenceSend(ctx, ccv.ConsumerPortID, channelID) + seq, _ := consumerIBCKeeper.ChannelKeeper.GetNextSequenceSend(ctx, ccv.ConsumerPortID, channelID) // establish ccv channel by sending an empty VSC packet to consumer endpoint suite.SendEmptyVSCPacket() @@ -695,7 +703,7 @@ func (suite *CCVTestSuite) TestSendSlashPacket() { // check that each pending slash requests is sent once // and that the downtime slash request duplicates are skipped (due to the outstanding downtime flag) for i := 0; i < 16; i++ { - commit := app.IBCKeeper.ChannelKeeper.GetPacketCommitment(ctx, ccv.ConsumerPortID, channelID, seq+uint64(i)) + commit := consumerIBCKeeper.ChannelKeeper.GetPacketCommitment(ctx, ccv.ConsumerPortID, channelID, seq+uint64(i)) if i > 11 { suite.Require().Nil(commit) continue @@ -709,18 +717,18 @@ func (suite *CCVTestSuite) TestSendSlashPacket() { downtime := r.Infraction == stakingtypes.Downtime if downtime { consAddr := sdk.ConsAddress(r.Packet.Validator.Address) - suite.Require().True(app.ConsumerKeeper.OutstandingDowntime(ctx, consAddr)) + suite.Require().True(consumerKeeper.OutstandingDowntime(ctx, consAddr)) } } // check that pending slash requests get cleared after being sent - requests = app.ConsumerKeeper.GetPendingSlashRequests(ctx) + requests = consumerKeeper.GetPendingSlashRequests(ctx) suite.Require().Len(requests.GetRequests(), 0) // check that slash requests aren't stored when channel is established - app.ConsumerKeeper.SendSlashPacket(ctx, abci.Validator{}, 0, stakingtypes.Downtime) - app.ConsumerKeeper.SendSlashPacket(ctx, abci.Validator{}, 0, stakingtypes.DoubleSign) + consumerKeeper.SendSlashPacket(ctx, abci.Validator{}, 0, stakingtypes.Downtime) + consumerKeeper.SendSlashPacket(ctx, abci.Validator{}, 0, stakingtypes.DoubleSign) - requests = app.ConsumerKeeper.GetPendingSlashRequests(ctx) + requests = consumerKeeper.GetPendingSlashRequests(ctx) suite.Require().Len(requests.GetRequests(), 0) } diff --git a/tests/e2e/stop_consumer_test.go b/tests/e2e/stop_consumer.go similarity index 70% rename from tests/e2e/stop_consumer_test.go rename to tests/e2e/stop_consumer.go index 767b8d793d..aceab09f31 100644 --- a/tests/e2e/stop_consumer_test.go +++ b/tests/e2e/stop_consumer.go @@ -1,11 +1,9 @@ -package e2e_test +package e2e import ( sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" - appConsumer "github.com/cosmos/interchain-security/app/consumer" - appProvider "github.com/cosmos/interchain-security/app/provider" ccv "github.com/cosmos/interchain-security/x/ccv/types" abci "github.com/tendermint/tendermint/abci/types" ) @@ -13,6 +11,9 @@ import ( // Tests the functionality of stopping a consumer chain at a higher level than unit tests func (s *CCVTestSuite) TestStopConsumerChain() { + providerKeeper := s.providerApp.GetProviderKeeper() + providerStakingKeeper := s.providerApp.GetE2eStakingKeeper() + // default consumer chain ID consumerChainID := s.consumerChain.ChainID @@ -21,7 +22,7 @@ func (s *CCVTestSuite) TestStopConsumerChain() { valAddr, err := sdk.ValAddressFromHex(tmValidator.Address.String()) s.Require().NoError(err) - validator, found := s.providerChain.App.(*appProvider.App).StakingKeeper.GetValidator(s.providerCtx(), valAddr) + validator, found := providerStakingKeeper.GetValidator(s.providerCtx(), valAddr) s.Require().True(found) // get delegator address @@ -54,7 +55,7 @@ func (s *CCVTestSuite) TestStopConsumerChain() { }, { func(suite *CCVTestSuite) error { - testShares, err = s.providerChain.App.(*appProvider.App).StakingKeeper.Delegate(s.providerCtx(), delAddr, bondAmt, stakingtypes.Unbonded, stakingtypes.Validator(validator), true) + testShares, err = providerStakingKeeper.Delegate(s.providerCtx(), delAddr, bondAmt, stakingtypes.Unbonded, stakingtypes.Validator(validator), true) return err }, }, @@ -62,7 +63,7 @@ func (s *CCVTestSuite) TestStopConsumerChain() { func(suite *CCVTestSuite) error { for i := 0; i < ubdOpsNum; i++ { // undelegate one quarter of the shares - _, err := s.providerChain.App.(*appProvider.App).StakingKeeper.Undelegate(s.providerCtx(), delAddr, valAddr, testShares.QuoInt64(int64(ubdOpsNum))) + _, err := providerStakingKeeper.Undelegate(s.providerCtx(), delAddr, valAddr, testShares.QuoInt64(int64(ubdOpsNum))) if err != nil { return err } @@ -74,9 +75,9 @@ func (s *CCVTestSuite) TestStopConsumerChain() { }, { func(suite *CCVTestSuite) error { - s.providerChain.App.(*appProvider.App).ProviderKeeper.SetSlashAcks(s.providerCtx(), consumerChainID, []string{"validator-1", "validator-2", "validator-3"}) - s.providerChain.App.(*appProvider.App).ProviderKeeper.SetLockUnbondingOnTimeout(s.providerCtx(), consumerChainID) - s.providerChain.App.(*appProvider.App).ProviderKeeper.AppendPendingVSC(s.providerCtx(), consumerChainID, ccv.ValidatorSetChangePacketData{ValsetUpdateId: 1}) + providerKeeper.SetSlashAcks(s.providerCtx(), consumerChainID, []string{"validator-1", "validator-2", "validator-3"}) + providerKeeper.SetLockUnbondingOnTimeout(s.providerCtx(), consumerChainID) + providerKeeper.AppendPendingVSC(s.providerCtx(), consumerChainID, ccv.ValidatorSetChangePacketData{ValsetUpdateId: 1}) return nil }, }, @@ -88,7 +89,7 @@ func (s *CCVTestSuite) TestStopConsumerChain() { } // stop the consumer chain - err = s.providerChain.App.(*appProvider.App).ProviderKeeper.StopConsumerChain(s.providerCtx(), consumerChainID, false, true) + err = providerKeeper.StopConsumerChain(s.providerCtx(), consumerChainID, false, true) s.Require().NoError(err) // check all states are removed and the unbonding operation released @@ -102,8 +103,10 @@ func (s *CCVTestSuite) TestStopConsumerOnChannelClosed() { s.SetupTransferChannel() s.SendEmptyVSCPacket() + providerKeeper := s.providerApp.GetProviderKeeper() + // stop the consumer chain - err := s.providerChain.App.(*appProvider.App).ProviderKeeper.StopConsumerChain(s.providerCtx(), s.consumerChain.ChainID, true, true) + err := providerKeeper.StopConsumerChain(s.providerCtx(), s.consumerChain.ChainID, true, true) s.Require().NoError(err) err = s.path.EndpointA.UpdateClient() @@ -120,20 +123,21 @@ func (s *CCVTestSuite) TestStopConsumerOnChannelClosed() { //s.consumerChain.NextBlock() // check that the provider's channel is removed - // _, found := s.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderChannel(s.consumerCtx()) + // _, found := s.consumerApp.GetConsumerKeeper().GetProviderChannel(s.consumerCtx()) // s.Require().False(found) } func (s *CCVTestSuite) checkConsumerChainIsRemoved(chainID string, lockUbd bool) { channelID := s.path.EndpointB.ChannelID - providerKeeper := s.providerChain.App.(*appProvider.App).ProviderKeeper + providerKeeper := s.providerApp.GetProviderKeeper() + providerStakingKeeper := s.providerApp.GetE2eStakingKeeper() // check channel's state is closed s.Require().Equal(channeltypes.CLOSED, s.path.EndpointB.GetChannel().State) // check UnbondingOps were deleted and undelegation entries aren't onHold if !lockUbd { - s.providerChain.App.(*appProvider.App).ProviderKeeper.IterateOverUnbondingOpIndex( + providerKeeper.IterateOverUnbondingOpIndex( s.providerCtx(), chainID, func(vscID uint64, ubdIndex []uint64) bool { @@ -142,7 +146,7 @@ func (s *CCVTestSuite) checkConsumerChainIsRemoved(chainID string, lockUbd bool) for _, ubdID := range ubdIndex { _, found = providerKeeper.GetUnbondingOp(s.providerCtx(), ubdIndex[ubdID]) s.Require().False(found) - ubd, _ := s.providerChain.App.(*appProvider.App).StakingKeeper.GetUnbondingDelegationByUnbondingId(s.providerCtx(), ubdIndex[ubdID]) + ubd, _ := providerStakingKeeper.GetUnbondingDelegationByUnbondingId(s.providerCtx(), ubdIndex[ubdID]) s.Require().Zero(ubd.Entries[ubdID].UnbondingOnHoldRefCount) } return true @@ -177,13 +181,15 @@ func (suite *CCVTestSuite) TestProviderChannelClosed() { // establish provider channel with a first VSC packet suite.SendEmptyVSCPacket() - channelID, found := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderChannel(suite.consumerChain.GetContext()) + consumerKeeper := suite.consumerApp.GetConsumerKeeper() + + channelID, found := consumerKeeper.GetProviderChannel(suite.consumerChain.GetContext()) suite.Require().True(found) // close provider channel - err := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.ChanCloseInit(suite.consumerChain.GetContext(), ccv.ConsumerPortID, channelID) + err := consumerKeeper.ChanCloseInit(suite.consumerChain.GetContext(), ccv.ConsumerPortID, channelID) suite.Require().NoError(err) - suite.Require().True(suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.IsChannelClosed(suite.consumerChain.GetContext(), channelID)) + suite.Require().True(consumerKeeper.IsChannelClosed(suite.consumerChain.GetContext(), channelID)) // assert begin blocker did panics defer func() { @@ -192,5 +198,5 @@ func (suite *CCVTestSuite) TestProviderChannelClosed() { } suite.Require().Fail("Begin blocker did not panic with a closed channel") }() - suite.consumerChain.App.(*appConsumer.App).BeginBlocker(suite.consumerChain.GetContext(), abci.RequestBeginBlock{}) + suite.consumerApp.BeginBlocker(suite.consumerChain.GetContext(), abci.RequestBeginBlock{}) } diff --git a/tests/e2e/unbonding_test.go b/tests/e2e/unbonding.go similarity index 93% rename from tests/e2e/unbonding_test.go rename to tests/e2e/unbonding.go index baeb96eb22..7dbb672d90 100644 --- a/tests/e2e/unbonding_test.go +++ b/tests/e2e/unbonding.go @@ -1,11 +1,10 @@ -package e2e_test +package e2e import ( "time" sdk "github.com/cosmos/cosmos-sdk/types" - appProvider "github.com/cosmos/interchain-security/app/provider" ccv "github.com/cosmos/interchain-security/x/ccv/types" ) @@ -141,6 +140,9 @@ func (s *CCVTestSuite) TestUndelegationNoValsetChange() { // - no undelegations can complete, even if the provider unbonding period elapses // - all the VSC packets are stored in state as pending func (s *CCVTestSuite) TestUndelegationDuringInit() { + + providerKeeper := s.providerApp.GetProviderKeeper() + // delegate bondAmt and undelegate 1/2 of it bondAmt := sdk.NewInt(10000000) delAddr := s.providerChain.SenderAccount.GetAddress() @@ -154,7 +156,7 @@ func (s *CCVTestSuite) TestUndelegationDuringInit() { s.providerChain.NextBlock() // check that the VSC packet is stored in state as pending - pendingVSCs, _ := s.providerChain.App.(*appProvider.App).ProviderKeeper.GetPendingVSCs(s.providerCtx(), s.consumerChain.ChainID) + pendingVSCs, _ := providerKeeper.GetPendingVSCs(s.providerCtx(), s.consumerChain.ChainID) s.Require().True(len(pendingVSCs) == 1, "no pending VSC packet found") // delegate again to create another VSC packet @@ -164,7 +166,7 @@ func (s *CCVTestSuite) TestUndelegationDuringInit() { s.providerChain.NextBlock() // check that the VSC packet is stored in state as pending - pendingVSCs, _ = s.providerChain.App.(*appProvider.App).ProviderKeeper.GetPendingVSCs(s.providerCtx(), s.consumerChain.ChainID) + pendingVSCs, _ = providerKeeper.GetPendingVSCs(s.providerCtx(), s.consumerChain.ChainID) s.Require().True(len(pendingVSCs) == 2, "only one pending VSC packet found") // increment time so that the unbonding period ends on the provider @@ -205,8 +207,12 @@ func (s *CCVTestSuite) TestUndelegationDuringInit() { // Advance time so that provider's unbonding op completes // Check that unbonding has completed in provider staking func (s *CCVTestSuite) TestUnbondingNoConsumer() { + + providerKeeper := s.providerApp.GetProviderKeeper() + providerStakingKeeper := s.providerApp.GetE2eStakingKeeper() + // remove the consumer chain, which was already registered during setup - s.providerChain.App.(*appProvider.App).ProviderKeeper.DeleteConsumerClientId(s.providerCtx(), s.consumerChain.ChainID) + providerKeeper.DeleteConsumerClientId(s.providerCtx(), s.consumerChain.ChainID) // delegate bondAmt and undelegate 1/2 of it bondAmt := sdk.NewInt(10000000) @@ -220,7 +226,7 @@ func (s *CCVTestSuite) TestUnbondingNoConsumer() { // increment time so that the unbonding period ends on the provider; // cannot use incrementTimeByUnbondingPeriod() since it tries // to also update the provider's client on the consumer - providerUnbondingPeriod := s.providerChain.App.GetStakingKeeper().UnbondingTime(s.providerCtx()) + providerUnbondingPeriod := providerStakingKeeper.UnbondingTime(s.providerCtx()) s.coordinator.IncrementTimeBy(providerUnbondingPeriod + time.Hour) // call NextBlock on the provider (which increments the height) @@ -237,8 +243,8 @@ func (s *CCVTestSuite) TestUnbondingNoConsumer() { // submitted on a provider chain with no consumers func (s *CCVTestSuite) TestRedelegationNoConsumer() { - providerKeeper := s.providerChain.App.(*appProvider.App).ProviderKeeper - stakingKeeper := s.providerChain.App.(*appProvider.App).StakingKeeper + providerKeeper := s.providerApp.GetProviderKeeper() + stakingKeeper := s.providerApp.GetE2eStakingKeeper() // remove the consumer chain, which was already registered during setup providerKeeper.DeleteConsumerClientId(s.providerCtx(), s.consumerChain.ChainID) @@ -246,8 +252,8 @@ func (s *CCVTestSuite) TestRedelegationNoConsumer() { // Setup delegator, bond amount, and src/dst validators bondAmt := sdk.NewInt(10000000) delAddr := s.providerChain.SenderAccount.GetAddress() - _, srcVal := s.getVal(0) - _, dstVal := s.getVal(1) + _, srcVal := s.getValByIdx(0) + _, dstVal := s.getValByIdx(1) delegateAndRedelegate( s, @@ -283,14 +289,14 @@ func (s *CCVTestSuite) TestRedelegationProviderFirst() { s.SetupCCVChannel() s.SetupTransferChannel() - stakingKeeper := s.providerChain.App.(*appProvider.App).StakingKeeper - providerKeeper := s.providerChain.App.(*appProvider.App).ProviderKeeper + providerKeeper := s.providerApp.GetProviderKeeper() + stakingKeeper := s.providerApp.GetE2eStakingKeeper() // Setup delegator, bond amount, and src/dst validators bondAmt := sdk.NewInt(10000000) delAddr := s.providerChain.SenderAccount.GetAddress() - _, srcVal := s.getVal(0) - _, dstVal := s.getVal(1) + _, srcVal := s.getValByIdx(0) + _, dstVal := s.getValByIdx(1) delegateAndRedelegate( s, diff --git a/tests/e2e/valset_update_test.go b/tests/e2e/valset_update.go similarity index 78% rename from tests/e2e/valset_update_test.go rename to tests/e2e/valset_update.go index faecf9cd1f..b0b1b5203f 100644 --- a/tests/e2e/valset_update_test.go +++ b/tests/e2e/valset_update.go @@ -1,4 +1,4 @@ -package e2e_test +package e2e import ( "time" @@ -7,7 +7,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" - appConsumer "github.com/cosmos/interchain-security/app/consumer" ccv "github.com/cosmos/interchain-security/x/ccv/types" abci "github.com/tendermint/tendermint/abci/types" ) @@ -37,6 +36,9 @@ func (s *CCVTestSuite) TestPacketRoundtrip() { // TestSendVSCMaturedPackets tests the behavior of SendVSCMaturedPackets and related state checks func (suite *CCVTestSuite) TestSendVSCMaturedPackets() { + + consumerKeeper := suite.consumerApp.GetConsumerKeeper() + // setup CCV channel suite.SetupCCVChannel() @@ -68,7 +70,7 @@ func (suite *CCVTestSuite) TestSendVSCMaturedPackets() { // send first packet packet := channeltypes.NewPacket(pd.GetBytes(), 1, ccv.ProviderPortID, suite.path.EndpointB.ChannelID, ccv.ConsumerPortID, suite.path.EndpointA.ChannelID, clienttypes.NewHeight(1, 0), 0) - ack := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.OnRecvVSCPacket(suite.consumerChain.GetContext(), packet, pd) + ack := consumerKeeper.OnRecvVSCPacket(suite.consumerChain.GetContext(), packet, pd) suite.Require().NotNil(ack, "OnRecvVSCPacket did not return ack") suite.Require().True(ack.Success(), "OnRecvVSCPacket did not return a Success Acknowledgment") @@ -80,7 +82,7 @@ func (suite *CCVTestSuite) TestSendVSCMaturedPackets() { pd.ValsetUpdateId = 2 packet.Data = pd.GetBytes() packet.Sequence = 2 - ack = suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.OnRecvVSCPacket(suite.consumerChain.GetContext(), packet, pd) + ack = consumerKeeper.OnRecvVSCPacket(suite.consumerChain.GetContext(), packet, pd) suite.Require().NotNil(ack, "OnRecvVSCPacket did not return ack") suite.Require().True(ack.Success(), "OnRecvVSCPacket did not return a Success Acknowledgment") @@ -92,31 +94,31 @@ func (suite *CCVTestSuite) TestSendVSCMaturedPackets() { pd.ValsetUpdateId = 3 packet.Data = pd.GetBytes() packet.Sequence = 3 - ack = suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.OnRecvVSCPacket(suite.consumerChain.GetContext(), packet, pd) + ack = consumerKeeper.OnRecvVSCPacket(suite.consumerChain.GetContext(), packet, pd) suite.Require().NotNil(ack, "OnRecvVSCPacket did not return ack") suite.Require().True(ack.Success(), "OnRecvVSCPacket did not return a Success Acknowledgment") // increase time such that first two packets are unbonded but third is not. - unbondingPeriod, found := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetUnbondingTime(suite.consumerChain.GetContext()) + unbondingPeriod, found := consumerKeeper.GetUnbondingTime(suite.consumerChain.GetContext()) suite.Require().True(found) // increase time incrementTimeBy(suite, unbondingPeriod-time.Hour) - err = suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.SendVSCMaturedPackets(suite.consumerChain.GetContext()) + err = consumerKeeper.SendVSCMaturedPackets(suite.consumerChain.GetContext()) suite.Require().NoError(err) // ensure first two packets are unbonded and VSCMatured packets are sent // unbonded time is deleted - time1 := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetPacketMaturityTime(suite.consumerChain.GetContext(), 1) - time2 := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetPacketMaturityTime(suite.consumerChain.GetContext(), 2) + time1 := consumerKeeper.GetPacketMaturityTime(suite.consumerChain.GetContext(), 1) + time2 := consumerKeeper.GetPacketMaturityTime(suite.consumerChain.GetContext(), 2) suite.Require().Equal(uint64(0), time1, "maturity time not deleted for mature packet 1") suite.Require().Equal(uint64(0), time2, "maturity time not deleted for mature packet 2") // ensure that third packet did not get unbonded and is still in store - time3 := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetPacketMaturityTime(suite.consumerChain.GetContext(), 3) + time3 := consumerKeeper.GetPacketMaturityTime(suite.consumerChain.GetContext(), 3) suite.Require().True(time3 > uint64(suite.consumerChain.GetContext().BlockTime().UnixNano()), "maturity time for packet 3 is not after current time") // check that the packets are committed in state - commitments := suite.consumerChain.App.GetIBCKeeper().ChannelKeeper.GetAllPacketCommitmentsAtChannel( + commitments := suite.consumerApp.GetIBCKeeper().ChannelKeeper.GetAllPacketCommitmentsAtChannel( suite.consumerChain.GetContext(), ccv.ConsumerPortID, suite.path.EndpointA.ChannelID, diff --git a/testutil/e2e/interfaces.go b/testutil/e2e/interfaces.go new file mode 100644 index 0000000000..0e34aacbe6 --- /dev/null +++ b/testutil/e2e/interfaces.go @@ -0,0 +1,148 @@ +package e2e + +import ( + "time" + + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" + slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" + "github.com/cosmos/cosmos-sdk/x/staking/types" + ibctesting "github.com/cosmos/ibc-go/v3/testing" + consumerkeeper "github.com/cosmos/interchain-security/x/ccv/consumer/keeper" + providerkeeper "github.com/cosmos/interchain-security/x/ccv/provider/keeper" + ccvtypes "github.com/cosmos/interchain-security/x/ccv/types" + abci "github.com/tendermint/tendermint/abci/types" +) + +// The interface that any provider app must implement to be compatible with ccv e2e tests. +// This is a wrapper around the ibc testing app interface with additional constraints. +type ProviderApp interface { + ibctesting.TestingApp + + // + // Keeper getters + // + + GetProviderKeeper() providerkeeper.Keeper + // Returns a staking keeper interface with more capabilities than the expected_keepers interface + GetE2eStakingKeeper() E2eStakingKeeper + // Returns a bank keeper interface with more capabilities than the expected_keepers interface + GetE2eBankKeeper() E2eBankKeeper + // Returns a slashing keeper interface with more capabilities than the expected_keepers interface + GetE2eSlashingKeeper() E2eSlashingKeeper + // Returns a distribution keeper interface with more capabilities than the expected_keepers interface + GetE2eDistributionKeeper() E2eDistributionKeeper +} + +// The interface that any consumer app must implement to be compatible with e2e tests +// This is a wrapper around the ibc testing app interface with additional constraints. +type ConsumerApp interface { + ibctesting.TestingApp + + BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock + GetConsumerKeeper() consumerkeeper.Keeper + GetSubspace(moduleName string) paramstypes.Subspace + + // + // Keeper getters + // + + // Returns a bank keeper interface with more capabilities than the expected_keepers interface + GetE2eBankKeeper() E2eBankKeeper + // Returns an account keeper interface with more capabilities than the expected_keepers interface + GetE2eAccountKeeper() E2eAccountKeeper + // Returns a slashing keeper interface with more capabilities than the expected_keepers interface + GetE2eSlashingKeeper() E2eSlashingKeeper + // Returns an evidence keeper interface with more capabilities than the expected_keepers interface + GetE2eEvidenceKeeper() E2eEvidenceKeeper +} + +type DemocConsumerApp interface { + ConsumerApp + // Returns a distribution keeper interface with more capabilities than the expected_keepers interface + GetE2eDistributionKeeper() E2eDistributionKeeper + // Returns a staking keeper interface with more capabilities than the expected_keepers interface + GetE2eStakingKeeper() E2eStakingKeeper + // Returns a mint keeper interface with more capabilities than the expected_keepers interface + GetE2eMintKeeper() E2eMintKeeper + // Returns a gov keeper interface with more capabilities than the expected_keepers interface + GetE2eGovKeeper() E2eGovKeeper +} + +// +// The following keeper interfaces are wrappers around the expected keepers for ccv modules, +// since e2e tests require extra functionality from external keepers. +// + +type E2eStakingKeeper interface { + ccvtypes.StakingKeeper + Delegate(ctx sdk.Context, delAddr sdk.AccAddress, bondAmt sdk.Int, tokenSrc types.BondStatus, + validator types.Validator, subtractAccount bool) (newShares sdk.Dec, err error) + Undelegate(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress, sharesAmount sdk.Dec, + ) (time.Time, error) + BeginRedelegation(ctx sdk.Context, delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress, + sharesAmount sdk.Dec) (completionTime time.Time, err error) + GetUnbondingDelegationByUnbondingId(ctx sdk.Context, id uint64, + ) (ubd types.UnbondingDelegation, found bool) + GetRedelegations(ctx sdk.Context, delegator sdk.AccAddress, + maxRetrieve uint16) (redelegations []types.Redelegation) + BondDenom(ctx sdk.Context) (res string) + IsValidatorJailed(ctx sdk.Context, addr sdk.ConsAddress) bool + GetUnbondingDelegation(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress, + ) (ubd types.UnbondingDelegation, found bool) + GetAllValidators(ctx sdk.Context) (validators []types.Validator) + GetValidatorSet() types.ValidatorSet +} + +type E2eBankKeeper interface { + ccvtypes.BankKeeper + SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, + recipientModule string, amt sdk.Coins) error +} + +type E2eAccountKeeper interface { + ccvtypes.AccountKeeper + GetParams(sdk.Context) authtypes.Params +} + +type E2eSlashingKeeper interface { + ccvtypes.SlashingKeeper + SetValidatorSigningInfo(ctx sdk.Context, address sdk.ConsAddress, + info slashingtypes.ValidatorSigningInfo) + SignedBlocksWindow(ctx sdk.Context) (res int64) + HandleValidatorSignature(ctx sdk.Context, addr cryptotypes.Address, power int64, signed bool) + MinSignedPerWindow(ctx sdk.Context) int64 + IterateValidatorMissedBlockBitArray(ctx sdk.Context, + address sdk.ConsAddress, handler func(index int64, missed bool) (stop bool)) +} + +type E2eEvidenceKeeper interface { + HandleEquivocationEvidence(ctx sdk.Context, evidence *evidencetypes.Equivocation) +} + +type E2eDistributionKeeper interface { + GetFeePoolCommunityCoins(ctx sdk.Context) sdk.DecCoins + GetDistributionAccount(ctx sdk.Context) authtypes.ModuleAccountI + GetValidatorOutstandingRewards(ctx sdk.Context, + val sdk.ValAddress) (rewards distributiontypes.ValidatorOutstandingRewards) + GetCommunityTax(ctx sdk.Context) (percent sdk.Dec) +} + +type E2eMintKeeper interface { + GetParams(ctx sdk.Context) (params minttypes.Params) +} + +type E2eGovKeeper interface { + GetDepositParams(ctx sdk.Context) govtypes.DepositParams + GetVotingParams(ctx sdk.Context) govtypes.VotingParams + SetVotingParams(ctx sdk.Context, votingParams govtypes.VotingParams) + SubmitProposal(ctx sdk.Context, content govtypes.Content) (govtypes.Proposal, error) + AddDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress, depositAmount sdk.Coins) (bool, error) + AddVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress, options govtypes.WeightedVoteOptions) error +}