diff --git a/e2e/dockerutil/dockerutil.go b/e2e/dockerutil/dockerutil.go index bd5a561323d..48fb97055d3 100644 --- a/e2e/dockerutil/dockerutil.go +++ b/e2e/dockerutil/dockerutil.go @@ -6,7 +6,6 @@ import ( "fmt" "io" "path" - "testing" dockertypes "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" @@ -16,15 +15,15 @@ import ( const testLabel = "ibc-test" // GetTestContainers returns all docker containers that have been created by interchain test. -func GetTestContainers(ctx context.Context, t *testing.T, dc *dockerclient.Client) ([]dockertypes.Container, error) { - t.Helper() - +// note: the test suite name must be passed as the chains are created in SetupSuite which will label +// them with the name of the test suite rather than the test. +func GetTestContainers(ctx context.Context, suiteName string, dc *dockerclient.Client) ([]dockertypes.Container, error) { testContainers, err := dc.ContainerList(ctx, dockertypes.ContainerListOptions{ All: true, Filters: filters.NewArgs( // see: https://github.com/strangelove-ventures/interchaintest/blob/0bdc194c2aa11aa32479f32b19e1c50304301981/internal/dockerutil/setup.go#L31-L36 - // for the label needed to identify test containers. - filters.Arg("label", testLabel+"="+t.Name()), + // for the suiteName needed to identify test containers. + filters.Arg("label", testLabel+"="+suiteName), ), }) if err != nil { diff --git a/e2e/tests/core/02-client/client_test.go b/e2e/tests/core/02-client/client_test.go index 34980045530..cb1da13cc7c 100644 --- a/e2e/tests/core/02-client/client_test.go +++ b/e2e/tests/core/02-client/client_test.go @@ -65,7 +65,6 @@ func (s *ClientTestSuite) TestScheduleIBCUpgrade_Succeeds() { t := s.T() ctx := context.TODO() - _, _ = s.SetupChainsRelayerAndChannel(ctx, nil) chainA, chainB := s.GetChains() chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) @@ -164,23 +163,20 @@ func (s *ClientTestSuite) TestClientUpdateProposal_Succeeds() { var ( pathName string - relayer ibc.Relayer subjectClientID string substituteClientID string // set the trusting period to a value which will still be valid upon client creation, but invalid before the first update badTrustingPeriod = time.Second * 10 ) - t.Run("create substitute client with correct trusting period", func(t *testing.T) { - relayer, _ = s.SetupChainsRelayerAndChannel(ctx, nil) + relayer := s.GetRelayer() + t.Run("create substitute client with correct trusting period", func(t *testing.T) { // TODO: update when client identifier created is accessible // currently assumes first client is 07-tendermint-0 substituteClientID = clienttypes.FormatClientIdentifier(ibcexported.Tendermint, 0) - // TODO: replace with better handling of path names - pathName = fmt.Sprintf("%s-path-%d", s.T().Name(), 0) - pathName = strings.ReplaceAll(pathName, "/", "-") + pathName = s.GetPaths()[0] }) chainA, chainB := s.GetChains() @@ -247,23 +243,20 @@ func (s *ClientTestSuite) TestRecoverClient_Succeeds() { var ( pathName string - relayer ibc.Relayer subjectClientID string substituteClientID string // set the trusting period to a value which will still be valid upon client creation, but invalid before the first update badTrustingPeriod = time.Second * 10 ) - t.Run("create substitute client with correct trusting period", func(t *testing.T) { - relayer, _ = s.SetupChainsRelayerAndChannel(ctx, nil) + relayer := s.GetRelayer() + t.Run("create substitute client with correct trusting period", func(t *testing.T) { // TODO: update when client identifier created is accessible // currently assumes first client is 07-tendermint-0 substituteClientID = clienttypes.FormatClientIdentifier(ibcexported.Tendermint, 0) - // TODO: replace with better handling of path names - pathName = fmt.Sprintf("%s-path-%d", s.T().Name(), 0) - pathName = strings.ReplaceAll(pathName, "/", "-") + pathName = s.GetPaths()[0] }) chainA, chainB := s.GetChains() @@ -341,13 +334,13 @@ func (s *ClientTestSuite) TestClient_Update_Misbehaviour() { err error ) - relayer, _ := s.SetupChainsRelayerAndChannel(ctx, nil) + relayer := s.GetRelayer() chainA, chainB := s.GetChains() s.Require().NoError(test.WaitForBlocks(ctx, 10, chainA, chainB)) t.Run("update clients", func(t *testing.T) { - err := relayer.UpdateClients(ctx, s.GetRelayerExecReporter(), s.GetPathName(0)) + err := relayer.UpdateClients(ctx, s.GetRelayerExecReporter(), s.GetPaths()[0]) s.Require().NoError(err) clientState, err = query.ClientState(ctx, chainA, ibctesting.FirstClientID) @@ -363,7 +356,7 @@ func (s *ClientTestSuite) TestClient_Update_Misbehaviour() { }) t.Run("update clients", func(t *testing.T) { - err := relayer.UpdateClients(ctx, s.GetRelayerExecReporter(), s.GetPathName(0)) + err := relayer.UpdateClients(ctx, s.GetRelayerExecReporter(), s.GetPaths()[0]) s.Require().NoError(err) clientState, err = query.ClientState(ctx, chainA, ibctesting.FirstClientID) @@ -397,11 +390,15 @@ func (s *ClientTestSuite) TestClient_Update_Misbehaviour() { t.Run("extract validator private keys", func(t *testing.T) { privateKeys := s.extractChainPrivateKeys(ctx, chainB) + s.Require().NotEmpty(privateKeys, "private keys are empty") + for i, pv := range privateKeys { pubKey, err := pv.GetPubKey() s.Require().NoError(err) validator := cmttypes.NewValidator(pubKey, validators[i].VotingPower) + err = validator.ValidateBasic() + s.Require().NoError(err, "invalid validator: %s", err) validatorSet = append(validatorSet, validator) signers = append(signers, pv) @@ -409,8 +406,12 @@ func (s *ClientTestSuite) TestClient_Update_Misbehaviour() { }) }) + s.Require().NotEmpty(validatorSet, "validator set is empty") + t.Run("create malicious header", func(t *testing.T) { valSet := cmttypes.NewValidatorSet(validatorSet) + err := valSet.ValidateBasic() + s.Require().NoError(err, "invalid validator set: %s", err) maliciousHeader, err = createMaliciousTMHeader(chainB.Config().ChainID, int64(latestHeight.GetRevisionHeight()), trustedHeight, header.GetTime(), valSet, valSet, signers, header) s.Require().NoError(err) @@ -437,8 +438,6 @@ func (s *ClientTestSuite) TestAllowedClientsParam() { t := s.T() ctx := context.TODO() - _, _ = s.SetupChainsRelayerAndChannel(ctx, s.TransferChannelOptions()) - chainA, chainB := s.GetChains() chainAVersion := chainA.Config().Images[0].Version chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) @@ -494,8 +493,9 @@ func (s *ClientTestSuite) TestAllowedClientsParam() { // extractChainPrivateKeys returns a slice of cmttypes.PrivValidator which hold the private keys for all validator // nodes for a given chain. func (s *ClientTestSuite) extractChainPrivateKeys(ctx context.Context, chain ibc.Chain) []cmttypes.PrivValidator { - testContainers, err := dockerutil.GetTestContainers(ctx, s.T(), s.DockerClient) + testContainers, err := dockerutil.GetTestContainers(ctx, s.SuiteName(), s.DockerClient) s.Require().NoError(err) + s.Require().NotEmpty(testContainers, "no test containers found") var filePvs []privval.FilePVKey var pvs []cmttypes.PrivValidator @@ -503,6 +503,7 @@ func (s *ClientTestSuite) extractChainPrivateKeys(ctx context.Context, chain ibc isNodeForDifferentChain := !strings.Contains(container.Names[0], chain.Config().ChainID) isFullNode := strings.Contains(container.Names[0], fmt.Sprintf("%s-fn", chain.Config().ChainID)) if isNodeForDifferentChain || isFullNode { + s.T().Logf("skipping container %s for chain %s", container.Names[0], chain.Config().ChainID) continue } diff --git a/e2e/tests/core/03-connection/connection_test.go b/e2e/tests/core/03-connection/connection_test.go index c9283be5abb..9caeb4a302b 100644 --- a/e2e/tests/core/03-connection/connection_test.go +++ b/e2e/tests/core/03-connection/connection_test.go @@ -33,6 +33,10 @@ type ConnectionTestSuite struct { testsuite.E2ETestSuite } +func (s *ConnectionTestSuite) SetupTest() { + s.SetupPath(ibc.DefaultClientOpts(), s.TransferChannelOptions()) +} + // QueryMaxExpectedTimePerBlockParam queries the on-chain max expected time per block param for 03-connection func (s *ConnectionTestSuite) QueryMaxExpectedTimePerBlockParam(ctx context.Context, chain ibc.Chain) uint64 { if testvalues.SelfParamsFeatureReleases.IsSupported(chain.Config().Images[0].Version) { @@ -61,7 +65,7 @@ func (s *ConnectionTestSuite) TestMaxExpectedTimePerBlockParam() { t := s.T() ctx := context.TODO() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, s.TransferChannelOptions()) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() chainA, chainB := s.GetChains() chainAVersion := chainA.Config().Images[0].Version diff --git a/e2e/tests/interchain_accounts/base_test.go b/e2e/tests/interchain_accounts/base_test.go index 583061d6eee..76e6e53beed 100644 --- a/e2e/tests/interchain_accounts/base_test.go +++ b/e2e/tests/interchain_accounts/base_test.go @@ -64,7 +64,7 @@ func (s *InterchainAccountsTestSuite) testMsgSendTxSuccessfulTransfer(order chan // setup relayers and connection-0 between two chains // channel-0 is a transfer channel but it will not be used in this test case - relayer, _ := s.SetupChainsRelayerAndChannel(ctx, nil) + relayer := s.GetRelayer() chainA, chainB := s.GetChains() // setup 2 accounts: controller account on chain A, a second chain B account. @@ -161,9 +161,7 @@ func (s *InterchainAccountsTestSuite) TestMsgSendTx_FailedTransfer_InsufficientF t := s.T() ctx := context.TODO() - // setup relayers and connection-0 between two chains - // channel-0 is a transfer channel but it will not be used in this test case - relayer, _ := s.SetupChainsRelayerAndChannel(ctx, nil) + relayer := s.GetRelayer() chainA, chainB := s.GetChains() // setup 2 accounts: controller account on chain A, a second chain B account. @@ -251,9 +249,7 @@ func (s *InterchainAccountsTestSuite) TestMsgSendTx_SuccessfulTransfer_AfterReop t := s.T() ctx := context.TODO() - // setup relayers and connection-0 between two chains - // channel-0 is a transfer channel but it will not be used in this test case - relayer, _ := s.SetupChainsRelayerAndChannel(ctx, nil) + relayer := s.GetRelayer() chainA, chainB := s.GetChains() // setup 2 accounts: controller account on chain A, a second chain B account. @@ -442,7 +438,7 @@ func (s *InterchainAccountsTestSuite) testMsgSendTxSuccessfulGovProposal(order c // setup relayers and connection-0 between two chains // channel-0 is a transfer channel but it will not be used in this test case - relayer, _ := s.SetupChainsRelayerAndChannel(ctx, nil) + relayer := s.GetRelayer() chainA, chainB := s.GetChains() // setup 2 accounts: controller account on chain A, a second chain B account. diff --git a/e2e/tests/interchain_accounts/gov_test.go b/e2e/tests/interchain_accounts/gov_test.go index 11cb8d358ab..98f1acd9fed 100644 --- a/e2e/tests/interchain_accounts/gov_test.go +++ b/e2e/tests/interchain_accounts/gov_test.go @@ -40,9 +40,7 @@ func (s *InterchainAccountsGovTestSuite) TestInterchainAccountsGovIntegration() t := s.T() ctx := context.TODO() - // setup relayers and connection-0 between two chains - // channel-0 is a transfer channel but it will not be used in this test case - relayer, _ := s.SetupChainsRelayerAndChannel(ctx, nil) + relayer := s.GetRelayer() chainA, chainB := s.GetChains() controllerAccount := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) diff --git a/e2e/tests/interchain_accounts/groups_test.go b/e2e/tests/interchain_accounts/groups_test.go index 2d1c51cda4b..2ebc61d660e 100644 --- a/e2e/tests/interchain_accounts/groups_test.go +++ b/e2e/tests/interchain_accounts/groups_test.go @@ -86,9 +86,7 @@ func (s *InterchainAccountsGroupsTestSuite) TestInterchainAccountsGroupsIntegrat err error ) - // setup relayers and connection-0 between two chains - // channel-0 is a transfer channel but it will not be used in this test case - relayer, _ := s.SetupChainsRelayerAndChannel(ctx, nil) + relayer := s.GetRelayer() chainA, chainB := s.GetChains() chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) diff --git a/e2e/tests/interchain_accounts/incentivized_test.go b/e2e/tests/interchain_accounts/incentivized_test.go index fb98fe3e89d..b4424f264f3 100644 --- a/e2e/tests/interchain_accounts/incentivized_test.go +++ b/e2e/tests/interchain_accounts/incentivized_test.go @@ -40,9 +40,7 @@ func (s *IncentivizedInterchainAccountsTestSuite) TestMsgSendTx_SuccessfulBankSe t := s.T() ctx := context.TODO() - // setup relayers and connection-0 between two chains - // channel-0 is a transfer channel but it will not be used in this test case - relayer, _ := s.SetupChainsRelayerAndChannel(ctx, nil) + relayer := s.GetRelayer() chainA, chainB := s.GetChains() var ( @@ -218,9 +216,7 @@ func (s *IncentivizedInterchainAccountsTestSuite) TestMsgSendTx_FailedBankSend_I t := s.T() ctx := context.TODO() - // setup relayers and connection-0 between two chains - // channel-0 is a transfer channel but it will not be used in this test case - relayer, _ := s.SetupChainsRelayerAndChannel(ctx, nil) + relayer := s.GetRelayer() chainA, chainB := s.GetChains() var ( diff --git a/e2e/tests/interchain_accounts/localhost_test.go b/e2e/tests/interchain_accounts/localhost_test.go index 7867a35e4a0..e11233c2f2c 100644 --- a/e2e/tests/interchain_accounts/localhost_test.go +++ b/e2e/tests/interchain_accounts/localhost_test.go @@ -42,7 +42,6 @@ func (s *LocalhostInterchainAccountsTestSuite) TestInterchainAccounts_Localhost( t := s.T() ctx := context.TODO() - _, _ = s.SetupChainsRelayerAndChannel(ctx, nil) chainA, _ := s.GetChains() chainADenom := chainA.Config().Denom @@ -196,8 +195,6 @@ func (s *LocalhostInterchainAccountsTestSuite) TestInterchainAccounts_ReopenChan t := s.T() ctx := context.TODO() - // relayer and channel output is discarded, only a single chain is required - _, _ = s.SetupChainsRelayerAndChannel(ctx, nil) chainA, _ := s.GetChains() chainADenom := chainA.Config().Denom diff --git a/e2e/tests/interchain_accounts/params_test.go b/e2e/tests/interchain_accounts/params_test.go index d0e37696fae..afe6893cf16 100644 --- a/e2e/tests/interchain_accounts/params_test.go +++ b/e2e/tests/interchain_accounts/params_test.go @@ -60,9 +60,6 @@ func (s *InterchainAccountsParamsTestSuite) TestControllerEnabledParam() { t := s.T() ctx := context.TODO() - // setup relayers and connection-0 between two chains - // channel-0 is a transfer channel but it will not be used in this test case - _, _ = s.SetupChainsRelayerAndChannel(ctx, nil) chainA, _ := s.GetChains() chainAVersion := chainA.Config().Images[0].Version @@ -115,9 +112,7 @@ func (s *InterchainAccountsParamsTestSuite) TestHostEnabledParam() { t := s.T() ctx := context.TODO() - // setup relayers and connection-0 between two chains - // channel-0 is a transfer channel but it will not be used in this test case - relayer, _ := s.SetupChainsRelayerAndChannel(ctx, nil) + relayer := s.GetRelayer() chainA, chainB := s.GetChains() chainBVersion := chainB.Config().Images[0].Version diff --git a/e2e/tests/interchain_accounts/query_test.go b/e2e/tests/interchain_accounts/query_test.go index cfacb0a71f8..7c864bf70c7 100644 --- a/e2e/tests/interchain_accounts/query_test.go +++ b/e2e/tests/interchain_accounts/query_test.go @@ -40,7 +40,7 @@ func (s *InterchainAccountsQueryTestSuite) TestInterchainAccountsQuery() { // setup relayers and connection-0 between two chains // channel-0 is a transfer channel but it will not be used in this test case - relayer, _ := s.SetupChainsRelayerAndChannel(ctx, nil) + relayer := s.GetRelayer() chainA, chainB := s.GetChains() chainBVersion := chainB.Config().Images[0].Version diff --git a/e2e/tests/interchain_accounts/upgrades_test.go b/e2e/tests/interchain_accounts/upgrades_test.go index cbc461c3c9e..af7b22e7ea4 100644 --- a/e2e/tests/interchain_accounts/upgrades_test.go +++ b/e2e/tests/interchain_accounts/upgrades_test.go @@ -45,7 +45,7 @@ func (s *InterchainAccountsChannelUpgradesTestSuite) TestMsgSendTx_SuccessfulTra // setup relayers and connection-0 between two chains // channel-0 is a transfer channel but it will not be used in this test case - relayer, _ := s.SetupChainsRelayerAndChannel(ctx, nil) + relayer := s.GetRelayer() chainA, chainB := s.GetChains() // setup 2 accounts: controller account on chain A, a second chain B account. @@ -223,9 +223,7 @@ func (s *InterchainAccountsChannelUpgradesTestSuite) TestChannelUpgrade_ICAChann t := s.T() ctx := context.TODO() - // setup relayers and connection-0 between two chains - // channel-0 is a transfer channel but it will not be used in this test case - relayer, _ := s.SetupChainsRelayerAndChannel(ctx, nil) + relayer := s.GetRelayer() chainA, chainB := s.GetChains() // setup 2 accounts: controller account on chain A, a second chain B account. diff --git a/e2e/tests/transfer/authz_test.go b/e2e/tests/transfer/authz_test.go index f527ee0663c..3e3f5389588 100644 --- a/e2e/tests/transfer/authz_test.go +++ b/e2e/tests/transfer/authz_test.go @@ -32,6 +32,10 @@ type AuthzTransferTestSuite struct { testsuite.E2ETestSuite } +func (suite *AuthzTransferTestSuite) SetupTest() { + suite.SetupPath(ibc.DefaultClientOpts(), suite.TransferChannelOptions()) +} + // QueryGranterGrants returns all GrantAuthorizations for the given granterAddress. func (*AuthzTransferTestSuite) QueryGranterGrants(ctx context.Context, chain ibc.Chain, granterAddress string) ([]*authz.GrantAuthorization, error) { res, err := query.GRPCQuery[authz.QueryGranterGrantsResponse](ctx, chain, &authz.QueryGranterGrantsRequest{ @@ -48,7 +52,7 @@ func (suite *AuthzTransferTestSuite) TestAuthz_MsgTransfer_Succeeds() { t := suite.T() ctx := context.TODO() - relayer, channelA := suite.SetupChainsRelayerAndChannel(ctx, suite.TransferChannelOptions()) + relayer, channelA := suite.GetRelayer(), suite.GetChainAChannel() chainA, chainB := suite.GetChains() chainADenom := chainA.Config().Denom @@ -206,7 +210,8 @@ func (suite *AuthzTransferTestSuite) TestAuthz_InvalidTransferAuthorizations() { t := suite.T() ctx := context.TODO() - relayer, channelA := suite.SetupChainsRelayerAndChannel(ctx, suite.TransferChannelOptions()) + relayer, channelA := suite.GetRelayer(), suite.GetChainAChannel() + chainA, chainB := suite.GetChains() chainADenom := chainA.Config().Denom chainAVersion := chainA.Config().Images[0].Version diff --git a/e2e/tests/transfer/base_test.go b/e2e/tests/transfer/base_test.go index d11c45c5798..5993f92862e 100644 --- a/e2e/tests/transfer/base_test.go +++ b/e2e/tests/transfer/base_test.go @@ -33,6 +33,10 @@ type TransferTestSuite struct { testsuite.E2ETestSuite } +func (s *TransferTestSuite) SetupTest() { + s.SetupPath(ibc.DefaultClientOpts(), s.TransferChannelOptions()) +} + // QueryTransferParams queries the on-chain send enabled param for the transfer module func (s *TransferTestSuite) QueryTransferParams(ctx context.Context, chain ibc.Chain) transfertypes.Params { res, err := query.GRPCQuery[transfertypes.QueryParamsResponse](ctx, chain, &transfertypes.QueryParamsRequest{}) @@ -47,7 +51,7 @@ func (s *TransferTestSuite) TestMsgTransfer_Succeeds_Nonincentivized() { t := s.T() ctx := context.TODO() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, s.TransferChannelOptions()) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() chainA, chainB := s.GetChains() chainAVersion := chainA.Config().Images[0].Version @@ -156,7 +160,7 @@ func (s *TransferTestSuite) TestMsgTransfer_Succeeds_Nonincentivized_MultiDenom( t := s.T() ctx := context.TODO() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, nil) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() chainA, chainB := s.GetChains() chainADenom := chainA.Config().Denom @@ -256,7 +260,7 @@ func (s *TransferTestSuite) TestMsgTransfer_Fails_InvalidAddress_MultiDenom() { t := s.T() ctx := context.TODO() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, nil) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() chainA, chainB := s.GetChains() chainADenom := chainA.Config().Denom @@ -375,7 +379,7 @@ func (s *TransferTestSuite) TestMsgTransfer_Fails_InvalidAddress() { t := s.T() ctx := context.TODO() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, s.TransferChannelOptions()) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() chainA, chainB := s.GetChains() chainADenom := chainA.Config().Denom @@ -419,7 +423,7 @@ func (s *TransferTestSuite) TestMsgTransfer_Timeout_Nonincentivized() { t := s.T() ctx := context.TODO() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, s.TransferChannelOptions()) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() chainA, _ := s.GetChains() chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) @@ -468,7 +472,7 @@ func (s *TransferTestSuite) TestSendEnabledParam() { t := s.T() ctx := context.TODO() - _, channelA := s.SetupChainsRelayerAndChannel(ctx, s.TransferChannelOptions()) + channelA := s.GetChainAChannel() chainA, chainB := s.GetChains() chainAVersion := chainA.Config().Images[0].Version @@ -528,7 +532,7 @@ func (s *TransferTestSuite) TestReceiveEnabledParam() { t := s.T() ctx := context.TODO() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, s.TransferChannelOptions()) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() chainA, chainB := s.GetChains() chainAVersion := chainA.Config().Images[0].Version @@ -648,7 +652,7 @@ func (s *TransferTestSuite) TestMsgTransfer_WithMemo() { t := s.T() ctx := context.TODO() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, s.TransferChannelOptions()) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() chainA, chainB := s.GetChains() chainADenom := chainA.Config().Denom diff --git a/e2e/tests/transfer/forwarding_test.go b/e2e/tests/transfer/forwarding_test.go index dbebfab1e9c..79ee19f6391 100644 --- a/e2e/tests/transfer/forwarding_test.go +++ b/e2e/tests/transfer/forwarding_test.go @@ -21,6 +21,11 @@ type TransferForwardingTestSuite struct { testsuite.E2ETestSuite } +// SetupSuite explicitly sets up three chains for this test suite. +func (s *TransferForwardingTestSuite) SetupSuite() { + s.SetupChains(context.TODO(), nil, testsuite.ThreeChainSetup()) +} + // TODO: replace this with actual tests https://github.com/cosmos/ibc-go/issues/6578 // this test verifies that three chains can be set up, and the relayer will relay // packets between them as configured in the newInterchain function. @@ -28,15 +33,21 @@ func (s *TransferForwardingTestSuite) TestThreeChainSetup() { ctx := context.TODO() t := s.T() - // TODO: note the ThreeChainSetup fn needs to be passed to TransferChannelOptions since it calls - // GetChains which will requires those settings. We should be able to update the function to accept - // the chain version rather than calling GetChains. - // https://github.com/cosmos/ibc-go/issues/6577 - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, s.TransferChannelOptions(testsuite.ThreeChainSetup()), testsuite.ThreeChainSetup()) - chains := s.GetAllChains() + relayer, chains := s.GetRelayer(), s.GetAllChains() chainA, chainB, chainC := chains[0], chains[1], chains[2] + chainAChannels := s.GetChannels(chainA) + chainBChannels := s.GetChannels(chainB) + chainCChannels := s.GetChannels(chainC) + + s.Require().Len(chainAChannels, 1, "expected 1 channels on chain A") + s.Require().Len(chainBChannels, 2, "expected 2 channels on chain B") + s.Require().Len(chainCChannels, 1, "expected 1 channels on chain C") + + channelAToB := chainAChannels[0] + channelBToC := chainBChannels[1] + chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) chainAAddress := chainAWallet.FormattedAddress() chainADenom := chainA.Config().Denom @@ -49,19 +60,12 @@ func (s *TransferForwardingTestSuite) TestThreeChainSetup() { chainCAddress := chainCWallet.FormattedAddress() t.Run("IBC transfer from A to B", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "") + transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelAToB.PortID, channelAToB.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "") s.AssertTxSuccess(transferTxResp) }) - chainBChannels, err := relayer.GetChannels(ctx, s.GetRelayerExecReporter(), chainB.Config().ChainID) - s.Require().NoError(err) - // channel between A and B and channel between B and C - s.Require().Len(chainBChannels, 2) - - chainBtoCChannel := chainBChannels[0] - t.Run("IBC transfer from B to C", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainB, chainBWallet, chainBtoCChannel.PortID, chainBtoCChannel.ChannelID, testvalues.DefaultTransferCoins(chainBDenom), chainBAddress, chainCAddress, s.GetTimeoutHeight(ctx, chainC), 0, "") + transferTxResp := s.Transfer(ctx, chainB, chainBWallet, channelBToC.PortID, channelBToC.ChannelID, testvalues.DefaultTransferCoins(chainBDenom), chainBAddress, chainCAddress, s.GetTimeoutHeight(ctx, chainC), 0, "") s.AssertTxSuccess(transferTxResp) }) @@ -69,9 +73,9 @@ func (s *TransferForwardingTestSuite) TestThreeChainSetup() { s.StartRelayer(relayer) }) - chainBIBCToken := testsuite.GetIBCToken(chainADenom, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID) + chainBIBCToken := testsuite.GetIBCToken(chainADenom, channelAToB.Counterparty.PortID, channelAToB.Counterparty.ChannelID) t.Run("packets are relayed from A to B", func(t *testing.T) { - s.AssertPacketRelayed(ctx, chainA, channelA.PortID, channelA.ChannelID, 1) + s.AssertPacketRelayed(ctx, chainA, channelAToB.PortID, channelAToB.ChannelID, 1) actualBalance, err := query.Balance(ctx, chainB, chainBAddress, chainBIBCToken.IBCDenom()) s.Require().NoError(err) @@ -80,9 +84,9 @@ func (s *TransferForwardingTestSuite) TestThreeChainSetup() { s.Require().Equal(expected, actualBalance.Int64()) }) - chainCIBCToken := testsuite.GetIBCToken(chainBDenom, chainBtoCChannel.Counterparty.PortID, chainBtoCChannel.Counterparty.ChannelID) + chainCIBCToken := testsuite.GetIBCToken(chainBDenom, channelBToC.Counterparty.PortID, channelBToC.Counterparty.ChannelID) t.Run("packets are relayed from B to C", func(t *testing.T) { - s.AssertPacketRelayed(ctx, chainB, chainBtoCChannel.PortID, chainBtoCChannel.ChannelID, 1) + s.AssertPacketRelayed(ctx, chainB, channelBToC.PortID, channelBToC.ChannelID, 1) actualBalance, err := query.Balance(ctx, chainC, chainCAddress, chainCIBCToken.IBCDenom()) s.Require().NoError(err) diff --git a/e2e/tests/transfer/incentivized_test.go b/e2e/tests/transfer/incentivized_test.go index 6b54c31b961..d57a8b2c0b8 100644 --- a/e2e/tests/transfer/incentivized_test.go +++ b/e2e/tests/transfer/incentivized_test.go @@ -36,11 +36,16 @@ func TestIncentivizedTransferTestSuite(t *testing.T) { testifysuite.Run(t, new(IncentivizedTransferTestSuite)) } +// SetupTest explicitly enables fee middleware in the channel options. +func (s *IncentivizedTransferTestSuite) SetupTest() { + s.SetupPath(ibc.DefaultClientOpts(), s.FeeTransferChannelOptions()) +} + func (s *IncentivizedTransferTestSuite) TestMsgPayPacketFee_AsyncSingleSender_Succeeds() { t := s.T() ctx := context.TODO() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, s.FeeMiddlewareChannelOptions()) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() chainA, chainB := s.GetChains() chainAVersion := chainA.Config().Images[0].Version @@ -158,7 +163,7 @@ func (s *IncentivizedTransferTestSuite) TestMsgPayPacketFee_InvalidReceiverAccou t := s.T() ctx := context.TODO() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, s.FeeMiddlewareChannelOptions()) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() chainA, chainB := s.GetChains() chainAVersion := chainA.Config().Images[0].Version @@ -285,7 +290,7 @@ func (s *IncentivizedTransferTestSuite) TestMultiMsg_MsgPayPacketFeeSingleSender t := s.T() ctx := context.TODO() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, s.FeeMiddlewareChannelOptions()) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() chainA, chainB := s.GetChains() chainAVersion := chainA.Config().Images[0].Version @@ -404,7 +409,7 @@ func (s *IncentivizedTransferTestSuite) TestMsgPayPacketFee_SingleSender_TimesOu t := s.T() ctx := context.TODO() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, s.FeeMiddlewareChannelOptions()) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() chainA, chainB := s.GetChains() chainAVersion := chainA.Config().Images[0].Version @@ -520,7 +525,7 @@ func (s *IncentivizedTransferTestSuite) TestPayPacketFeeAsync_SingleSender_NoCou t := s.T() ctx := context.TODO() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, s.FeeMiddlewareChannelOptions()) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() chainA, _ := s.GetChains() chainAVersion := chainA.Config().Images[0].Version @@ -621,7 +626,7 @@ func (s *IncentivizedTransferTestSuite) TestMsgPayPacketFee_AsyncMultipleSenders t := s.T() ctx := context.TODO() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, s.FeeMiddlewareChannelOptions()) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() chainA, chainB := s.GetChains() chainAVersion := chainA.Config().Images[0].Version diff --git a/e2e/tests/transfer/localhost_test.go b/e2e/tests/transfer/localhost_test.go index 8d3de8e2808..c24a4d19425 100644 --- a/e2e/tests/transfer/localhost_test.go +++ b/e2e/tests/transfer/localhost_test.go @@ -35,7 +35,7 @@ func (s *LocalhostTransferTestSuite) TestMsgTransfer_Localhost() { t := s.T() ctx := context.TODO() - _, channelA := s.SetupChainsRelayerAndChannel(ctx, s.TransferChannelOptions()) + channelA := s.GetChainAChannel() chainA, _ := s.GetChains() chainADenom := chainA.Config().Denom diff --git a/e2e/tests/transfer/upgradesv1_test.go b/e2e/tests/transfer/upgradesv1_test.go new file mode 100644 index 00000000000..254b288127f --- /dev/null +++ b/e2e/tests/transfer/upgradesv1_test.go @@ -0,0 +1,356 @@ +//go:build !test_e2e + +package transfer + +import ( + "context" + "testing" + + "github.com/strangelove-ventures/interchaintest/v8/ibc" + test "github.com/strangelove-ventures/interchaintest/v8/testutil" + testifysuite "github.com/stretchr/testify/suite" + + sdkmath "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/ibc-go/e2e/testsuite" + "github.com/cosmos/ibc-go/e2e/testsuite/query" + "github.com/cosmos/ibc-go/e2e/testvalues" + feetypes "github.com/cosmos/ibc-go/v8/modules/apps/29-fee/types" + transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" + channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" +) + +func TestTransferChannelUpgradesV1TestSuite(t *testing.T) { + testifysuite.Run(t, new(TransferChannelUpgradesV1TestSuite)) +} + +type TransferChannelUpgradesV1TestSuite struct { + testsuite.E2ETestSuite +} + +func (s *TransferChannelUpgradesV1TestSuite) SetupTest() { + opts := s.TransferChannelOptions() + opts.Version = transfertypes.V1 + s.SetupPath(ibc.DefaultClientOpts(), opts) +} + +// TestChannelUpgrade_WithICS20v2_Succeeds tests upgrading a transfer channel to ICS20 v2. +func (s *TransferChannelUpgradesV1TestSuite) TestChannelUpgrade_WithICS20v2_Succeeds() { + t := s.T() + ctx := context.TODO() + + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() + + channelB := channelA.Counterparty + chainA, chainB := s.GetChains() + + chainADenom := chainA.Config().Denom + chainBDenom := chainB.Config().Denom + chainAIBCToken := testsuite.GetIBCToken(chainBDenom, channelA.PortID, channelA.ChannelID) + chainBIBCToken := testsuite.GetIBCToken(chainADenom, channelB.PortID, channelB.ChannelID) + + chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) + chainAAddress := chainAWallet.FormattedAddress() + + chainBWallet := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) + chainBAddress := chainBWallet.FormattedAddress() + + s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA, chainB), "failed to wait for blocks") + + t.Run("verify transfer version of channel A is ics20-1", func(t *testing.T) { + channel, err := query.Channel(ctx, chainA, channelA.PortID, channelA.ChannelID) + s.Require().NoError(err) + s.Require().Equal(transfertypes.V1, channel.Version, "the channel version is not ics20-1") + }) + + t.Run("native token transfer from chainA to chainB, sender is source of tokens", func(t *testing.T) { + chainBWalletAmount := ibc.WalletAmount{ + Address: chainBWallet.FormattedAddress(), // destination address + Denom: chainA.Config().Denom, + Amount: sdkmath.NewInt(testvalues.IBCTransferAmount), + } + + transferTxResp, err := chainA.SendIBCTransfer(ctx, channelA.ChannelID, chainAWallet.KeyName(), chainBWalletAmount, ibc.TransferOptions{}) + s.Require().NoError(err) + s.Require().NoError(transferTxResp.Validate(), "chain-a ibc transfer tx is invalid") + }) + + s.Require().NoError(test.WaitForBlocks(ctx, 5, chainA, chainB), "failed to wait for blocks") + + t.Run("tokens are escrowed", func(t *testing.T) { + actualBalance, err := s.GetChainANativeBalance(ctx, chainAWallet) + s.Require().NoError(err) + + expected := testvalues.StartingTokenAmount - testvalues.IBCTransferAmount + s.Require().Equal(expected, actualBalance) + + actualTotalEscrow, err := query.TotalEscrowForDenom(ctx, chainA, chainADenom) + s.Require().NoError(err) + + expectedTotalEscrow := sdk.NewCoin(chainADenom, sdkmath.NewInt(testvalues.IBCTransferAmount)) + s.Require().Equal(expectedTotalEscrow, actualTotalEscrow) + }) + + t.Run("start relayer", func(t *testing.T) { + s.StartRelayer(relayer) + }) + + t.Run("packets are relayed", func(t *testing.T) { + s.AssertPacketRelayed(ctx, chainA, channelA.PortID, channelA.ChannelID, 1) + + actualBalance, err := query.Balance(ctx, chainB, chainBAddress, chainBIBCToken.IBCDenom()) + s.Require().NoError(err) + + expected := testvalues.IBCTransferAmount + s.Require().Equal(expected, actualBalance.Int64()) + }) + + t.Run("execute gov proposal to initiate channel upgrade", func(t *testing.T) { + chA, err := query.Channel(ctx, chainA, channelA.PortID, channelA.ChannelID) + s.Require().NoError(err) + + upgradeFields := channeltypes.NewUpgradeFields(chA.Ordering, chA.ConnectionHops, transfertypes.V2) + s.InitiateChannelUpgrade(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, upgradeFields) + }) + + s.Require().NoError(test.WaitForBlocks(ctx, 10, chainA, chainB), "failed to wait for blocks") + + t.Run("verify channel A upgraded and transfer version is ics20-2", func(t *testing.T) { + channel, err := query.Channel(ctx, chainA, channelA.PortID, channelA.ChannelID) + s.Require().NoError(err) + s.Require().Equal(transfertypes.V2, channel.Version, "the channel version is not ics20-2") + }) + + t.Run("verify channel B upgraded and transfer version is ics20-2", func(t *testing.T) { + channel, err := query.Channel(ctx, chainB, channelB.PortID, channelB.ChannelID) + s.Require().NoError(err) + s.Require().Equal(transfertypes.V2, channel.Version, "the channel version is not ics20-2") + }) + + // send the native chainB denom and also the ibc token from chainA + transferCoins := []sdk.Coin{ + testvalues.DefaultTransferAmount(chainBIBCToken.IBCDenom()), + testvalues.DefaultTransferAmount(chainBDenom), + } + + t.Run("native token from chain B and non-native IBC token from chainA, both to chainA", func(t *testing.T) { + transferTxResp := s.Transfer(ctx, chainB, chainBWallet, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, transferCoins, chainBAddress, chainAAddress, s.GetTimeoutHeight(ctx, chainA), 0, "") + s.AssertTxSuccess(transferTxResp) + }) + + s.Require().NoError(test.WaitForBlocks(ctx, 5, chainA, chainB), "failed to wait for blocks") + + t.Run("packets are relayed", func(t *testing.T) { + s.AssertPacketRelayed(ctx, chainB, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, 1) + + t.Run("chain A native denom", func(t *testing.T) { + actualBalance, err := s.GetChainANativeBalance(ctx, chainAWallet) + s.Require().NoError(err) + + expected := testvalues.StartingTokenAmount + s.Require().Equal(expected, actualBalance) + }) + + t.Run("chain B IBC denom", func(t *testing.T) { + actualBalance, err := query.Balance(ctx, chainA, chainAAddress, chainAIBCToken.IBCDenom()) + s.Require().NoError(err) + + expected := testvalues.IBCTransferAmount + s.Require().Equal(expected, actualBalance.Int64()) + }) + }) + + t.Run("tokens are un-escrowed", func(t *testing.T) { + t.Run("chain A escrow", func(t *testing.T) { + actualTotalEscrow, err := query.TotalEscrowForDenom(ctx, chainA, chainADenom) + s.Require().NoError(err) + s.Require().Equal(sdk.NewCoin(chainADenom, sdkmath.NewInt(0)), actualTotalEscrow) // total escrow is zero because tokens have come back + }) + + t.Run("chain B escrow", func(t *testing.T) { + actualTotalEscrow, err := query.TotalEscrowForDenom(ctx, chainB, chainBDenom) + s.Require().NoError(err) + s.Require().Equal(sdk.NewCoin(chainBDenom, sdkmath.NewInt(testvalues.IBCTransferAmount)), actualTotalEscrow) + }) + }) +} + +// TestChannelUpgrade_WithFeeMiddlewareAndICS20v2_Succeeds tests upgrading a transfer channel to wire up fee middleware and upgrade to ICS20 v2. +func (s *TransferChannelUpgradesV1TestSuite) TestChannelUpgrade_WithFeeMiddlewareAndICS20v2_Succeeds() { + t := s.T() + ctx := context.TODO() + + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() + + channelB := channelA.Counterparty + chainA, chainB := s.GetChains() + + chainADenom := chainA.Config().Denom + chainBDenom := chainB.Config().Denom + chainAIBCToken := testsuite.GetIBCToken(chainBDenom, channelA.PortID, channelA.ChannelID) + chainBIBCToken := testsuite.GetIBCToken(chainADenom, channelB.PortID, channelB.ChannelID) + + chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) + chainBWallet := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) + chainBAddress := chainBWallet.FormattedAddress() + + s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA, chainB), "failed to wait for blocks") + + var ( + err error + channel channeltypes.Channel + ) + + t.Run("verify transfer version of channel A is ics20-1", func(t *testing.T) { + channel, err = query.Channel(ctx, chainA, channelA.PortID, channelA.ChannelID) + s.Require().NoError(err) + s.Require().Equal(transfertypes.V1, channel.Version, "the channel version is not ics20-1") + }) + + t.Run("native token transfer from chainB to chainA, sender is source of tokens", func(t *testing.T) { + chainAwalletAmount := ibc.WalletAmount{ + Address: chainAWallet.FormattedAddress(), // destination address + Denom: chainBDenom, + Amount: sdkmath.NewInt(testvalues.IBCTransferAmount), + } + + transferTxResp, err := chainB.SendIBCTransfer(ctx, channelB.ChannelID, chainBWallet.KeyName(), chainAwalletAmount, ibc.TransferOptions{}) + s.Require().NoError(err) + s.Require().NoError(transferTxResp.Validate(), "chain-b ibc transfer tx is invalid") + }) + + t.Run("start relayer", func(t *testing.T) { + s.StartRelayer(relayer) + }) + + t.Run("execute gov proposal to initiate channel upgrade", func(t *testing.T) { + channel.Version = transfertypes.V2 // change version to ics20-2 + s.InitiateChannelUpgrade(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, s.CreateUpgradeFields(channel)) + }) + + s.Require().NoError(test.WaitForBlocks(ctx, 10, chainA, chainB), "failed to wait for blocks") + + t.Run("verify channel A upgraded and channel version is {ics29-1,ics20-2}", func(t *testing.T) { + channel, err = query.Channel(ctx, chainA, channelA.PortID, channelA.ChannelID) + s.Require().NoError(err) + + // check the channel version include the fee version + version, err := feetypes.MetadataFromVersion(channel.Version) + s.Require().NoError(err) + s.Require().Equal(feetypes.Version, version.FeeVersion, "the channel version did not include ics29") + s.Require().Equal(transfertypes.V2, version.AppVersion, "the channel version is not ics20-2") + }) + + t.Run("verify channel B upgraded and channel version is {ics29-1,ics20-2}", func(t *testing.T) { + channel, err = query.Channel(ctx, chainB, channelB.PortID, channelB.ChannelID) + s.Require().NoError(err) + + // check the channel version include the fee version + version, err := feetypes.MetadataFromVersion(channel.Version) + s.Require().NoError(err) + s.Require().Equal(feetypes.Version, version.FeeVersion, "the channel version did not include ics29") + s.Require().Equal(transfertypes.V2, version.AppVersion, "the channel version is not ics20-2") + }) + + var ( + chainARelayerWallet, chainBRelayerWallet ibc.Wallet + relayerAStartingBalance int64 + testFee = testvalues.DefaultFee(chainADenom) + ) + + t.Run("recover relayer wallets", func(t *testing.T) { + err := s.RecoverRelayerWallets(ctx, relayer) + s.Require().NoError(err) + + chainARelayerWallet, chainBRelayerWallet, err = s.GetRelayerWallets(relayer) + s.Require().NoError(err) + + relayerAStartingBalance, err = s.GetChainANativeBalance(ctx, chainARelayerWallet) + s.Require().NoError(err) + t.Logf("relayer A user starting with balance: %d", relayerAStartingBalance) + }) + + t.Run("register and verify counterparty payee", func(t *testing.T) { + _, chainBRelayerUser := s.GetRelayerUsers(ctx) + resp := s.RegisterCounterPartyPayee(ctx, chainB, chainBRelayerUser, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, chainBRelayerWallet.FormattedAddress(), chainARelayerWallet.FormattedAddress()) + s.AssertTxSuccess(resp) + + address, err := query.CounterPartyPayee(ctx, chainB, chainBRelayerWallet.FormattedAddress(), channelA.Counterparty.ChannelID) + s.Require().NoError(err) + s.Require().Equal(chainARelayerWallet.FormattedAddress(), address) + }) + + // send the native chainA denom and also the ibc token from chainB + denoms := []string{chainAIBCToken.IBCDenom(), chainADenom} + var transferCoins []sdk.Coin + for _, denom := range denoms { + transferCoins = append(transferCoins, testvalues.DefaultTransferAmount(denom)) + } + + t.Run("send incentivized transfer packet to chain B with native token from chain A and non-native IBC token from chainB", func(t *testing.T) { + // before adding fees for the packet, there should not be incentivized packets + packets, err := query.IncentivizedPacketsForChannel(ctx, chainA, channelA.PortID, channelA.ChannelID) + s.Require().NoError(err) + s.Require().Empty(packets) + + msgPayPacketFee := feetypes.NewMsgPayPacketFee(testFee, channelA.PortID, channelA.ChannelID, chainAWallet.FormattedAddress(), nil) + msgTransfer := testsuite.GetMsgTransfer( + channelA.PortID, + channelA.ChannelID, + transfertypes.V2, + transferCoins, + chainAWallet.FormattedAddress(), + chainBWallet.FormattedAddress(), + s.GetTimeoutHeight(ctx, chainB), + 0, + "", + ) + resp := s.BroadcastMessages(ctx, chainA, chainAWallet, msgPayPacketFee, msgTransfer) + s.AssertTxSuccess(resp) + }) + + t.Run("packets are relayed", func(t *testing.T) { + s.AssertPacketRelayed(ctx, chainA, channelA.PortID, channelA.ChannelID, 1) + + t.Run("chain B native denom", func(t *testing.T) { + actualBalance, err := s.GetChainBNativeBalance(ctx, chainBWallet) + s.Require().NoError(err) + + expected := testvalues.StartingTokenAmount + s.Require().Equal(expected, actualBalance) + }) + + t.Run("chain A IBC denom", func(t *testing.T) { + actualBalance, err := query.Balance(ctx, chainB, chainBAddress, chainBIBCToken.IBCDenom()) + s.Require().NoError(err) + + expected := testvalues.IBCTransferAmount + s.Require().Equal(expected, actualBalance.Int64()) + }) + }) + + t.Run("timeout fee is refunded", func(t *testing.T) { + actualBalance, err := s.GetChainANativeBalance(ctx, chainAWallet) + s.Require().NoError(err) + + // once the relayer has relayed the packets, the timeout fee should be refunded. + expected := testvalues.StartingTokenAmount - testvalues.IBCTransferAmount - testFee.AckFee.AmountOf(chainADenom).Int64() - testFee.RecvFee.AmountOf(chainADenom).Int64() + s.Require().Equal(expected, actualBalance) + }) + + t.Run("relayerA is paid ack and recv fee", func(t *testing.T) { + actualBalance, err := s.GetChainANativeBalance(ctx, chainARelayerWallet) + s.Require().NoError(err) + + expected := relayerAStartingBalance + testFee.AckFee.AmountOf(chainADenom).Int64() + testFee.RecvFee.AmountOf(chainADenom).Int64() + s.Require().Equal(expected, actualBalance) + }) + + t.Run("tokens are un-escrowed", func(t *testing.T) { + actualTotalEscrow, err := query.TotalEscrowForDenom(ctx, chainB, chainADenom) + s.Require().NoError(err) + s.Require().Equal(sdk.NewCoin(chainADenom, sdkmath.NewInt(0)), actualTotalEscrow) // total escrow is zero because tokens have come back + }) +} diff --git a/e2e/tests/transfer/upgrades_test.go b/e2e/tests/transfer/upgradesv2_test.go similarity index 58% rename from e2e/tests/transfer/upgrades_test.go rename to e2e/tests/transfer/upgradesv2_test.go index c458e71cf96..b35d38d5dba 100644 --- a/e2e/tests/transfer/upgrades_test.go +++ b/e2e/tests/transfer/upgradesv2_test.go @@ -31,12 +31,16 @@ type TransferChannelUpgradesTestSuite struct { testsuite.E2ETestSuite } +func (s *TransferChannelUpgradesTestSuite) SetupTest() { + s.SetupPath(ibc.DefaultClientOpts(), s.TransferChannelOptions()) +} + // TestChannelUpgrade_WithFeeMiddleware_Succeeds tests upgrading a transfer channel to wire up fee middleware func (s *TransferChannelUpgradesTestSuite) TestChannelUpgrade_WithFeeMiddleware_Succeeds() { t := s.T() ctx := context.TODO() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, s.TransferChannelOptions()) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() channelB := channelA.Counterparty @@ -248,337 +252,12 @@ func (s *TransferChannelUpgradesTestSuite) TestChannelUpgrade_WithFeeMiddleware_ }) } -// TestChannelUpgrade_WithICS20v2_Succeeds tests upgrading a transfer channel to ICS20 v2. -func (s *TransferChannelUpgradesTestSuite) TestChannelUpgrade_WithICS20v2_Succeeds() { - t := s.T() - ctx := context.TODO() - - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, func(opts *ibc.CreateChannelOptions) { - opts.Version = transfertypes.V1 - }) - - channelB := channelA.Counterparty - chainA, chainB := s.GetChains() - - chainADenom := chainA.Config().Denom - chainBDenom := chainB.Config().Denom - chainAIBCToken := testsuite.GetIBCToken(chainBDenom, channelA.PortID, channelA.ChannelID) - chainBIBCToken := testsuite.GetIBCToken(chainADenom, channelB.PortID, channelB.ChannelID) - - chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) - chainAAddress := chainAWallet.FormattedAddress() - - chainBWallet := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) - chainBAddress := chainBWallet.FormattedAddress() - - s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA, chainB), "failed to wait for blocks") - - t.Run("verify transfer version of channel A is ics20-1", func(t *testing.T) { - channel, err := query.Channel(ctx, chainA, channelA.PortID, channelA.ChannelID) - s.Require().NoError(err) - s.Require().Equal(transfertypes.V1, channel.Version, "the channel version is not ics20-1") - }) - - t.Run("native token transfer from chainA to chainB, sender is source of tokens", func(t *testing.T) { - chainBWalletAmount := ibc.WalletAmount{ - Address: chainBWallet.FormattedAddress(), // destination address - Denom: chainA.Config().Denom, - Amount: sdkmath.NewInt(testvalues.IBCTransferAmount), - } - - transferTxResp, err := chainA.SendIBCTransfer(ctx, channelA.ChannelID, chainAWallet.KeyName(), chainBWalletAmount, ibc.TransferOptions{}) - s.Require().NoError(err) - s.Require().NoError(transferTxResp.Validate(), "chain-a ibc transfer tx is invalid") - }) - - s.Require().NoError(test.WaitForBlocks(ctx, 5, chainA, chainB), "failed to wait for blocks") - - t.Run("tokens are escrowed", func(t *testing.T) { - actualBalance, err := s.GetChainANativeBalance(ctx, chainAWallet) - s.Require().NoError(err) - - expected := testvalues.StartingTokenAmount - testvalues.IBCTransferAmount - s.Require().Equal(expected, actualBalance) - - actualTotalEscrow, err := query.TotalEscrowForDenom(ctx, chainA, chainADenom) - s.Require().NoError(err) - - expectedTotalEscrow := sdk.NewCoin(chainADenom, sdkmath.NewInt(testvalues.IBCTransferAmount)) - s.Require().Equal(expectedTotalEscrow, actualTotalEscrow) - }) - - t.Run("start relayer", func(t *testing.T) { - s.StartRelayer(relayer) - }) - - t.Run("packets are relayed", func(t *testing.T) { - s.AssertPacketRelayed(ctx, chainA, channelA.PortID, channelA.ChannelID, 1) - - actualBalance, err := query.Balance(ctx, chainB, chainBAddress, chainBIBCToken.IBCDenom()) - s.Require().NoError(err) - - expected := testvalues.IBCTransferAmount - s.Require().Equal(expected, actualBalance.Int64()) - }) - - t.Run("execute gov proposal to initiate channel upgrade", func(t *testing.T) { - chA, err := query.Channel(ctx, chainA, channelA.PortID, channelA.ChannelID) - s.Require().NoError(err) - - upgradeFields := channeltypes.NewUpgradeFields(chA.Ordering, chA.ConnectionHops, transfertypes.V2) - s.InitiateChannelUpgrade(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, upgradeFields) - }) - - s.Require().NoError(test.WaitForBlocks(ctx, 10, chainA, chainB), "failed to wait for blocks") - - t.Run("verify channel A upgraded and transfer version is ics20-2", func(t *testing.T) { - channel, err := query.Channel(ctx, chainA, channelA.PortID, channelA.ChannelID) - s.Require().NoError(err) - s.Require().Equal(transfertypes.V2, channel.Version, "the channel version is not ics20-2") - }) - - t.Run("verify channel B upgraded and transfer version is ics20-2", func(t *testing.T) { - channel, err := query.Channel(ctx, chainB, channelB.PortID, channelB.ChannelID) - s.Require().NoError(err) - s.Require().Equal(transfertypes.V2, channel.Version, "the channel version is not ics20-2") - }) - - // send the native chainB denom and also the ibc token from chainA - transferCoins := []sdk.Coin{ - testvalues.DefaultTransferAmount(chainBIBCToken.IBCDenom()), - testvalues.DefaultTransferAmount(chainBDenom), - } - - t.Run("native token from chain B and non-native IBC token from chainA, both to chainA", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainB, chainBWallet, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, transferCoins, chainBAddress, chainAAddress, s.GetTimeoutHeight(ctx, chainA), 0, "") - s.AssertTxSuccess(transferTxResp) - }) - - s.Require().NoError(test.WaitForBlocks(ctx, 5, chainA, chainB), "failed to wait for blocks") - - t.Run("packets are relayed", func(t *testing.T) { - s.AssertPacketRelayed(ctx, chainB, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, 1) - - t.Run("chain A native denom", func(t *testing.T) { - actualBalance, err := s.GetChainANativeBalance(ctx, chainAWallet) - s.Require().NoError(err) - - expected := testvalues.StartingTokenAmount - s.Require().Equal(expected, actualBalance) - }) - - t.Run("chain B IBC denom", func(t *testing.T) { - actualBalance, err := query.Balance(ctx, chainA, chainAAddress, chainAIBCToken.IBCDenom()) - s.Require().NoError(err) - - expected := testvalues.IBCTransferAmount - s.Require().Equal(expected, actualBalance.Int64()) - }) - }) - - t.Run("tokens are un-escrowed", func(t *testing.T) { - t.Run("chain A escrow", func(t *testing.T) { - actualTotalEscrow, err := query.TotalEscrowForDenom(ctx, chainA, chainADenom) - s.Require().NoError(err) - s.Require().Equal(sdk.NewCoin(chainADenom, sdkmath.NewInt(0)), actualTotalEscrow) // total escrow is zero because tokens have come back - }) - - t.Run("chain B escrow", func(t *testing.T) { - actualTotalEscrow, err := query.TotalEscrowForDenom(ctx, chainB, chainBDenom) - s.Require().NoError(err) - s.Require().Equal(sdk.NewCoin(chainBDenom, sdkmath.NewInt(testvalues.IBCTransferAmount)), actualTotalEscrow) - }) - }) -} - -// TestChannelUpgrade_WithFeeMiddlewareAndICS20v2_Succeeds tests upgrading a transfer channel to wire up fee middleware and upgrade to ICS20 v2. -func (s *TransferChannelUpgradesTestSuite) TestChannelUpgrade_WithFeeMiddlewareAndICS20v2_Succeeds() { - t := s.T() - ctx := context.TODO() - - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, func(opts *ibc.CreateChannelOptions) { - opts.Version = transfertypes.V1 - opts.SourcePortName = transfertypes.PortID - opts.DestPortName = transfertypes.PortID - }) - - channelB := channelA.Counterparty - chainA, chainB := s.GetChains() - - chainADenom := chainA.Config().Denom - chainBDenom := chainB.Config().Denom - chainAIBCToken := testsuite.GetIBCToken(chainBDenom, channelA.PortID, channelA.ChannelID) - chainBIBCToken := testsuite.GetIBCToken(chainADenom, channelB.PortID, channelB.ChannelID) - - chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) - chainBWallet := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) - chainBAddress := chainBWallet.FormattedAddress() - - s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA, chainB), "failed to wait for blocks") - - var ( - err error - channel channeltypes.Channel - ) - - t.Run("verify transfer version of channel A is ics20-1", func(t *testing.T) { - channel, err = query.Channel(ctx, chainA, channelA.PortID, channelA.ChannelID) - s.Require().NoError(err) - s.Require().Equal(transfertypes.V1, channel.Version, "the channel version is not ics20-1") - }) - - t.Run("native token transfer from chainB to chainA, sender is source of tokens", func(t *testing.T) { - chainAwalletAmount := ibc.WalletAmount{ - Address: chainAWallet.FormattedAddress(), // destination address - Denom: chainBDenom, - Amount: sdkmath.NewInt(testvalues.IBCTransferAmount), - } - - transferTxResp, err := chainB.SendIBCTransfer(ctx, channelB.ChannelID, chainBWallet.KeyName(), chainAwalletAmount, ibc.TransferOptions{}) - s.Require().NoError(err) - s.Require().NoError(transferTxResp.Validate(), "chain-b ibc transfer tx is invalid") - }) - - t.Run("start relayer", func(t *testing.T) { - s.StartRelayer(relayer) - }) - - t.Run("execute gov proposal to initiate channel upgrade", func(t *testing.T) { - channel.Version = transfertypes.V2 // change version to ics20-2 - s.InitiateChannelUpgrade(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, s.CreateUpgradeFields(channel)) - }) - - s.Require().NoError(test.WaitForBlocks(ctx, 10, chainA, chainB), "failed to wait for blocks") - - t.Run("verify channel A upgraded and channel version is {ics29-1,ics20-2}", func(t *testing.T) { - channel, err = query.Channel(ctx, chainA, channelA.PortID, channelA.ChannelID) - s.Require().NoError(err) - - // check the channel version include the fee version - version, err := feetypes.MetadataFromVersion(channel.Version) - s.Require().NoError(err) - s.Require().Equal(feetypes.Version, version.FeeVersion, "the channel version did not include ics29") - s.Require().Equal(transfertypes.V2, version.AppVersion, "the channel version is not ics20-2") - }) - - t.Run("verify channel B upgraded and channel version is {ics29-1,ics20-2}", func(t *testing.T) { - channel, err = query.Channel(ctx, chainB, channelB.PortID, channelB.ChannelID) - s.Require().NoError(err) - - // check the channel version include the fee version - version, err := feetypes.MetadataFromVersion(channel.Version) - s.Require().NoError(err) - s.Require().Equal(feetypes.Version, version.FeeVersion, "the channel version did not include ics29") - s.Require().Equal(transfertypes.V2, version.AppVersion, "the channel version is not ics20-2") - }) - - var ( - chainARelayerWallet, chainBRelayerWallet ibc.Wallet - relayerAStartingBalance int64 - testFee = testvalues.DefaultFee(chainADenom) - ) - - t.Run("recover relayer wallets", func(t *testing.T) { - err := s.RecoverRelayerWallets(ctx, relayer) - s.Require().NoError(err) - - chainARelayerWallet, chainBRelayerWallet, err = s.GetRelayerWallets(relayer) - s.Require().NoError(err) - - relayerAStartingBalance, err = s.GetChainANativeBalance(ctx, chainARelayerWallet) - s.Require().NoError(err) - t.Logf("relayer A user starting with balance: %d", relayerAStartingBalance) - }) - - t.Run("register and verify counterparty payee", func(t *testing.T) { - _, chainBRelayerUser := s.GetRelayerUsers(ctx) - resp := s.RegisterCounterPartyPayee(ctx, chainB, chainBRelayerUser, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, chainBRelayerWallet.FormattedAddress(), chainARelayerWallet.FormattedAddress()) - s.AssertTxSuccess(resp) - - address, err := query.CounterPartyPayee(ctx, chainB, chainBRelayerWallet.FormattedAddress(), channelA.Counterparty.ChannelID) - s.Require().NoError(err) - s.Require().Equal(chainARelayerWallet.FormattedAddress(), address) - }) - - // send the native chainA denom and also the ibc token from chainB - denoms := []string{chainAIBCToken.IBCDenom(), chainADenom} - var transferCoins []sdk.Coin - for _, denom := range denoms { - transferCoins = append(transferCoins, testvalues.DefaultTransferAmount(denom)) - } - - t.Run("send incentivized transfer packet to chain B with native token from chain A and non-native IBC token from chainB", func(t *testing.T) { - // before adding fees for the packet, there should not be incentivized packets - packets, err := query.IncentivizedPacketsForChannel(ctx, chainA, channelA.PortID, channelA.ChannelID) - s.Require().NoError(err) - s.Require().Empty(packets) - - msgPayPacketFee := feetypes.NewMsgPayPacketFee(testFee, channelA.PortID, channelA.ChannelID, chainAWallet.FormattedAddress(), nil) - msgTransfer := testsuite.GetMsgTransfer( - channelA.PortID, - channelA.ChannelID, - transfertypes.V2, - transferCoins, - chainAWallet.FormattedAddress(), - chainBWallet.FormattedAddress(), - s.GetTimeoutHeight(ctx, chainB), - 0, - "", - ) - resp := s.BroadcastMessages(ctx, chainA, chainAWallet, msgPayPacketFee, msgTransfer) - s.AssertTxSuccess(resp) - }) - - t.Run("packets are relayed", func(t *testing.T) { - s.AssertPacketRelayed(ctx, chainA, channelA.PortID, channelA.ChannelID, 1) - - t.Run("chain B native denom", func(t *testing.T) { - actualBalance, err := s.GetChainBNativeBalance(ctx, chainBWallet) - s.Require().NoError(err) - - expected := testvalues.StartingTokenAmount - s.Require().Equal(expected, actualBalance) - }) - - t.Run("chain A IBC denom", func(t *testing.T) { - actualBalance, err := query.Balance(ctx, chainB, chainBAddress, chainBIBCToken.IBCDenom()) - s.Require().NoError(err) - - expected := testvalues.IBCTransferAmount - s.Require().Equal(expected, actualBalance.Int64()) - }) - }) - - t.Run("timeout fee is refunded", func(t *testing.T) { - actualBalance, err := s.GetChainANativeBalance(ctx, chainAWallet) - s.Require().NoError(err) - - // once the relayer has relayed the packets, the timeout fee should be refunded. - expected := testvalues.StartingTokenAmount - testvalues.IBCTransferAmount - testFee.AckFee.AmountOf(chainADenom).Int64() - testFee.RecvFee.AmountOf(chainADenom).Int64() - s.Require().Equal(expected, actualBalance) - }) - - t.Run("relayerA is paid ack and recv fee", func(t *testing.T) { - actualBalance, err := s.GetChainANativeBalance(ctx, chainARelayerWallet) - s.Require().NoError(err) - - expected := relayerAStartingBalance + testFee.AckFee.AmountOf(chainADenom).Int64() + testFee.RecvFee.AmountOf(chainADenom).Int64() - s.Require().Equal(expected, actualBalance) - }) - - t.Run("tokens are un-escrowed", func(t *testing.T) { - actualTotalEscrow, err := query.TotalEscrowForDenom(ctx, chainB, chainADenom) - s.Require().NoError(err) - s.Require().Equal(sdk.NewCoin(chainADenom, sdkmath.NewInt(0)), actualTotalEscrow) // total escrow is zero because tokens have come back - }) -} - // TestChannelDowngrade_WithICS20v1_Succeeds tests downgrading a transfer channel from ICS20 v2 to ICS20 v1. func (s *TransferChannelUpgradesTestSuite) TestChannelDowngrade_WithICS20v1_Succeeds() { t := s.T() ctx := context.TODO() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, s.TransferChannelOptions()) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() channelB := channelA.Counterparty chainA, chainB := s.GetChains() @@ -670,7 +349,7 @@ func (s *TransferChannelUpgradesTestSuite) TestChannelUpgrade_WithFeeMiddleware_ t := s.T() ctx := context.TODO() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, s.TransferChannelOptions()) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() channelB := channelA.Counterparty @@ -760,7 +439,7 @@ func (s *TransferChannelUpgradesTestSuite) TestChannelUpgrade_WithFeeMiddleware_ t := s.T() ctx := context.TODO() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, s.TransferChannelOptions()) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() chainA, chainB := s.GetChains() channelB := channelA.Counterparty diff --git a/e2e/tests/upgrades/genesis_test.go b/e2e/tests/upgrades/genesis_test.go index e8f606df85f..c5c8a154168 100644 --- a/e2e/tests/upgrades/genesis_test.go +++ b/e2e/tests/upgrades/genesis_test.go @@ -53,7 +53,7 @@ func (s *GenesisTestSuite) TestIBCGenesis() { chainA, chainB := s.GetChains(chainOpts) ctx := context.Background() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, nil) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() var ( chainADenom = chainA.Config().Denom chainBIBCToken = testsuite.GetIBCToken(chainADenom, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID) // IBC token sent to chainB diff --git a/e2e/tests/upgrades/upgrade_test.go b/e2e/tests/upgrades/upgrade_test.go index 942a11d18ca..0e6b7ad56aa 100644 --- a/e2e/tests/upgrades/upgrade_test.go +++ b/e2e/tests/upgrades/upgrade_test.go @@ -5,6 +5,7 @@ package upgrades import ( "context" "fmt" + "strings" "sync" "testing" "time" @@ -55,6 +56,15 @@ type UpgradeTestSuite struct { testsuite.E2ETestSuite } +func (s *UpgradeTestSuite) SetupTest() { + channelOpts := s.TransferChannelOptions() + // TODO(chatton) hack to handle special case for the v8 to v8.1 upgrade test. + if strings.HasSuffix(s.T().Name(), "TestV8ToV8_1ChainUpgrade") { + channelOpts = s.FeeTransferChannelOptions() + } + s.SetupPath(ibc.DefaultClientOpts(), channelOpts) +} + // UpgradeChain upgrades a chain to a specific version using the planName provided. // The software upgrade proposal is broadcast by the provided wallet. func (s *UpgradeTestSuite) UpgradeChain(ctx context.Context, chain *cosmos.CosmosChain, wallet ibc.Wallet, planName, currentVersion, upgradeVersion string) { @@ -119,7 +129,7 @@ func (s *UpgradeTestSuite) TestIBCChainUpgrade() { testCfg := testsuite.LoadConfig() ctx := context.Background() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, nil) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() chainA, chainB := s.GetChains() var ( @@ -223,7 +233,9 @@ func (s *UpgradeTestSuite) TestChainUpgrade() { t := s.T() ctx := context.Background() - chain := s.SetupSingleChain(ctx) + + // TODO(chatton): this test is still creating a relayer and a channel, but it is not using them. + chain := s.GetAllChains()[0] userWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) userWalletAddr := userWallet.FormattedAddress() @@ -282,7 +294,7 @@ func (s *UpgradeTestSuite) TestV6ToV7ChainUpgrade() { testCfg := testsuite.LoadConfig() ctx := context.Background() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, nil) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() chainA, chainB := s.GetChains() var ( @@ -436,7 +448,7 @@ func (s *UpgradeTestSuite) TestV7ToV7_1ChainUpgrade() { testCfg := testsuite.LoadConfig() ctx := context.Background() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, nil) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() chainA, chainB := s.GetChains() chainADenom := chainA.Config().Denom @@ -527,7 +539,7 @@ func (s *UpgradeTestSuite) TestV7ToV8ChainUpgrade() { testCfg := testsuite.LoadConfig() ctx := context.Background() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, nil) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() chainA, chainB := s.GetChains() chainADenom := chainA.Config().Denom @@ -620,7 +632,7 @@ func (s *UpgradeTestSuite) TestV8ToV8_1ChainUpgrade() { t := s.T() ctx := context.Background() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, s.FeeMiddlewareChannelOptions()) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() chainA, chainB := s.GetChains() chainADenom := chainA.Config().Denom @@ -747,7 +759,7 @@ func (s *UpgradeTestSuite) TestV8ToV8_1ChainUpgrade_ChannelUpgrades() { testCfg := testsuite.LoadConfig() ctx := context.Background() - relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, s.TransferChannelOptions()) + relayer, channelA := s.GetRelayer(), s.GetChainAChannel() channelB := channelA.Counterparty chainA, chainB := s.GetChains() diff --git a/e2e/tests/wasm/grandpa_test.go b/e2e/tests/wasm/grandpa_test.go index 63488f79d79..a9f8447c617 100644 --- a/e2e/tests/wasm/grandpa_test.go +++ b/e2e/tests/wasm/grandpa_test.go @@ -64,6 +64,61 @@ type GrandpaTestSuite struct { testsuite.E2ETestSuite } +func (s *GrandpaTestSuite) SetupSuite() { + s.SetupChains(context.Background(), nil, func(options *testsuite.ChainOptions) { + // configure chain A (polkadot) + options.ChainSpecs[0].ChainName = composable + options.ChainSpecs[0].Type = "polkadot" + options.ChainSpecs[0].ChainID = "rococo-local" + options.ChainSpecs[0].Name = "composable" + options.ChainSpecs[0].Images = []ibc.DockerImage{ + // TODO: https://github.com/cosmos/ibc-go/issues/4965 + { + Repository: "ghcr.io/misko9/polkadot-node", + Version: "v39", + UidGid: "1000:1000", + }, + { + Repository: "ghcr.io/misko9/parachain-node", + Version: "20231122v39", + UidGid: "1000:1000", + }, + } + options.ChainSpecs[0].Bin = "polkadot" + options.ChainSpecs[0].Bech32Prefix = composable + options.ChainSpecs[0].Denom = "uDOT" + options.ChainSpecs[0].GasPrices = "" + options.ChainSpecs[0].GasAdjustment = 0 + options.ChainSpecs[0].TrustingPeriod = "" + options.ChainSpecs[0].CoinType = "354" + + // these values are set by default for our cosmos chains, we need to explicitly remove them here. + options.ChainSpecs[0].ModifyGenesis = nil + options.ChainSpecs[0].ConfigFileOverrides = nil + options.ChainSpecs[0].EncodingConfig = nil + + // configure chain B (cosmos) + options.ChainSpecs[1].ChainName = simd // Set chain name so that a suffix with a "dash" is not appended (required for hyperspace) + options.ChainSpecs[1].Type = "cosmos" + options.ChainSpecs[1].Name = "simd" + options.ChainSpecs[1].ChainID = simd + options.ChainSpecs[1].Bin = simd + options.ChainSpecs[1].Bech32Prefix = "cosmos" + + // TODO: hyperspace relayer assumes a denom of "stake", hard code this here right now. + // https://github.com/cosmos/ibc-go/issues/4964 + options.ChainSpecs[1].Denom = "stake" + options.ChainSpecs[1].GasPrices = "0.00stake" + options.ChainSpecs[1].GasAdjustment = 1 + options.ChainSpecs[1].TrustingPeriod = "504h" + options.ChainSpecs[1].CoinType = "118" + + options.ChainSpecs[1].ChainConfig.NoHostMount = false + options.ChainSpecs[1].ConfigFileOverrides = getConfigOverrides() + options.ChainSpecs[1].EncodingConfig = testsuite.SDKEncodingConfig() + }) +} + // TestMsgTransfer_Succeeds_GrandpaContract features // * sets up a Polkadot parachain // * sets up a Cosmos chain @@ -77,7 +132,7 @@ func (s *GrandpaTestSuite) TestMsgTransfer_Succeeds_GrandpaContract() { ctx := context.Background() t := s.T() - chainA, chainB := s.GetGrandpaTestChains() + chainA, chainB := s.GetChains() polkadotChain, ok := chainA.(*polkadot.PolkadotChain) s.Require().True(ok) @@ -122,7 +177,7 @@ func (s *GrandpaTestSuite) TestMsgTransfer_Succeeds_GrandpaContract() { Amount: sdkmath.NewInt(amountToSend), } - pathName := s.GetPathName(0) + pathName := testsuite.GetPathName(0) err = r.GeneratePath(ctx, eRep, cosmosChain.Config().ChainID, polkadotChain.Config().ChainID, pathName) s.Require().NoError(err) @@ -230,7 +285,7 @@ func (s *GrandpaTestSuite) TestMsgTransfer_TimesOut_GrandpaContract() { ctx := context.Background() t := s.T() - chainA, chainB := s.GetGrandpaTestChains() + chainA, chainB := s.GetChains() polkadotChain, ok := chainA.(*polkadot.PolkadotChain) s.Require().True(ok) @@ -275,7 +330,7 @@ func (s *GrandpaTestSuite) TestMsgTransfer_TimesOut_GrandpaContract() { Amount: sdkmath.NewInt(amountToSend), } - pathName := s.GetPathName(0) + pathName := testsuite.GetPathName(0) err = r.GeneratePath(ctx, eRep, cosmosChain.Config().ChainID, polkadotChain.Config().ChainID, pathName) s.Require().NoError(err) @@ -317,7 +372,7 @@ func (s *GrandpaTestSuite) TestMsgTransfer_TimesOut_GrandpaContract() { s.Require().Equal(expected, actualBalance.Int64()) // start relayer - s.Require().NoError(r.StartRelayer(ctx, s.GetRelayerExecReporter(), s.GetPathName(0))) + s.Require().NoError(r.StartRelayer(ctx, s.GetRelayerExecReporter(), testsuite.GetPathName(0))) err = testutil.WaitForBlocks(ctx, 15, polkadotChain, cosmosChain) s.Require().NoError(err) @@ -345,7 +400,7 @@ func (s *GrandpaTestSuite) TestMsgTransfer_TimesOut_GrandpaContract() { func (s *GrandpaTestSuite) TestMsgMigrateContract_Success_GrandpaContract() { ctx := context.Background() - chainA, chainB := s.GetGrandpaTestChains() + chainA, chainB := s.GetChains() polkadotChain, ok := chainA.(*polkadot.PolkadotChain) s.Require().True(ok) @@ -377,7 +432,7 @@ func (s *GrandpaTestSuite) TestMsgMigrateContract_Success_GrandpaContract() { err = testutil.WaitForBlocks(ctx, 1, polkadotChain) s.Require().NoError(err, "polkadot chain failed to make blocks") - pathName := s.GetPathName(0) + pathName := testsuite.GetPathName(0) err = r.GeneratePath(ctx, eRep, cosmosChain.Config().ChainID, polkadotChain.Config().ChainID, pathName) s.Require().NoError(err) @@ -433,7 +488,7 @@ func (s *GrandpaTestSuite) TestMsgMigrateContract_Success_GrandpaContract() { func (s *GrandpaTestSuite) TestMsgMigrateContract_ContractError_GrandpaContract() { ctx := context.Background() - chainA, chainB := s.GetGrandpaTestChains() + chainA, chainB := s.GetChains() polkadotChain, ok := chainA.(*polkadot.PolkadotChain) s.Require().True(ok) @@ -464,7 +519,7 @@ func (s *GrandpaTestSuite) TestMsgMigrateContract_ContractError_GrandpaContract( err = testutil.WaitForBlocks(ctx, 1, polkadotChain) s.Require().NoError(err, "polkadot chain failed to make blocks") - pathName := s.GetPathName(0) + pathName := testsuite.GetPathName(0) err = r.GeneratePath(ctx, eRep, cosmosChain.Config().ChainID, polkadotChain.Config().ChainID, pathName) s.Require().NoError(err) @@ -526,7 +581,7 @@ func (s *GrandpaTestSuite) TestRecoverClient_Succeeds_GrandpaContract() { // the contract uses 1600s as the unbonding period with the trusting period evaluating to (unbonding period / 3) modifiedTrustingPeriod := (1600 * time.Second) / 3 - chainA, chainB := s.GetGrandpaTestChains() + chainA, chainB := s.GetChains() polkadotChain, ok := chainA.(*polkadot.PolkadotChain) s.Require().True(ok) @@ -561,7 +616,7 @@ func (s *GrandpaTestSuite) TestRecoverClient_Succeeds_GrandpaContract() { fundAmount := int64(12_333_000_000_000) _, cosmosUser := s.fundUsers(ctx, fundAmount, polkadotChain, cosmosChain) - pathName := s.GetPathName(0) + pathName := testsuite.GetPathName(0) err = r.GeneratePath(ctx, eRep, cosmosChain.Config().ChainID, polkadotChain.Config().ChainID, pathName) s.Require().NoError(err) @@ -705,59 +760,3 @@ func getConfigOverrides() map[string]any { configFileOverrides["config/config.toml"] = configTomlOverrides return configFileOverrides } - -// GetGrandpaTestChains returns the configured chains for the grandpa test suite. -func (s *GrandpaTestSuite) GetGrandpaTestChains() (ibc.Chain, ibc.Chain) { - return s.GetChains(func(options *testsuite.ChainOptions) { - // configure chain A (polkadot) - options.ChainSpecs[0].ChainName = composable - options.ChainSpecs[0].Type = "polkadot" - options.ChainSpecs[0].ChainID = "rococo-local" - options.ChainSpecs[0].Name = "composable" - options.ChainSpecs[0].Images = []ibc.DockerImage{ - // TODO: https://github.com/cosmos/ibc-go/issues/4965 - { - Repository: "ghcr.io/misko9/polkadot-node", - Version: "v39", - UidGid: "1000:1000", - }, - { - Repository: "ghcr.io/misko9/parachain-node", - Version: "20231122v39", - UidGid: "1000:1000", - }, - } - options.ChainSpecs[0].Bin = "polkadot" - options.ChainSpecs[0].Bech32Prefix = composable - options.ChainSpecs[0].Denom = "uDOT" - options.ChainSpecs[0].GasPrices = "" - options.ChainSpecs[0].GasAdjustment = 0 - options.ChainSpecs[0].TrustingPeriod = "" - options.ChainSpecs[0].CoinType = "354" - - // these values are set by default for our cosmos chains, we need to explicitly remove them here. - options.ChainSpecs[0].ModifyGenesis = nil - options.ChainSpecs[0].ConfigFileOverrides = nil - options.ChainSpecs[0].EncodingConfig = nil - - // configure chain B (cosmos) - options.ChainSpecs[1].ChainName = simd // Set chain name so that a suffix with a "dash" is not appended (required for hyperspace) - options.ChainSpecs[1].Type = "cosmos" - options.ChainSpecs[1].Name = "simd" - options.ChainSpecs[1].ChainID = simd - options.ChainSpecs[1].Bin = simd - options.ChainSpecs[1].Bech32Prefix = "cosmos" - - // TODO: hyperspace relayer assumes a denom of "stake", hard code this here right now. - // https://github.com/cosmos/ibc-go/issues/4964 - options.ChainSpecs[1].Denom = "stake" - options.ChainSpecs[1].GasPrices = "0.00stake" - options.ChainSpecs[1].GasAdjustment = 1 - options.ChainSpecs[1].TrustingPeriod = "504h" - options.ChainSpecs[1].CoinType = "118" - - options.ChainSpecs[1].ChainConfig.NoHostMount = false - options.ChainSpecs[1].ConfigFileOverrides = getConfigOverrides() - options.ChainSpecs[1].EncodingConfig = testsuite.SDKEncodingConfig() - }) -} diff --git a/e2e/tests/wasm/upgrade_test.go b/e2e/tests/wasm/upgrade_test.go index 2b9442a73dc..3b683158d63 100644 --- a/e2e/tests/wasm/upgrade_test.go +++ b/e2e/tests/wasm/upgrade_test.go @@ -53,7 +53,8 @@ func (s *IBCWasmUpgradeTestSuite) TestIBCWasmChainUpgrade() { t := s.T() ctx := context.Background() - chain := s.SetupSingleChain(ctx) + // TODO(chatton): this test is still creating a relayer and a channel, but it is not using them. + chain := s.GetAllChains()[0] checksum := "" userWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) diff --git a/e2e/testsuite/diagnostics/diagnostics.go b/e2e/testsuite/diagnostics/diagnostics.go index 4b24a1cfc9f..6619b844979 100644 --- a/e2e/testsuite/diagnostics/diagnostics.go +++ b/e2e/testsuite/diagnostics/diagnostics.go @@ -23,7 +23,7 @@ const ( // Collect can be used in `t.Cleanup` and will copy all the of the container logs and relevant files // into e2e//.log. These log files will be uploaded to GH upon test failure. -func Collect(t *testing.T, dc *dockerclient.Client, debugModeEnabled bool, chainNames ...string) { +func Collect(t *testing.T, dc *dockerclient.Client, debugModeEnabled bool, suiteName string, chainNames ...string) { t.Helper() if !debugModeEnabled { @@ -50,7 +50,7 @@ func Collect(t *testing.T, dc *dockerclient.Client, debugModeEnabled bool, chain return } - testContainers, err := dockerutil.GetTestContainers(ctx, t, dc) + testContainers, err := dockerutil.GetTestContainers(ctx, suiteName, dc) if err != nil { t.Logf("failed listing containers during test cleanup: %s", err) return diff --git a/e2e/testsuite/testsuite.go b/e2e/testsuite/testsuite.go index 0924ce0f4b2..0b13387ffe1 100644 --- a/e2e/testsuite/testsuite.go +++ b/e2e/testsuite/testsuite.go @@ -48,20 +48,58 @@ type E2ETestSuite struct { testifysuite.Suite // proposalIDs keeps track of the active proposal ID for each chain. - proposalIDs map[string]uint64 - paths map[string][]ibc.Chain + proposalIDs map[string]uint64 + + // chains is a list of chains that are created for the test suite. + // each test suite has a single slice of chains that are used for all individual test + // cases. + chains []ibc.Chain relayers relayer.Map logger *zap.Logger DockerClient *dockerclient.Client network string startRelayerFn func(relayer ibc.Relayer) - // pathNameIndex is the latest index to be used for generating paths + // pathNameIndex is the latest index to be used for generating chains pathNameIndex int64 + + // TODO: refactor this to use a relayer per test + // relayer is a single relayer which only works when running tests one per host. + // this needs to be refactored to use a different relayer per test. + relayer ibc.Relayer + + // testSuiteName is the name of the test suite, used to store chains under the test suite name. + testSuiteName string + testPaths map[string][]string + channels map[string]map[ibc.Chain][]ibc.ChannelOutput } -func (s *E2ETestSuite) SetupTest() { - s.configureGenesisDebugExport() +// initState populates variables that are used across the test suite. +// note: this should be called only from SetupSuite. +func (s *E2ETestSuite) initState() { + s.initDockerClient() + s.proposalIDs = map[string]uint64{} + s.testPaths = make(map[string][]string) + s.channels = make(map[string]map[ibc.Chain][]ibc.ChannelOutput) + + // testSuiteName gets populated in the context of SetupSuite and stored as s.T().Name() + // will return the name of the suite and test when called from SetupTest or within the body of tests. + // the chains will be stored under the test suite name, so we need to store this for future use. + s.testSuiteName = s.T().Name() +} + +// initDockerClient creates a docker client and populates the network to be used for the test. +func (s *E2ETestSuite) initDockerClient() { + client, network := interchaintest.DockerSetup(s.T()) + s.logger = zap.NewExample() + s.DockerClient = client + s.network = network +} + +// SetupSuite will by default create chains with no additional options. If additional options are required, +// the test suite must define the SetupSuite function and provide the required options. +func (s *E2ETestSuite) SetupSuite() { + s.SetupChains(context.TODO(), nil) } // configureGenesisDebugExport sets, if needed, env variables to enable exporting of Genesis debug files. @@ -103,6 +141,111 @@ func (s *E2ETestSuite) configureGenesisDebugExport() { t.Setenv("EXPORT_GENESIS_CHAIN", genesisChainName) } +// SetupChains creates the chains for the test suite, and also a relayer that is wired up to establish +// connections and channels between the chains. +func (s *E2ETestSuite) SetupChains(ctx context.Context, channelOptionsModifier ChainOptionModifier, chainSpecOpts ...ChainOptionConfiguration) { + s.T().Logf("Setting up chains: %s", s.T().Name()) + s.initState() + s.configureGenesisDebugExport() + + chainOptions := DefaultChainOptions() + for _, opt := range chainSpecOpts { + opt(&chainOptions) + } + + s.chains = s.createChains(chainOptions) + + // TODO: we need to create a relayer for each test that will run + // having a single relayer for all tests will cause issues when running tests in parallel. + s.relayer = relayer.New(s.T(), *LoadConfig().GetActiveRelayerConfig(), s.logger, s.DockerClient, s.network) + ic := s.newInterchain(ctx, s.relayer, s.chains, channelOptionsModifier) + + buildOpts := interchaintest.InterchainBuildOptions{ + TestName: s.T().Name(), + Client: s.DockerClient, + NetworkID: s.network, + // we skip path creation because we are just creating the chains and not connections/channels + SkipPathCreation: true, + } + + s.Require().NoError(ic.Build(ctx, s.GetRelayerExecReporter(), buildOpts)) +} + +// SetupTest will by default use the default channel options to create a path between the chains. +// if non default channel options are required, the test suite must override the `SetupTest` function. +func (s *E2ETestSuite) SetupTest() { + s.SetupPath(ibc.DefaultClientOpts(), defaultChannelOpts(s.GetAllChains())) +} + +// SetupPath creates a path between the chains using the provided client and channel options. +func (s *E2ETestSuite) SetupPath(clientOpts ibc.CreateClientOptions, channelOpts ibc.CreateChannelOptions) { + s.T().Logf("Setting up path for: %s", s.T().Name()) + r := s.relayer + + ctx := context.TODO() + allChains := s.GetAllChains() + for i := 0; i < len(allChains)-1; i++ { + chainA, chainB := allChains[i], allChains[i+1] + pathName := s.generatePathName() + s.T().Logf("establishing path between %s and %s on path %s", chainA.Config().ChainID, chainB.Config().ChainID, pathName) + + err := r.GeneratePath(ctx, s.GetRelayerExecReporter(), chainA.Config().ChainID, chainB.Config().ChainID, pathName) + s.Require().NoError(err) + + // Create new clients + err = r.CreateClients(ctx, s.GetRelayerExecReporter(), pathName, clientOpts) + s.Require().NoError(err) + err = test.WaitForBlocks(ctx, 1, chainA, chainB) + s.Require().NoError(err) + + err = r.CreateConnections(ctx, s.GetRelayerExecReporter(), pathName) + s.Require().NoError(err) + err = test.WaitForBlocks(ctx, 1, chainA, chainB) + s.Require().NoError(err) + + err = r.CreateChannel(ctx, s.GetRelayerExecReporter(), pathName, channelOpts) + s.Require().NoError(err) + err = test.WaitForBlocks(ctx, 1, chainA, chainB) + s.Require().NoError(err) + + channelsA, err := r.GetChannels(ctx, s.GetRelayerExecReporter(), chainA.Config().ChainID) + s.Require().NoError(err) + + channelsB, err := r.GetChannels(ctx, s.GetRelayerExecReporter(), chainB.Config().ChainID) + s.Require().NoError(err) + + if s.channels[s.T().Name()] == nil { + s.channels[s.T().Name()] = make(map[ibc.Chain][]ibc.ChannelOutput) + } + + // keep track of channels associated with a given chain for access within the tests. + s.channels[s.T().Name()][chainA] = channelsA + s.channels[s.T().Name()][chainB] = channelsB + s.testPaths[s.T().Name()] = append(s.testPaths[s.T().Name()], pathName) + } +} + +// GetChainAChannel returns the ibc.ChannelOutput for the current test. +// this defaults to the first entry in the list, and will be what is needed in the case of +// a single channel test. +func (s *E2ETestSuite) GetChainAChannel() ibc.ChannelOutput { + chainA := s.GetAllChains()[0] + return s.GetChannels(chainA)[0] +} + +// GetChannels returns all channels for the current test. +func (s *E2ETestSuite) GetChannels(chain ibc.Chain) []ibc.ChannelOutput { + channels, ok := s.channels[s.T().Name()][chain] + s.Require().True(ok, "channel not found for test %s", s.T().Name()) + return channels +} + +// GetRelayer returns the relayer to be used in the specific test. +// TODO: for now a single instance is still used, preventing parallel test runs. +func (s *E2ETestSuite) GetRelayer() ibc.Relayer { + return s.relayer +} + // GetRelayerUsers returns two ibc.Wallet instances which can be used for the relayer users // on the two chains. func (s *E2ETestSuite) GetRelayerUsers(ctx context.Context, chainOpts ...ChainOptionConfiguration) (ibc.Wallet, ibc.Wallet) { @@ -126,62 +269,48 @@ func (s *E2ETestSuite) GetRelayerUsers(ctx context.Context, chainOpts ...ChainOp return chainARelayerUser, chainBRelayerUser } -// SetupChainsRelayerAndChannel create two chains, a relayer, establishes a connection and creates a channel -// using the given channel options. The relayer returned by this function has not yet started. It should be started -// with E2ETestSuite.StartRelayer if needed. -// This should be called at the start of every test, unless fine grained control is required. -func (s *E2ETestSuite) SetupChainsRelayerAndChannel(ctx context.Context, channelOpts func(*ibc.CreateChannelOptions), chainSpecOpts ...ChainOptionConfiguration) (ibc.Relayer, ibc.ChannelOutput) { - chains := s.GetAllChains(chainSpecOpts...) - - r := relayer.New(s.T(), *LoadConfig().GetActiveRelayerConfig(), s.logger, s.DockerClient, s.network) - - ic := s.newInterchain(ctx, r, chains, channelOpts) - - buildOpts := interchaintest.InterchainBuildOptions{ - TestName: s.T().Name(), - Client: s.DockerClient, - NetworkID: s.network, - } - - s.Require().NoError(ic.Build(ctx, s.GetRelayerExecReporter(), buildOpts)) - - chainAChannels, err := r.GetChannels(ctx, s.GetRelayerExecReporter(), chains[0].Config().ChainID) - s.Require().NoError(err) - return r, chainAChannels[len(chainAChannels)-1] -} +// ChainOptionModifier is a function which accepts 2 chains as inputs, and returns a channel creation modifier function +// in order to conditionally modify the channel options based on the chains being used. +type ChainOptionModifier func(chainA, chainB ibc.Chain) func(options *ibc.CreateChannelOptions) // newInterchain constructs a new interchain instance that creates channels between the chains. -func (s *E2ETestSuite) newInterchain(ctx context.Context, r ibc.Relayer, chains []ibc.Chain, channelOpts func(*ibc.CreateChannelOptions)) *interchaintest.Interchain { - channelOptions := defaultChannelOpts(chains) - if channelOpts != nil { - channelOpts(&channelOptions) - } - +func (s *E2ETestSuite) newInterchain(ctx context.Context, r ibc.Relayer, chains []ibc.Chain, modificationProvider ChainOptionModifier) *interchaintest.Interchain { ic := interchaintest.NewInterchain() for _, chain := range chains { ic.AddChain(chain) } ic.AddRelayer(r, "r") - var pathNames []string - // iterate through all chains, and create links such that there is a channel between // - chainA and chainB // - chainB and chainC // - chainC and chainD etc for i := 0; i < len(chains)-1; i++ { pathName := s.generatePathName() - pathNames = append(pathNames, pathName) + channelOpts := defaultChannelOpts(chains) + chain1, chain2 := chains[i], chains[i+1] + + if modificationProvider != nil { + // make a modification to the channel options based on the chains which are being used. + modificationFn := modificationProvider(chain1, chain2) + modificationFn(&channelOpts) + } + ic.AddLink(interchaintest.InterchainLink{ Chain1: chains[i], Chain2: chains[i+1], Relayer: r, Path: pathName, - CreateChannelOpts: channelOptions, + CreateChannelOpts: channelOpts, }) } s.startRelayerFn = func(relayer ibc.Relayer) { + // depending on the test, the path names will be different. + // whenever a relayer is started, it should use the paths associated with the test the relayer is running in. + pathNames, ok := s.testPaths[s.T().Name()] + s.Require().True(ok, "path names not found for test %s", s.T().Name()) + err := relayer.StartRelayer(ctx, s.GetRelayerExecReporter(), pathNames...) s.Require().NoError(err, fmt.Sprintf("failed to start relayer: %s", err)) @@ -242,38 +371,23 @@ func (s *E2ETestSuite) ConfigureRelayer(ctx context.Context, chainA, chainB ibc. return r } -// SetupSingleChain creates and returns a single CosmosChain for usage in e2e tests. -// This is useful for testing single chain functionality when performing coordinated upgrades as well as testing localhost ibc client functionality. -// TODO: Actually setup a single chain. Seeing panic: runtime error: index out of range [0] with length 0 when using a single chain. -// issue: https://github.com/strangelove-ventures/interchaintest/issues/401 -func (s *E2ETestSuite) SetupSingleChain(ctx context.Context) ibc.Chain { - chains := s.GetAllChains() - chainA, chainB := chains[0], chains[1] - - ic := interchaintest.NewInterchain().AddChain(chainA).AddChain(chainB) - - eRep := s.GetRelayerExecReporter() - s.Require().NoError(ic.Build(ctx, eRep, interchaintest.InterchainBuildOptions{ - TestName: s.T().Name(), - Client: s.DockerClient, - NetworkID: s.network, - SkipPathCreation: true, - })) - - return chainA -} - // generatePathName generates the path name using the test suites name func (s *E2ETestSuite) generatePathName() string { - pathName := s.GetPathName(s.pathNameIndex) + pathName := GetPathName(s.pathNameIndex) s.pathNameIndex++ return pathName } +func (s *E2ETestSuite) GetPaths() []string { + paths, ok := s.testPaths[s.T().Name()] + s.Require().True(ok, "paths not found for test %s", s.T().Name()) + return paths +} + // GetPathName returns the name of a path at a specific index. This can be used in tests // when the path name is required. -func (s *E2ETestSuite) GetPathName(idx int64) string { - pathName := fmt.Sprintf("%s-path-%d", s.T().Name(), idx) +func GetPathName(idx int64) string { + pathName := fmt.Sprintf("path-%d", idx) return strings.ReplaceAll(pathName, "/", "-") } @@ -317,31 +431,9 @@ func (s *E2ETestSuite) GetChains(chainOpts ...ChainOptionConfiguration) (ibc.Cha // GetAllChains returns all chains that can be used in a test. The chains returned // are unique to the current test being run. Note: this function does not create containers. func (s *E2ETestSuite) GetAllChains(chainOpts ...ChainOptionConfiguration) []ibc.Chain { - if s.paths == nil { - s.paths = map[string][]ibc.Chain{} - } - - if chains, ok := s.paths[s.T().Name()]; ok { - return chains - } - - chainOptions := DefaultChainOptions() - for _, opt := range chainOpts { - opt(&chainOptions) - } - - chains := s.createChains(chainOptions) - s.paths[s.T().Name()] = chains - - if s.proposalIDs == nil { - s.proposalIDs = map[string]uint64{} - } - - // initialise proposal ids for all chains. - for _, chain := range chains { - s.proposalIDs[chain.Config().ChainID] = 1 - } - + // chains are stored on a per test suite level + chains := s.chains + s.Require().NotEmpty(chains, "chains not found for test %s", s.testSuiteName) return chains } @@ -486,13 +578,7 @@ func (s *E2ETestSuite) AssertHumanReadableDenom(ctx context.Context, chain ibc.C // createChains creates two separate chains in docker containers. // test and can be retrieved with GetChains. func (s *E2ETestSuite) createChains(chainOptions ChainOptions) []ibc.Chain { - client, network := interchaintest.DockerSetup(s.T()) t := s.T() - - s.logger = zap.NewExample() - s.DockerClient = client - s.network = network - cf := interchaintest.NewBuiltinChainFactory(s.logger, chainOptions.ChainSpecs) // this is intentionally called after the interchaintest.DockerSetup function. The above function registers a @@ -504,12 +590,17 @@ func (s *E2ETestSuite) createChains(chainOptions ChainOptions) []ibc.Chain { for _, chain := range chainOptions.ChainSpecs { chainNames = append(chainNames, chain.Name) } - diagnostics.Collect(t, s.DockerClient, dumpLogs, chainNames...) + diagnostics.Collect(t, s.DockerClient, dumpLogs, s.testSuiteName, chainNames...) }) chains, err := cf.Chains(t.Name()) s.Require().NoError(err) + // initialise proposal ids for all chains. + for _, chain := range chains { + s.proposalIDs[chain.Config().ChainID] = 1 + } + return chains } @@ -521,48 +612,24 @@ func (s *E2ETestSuite) GetRelayerExecReporter() *testreporter.RelayerExecReporte } // TransferChannelOptions configures both of the chains to have non-incentivized transfer channels. -func (s *E2ETestSuite) TransferChannelOptions(chainOpts ...ChainOptionConfiguration) func(options *ibc.CreateChannelOptions) { - chainA, chainB := s.GetChains(chainOpts...) - chainAVersion := chainA.Config().Images[0].Version - chainBVersion := chainB.Config().Images[0].Version - - // select the transfer version based on the chain versions - transferVersion := transfertypes.V1 - if testvalues.ICS20v2FeatureReleases.IsSupported(chainAVersion) && testvalues.ICS20v2FeatureReleases.IsSupported(chainBVersion) { - transferVersion = transfertypes.V2 - } - - return func(opts *ibc.CreateChannelOptions) { - opts.Version = transferVersion - opts.SourcePortName = transfertypes.PortID - opts.DestPortName = transfertypes.PortID - } +func (s *E2ETestSuite) TransferChannelOptions() ibc.CreateChannelOptions { + opts := ibc.DefaultChannelOpts() + opts.Version = determineDefaultTransferVersion(s.GetAllChains()) + return opts } -// FeeMiddlewareChannelOptions configures both of the chains to have fee middleware enabled. -func (s *E2ETestSuite) FeeMiddlewareChannelOptions() func(options *ibc.CreateChannelOptions) { - chainA, chainB := s.GetChains() - chainAVersion := chainA.Config().Images[0].Version - chainBVersion := chainB.Config().Images[0].Version - - // select the transfer version based on the chain versions - transferVersion := transfertypes.V1 - if testvalues.ICS20v2FeatureReleases.IsSupported(chainAVersion) && testvalues.ICS20v2FeatureReleases.IsSupported(chainBVersion) { - transferVersion = transfertypes.V2 - } - +// FeeTransferChannelOptions configures both of the chains to have fee middleware enabled. +func (s *E2ETestSuite) FeeTransferChannelOptions() ibc.CreateChannelOptions { versionMetadata := feetypes.Metadata{ FeeVersion: feetypes.Version, - AppVersion: transferVersion, + AppVersion: determineDefaultTransferVersion(s.GetAllChains()), } versionBytes, err := feetypes.ModuleCdc.MarshalJSON(&versionMetadata) s.Require().NoError(err) - return func(opts *ibc.CreateChannelOptions) { - opts.Version = string(versionBytes) - opts.DestPortName = transfertypes.PortID - opts.SourcePortName = transfertypes.PortID - } + opts := ibc.DefaultChannelOpts() + opts.Version = string(versionBytes) + return opts } // GetTimeoutHeight returns a timeout height of 1000 blocks above the current block height. @@ -653,6 +720,11 @@ func GetMsgTransfer(portID, channelID, version string, tokens sdk.Coins, sender, return msg } +// SuiteName returns the name of the test suite. +func (s *E2ETestSuite) SuiteName() string { + return s.testSuiteName +} + // ThreeChainSetup provides the default behaviour to wire up 3 chains in the tests. func ThreeChainSetup() ChainOptionConfiguration { // copy all values of existing chains and tweak to make unique to new chain.