Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: e2e for ICA reopening #2720

Merged
merged 26 commits into from
Nov 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
2259ab5
wip test
crodriguezvega Sep 16, 2022
38818f1
add sleep
crodriguezvega Sep 16, 2022
e693456
add logging
crodriguezvega Sep 16, 2022
4455226
remove logging
crodriguezvega Sep 16, 2022
f72efb4
Merge branch 'main' into carlos/add-ica-reopen-channel-test
crodriguezvega Sep 30, 2022
1056302
add new tag
crodriguezvega Sep 30, 2022
09f2db6
trial & error to see if I can get the channel to get closed...
crodriguezvega Oct 3, 2022
c3402b4
some more trial and error
crodriguezvega Oct 10, 2022
893d43c
comment import
crodriguezvega Oct 10, 2022
cff318f
Merge branch 'main' into e2e_channel_reopen
charleenfei Nov 7, 2022
ac9ac4f
.
charleenfei Nov 7, 2022
814627a
fix test
charleenfei Nov 9, 2022
6b2aee3
rm todos
charleenfei Nov 9, 2022
20bb218
Merge branch 'main' into e2e_channel_reopen
charleenfei Nov 9, 2022
45c3533
update re: comments
charleenfei Nov 10, 2022
939f348
update block time wait period
charleenfei Nov 10, 2022
9ce26ff
Merge branch 'main' into e2e_channel_reopen
charleenfei Nov 10, 2022
4e13744
pr comments
charleenfei Nov 10, 2022
41a689e
typo
charleenfei Nov 10, 2022
12f8537
typo
charleenfei Nov 10, 2022
6e1da4f
add controllerAddress var in other tests
charleenfei Nov 10, 2022
67db5e9
Merge branch 'main' into e2e_channel_reopen
charleenfei Nov 10, 2022
f7e2dbf
update expected balance to correct int64
charleenfei Nov 11, 2022
62d4b2c
rm icad v0.1.5 tag (same as v0.1.4 but with shorter timeout)
charleenfei Nov 11, 2022
d13b134
merge
charleenfei Nov 11, 2022
4c91678
Merge branch 'main' into e2e_channel_reopen
charleenfei Nov 14, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
199 changes: 194 additions & 5 deletions e2e/tests/interchain_accounts/base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"time"

ibctest "github.com/strangelove-ventures/ibctest/v6"
"github.com/strangelove-ventures/ibctest/v6/chain/cosmos"
"github.com/strangelove-ventures/ibctest/v6/ibc"
"github.com/strangelove-ventures/ibctest/v6/test"
"github.com/stretchr/testify/suite"
Expand All @@ -21,6 +22,7 @@ import (

controllertypes "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts/controller/types"
icatypes "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts/types"
channeltypes "github.com/cosmos/ibc-go/v6/modules/core/04-channel/types"
ibctesting "github.com/cosmos/ibc-go/v6/testing"
)

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

// RegisterInterchainAccount will attempt to register an interchain account on the counterparty chain.
func (s *InterchainAccountsTestSuite) RegisterInterchainAccount(ctx context.Context, chain *cosmos.CosmosChain, user *ibc.Wallet, msgRegisterAccount *controllertypes.MsgRegisterInterchainAccount) {
txResp, err := s.BroadcastMessages(ctx, chain, user, msgRegisterAccount)
s.Require().NoError(err)
s.AssertValidTxResponse(txResp)
}

func (s *InterchainAccountsTestSuite) TestMsgSendTx_SuccessfulTransfer() {
t := s.T()
ctx := context.TODO()
Expand All @@ -56,12 +65,13 @@ func (s *InterchainAccountsTestSuite) TestMsgSendTx_SuccessfulTransfer() {
// setup 2 accounts: controller account on chain A, a second chain B account.
// host account will be created when the ICA is registered
controllerAccount := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount)
controllerAddress := controllerAccount.Bech32Address(chainA.Config().Bech32Prefix)
chainBAccount := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount)
var hostAccount string

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

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

t.Run("verify interchain account", func(t *testing.T) {
var err error
hostAccount, err = s.QueryInterchainAccount(ctx, chainA, controllerAccount.Bech32Address(chainA.Config().Bech32Prefix), ibctesting.FirstConnectionID)
hostAccount, err = s.QueryInterchainAccount(ctx, chainA, controllerAddress, ibctesting.FirstConnectionID)
s.Require().NoError(err)
s.Require().NotZero(len(hostAccount))

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

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

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

t.Run("verify interchain account", func(t *testing.T) {
var err error
hostAccount, err = s.QueryInterchainAccount(ctx, chainA, controllerAccount.Bech32Address(chainA.Config().Bech32Prefix), ibctesting.FirstConnectionID)
hostAccount, err = s.QueryInterchainAccount(ctx, chainA, controllerAddress, ibctesting.FirstConnectionID)
s.Require().NoError(err)
s.Require().NotZero(len(hostAccount))

Expand Down Expand Up @@ -204,7 +215,7 @@ func (s *InterchainAccountsTestSuite) TestMsgSendTx_FailedTransfer_InsufficientF
Memo: "e2e",
}

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

txResp, err := s.BroadcastMessages(
ctx,
Expand All @@ -228,3 +239,181 @@ func (s *InterchainAccountsTestSuite) TestMsgSendTx_FailedTransfer_InsufficientF
})
})
}

func (s *InterchainAccountsTestSuite) TestMsgSubmitTx_SuccessfulTransfer_AfterReopeningICA() {
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)
chainA, chainB := s.GetChains()

// setup 2 accounts: controller account on chain A, a second chain B account.
// host account will be created when the ICA is registered
controllerAccount := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount)
controllerAddress := controllerAccount.Bech32Address(chainA.Config().Bech32Prefix)
chainBAccount := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount)

var (
portID string
hostAccount string

initialChannelID = "channel-1"
channelIDAfterReopening = "channel-2"
)

t.Run("register interchain account", func(t *testing.T) {
var err error
version := getICAVersion(testconfig.GetChainATag(), testconfig.GetChainBTag())
msgRegisterInterchainAccount := controllertypes.NewMsgRegisterInterchainAccount(ibctesting.FirstConnectionID, controllerAddress, version)
s.RegisterInterchainAccount(ctx, chainA, controllerAccount, msgRegisterInterchainAccount)
portID, err = icatypes.NewControllerPortID(controllerAddress)
s.Require().NoError(err)
})

t.Run("start relayer", func(t *testing.T) {
s.StartRelayer(relayer)
})

t.Run("verify interchain account", func(t *testing.T) {
var err error
hostAccount, err = s.QueryInterchainAccount(ctx, chainA, controllerAddress, ibctesting.FirstConnectionID)
s.Require().NoError(err)
s.Require().NotZero(len(hostAccount))

_, err = s.QueryChannel(ctx, chainA, portID, initialChannelID)
s.Require().NoError(err)
})

// stop the relayer to let the submit tx message time out
t.Run("stop relayer", func(t *testing.T) {
s.StopRelayer(ctx, relayer)
})

t.Run("submit tx message with bank transfer message times out", func(t *testing.T) {
t.Run("fund interchain account wallet", func(t *testing.T) {
// fund the host account account so it has some $$ to send
err := chainB.SendFunds(ctx, ibctest.FaucetAccountKeyName, ibc.WalletAmount{
Address: hostAccount,
Amount: testvalues.StartingTokenAmount,
Denom: chainB.Config().Denom,
})
s.Require().NoError(err)
})

t.Run("broadcast MsgSendTx", func(t *testing.T) {
// assemble bank transfer message from host account to user account on host chain
msgSend := &banktypes.MsgSend{
FromAddress: hostAccount,
ToAddress: chainBAccount.Bech32Address(chainB.Config().Bech32Prefix),
Amount: sdk.NewCoins(testvalues.DefaultTransferAmount(chainB.Config().Denom)),
}

cdc := testsuite.Codec()

bz, err := icatypes.SerializeCosmosTx(cdc, []proto.Message{msgSend})
s.Require().NoError(err)

packetData := icatypes.InterchainAccountPacketData{
Type: icatypes.EXECUTE_TX,
Data: bz,
Memo: "e2e",
}

msgSendTx := controllertypes.NewMsgSendTx(controllerAddress, ibctesting.FirstConnectionID, uint64(1), packetData)

resp, err := s.BroadcastMessages(
ctx,
chainA,
controllerAccount,
msgSendTx,
)

s.AssertValidTxResponse(resp)
s.Require().NoError(err)

// this sleep is to allow the packet to timeout
time.Sleep(1 * time.Second)
})
})

t.Run("start relayer", func(t *testing.T) {
s.StartRelayer(relayer)
})

t.Run("verify channel is closed due to timeout on ordered channel", func(t *testing.T) {
channel, err := s.QueryChannel(ctx, chainA, portID, initialChannelID)
s.Require().NoError(err)

s.Require().Equal(channeltypes.CLOSED, channel.State, "the channel was not in an expected state")
})
Comment on lines +345 to +350
Copy link
Contributor

@damiannolan damiannolan Nov 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the expected state of the channel end on chainB here?

If a packet timeout on chainA results in the channel end being CLOSED I'd expect the counterparty to be CLOSED too at some point, maybe based off of this event emission?
But I could be wrong, possibly it stays indefinitely in an OPEN state, but I would find that weird.

cc. @colin-axner

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i thought the channel close init handshake would actually result in a channel close confirm on chain B -- 2 step handshake

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will close via CloseConfirm if the relayer relays the close


t.Run("verify tokens not transferred", func(t *testing.T) {
balance, err := chainB.GetBalance(ctx, chainBAccount.Bech32Address(chainB.Config().Bech32Prefix), chainB.Config().Denom)
s.Require().NoError(err)

_, err = chainB.GetBalance(ctx, hostAccount, chainB.Config().Denom)
s.Require().NoError(err)

expected := testvalues.StartingTokenAmount
s.Require().Equal(expected, balance)
})

// re-register interchain account to reopen the channel now that it has been closed due to timeout
// on an ordered channel
t.Run("register interchain account", func(t *testing.T) {
version := getICAVersion(testconfig.GetChainATag(), testconfig.GetChainBTag())
msgRegisterInterchainAccount := controllertypes.NewMsgRegisterInterchainAccount(ibctesting.FirstConnectionID, controllerAddress, version)
s.RegisterInterchainAccount(ctx, chainA, controllerAccount, msgRegisterInterchainAccount)

s.Require().NoError(test.WaitForBlocks(ctx, 10, chainA, chainB))
})

t.Run("verify new channel is now open and interchain account has been reregistered with the same portID", func(t *testing.T) {
channel, err := s.QueryChannel(ctx, chainA, portID, channelIDAfterReopening)
s.Require().NoError(err)

s.Require().Equal(channeltypes.OPEN, channel.State, "the channel was not in an expected state")
})

t.Run("broadcast MsgSendTx", func(t *testing.T) {
// assemble bank transfer message from host account to user account on host chain
msgSend := &banktypes.MsgSend{
FromAddress: hostAccount,
ToAddress: chainBAccount.Bech32Address(chainB.Config().Bech32Prefix),
Amount: sdk.NewCoins(testvalues.DefaultTransferAmount(chainB.Config().Denom)),
}

cdc := testsuite.Codec()

bz, err := icatypes.SerializeCosmosTx(cdc, []proto.Message{msgSend})
s.Require().NoError(err)

packetData := icatypes.InterchainAccountPacketData{
Type: icatypes.EXECUTE_TX,
Data: bz,
Memo: "e2e",
}

msgSendTx := controllertypes.NewMsgSendTx(controllerAddress, ibctesting.FirstConnectionID, uint64(5*time.Minute), packetData)

resp, err := s.BroadcastMessages(
ctx,
chainA,
controllerAccount,
msgSendTx,
)

s.AssertValidTxResponse(resp)
s.Require().NoError(err)
})

t.Run("verify tokens transferred", func(t *testing.T) {
balance, err := chainB.GetBalance(ctx, chainBAccount.Bech32Address(chainB.Config().Bech32Prefix), chainB.Config().Denom)
s.Require().NoError(err)

expected := testvalues.IBCTransferAmount + testvalues.StartingTokenAmount
s.Require().Equal(expected, balance)
})
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we verify the bank send transferred funds correctly?

14 changes: 14 additions & 0 deletions e2e/testsuite/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ func (s *E2ETestSuite) QueryClientState(ctx context.Context, chain ibc.Chain, cl
return clientState, nil
}

// QueryChannel queries the channel on a given chain for the provided portID and channelID
func (s *E2ETestSuite) QueryChannel(ctx context.Context, chain ibc.Chain, portID, channelID string) (channeltypes.Channel, error) {
queryClient := s.GetChainGRCPClients(chain).ChannelQueryClient
res, err := queryClient.Channel(ctx, &channeltypes.QueryChannelRequest{
PortId: portID,
ChannelId: channelID,
})
if err != nil {
return channeltypes.Channel{}, err
}

return *res.Channel, nil
}

Comment on lines +37 to +49
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great addition!

// QueryPacketCommitment queries the packet commitment on the given chain for the provided channel and sequence.
func (s *E2ETestSuite) QueryPacketCommitment(ctx context.Context, chain ibc.Chain, portID, channelID string, sequence uint64) ([]byte, error) {
queryClient := s.GetChainGRCPClients(chain).ChannelQueryClient
Expand Down