-
Notifications
You must be signed in to change notification settings - Fork 639
Commit
* imp: initial modification of tx.proto * imp: ran 'make proto-all' * fix: compiler errors * imp: added query router interface * imp: added queryRouter to icahost keeper * imp: improved proto definitions * imp: ran 'make proto-all' * imp: added sdk.Msg helpers * feat: basic implementation * style: improved field names * imp: ran 'make proto-all' * fix: compiler errors * imp: ran gofumpt * feat: tests passing * feat: tests improved * test: removed unneeded code * imp: improved 'IsModuleSafe' function * imp: added IsModuleQuerySafe to msg_server * imp: added more test cases * fix: callbacks compiler * fix: non determinancy issues * fix: added query msg to codec * imp: whitelist logic added * e2e: new test added * fix: new test * fix: test * fix: e2e * fix: e2e * imp(e2e): added the QueryTxsByEvents function * fix: e2e * e2e: lint fix * fix: e2e * e2e: debug * fix: e2e * test: debug helpers * debug * test: added codec_test case * imp: additional test case * imp: added important unit test * r4r * e2e: debug * imp: added logs * fix: e2e * fix: e2e * fix: e2e * imp: added height to proto response * imp: ran 'make proto-all' * imp: added height * e2e: updated e2e to test height * imp: review suggestions * e2e: remove unneeded log * refactor: refactored 'ExtractValueFromEvents' * e2e: review item * imp: review item * nit: review item * docs: added godocs * test: unit test for mqsWhitelist added * imp: added logging * style: rename to allow list * add changelog --------- Co-authored-by: Carlos Rodriguez <[email protected]> (cherry picked from commit eecfa5c) # Conflicts: # e2e/testsuite/codec.go # e2e/testsuite/tx.go # modules/apps/27-interchain-accounts/host/keeper/keeper.go # modules/apps/27-interchain-accounts/host/keeper/keeper_test.go # modules/apps/27-interchain-accounts/host/keeper/msg_server.go # modules/apps/27-interchain-accounts/host/keeper/msg_server_test.go # modules/apps/27-interchain-accounts/host/types/codec.go # modules/apps/27-interchain-accounts/host/types/codec_test.go # modules/apps/27-interchain-accounts/host/types/host.pb.go # modules/apps/27-interchain-accounts/host/types/msgs.go # modules/apps/27-interchain-accounts/host/types/tx.pb.go # modules/apps/callbacks/testing/simapp/app.go # modules/light-clients/08-wasm/testing/simapp/app.go # proto/ibc/applications/interchain_accounts/host/v1/tx.proto # testing/simapp/app.go
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
//go:build !test_e2e | ||
|
||
package interchainaccounts | ||
|
||
import ( | ||
"context" | ||
"encoding/hex" | ||
"encoding/json" | ||
"testing" | ||
"time" | ||
|
||
"github.com/cosmos/gogoproto/proto" | ||
"github.com/strangelove-ventures/interchaintest/v8/testutil" | ||
testifysuite "github.com/stretchr/testify/suite" | ||
|
||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" | ||
|
||
"github.com/cosmos/ibc-go/e2e/testsuite" | ||
"github.com/cosmos/ibc-go/e2e/testvalues" | ||
controllertypes "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/controller/types" | ||
icahosttypes "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" | ||
ibctesting "github.com/cosmos/ibc-go/v8/testing" | ||
) | ||
|
||
func TestInterchainAccountsQueryTestSuite(t *testing.T) { | ||
testifysuite.Run(t, new(InterchainAccountsQueryTestSuite)) | ||
} | ||
|
||
type InterchainAccountsQueryTestSuite struct { | ||
testsuite.E2ETestSuite | ||
} | ||
|
||
func (s *InterchainAccountsQueryTestSuite) TestInterchainAccountsQuery() { | ||
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) | ||
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.FormattedAddress() | ||
chainBAccount := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) | ||
var hostAccount string | ||
|
||
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.UNORDERED) | ||
|
||
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().Len(channels, 2) | ||
}) | ||
|
||
t.Run("query via interchain account", func(t *testing.T) { | ||
// the host account need not be funded | ||
t.Run("broadcast query packet", func(t *testing.T) { | ||
balanceQuery := banktypes.NewQueryBalanceRequest(chainBAccount.Address(), chainB.Config().Denom) | ||
queryBz, err := balanceQuery.Marshal() | ||
s.Require().NoError(err) | ||
|
||
queryMsg := icahosttypes.NewMsgModuleQuerySafe(hostAccount, []*icahosttypes.QueryRequest{ | ||
{ | ||
Path: "/cosmos.bank.v1beta1.Query/Balance", | ||
Data: queryBz, | ||
}, | ||
}) | ||
|
||
cdc := testsuite.Codec() | ||
bz, err := icatypes.SerializeCosmosTx(cdc, []proto.Message{queryMsg}, icatypes.EncodingProtobuf) | ||
s.Require().NoError(err) | ||
|
||
packetData := icatypes.InterchainAccountPacketData{ | ||
Type: icatypes.EXECUTE_TX, | ||
Data: bz, | ||
Memo: "e2e", | ||
} | ||
|
||
icaQueryMsg := controllertypes.NewMsgSendTx(controllerAddress, ibctesting.FirstConnectionID, uint64(time.Hour.Nanoseconds()), packetData) | ||
|
||
txResp := s.BroadcastMessages(ctx, chainA, controllerAccount, icaQueryMsg) | ||
s.AssertTxSuccess(txResp) | ||
|
||
s.Require().NoError(testutil.WaitForBlocks(ctx, 10, chainA, chainB)) | ||
}) | ||
|
||
t.Run("verify query response", func(t *testing.T) { | ||
var expQueryHeight uint64 | ||
|
||
ack := &channeltypes.Acknowledgement_Result{} | ||
t.Run("retrieve acknowledgement", 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) | ||
|
||
expQueryHeight = uint64(txSearchRes.Txs[0].Height) | ||
|
||
ackHexValue, isFound := s.ExtractValueFromEvents( | ||
txSearchRes.Txs[0].Events, | ||
channeltypes.EventTypeWriteAck, | ||
channeltypes.AttributeKeyAckHex, | ||
) | ||
s.Require().True(isFound) | ||
s.Require().NotEmpty(ackHexValue) | ||
|
||
ackBz, err := hex.DecodeString(ackHexValue) | ||
s.Require().NoError(err) | ||
|
||
err = json.Unmarshal(ackBz, ack) | ||
s.Require().NoError(err) | ||
}) | ||
|
||
icaAck := &sdk.TxMsgData{} | ||
t.Run("unmarshal ica response", func(t *testing.T) { | ||
err := proto.Unmarshal(ack.Result, icaAck) | ||
s.Require().NoError(err) | ||
s.Require().Len(icaAck.GetMsgResponses(), 1) | ||
}) | ||
|
||
queryTxResp := &icahosttypes.MsgModuleQuerySafeResponse{} | ||
t.Run("unmarshal MsgModuleQuerySafeResponse", func(t *testing.T) { | ||
err := proto.Unmarshal(icaAck.MsgResponses[0].Value, queryTxResp) | ||
s.Require().NoError(err) | ||
s.Require().Len(queryTxResp.Responses, 1) | ||
s.Require().Equal(expQueryHeight, queryTxResp.Height) | ||
}) | ||
|
||
balanceResp := &banktypes.QueryBalanceResponse{} | ||
t.Run("unmarshal and verify bank query response", func(t *testing.T) { | ||
err := proto.Unmarshal(queryTxResp.Responses[0], balanceResp) | ||
s.Require().NoError(err) | ||
s.Require().Equal(chainB.Config().Denom, balanceResp.Balance.Denom) | ||
s.Require().Equal(testvalues.StartingTokenAmount, balanceResp.Balance.Amount.Int64()) | ||
}) | ||
}) | ||
}) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
package testsuite | ||
|
||
import ( | ||
"bytes" | ||
"encoding/hex" | ||
|
||
"github.com/cosmos/gogoproto/jsonpb" | ||
"github.com/cosmos/gogoproto/proto" | ||
|
||
upgradetypes "cosmossdk.io/x/upgrade/types" | ||
Check failure on line 10 in e2e/testsuite/codec.go GitHub Actions / build (amd64)
|
||
|
||
"github.com/cosmos/cosmos-sdk/codec" | ||
codectypes "github.com/cosmos/cosmos-sdk/codec/types" | ||
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
"github.com/cosmos/cosmos-sdk/types/module/testutil" | ||
txtypes "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" | ||
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" | ||
govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" | ||
grouptypes "github.com/cosmos/cosmos-sdk/x/group" | ||
proposaltypes "github.com/cosmos/cosmos-sdk/x/params/types/proposal" | ||
|
||
wasmtypes "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/types" | ||
Check failure on line 26 in e2e/testsuite/codec.go GitHub Actions / build (amd64)
|
||
icacontrollertypes "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/controller/types" | ||
Check failure on line 27 in e2e/testsuite/codec.go GitHub Actions / build (amd64)
|
||
icahosttypes "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/host/types" | ||
Check failure on line 28 in e2e/testsuite/codec.go GitHub Actions / build (amd64)
|
||
feetypes "github.com/cosmos/ibc-go/v8/modules/apps/29-fee/types" | ||
Check failure on line 29 in e2e/testsuite/codec.go GitHub Actions / build (amd64)
|
||
transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" | ||
Check failure on line 30 in e2e/testsuite/codec.go GitHub Actions / build (amd64)
|
||
v7migrations "github.com/cosmos/ibc-go/v8/modules/core/02-client/migrations/v7" | ||
Check failure on line 31 in e2e/testsuite/codec.go GitHub Actions / build (amd64)
|
||
clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" | ||
Check failure on line 32 in e2e/testsuite/codec.go GitHub Actions / build (amd64)
|
||
connectiontypes "github.com/cosmos/ibc-go/v8/modules/core/03-connection/types" | ||
channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" | ||
solomachine "github.com/cosmos/ibc-go/v8/modules/light-clients/06-solomachine" | ||
ibctmtypes "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" | ||
localhost "github.com/cosmos/ibc-go/v8/modules/light-clients/09-localhost" | ||
ibctesting "github.com/cosmos/ibc-go/v8/testing" | ||
simappparams "github.com/cosmos/ibc-go/v8/testing/simapp/params" | ||
) | ||
|
||
// Codec returns the global E2E protobuf codec. | ||
func Codec() *codec.ProtoCodec { | ||
cdc, _ := codecAndEncodingConfig() | ||
return cdc | ||
} | ||
|
||
// EncodingConfig returns the global E2E encoding config. | ||
func EncodingConfig() simappparams.EncodingConfig { | ||
_, cfg := codecAndEncodingConfig() | ||
return cfg | ||
} | ||
|
||
// SDKEncodingConfig returns the global E2E encoding config. | ||
func SDKEncodingConfig() *testutil.TestEncodingConfig { | ||
_, cfg := codecAndEncodingConfig() | ||
return &testutil.TestEncodingConfig{ | ||
InterfaceRegistry: cfg.InterfaceRegistry, | ||
Codec: cfg.Codec, | ||
TxConfig: cfg.TxConfig, | ||
Amino: cfg.Amino, | ||
} | ||
} | ||
|
||
func codecAndEncodingConfig() (*codec.ProtoCodec, simappparams.EncodingConfig) { | ||
cfg := simappparams.MakeTestEncodingConfig() | ||
|
||
// ibc types | ||
icacontrollertypes.RegisterInterfaces(cfg.InterfaceRegistry) | ||
icahosttypes.RegisterInterfaces(cfg.InterfaceRegistry) | ||
feetypes.RegisterInterfaces(cfg.InterfaceRegistry) | ||
solomachine.RegisterInterfaces(cfg.InterfaceRegistry) | ||
v7migrations.RegisterInterfaces(cfg.InterfaceRegistry) | ||
transfertypes.RegisterInterfaces(cfg.InterfaceRegistry) | ||
clienttypes.RegisterInterfaces(cfg.InterfaceRegistry) | ||
channeltypes.RegisterInterfaces(cfg.InterfaceRegistry) | ||
connectiontypes.RegisterInterfaces(cfg.InterfaceRegistry) | ||
ibctmtypes.RegisterInterfaces(cfg.InterfaceRegistry) | ||
localhost.RegisterInterfaces(cfg.InterfaceRegistry) | ||
wasmtypes.RegisterInterfaces(cfg.InterfaceRegistry) | ||
|
||
// all other types | ||
upgradetypes.RegisterInterfaces(cfg.InterfaceRegistry) | ||
banktypes.RegisterInterfaces(cfg.InterfaceRegistry) | ||
govv1beta1.RegisterInterfaces(cfg.InterfaceRegistry) | ||
govv1.RegisterInterfaces(cfg.InterfaceRegistry) | ||
authtypes.RegisterInterfaces(cfg.InterfaceRegistry) | ||
cryptocodec.RegisterInterfaces(cfg.InterfaceRegistry) | ||
grouptypes.RegisterInterfaces(cfg.InterfaceRegistry) | ||
proposaltypes.RegisterInterfaces(cfg.InterfaceRegistry) | ||
authz.RegisterInterfaces(cfg.InterfaceRegistry) | ||
txtypes.RegisterInterfaces(cfg.InterfaceRegistry) | ||
|
||
cdc := codec.NewProtoCodec(cfg.InterfaceRegistry) | ||
return cdc, cfg | ||
} | ||
|
||
// UnmarshalMsgResponses attempts to unmarshal the tx msg responses into the provided message types. | ||
func UnmarshalMsgResponses(txResp sdk.TxResponse, msgs ...codec.ProtoMarshaler) error { | ||
cdc := Codec() | ||
bz, err := hex.DecodeString(txResp.Data) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return ibctesting.UnmarshalMsgResponses(cdc, bz, msgs...) | ||
} | ||
|
||
// MustProtoMarshalJSON provides an auxiliary function to return Proto3 JSON encoded | ||
// bytes of a message. This function should be used when marshalling a proto.Message | ||
// from the e2e tests. This function strips out unknown fields. This is useful for | ||
// backwards compatibility tests where the the types imported by the e2e package have | ||
// new fields that older versions do not recognize. | ||
func MustProtoMarshalJSON(msg proto.Message) []byte { | ||
anyResolver := codectypes.NewInterfaceRegistry() | ||
|
||
// EmitDefaults is set to false to prevent marshalling of unpopulated fields (memo) | ||
// OrigName and the anyResovler match the fields the original SDK function would expect | ||
// in order to minimize changes. | ||
|
||
// OrigName is true since there is no particular reason to use camel case | ||
// The any resolver is empty, but provided anyways. | ||
jm := &jsonpb.Marshaler{OrigName: true, EmitDefaults: false, AnyResolver: anyResolver} | ||
|
||
err := codectypes.UnpackInterfaces(msg, codectypes.ProtoJSONPacker{JSONPBMarshaler: jm}) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
buf := new(bytes.Buffer) | ||
if err := jm.Marshal(buf, msg); err != nil { | ||
panic(err) | ||
} | ||
|
||
return buf.Bytes() | ||
} |