From 38aa8a5c7140579a0406ae31c5d492356e9efe01 Mon Sep 17 00:00:00 2001 From: Gjermund Garaba Date: Mon, 25 Mar 2024 12:34:23 +0100 Subject: [PATCH] test(e2e): verify host params disabled --- e2e/tests/interchain_accounts/params_test.go | 146 ++++++++++++++++++- e2e/testsuite/codec.go | 2 + e2e/testsuite/tx.go | 34 +++++ 3 files changed, 176 insertions(+), 6 deletions(-) diff --git a/e2e/tests/interchain_accounts/params_test.go b/e2e/tests/interchain_accounts/params_test.go index 4cdc64fa3715..c11891399cbb 100644 --- a/e2e/tests/interchain_accounts/params_test.go +++ b/e2e/tests/interchain_accounts/params_test.go @@ -5,10 +5,18 @@ package interchainaccounts import ( "context" "testing" + "time" + "github.com/cosmos/gogoproto/proto" + "github.com/strangelove-ventures/interchaintest/v8" "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" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" paramsproposaltypes "github.com/cosmos/cosmos-sdk/x/params/types/proposal" @@ -18,6 +26,7 @@ import ( hosttypes "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/host/types" icatypes "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/types" channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" + coretypes "github.com/cosmos/ibc-go/v8/modules/core/types" ibctesting "github.com/cosmos/ibc-go/v8/testing" ) @@ -109,13 +118,17 @@ func (s *InterchainAccountsParamsTestSuite) TestHostEnabledParam() { // 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) - _, chainB := s.GetChains() + relayer, _ := s.SetupChainsRelayerAndChannel(ctx, nil) + chainA, chainB := s.GetChains() chainBVersion := chainB.Config().Images[0].Version - // setup 2 accounts: controller account on chain A, a second chain B account. + // setup 2 accounts: controller account on chain A, a second chain B account (to do the disable host gov proposal) // host account will be created when the ICA is registered - chainBUser := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) + controllerAccount := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) + controllerAddress := controllerAccount.FormattedAddress() + chainBAccount := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) + chainBAddress := chainBAccount.FormattedAddress() + var hostAccount string // Assert that default value for enabled is true. t.Run("ensure the host is enabled", func(t *testing.T) { @@ -124,6 +137,36 @@ func (s *InterchainAccountsParamsTestSuite) TestHostEnabledParam() { s.Require().Equal([]string{hosttypes.AllowAllHostMsgs}, params.AllowMessages) }) + t.Run("ensure ica packets are flowing before disabling the host", func(t *testing.T) { + t.Run("broadcast MsgRegisterInterchainAccount", func(t *testing.T) { + // explicitly set the version string because we don't want to use incentivized channels. + version := icatypes.NewDefaultMetadataString(ibctesting.FirstConnectionID, ibctesting.FirstConnectionID) + msgRegisterAccount := controllertypes.NewMsgRegisterInterchainAccount(ibctesting.FirstConnectionID, controllerAddress, version, channeltypes.ORDERED) + + txResp := s.BroadcastMessages(ctx, chainA, controllerAccount, msgRegisterAccount) + s.AssertTxSuccess(txResp) + }) + + 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)) + + channels, err := relayer.GetChannels(ctx, s.GetRelayerExecReporter(), chainA.Config().ChainID) + s.Require().NoError(err) + s.Require().Equal(len(channels), 2) + }) + + t.Run("stop relayer", func(t *testing.T) { + s.StopRelayer(ctx, relayer) + }) + }) + t.Run("disable the host", func(t *testing.T) { if testvalues.SelfParamsFeatureReleases.IsSupported(chainBVersion) { authority, err := s.QueryModuleAccountAddress(ctx, govtypes.ModuleName, chainB) @@ -134,14 +177,14 @@ func (s *InterchainAccountsParamsTestSuite) TestHostEnabledParam() { Signer: authority.String(), Params: hosttypes.NewParams(false, []string{hosttypes.AllowAllHostMsgs}), } - s.ExecuteAndPassGovV1Proposal(ctx, &msg, chainB, chainBUser) + s.ExecuteAndPassGovV1Proposal(ctx, &msg, chainB, chainBAccount) } else { changes := []paramsproposaltypes.ParamChange{ paramsproposaltypes.NewParamChange(hosttypes.StoreKey, string(hosttypes.KeyHostEnabled), "false"), } proposal := paramsproposaltypes.NewParameterChangeProposal(ibctesting.Title, ibctesting.Description, changes) - s.ExecuteAndPassGovV1Beta1Proposal(ctx, chainB, chainBUser, proposal) + s.ExecuteAndPassGovV1Beta1Proposal(ctx, chainB, chainBAccount, proposal) } }) @@ -149,4 +192,95 @@ func (s *InterchainAccountsParamsTestSuite) TestHostEnabledParam() { params := s.QueryHostParams(ctx, chainB) s.Require().False(params.HostEnabled) }) + + t.Run("ensure that ica packets are not flowing", func(t *testing.T) { + t.Run("fund interchain account wallet", func(t *testing.T) { + // fund the host account so it has some $$ to send + err := chainB.SendFunds(ctx, interchaintest.FaucetAccountKeyName, ibc.WalletAmount{ + Address: hostAccount, + Amount: sdkmath.NewInt(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: chainBAddress, + Amount: sdk.NewCoins(testvalues.DefaultTransferAmount(chainB.Config().Denom)), + } + + cdc := testsuite.Codec() + bz, err := icatypes.SerializeCosmosTx(cdc, []proto.Message{msgSend}, icatypes.EncodingProtobuf) + s.Require().NoError(err) + + packetData := icatypes.InterchainAccountPacketData{ + Type: icatypes.EXECUTE_TX, + Data: bz, + Memo: "e2e", + } + + msgSendTx := controllertypes.NewMsgSendTx(controllerAddress, ibctesting.FirstConnectionID, uint64(time.Hour.Nanoseconds()), packetData) + + resp := s.BroadcastMessages( + ctx, + chainA, + controllerAccount, + msgSendTx, + ) + + s.AssertTxSuccess(resp) + }) + + t.Run("start relayer", func(t *testing.T) { + s.StartRelayer(relayer) + }) + + s.Require().NoError(test.WaitForBlocks(ctx, 10, chainA, chainB)) + + t.Run("verify no tokens were transferred", func(t *testing.T) { + chainBAccountBalance, err := s.QueryBalance(ctx, chainB, chainBAddress, chainB.Config().Denom) + s.Require().NoError(err) + s.Require().Equal(testvalues.StartingTokenAmount, chainBAccountBalance.Int64()) + + hostAccountBalance, err := s.QueryBalance(ctx, chainB, hostAccount, chainB.Config().Denom) + s.Require().NoError(err) + s.Require().Equal(testvalues.StartingTokenAmount, hostAccountBalance.Int64()) + }) + + t.Run("verify acknowledgement error", func(t *testing.T) { + txSearchRes, err := s.QueryTxsByEvents(ctx, chainB, 1, 1, "message.action='/ibc.core.channel.v1.MsgRecvPacket'", "") + s.Require().NoError(err) + s.Require().Len(txSearchRes.Txs, 1) + + // get acknowledgement + ackFound := false + var errorMessage string + + searchAckError: + for _, event := range txSearchRes.Txs[0].Events { + if event.Type != coretypes.ErrorAttributeKeyPrefix+icatypes.EventTypePacket { + continue + } + + for _, attr := range event.Attributes { + if attr.Key != coretypes.ErrorAttributeKeyPrefix+icatypes.AttributeKeyAckError { + continue + } + + errorMessage = attr.Value + s.T().Logf("ack found: %s", errorMessage) + + ackFound = true + + break searchAckError + } + } + + s.Require().True(ackFound) + s.Require().Equal(errorMessage, hosttypes.ErrHostSubModuleDisabled.Error()) + }) + }) } diff --git a/e2e/testsuite/codec.go b/e2e/testsuite/codec.go index b9240aeb326d..7669a4b14b1e 100644 --- a/e2e/testsuite/codec.go +++ b/e2e/testsuite/codec.go @@ -14,6 +14,7 @@ import ( cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module/testutil" + "github.com/cosmos/cosmos-sdk/types/tx" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/authz" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -88,6 +89,7 @@ func codecAndEncodingConfig() (*codec.ProtoCodec, simappparams.EncodingConfig) { grouptypes.RegisterInterfaces(cfg.InterfaceRegistry) proposaltypes.RegisterInterfaces(cfg.InterfaceRegistry) authz.RegisterInterfaces(cfg.InterfaceRegistry) + tx.RegisterInterfaces(cfg.InterfaceRegistry) cdc := codec.NewProtoCodec(cfg.InterfaceRegistry) return cdc, cfg diff --git a/e2e/testsuite/tx.go b/e2e/testsuite/tx.go index c3f39b8685c7..1f92600a1f4d 100644 --- a/e2e/testsuite/tx.go +++ b/e2e/testsuite/tx.go @@ -16,6 +16,7 @@ import ( sdkmath "cosmossdk.io/math" "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" sdk "github.com/cosmos/cosmos-sdk/types" signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" @@ -297,3 +298,36 @@ func (s *E2ETestSuite) PruneAcknowledgements( msg := channeltypes.NewMsgPruneAcknowledgements(portID, channelID, limit, user.FormattedAddress()) return s.BroadcastMessages(ctx, chain, user, msg) } + +// QueryTxsByEvents runs the QueryTxsByEvents command on the given chain. +// https://github.com/cosmos/cosmos-sdk/blob/65ab2530cc654fd9e252b124ed24cbaa18023b2b/x/auth/client/cli/query.go#L33 +func (*E2ETestSuite) QueryTxsByEvents( + ctx context.Context, chain ibc.Chain, + page, limit int, query, orderBy string, +) (*sdk.SearchTxsResult, error) { + cosmosChain, ok := chain.(*cosmos.CosmosChain) + if !ok { + return nil, fmt.Errorf("QueryTxsByEvents must be passed a cosmos.CosmosChain") + } + + cmd := []string{"txs", "--query", query} + if orderBy != "" { + cmd = append(cmd, "--order_by", orderBy) + } + if page != 0 { + cmd = append(cmd, "--"+flags.FlagPage, strconv.Itoa(page)) + } + if limit != 0 { + cmd = append(cmd, "--"+flags.FlagLimit, strconv.Itoa(limit)) + } + + stdout, _, err := cosmosChain.GetNode().ExecQuery(ctx, cmd...) + if err != nil { + return nil, err + } + + result := &sdk.SearchTxsResult{} + Codec().MustUnmarshalJSON(stdout, result) + + return result, nil +}