Skip to content

Commit 3b2ab6a

Browse files
chore: e2e for ICA reopening (#2720)
Co-authored-by: crodriguezvega <carlos@interchain.io>
1 parent cce91a1 commit 3b2ab6a

File tree

2 files changed

+208
-5
lines changed

2 files changed

+208
-5
lines changed

e2e/tests/interchain_accounts/base_test.go

Lines changed: 194 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"time"
77

88
ibctest "github.com/strangelove-ventures/ibctest/v6"
9+
"github.com/strangelove-ventures/ibctest/v6/chain/cosmos"
910
"github.com/strangelove-ventures/ibctest/v6/ibc"
1011
"github.com/strangelove-ventures/ibctest/v6/test"
1112
"github.com/stretchr/testify/suite"
@@ -21,6 +22,7 @@ import (
2122

2223
controllertypes "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts/controller/types"
2324
icatypes "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts/types"
25+
channeltypes "github.com/cosmos/ibc-go/v6/modules/core/04-channel/types"
2426
ibctesting "github.com/cosmos/ibc-go/v6/testing"
2527
)
2628

@@ -44,6 +46,13 @@ func getICAVersion(chainAVersion, chainBVersion string) string {
4446
return icatypes.NewDefaultMetadataString(ibctesting.FirstConnectionID, ibctesting.FirstConnectionID)
4547
}
4648

49+
// RegisterInterchainAccount will attempt to register an interchain account on the counterparty chain.
50+
func (s *InterchainAccountsTestSuite) RegisterInterchainAccount(ctx context.Context, chain *cosmos.CosmosChain, user *ibc.Wallet, msgRegisterAccount *controllertypes.MsgRegisterInterchainAccount) {
51+
txResp, err := s.BroadcastMessages(ctx, chain, user, msgRegisterAccount)
52+
s.Require().NoError(err)
53+
s.AssertValidTxResponse(txResp)
54+
}
55+
4756
func (s *InterchainAccountsTestSuite) TestMsgSendTx_SuccessfulTransfer() {
4857
t := s.T()
4958
ctx := context.TODO()
@@ -56,12 +65,13 @@ func (s *InterchainAccountsTestSuite) TestMsgSendTx_SuccessfulTransfer() {
5665
// setup 2 accounts: controller account on chain A, a second chain B account.
5766
// host account will be created when the ICA is registered
5867
controllerAccount := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount)
68+
controllerAddress := controllerAccount.Bech32Address(chainA.Config().Bech32Prefix)
5969
chainBAccount := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount)
6070
var hostAccount string
6171

6272
t.Run("broadcast MsgRegisterInterchainAccount", func(t *testing.T) {
6373
version := getICAVersion(testconfig.GetChainATag(), testconfig.GetChainBTag())
64-
msgRegisterAccount := controllertypes.NewMsgRegisterInterchainAccount(ibctesting.FirstConnectionID, controllerAccount.Bech32Address(chainA.Config().Bech32Prefix), version)
74+
msgRegisterAccount := controllertypes.NewMsgRegisterInterchainAccount(ibctesting.FirstConnectionID, controllerAddress, version)
6575

6676
txResp, err := s.BroadcastMessages(ctx, chainA, controllerAccount, msgRegisterAccount)
6777
s.Require().NoError(err)
@@ -74,7 +84,7 @@ func (s *InterchainAccountsTestSuite) TestMsgSendTx_SuccessfulTransfer() {
7484

7585
t.Run("verify interchain account", func(t *testing.T) {
7686
var err error
77-
hostAccount, err = s.QueryInterchainAccount(ctx, chainA, controllerAccount.Bech32Address(chainA.Config().Bech32Prefix), ibctesting.FirstConnectionID)
87+
hostAccount, err = s.QueryInterchainAccount(ctx, chainA, controllerAddress, ibctesting.FirstConnectionID)
7888
s.Require().NoError(err)
7989
s.Require().NotZero(len(hostAccount))
8090

@@ -152,12 +162,13 @@ func (s *InterchainAccountsTestSuite) TestMsgSendTx_FailedTransfer_InsufficientF
152162
// setup 2 accounts: controller account on chain A, a second chain B account.
153163
// host account will be created when the ICA is registered
154164
controllerAccount := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount)
165+
controllerAddress := controllerAccount.Bech32Address(chainA.Config().Bech32Prefix)
155166
chainBAccount := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount)
156167
var hostAccount string
157168

158169
t.Run("broadcast MsgRegisterInterchainAccount", func(t *testing.T) {
159170
version := getICAVersion(testconfig.GetChainATag(), testconfig.GetChainBTag())
160-
msgRegisterAccount := controllertypes.NewMsgRegisterInterchainAccount(ibctesting.FirstConnectionID, controllerAccount.Bech32Address(chainA.Config().Bech32Prefix), version)
171+
msgRegisterAccount := controllertypes.NewMsgRegisterInterchainAccount(ibctesting.FirstConnectionID, controllerAddress, version)
161172

162173
txResp, err := s.BroadcastMessages(ctx, chainA, controllerAccount, msgRegisterAccount)
163174
s.Require().NoError(err)
@@ -170,7 +181,7 @@ func (s *InterchainAccountsTestSuite) TestMsgSendTx_FailedTransfer_InsufficientF
170181

171182
t.Run("verify interchain account", func(t *testing.T) {
172183
var err error
173-
hostAccount, err = s.QueryInterchainAccount(ctx, chainA, controllerAccount.Bech32Address(chainA.Config().Bech32Prefix), ibctesting.FirstConnectionID)
184+
hostAccount, err = s.QueryInterchainAccount(ctx, chainA, controllerAddress, ibctesting.FirstConnectionID)
174185
s.Require().NoError(err)
175186
s.Require().NotZero(len(hostAccount))
176187

@@ -204,7 +215,7 @@ func (s *InterchainAccountsTestSuite) TestMsgSendTx_FailedTransfer_InsufficientF
204215
Memo: "e2e",
205216
}
206217

207-
msgSendTx := controllertypes.NewMsgSendTx(controllerAccount.Bech32Address(chainA.Config().Bech32Prefix), ibctesting.FirstConnectionID, uint64(time.Hour.Nanoseconds()), packetData)
218+
msgSendTx := controllertypes.NewMsgSendTx(controllerAddress, ibctesting.FirstConnectionID, uint64(time.Hour.Nanoseconds()), packetData)
208219

209220
txResp, err := s.BroadcastMessages(
210221
ctx,
@@ -228,3 +239,181 @@ func (s *InterchainAccountsTestSuite) TestMsgSendTx_FailedTransfer_InsufficientF
228239
})
229240
})
230241
}
242+
243+
func (s *InterchainAccountsTestSuite) TestMsgSubmitTx_SuccessfulTransfer_AfterReopeningICA() {
244+
t := s.T()
245+
ctx := context.TODO()
246+
247+
// setup relayers and connection-0 between two chains
248+
// channel-0 is a transfer channel but it will not be used in this test case
249+
relayer, _ := s.SetupChainsRelayerAndChannel(ctx)
250+
chainA, chainB := s.GetChains()
251+
252+
// setup 2 accounts: controller account on chain A, a second chain B account.
253+
// host account will be created when the ICA is registered
254+
controllerAccount := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount)
255+
controllerAddress := controllerAccount.Bech32Address(chainA.Config().Bech32Prefix)
256+
chainBAccount := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount)
257+
258+
var (
259+
portID string
260+
hostAccount string
261+
262+
initialChannelID = "channel-1"
263+
channelIDAfterReopening = "channel-2"
264+
)
265+
266+
t.Run("register interchain account", func(t *testing.T) {
267+
var err error
268+
version := getICAVersion(testconfig.GetChainATag(), testconfig.GetChainBTag())
269+
msgRegisterInterchainAccount := controllertypes.NewMsgRegisterInterchainAccount(ibctesting.FirstConnectionID, controllerAddress, version)
270+
s.RegisterInterchainAccount(ctx, chainA, controllerAccount, msgRegisterInterchainAccount)
271+
portID, err = icatypes.NewControllerPortID(controllerAddress)
272+
s.Require().NoError(err)
273+
})
274+
275+
t.Run("start relayer", func(t *testing.T) {
276+
s.StartRelayer(relayer)
277+
})
278+
279+
t.Run("verify interchain account", func(t *testing.T) {
280+
var err error
281+
hostAccount, err = s.QueryInterchainAccount(ctx, chainA, controllerAddress, ibctesting.FirstConnectionID)
282+
s.Require().NoError(err)
283+
s.Require().NotZero(len(hostAccount))
284+
285+
_, err = s.QueryChannel(ctx, chainA, portID, initialChannelID)
286+
s.Require().NoError(err)
287+
})
288+
289+
// stop the relayer to let the submit tx message time out
290+
t.Run("stop relayer", func(t *testing.T) {
291+
s.StopRelayer(ctx, relayer)
292+
})
293+
294+
t.Run("submit tx message with bank transfer message times out", func(t *testing.T) {
295+
t.Run("fund interchain account wallet", func(t *testing.T) {
296+
// fund the host account account so it has some $$ to send
297+
err := chainB.SendFunds(ctx, ibctest.FaucetAccountKeyName, ibc.WalletAmount{
298+
Address: hostAccount,
299+
Amount: testvalues.StartingTokenAmount,
300+
Denom: chainB.Config().Denom,
301+
})
302+
s.Require().NoError(err)
303+
})
304+
305+
t.Run("broadcast MsgSendTx", func(t *testing.T) {
306+
// assemble bank transfer message from host account to user account on host chain
307+
msgSend := &banktypes.MsgSend{
308+
FromAddress: hostAccount,
309+
ToAddress: chainBAccount.Bech32Address(chainB.Config().Bech32Prefix),
310+
Amount: sdk.NewCoins(testvalues.DefaultTransferAmount(chainB.Config().Denom)),
311+
}
312+
313+
cdc := testsuite.Codec()
314+
315+
bz, err := icatypes.SerializeCosmosTx(cdc, []proto.Message{msgSend})
316+
s.Require().NoError(err)
317+
318+
packetData := icatypes.InterchainAccountPacketData{
319+
Type: icatypes.EXECUTE_TX,
320+
Data: bz,
321+
Memo: "e2e",
322+
}
323+
324+
msgSendTx := controllertypes.NewMsgSendTx(controllerAddress, ibctesting.FirstConnectionID, uint64(1), packetData)
325+
326+
resp, err := s.BroadcastMessages(
327+
ctx,
328+
chainA,
329+
controllerAccount,
330+
msgSendTx,
331+
)
332+
333+
s.AssertValidTxResponse(resp)
334+
s.Require().NoError(err)
335+
336+
// this sleep is to allow the packet to timeout
337+
time.Sleep(1 * time.Second)
338+
})
339+
})
340+
341+
t.Run("start relayer", func(t *testing.T) {
342+
s.StartRelayer(relayer)
343+
})
344+
345+
t.Run("verify channel is closed due to timeout on ordered channel", func(t *testing.T) {
346+
channel, err := s.QueryChannel(ctx, chainA, portID, initialChannelID)
347+
s.Require().NoError(err)
348+
349+
s.Require().Equal(channeltypes.CLOSED, channel.State, "the channel was not in an expected state")
350+
})
351+
352+
t.Run("verify tokens not transferred", func(t *testing.T) {
353+
balance, err := chainB.GetBalance(ctx, chainBAccount.Bech32Address(chainB.Config().Bech32Prefix), chainB.Config().Denom)
354+
s.Require().NoError(err)
355+
356+
_, err = chainB.GetBalance(ctx, hostAccount, chainB.Config().Denom)
357+
s.Require().NoError(err)
358+
359+
expected := testvalues.StartingTokenAmount
360+
s.Require().Equal(expected, balance)
361+
})
362+
363+
// re-register interchain account to reopen the channel now that it has been closed due to timeout
364+
// on an ordered channel
365+
t.Run("register interchain account", func(t *testing.T) {
366+
version := getICAVersion(testconfig.GetChainATag(), testconfig.GetChainBTag())
367+
msgRegisterInterchainAccount := controllertypes.NewMsgRegisterInterchainAccount(ibctesting.FirstConnectionID, controllerAddress, version)
368+
s.RegisterInterchainAccount(ctx, chainA, controllerAccount, msgRegisterInterchainAccount)
369+
370+
s.Require().NoError(test.WaitForBlocks(ctx, 10, chainA, chainB))
371+
})
372+
373+
t.Run("verify new channel is now open and interchain account has been reregistered with the same portID", func(t *testing.T) {
374+
channel, err := s.QueryChannel(ctx, chainA, portID, channelIDAfterReopening)
375+
s.Require().NoError(err)
376+
377+
s.Require().Equal(channeltypes.OPEN, channel.State, "the channel was not in an expected state")
378+
})
379+
380+
t.Run("broadcast MsgSendTx", func(t *testing.T) {
381+
// assemble bank transfer message from host account to user account on host chain
382+
msgSend := &banktypes.MsgSend{
383+
FromAddress: hostAccount,
384+
ToAddress: chainBAccount.Bech32Address(chainB.Config().Bech32Prefix),
385+
Amount: sdk.NewCoins(testvalues.DefaultTransferAmount(chainB.Config().Denom)),
386+
}
387+
388+
cdc := testsuite.Codec()
389+
390+
bz, err := icatypes.SerializeCosmosTx(cdc, []proto.Message{msgSend})
391+
s.Require().NoError(err)
392+
393+
packetData := icatypes.InterchainAccountPacketData{
394+
Type: icatypes.EXECUTE_TX,
395+
Data: bz,
396+
Memo: "e2e",
397+
}
398+
399+
msgSendTx := controllertypes.NewMsgSendTx(controllerAddress, ibctesting.FirstConnectionID, uint64(5*time.Minute), packetData)
400+
401+
resp, err := s.BroadcastMessages(
402+
ctx,
403+
chainA,
404+
controllerAccount,
405+
msgSendTx,
406+
)
407+
408+
s.AssertValidTxResponse(resp)
409+
s.Require().NoError(err)
410+
})
411+
412+
t.Run("verify tokens transferred", func(t *testing.T) {
413+
balance, err := chainB.GetBalance(ctx, chainBAccount.Bech32Address(chainB.Config().Bech32Prefix), chainB.Config().Denom)
414+
s.Require().NoError(err)
415+
416+
expected := testvalues.IBCTransferAmount + testvalues.StartingTokenAmount
417+
s.Require().Equal(expected, balance)
418+
})
419+
}

e2e/testsuite/grpc_query.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,20 @@ func (s *E2ETestSuite) QueryClientState(ctx context.Context, chain ibc.Chain, cl
3333
return clientState, nil
3434
}
3535

36+
// QueryChannel queries the channel on a given chain for the provided portID and channelID
37+
func (s *E2ETestSuite) QueryChannel(ctx context.Context, chain ibc.Chain, portID, channelID string) (channeltypes.Channel, error) {
38+
queryClient := s.GetChainGRCPClients(chain).ChannelQueryClient
39+
res, err := queryClient.Channel(ctx, &channeltypes.QueryChannelRequest{
40+
PortId: portID,
41+
ChannelId: channelID,
42+
})
43+
if err != nil {
44+
return channeltypes.Channel{}, err
45+
}
46+
47+
return *res.Channel, nil
48+
}
49+
3650
// QueryPacketCommitment queries the packet commitment on the given chain for the provided channel and sequence.
3751
func (s *E2ETestSuite) QueryPacketCommitment(ctx context.Context, chain ibc.Chain, portID, channelID string, sequence uint64) ([]byte, error) {
3852
queryClient := s.GetChainGRCPClients(chain).ChannelQueryClient

0 commit comments

Comments
 (0)