From 4d3cb47aedce42fb0d6b4e7a60982252b86687fb Mon Sep 17 00:00:00 2001 From: Lockwarr Date: Thu, 7 Nov 2024 09:52:54 +0200 Subject: [PATCH] fix: wasmbinding tests --- go.mod | 2 + testutil/test_helpers.go | 76 +-- wasmbinding/test/custom_message_test.go | 601 ++++++++++-------------- 3 files changed, 282 insertions(+), 397 deletions(-) diff --git a/go.mod b/go.mod index a11d4d53..90cc9466 100644 --- a/go.mod +++ b/go.mod @@ -57,6 +57,7 @@ require ( cosmossdk.io/collections v0.4.0 // indirect cosmossdk.io/depinject v1.0.0 // indirect cosmossdk.io/x/circuit v0.1.1 // indirect + cosmossdk.io/x/nft v0.1.1 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.2 // indirect @@ -84,6 +85,7 @@ require ( github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/iavl v1.2.0 // indirect + github.com/cosmos/ibc-go/modules/apps/callbacks v0.2.1-0.20231113120333-342c00b0f8bd // indirect github.com/cosmos/ics23/go v0.11.0 // indirect github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect github.com/creachadair/atomicfile v0.3.3 // indirect diff --git a/testutil/test_helpers.go b/testutil/test_helpers.go index e00a0dd3..3c8c93a8 100644 --- a/testutil/test_helpers.go +++ b/testutil/test_helpers.go @@ -4,9 +4,13 @@ import ( "encoding/json" "fmt" "os" + "time" "cosmossdk.io/log" + "cosmossdk.io/math" + icacontrollerkeeper "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/controller/keeper" + icacontrollertypes "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/controller/types" icatypes "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/types" "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" ibctesting "github.com/cosmos/ibc-go/v8/testing" @@ -27,8 +31,6 @@ import ( "github.com/Nolus-Protocol/nolus-core/app" "github.com/Nolus-Protocol/nolus-core/app/params" - - ictxstypes "github.com/Nolus-Protocol/nolus-core/x/interchaintxs/types" ) var ( @@ -37,7 +39,7 @@ var ( TestInterchainID = "owner_id" - Connection = "connection-0" + Connection = "connection-1" // TestVersion defines a reusable interchainaccounts version string for testing purposes. TestVersion = string(icatypes.ModuleCdc.MustMarshalJSON(&icatypes.Metadata{ @@ -65,7 +67,7 @@ type IBCConnectionTestSuite struct { ChainA *ibctesting.TestChain ChainB *ibctesting.TestChain - Path *ibctesting.Path + // Path *ibctesting.Path TransferPath *ibctesting.Path } @@ -77,20 +79,7 @@ func (suite *IBCConnectionTestSuite) SetupTest() { suite.ChainA = suite.Coordinator.GetChain(ibctesting.GetChainID(1)) suite.ChainB = suite.Coordinator.GetChain(ibctesting.GetChainID(2)) - // move chains to the next block - suite.ChainA.NextBlock() - suite.ChainB.NextBlock() - - // path := ibctesting.NewPath(suite.ChainA, suite.ChainB) // clientID, connectionID, channelID empty - // suite.Coordinator.Setup(path) // clientID, connectionID, channelID filled - // suite.Require().Equal("07-tendermint-0", path.EndpointA.ClientID) - // suite.Require().Equal("connection-0", path.EndpointA.ClientID) - // suite.Require().Equal("channel-0", path.EndpointA.ClientID) - - // suite.Path = NewICAPath(suite.ChainA, suite.ChainB) - suite.ConfigureTransferChannel() - // suite.Coordinator.Setup(suite.Path) } func (suite *IBCConnectionTestSuite) ConfigureTransferChannel() { @@ -130,28 +119,42 @@ func (suite *IBCConnectionTestSuite) InstantiateTestContract(ctx sdk.Context, fu return addr } -func NewICAPath(chainA, chainB *ibctesting.TestChain) *ibctesting.Path { +func calculateTrustPeriod(unbondingPeriod time.Duration, defaultTrustPeriodFraction string) (time.Duration, error) { + trustDec, err := math.LegacyNewDecFromStr(defaultTrustPeriodFraction) + if err != nil { + return time.Duration(0), err + } + trustPeriod := time.Duration(trustDec.MulInt64(unbondingPeriod.Nanoseconds()).TruncateInt64()) + + return trustPeriod, nil +} + +func NewICAPath(chainA, chainB *ibctesting.TestChain, icaowner string) *ibctesting.Path { path := ibctesting.NewPath(chainA, chainB) path.EndpointA.Counterparty = path.EndpointB path.EndpointB.Counterparty = path.EndpointA - path.EndpointA.ChannelConfig.PortID = icatypes.HostPortID + path.EndpointA.ChannelConfig.PortID = icatypes.ControllerPortPrefix + icaowner path.EndpointB.ChannelConfig.PortID = icatypes.HostPortID - path.EndpointA.ChannelConfig.Order = channeltypes.ORDERED - path.EndpointB.ChannelConfig.Order = channeltypes.ORDERED + path.EndpointA.ChannelConfig.Order = channeltypes.UNORDERED + path.EndpointB.ChannelConfig.Order = channeltypes.UNORDERED path.EndpointA.ChannelConfig.Version = TestVersion path.EndpointB.ChannelConfig.Version = TestVersion - path.EndpointA.ClientConfig.(*ibctesting.TendermintConfig).UnbondingPeriod = 3600000000000 - path.EndpointA.ClientConfig.(*ibctesting.TendermintConfig).TrustingPeriod = 1200000000000 + unbondingPeriodA := time.Duration(3600000000000) + unbondingPeriodB := time.Duration(3600000000000) + trustingPeriodFraction := "0.1" + + path.EndpointA.ClientConfig.(*ibctesting.TendermintConfig).UnbondingPeriod = unbondingPeriodA + path.EndpointA.ClientConfig.(*ibctesting.TendermintConfig).TrustingPeriod, _ = calculateTrustPeriod(unbondingPeriodA, trustingPeriodFraction) - path.EndpointB.ClientConfig.(*ibctesting.TendermintConfig).UnbondingPeriod = 3600000000000 - path.EndpointB.ClientConfig.(*ibctesting.TendermintConfig).TrustingPeriod = 1200000000000 + path.EndpointB.ClientConfig.(*ibctesting.TendermintConfig).UnbondingPeriod = unbondingPeriodB + path.EndpointB.ClientConfig.(*ibctesting.TendermintConfig).TrustingPeriod, _ = calculateTrustPeriod(unbondingPeriodB, trustingPeriodFraction) return path } // SetupICAPath invokes the InterchainAccounts entrypoint and subsequent channel handshake handlers. -func SetupICAPath(path *ibctesting.Path, owner string) error { +func (suite *IBCConnectionTestSuite) SetupICAPath(path *ibctesting.Path, owner string) error { if err := RegisterInterchainAccount(path.EndpointA, owner); err != nil { return err } @@ -169,32 +172,35 @@ func SetupICAPath(path *ibctesting.Path, owner string) error { // RegisterInterchainAccount is a helper function for starting the channel handshake. func RegisterInterchainAccount(endpoint *ibctesting.Endpoint, owner string) error { - icaOwner, _ := ictxstypes.NewICAOwner(owner, TestInterchainID) - portID, err := icatypes.NewControllerPortID(icaOwner.String()) + portID, err := icatypes.NewControllerPortID(owner) if err != nil { return err } - ctx := endpoint.Chain.GetContext() - - channelSequence := endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.GetNextChannelSequence(ctx) + channelSequence := endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.GetNextChannelSequence(endpoint.Chain.GetContext()) a, ok := endpoint.Chain.App.(*app.App) if !ok { - return fmt.Errorf("not NolusZoneApp") + return fmt.Errorf("not NolusApp") } - // TODO(pr0n00gler): are we sure it's okay? - if err := a.ICAControllerKeeper.RegisterInterchainAccount(ctx, endpoint.ConnectionID, icaOwner.String(), ""); err != nil { + icaMsgServer := icacontrollerkeeper.NewMsgServerImpl(a.ICAControllerKeeper) + _, err = icaMsgServer.RegisterInterchainAccount(endpoint.Chain.GetContext(), &icacontrollertypes.MsgRegisterInterchainAccount{ + Owner: owner, + ConnectionId: endpoint.ConnectionID, + Version: TestVersion, + Ordering: channeltypes.UNORDERED, + }) + if err != nil { return err } - // commit state changes for proof verification endpoint.Chain.NextBlock() // update port/channel ids endpoint.ChannelID = channeltypes.FormatChannelIdentifier(channelSequence) endpoint.ChannelConfig.PortID = portID + endpoint.ChannelConfig.Version = TestVersion return nil } diff --git a/wasmbinding/test/custom_message_test.go b/wasmbinding/test/custom_message_test.go index 7ebb18db..87792bbe 100644 --- a/wasmbinding/test/custom_message_test.go +++ b/wasmbinding/test/custom_message_test.go @@ -1,295 +1,166 @@ package test -// import ( -// "encoding/json" -// "testing" - -// "cosmossdk.io/math" -// wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" - -// ibcchanneltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" - -// "github.com/stretchr/testify/suite" - -// ictxtypes "github.com/Nolus-Protocol/nolus-core/x/interchaintxs/types" - -// "github.com/CosmWasm/wasmd/x/wasm/keeper" -// "github.com/CosmWasm/wasmvm/v2/types" -// sdk "github.com/cosmos/cosmos-sdk/types" -// "github.com/stretchr/testify/require" - -// "github.com/Nolus-Protocol/nolus-core/app" -// "github.com/Nolus-Protocol/nolus-core/app/params" -// "github.com/Nolus-Protocol/nolus-core/testutil" -// "github.com/Nolus-Protocol/nolus-core/wasmbinding" -// "github.com/Nolus-Protocol/nolus-core/wasmbinding/bindings" -// contractmanagerkeeper "github.com/Nolus-Protocol/nolus-core/x/contractmanager/keeper" -// feetypes "github.com/Nolus-Protocol/nolus-core/x/feerefunder/types" -// icqkeeper "github.com/Nolus-Protocol/nolus-core/x/interchainqueries/keeper" -// ictxkeeper "github.com/Nolus-Protocol/nolus-core/x/interchaintxs/keeper" -// ) - -// const FeeCollectorAddress = "nolus1vguuxez2h5ekltfj9gjd62fs5k4rl2zy5hfrncasykzw08rezpfsd2rhm7" - -// type CustomMessengerTestSuite struct { -// testutil.IBCConnectionTestSuite -// nolus *app.App -// ctx sdk.Context -// messenger *wasmbinding.CustomMessenger -// contractOwner sdk.AccAddress -// contractAddress sdk.AccAddress -// contractKeeper wasmtypes.ContractOpsKeeper -// } - -// func (suite *CustomMessengerTestSuite) SetupTest() { -// suite.IBCConnectionTestSuite.SetupTest() -// suite.nolus = suite.GetNolusZoneApp(suite.ChainA) -// suite.ctx = suite.ChainA.GetContext() -// suite.messenger = &wasmbinding.CustomMessenger{} -// suite.messenger.Ictxmsgserver = ictxkeeper.NewMsgServerImpl(*suite.nolus.InterchainTxsKeeper) -// suite.messenger.Keeper = *suite.nolus.InterchainTxsKeeper -// suite.messenger.Icqmsgserver = icqkeeper.NewMsgServerImpl(*suite.nolus.InterchainQueriesKeeper) -// suite.messenger.ContractmanagerKeeper = suite.nolus.ContractManagerKeeper -// suite.contractOwner = keeper.RandomAccountAddress(suite.T()) - -// suite.contractKeeper = keeper.NewDefaultPermissionKeeper(&suite.nolus.WasmKeeper) - -// codeID := suite.StoreTestCode(suite.ctx, suite.contractOwner, "../testdata/reflect.wasm") -// suite.contractAddress = suite.InstantiateTestContract(suite.ctx, suite.contractOwner, codeID) -// suite.Require().NotEmpty(suite.contractAddress) -// } - -// func (suite *CustomMessengerTestSuite) TestRegisterInterchainAccount() { -// // Craft RegisterInterchainAccount message -// msg := bindings.NeutronMsg{ -// RegisterInterchainAccount: &bindings.RegisterInterchainAccount{ -// ConnectionId: suite.Path.EndpointA.ConnectionID, -// InterchainAccountId: testutil.TestInterchainID, -// RegisterFee: sdk.NewCoins(sdk.NewCoin(params.DefaultBondDenom, math.NewInt(1_000_000))), -// }, -// } - -// bankKeeper := suite.nolus.BankKeeper -// senderAddress := suite.ChainA.SenderAccounts[0].SenderAccount.GetAddress() -// err := bankKeeper.SendCoins(suite.ctx, senderAddress, suite.contractAddress, sdk.NewCoins(sdk.NewCoin(params.DefaultBondDenom, math.NewInt(1_000_000)))) -// suite.NoError(err) - -// // Dispatch RegisterInterchainAccount message -// _, err = suite.executeNeutronMsg(suite.contractAddress, msg) -// suite.NoError(err) -// } - -// func (suite *CustomMessengerTestSuite) TestRegisterInterchainAccountLongID() { -// // Store code and instantiate reflect contract -// codeID := suite.StoreTestCode(suite.ctx, suite.contractOwner, "../testdata/reflect.wasm") -// suite.contractAddress = suite.InstantiateTestContract(suite.ctx, suite.contractOwner, codeID) -// suite.Require().NotEmpty(suite.contractAddress) - -// // Craft RegisterInterchainAccount message -// msg, err := json.Marshal(bindings.NeutronMsg{ -// RegisterInterchainAccount: &bindings.RegisterInterchainAccount{ -// ConnectionId: suite.Path.EndpointA.ConnectionID, -// // the limit is 47, this line is 50 characters long -// InterchainAccountId: "01234567890123456789012345678901234567890123456789", -// }, -// }) -// suite.NoError(err) - -// // Dispatch RegisterInterchainAccount message via DispatchHandler cause we want to catch an error from SDK directly, not from a contract -// _, _, _, err = suite.messenger.DispatchMsg(suite.ctx, suite.contractAddress, suite.Path.EndpointA.ChannelConfig.PortID, types.CosmosMsg{ -// Custom: msg, -// }) -// suite.Error(err) -// suite.ErrorIs(err, ictxtypes.ErrLongInterchainAccountID) -// } - -// // func (suite *CustomMessengerTestSuite) TestRegisterInterchainQuery() { -// // // Store code and instantiate reflect contract -// // codeID := suite.StoreTestCode(suite.ctx, suite.contractOwner, "../testdata/reflect.wasm") -// // suite.contractAddress = suite.InstantiateTestContract(suite.ctx, suite.contractOwner, codeID) -// // suite.Require().NotEmpty(suite.contractAddress) - -// // err := testutil.SetupICAPath(suite.Path, suite.contractAddress.String()) -// // suite.Require().NoError(err) - -// // // Top up contract balance -// // senderAddress := suite.ChainA.SenderAccounts[0].SenderAccount.GetAddress() -// // coinsAmnt := sdk.NewCoins(sdk.NewCoin(params.DefaultBondDenom, math.NewInt(int64(10_000_000)))) -// // bankKeeper := suite.nolus.BankKeeper -// // err = bankKeeper.SendCoins(suite.ctx, senderAddress, suite.contractAddress, coinsAmnt) -// // suite.NoError(err) - -// // // Craft RegisterInterchainQuery message -// // msg, err := json.Marshal(bindings.NeutronMsg{ -// // RegisterInterchainQuery: &bindings.RegisterInterchainQuery{ -// // QueryType: string(icqtypes.InterchainQueryTypeKV), -// // Keys: []*icqtypes.KVKey{ -// // {Path: ibchost.StoreKey, Key: host.FullClientStateKey(suite.Path.EndpointB.ClientID)}, -// // }, -// // TransactionsFilter: "{}", -// // ConnectionId: suite.Path.EndpointA.ConnectionID, -// // UpdatePeriod: 20, -// // }, -// // }) -// // suite.NoError(err) - -// // // Dispatch RegisterInterchainQuery message -// // events, data, _, err := suite.messenger.DispatchMsg(suite.ctx, suite.contractAddress, suite.Path.EndpointA.ChannelConfig.PortID, types.CosmosMsg{ -// // Custom: msg, -// // }) -// // suite.NoError(err) -// // suite.Nil(events) -// // suite.Equal([][]byte{[]byte(`{"id":1}`)}, data) -// // } - -// // func (suite *CustomMessengerTestSuite) TestUpdateInterchainQuery() { -// // // reuse register interchain query test to get query registered -// // suite.TestRegisterInterchainQuery() - -// // // Craft UpdateInterchainQuery message -// // msg, err := json.Marshal(bindings.NeutronMsg{ -// // UpdateInterchainQuery: &bindings.UpdateInterchainQuery{ -// // QueryId: 1, -// // NewKeys: nil, -// // NewUpdatePeriod: 111, -// // }, -// // }) -// // suite.NoError(err) - -// // // Dispatch UpdateInterchainQuery message -// // events, data, _, err := suite.messenger.DispatchMsg(suite.ctx, suite.contractAddress, suite.Path.EndpointA.ChannelConfig.PortID, types.CosmosMsg{ -// // Custom: msg, -// // }) -// // suite.NoError(err) -// // suite.Nil(events) -// // suite.Equal([][]byte{[]byte(`{}`)}, data) -// // } - -// // func (suite *CustomMessengerTestSuite) TestUpdateInterchainQueryFailed() { -// // // Craft UpdateInterchainQuery message -// // msg, err := json.Marshal(bindings.NeutronMsg{ -// // UpdateInterchainQuery: &bindings.UpdateInterchainQuery{ -// // QueryId: 1, -// // NewKeys: nil, -// // NewUpdatePeriod: 1, -// // }, -// // }) -// // suite.NoError(err) - -// // // Dispatch UpdateInterchainQuery message -// // owner, err := sdk.AccAddressFromBech32(testutil.TestOwnerAddress) -// // suite.NoError(err) -// // events, data, _, err := suite.messenger.DispatchMsg(suite.ctx, owner, suite.Path.EndpointA.ChannelConfig.PortID, types.CosmosMsg{ -// // Custom: msg, -// // }) -// // expectedErrMsg := "failed to update interchain query: failed to update interchain query: failed to get query by query id: there is no query with id: 1" -// // suite.Require().ErrorContains(err, expectedErrMsg) -// // suite.Nil(events) -// // suite.Nil(data) -// // } - -// // func (suite *CustomMessengerTestSuite) TestRemoveInterchainQuery() { -// // // Reuse register interchain query test to get query registered -// // suite.TestRegisterInterchainQuery() - -// // // Craft RemoveInterchainQuery message -// // msg, err := json.Marshal(bindings.NeutronMsg{ -// // RemoveInterchainQuery: &bindings.RemoveInterchainQuery{ -// // QueryId: 1, -// // }, -// // }) -// // suite.NoError(err) - -// // // Dispatch RemoveInterchainQuery message -// // suite.NoError(err) -// // events, data, _, err := suite.messenger.DispatchMsg(suite.ctx, suite.contractAddress, suite.Path.EndpointA.ChannelConfig.PortID, types.CosmosMsg{ -// // Custom: msg, -// // }) -// // suite.NoError(err) -// // suite.Nil(events) -// // suite.Equal([][]byte{[]byte(`{}`)}, data) -// // } - -// // func (suite *CustomMessengerTestSuite) TestRemoveInterchainQueryFailed() { -// // // Craft RemoveInterchainQuery message -// // msg, err := json.Marshal(bindings.NeutronMsg{ -// // RemoveInterchainQuery: &bindings.RemoveInterchainQuery{ -// // QueryId: 1, -// // }, -// // }) -// // suite.NoError(err) - -// // // Dispatch RemoveInterchainQuery message -// // owner, err := sdk.AccAddressFromBech32(testutil.TestOwnerAddress) -// // suite.NoError(err) -// // events, data, _, err := suite.messenger.DispatchMsg(suite.ctx, owner, suite.Path.EndpointA.ChannelConfig.PortID, types.CosmosMsg{ -// // Custom: msg, -// // }) -// // expectedErrMsg := "failed to remove interchain query: failed to remove interchain query: failed to get query by query id: there is no query with id: 1" -// // suite.Require().ErrorContains(err, expectedErrMsg) -// // suite.Nil(events) -// // suite.Nil(data) -// // } - -// func (suite *CustomMessengerTestSuite) TestSubmitTx() { -// // Store code and instantiate reflect contract -// codeID := suite.StoreTestCode(suite.ctx, suite.contractOwner, "../testdata/reflect.wasm") -// suite.contractAddress = suite.InstantiateTestContract(suite.ctx, suite.contractOwner, codeID) -// suite.Require().NotEmpty(suite.contractAddress) - -// senderAddress := suite.ChainA.SenderAccounts[0].SenderAccount.GetAddress() -// coinsAmnt := sdk.NewCoins(sdk.NewCoin(params.DefaultBondDenom, math.NewInt(int64(10_000_000)))) -// bankKeeper := suite.nolus.BankKeeper -// err := bankKeeper.SendCoins(suite.ctx, senderAddress, suite.contractAddress, coinsAmnt) -// suite.NoError(err) - -// err = testutil.SetupICAPath(suite.Path, suite.contractAddress.String()) -// suite.Require().NoError(err) - -// events, data, _, err := suite.messenger.DispatchMsg( -// suite.ctx, -// suite.contractAddress, -// suite.Path.EndpointA.ChannelConfig.PortID, -// types.CosmosMsg{ -// Custom: suite.craftMarshaledMsgSubmitTxWithNumMsgs(1), -// }, -// ) -// suite.NoError(err) - -// var response ictxtypes.MsgSubmitTxResponse -// err = json.Unmarshal(data[0], &response) -// suite.NoError(err) -// suite.Nil(events) -// suite.Equal(uint64(1), response.SequenceId) -// suite.Equal("channel-2", response.Channel) -// } - -// func (suite *CustomMessengerTestSuite) TestSubmitTxTooMuchTxs() { -// // Store code and instantiate reflect contract -// codeID := suite.StoreTestCode(suite.ctx, suite.contractOwner, "../testdata/reflect.wasm") -// suite.contractAddress = suite.InstantiateTestContract(suite.ctx, suite.contractOwner, codeID) -// suite.Require().NotEmpty(suite.contractAddress) - -// err := testutil.SetupICAPath(suite.Path, suite.contractAddress.String()) -// suite.Require().NoError(err) - -// _, _, _, err = suite.messenger.DispatchMsg( -// suite.ctx, -// suite.contractAddress, -// suite.Path.EndpointA.ChannelConfig.PortID, -// types.CosmosMsg{ -// Custom: suite.craftMarshaledMsgSubmitTxWithNumMsgs(20), -// }, -// ) -// suite.ErrorContains(err, "MsgSubmitTx contains more messages than allowed") -// } +import ( + "encoding/json" + "testing" + + "cosmossdk.io/math" + + "github.com/CosmWasm/wasmd/x/wasm/keeper" + wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" + "github.com/CosmWasm/wasmvm/v2/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/suite" + + ibctesting "github.com/cosmos/ibc-go/v8/testing" + + "github.com/Nolus-Protocol/nolus-core/app" + "github.com/Nolus-Protocol/nolus-core/app/params" + "github.com/Nolus-Protocol/nolus-core/testutil" + "github.com/Nolus-Protocol/nolus-core/wasmbinding" + "github.com/Nolus-Protocol/nolus-core/wasmbinding/bindings" + feetypes "github.com/Nolus-Protocol/nolus-core/x/feerefunder/types" + ictxkeeper "github.com/Nolus-Protocol/nolus-core/x/interchaintxs/keeper" + ictxtypes "github.com/Nolus-Protocol/nolus-core/x/interchaintxs/types" +) + +const FeeCollectorAddress = "nolus1vguuxez2h5ekltfj9gjd62fs5k4rl2zy5hfrncasykzw08rezpfsd2rhm7" + +type CustomMessengerTestSuite struct { + testutil.IBCConnectionTestSuite + nolus *app.App + ctx sdk.Context + messenger *wasmbinding.CustomMessenger + contractOwner sdk.AccAddress + contractAddress sdk.AccAddress + contractKeeper wasmtypes.ContractOpsKeeper +} + +func (suite *CustomMessengerTestSuite) SetupTest() { + suite.IBCConnectionTestSuite.SetupTest() + suite.nolus = suite.GetNolusZoneApp(suite.ChainA) + suite.ctx = suite.ChainA.GetContext() + suite.messenger = &wasmbinding.CustomMessenger{} + suite.messenger.Ictxmsgserver = ictxkeeper.NewMsgServerImpl(*suite.nolus.InterchainTxsKeeper) + suite.messenger.Keeper = *suite.nolus.InterchainTxsKeeper + suite.messenger.ContractmanagerKeeper = suite.nolus.ContractManagerKeeper + suite.contractOwner = keeper.RandomAccountAddress(suite.T()) + + suite.contractKeeper = keeper.NewDefaultPermissionKeeper(&suite.nolus.WasmKeeper) + + codeID := suite.StoreTestCode(suite.ctx, suite.contractOwner, "../testdata/reflect.wasm") + suite.contractAddress = suite.InstantiateTestContract(suite.ctx, suite.contractOwner, codeID) + suite.Require().NotEmpty(suite.contractAddress) +} + +func (suite *CustomMessengerTestSuite) TestRegisterInterchainAccount() { + // Craft RegisterInterchainAccount message + msg := bindings.NolusMsg{ + RegisterInterchainAccount: &bindings.RegisterInterchainAccount{ + ConnectionId: suite.TransferPath.EndpointA.ConnectionID, + InterchainAccountId: testutil.TestInterchainID, + RegisterFee: sdk.NewCoins(sdk.NewCoin(params.DefaultBondDenom, math.NewInt(1_000_000))), + }, + } + + bankKeeper := suite.nolus.BankKeeper + senderAddress := suite.ChainA.SenderAccounts[0].SenderAccount.GetAddress() + err := bankKeeper.SendCoins(suite.ctx, senderAddress, suite.contractAddress, sdk.NewCoins(sdk.NewCoin(params.DefaultBondDenom, math.NewInt(1_000_000)))) + suite.NoError(err) + + // Dispatch RegisterInterchainAccount message + _, err = suite.executeNolusMsg(suite.contractAddress, msg) + suite.NoError(err) +} + +func (suite *CustomMessengerTestSuite) TestRegisterInterchainAccountLongID() { + // Store code and instantiate reflect contract + codeID := suite.StoreTestCode(suite.ctx, suite.contractOwner, "../testdata/reflect.wasm") + suite.contractAddress = suite.InstantiateTestContract(suite.ctx, suite.contractOwner, codeID) + suite.Require().NotEmpty(suite.contractAddress) + + // Craft RegisterInterchainAccount message + msg, err := json.Marshal(bindings.NolusMsg{ + RegisterInterchainAccount: &bindings.RegisterInterchainAccount{ + ConnectionId: suite.TransferPath.EndpointA.ConnectionID, + // the limit is 47, this line is 50 characters long + InterchainAccountId: "01234567890123456789012345678901234567890123456789", + }, + }) + suite.NoError(err) + + // Dispatch RegisterInterchainAccount message via DispatchHandler cause we want to catch an error from SDK directly, not from a contract + _, _, _, err = suite.messenger.DispatchMsg(suite.ctx, suite.contractAddress, suite.TransferPath.EndpointA.ChannelConfig.PortID, types.CosmosMsg{ + Custom: msg, + }) + suite.Error(err) + suite.ErrorIs(err, ictxtypes.ErrLongInterchainAccountID) +} + +func (suite *CustomMessengerTestSuite) TestSubmitTx() { + // Store code and instantiate reflect contract + codeID := suite.StoreTestCode(suite.ctx, suite.contractOwner, "../testdata/reflect.wasm") + suite.contractAddress = suite.InstantiateTestContract(suite.ctx, suite.contractOwner, codeID) + suite.Require().NotEmpty(suite.contractAddress) + + senderAddress := suite.ChainA.SenderAccounts[0].SenderAccount.GetAddress() + coinsAmnt := sdk.NewCoins(sdk.NewCoin(params.DefaultBondDenom, math.NewInt(int64(10_000_000)))) + bankKeeper := suite.nolus.BankKeeper + err := bankKeeper.SendCoins(suite.ctx, senderAddress, suite.contractAddress, coinsAmnt) + suite.NoError(err) + + icaowner := suite.contractAddress.String() + ".0" + + path := testutil.NewICAPath(suite.ChainA, suite.ChainB, icaowner) + suite.Coordinator.SetupConnections(path) + + err = suite.SetupICAPath(path, icaowner) + suite.Require().NoError(err) + + events, data, _, err := suite.messenger.DispatchMsg( + suite.ctx, + suite.contractAddress, + path.EndpointA.ChannelConfig.PortID, + types.CosmosMsg{ + Custom: suite.craftMarshaledMsgSubmitTxWithNumMsgs(1, path), + }, + ) + suite.NoError(err) + + var response ictxtypes.MsgSubmitTxResponse + err = json.Unmarshal(data[0], &response) + suite.NoError(err) + suite.Nil(events) + suite.Equal(uint64(1), response.SequenceId) + suite.Equal("channel-1", response.Channel) +} + +func (suite *CustomMessengerTestSuite) TestSubmitTxTooMuchTxs() { + // Store code and instantiate reflect contract + codeID := suite.StoreTestCode(suite.ctx, suite.contractOwner, "../testdata/reflect.wasm") + suite.contractAddress = suite.InstantiateTestContract(suite.ctx, suite.contractOwner, codeID) + suite.Require().NotEmpty(suite.contractAddress) + + icaowner := suite.contractAddress.String() + ".0" + + path := testutil.NewICAPath(suite.ChainA, suite.ChainB, icaowner) + suite.Coordinator.SetupConnections(path) + + err := suite.SetupICAPath(path, icaowner) + suite.Require().NoError(err) + + _, _, _, err = suite.messenger.DispatchMsg( + suite.ctx, + suite.contractAddress, + path.EndpointA.ChannelConfig.PortID, + types.CosmosMsg{ + Custom: suite.craftMarshaledMsgSubmitTxWithNumMsgs(20, path), + }, + ) + suite.ErrorContains(err, "MsgSubmitTx contains more messages than allowed") +} // func (suite *CustomMessengerTestSuite) TestResubmitFailureAck() { -// // Store code and instantiate reflect contract -// codeID := suite.StoreTestCode(suite.ctx, suite.contractOwner, "../testdata/reflect.wasm") -// suite.contractAddress = suite.InstantiateTestContract(suite.ctx, suite.contractOwner, codeID) -// suite.Require().NotEmpty(suite.contractAddress) - // // Add failure // packet := ibcchanneltypes.Packet{} // ack := ibcchanneltypes.Acknowledgement{ @@ -301,22 +172,20 @@ package test // suite.messenger.ContractmanagerKeeper.AddContractFailure(suite.ctx, suite.contractAddress.String(), payload, "test error") // // Craft message -// msg, err := json.Marshal(bindings.NeutronMsg{ +// msg := bindings.NolusMsg{ // ResubmitFailure: &bindings.ResubmitFailure{ // FailureId: failureID, // }, -// }) -// suite.NoError(err) +// } // // Dispatch -// events, data, _, err := suite.messenger.DispatchMsg(suite.ctx, suite.contractAddress, suite.Path.EndpointA.ChannelConfig.PortID, types.CosmosMsg{ -// Custom: msg, -// }) +// data, err := suite.executeNolusMsg(suite.contractAddress, msg) // suite.NoError(err) -// suite.Nil(events) -// expected, err := json.Marshal(&bindings.ResubmitFailureResponse{}) + +// var expected contractmanagertypes.Failure +// err = expected.Unmarshal(data) // suite.NoError(err) -// suite.Equal([][]uint8{expected}, data) +// suite.Equal(expected.Id, failureID) // } // func (suite *CustomMessengerTestSuite) TestResubmitFailureTimeout() { @@ -333,15 +202,23 @@ package test // suite.messenger.ContractmanagerKeeper.AddContractFailure(suite.ctx, suite.contractAddress.String(), payload, "test error") // // Craft message -// msg, err := json.Marshal(bindings.NeutronMsg{ +// msg, err := json.Marshal(bindings.NolusMsg{ // ResubmitFailure: &bindings.ResubmitFailure{ // FailureId: failureID, // }, // }) // suite.NoError(err) +// icaowner := suite.contractAddress.String() + ".0" + +// path := testutil.NewICAPath(suite.ChainA, suite.ChainB, icaowner) +// suite.Coordinator.SetupConnections(path) + +// err = suite.SetupICAPath(path, icaowner) +// suite.Require().NoError(err) + // // Dispatch -// events, data, _, err := suite.messenger.DispatchMsg(suite.ctx, suite.contractAddress, suite.Path.EndpointA.ChannelConfig.PortID, types.CosmosMsg{ +// events, data, _, err := suite.messenger.DispatchMsg(suite.ctx, suite.contractAddress, path.EndpointA.ChannelConfig.PortID, types.CosmosMsg{ // Custom: msg, // }) // suite.NoError(err) @@ -368,7 +245,7 @@ package test // suite.messenger.ContractmanagerKeeper.AddContractFailure(suite.ctx, testutil.TestOwnerAddress, payload, "test error") // // Craft message -// msg, err := json.Marshal(bindings.NeutronMsg{ +// msg, err := json.Marshal(bindings.NolusMsg{ // ResubmitFailure: &bindings.ResubmitFailure{ // FailureId: failureID, // }, @@ -382,65 +259,65 @@ package test // suite.ErrorContains(err, "no failure found to resubmit: not found") // } -// func (suite *CustomMessengerTestSuite) craftMarshaledMsgSubmitTxWithNumMsgs(numMsgs int) (result []byte) { -// msg := bindings.ProtobufAny{ -// TypeURL: "/cosmos.staking.v1beta1.MsgDelegate", -// Value: []byte{26, 10, 10, 5, 115, 116, 97, 107, 101, 18, 1, 48}, -// } -// msgs := make([]bindings.ProtobufAny, 0, numMsgs) -// for i := 0; i < numMsgs; i++ { -// msgs = append(msgs, msg) -// } -// result, err := json.Marshal(struct { -// SubmitTx bindings.SubmitTx `json:"submit_tx"` -// }{ -// SubmitTx: bindings.SubmitTx{ -// ConnectionId: suite.Path.EndpointA.ConnectionID, -// InterchainAccountId: testutil.TestInterchainID, -// Msgs: msgs, -// Memo: "Jimmy", -// Timeout: 2000, -// Fee: feetypes.Fee{ -// RecvFee: sdk.NewCoins(), -// AckFee: sdk.NewCoins(sdk.NewCoin(params.DefaultBondDenom, math.NewInt(1000))), -// TimeoutFee: sdk.NewCoins(sdk.NewCoin(params.DefaultBondDenom, math.NewInt(1000))), -// }, -// }, -// }) -// suite.NoError(err) -// return -// } - -// func (suite *CustomMessengerTestSuite) executeCustomMsg(contractAddress sdk.AccAddress, fullMsg json.RawMessage) (data []byte, err error) { -// customMsg := types.CosmosMsg{ -// Custom: fullMsg, -// } - -// type ExecuteMsg struct { -// ReflectMsg struct { -// Msgs []types.CosmosMsg `json:"msgs"` -// } `json:"reflect_msg"` -// } - -// execMsg := ExecuteMsg{ReflectMsg: struct { -// Msgs []types.CosmosMsg `json:"msgs"` -// }(struct{ Msgs []types.CosmosMsg }{Msgs: []types.CosmosMsg{customMsg}})} - -// msg, err := json.Marshal(execMsg) -// suite.NoError(err) - -// data, err = suite.contractKeeper.Execute(suite.ctx, contractAddress, suite.contractOwner, msg, nil) - -// return -// } - -// func (suite *CustomMessengerTestSuite) executeNeutronMsg(contractAddress sdk.AccAddress, fullMsg bindings.NeutronMsg) (data []byte, err error) { -// fullMsgBz, err := json.Marshal(fullMsg) -// suite.NoError(err) - -// return suite.executeCustomMsg(contractAddress, fullMsgBz) -// } - -// func TestMessengerTestSuite(t *testing.T) { -// suite.Run(t, new(CustomMessengerTestSuite)) -// } +func (suite *CustomMessengerTestSuite) craftMarshaledMsgSubmitTxWithNumMsgs(numMsgs int, path *ibctesting.Path) (result []byte) { + msg := bindings.ProtobufAny{ + TypeURL: "/cosmos.staking.v1beta1.MsgDelegate", + Value: []byte{26, 10, 10, 5, 115, 116, 97, 107, 101, 18, 1, 48}, + } + msgs := make([]bindings.ProtobufAny, 0, numMsgs) + for i := 0; i < numMsgs; i++ { + msgs = append(msgs, msg) + } + result, err := json.Marshal(struct { + SubmitTx bindings.SubmitTx `json:"submit_tx"` + }{ + SubmitTx: bindings.SubmitTx{ + ConnectionId: path.EndpointA.ConnectionID, + InterchainAccountId: "0", + Msgs: msgs, + Memo: "Jimmy", + Timeout: 2000, + Fee: feetypes.Fee{ + RecvFee: sdk.NewCoins(), + AckFee: sdk.NewCoins(sdk.NewCoin(params.DefaultBondDenom, math.NewInt(1000))), + TimeoutFee: sdk.NewCoins(sdk.NewCoin(params.DefaultBondDenom, math.NewInt(1000))), + }, + }, + }) + suite.NoError(err) + return +} + +func (suite *CustomMessengerTestSuite) executeCustomMsg(contractAddress sdk.AccAddress, fullMsg json.RawMessage) (data []byte, err error) { + customMsg := types.CosmosMsg{ + Custom: fullMsg, + } + + type ExecuteMsg struct { + ReflectMsg struct { + Msgs []types.CosmosMsg `json:"msgs"` + } `json:"reflect_msg"` + } + + execMsg := ExecuteMsg{ReflectMsg: struct { + Msgs []types.CosmosMsg `json:"msgs"` + }(struct{ Msgs []types.CosmosMsg }{Msgs: []types.CosmosMsg{customMsg}})} + + msg, err := json.Marshal(execMsg) + suite.NoError(err) + + data, err = suite.contractKeeper.Execute(suite.ctx, contractAddress, suite.contractOwner, msg, nil) + + return +} + +func (suite *CustomMessengerTestSuite) executeNolusMsg(contractAddress sdk.AccAddress, fullMsg bindings.NolusMsg) (data []byte, err error) { + fullMsgBz, err := json.Marshal(fullMsg) + suite.NoError(err) + + return suite.executeCustomMsg(contractAddress, fullMsgBz) +} + +func TestMessengerTestSuite(t *testing.T) { + suite.Run(t, new(CustomMessengerTestSuite)) +}