diff --git a/.github/mergify.yml b/.github/mergify.yml index 83b6f2d771c..70c3828d03f 100644 --- a/.github/mergify.yml +++ b/.github/mergify.yml @@ -26,7 +26,7 @@ pull_request_rules: backport: branches: - release/v1.1.x - - name: backport patches to v1.2x branch + - name: backport patches to v1.2.x branch conditions: - base=main - label=backport-to-v1.2.x @@ -34,6 +34,22 @@ pull_request_rules: backport: branches: - release/v1.2.x + - name: backport patches to v1.3.x branch + conditions: + - base=main + - label=backport-to-v1.3.x + actions: + backport: + branches: + - release/v1.3.x + - name: backport patches to v1.4.x branch + conditions: + - base=main + - label=backport-to-v1.4.x + actions: + backport: + branches: + - release/v1.4.x - name: backport patches to v2.0.x branch conditions: - base=main @@ -42,6 +58,22 @@ pull_request_rules: backport: branches: - release/v2.0.x + - name: backport patches to v2.1.x branch + conditions: + - base=main + - label=backport-to-v2.1.x + actions: + backport: + branches: + - release/v2.1.x + - name: backport patches to v2.2.x branch + conditions: + - base=main + - label=backport-to-v2.2.x + actions: + backport: + branches: + - release/v2.2.x - name: backport patches to v3.0.x branch conditions: - base=main @@ -49,4 +81,4 @@ pull_request_rules: actions: backport: branches: - - release/v3.0.x \ No newline at end of file + - release/v3.0.x diff --git a/.github/workflows/check-docs.yml b/.github/workflows/check-docs.yml index abcaa066e2d..0060623ba15 100644 --- a/.github/workflows/check-docs.yml +++ b/.github/workflows/check-docs.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout 🛎️ - uses: actions/checkout@v2.4.0 + uses: actions/checkout@v3 with: persist-credentials: false fetch-depth: 0 diff --git a/.github/workflows/link-check.yml b/.github/workflows/link-check.yml index d40882e4fde..fdf8b184259 100644 --- a/.github/workflows/link-check.yml +++ b/.github/workflows/link-check.yml @@ -4,7 +4,7 @@ jobs: markdown-link-check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2.4.0 + - uses: actions/checkout@v3 - uses: gaurav-nelson/github-action-markdown-link-check@v1 with: config-file: '.github/workflows/link-check-config.json' \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a1a1da8a340..ffffe3a4dae 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2.4.0 + uses: actions/checkout@v3 with: fetch-depth: 0 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 585a3653270..fdcc086ae4f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -37,7 +37,7 @@ jobs: matrix: go-arch: ["amd64", "arm", "arm64"] steps: - - uses: actions/checkout@v2.4.0 + - uses: actions/checkout@v3 - uses: actions/setup-go@v2.1.5 with: go-version: 1.17 @@ -54,7 +54,7 @@ jobs: split-test-files: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2.4.0 + - uses: actions/checkout@v3 - name: Create a file with all the pkgs run: go list ./... > pkgs.txt - name: Split pkgs into 4 files @@ -85,7 +85,7 @@ jobs: matrix: part: ["00", "01", "02", "03"] steps: - - uses: actions/checkout@v2.4.0 + - uses: actions/checkout@v3 - uses: actions/setup-go@v2.1.5 with: go-version: 1.17 @@ -112,7 +112,7 @@ jobs: runs-on: ubuntu-latest needs: tests steps: - - uses: actions/checkout@v2.4.0 + - uses: actions/checkout@v3 - uses: technote-space/get-diff-action@v6.0.1 with: PATTERNS: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 18f8c23903c..66296a985a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,10 +39,13 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Dependencies * [\#404](https://github.com/cosmos/ibc-go/pull/404) Bump Go version to 1.17 +* [\#851](https://github.com/cosmos/ibc-go/pull/851) Bump SDK version to v0.45.1 +* [\#948](https://github.com/cosmos/ibc-go/pull/948) Bump ics23/go to v0.7 * (core) [\#709](https://github.com/cosmos/ibc-go/pull/709) Replace github.com/pkg/errors with stdlib errors ### API Breaking - +* (testing) [\#939](https://github.com/cosmos/ibc-go/pull/939) Support custom power reduction for testing. +* (modules/core/05-port) [\#1086](https://github.com/cosmos/ibc-go/pull/1086) Added `counterpartyChannelID` argument to IBCModule.OnChanOpenAck * (06-solomachine) [\#1100](https://github.com/cosmos/ibc-go/pull/1100) Remove `GetClientID` function from 06-solomachine `Misbehaviour` type. * (06-solomachine) [\#1100](https://github.com/cosmos/ibc-go/pull/1100) Deprecate `ClientId` field in 06-solomachine `Misbehaviour` type. * (07-tendermint) [\#1097](https://github.com/cosmos/ibc-go/pull/1097) Remove `GetClientID` function from 07-tendermint `Misbehaviour` type. @@ -57,7 +60,9 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (modules/core/02-client) [\#536](https://github.com/cosmos/ibc-go/pull/536) `GetSelfConsensusState` return type changed from bool to error. * (channel) [\#644](https://github.com/cosmos/ibc-go/pull/644) Removes `CounterpartyHops` function from the ChannelKeeper. * (testing) [\#776](https://github.com/cosmos/ibc-go/pull/776) Adding helper fn to generate capability name for testing callbacks +* (testing) [\#892](https://github.com/cosmos/ibc-go/pull/892) IBC Mock modules store the scoped keeper and portID within the IBCMockApp. They also maintain reference to the AppModule to update the AppModule's list of IBC applications it references. Allows for the mock module to be reused as a base application in middleware stacks. * (channel) [\#882](https://github.com/cosmos/ibc-go/pull/882) The `WriteAcknowledgement` API now takes `exported.Acknowledgement` instead of a byte array +* (modules/core/ante) [\#950](https://github.com/cosmos/ibc-go/pull/950) Replaces the channel keeper with the IBC keeper in the IBC `AnteDecorator` in order to execute the entire message and be able to reject redundant messages that are in the same block as the non-redundant messages. ### State Machine Breaking @@ -65,13 +70,17 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* (interchain-accounts) [\#1037](https://github.com/cosmos/ibc-go/pull/1037) Add a function `InitModule` to the interchain accounts `AppModule`. This function should be called within the upgrade handler when adding the interchain accounts module to a chain. It should be called in place of InitGenesis (set the consensus version in the version map). +* (testing) [\#942](https://github.com/cosmos/ibc-go/pull/942) `NewTestChain` will create 4 validators in validator set by default. A new constructor function `NewTestChainWithValSet` is provided for test writers who want custom control over the validator set of test chains. +* (testing) [\#904](https://github.com/cosmos/ibc-go/pull/904) Add `ParsePacketFromEvents` function to the testing package. Useful when sending/relaying packets via the testing package. +* (testing) [\#893](https://github.com/cosmos/ibc-go/pull/893) Support custom private keys for testing. * (testing) [\#810](https://github.com/cosmos/ibc-go/pull/810) Additional testing function added to `Endpoint` type called `RecvPacketWithResult`. Performs the same functionality as the existing `RecvPacket` function but also returns the message result. `path.RelayPacket` no longer uses the provided acknowledgement argument and instead obtains the acknowledgement via MsgRecvPacket events. * (connection) [\#721](https://github.com/cosmos/ibc-go/pull/721) Simplify connection handshake error messages when unpacking client state. * (channel) [\#692](https://github.com/cosmos/ibc-go/pull/692) Minimize channel logging by only emitting the packet sequence, source port/channel, destination port/channel upon packet receives, acknowledgements and timeouts. * [\#383](https://github.com/cosmos/ibc-go/pull/383) Adds helper functions for merging and splitting middleware versions from the underlying app version. * (modules/core/05-port) [\#288](https://github.com/cosmos/ibc-go/issues/288) Making the 05-port keeper function IsBound public. The IsBound function checks if the provided portID is already binded to a module. * (channel) [\#644](https://github.com/cosmos/ibc-go/pull/644) Adds `GetChannelConnection` to the ChannelKeeper. This function returns the connectionID and connection state associated with a channel. -* (channel) [\647](https://github.com/cosmos/ibc-go/pull/647) Reorganizes channel handshake handling to set channel state after IBC application callbacks. +* (channel) [\#647](https://github.com/cosmos/ibc-go/pull/647) Reorganizes channel handshake handling to set channel state after IBC application callbacks. * (client) [\#724](https://github.com/cosmos/ibc-go/pull/724) `IsRevisionFormat` and `IsClientIDFormat` have been updated to disallow newlines before the dash used to separate the chainID and revision number, and the client type and client sequence. ### Features @@ -83,6 +92,9 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes * (testing) [\#884](https://github.com/cosmos/ibc-go/pull/884) Add and use in simapp a custom ante handler that rejects redundant transactions +* (transfer) [\#978](https://github.com/cosmos/ibc-go/pull/978) Support base denoms with slashes in denom validation +* (client) [\#941](https://github.com/cosmos/ibc-go/pull/941) Classify client states without consensus states as expired +* (modules/core/04-channel) [\#994](https://github.com/cosmos/ibc-go/pull/944) Call `packet.GetSequence()` rather than passing func in `AcknowledgePacket` log output ## [v2.0.2](https://github.com/cosmos/ibc-go/releases/tag/v2.0.2) - 2021-12-15 diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 8a69e377fe3..8e83c7c7cd3 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -109,37 +109,37 @@ module.exports = { { title: "Interchain Accounts", directory: true, - path: "/app-modules", + path: "/apps", children: [ { title: "Overview", directory: false, - path: "/app-modules/interchain-accounts/overview.html" + path: "/apps/interchain-accounts/overview.html" }, { title: "Authentication Modules", directory: false, - path: "/app-modules/interchain-accounts/auth-modules.html" + path: "/apps/interchain-accounts/auth-modules.html" }, { title: "Active Channels", directory: false, - path: "/app-modules/interchain-accounts/active-channels.html" + path: "/apps/interchain-accounts/active-channels.html" }, { title: "Integration", directory: false, - path: "/app-modules/interchain-accounts/integration.html" + path: "/apps/interchain-accounts/integration.html" }, { title: "Parameters", directory: false, - path: "/app-modules/interchain-accounts/parameters.html" + path: "/apps/interchain-accounts/parameters.html" }, { title: "Transactions", directory: false, - path: "/app-modules/interchain-accounts/transactions.html" + path: "/apps/interchain-accounts/transactions.html" }, ] }, diff --git a/docs/app-modules/interchain-accounts/active-channels.md b/docs/apps/interchain-accounts/active-channels.md similarity index 100% rename from docs/app-modules/interchain-accounts/active-channels.md rename to docs/apps/interchain-accounts/active-channels.md diff --git a/docs/apps/interchain-accounts/audits/Trail of Bits audit - Final Report.pdf b/docs/apps/interchain-accounts/audits/Trail of Bits audit - Final Report.pdf new file mode 100644 index 00000000000..3f6182e4e98 Binary files /dev/null and b/docs/apps/interchain-accounts/audits/Trail of Bits audit - Final Report.pdf differ diff --git a/docs/app-modules/interchain-accounts/auth-modules.md b/docs/apps/interchain-accounts/auth-modules.md similarity index 100% rename from docs/app-modules/interchain-accounts/auth-modules.md rename to docs/apps/interchain-accounts/auth-modules.md diff --git a/docs/app-modules/interchain-accounts/integration.md b/docs/apps/interchain-accounts/integration.md similarity index 100% rename from docs/app-modules/interchain-accounts/integration.md rename to docs/apps/interchain-accounts/integration.md diff --git a/docs/app-modules/interchain-accounts/overview.md b/docs/apps/interchain-accounts/overview.md similarity index 100% rename from docs/app-modules/interchain-accounts/overview.md rename to docs/apps/interchain-accounts/overview.md diff --git a/docs/app-modules/interchain-accounts/parameters.md b/docs/apps/interchain-accounts/parameters.md similarity index 100% rename from docs/app-modules/interchain-accounts/parameters.md rename to docs/apps/interchain-accounts/parameters.md diff --git a/docs/app-modules/interchain-accounts/transactions.md b/docs/apps/interchain-accounts/transactions.md similarity index 100% rename from docs/app-modules/interchain-accounts/transactions.md rename to docs/apps/interchain-accounts/transactions.md diff --git a/docs/ibc/integration.md b/docs/ibc/integration.md index f823ffe07e4..09c1d2d2de9 100644 --- a/docs/ibc/integration.md +++ b/docs/ibc/integration.md @@ -92,13 +92,13 @@ func NewApp(...args) *App { // Create IBC Keeper app.IBCKeeper = ibckeeper.NewKeeper( - appCodec, keys[ibchost.StoreKey], app.StakingKeeper, scopedIBCKeeper, + appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, app.UpgradeKeeper, scopedIBCKeeper, ) // Create Transfer Keepers app.TransferKeeper = ibctransferkeeper.NewKeeper( - appCodec, keys[ibctransfertypes.StoreKey], - app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, + appCodec, keys[ibctransfertypes.StoreKey], app.GetSubspace(ibctransfertypes.ModuleName), + app.IBCKeeper.ChannelKeeper, app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, app.AccountKeeper, app.BankKeeper, scopedTransferKeeper, ) transferModule := transfer.NewAppModule(app.TransferKeeper) diff --git a/docs/ibc/proto-docs.md b/docs/ibc/proto-docs.md index cedc9fac02e..569289dc01f 100644 --- a/docs/ibc/proto-docs.md +++ b/docs/ibc/proto-docs.md @@ -127,6 +127,8 @@ - [MsgTimeoutOnCloseResponse](#ibc.core.channel.v1.MsgTimeoutOnCloseResponse) - [MsgTimeoutResponse](#ibc.core.channel.v1.MsgTimeoutResponse) + - [ResponseResultType](#ibc.core.channel.v1.ResponseResultType) + - [Msg](#ibc.core.channel.v1.Msg) - [ibc/core/client/v1/genesis.proto](#ibc/core/client/v1/genesis.proto) @@ -1738,6 +1740,11 @@ MsgAcknowledgement receives incoming IBC acknowledgement MsgAcknowledgementResponse defines the Msg/Acknowledgement response type. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `result` | [ResponseResultType](#ibc.core.channel.v1.ResponseResultType) | | | + + @@ -1954,6 +1961,11 @@ MsgRecvPacket receives incoming IBC packet MsgRecvPacketResponse defines the Msg/RecvPacket response type. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `result` | [ResponseResultType](#ibc.core.channel.v1.ResponseResultType) | | | + + @@ -2003,6 +2015,11 @@ MsgTimeoutOnClose timed-out packet upon counterparty channel closure. MsgTimeoutOnCloseResponse defines the Msg/TimeoutOnClose response type. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `result` | [ResponseResultType](#ibc.core.channel.v1.ResponseResultType) | | | + + @@ -2013,11 +2030,29 @@ MsgTimeoutOnCloseResponse defines the Msg/TimeoutOnClose response type. MsgTimeoutResponse defines the Msg/Timeout response type. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `result` | [ResponseResultType](#ibc.core.channel.v1.ResponseResultType) | | | + + + + + +### ResponseResultType +ResponseResultType defines the possible outcomes of the execution of a message + +| Name | Number | Description | +| ---- | ------ | ----------- | +| RESPONSE_RESULT_UNSPECIFIED | 0 | Default zero value enumeration | +| RESPONSE_RESULT_NOOP | 1 | The message did not call the IBC application callbacks (because, for example, the packet had already been relayed) | +| RESPONSE_RESULT_SUCCESS | 2 | The message was executed successfully | + + diff --git a/docs/ibc/relayer.md b/docs/ibc/relayer.md index c846f2c7320..ce3fabe252d 100644 --- a/docs/ibc/relayer.md +++ b/docs/ibc/relayer.md @@ -27,7 +27,7 @@ a module event emission with the attribute value `ibc_` (02-clien ### Subscribing with Tendermint -Calling the Tendermint RPC method `Subscribe` via [Tendermint's Websocket](https://docs.tendermint.com/master/rpc/) will return events using +Calling the Tendermint RPC method `Subscribe` via [Tendermint's Websocket](https://docs.tendermint.com/v0.35/rpc/) will return events using Tendermint's internal representation of them. Instead of receiving back a list of events as they were emitted, Tendermint will return the type `map[string][]string` which maps a string in the form `.` to `attribute_value`. This causes extraction of the event diff --git a/docs/migrations/v2-to-v3.md b/docs/migrations/v2-to-v3.md index 710e273a954..6b1c61735fc 100644 --- a/docs/migrations/v2-to-v3.md +++ b/docs/migrations/v2-to-v3.md @@ -26,7 +26,98 @@ The ICS4Wrapper should be the IBC Channel Keeper unless ICS 20 is being connecte ### ICS27 ICS27 Interchain Accounts has been added as a supported IBC application of ibc-go. -Please see the [ICS27 documentation](../app-modules/interchain-accounts/overview.md) for more information. +Please see the [ICS27 documentation](../apps/interchain-accounts/overview.md) for more information. + +### Upgrade Proposal + +If the chain will adopt ICS27, it must set the appropriate params during the execution of the upgrade handler in `app.go`: +```go +app.UpgradeKeeper.SetUpgradeHandler("v3", + func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + // set the ICS27 consensus version so InitGenesis is not run + fromVM[icatypes.ModuleName] = icamodule.ConsensusVersion() + + // create ICS27 Controller submodule params + controllerParams := icacontrollertypes.Params{ + ControllerEnabled: true, + } + + // create ICS27 Host submodule params + hostParams := icahosttypes.Params{ + HostEnabled: true, + AllowMessages: []string{"/cosmos.bank.v1beta1.MsgSend", ...}, + } + + // initialize ICS27 module + icamodule.InitModule(ctx, controllerParams, hostParams) + + ... + + return app.mm.RunMigrations(ctx, app.configurator, fromVM) + }) + +``` + +The host and controller submodule params only need to be set if you integrate those submodules. +For example, if a chain chooses not to integrate a controller submodule, it does not need to set the controller params. + +#### Add `StoreUpgrades` for ICS27 module + +For ICS27 it is also necessary to [manually add store upgrades](https://docs.cosmos.network/v0.44/core/upgrade.html#add-storeupgrades-for-new-modules) for the new ICS27 module and then configure the store loader to apply those upgrades in `app.go`: + +```go +if upgradeInfo.Name == "v3" && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) { + storeUpgrades := store.StoreUpgrades{ + Added: []string{icacontrollertypes.StoreKey, icahosttypes.StoreKey}, + } + + app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storeUpgrades)) +} +``` + +This ensures that the new module's stores are added to the multistore before the migrations begin. + +### Genesis migrations + +If the chain will adopt ICS27 and chooses to upgrade via a genesis export, then the ICS27 parameters must be set during genesis migration. + +The migration code required may look like: + +```go + controllerGenesisState := icatypes.DefaultControllerGenesis() + // overwrite parameters as desired + controllerGenesisState.Params = icacontrollertypes.Params{ + ControllerEnabled: true, + } + + hostGenesisState := icatypes.DefaultHostGenesis() + // overwrite parameters as desired + hostGenesisState.Params = icahosttypes.Params{ + HostEnabled: true, + AllowMessages: []string{"/cosmos.bank.v1beta1.MsgSend", ...}, + } + + icaGenesisState := icatypes.NewGenesisState(controllerGenesisState, hostGenesisState) + + // set new ics27 genesis state + appState[icatypes.ModuleName] = clientCtx.JSONCodec.MustMarshalJSON(icaGenesisState) +``` + +### Ante decorator + +The field of type `channelkeeper.Keeper` in the `AnteDecorator` structure has been replaced with a field of type `*keeper.Keeper`: + +```diff +type AnteDecorator struct { +- k channelkeeper.Keeper ++ k *keeper.Keeper +} + +- func NewAnteDecorator(k channelkeeper.Keeper) AnteDecorator { ++ func NewAnteDecorator(k *keeper.Keeper) AnteDecorator { + return AnteDecorator{k: k} +} +``` ## IBC Apps @@ -39,6 +130,10 @@ IBC applications must perform application version negoitation in `OnChanOpenTry` The negotiated application version then must be returned in `OnChanOpenTry` to core IBC. Core IBC will set this version in the TRYOPEN channel. +### `OnChanOpenAck` will take additional `counterpartyChannelID` argument +The `OnChanOpenAck` application callback has been modified. +The arguments now include the counterparty channel id. + ### `NegotiateAppVersion` removed from `IBCModule` interface Previously this logic was handled by the `NegotiateAppVersion` function. @@ -64,6 +159,10 @@ As apart of this release, the mock module now supports middleware testing. Pleas Please review the [mock](../../testing/mock/ibc_module.go) and [transfer](../../modules/apps/transfer/ibc_module.go) modules as examples. Additionally, [simapp](../../testing/simapp/app.go) provides an example of how `IBCModule` types should now be added to the IBC router in favour of `AppModule`. +### IBC testing package + +`TestChain`s are now created with chainID's beginning from an index of 1. Any calls to `GetChainID(0)` will now fail. Please increment all calls to `GetChainID` by 1. + ## Relayers `AppVersion` gRPC has been removed. diff --git a/go.mod b/go.mod index 639c5607ced..eb9dc1a9548 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alp require ( github.com/armon/go-metrics v0.3.10 - github.com/confio/ics23/go v0.6.6 + github.com/confio/ics23/go v0.7.0 github.com/cosmos/cosmos-sdk v0.45.1 github.com/gogo/protobuf v1.3.3 github.com/golang/protobuf v1.5.2 diff --git a/go.sum b/go.sum index 25a2e5dd4c4..5544d71eb5f 100644 --- a/go.sum +++ b/go.sum @@ -184,8 +184,9 @@ github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:z github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coinbase/rosetta-sdk-go v0.7.0 h1:lmTO/JEpCvZgpbkOITL95rA80CPKb5CtMzLaqF2mCNg= github.com/coinbase/rosetta-sdk-go v0.7.0/go.mod h1:7nD3oBPIiHqhRprqvMgPoGxe/nyq3yftRmpsy29coWE= -github.com/confio/ics23/go v0.6.6 h1:pkOy18YxxJ/r0XFDCnrl4Bjv6h4LkBSpLS6F38mrKL8= github.com/confio/ics23/go v0.6.6/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= +github.com/confio/ics23/go v0.7.0 h1:00d2kukk7sPoHWL4zZBZwzxnpA2pec1NPdwbSokJ5w8= +github.com/confio/ics23/go v0.7.0/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6 h1:NmTXa/uVnDyp0TY5MKi197+3HWcnYWfnHGyaFthlnGw= github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= @@ -465,7 +466,6 @@ github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIv github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= -github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= @@ -800,7 +800,6 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= -github.com/sagikazarmark/crypt v0.4.0/go.mod h1:ALv2SRj7GxYV4HO9elxH9nS6M9gW+xDNxqmyJ6RfDFM= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa h1:0U2s5loxrTy6/VgfVoLuVLFJcURKLH49ie0zSch7gh4= github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= @@ -1312,7 +1311,6 @@ google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdr google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw= -google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1425,7 +1423,6 @@ google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg= google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= diff --git a/modules/apps/27-interchain-accounts/controller/ibc_module.go b/modules/apps/27-interchain-accounts/controller/ibc_module.go index 1aa362a4247..c00c9f5d1c2 100644 --- a/modules/apps/27-interchain-accounts/controller/ibc_module.go +++ b/modules/apps/27-interchain-accounts/controller/ibc_module.go @@ -80,6 +80,7 @@ func (im IBCModule) OnChanOpenAck( ctx sdk.Context, portID, channelID string, + counterpartyChannelID string, counterpartyVersion string, ) error { if !im.keeper.IsControllerEnabled(ctx) { @@ -91,7 +92,7 @@ func (im IBCModule) OnChanOpenAck( } // call underlying app's OnChanOpenAck callback with the counterparty app version. - return im.app.OnChanOpenAck(ctx, portID, channelID, counterpartyVersion) + return im.app.OnChanOpenAck(ctx, portID, channelID, counterpartyChannelID, counterpartyVersion) } // OnChanOpenAck implements the IBCModule interface diff --git a/modules/apps/27-interchain-accounts/controller/ibc_module_test.go b/modules/apps/27-interchain-accounts/controller/ibc_module_test.go index f2b5d36ac63..db4412d144e 100644 --- a/modules/apps/27-interchain-accounts/controller/ibc_module_test.go +++ b/modules/apps/27-interchain-accounts/controller/ibc_module_test.go @@ -285,7 +285,7 @@ func (suite *InterchainAccountsTestSuite) TestOnChanOpenAck() { { "ICA auth module callback fails", func() { suite.chainA.GetSimApp().ICAAuthModule.IBCApp.OnChanOpenAck = func( - ctx sdk.Context, portID, channelID string, counterpartyVersion string, + ctx sdk.Context, portID, channelID string, counterpartyChannelID string, counterpartyVersion string, ) error { return fmt.Errorf("mock ica auth fails") } @@ -316,7 +316,7 @@ func (suite *InterchainAccountsTestSuite) TestOnChanOpenAck() { cbs, ok := suite.chainA.App.GetIBCKeeper().Router.GetRoute(module) suite.Require().True(ok) - err = cbs.OnChanOpenAck(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.Version) + err = cbs.OnChanOpenAck(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelID, path.EndpointB.ChannelConfig.Version) if tc.expPass { suite.Require().NoError(err) diff --git a/modules/apps/27-interchain-accounts/host/ibc_module.go b/modules/apps/27-interchain-accounts/host/ibc_module.go index 630c4d44fc1..fb403c71937 100644 --- a/modules/apps/27-interchain-accounts/host/ibc_module.go +++ b/modules/apps/27-interchain-accounts/host/ibc_module.go @@ -61,6 +61,7 @@ func (im IBCModule) OnChanOpenAck( ctx sdk.Context, portID, channelID string, + counterpartyChannelID string, counterpartyVersion string, ) error { return sdkerrors.Wrap(icatypes.ErrInvalidChannelFlow, "channel handshake must be initiated by controller chain") diff --git a/modules/apps/27-interchain-accounts/module.go b/modules/apps/27-interchain-accounts/module.go index b11c611e0c9..969c07caf9d 100644 --- a/modules/apps/27-interchain-accounts/module.go +++ b/modules/apps/27-interchain-accounts/module.go @@ -24,6 +24,7 @@ import ( hosttypes "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/host/types" "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/types" porttypes "github.com/cosmos/ibc-go/v3/modules/core/05-port/types" + ibchost "github.com/cosmos/ibc-go/v3/modules/core/24-host" ) var ( @@ -101,6 +102,18 @@ func NewAppModule(controllerKeeper *controllerkeeper.Keeper, hostKeeper *hostkee } } +// InitModule will initialize the interchain accounts moudule. It should only be +// called once and as an alternative to InitGenesis. +func (am AppModule) InitModule(ctx sdk.Context, controllerParams controllertypes.Params, hostParams hosttypes.Params) { + am.controllerKeeper.SetParams(ctx, controllerParams) + am.hostKeeper.SetParams(ctx, hostParams) + + cap := am.hostKeeper.BindPort(ctx, types.PortID) + if err := am.hostKeeper.ClaimCapability(ctx, cap, ibchost.PortPath(types.PortID)); err != nil { + panic(fmt.Sprintf("could not claim port capability: %v", err)) + } +} + // RegisterInvariants implements the AppModule interface func (AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { } diff --git a/modules/apps/27-interchain-accounts/module_test.go b/modules/apps/27-interchain-accounts/module_test.go new file mode 100644 index 00000000000..de5f51ae921 --- /dev/null +++ b/modules/apps/27-interchain-accounts/module_test.go @@ -0,0 +1,74 @@ +package ica_test + +import ( + "testing" + + "github.com/stretchr/testify/suite" + "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + dbm "github.com/tendermint/tm-db" + + ica "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts" + controllertypes "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/controller/types" + hosttypes "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/host/types" + "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/types" + ibctesting "github.com/cosmos/ibc-go/v3/testing" + "github.com/cosmos/ibc-go/v3/testing/simapp" +) + +type InterchainAccountsTestSuite struct { + suite.Suite + + coordinator *ibctesting.Coordinator +} + +func TestICATestSuite(t *testing.T) { + suite.Run(t, new(InterchainAccountsTestSuite)) +} + +func (suite *InterchainAccountsTestSuite) SetupTest() { + suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2) +} + +func (suite *InterchainAccountsTestSuite) TestInitModule() { + app := simapp.NewSimApp(log.NewNopLogger(), dbm.NewMemDB(), nil, true, map[int64]bool{}, simapp.DefaultNodeHome, 5, simapp.MakeTestEncodingConfig(), simapp.EmptyAppOptions{}) + icamodule, ok := app.GetModuleManager().Modules[types.ModuleName].(ica.AppModule) + suite.Require().True(ok) + + header := tmproto.Header{ + ChainID: "testchain", + Height: 1, + Time: suite.coordinator.CurrentTime.UTC(), + } + + ctx := app.GetBaseApp().NewContext(true, header) + + // ensure params are not set + suite.Require().Panics(func() { + app.ICAControllerKeeper.GetParams(ctx) + }) + suite.Require().Panics(func() { + app.ICAHostKeeper.GetParams(ctx) + }) + + controllerParams := controllertypes.DefaultParams() + controllerParams.ControllerEnabled = true + + hostParams := hosttypes.DefaultParams() + expAllowMessages := []string{"sdk.Msg"} + hostParams.HostEnabled = true + hostParams.AllowMessages = expAllowMessages + + suite.Require().False(app.IBCKeeper.PortKeeper.IsBound(ctx, types.PortID)) + + icamodule.InitModule(ctx, controllerParams, hostParams) + + controllerParams = app.ICAControllerKeeper.GetParams(ctx) + suite.Require().True(controllerParams.ControllerEnabled) + + hostParams = app.ICAHostKeeper.GetParams(ctx) + suite.Require().True(hostParams.HostEnabled) + suite.Require().Equal(expAllowMessages, hostParams.AllowMessages) + + suite.Require().True(app.IBCKeeper.PortKeeper.IsBound(ctx, types.PortID)) +} diff --git a/modules/apps/transfer/ibc_module.go b/modules/apps/transfer/ibc_module.go index 26f1c533434..f5ed807d8b2 100644 --- a/modules/apps/transfer/ibc_module.go +++ b/modules/apps/transfer/ibc_module.go @@ -125,6 +125,7 @@ func (im IBCModule) OnChanOpenAck( ctx sdk.Context, portID, channelID string, + _ string, counterpartyVersion string, ) error { if counterpartyVersion != types.Version { @@ -162,7 +163,7 @@ func (im IBCModule) OnChanCloseConfirm( } // OnRecvPacket implements the IBCModule interface. A successful acknowledgement -// is returned if the packet data is succesfully decoded and the receive application +// is returned if the packet data is successfully decoded and the receive application // logic returns without error. func (im IBCModule) OnRecvPacket( ctx sdk.Context, diff --git a/modules/apps/transfer/ibc_module_test.go b/modules/apps/transfer/ibc_module_test.go index b5f834a3a8e..92d0f30d4c7 100644 --- a/modules/apps/transfer/ibc_module_test.go +++ b/modules/apps/transfer/ibc_module_test.go @@ -228,7 +228,7 @@ func (suite *TransferTestSuite) TestOnChanOpenAck() { tc.malleate() // explicitly change fields in channel and testChannel - err = cbs.OnChanOpenAck(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, counterpartyVersion) + err = cbs.OnChanOpenAck(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointA.Counterparty.ChannelID, counterpartyVersion) if tc.expPass { suite.Require().NoError(err) diff --git a/modules/apps/transfer/keeper/relay_test.go b/modules/apps/transfer/keeper/relay_test.go index 8e77c73db9e..9d03bbde962 100644 --- a/modules/apps/transfer/keeper/relay_test.go +++ b/modules/apps/transfer/keeper/relay_test.go @@ -186,12 +186,12 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() { // send coin from chainB to chainA, receive them, acknowledge them, and send back to chainB coinFromBToA := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)) transferMsg := types.NewMsgTransfer(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, coinFromBToA, suite.chainB.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String(), clienttypes.NewHeight(0, 110), 0) - _, err := suite.chainB.SendMsgs(transferMsg) + res, err := suite.chainB.SendMsgs(transferMsg) suite.Require().NoError(err) // message committed - // relay send packet - fungibleTokenPacket := types.NewFungibleTokenPacketData(coinFromBToA.Denom, coinFromBToA.Amount.String(), suite.chainB.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String()) - packet := channeltypes.NewPacket(fungibleTokenPacket.GetBytes(), 1, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, clienttypes.NewHeight(0, 110), 0) + packet, err := ibctesting.ParsePacketFromEvents(res.GetEvents()) + suite.Require().NoError(err) + err = path.RelayPacket(packet) suite.Require().NoError(err) // relay committed diff --git a/modules/apps/transfer/transfer_test.go b/modules/apps/transfer/transfer_test.go index ec36af78ceb..5190cdc8d29 100644 --- a/modules/apps/transfer/transfer_test.go +++ b/modules/apps/transfer/transfer_test.go @@ -8,7 +8,6 @@ import ( "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" - channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" ibctesting "github.com/cosmos/ibc-go/v3/testing" ) @@ -56,13 +55,13 @@ func (suite *TransferTestSuite) TestHandleMsgTransfer() { // send from chainA to chainB msg := types.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, coinToSendToB, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), timeoutHeight, 0) - - _, err := suite.chainA.SendMsgs(msg) + res, err := suite.chainA.SendMsgs(msg) suite.Require().NoError(err) // message committed + packet, err := ibctesting.ParsePacketFromEvents(res.GetEvents()) + suite.Require().NoError(err) + // relay send - fungibleTokenPacket := types.NewFungibleTokenPacketData(coinToSendToB.Denom, coinToSendToB.Amount.String(), suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String()) - packet := channeltypes.NewPacket(fungibleTokenPacket.GetBytes(), 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0) err = path.RelayPacket(packet) suite.Require().NoError(err) // relay committed @@ -82,18 +81,18 @@ func (suite *TransferTestSuite) TestHandleMsgTransfer() { // send from chainB to chainC msg = types.NewMsgTransfer(pathBtoC.EndpointA.ChannelConfig.PortID, pathBtoC.EndpointA.ChannelID, coinSentFromAToB, suite.chainB.SenderAccount.GetAddress().String(), suite.chainC.SenderAccount.GetAddress().String(), timeoutHeight, 0) - - _, err = suite.chainB.SendMsgs(msg) + res, err = suite.chainB.SendMsgs(msg) suite.Require().NoError(err) // message committed - // relay send - // NOTE: fungible token is prefixed with the full trace in order to verify the packet commitment - fullDenomPath := types.GetPrefixedDenom(pathBtoC.EndpointB.ChannelConfig.PortID, pathBtoC.EndpointB.ChannelID, voucherDenomTrace.GetFullDenomPath()) - fungibleTokenPacket = types.NewFungibleTokenPacketData(voucherDenomTrace.GetFullDenomPath(), coinSentFromAToB.Amount.String(), suite.chainB.SenderAccount.GetAddress().String(), suite.chainC.SenderAccount.GetAddress().String()) - packet = channeltypes.NewPacket(fungibleTokenPacket.GetBytes(), 1, pathBtoC.EndpointA.ChannelConfig.PortID, pathBtoC.EndpointA.ChannelID, pathBtoC.EndpointB.ChannelConfig.PortID, pathBtoC.EndpointB.ChannelID, timeoutHeight, 0) + packet, err = ibctesting.ParsePacketFromEvents(res.GetEvents()) + suite.Require().NoError(err) + err = pathBtoC.RelayPacket(packet) suite.Require().NoError(err) // relay committed + // NOTE: fungible token is prefixed with the full trace in order to verify the packet commitment + fullDenomPath := types.GetPrefixedDenom(pathBtoC.EndpointB.ChannelConfig.PortID, pathBtoC.EndpointB.ChannelID, voucherDenomTrace.GetFullDenomPath()) + coinSentFromBToC := sdk.NewCoin(types.ParseDenomTrace(fullDenomPath).IBCDenom(), amount) balance = suite.chainC.GetSimApp().BankKeeper.GetBalance(suite.chainC.GetContext(), suite.chainC.SenderAccount.GetAddress(), coinSentFromBToC.Denom) @@ -106,14 +105,12 @@ func (suite *TransferTestSuite) TestHandleMsgTransfer() { // send from chainC back to chainB msg = types.NewMsgTransfer(pathBtoC.EndpointB.ChannelConfig.PortID, pathBtoC.EndpointB.ChannelID, coinSentFromBToC, suite.chainC.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), timeoutHeight, 0) - - _, err = suite.chainC.SendMsgs(msg) + res, err = suite.chainC.SendMsgs(msg) suite.Require().NoError(err) // message committed - // relay send - // NOTE: fungible token is prefixed with the full trace in order to verify the packet commitment - fungibleTokenPacket = types.NewFungibleTokenPacketData(fullDenomPath, coinSentFromBToC.Amount.String(), suite.chainC.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String()) - packet = channeltypes.NewPacket(fungibleTokenPacket.GetBytes(), 1, pathBtoC.EndpointB.ChannelConfig.PortID, pathBtoC.EndpointB.ChannelID, pathBtoC.EndpointA.ChannelConfig.PortID, pathBtoC.EndpointA.ChannelID, timeoutHeight, 0) + packet, err = ibctesting.ParsePacketFromEvents(res.GetEvents()) + suite.Require().NoError(err) + err = pathBtoC.RelayPacket(packet) suite.Require().NoError(err) // relay committed diff --git a/modules/apps/transfer/types/ack_test.go b/modules/apps/transfer/types/ack_test.go index bc4e2d07afc..4f4c3a874d7 100644 --- a/modules/apps/transfer/types/ack_test.go +++ b/modules/apps/transfer/types/ack_test.go @@ -9,7 +9,7 @@ import ( tmprotostate "github.com/tendermint/tendermint/proto/tendermint/state" tmstate "github.com/tendermint/tendermint/state" - "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/host/types" + "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" ibctesting "github.com/cosmos/ibc-go/v3/testing" ) diff --git a/modules/apps/transfer/types/msgs_test.go b/modules/apps/transfer/types/msgs_test.go index 5cf074a6d8d..00570ac15ed 100644 --- a/modules/apps/transfer/types/msgs_test.go +++ b/modules/apps/transfer/types/msgs_test.go @@ -32,7 +32,7 @@ var ( coin = sdk.NewCoin("atom", sdk.NewInt(100)) ibcCoin = sdk.NewCoin("ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2", sdk.NewInt(100)) - invalidIBCCoin = sdk.NewCoin("notibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2", sdk.NewInt(100)) + invalidIBCCoin = sdk.NewCoin("ibc/7F1D3FCF4AE79E1554", sdk.NewInt(100)) invalidDenomCoin = sdk.Coin{Denom: "0atom", Amount: sdk.NewInt(100)} zeroCoin = sdk.Coin{Denom: "atoms", Amount: sdk.NewInt(0)} diff --git a/modules/apps/transfer/types/trace.go b/modules/apps/transfer/types/trace.go index 6bbbbadfc23..303ddd3769e 100644 --- a/modules/apps/transfer/types/trace.go +++ b/modules/apps/transfer/types/trace.go @@ -162,7 +162,7 @@ func ValidatePrefixedDenom(denom string) error { // ValidateIBCDenom validates that the given denomination is either: // -// - A valid base denomination (eg: 'uatom') +// - A valid base denomination (eg: 'uatom' or 'gamm/pool/1' as in https://github.com/cosmos/ibc-go/issues/894) // - A valid fungible token representation (i.e 'ibc/{hash}') per ADR 001 https://github.com/cosmos/ibc-go/blob/main/docs/architecture/adr-001-coin-source-tracing.md func ValidateIBCDenom(denom string) error { if err := sdk.ValidateDenom(denom); err != nil { @@ -172,17 +172,17 @@ func ValidateIBCDenom(denom string) error { denomSplit := strings.SplitN(denom, "/", 2) switch { - case strings.TrimSpace(denom) == "", - len(denomSplit) == 1 && denomSplit[0] == DenomPrefix, - len(denomSplit) == 2 && (denomSplit[0] != DenomPrefix || strings.TrimSpace(denomSplit[1]) == ""): + case denom == DenomPrefix: return sdkerrors.Wrapf(ErrInvalidDenomForTransfer, "denomination should be prefixed with the format 'ibc/{hash(trace + \"/\" + %s)}'", denom) - case denomSplit[0] == denom && strings.TrimSpace(denom) != "": - return nil - } + case len(denomSplit) == 2 && denomSplit[0] == DenomPrefix: + if strings.TrimSpace(denomSplit[1]) == "" { + return sdkerrors.Wrapf(ErrInvalidDenomForTransfer, "denomination should be prefixed with the format 'ibc/{hash(trace + \"/\" + %s)}'", denom) + } - if _, err := ParseHexHash(denomSplit[1]); err != nil { - return sdkerrors.Wrapf(err, "invalid denom trace hash %s", denomSplit[1]) + if _, err := ParseHexHash(denomSplit[1]); err != nil { + return sdkerrors.Wrapf(err, "invalid denom trace hash %s", denomSplit[1]) + } } return nil diff --git a/modules/apps/transfer/types/trace_test.go b/modules/apps/transfer/types/trace_test.go index f0868d5680e..e35fd33317b 100644 --- a/modules/apps/transfer/types/trace_test.go +++ b/modules/apps/transfer/types/trace_test.go @@ -131,11 +131,12 @@ func TestValidateIBCDenom(t *testing.T) { }{ {"denom with trace hash", "ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2", false}, {"base denom", "uatom", false}, + {"base denom with single '/'s", "gamm/pool/1", false}, + {"base denom with double '/'s", "gamm//pool//1", false}, + {"non-ibc prefix with hash", "notibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2", false}, {"empty denom", "", true}, - {"invalid prefixed denom", "transfer/channelToA/uatom", true}, {"denom 'ibc'", "ibc", true}, {"denom 'ibc/'", "ibc/", true}, - {"invald prefix", "notibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2", true}, {"invald hash", "ibc/!@#$!@#", true}, } diff --git a/modules/core/02-client/keeper/grpc_query_test.go b/modules/core/02-client/keeper/grpc_query_test.go index f4fa3c59322..5e393c33a97 100644 --- a/modules/core/02-client/keeper/grpc_query_test.go +++ b/modules/core/02-client/keeper/grpc_query_test.go @@ -452,7 +452,7 @@ func (suite *KeeperTestSuite) TestQueryClientStatus() { ClientId: path.EndpointA.ClientID, } }, - true, exported.Unknown.String(), + true, exported.Expired.String(), }, { "Frozen client status", diff --git a/modules/core/04-channel/keeper/keeper.go b/modules/core/04-channel/keeper/keeper.go index d1ea53ac180..65378039ad9 100644 --- a/modules/core/04-channel/keeper/keeper.go +++ b/modules/core/04-channel/keeper/keeper.go @@ -403,7 +403,7 @@ func (k Keeper) GetChannelClientState(ctx sdk.Context, portID, channelID string) return connection.ClientId, clientState, nil } -// GetConnection wraps the conenction keeper's GetConnection function. +// GetConnection wraps the connection keeper's GetConnection function. func (k Keeper) GetConnection(ctx sdk.Context, connectionID string) (exported.ConnectionI, error) { connection, found := k.connectionKeeper.GetConnection(ctx, connectionID) if !found { diff --git a/modules/core/04-channel/keeper/packet.go b/modules/core/04-channel/keeper/packet.go index 5879c9ecb08..b54926b85e9 100644 --- a/modules/core/04-channel/keeper/packet.go +++ b/modules/core/04-channel/keeper/packet.go @@ -494,7 +494,7 @@ func (k Keeper) AcknowledgePacket( // log that a packet has been acknowledged k.Logger(ctx).Info( "packet acknowledged", - "sequence", packet.GetSequence, + "sequence", packet.GetSequence(), "src_port", packet.GetSourcePort(), "src_channel", packet.GetSourceChannel(), "dst_port", packet.GetDestPort(), diff --git a/modules/core/04-channel/types/tx.pb.go b/modules/core/04-channel/types/tx.pb.go index 6fcc1a44276..e497cf802b1 100644 --- a/modules/core/04-channel/types/tx.pb.go +++ b/modules/core/04-channel/types/tx.pb.go @@ -29,6 +29,38 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// ResponseResultType defines the possible outcomes of the execution of a message +type ResponseResultType int32 + +const ( + // Default zero value enumeration + UNSPECIFIED ResponseResultType = 0 + // The message did not call the IBC application callbacks (because, for example, the packet had already been relayed) + NOOP ResponseResultType = 1 + // The message was executed successfully + SUCCESS ResponseResultType = 2 +) + +var ResponseResultType_name = map[int32]string{ + 0: "RESPONSE_RESULT_UNSPECIFIED", + 1: "RESPONSE_RESULT_NOOP", + 2: "RESPONSE_RESULT_SUCCESS", +} + +var ResponseResultType_value = map[string]int32{ + "RESPONSE_RESULT_UNSPECIFIED": 0, + "RESPONSE_RESULT_NOOP": 1, + "RESPONSE_RESULT_SUCCESS": 2, +} + +func (x ResponseResultType) String() string { + return proto.EnumName(ResponseResultType_name, int32(x)) +} + +func (ResponseResultType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_bc4637e0ac3fc7b7, []int{0} +} + // MsgChannelOpenInit defines an sdk.Msg to initialize a channel handshake. It // is called by a relayer on Chain A. type MsgChannelOpenInit struct { @@ -566,6 +598,7 @@ var xxx_messageInfo_MsgRecvPacket proto.InternalMessageInfo // MsgRecvPacketResponse defines the Msg/RecvPacket response type. type MsgRecvPacketResponse struct { + Result ResponseResultType `protobuf:"varint,1,opt,name=result,proto3,enum=ibc.core.channel.v1.ResponseResultType" json:"result,omitempty"` } func (m *MsgRecvPacketResponse) Reset() { *m = MsgRecvPacketResponse{} } @@ -645,6 +678,7 @@ var xxx_messageInfo_MsgTimeout proto.InternalMessageInfo // MsgTimeoutResponse defines the Msg/Timeout response type. type MsgTimeoutResponse struct { + Result ResponseResultType `protobuf:"varint,1,opt,name=result,proto3,enum=ibc.core.channel.v1.ResponseResultType" json:"result,omitempty"` } func (m *MsgTimeoutResponse) Reset() { *m = MsgTimeoutResponse{} } @@ -725,6 +759,7 @@ var xxx_messageInfo_MsgTimeoutOnClose proto.InternalMessageInfo // MsgTimeoutOnCloseResponse defines the Msg/TimeoutOnClose response type. type MsgTimeoutOnCloseResponse struct { + Result ResponseResultType `protobuf:"varint,1,opt,name=result,proto3,enum=ibc.core.channel.v1.ResponseResultType" json:"result,omitempty"` } func (m *MsgTimeoutOnCloseResponse) Reset() { *m = MsgTimeoutOnCloseResponse{} } @@ -804,6 +839,7 @@ var xxx_messageInfo_MsgAcknowledgement proto.InternalMessageInfo // MsgAcknowledgementResponse defines the Msg/Acknowledgement response type. type MsgAcknowledgementResponse struct { + Result ResponseResultType `protobuf:"varint,1,opt,name=result,proto3,enum=ibc.core.channel.v1.ResponseResultType" json:"result,omitempty"` } func (m *MsgAcknowledgementResponse) Reset() { *m = MsgAcknowledgementResponse{} } @@ -840,6 +876,7 @@ func (m *MsgAcknowledgementResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgAcknowledgementResponse proto.InternalMessageInfo func init() { + proto.RegisterEnum("ibc.core.channel.v1.ResponseResultType", ResponseResultType_name, ResponseResultType_value) proto.RegisterType((*MsgChannelOpenInit)(nil), "ibc.core.channel.v1.MsgChannelOpenInit") proto.RegisterType((*MsgChannelOpenInitResponse)(nil), "ibc.core.channel.v1.MsgChannelOpenInitResponse") proto.RegisterType((*MsgChannelOpenTry)(nil), "ibc.core.channel.v1.MsgChannelOpenTry") @@ -865,79 +902,87 @@ func init() { func init() { proto.RegisterFile("ibc/core/channel/v1/tx.proto", fileDescriptor_bc4637e0ac3fc7b7) } var fileDescriptor_bc4637e0ac3fc7b7 = []byte{ - // 1138 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x58, 0x4d, 0x6f, 0xdb, 0x46, - 0x13, 0xd6, 0x87, 0x2d, 0xdb, 0x63, 0xbf, 0xb1, 0x4d, 0xf9, 0x43, 0xa1, 0x6c, 0xd1, 0x2f, 0x0f, - 0x89, 0x91, 0x22, 0x62, 0x6c, 0x07, 0x28, 0x12, 0xf4, 0x62, 0x09, 0x28, 0x6a, 0x14, 0x6e, 0x0a, - 0xda, 0xed, 0xc1, 0x28, 0x20, 0x48, 0xab, 0x0d, 0x45, 0x48, 0xe2, 0xaa, 0x24, 0xa5, 0x44, 0xff, - 0xa0, 0xc7, 0x9c, 0x7b, 0x4a, 0xcf, 0x3d, 0xa4, 0x3f, 0x23, 0xc7, 0x9c, 0xda, 0xa2, 0x07, 0xa2, - 0xb0, 0x2f, 0x3d, 0xf3, 0x17, 0x14, 0x5c, 0x2e, 0x3f, 0x24, 0x91, 0x15, 0x95, 0x54, 0x6e, 0x6e, - 0xe4, 0xcc, 0xb3, 0xb3, 0xb3, 0xcf, 0x33, 0x9c, 0xdd, 0x25, 0xec, 0xa9, 0x0d, 0x24, 0x21, 0xa2, - 0x63, 0x09, 0xb5, 0xea, 0x9a, 0x86, 0x3b, 0xd2, 0xe0, 0x48, 0x32, 0x5f, 0x96, 0x7b, 0x3a, 0x31, - 0x09, 0x97, 0x57, 0x1b, 0xa8, 0xec, 0x78, 0xcb, 0xcc, 0x5b, 0x1e, 0x1c, 0xf1, 0x5b, 0x0a, 0x51, - 0x08, 0xf5, 0x4b, 0xce, 0x93, 0x0b, 0xe5, 0x85, 0x20, 0x50, 0x47, 0xc5, 0x9a, 0xe9, 0xc4, 0x71, - 0x9f, 0x18, 0xe0, 0xff, 0x51, 0x33, 0x79, 0x61, 0x29, 0x44, 0xfc, 0x29, 0x0d, 0xdc, 0xb9, 0xa1, - 0x54, 0x5d, 0xe3, 0xb3, 0x1e, 0xd6, 0xce, 0x34, 0xd5, 0xe4, 0x3e, 0x81, 0xa5, 0x1e, 0xd1, 0xcd, - 0x9a, 0xda, 0x2c, 0xa4, 0x0f, 0xd2, 0x87, 0x2b, 0x15, 0xce, 0xb6, 0x84, 0x3b, 0xc3, 0x7a, 0xb7, - 0xf3, 0x54, 0x64, 0x0e, 0x51, 0xce, 0x39, 0x4f, 0x67, 0x4d, 0xee, 0x33, 0x58, 0x62, 0x41, 0x0b, - 0x99, 0x83, 0xf4, 0xe1, 0xea, 0xf1, 0x5e, 0x39, 0x62, 0x11, 0x65, 0x36, 0x47, 0x65, 0xe1, 0xad, - 0x25, 0xa4, 0x64, 0x6f, 0x08, 0xb7, 0x03, 0x39, 0x43, 0x55, 0x34, 0xac, 0x17, 0xb2, 0xce, 0x4c, - 0x32, 0x7b, 0x7b, 0xba, 0xfc, 0xc3, 0x6b, 0x21, 0xf5, 0xd7, 0x6b, 0x21, 0x25, 0xca, 0xc0, 0x4f, - 0xa6, 0x28, 0x63, 0xa3, 0x47, 0x34, 0x03, 0x73, 0x8f, 0x01, 0x58, 0xa8, 0x20, 0xdb, 0x6d, 0xdb, - 0x12, 0x36, 0xdd, 0x6c, 0x03, 0x9f, 0x28, 0xaf, 0xb0, 0x97, 0xb3, 0xa6, 0xf8, 0x6b, 0x16, 0x36, - 0x47, 0x83, 0x5e, 0xea, 0xc3, 0xd9, 0x96, 0xfd, 0x15, 0xe4, 0x7b, 0x3a, 0x1e, 0xa8, 0xa4, 0x6f, - 0xd4, 0x42, 0x19, 0x64, 0xe8, 0xc0, 0x92, 0x6d, 0x09, 0x3c, 0x1b, 0x38, 0x09, 0x12, 0xe5, 0x4d, - 0xcf, 0x5a, 0xf5, 0x52, 0x0a, 0xd3, 0x98, 0x9d, 0x9d, 0x46, 0x19, 0xb6, 0x10, 0xe9, 0x6b, 0x26, - 0xd6, 0x7b, 0x75, 0xdd, 0x1c, 0xd6, 0x06, 0x58, 0x37, 0x54, 0xa2, 0x15, 0x16, 0x68, 0x3a, 0x82, - 0x6d, 0x09, 0x45, 0x46, 0x48, 0x04, 0x4a, 0x94, 0xf3, 0x61, 0xf3, 0xb7, 0xae, 0xd5, 0xa1, 0xb6, - 0xa7, 0x13, 0xf2, 0xbc, 0xa6, 0x6a, 0xaa, 0x59, 0x58, 0x3c, 0x48, 0x1f, 0xae, 0x85, 0xa9, 0x0d, - 0x7c, 0xa2, 0xbc, 0x42, 0x5f, 0x68, 0xed, 0x5c, 0xc1, 0x9a, 0xeb, 0x69, 0x61, 0x55, 0x69, 0x99, - 0x85, 0x1c, 0x5d, 0x0c, 0x1f, 0x5a, 0x8c, 0x5b, 0xa3, 0x83, 0xa3, 0xf2, 0x17, 0x14, 0x51, 0x29, - 0x3a, 0x4b, 0xb1, 0x2d, 0x21, 0x1f, 0x8e, 0xeb, 0x8e, 0x16, 0xe5, 0x55, 0xfa, 0xea, 0x22, 0x43, - 0xc5, 0xb2, 0x14, 0x53, 0x2c, 0x45, 0xb8, 0x3b, 0xa1, 0xab, 0x57, 0x2b, 0xe2, 0x6f, 0x13, 0xaa, - 0x9f, 0xa2, 0xf6, 0x6c, 0xaa, 0x8f, 0x96, 0x5b, 0x26, 0x59, 0xb9, 0x71, 0x57, 0xb0, 0x3b, 0xc2, - 0x7b, 0x28, 0x04, 0xad, 0xfa, 0x8a, 0x68, 0x5b, 0x42, 0x29, 0x42, 0xa0, 0x70, 0xbc, 0xed, 0xb0, - 0x27, 0xa8, 0x9b, 0x79, 0x28, 0x7f, 0x04, 0xae, 0xa0, 0x35, 0x53, 0x1f, 0x32, 0xe1, 0xb7, 0x6c, - 0x4b, 0xd8, 0x08, 0x0b, 0x64, 0xea, 0x43, 0x51, 0x5e, 0xa6, 0xcf, 0xce, 0xb7, 0xf3, 0x91, 0xc9, - 0x7e, 0x8a, 0xda, 0xbe, 0xec, 0x3f, 0x67, 0x60, 0x7b, 0xd4, 0x5b, 0x25, 0xda, 0x73, 0x55, 0xef, - 0xde, 0x86, 0xf4, 0x3e, 0x95, 0x75, 0xd4, 0xa6, 0x62, 0x47, 0x50, 0x59, 0x47, 0x6d, 0x8f, 0x4a, - 0xa7, 0x20, 0xc7, 0xa9, 0x5c, 0x98, 0x0b, 0x95, 0x8b, 0x31, 0x54, 0x0a, 0xb0, 0x1f, 0x49, 0x96, - 0x4f, 0xe7, 0x8f, 0x69, 0xc8, 0x07, 0x88, 0x6a, 0x87, 0x18, 0x78, 0xf6, 0x4d, 0xe3, 0xfd, 0xc8, - 0x9c, 0xbe, 0x59, 0xec, 0x43, 0x31, 0x22, 0x37, 0x3f, 0xf7, 0x37, 0x19, 0xd8, 0x19, 0xf3, 0xdf, - 0x62, 0x2d, 0x8c, 0x36, 0xd4, 0xec, 0x7b, 0x36, 0xd4, 0xdb, 0x2d, 0x87, 0x03, 0x28, 0x45, 0x13, - 0xe6, 0x73, 0xfa, 0x2a, 0x03, 0xff, 0x3b, 0x37, 0x14, 0x19, 0xa3, 0xc1, 0xd7, 0x75, 0xd4, 0xc6, - 0x26, 0xf7, 0x04, 0x72, 0x3d, 0xfa, 0x44, 0x99, 0x5c, 0x3d, 0x2e, 0x46, 0xee, 0x64, 0x2e, 0x98, - 0x6d, 0x64, 0x6c, 0x00, 0xf7, 0x39, 0x6c, 0xb8, 0xe9, 0x22, 0xd2, 0xed, 0xaa, 0x66, 0x17, 0x6b, - 0x26, 0xa5, 0x77, 0xad, 0x52, 0xb4, 0x2d, 0x61, 0x37, 0xbc, 0xa0, 0x00, 0x21, 0xca, 0xeb, 0xd4, - 0x54, 0xf5, 0x2d, 0x13, 0xa4, 0x65, 0xe7, 0x42, 0xda, 0x42, 0x0c, 0x69, 0xbb, 0xb4, 0xe1, 0x04, - 0x8c, 0xf8, 0x5c, 0xfd, 0x91, 0x01, 0x38, 0x37, 0x94, 0x4b, 0xb5, 0x8b, 0x49, 0xff, 0xdf, 0x21, - 0xaa, 0xaf, 0xe9, 0x18, 0x61, 0x75, 0x80, 0x9b, 0x71, 0x44, 0x05, 0x08, 0x8f, 0xa8, 0x6f, 0x7c, - 0xcb, 0x5c, 0x89, 0xfa, 0x12, 0x38, 0x0d, 0xbf, 0x34, 0x6b, 0x06, 0xfe, 0xbe, 0x8f, 0x35, 0x84, - 0x6b, 0x3a, 0x46, 0x03, 0x4a, 0xda, 0x42, 0x65, 0xdf, 0xb6, 0x84, 0xbb, 0x6e, 0x84, 0x49, 0x8c, - 0x28, 0x6f, 0x38, 0xc6, 0x0b, 0x66, 0x73, 0x88, 0x4c, 0x50, 0xaa, 0x5b, 0xf4, 0x2c, 0xcb, 0xb8, - 0x0d, 0xda, 0x95, 0xbb, 0xe9, 0x33, 0xf3, 0x33, 0x8d, 0xd6, 0xf0, 0xc7, 0xc0, 0xfc, 0xa7, 0xb0, - 0xca, 0x0a, 0xd9, 0xc9, 0x88, 0xb5, 0x83, 0x1d, 0xdb, 0x12, 0xb8, 0x91, 0x2a, 0x77, 0x9c, 0xa2, - 0xec, 0x36, 0x0e, 0x37, 0xf7, 0x79, 0x36, 0x84, 0x68, 0xc9, 0x16, 0x3f, 0x54, 0xb2, 0xdc, 0x3f, - 0xee, 0xdb, 0xa3, 0xda, 0xf8, 0xca, 0xfd, 0x92, 0xa1, 0x82, 0x9e, 0xa2, 0xb6, 0x46, 0x5e, 0x74, - 0x70, 0x53, 0xc1, 0xf4, 0xd3, 0xfe, 0x00, 0xe9, 0x0e, 0x61, 0xbd, 0x3e, 0x1a, 0xcd, 0x55, 0x4e, - 0x1e, 0x37, 0x07, 0xe2, 0x38, 0x03, 0x9b, 0x71, 0xe2, 0x50, 0xa7, 0x27, 0xce, 0xa9, 0xf3, 0xf2, - 0x1f, 0x77, 0xeb, 0x3d, 0x7a, 0x57, 0x1a, 0x63, 0xcc, 0x23, 0xf4, 0xf8, 0xcd, 0x32, 0x64, 0xcf, - 0x0d, 0x85, 0x6b, 0xc3, 0xfa, 0xf8, 0x8d, 0xef, 0x7e, 0x24, 0x89, 0x93, 0xf7, 0x2e, 0x5e, 0x4a, - 0x08, 0xf4, 0x2f, 0x68, 0x2d, 0xb8, 0x33, 0x76, 0xcd, 0xba, 0x97, 0x20, 0xc4, 0xa5, 0x3e, 0xe4, - 0xcb, 0xc9, 0x70, 0x31, 0x33, 0x39, 0x27, 0xa9, 0x24, 0x33, 0x9d, 0xa2, 0x76, 0xa2, 0x99, 0x42, - 0x27, 0x4a, 0xce, 0x04, 0x2e, 0xe2, 0x34, 0xf9, 0x20, 0x41, 0x14, 0x86, 0xe5, 0x8f, 0x93, 0x63, - 0xfd, 0x59, 0x35, 0xd8, 0x98, 0x38, 0x74, 0x1d, 0x4e, 0x89, 0xe3, 0x23, 0xf9, 0x47, 0x49, 0x91, - 0xfe, 0x7c, 0x2f, 0x20, 0x1f, 0x79, 0x50, 0x4a, 0x12, 0xc8, 0x5b, 0xe7, 0xc9, 0x0c, 0x60, 0x7f, - 0xe2, 0xef, 0x00, 0x42, 0xa7, 0x09, 0x31, 0x2e, 0x44, 0x80, 0xe1, 0x1f, 0x4c, 0xc7, 0xf8, 0xd1, - 0x2f, 0x60, 0xc9, 0xdb, 0x7f, 0x85, 0xb8, 0x61, 0x0c, 0xc0, 0xdf, 0x9f, 0x02, 0x08, 0xd7, 0xde, - 0xd8, 0x0e, 0x73, 0x6f, 0xca, 0x50, 0x86, 0x8b, 0xaf, 0xbd, 0xe8, 0xae, 0xe8, 0x7c, 0xbc, 0xe3, - 0x1d, 0x31, 0x36, 0xcb, 0x31, 0x60, 0xfc, 0xc7, 0x1b, 0xd3, 0x31, 0x2a, 0x17, 0x6f, 0xaf, 0x4b, - 0xe9, 0x77, 0xd7, 0xa5, 0xf4, 0x9f, 0xd7, 0xa5, 0xf4, 0xab, 0x9b, 0x52, 0xea, 0xdd, 0x4d, 0x29, - 0xf5, 0xfb, 0x4d, 0x29, 0x75, 0xf5, 0x44, 0x51, 0xcd, 0x56, 0xbf, 0x51, 0x46, 0xa4, 0x2b, 0x21, - 0x62, 0x74, 0x89, 0x21, 0xa9, 0x0d, 0xf4, 0x50, 0x21, 0xd2, 0xe0, 0x44, 0xea, 0x92, 0x66, 0xbf, - 0x83, 0x0d, 0xf7, 0xe7, 0xd3, 0xa3, 0xc7, 0x0f, 0xbd, 0xff, 0x4f, 0xe6, 0xb0, 0x87, 0x8d, 0x46, - 0x8e, 0xfe, 0x7b, 0x3a, 0xf9, 0x3b, 0x00, 0x00, 0xff, 0xff, 0xc5, 0x64, 0xa7, 0xfd, 0x0a, 0x13, - 0x00, 0x00, + // 1267 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x58, 0x4b, 0x6f, 0xdb, 0x46, + 0x10, 0xd6, 0xcb, 0xb2, 0x3d, 0x72, 0x6d, 0x99, 0xf2, 0x43, 0xa1, 0x62, 0x51, 0xe5, 0x21, 0x11, + 0x5c, 0x44, 0xf2, 0x23, 0x40, 0x11, 0xa3, 0x40, 0x61, 0xa9, 0x0a, 0x6a, 0xb4, 0x7e, 0x80, 0xb2, + 0x7b, 0x70, 0x8b, 0x0a, 0x12, 0xb5, 0x91, 0x09, 0x49, 0x5c, 0x95, 0xa4, 0x94, 0xe8, 0x1f, 0x04, + 0x3e, 0xe5, 0x6c, 0xc0, 0x40, 0x8a, 0x1e, 0x7b, 0x48, 0x7f, 0x46, 0x8e, 0x39, 0xb5, 0x45, 0x0f, + 0x42, 0x61, 0x5f, 0x7a, 0xd6, 0x2f, 0x28, 0xb8, 0x5c, 0x52, 0x94, 0x44, 0xc2, 0x74, 0x62, 0x3b, + 0xb9, 0xed, 0xce, 0x7c, 0x3b, 0x3b, 0xfb, 0x7d, 0xc3, 0x7d, 0x10, 0xee, 0x4b, 0x15, 0x31, 0x2b, + 0x62, 0x05, 0x65, 0xc5, 0x93, 0xb2, 0x2c, 0xa3, 0x46, 0xb6, 0xb3, 0x9e, 0xd5, 0x5e, 0x64, 0x5a, + 0x0a, 0xd6, 0x30, 0x13, 0x93, 0x2a, 0x62, 0x46, 0xf7, 0x66, 0xa8, 0x37, 0xd3, 0x59, 0x67, 0x17, + 0x6a, 0xb8, 0x86, 0x89, 0x3f, 0xab, 0xb7, 0x0c, 0x28, 0xcb, 0x0d, 0x02, 0x35, 0x24, 0x24, 0x6b, + 0x7a, 0x1c, 0xa3, 0x45, 0x01, 0x9f, 0x3b, 0xcd, 0x64, 0x86, 0x25, 0x10, 0xfe, 0x57, 0x3f, 0x30, + 0xbb, 0x6a, 0x2d, 0x6f, 0x18, 0xf7, 0x5b, 0x48, 0xde, 0x91, 0x25, 0x8d, 0xf9, 0x02, 0x26, 0x5b, + 0x58, 0xd1, 0x4a, 0x52, 0x35, 0xee, 0x4f, 0xf9, 0xd3, 0xd3, 0x39, 0xa6, 0xdf, 0xe3, 0x66, 0xbb, + 0xe5, 0x66, 0x63, 0x8b, 0xa7, 0x0e, 0x5e, 0x08, 0xeb, 0xad, 0x9d, 0x2a, 0xf3, 0x15, 0x4c, 0xd2, + 0xa0, 0xf1, 0x40, 0xca, 0x9f, 0x8e, 0x6c, 0xdc, 0xcf, 0x38, 0x2c, 0x22, 0x43, 0xe7, 0xc8, 0x85, + 0xde, 0xf6, 0x38, 0x9f, 0x60, 0x0e, 0x61, 0x96, 0x20, 0xac, 0x4a, 0x35, 0x19, 0x29, 0xf1, 0xa0, + 0x3e, 0x93, 0x40, 0x7b, 0x5b, 0x53, 0x2f, 0x5f, 0x73, 0xbe, 0xff, 0x5e, 0x73, 0x3e, 0x5e, 0x00, + 0x76, 0x3c, 0x45, 0x01, 0xa9, 0x2d, 0x2c, 0xab, 0x88, 0x79, 0x0c, 0x40, 0x43, 0x0d, 0xb2, 0x5d, + 0xec, 0xf7, 0xb8, 0x79, 0x23, 0xdb, 0x81, 0x8f, 0x17, 0xa6, 0x69, 0x67, 0xa7, 0xca, 0xff, 0x19, + 0x84, 0xf9, 0xe1, 0xa0, 0x87, 0x4a, 0xf7, 0x7a, 0xcb, 0xde, 0x83, 0x58, 0x4b, 0x41, 0x1d, 0x09, + 0xb7, 0xd5, 0x92, 0x2d, 0x83, 0x00, 0x19, 0x98, 0xec, 0xf7, 0x38, 0x96, 0x0e, 0x1c, 0x07, 0xf1, + 0xc2, 0xbc, 0x69, 0xcd, 0x9b, 0x29, 0xd9, 0x69, 0x0c, 0x5e, 0x9f, 0x46, 0x01, 0x16, 0x44, 0xdc, + 0x96, 0x35, 0xa4, 0xb4, 0xca, 0x8a, 0xd6, 0x2d, 0x75, 0x90, 0xa2, 0x4a, 0x58, 0x8e, 0x87, 0x48, + 0x3a, 0x5c, 0xbf, 0xc7, 0x25, 0x28, 0x21, 0x0e, 0x28, 0x5e, 0x88, 0xd9, 0xcd, 0x3f, 0x18, 0x56, + 0x9d, 0xda, 0x96, 0x82, 0xf1, 0xb3, 0x92, 0x24, 0x4b, 0x5a, 0x7c, 0x22, 0xe5, 0x4f, 0xcf, 0xd8, + 0xa9, 0x1d, 0xf8, 0x78, 0x61, 0x9a, 0x74, 0x48, 0xed, 0x1c, 0xc3, 0x8c, 0xe1, 0x39, 0x41, 0x52, + 0xed, 0x44, 0x8b, 0x87, 0xc9, 0x62, 0x58, 0xdb, 0x62, 0x8c, 0x1a, 0xed, 0xac, 0x67, 0xbe, 0x25, + 0x88, 0x5c, 0x42, 0x5f, 0x4a, 0xbf, 0xc7, 0xc5, 0xec, 0x71, 0x8d, 0xd1, 0xbc, 0x10, 0x21, 0x5d, + 0x03, 0x69, 0x2b, 0x96, 0x49, 0x97, 0x62, 0x49, 0xc0, 0xbd, 0x31, 0x5d, 0xcd, 0x5a, 0xe1, 0xff, + 0x1a, 0x53, 0x7d, 0x5b, 0xac, 0x5f, 0x4f, 0xf5, 0xe1, 0x72, 0x0b, 0x78, 0x2b, 0x37, 0xe6, 0x18, + 0x96, 0x87, 0x78, 0xb7, 0x85, 0x20, 0x55, 0x9f, 0xe3, 0xfb, 0x3d, 0x2e, 0xe9, 0x20, 0x90, 0x3d, + 0xde, 0xa2, 0xdd, 0x33, 0xa8, 0x9b, 0xdb, 0x50, 0x7e, 0x1d, 0x0c, 0x41, 0x4b, 0x9a, 0xd2, 0xa5, + 0xc2, 0x2f, 0xf4, 0x7b, 0x5c, 0xd4, 0x2e, 0x90, 0xa6, 0x74, 0x79, 0x61, 0x8a, 0xb4, 0xf5, 0x6f, + 0xe7, 0x13, 0x93, 0x7d, 0x5b, 0xac, 0x5b, 0xb2, 0xff, 0x1e, 0x80, 0xc5, 0x61, 0x6f, 0x1e, 0xcb, + 0xcf, 0x24, 0xa5, 0x79, 0x17, 0xd2, 0x5b, 0x54, 0x96, 0xc5, 0x3a, 0x11, 0xdb, 0x81, 0xca, 0xb2, + 0x58, 0x37, 0xa9, 0xd4, 0x0b, 0x72, 0x94, 0xca, 0xd0, 0xad, 0x50, 0x39, 0xe1, 0x42, 0x25, 0x07, + 0x2b, 0x8e, 0x64, 0x59, 0x74, 0x9e, 0xf9, 0x21, 0x36, 0x40, 0xe4, 0x1b, 0x58, 0x45, 0xd7, 0x3f, + 0x34, 0xde, 0x8f, 0xcc, 0xab, 0x0f, 0x8b, 0x15, 0x48, 0x38, 0xe4, 0x66, 0xe5, 0xfe, 0x26, 0x00, + 0x4b, 0x23, 0xfe, 0x3b, 0xac, 0x85, 0xe1, 0x0d, 0x35, 0xf8, 0x9e, 0x1b, 0xea, 0xdd, 0x96, 0x43, + 0x0a, 0x92, 0xce, 0x84, 0x59, 0x9c, 0xbe, 0x0a, 0xc0, 0x67, 0xbb, 0x6a, 0x4d, 0x40, 0x62, 0xe7, + 0xa0, 0x2c, 0xd6, 0x91, 0xc6, 0x3c, 0x81, 0x70, 0x8b, 0xb4, 0x08, 0x93, 0x91, 0x8d, 0x84, 0xe3, + 0x49, 0x66, 0x80, 0xe9, 0x41, 0x46, 0x07, 0x30, 0x4f, 0x21, 0x6a, 0xa4, 0x2b, 0xe2, 0x66, 0x53, + 0xd2, 0x9a, 0x48, 0xd6, 0x08, 0xbd, 0x33, 0xb9, 0x44, 0xbf, 0xc7, 0x2d, 0xdb, 0x17, 0x34, 0x40, + 0xf0, 0xc2, 0x1c, 0x31, 0xe5, 0x2d, 0xcb, 0x18, 0x69, 0xc1, 0x5b, 0x21, 0x2d, 0xe4, 0x42, 0xda, + 0xcf, 0x64, 0xc3, 0x19, 0x30, 0x62, 0xdd, 0x56, 0xbe, 0x86, 0xb0, 0x82, 0xd4, 0x76, 0xc3, 0x60, + 0x66, 0x76, 0xe3, 0xa1, 0x23, 0x33, 0x26, 0x5c, 0x20, 0xd0, 0xc3, 0x6e, 0x0b, 0x09, 0x74, 0xd8, + 0x56, 0x48, 0x9f, 0x83, 0xff, 0x27, 0x00, 0xb0, 0xab, 0xd6, 0x0e, 0xa5, 0x26, 0xc2, 0xed, 0x9b, + 0xe1, 0xbb, 0x2d, 0x2b, 0x48, 0x44, 0x52, 0x07, 0x55, 0xdd, 0xf8, 0x1e, 0x20, 0x4c, 0xbe, 0x8f, + 0x2c, 0xcb, 0xad, 0xf2, 0xfd, 0x1d, 0x30, 0x32, 0x7a, 0xa1, 0x95, 0x54, 0xf4, 0x4b, 0x1b, 0xc9, + 0x22, 0x2a, 0x29, 0x48, 0xec, 0x10, 0xee, 0x43, 0xb9, 0x95, 0x7e, 0x8f, 0xbb, 0x67, 0x44, 0x18, + 0xc7, 0xf0, 0x42, 0x54, 0x37, 0x16, 0xa9, 0x4d, 0xd7, 0xc3, 0x43, 0xc5, 0xff, 0x48, 0xae, 0xc4, + 0x94, 0xdb, 0x9b, 0x56, 0xee, 0xcc, 0xb8, 0x82, 0xd0, 0xe8, 0xfb, 0x32, 0xf9, 0xa2, 0x3e, 0x05, + 0x01, 0xbf, 0x84, 0x08, 0xfd, 0xac, 0xf4, 0x8c, 0xe8, 0xe6, 0xb4, 0xd4, 0xef, 0x71, 0xcc, 0xd0, + 0x37, 0xa7, 0x3b, 0x79, 0xc1, 0xd8, 0xc6, 0x8c, 0xdc, 0x6f, 0x73, 0x7b, 0x72, 0x56, 0x7e, 0xe2, + 0x43, 0x95, 0x0f, 0xbb, 0x28, 0x5f, 0x21, 0xb7, 0x88, 0x61, 0x6d, 0x6e, 0xba, 0x00, 0xfe, 0x08, + 0x90, 0xf2, 0xda, 0x16, 0xeb, 0x32, 0x7e, 0xde, 0x40, 0xd5, 0x1a, 0x22, 0xfb, 0xd5, 0x07, 0x54, + 0x40, 0x1a, 0xe6, 0xca, 0xc3, 0xd1, 0x8c, 0x02, 0x10, 0x46, 0xcd, 0x03, 0x8d, 0xf5, 0x81, 0x55, + 0x37, 0x8d, 0x89, 0xd3, 0xd4, 0x78, 0x5b, 0xef, 0x7c, 0xe4, 0x23, 0x48, 0x24, 0x0f, 0xc0, 0x11, + 0xc6, 0x6e, 0x58, 0x97, 0xd5, 0x33, 0x3f, 0x30, 0xe3, 0x20, 0x66, 0x0d, 0x12, 0x42, 0xa1, 0x78, + 0xb0, 0xbf, 0x57, 0x2c, 0x94, 0x84, 0x42, 0xf1, 0xe8, 0xfb, 0xc3, 0xd2, 0xd1, 0x5e, 0xf1, 0xa0, + 0x90, 0xdf, 0x79, 0xba, 0x53, 0xf8, 0x26, 0xea, 0x63, 0xe7, 0x4e, 0xcf, 0x53, 0x11, 0x9b, 0x89, + 0xe1, 0x61, 0x61, 0x74, 0xc4, 0xde, 0xfe, 0xfe, 0x41, 0xd4, 0xcf, 0x4e, 0x9d, 0x9e, 0xa7, 0x42, + 0x7a, 0x9b, 0x49, 0xc3, 0xf2, 0x28, 0xa6, 0x78, 0x94, 0xcf, 0x17, 0x8a, 0xc5, 0x68, 0x80, 0x8d, + 0x9c, 0x9e, 0xa7, 0x26, 0x69, 0x97, 0x0d, 0xbd, 0xfc, 0x2d, 0xe9, 0xdb, 0x78, 0x33, 0x05, 0xc1, + 0x5d, 0xb5, 0xc6, 0xd4, 0x61, 0x6e, 0xf4, 0xa9, 0xee, 0xbc, 0xdc, 0xf1, 0x07, 0x33, 0x9b, 0xf5, + 0x08, 0xb4, 0x88, 0x3d, 0x81, 0xd9, 0x91, 0xf7, 0xf1, 0x03, 0x0f, 0x21, 0x0e, 0x95, 0x2e, 0x9b, + 0xf1, 0x86, 0x73, 0x99, 0x49, 0xbf, 0x02, 0x7b, 0x99, 0x69, 0x5b, 0xac, 0x7b, 0x9a, 0xc9, 0xf6, + 0x14, 0x60, 0x34, 0x60, 0x1c, 0x9e, 0x01, 0xab, 0x1e, 0xa2, 0x50, 0x2c, 0xbb, 0xe1, 0x1d, 0x6b, + 0xcd, 0x2a, 0x43, 0x74, 0xec, 0xb6, 0x9c, 0xbe, 0x22, 0x8e, 0x85, 0x64, 0xd7, 0xbc, 0x22, 0xad, + 0xf9, 0x9e, 0x43, 0xcc, 0xf1, 0x86, 0xeb, 0x25, 0x90, 0xb9, 0xce, 0xcd, 0x6b, 0x80, 0xad, 0x89, + 0x7f, 0x02, 0xb0, 0x5d, 0x03, 0x79, 0xb7, 0x10, 0x03, 0x0c, 0xbb, 0x7a, 0x35, 0xc6, 0x8a, 0x5e, + 0x84, 0x49, 0xf3, 0xc6, 0xc3, 0xb9, 0x0d, 0xa3, 0x00, 0xf6, 0xe1, 0x15, 0x00, 0x7b, 0xed, 0x8d, + 0x1c, 0xc6, 0x0f, 0xae, 0x18, 0x4a, 0x71, 0xee, 0xb5, 0xe7, 0x72, 0x80, 0xd4, 0x61, 0x6e, 0x74, + 0xd7, 0x77, 0xcd, 0x72, 0x04, 0xe8, 0xfe, 0xf1, 0xba, 0xec, 0x8a, 0xb9, 0xe2, 0xdb, 0x8b, 0xa4, + 0xff, 0xdd, 0x45, 0xd2, 0xff, 0xef, 0x45, 0xd2, 0xff, 0xea, 0x32, 0xe9, 0x7b, 0x77, 0x99, 0xf4, + 0xfd, 0x7d, 0x99, 0xf4, 0x1d, 0x3f, 0xa9, 0x49, 0xda, 0x49, 0xbb, 0x92, 0x11, 0x71, 0x33, 0x2b, + 0x62, 0xb5, 0x89, 0xd5, 0xac, 0x54, 0x11, 0x1f, 0xd5, 0x70, 0xb6, 0xb3, 0x99, 0x6d, 0xe2, 0x6a, + 0xbb, 0x81, 0x54, 0xe3, 0xaf, 0xe1, 0xda, 0xe3, 0x47, 0xe6, 0x8f, 0x43, 0xad, 0xdb, 0x42, 0x6a, + 0x25, 0x4c, 0x7e, 0x1a, 0x6e, 0xfe, 0x1f, 0x00, 0x00, 0xff, 0xff, 0xd5, 0x99, 0xe1, 0x0c, 0xc3, + 0x14, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1954,6 +1999,11 @@ func (m *MsgRecvPacketResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Result != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.Result)) + i-- + dAtA[i] = 0x8 + } return len(dAtA) - i, nil } @@ -2039,6 +2089,11 @@ func (m *MsgTimeoutResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Result != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.Result)) + i-- + dAtA[i] = 0x8 + } return len(dAtA) - i, nil } @@ -2131,6 +2186,11 @@ func (m *MsgTimeoutOnCloseResponse) MarshalToSizedBuffer(dAtA []byte) (int, erro _ = i var l int _ = l + if m.Result != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.Result)) + i-- + dAtA[i] = 0x8 + } return len(dAtA) - i, nil } @@ -2218,6 +2278,11 @@ func (m *MsgAcknowledgementResponse) MarshalToSizedBuffer(dAtA []byte) (int, err _ = i var l int _ = l + if m.Result != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.Result)) + i-- + dAtA[i] = 0x8 + } return len(dAtA) - i, nil } @@ -2479,6 +2544,9 @@ func (m *MsgRecvPacketResponse) Size() (n int) { } var l int _ = l + if m.Result != 0 { + n += 1 + sovTx(uint64(m.Result)) + } return n } @@ -2512,6 +2580,9 @@ func (m *MsgTimeoutResponse) Size() (n int) { } var l int _ = l + if m.Result != 0 { + n += 1 + sovTx(uint64(m.Result)) + } return n } @@ -2549,6 +2620,9 @@ func (m *MsgTimeoutOnCloseResponse) Size() (n int) { } var l int _ = l + if m.Result != 0 { + n += 1 + sovTx(uint64(m.Result)) + } return n } @@ -2583,6 +2657,9 @@ func (m *MsgAcknowledgementResponse) Size() (n int) { } var l int _ = l + if m.Result != 0 { + n += 1 + sovTx(uint64(m.Result)) + } return n } @@ -4409,6 +4486,25 @@ func (m *MsgRecvPacketResponse) Unmarshal(dAtA []byte) error { return fmt.Errorf("proto: MsgRecvPacketResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Result", wireType) + } + m.Result = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Result |= ResponseResultType(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) @@ -4660,6 +4756,25 @@ func (m *MsgTimeoutResponse) Unmarshal(dAtA []byte) error { return fmt.Errorf("proto: MsgTimeoutResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Result", wireType) + } + m.Result = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Result |= ResponseResultType(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) @@ -4945,6 +5060,25 @@ func (m *MsgTimeoutOnCloseResponse) Unmarshal(dAtA []byte) error { return fmt.Errorf("proto: MsgTimeoutOnCloseResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Result", wireType) + } + m.Result = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Result |= ResponseResultType(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) @@ -5211,6 +5345,25 @@ func (m *MsgAcknowledgementResponse) Unmarshal(dAtA []byte) error { return fmt.Errorf("proto: MsgAcknowledgementResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Result", wireType) + } + m.Result = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Result |= ResponseResultType(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) diff --git a/modules/core/05-port/types/module.go b/modules/core/05-port/types/module.go index dea418b7250..9f754fe0a3e 100644 --- a/modules/core/05-port/types/module.go +++ b/modules/core/05-port/types/module.go @@ -51,6 +51,7 @@ type IBCModule interface { ctx sdk.Context, portID, channelID string, + counterpartyChannelID string, counterpartyVersion string, ) error diff --git a/modules/core/ante/ante.go b/modules/core/ante/ante.go index 42e392905ec..e9218ea4b94 100644 --- a/modules/core/ante/ante.go +++ b/modules/core/ante/ante.go @@ -4,22 +4,23 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" - channelkeeper "github.com/cosmos/ibc-go/v3/modules/core/04-channel/keeper" channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" + "github.com/cosmos/ibc-go/v3/modules/core/keeper" ) type AnteDecorator struct { - k channelkeeper.Keeper + k *keeper.Keeper } -func NewAnteDecorator(k channelkeeper.Keeper) AnteDecorator { +func NewAnteDecorator(k *keeper.Keeper) AnteDecorator { return AnteDecorator{k: k} } -// AnteDecorator returns an error if a multiMsg tx only contains packet messages (Recv, Ack, Timeout) and additional update messages and all packet messages -// are redundant. If the transaction is just a single UpdateClient message, or the multimsg transaction contains some other message type, then the antedecorator returns no error -// and continues processing to ensure these transactions are included. -// This will ensure that relayers do not waste fees on multiMsg transactions when another relayer has already submitted all packets, by rejecting the tx at the mempool layer. +// AnteDecorator returns an error if a multiMsg tx only contains packet messages (Recv, Ack, Timeout) and additional update messages +// and all packet messages are redundant. If the transaction is just a single UpdateClient message, or the multimsg transaction +// contains some other message type, then the antedecorator returns no error and continues processing to ensure these transactions +// are included. This will ensure that relayers do not waste fees on multiMsg transactions when another relayer has already submitted +// all packets, by rejecting the tx at the mempool layer. func (ad AnteDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { // do not run redundancy check on DeliverTx or simulate if (ctx.IsCheckTx() || ctx.IsReCheckTx()) && !simulate { @@ -29,31 +30,50 @@ func (ad AnteDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, ne for _, m := range tx.GetMsgs() { switch msg := m.(type) { case *channeltypes.MsgRecvPacket: - if _, found := ad.k.GetPacketReceipt(ctx, msg.Packet.GetDestPort(), msg.Packet.GetDestChannel(), msg.Packet.GetSequence()); found { + response, err := ad.k.RecvPacket(sdk.WrapSDKContext(ctx), msg) + if err != nil { + return ctx, err + } + if response.Result == channeltypes.NOOP { redundancies += 1 } packetMsgs += 1 case *channeltypes.MsgAcknowledgement: - if commitment := ad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { + response, err := ad.k.Acknowledgement(sdk.WrapSDKContext(ctx), msg) + if err != nil { + return ctx, err + } + if response.Result == channeltypes.NOOP { redundancies += 1 } packetMsgs += 1 case *channeltypes.MsgTimeout: - if commitment := ad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { + response, err := ad.k.Timeout(sdk.WrapSDKContext(ctx), msg) + if err != nil { + return ctx, err + } + if response.Result == channeltypes.NOOP { redundancies += 1 } packetMsgs += 1 case *channeltypes.MsgTimeoutOnClose: - if commitment := ad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { + response, err := ad.k.TimeoutOnClose(sdk.WrapSDKContext(ctx), msg) + if err != nil { + return ctx, err + } + if response.Result == channeltypes.NOOP { redundancies += 1 } packetMsgs += 1 case *clienttypes.MsgUpdateClient: - // do nothing here, as we want to avoid updating clients if it is batched with only redundant messages + _, err := ad.k.UpdateClient(sdk.WrapSDKContext(ctx), msg) + if err != nil { + return ctx, err + } default: // if the multiMsg tx has a msg that is not a packet msg or update msg, then we will not return error @@ -61,7 +81,6 @@ func (ad AnteDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, ne // even if they get batched with redundant packet messages. return next(ctx, tx, simulate) } - } // only return error if all packet messages are redundant diff --git a/modules/core/ante/ante_test.go b/modules/core/ante/ante_test.go index 0336e07a3ae..c04f6483f74 100644 --- a/modules/core/ante/ante_test.go +++ b/modules/core/ante/ante_test.go @@ -4,13 +4,15 @@ import ( "testing" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" + host "github.com/cosmos/ibc-go/v3/modules/core/24-host" "github.com/cosmos/ibc-go/v3/modules/core/ante" + "github.com/cosmos/ibc-go/v3/modules/core/exported" ibctesting "github.com/cosmos/ibc-go/v3/testing" - "github.com/cosmos/ibc-go/v3/testing/mock" ) type AnteTestSuite struct { @@ -42,6 +44,133 @@ func TestAnteTestSuite(t *testing.T) { suite.Run(t, new(AnteTestSuite)) } +// createRecvPacketMessage creates a RecvPacket message for a packet sent from chain A to chain B. +func (suite *AnteTestSuite) createRecvPacketMessage(sequenceNumber uint64, isRedundant bool) sdk.Msg { + packet := channeltypes.NewPacket(ibctesting.MockPacketData, sequenceNumber, + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + clienttypes.NewHeight(1, 0), 0) + + err := suite.path.EndpointA.SendPacket(packet) + suite.Require().NoError(err) + + if isRedundant { + err = suite.path.EndpointB.RecvPacket(packet) + suite.Require().NoError(err) + } + + err = suite.path.EndpointB.UpdateClient() + suite.Require().NoError(err) + + packetKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) + proof, proofHeight := suite.chainA.QueryProof(packetKey) + + return channeltypes.NewMsgRecvPacket(packet, proof, proofHeight, suite.path.EndpointA.Chain.SenderAccount.GetAddress().String()) +} + +// createAcknowledgementMessage creates an Acknowledgement message for a packet sent from chain B to chain A. +func (suite *AnteTestSuite) createAcknowledgementMessage(sequenceNumber uint64, isRedundant bool) sdk.Msg { + packet := channeltypes.NewPacket(ibctesting.MockPacketData, sequenceNumber, + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + clienttypes.NewHeight(1, 0), 0) + + err := suite.path.EndpointB.SendPacket(packet) + suite.Require().NoError(err) + err = suite.path.EndpointA.RecvPacket(packet) + suite.Require().NoError(err) + + if isRedundant { + err = suite.path.EndpointB.AcknowledgePacket(packet, ibctesting.MockAcknowledgement) + suite.Require().NoError(err) + } + + packetKey := host.PacketAcknowledgementKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) + proof, proofHeight := suite.chainA.QueryProof(packetKey) + + return channeltypes.NewMsgAcknowledgement(packet, ibctesting.MockAcknowledgement, proof, proofHeight, suite.path.EndpointA.Chain.SenderAccount.GetAddress().String()) +} + +// createTimeoutMessage creates an Timeout message for a packet sent from chain B to chain A. +func (suite *AnteTestSuite) createTimeoutMessage(sequenceNumber uint64, isRedundant bool) sdk.Msg { + height := suite.chainA.LastHeader.GetHeight() + timeoutHeight := clienttypes.NewHeight(height.GetRevisionNumber(), height.GetRevisionHeight()+1) + packet := channeltypes.NewPacket(ibctesting.MockPacketData, sequenceNumber, + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + timeoutHeight, 0) + + err := suite.path.EndpointB.SendPacket(packet) + suite.Require().NoError(err) + + suite.coordinator.CommitNBlocks(suite.chainA, 3) + + err = suite.path.EndpointB.UpdateClient() + suite.Require().NoError(err) + + if isRedundant { + err = suite.path.EndpointB.TimeoutPacket(packet) + suite.Require().NoError(err) + } + + packetKey := host.PacketReceiptKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) + proof, proofHeight := suite.chainA.QueryProof(packetKey) + + return channeltypes.NewMsgTimeout(packet, sequenceNumber, proof, proofHeight, suite.path.EndpointA.Chain.SenderAccount.GetAddress().String()) +} + +// createTimeoutOnCloseMessage creates an TimeoutOnClose message for a packet sent from chain B to chain A. +func (suite *AnteTestSuite) createTimeoutOnCloseMessage(sequenceNumber uint64, isRedundant bool) sdk.Msg { + height := suite.chainA.LastHeader.GetHeight() + timeoutHeight := clienttypes.NewHeight(height.GetRevisionNumber(), height.GetRevisionHeight()+1) + packet := channeltypes.NewPacket(ibctesting.MockPacketData, sequenceNumber, + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + timeoutHeight, 0) + + err := suite.path.EndpointB.SendPacket(packet) + suite.Require().NoError(err) + err = suite.path.EndpointA.SetChannelClosed() + suite.Require().NoError(err) + + if isRedundant { + err = suite.path.EndpointB.TimeoutOnClose(packet) + suite.Require().NoError(err) + } + + packetKey := host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) + proof, proofHeight := suite.chainA.QueryProof(packetKey) + + channelKey := host.ChannelKey(packet.GetDestPort(), packet.GetDestChannel()) + proofClosed, _ := suite.chainA.QueryProof(channelKey) + + return channeltypes.NewMsgTimeoutOnClose(packet, 1, proof, proofClosed, proofHeight, suite.path.EndpointA.Chain.SenderAccount.GetAddress().String()) +} + +func (suite *AnteTestSuite) createUpdateClientMessage() sdk.Msg { + endpoint := suite.path.EndpointB + + // ensure counterparty has committed state + endpoint.Chain.Coordinator.CommitBlock(endpoint.Counterparty.Chain) + + var header exported.Header + + switch endpoint.ClientConfig.GetClientType() { + case exported.Tendermint: + header, _ = endpoint.Chain.ConstructUpdateTMClientHeader(endpoint.Counterparty.Chain, endpoint.ClientID) + + default: + } + + msg, err := clienttypes.NewMsgUpdateClient( + endpoint.ClientID, header, + endpoint.Chain.SenderAccount.GetAddress().String(), + ) + require.NoError(endpoint.Chain.T, err) + + return msg +} + func (suite *AnteTestSuite) TestAnteDecorator() { testCases := []struct { name string @@ -49,404 +178,276 @@ func (suite *AnteTestSuite) TestAnteDecorator() { expPass bool }{ { - "success on single msg", + "success on one new RecvPacket message", func(suite *AnteTestSuite) []sdk.Msg { - packet := channeltypes.NewPacket([]byte(mock.MockPacketData), 1, - suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - clienttypes.NewHeight(1, 0), 0) - - return []sdk.Msg{channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")} + // the RecvPacket message has not been submitted to the chain yet, so it will succeed + return []sdk.Msg{suite.createRecvPacketMessage(1, false)} }, true, }, { - "success on multiple msgs", + "success on one new Acknowledgement message", func(suite *AnteTestSuite) []sdk.Msg { - var msgs []sdk.Msg - - for i := 1; i <= 5; i++ { - packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), - suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - clienttypes.NewHeight(1, 0), 0) - - msgs = append(msgs, channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) - } - return msgs + // the Acknowledgement message has not been submitted to the chain yet, so it will succeed + return []sdk.Msg{suite.createAcknowledgementMessage(1, false)} }, true, }, { - "success on multiple msgs: 1 fresh recv packet", + "success on one new Timeout message", func(suite *AnteTestSuite) []sdk.Msg { - var msgs []sdk.Msg - - for i := 1; i <= 5; i++ { - packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), - suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - clienttypes.NewHeight(1, 0), 0) - - err := suite.path.EndpointA.SendPacket(packet) - suite.Require().NoError(err) - - // receive all sequences except packet 3 - if i != 3 { - err = suite.path.EndpointB.RecvPacket(packet) - suite.Require().NoError(err) - } - - msgs = append(msgs, channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) - } - - return msgs + // the Timeout message has not been submitted to the chain yet, so it will succeed + return []sdk.Msg{suite.createTimeoutMessage(1, false)} }, true, }, { - "success on multiple mixed msgs", + "success on one new TimeoutOnClose message", + func(suite *AnteTestSuite) []sdk.Msg { + // the TimeoutOnClose message has not been submitted to the chain yet, so it will succeed + return []sdk.Msg{suite.createTimeoutOnCloseMessage(uint64(1), false)} + }, + true, + }, + { + "success on three new messages of each type", func(suite *AnteTestSuite) []sdk.Msg { var msgs []sdk.Msg + // none of the messages of each type has been submitted to the chain yet, + // the first message is succeed and the next two of each type will be rejected + // because they are redundant. + + // from A to B for i := 1; i <= 3; i++ { - packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), - suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - clienttypes.NewHeight(1, 0), 0) - err := suite.path.EndpointA.SendPacket(packet) - suite.Require().NoError(err) - - msgs = append(msgs, channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) - } - for i := 1; i <= 3; i++ { - packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), - suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - clienttypes.NewHeight(1, 0), 0) - err := suite.path.EndpointB.SendPacket(packet) - suite.Require().NoError(err) - - msgs = append(msgs, channeltypes.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, suite.createRecvPacketMessage(uint64(i), false)) } - for i := 4; i <= 6; i++ { - packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), - suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - clienttypes.NewHeight(1, 0), 0) - err := suite.path.EndpointB.SendPacket(packet) - suite.Require().NoError(err) - - msgs = append(msgs, channeltypes.NewMsgTimeout(packet, uint64(i), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + + // from B to A + for i := 1; i <= 9; i++ { + switch { + case i >= 1 && i <= 3: + msgs = append(msgs, suite.createAcknowledgementMessage(uint64(i), false)) + case i >= 4 && i <= 6: + msgs = append(msgs, suite.createTimeoutMessage(uint64(i), false)) + case i >= 7 && i <= 9: + msgs = append(msgs, suite.createTimeoutOnCloseMessage(uint64(i), false)) + } } return msgs }, true, }, { - "success on multiple mixed msgs: 1 fresh packet of each type", + "success on three redundant messages of RecvPacket, Acknowledgement and TimeoutOnClose, and one new Timeout message", func(suite *AnteTestSuite) []sdk.Msg { var msgs []sdk.Msg - for i := 1; i <= 3; i++ { - packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), - suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - clienttypes.NewHeight(1, 0), 0) - err := suite.path.EndpointA.SendPacket(packet) - suite.Require().NoError(err) - - // receive all sequences except packet 3 - if i != 3 { - - err := suite.path.EndpointB.RecvPacket(packet) - suite.Require().NoError(err) - } + // we pass three messages of RecvPacket, Acknowledgement and TimeoutOnClose that + // are all redundant (i.e. those messages have already been submitted and + // processed by the chain). But these messages will not be rejected because the + // Timeout message is new. - msgs = append(msgs, channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) - } + // from A to B for i := 1; i <= 3; i++ { - packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), - suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - clienttypes.NewHeight(1, 0), 0) - err := suite.path.EndpointB.SendPacket(packet) - suite.Require().NoError(err) - - // receive all acks except ack 2 - if i != 2 { - err = suite.path.EndpointA.RecvPacket(packet) - suite.Require().NoError(err) - err = suite.path.EndpointB.AcknowledgePacket(packet, mock.MockAcknowledgement.Acknowledgement()) - suite.Require().NoError(err) - } - - msgs = append(msgs, channeltypes.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, suite.createRecvPacketMessage(uint64(i), true)) } - for i := 4; i <= 6; i++ { - height := suite.chainA.LastHeader.GetHeight() - timeoutHeight := clienttypes.NewHeight(height.GetRevisionNumber(), height.GetRevisionHeight()+1) - packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), - suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - timeoutHeight, 0) - err := suite.path.EndpointB.SendPacket(packet) - suite.Require().NoError(err) - - // timeout packet - suite.coordinator.CommitNBlocks(suite.chainA, 3) - - // timeout packets except sequence 5 - if i != 5 { - suite.path.EndpointB.UpdateClient() - err = suite.path.EndpointB.TimeoutPacket(packet) - suite.Require().NoError(err) - } - msgs = append(msgs, channeltypes.NewMsgTimeout(packet, uint64(i), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + // from B to A + for i := 1; i <= 7; i++ { + switch { + case i >= 1 && i <= 3: + msgs = append(msgs, suite.createAcknowledgementMessage(uint64(i), true)) + case i == 4: + msgs = append(msgs, suite.createTimeoutMessage(uint64(i), false)) + case i >= 5 && i <= 7: + msgs = append(msgs, suite.createTimeoutOnCloseMessage(uint64(i), true)) + } } return msgs }, true, }, { - "success on multiple mixed msgs: only 1 fresh msg in total", + "success on one new message and two redundant messages of each type", func(suite *AnteTestSuite) []sdk.Msg { var msgs []sdk.Msg - for i := 1; i <= 3; i++ { - packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), - suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - clienttypes.NewHeight(1, 0), 0) - - // receive all packets - suite.path.EndpointA.SendPacket(packet) - suite.path.EndpointB.RecvPacket(packet) + // For each type there is a new message and two messages that are redundant + // (i.e. they have been already submitted and processed by the chain). But all + // the redundant messages will not be rejected because there is a new message + // of each type. - msgs = append(msgs, channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) - } + // from A to B for i := 1; i <= 3; i++ { - packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), - suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - clienttypes.NewHeight(1, 0), 0) - - // receive all acks - suite.path.EndpointB.SendPacket(packet) - suite.path.EndpointA.RecvPacket(packet) - suite.path.EndpointB.AcknowledgePacket(packet, mock.MockAcknowledgement.Acknowledgement()) - - msgs = append(msgs, channeltypes.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, suite.createRecvPacketMessage(uint64(i), i != 2)) } - for i := 4; i < 5; i++ { - height := suite.chainA.LastHeader.GetHeight() - timeoutHeight := clienttypes.NewHeight(height.GetRevisionNumber(), height.GetRevisionHeight()+1) - packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), - suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - timeoutHeight, 0) - - // do not timeout packet, timeout msg is fresh - suite.path.EndpointB.SendPacket(packet) - - msgs = append(msgs, channeltypes.NewMsgTimeout(packet, uint64(i), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + + // from B to A + for i := 1; i <= 9; i++ { + switch { + case i >= 1 && i <= 3: + msgs = append(msgs, suite.createAcknowledgementMessage(uint64(i), i != 2)) + case i >= 4 && i <= 6: + msgs = append(msgs, suite.createTimeoutMessage(uint64(i), i != 5)) + case i >= 7 && i <= 9: + msgs = append(msgs, suite.createTimeoutOnCloseMessage(uint64(i), i != 8)) + } } return msgs }, true, }, { - "success on single update client msg", + "success on one new UpdateClient message", func(suite *AnteTestSuite) []sdk.Msg { - return []sdk.Msg{&clienttypes.MsgUpdateClient{}} + return []sdk.Msg{suite.createUpdateClientMessage()} }, true, }, { - "success on multiple update clients", + "success on three new UpdateClient messages", func(suite *AnteTestSuite) []sdk.Msg { - return []sdk.Msg{&clienttypes.MsgUpdateClient{}, &clienttypes.MsgUpdateClient{}, &clienttypes.MsgUpdateClient{}} + return []sdk.Msg{suite.createUpdateClientMessage(), suite.createUpdateClientMessage(), suite.createUpdateClientMessage()} }, true, }, { - "success on multiple update clients and fresh packet message", + "success on three new Updateclient messages and one new RecvPacket message", func(suite *AnteTestSuite) []sdk.Msg { - msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{}, &clienttypes.MsgUpdateClient{}, &clienttypes.MsgUpdateClient{}} - - packet := channeltypes.NewPacket([]byte(mock.MockPacketData), 1, - suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - clienttypes.NewHeight(1, 0), 0) - - return append(msgs, channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + return []sdk.Msg{ + suite.createUpdateClientMessage(), + suite.createUpdateClientMessage(), + suite.createUpdateClientMessage(), + suite.createRecvPacketMessage(uint64(1), false), + } }, true, }, { - "success of tx with different msg type even if all packet messages are redundant", + "success on three redundant RecvPacket messages and one SubmitMisbehaviour message", func(suite *AnteTestSuite) []sdk.Msg { - msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{}} + msgs := []sdk.Msg{suite.createUpdateClientMessage()} for i := 1; i <= 3; i++ { - packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), - suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - clienttypes.NewHeight(1, 0), 0) - - // receive all packets - suite.path.EndpointA.SendPacket(packet) - suite.path.EndpointB.RecvPacket(packet) - - msgs = append(msgs, channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) - } - for i := 1; i <= 3; i++ { - packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), - suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - clienttypes.NewHeight(1, 0), 0) - - // receive all acks - suite.path.EndpointB.SendPacket(packet) - suite.path.EndpointA.RecvPacket(packet) - suite.path.EndpointB.AcknowledgePacket(packet, mock.MockAcknowledgement.Acknowledgement()) - - msgs = append(msgs, channeltypes.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) - } - for i := 4; i < 6; i++ { - height := suite.chainA.LastHeader.GetHeight() - timeoutHeight := clienttypes.NewHeight(height.GetRevisionNumber(), height.GetRevisionHeight()+1) - packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), - suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - timeoutHeight, 0) - - err := suite.path.EndpointB.SendPacket(packet) - suite.Require().NoError(err) - - // timeout packet - suite.coordinator.CommitNBlocks(suite.chainA, 3) - - suite.path.EndpointB.UpdateClient() - suite.path.EndpointB.TimeoutPacket(packet) - - msgs = append(msgs, channeltypes.NewMsgTimeoutOnClose(packet, uint64(i), []byte("proof"), []byte("channelProof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, suite.createRecvPacketMessage(uint64(i), true)) } // append non packet and update message to msgs to ensure multimsg tx should pass msgs = append(msgs, &clienttypes.MsgSubmitMisbehaviour{}) - return msgs }, true, }, { - "no success on multiple mixed message: all are redundant", + "no success on one redundant RecvPacket message", + func(suite *AnteTestSuite) []sdk.Msg { + return []sdk.Msg{suite.createRecvPacketMessage(uint64(1), true)} + }, + false, + }, + { + "no success on three redundant messages of each type", func(suite *AnteTestSuite) []sdk.Msg { var msgs []sdk.Msg + // from A to B for i := 1; i <= 3; i++ { - packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), - suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - clienttypes.NewHeight(1, 0), 0) - - // receive all packets - suite.path.EndpointA.SendPacket(packet) - suite.path.EndpointB.RecvPacket(packet) - - msgs = append(msgs, channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, suite.createRecvPacketMessage(uint64(i), true)) } - for i := 1; i <= 3; i++ { - packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), - suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - clienttypes.NewHeight(1, 0), 0) - // receive all acks - suite.path.EndpointB.SendPacket(packet) - suite.path.EndpointA.RecvPacket(packet) - suite.path.EndpointB.AcknowledgePacket(packet, mock.MockAcknowledgement.Acknowledgement()) - - msgs = append(msgs, channeltypes.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) - } - for i := 4; i < 6; i++ { - height := suite.chainA.LastHeader.GetHeight() - timeoutHeight := clienttypes.NewHeight(height.GetRevisionNumber(), height.GetRevisionHeight()+1) - packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), - suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - timeoutHeight, 0) - - err := suite.path.EndpointB.SendPacket(packet) - suite.Require().NoError(err) - - // timeout packet - suite.coordinator.CommitNBlocks(suite.chainA, 3) - - suite.path.EndpointB.UpdateClient() - suite.path.EndpointB.TimeoutPacket(packet) - - msgs = append(msgs, channeltypes.NewMsgTimeoutOnClose(packet, uint64(i), []byte("proof"), []byte("channelProof"), clienttypes.NewHeight(0, 1), "signer")) + // from B to A + for i := 1; i <= 9; i++ { + switch { + case i >= 1 && i <= 3: + msgs = append(msgs, suite.createAcknowledgementMessage(uint64(i), true)) + case i >= 4 && i <= 6: + msgs = append(msgs, suite.createTimeoutMessage(uint64(i), true)) + case i >= 7 && i <= 9: + msgs = append(msgs, suite.createTimeoutOnCloseMessage(uint64(i), true)) + } } return msgs }, false, }, { - "no success if msgs contain update clients and redundant packet messages", + "no success on one new UpdateClient message and three redundant RecvPacket messages", func(suite *AnteTestSuite) []sdk.Msg { - msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{}, &clienttypes.MsgUpdateClient{}, &clienttypes.MsgUpdateClient{}} + msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{}} for i := 1; i <= 3; i++ { - packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), - suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - clienttypes.NewHeight(1, 0), 0) - - // receive all packets - suite.path.EndpointA.SendPacket(packet) - suite.path.EndpointB.RecvPacket(packet) - - msgs = append(msgs, channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, suite.createRecvPacketMessage(uint64(i), true)) } - for i := 1; i <= 3; i++ { - packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), - suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - clienttypes.NewHeight(1, 0), 0) - // receive all acks - suite.path.EndpointB.SendPacket(packet) - suite.path.EndpointA.RecvPacket(packet) - suite.path.EndpointB.AcknowledgePacket(packet, mock.MockAcknowledgement.Acknowledgement()) + return msgs + }, + false, + }, + { + "no success on three new UpdateClient messages and three redundant messages of each type", + func(suite *AnteTestSuite) []sdk.Msg { + msgs := []sdk.Msg{suite.createUpdateClientMessage(), suite.createUpdateClientMessage(), suite.createUpdateClientMessage()} - msgs = append(msgs, channeltypes.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + // from A to B + for i := 1; i <= 3; i++ { + msgs = append(msgs, suite.createRecvPacketMessage(uint64(i), true)) } - for i := 4; i < 6; i++ { - height := suite.chainA.LastHeader.GetHeight() - timeoutHeight := clienttypes.NewHeight(height.GetRevisionNumber(), height.GetRevisionHeight()+1) - packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), - suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - timeoutHeight, 0) - - err := suite.path.EndpointB.SendPacket(packet) - suite.Require().NoError(err) - - // timeout packet - suite.coordinator.CommitNBlocks(suite.chainA, 3) - suite.path.EndpointB.UpdateClient() - suite.path.EndpointB.TimeoutPacket(packet) - - msgs = append(msgs, channeltypes.NewMsgTimeoutOnClose(packet, uint64(i), []byte("proof"), []byte("channelProof"), clienttypes.NewHeight(0, 1), "signer")) + // from B to A + for i := 1; i <= 9; i++ { + switch { + case i >= 1 && i <= 3: + msgs = append(msgs, suite.createAcknowledgementMessage(uint64(i), true)) + case i >= 4 && i <= 6: + msgs = append(msgs, suite.createTimeoutMessage(uint64(i), true)) + case i >= 7 && i <= 9: + msgs = append(msgs, suite.createTimeoutOnCloseMessage(uint64(i), true)) + } } return msgs }, false, }, + { + "no success on one new message and one invalid message", + func(suite *AnteTestSuite) []sdk.Msg { + packet := channeltypes.NewPacket(ibctesting.MockPacketData, 2, + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + clienttypes.NewHeight(1, 0), 0) + + return []sdk.Msg{ + suite.createRecvPacketMessage(uint64(1), false), + channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer"), + } + }, + false, + }, + { + "no success on one new message and one redundant message in the same block", + func(suite *AnteTestSuite) []sdk.Msg { + msg := suite.createRecvPacketMessage(uint64(1), false) + + // We want to be able to run check tx with the non-redundant message without + // commiting it to a block, so that the when check tx runs with the redundant + // message they are both in the same block + k := suite.chainB.App.GetIBCKeeper() + decorator := ante.NewAnteDecorator(k) + checkCtx := suite.chainB.GetContext().WithIsCheckTx(true) + next := func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) { return ctx, nil } + txBuilder := suite.chainB.TxConfig.NewTxBuilder() + err := txBuilder.SetMsgs([]sdk.Msg{msg}...) + suite.Require().NoError(err) + tx := txBuilder.GetTx() + + _, err = decorator.AnteHandle(checkCtx, tx, false, next) + suite.Require().NoError(err) + + return []sdk.Msg{msg} + }, + false, + }, } for _, tc := range testCases { @@ -456,7 +457,7 @@ func (suite *AnteTestSuite) TestAnteDecorator() { // reset suite suite.SetupTest() - k := suite.chainB.App.GetIBCKeeper().ChannelKeeper + k := suite.chainB.App.GetIBCKeeper() decorator := ante.NewAnteDecorator(k) msgs := tc.malleate(suite) diff --git a/modules/core/keeper/msg_server.go b/modules/core/keeper/msg_server.go index a36f064e8ae..74e7cc19ae4 100644 --- a/modules/core/keeper/msg_server.go +++ b/modules/core/keeper/msg_server.go @@ -261,7 +261,7 @@ func (k Keeper) ChannelOpenAck(goCtx context.Context, msg *channeltypes.MsgChann } // Perform application logic callback - if err = cbs.OnChanOpenAck(ctx, msg.PortId, msg.ChannelId, msg.CounterpartyVersion); err != nil { + if err = cbs.OnChanOpenAck(ctx, msg.PortId, msg.ChannelId, msg.CounterpartyChannelId, msg.CounterpartyVersion); err != nil { return nil, sdkerrors.Wrap(err, "channel open ack callback failed") } @@ -395,7 +395,7 @@ func (k Keeper) RecvPacket(goCtx context.Context, msg *channeltypes.MsgRecvPacke case nil: writeFn() case channeltypes.ErrNoOpMsg: - return &channeltypes.MsgRecvPacketResponse{}, nil // no-op + return &channeltypes.MsgRecvPacketResponse{Result: channeltypes.NOOP}, nil default: return nil, sdkerrors.Wrap(err, "receive packet verification failed") } @@ -435,7 +435,7 @@ func (k Keeper) RecvPacket(goCtx context.Context, msg *channeltypes.MsgRecvPacke ) }() - return &channeltypes.MsgRecvPacketResponse{}, nil + return &channeltypes.MsgRecvPacketResponse{Result: channeltypes.SUCCESS}, nil } // Timeout defines a rpc handler method for MsgTimeout. @@ -473,7 +473,7 @@ func (k Keeper) Timeout(goCtx context.Context, msg *channeltypes.MsgTimeout) (*c case nil: writeFn() case channeltypes.ErrNoOpMsg: - return &channeltypes.MsgTimeoutResponse{}, nil // no-op + return &channeltypes.MsgTimeoutResponse{Result: channeltypes.NOOP}, nil default: return nil, sdkerrors.Wrap(err, "timeout packet verification failed") } @@ -503,7 +503,7 @@ func (k Keeper) Timeout(goCtx context.Context, msg *channeltypes.MsgTimeout) (*c ) }() - return &channeltypes.MsgTimeoutResponse{}, nil + return &channeltypes.MsgTimeoutResponse{Result: channeltypes.SUCCESS}, nil } // TimeoutOnClose defines a rpc handler method for MsgTimeoutOnClose. @@ -541,7 +541,7 @@ func (k Keeper) TimeoutOnClose(goCtx context.Context, msg *channeltypes.MsgTimeo case nil: writeFn() case channeltypes.ErrNoOpMsg: - return &channeltypes.MsgTimeoutOnCloseResponse{}, nil // no-op + return &channeltypes.MsgTimeoutOnCloseResponse{Result: channeltypes.NOOP}, nil default: return nil, sdkerrors.Wrap(err, "timeout on close packet verification failed") } @@ -574,7 +574,7 @@ func (k Keeper) TimeoutOnClose(goCtx context.Context, msg *channeltypes.MsgTimeo ) }() - return &channeltypes.MsgTimeoutOnCloseResponse{}, nil + return &channeltypes.MsgTimeoutOnCloseResponse{Result: channeltypes.SUCCESS}, nil } // Acknowledgement defines a rpc handler method for MsgAcknowledgement. @@ -612,7 +612,7 @@ func (k Keeper) Acknowledgement(goCtx context.Context, msg *channeltypes.MsgAckn case nil: writeFn() case channeltypes.ErrNoOpMsg: - return &channeltypes.MsgAcknowledgementResponse{}, nil // no-op + return &channeltypes.MsgAcknowledgementResponse{Result: channeltypes.NOOP}, nil default: return nil, sdkerrors.Wrap(err, "acknowledge packet verification failed") } @@ -636,5 +636,5 @@ func (k Keeper) Acknowledgement(goCtx context.Context, msg *channeltypes.MsgAckn ) }() - return &channeltypes.MsgAcknowledgementResponse{}, nil + return &channeltypes.MsgAcknowledgementResponse{Result: channeltypes.SUCCESS}, nil } diff --git a/modules/light-clients/07-tendermint/types/client_state.go b/modules/light-clients/07-tendermint/types/client_state.go index a0430337d0b..51f826979fd 100644 --- a/modules/light-clients/07-tendermint/types/client_state.go +++ b/modules/light-clients/07-tendermint/types/client_state.go @@ -78,7 +78,9 @@ func (cs ClientState) Status( // get latest consensus state from clientStore to check for expiry consState, err := GetConsensusState(clientStore, cdc, cs.GetLatestHeight()) if err != nil { - return exported.Unknown + // if the client state does not have an associated consensus state for its latest height + // then it must be expired + return exported.Expired } if cs.IsExpired(consState.Timestamp, ctx.BlockTime()) { diff --git a/modules/light-clients/07-tendermint/types/client_state_test.go b/modules/light-clients/07-tendermint/types/client_state_test.go index b0434579b76..cf52d2996b5 100644 --- a/modules/light-clients/07-tendermint/types/client_state_test.go +++ b/modules/light-clients/07-tendermint/types/client_state_test.go @@ -47,10 +47,10 @@ func (suite *TendermintTestSuite) TestStatus() { clientState.FrozenHeight = clienttypes.NewHeight(0, 1) path.EndpointA.SetClientState(clientState) }, exported.Frozen}, - {"client status is unknown", func() { + {"client status without consensus state", func() { clientState.LatestHeight = clientState.LatestHeight.Increment().(clienttypes.Height) path.EndpointA.SetClientState(clientState) - }, exported.Unknown}, + }, exported.Expired}, {"client status is expired", func() { suite.coordinator.IncrementTimeBy(clientState.TrustingPeriod) }, exported.Expired}, diff --git a/proto/ibc/core/channel/v1/tx.proto b/proto/ibc/core/channel/v1/tx.proto index 7fc8f730e33..d4d6df1d5e9 100644 --- a/proto/ibc/core/channel/v1/tx.proto +++ b/proto/ibc/core/channel/v1/tx.proto @@ -42,6 +42,18 @@ service Msg { rpc Acknowledgement(MsgAcknowledgement) returns (MsgAcknowledgementResponse); } +// ResponseResultType defines the possible outcomes of the execution of a message +enum ResponseResultType { + option (gogoproto.goproto_enum_prefix) = false; + + // Default zero value enumeration + RESPONSE_RESULT_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "UNSPECIFIED"]; + // The message did not call the IBC application callbacks (because, for example, the packet had already been relayed) + RESPONSE_RESULT_NOOP = 1 [(gogoproto.enumvalue_customname) = "NOOP"]; + // The message was executed successfully + RESPONSE_RESULT_SUCCESS = 2 [(gogoproto.enumvalue_customname) = "SUCCESS"]; +} + // MsgChannelOpenInit defines an sdk.Msg to initialize a channel handshake. It // is called by a relayer on Chain A. message MsgChannelOpenInit { @@ -163,7 +175,11 @@ message MsgRecvPacket { } // MsgRecvPacketResponse defines the Msg/RecvPacket response type. -message MsgRecvPacketResponse {} +message MsgRecvPacketResponse { + option (gogoproto.goproto_getters) = false; + + ResponseResultType result = 1; +} // MsgTimeout receives timed-out packet message MsgTimeout { @@ -179,7 +195,11 @@ message MsgTimeout { } // MsgTimeoutResponse defines the Msg/Timeout response type. -message MsgTimeoutResponse {} +message MsgTimeoutResponse { + option (gogoproto.goproto_getters) = false; + + ResponseResultType result = 1; +} // MsgTimeoutOnClose timed-out packet upon counterparty channel closure. message MsgTimeoutOnClose { @@ -196,7 +216,11 @@ message MsgTimeoutOnClose { } // MsgTimeoutOnCloseResponse defines the Msg/TimeoutOnClose response type. -message MsgTimeoutOnCloseResponse {} +message MsgTimeoutOnCloseResponse { + option (gogoproto.goproto_getters) = false; + + ResponseResultType result = 1; +} // MsgAcknowledgement receives incoming IBC acknowledgement message MsgAcknowledgement { @@ -212,4 +236,8 @@ message MsgAcknowledgement { } // MsgAcknowledgementResponse defines the Msg/Acknowledgement response type. -message MsgAcknowledgementResponse {} +message MsgAcknowledgementResponse { + option (gogoproto.goproto_getters) = false; + + ResponseResultType result = 1; +} diff --git a/scripts/protocgen.sh b/scripts/protocgen.sh index 1015709e861..efcfb36b30a 100755 --- a/scripts/protocgen.sh +++ b/scripts/protocgen.sh @@ -32,8 +32,6 @@ buf protoc \ --doc_out=./docs/ibc \ --doc_opt=./docs/protodoc-markdown.tmpl,proto-docs.md \ $(find "$(pwd)/proto" -maxdepth 5 -name '*.proto') -go mod tidy - # move proto files to the right places cp -r github.com/cosmos/ibc-go/v*/modules/* modules/ diff --git a/testing/README.md b/testing/README.md index 97f540d5c4c..ad02a80e640 100644 --- a/testing/README.md +++ b/testing/README.md @@ -296,6 +296,7 @@ The mock module may also be leveraged to act as a base application in the instan The mock IBC module contains a `MockIBCApp`. This struct contains a function field for every IBC App Module callback. Each of these functions can be individually set to mock expected behaviour of a base application. +The portID and scoped keeper for the `MockIBCApp` should be set within `MockIBCApp` before calling `NewIBCModule`. For example, if one wanted to test that the base application cannot affect the outcome of the `OnChanOpenTry` callback, the mock module base application callback could be updated as such: ```go diff --git a/testing/app.go b/testing/app.go index 1c5bbe7c88a..3c6a14ed453 100644 --- a/testing/app.go +++ b/testing/app.go @@ -58,8 +58,9 @@ func SetupTestingApp() (TestingApp, map[string]json.RawMessage) { // that also act as delegators. For simplicity, each validator is bonded with a delegation // of one consensus engine unit (10^6) in the default token of the simapp from first genesis // account. A Nop logger is set in SimApp. -func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, chainID string, balances ...banktypes.Balance) TestingApp { +func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, chainID string, powerReduction sdk.Int, balances ...banktypes.Balance) TestingApp { app, genesisState := DefaultTestingAppInit() + // set genesis accounts authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs) genesisState[authtypes.ModuleName] = app.AppCodec().MustMarshalJSON(authGenesis) @@ -67,7 +68,7 @@ func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs validators := make([]stakingtypes.Validator, 0, len(valSet.Validators)) delegations := make([]stakingtypes.Delegation, 0, len(valSet.Validators)) - bondAmt := sdk.NewInt(1000000) + bondAmt := sdk.TokensFromConsensusPower(1, powerReduction) for _, val := range valSet.Validators { pk, err := cryptocodec.FromTmPubKeyInterface(val.PubKey) @@ -87,26 +88,29 @@ func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs Commission: stakingtypes.NewCommission(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()), MinSelfDelegation: sdk.ZeroInt(), } + validators = append(validators, validator) delegations = append(delegations, stakingtypes.NewDelegation(genAccs[0].GetAddress(), val.Address.Bytes(), sdk.OneDec())) } // set validators and delegations - stakingGenesis := stakingtypes.NewGenesisState(stakingtypes.DefaultParams(), validators, delegations) - genesisState[stakingtypes.ModuleName] = app.AppCodec().MustMarshalJSON(stakingGenesis) + var stakingGenesis stakingtypes.GenesisState + app.AppCodec().MustUnmarshalJSON(genesisState[stakingtypes.ModuleName], &stakingGenesis) + + bondDenom := stakingGenesis.Params.BondDenom totalSupply := sdk.NewCoins() - for _, b := range balances { - // add genesis acc tokens and delegated tokens to total supply - totalSupply = totalSupply.Add(b.Coins.Add(sdk.NewCoin(sdk.DefaultBondDenom, bondAmt))...) - } // add bonded amount to bonded pool module account balances = append(balances, banktypes.Balance{ Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).String(), - Coins: sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, bondAmt)}, + Coins: sdk.Coins{sdk.NewCoin(bondDenom, bondAmt.Mul(sdk.NewInt(int64(len(valSet.Validators)))))}, }) + // set validators and delegations + stakingGenesis = *stakingtypes.NewGenesisState(stakingGenesis.Params, validators, delegations) + genesisState[stakingtypes.ModuleName] = app.AppCodec().MustMarshalJSON(&stakingGenesis) + // update total supply bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, totalSupply, []banktypes.Metadata{}) genesisState[banktypes.ModuleName] = app.AppCodec().MustMarshalJSON(bankGenesis) @@ -126,13 +130,17 @@ func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs // commit genesis changes app.Commit() - app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{ - ChainID: chainID, - Height: app.LastBlockHeight() + 1, - AppHash: app.LastCommitID().Hash, - ValidatorsHash: valSet.Hash(), - NextValidatorsHash: valSet.Hash(), - }}) + app.BeginBlock( + abci.RequestBeginBlock{ + Header: tmproto.Header{ + ChainID: chainID, + Height: app.LastBlockHeight() + 1, + AppHash: app.LastCommitID().Hash, + ValidatorsHash: valSet.Hash(), + NextValidatorsHash: valSet.Hash(), + }, + }, + ) return app } diff --git a/testing/chain.go b/testing/chain.go index 281782f7837..28382a6c463 100644 --- a/testing/chain.go +++ b/testing/chain.go @@ -36,13 +36,20 @@ import ( "github.com/cosmos/ibc-go/v3/testing/simapp" ) +var MaxAccounts = 10 + +type SenderAccount struct { + SenderPrivKey cryptotypes.PrivKey + SenderAccount authtypes.AccountI +} + // TestChain is a testing struct that wraps a simapp with the last TM Header, the current ABCI // header and the validators of the TestChain. It also contains a field called ChainID. This // is the clientID that *other* chains use to refer to this TestChain. The SenderAccount // is used for delivering transactions through the application state. // NOTE: the actual application uses an empty chain-id for ease of testing. type TestChain struct { - t *testing.T + *testing.T Coordinator *Coordinator App TestingApp @@ -56,41 +63,57 @@ type TestChain struct { Vals *tmtypes.ValidatorSet Signers []tmtypes.PrivValidator - senderPrivKey cryptotypes.PrivKey + // autogenerated sender private key + SenderPrivKey cryptotypes.PrivKey SenderAccount authtypes.AccountI + + SenderAccounts []SenderAccount } -// NewTestChain initializes a new TestChain instance with a single validator set using a -// generated private key. It also creates a sender account to be used for delivering transactions. +// NewTestChainWithValSet initializes a new TestChain instance with the given validator set +// and signer array. It also initializes 10 Sender accounts with a balance of 10000000000000000000 coins of +// bond denom to use for tests. // // The first block height is committed to state in order to allow for client creations on // counterparty chains. The TestChain will return with a block height starting at 2. // // Time management is handled by the Coordinator in order to ensure synchrony between chains. // Each update of any chain increments the block header time for all chains by 5 seconds. -func NewTestChain(t *testing.T, coord *Coordinator, chainID string) *TestChain { - // generate validator private/public key - privVal := mock.NewPV() - pubKey, err := privVal.GetPubKey() - require.NoError(t, err) - - // create validator set with single validator - validator := tmtypes.NewValidator(pubKey, 1) - valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{validator}) - signers := []tmtypes.PrivValidator{privVal} - - // generate genesis account - senderPrivKey := secp256k1.GenPrivKey() - acc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), 0, 0) - amount, ok := sdk.NewIntFromString("10000000000000000000") - require.True(t, ok) - - balance := banktypes.Balance{ - Address: acc.GetAddress().String(), - Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, amount)), +// +// NOTE: to use a custom sender privkey and account for testing purposes, replace and modify this +// constructor function. +// +// CONTRACT: Validator and signer array must be provided in the order expected by Tendermint. +// i.e. sorted first by power and then lexicographically by address. +func NewTestChainWithValSet(t *testing.T, coord *Coordinator, chainID string, valSet *tmtypes.ValidatorSet, signers []tmtypes.PrivValidator) *TestChain { + genAccs := []authtypes.GenesisAccount{} + genBals := []banktypes.Balance{} + senderAccs := []SenderAccount{} + + // generate genesis accounts + for i := 0; i < MaxAccounts; i++ { + senderPrivKey := secp256k1.GenPrivKey() + acc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), uint64(i), 0) + amount, ok := sdk.NewIntFromString("10000000000000000000") + require.True(t, ok) + + balance := banktypes.Balance{ + Address: acc.GetAddress().String(), + Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, amount)), + } + + genAccs = append(genAccs, acc) + genBals = append(genBals, balance) + + senderAcc := SenderAccount{ + SenderAccount: acc, + SenderPrivKey: senderPrivKey, + } + + senderAccs = append(senderAccs, senderAcc) } - app := SetupWithGenesisValSet(t, valSet, []authtypes.GenesisAccount{acc}, chainID, balance) + app := SetupWithGenesisValSet(t, valSet, genAccs, chainID, sdk.DefaultPowerReduction, genBals...) // create current header and call begin block header := tmproto.Header{ @@ -103,18 +126,19 @@ func NewTestChain(t *testing.T, coord *Coordinator, chainID string) *TestChain { // create an account to send transactions from chain := &TestChain{ - t: t, - Coordinator: coord, - ChainID: chainID, - App: app, - CurrentHeader: header, - QueryServer: app.GetIBCKeeper(), - TxConfig: txConfig, - Codec: app.AppCodec(), - Vals: valSet, - Signers: signers, - senderPrivKey: senderPrivKey, - SenderAccount: acc, + T: t, + Coordinator: coord, + ChainID: chainID, + App: app, + CurrentHeader: header, + QueryServer: app.GetIBCKeeper(), + TxConfig: txConfig, + Codec: app.AppCodec(), + Vals: valSet, + Signers: signers, + SenderPrivKey: senderAccs[0].SenderPrivKey, + SenderAccount: senderAccs[0].SenderAccount, + SenderAccounts: senderAccs, } coord.CommitBlock(chain) @@ -122,6 +146,38 @@ func NewTestChain(t *testing.T, coord *Coordinator, chainID string) *TestChain { return chain } +// NewTestChain initializes a new test chain with a default of 4 validators +// Use this function if the tests do not need custom control over the validator set +func NewTestChain(t *testing.T, coord *Coordinator, chainID string) *TestChain { + // generate validators private/public key + var ( + validatorsPerChain = 4 + validators []*tmtypes.Validator + signersByAddress = make(map[string]tmtypes.PrivValidator, validatorsPerChain) + ) + + for i := 0; i < validatorsPerChain; i++ { + privVal := mock.NewPV() + pubKey, err := privVal.GetPubKey() + require.NoError(t, err) + validators = append(validators, tmtypes.NewValidator(pubKey, 1)) + signersByAddress[pubKey.Address().String()] = privVal + } + + // construct validator set; + // Note that the validators are sorted by voting power + // or, if equal, by address lexical order + valSet := tmtypes.NewValidatorSet(validators) + + // create signers indexed by the valSet validators's order + signers := []tmtypes.PrivValidator{} + for _, val := range valSet.Validators { + signers = append(signers, signersByAddress[val.PubKey.Address().String()]) + } + + return NewTestChainWithValSet(t, coord, chainID, valSet, signers) +} + // GetContext returns the current context for the application. func (chain *TestChain) GetContext() sdk.Context { return chain.App.GetBaseApp().NewContext(false, chain.CurrentHeader) @@ -132,7 +188,7 @@ func (chain *TestChain) GetContext() sdk.Context { // their own SimApp. func (chain *TestChain) GetSimApp() *simapp.SimApp { app, ok := chain.App.(*simapp.SimApp) - require.True(chain.t, ok) + require.True(chain.T, ok) return app } @@ -154,10 +210,10 @@ func (chain *TestChain) QueryProofAtHeight(key []byte, height int64) ([]byte, cl }) merkleProof, err := commitmenttypes.ConvertProofs(res.ProofOps) - require.NoError(chain.t, err) + require.NoError(chain.T, err) proof, err := chain.App.AppCodec().Marshal(&merkleProof) - require.NoError(chain.t, err) + require.NoError(chain.T, err) revision := clienttypes.ParseChainID(chain.ChainID) @@ -178,10 +234,10 @@ func (chain *TestChain) QueryUpgradeProof(key []byte, height uint64) ([]byte, cl }) merkleProof, err := commitmenttypes.ConvertProofs(res.ProofOps) - require.NoError(chain.t, err) + require.NoError(chain.T, err) proof, err := chain.App.AppCodec().Marshal(&merkleProof) - require.NoError(chain.t, err) + require.NoError(chain.T, err) revision := clienttypes.ParseChainID(chain.ChainID) @@ -237,12 +293,11 @@ func (chain *TestChain) sendMsgs(msgs ...sdk.Msg) error { // number and updates the TestChain's headers. It returns the result and error if one // occurred. func (chain *TestChain) SendMsgs(msgs ...sdk.Msg) (*sdk.Result, error) { - // ensure the chain has the latest time chain.Coordinator.UpdateTimeForChain(chain) _, r, err := simapp.SignAndDeliver( - chain.t, + chain.T, chain.TxConfig, chain.App.GetBaseApp(), chain.GetContext().BlockHeader(), @@ -250,7 +305,7 @@ func (chain *TestChain) SendMsgs(msgs ...sdk.Msg) (*sdk.Result, error) { chain.ChainID, []uint64{chain.SenderAccount.GetAccountNumber()}, []uint64{chain.SenderAccount.GetSequence()}, - true, true, chain.senderPrivKey, + true, true, chain.SenderPrivKey, ) if err != nil { return nil, err @@ -271,7 +326,7 @@ func (chain *TestChain) SendMsgs(msgs ...sdk.Msg) (*sdk.Result, error) { // expected to exist otherwise testing will fail. func (chain *TestChain) GetClientState(clientID string) exported.ClientState { clientState, found := chain.App.GetIBCKeeper().ClientKeeper.GetClientState(chain.GetContext(), clientID) - require.True(chain.t, found) + require.True(chain.T, found) return clientState } @@ -303,7 +358,7 @@ func (chain *TestChain) GetValsAtHeight(height int64) (*tmtypes.ValidatorSet, bo // acknowledgement does not exist then testing will fail. func (chain *TestChain) GetAcknowledgement(packet exported.PacketI) []byte { ack, found := chain.App.GetIBCKeeper().ChannelKeeper.GetPacketAcknowledgement(chain.GetContext(), packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - require.True(chain.t, found) + require.True(chain.T, found) return ack } @@ -357,7 +412,6 @@ func (chain *TestChain) ConstructUpdateTMClientHeaderWithTrustedHeight(counterpa header.TrustedValidators = trustedVals return header, nil - } // ExpireClient fast forwards the chain's block time by the provided amount of time which will @@ -379,7 +433,7 @@ func (chain *TestChain) CreateTMClientHeader(chainID string, blockHeight int64, valSet *tmproto.ValidatorSet trustedVals *tmproto.ValidatorSet ) - require.NotNil(chain.t, tmValSet) + require.NotNil(chain.T, tmValSet) vsetHash := tmValSet.Hash() @@ -399,12 +453,13 @@ func (chain *TestChain) CreateTMClientHeader(chainID string, blockHeight int64, EvidenceHash: tmhash.Sum([]byte("evidence_hash")), ProposerAddress: tmValSet.Proposer.Address, //nolint:staticcheck } + hhash := tmHeader.Hash() blockID := MakeBlockID(hhash, 3, tmhash.Sum([]byte("part_set"))) voteSet := tmtypes.NewVoteSet(chainID, blockHeight, 1, tmproto.PrecommitType, tmValSet) commit, err := tmtypes.MakeCommit(blockID, blockHeight, 1, voteSet, signers, timestamp) - require.NoError(chain.t, err) + require.NoError(chain.T, err) signedHeader := &tmproto.SignedHeader{ Header: tmHeader.ToProto(), @@ -413,16 +468,12 @@ func (chain *TestChain) CreateTMClientHeader(chainID string, blockHeight int64, if tmValSet != nil { valSet, err = tmValSet.ToProto() - if err != nil { - panic(err) - } + require.NoError(chain.T, err) } if tmTrustedVals != nil { trustedVals, err = tmTrustedVals.ToProto() - if err != nil { - panic(err) - } + require.NoError(chain.T, err) } // The trusted fields may be nil. They may be filled before relaying messages to a client. @@ -451,8 +502,8 @@ func MakeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) tmtypes.Bl // sorting of ValidatorSet. // The sorting is first by .VotingPower (descending), with secondary index of .Address (ascending). func CreateSortedSignerArray(altPrivVal, suitePrivVal tmtypes.PrivValidator, - altVal, suiteVal *tmtypes.Validator) []tmtypes.PrivValidator { - + altVal, suiteVal *tmtypes.Validator, +) []tmtypes.PrivValidator { switch { case altVal.VotingPower > suiteVal.VotingPower: return []tmtypes.PrivValidator{altPrivVal, suitePrivVal} @@ -468,7 +519,7 @@ func CreateSortedSignerArray(altPrivVal, suitePrivVal tmtypes.PrivValidator, // CreatePortCapability binds and claims a capability for the given portID if it does not // already exist. This function will fail testing on any resulting error. -// NOTE: only creation of a capbility for a transfer or mock port is supported +// NOTE: only creation of a capability for a transfer or mock port is supported // Other applications must bind to the port in InitGenesis or modify this code. func (chain *TestChain) CreatePortCapability(scopedKeeper capabilitykeeper.ScopedKeeper, portID string) { // check if the portId is already binded, if not bind it @@ -476,11 +527,11 @@ func (chain *TestChain) CreatePortCapability(scopedKeeper capabilitykeeper.Scope if !ok { // create capability using the IBC capability keeper cap, err := chain.App.GetScopedIBCKeeper().NewCapability(chain.GetContext(), host.PortPath(portID)) - require.NoError(chain.t, err) + require.NoError(chain.T, err) // claim capability using the scopedKeeper err = scopedKeeper.ClaimCapability(chain.GetContext(), cap, host.PortPath(portID)) - require.NoError(chain.t, err) + require.NoError(chain.T, err) } chain.App.Commit() @@ -492,7 +543,7 @@ func (chain *TestChain) CreatePortCapability(scopedKeeper capabilitykeeper.Scope // exist, otherwise testing will fail. func (chain *TestChain) GetPortCapability(portID string) *capabilitytypes.Capability { cap, ok := chain.App.GetScopedIBCKeeper().GetCapability(chain.GetContext(), host.PortPath(portID)) - require.True(chain.t, ok) + require.True(chain.T, ok) return cap } @@ -506,9 +557,9 @@ func (chain *TestChain) CreateChannelCapability(scopedKeeper capabilitykeeper.Sc _, ok := chain.App.GetScopedIBCKeeper().GetCapability(chain.GetContext(), capName) if !ok { cap, err := chain.App.GetScopedIBCKeeper().NewCapability(chain.GetContext(), capName) - require.NoError(chain.t, err) + require.NoError(chain.T, err) err = scopedKeeper.ClaimCapability(chain.GetContext(), cap, capName) - require.NoError(chain.t, err) + require.NoError(chain.T, err) } chain.App.Commit() @@ -520,7 +571,7 @@ func (chain *TestChain) CreateChannelCapability(scopedKeeper capabilitykeeper.Sc // The capability must exist, otherwise testing will fail. func (chain *TestChain) GetChannelCapability(portID, channelID string) *capabilitytypes.Capability { cap, ok := chain.App.GetScopedIBCKeeper().GetCapability(chain.GetContext(), host.ChannelCapabilityPath(portID, channelID)) - require.True(chain.t, ok) + require.True(chain.T, ok) return cap } diff --git a/testing/coordinator.go b/testing/coordinator.go index 615bd830ced..217c257473a 100644 --- a/testing/coordinator.go +++ b/testing/coordinator.go @@ -19,7 +19,7 @@ var ( // Coordinator is a testing struct which contains N TestChain's. It handles keeping all chains // in sync with regards to time. type Coordinator struct { - t *testing.T + *testing.T CurrentTime time.Time Chains map[string]*TestChain @@ -29,7 +29,7 @@ type Coordinator struct { func NewCoordinator(t *testing.T, n int) *Coordinator { chains := make(map[string]*TestChain) coord := &Coordinator{ - t: t, + T: t, CurrentTime: globalStartTime, } @@ -55,7 +55,6 @@ func (coord *Coordinator) IncrementTime() { func (coord *Coordinator) IncrementTimeBy(increment time.Duration) { coord.CurrentTime = coord.CurrentTime.Add(increment).UTC() coord.UpdateTime() - } // UpdateTime updates all clocks for the TestChains to the current global time. @@ -85,10 +84,10 @@ func (coord *Coordinator) Setup(path *Path) { // caller does not anticipate any errors. func (coord *Coordinator) SetupClients(path *Path) { err := path.EndpointA.CreateClient() - require.NoError(coord.t, err) + require.NoError(coord.T, err) err = path.EndpointB.CreateClient() - require.NoError(coord.t, err) + require.NoError(coord.T, err) } // SetupClientConnections is a helper function to create clients and the appropriate @@ -105,21 +104,21 @@ func (coord *Coordinator) SetupConnections(path *Path) { // are returned within a TestConnection struct. The function expects the connections to be // successfully opened otherwise testing will fail. func (coord *Coordinator) CreateConnections(path *Path) { - err := path.EndpointA.ConnOpenInit() - require.NoError(coord.t, err) + require.NoError(coord.T, err) err = path.EndpointB.ConnOpenTry() - require.NoError(coord.t, err) + require.NoError(coord.T, err) err = path.EndpointA.ConnOpenAck() - require.NoError(coord.t, err) + require.NoError(coord.T, err) err = path.EndpointB.ConnOpenConfirm() - require.NoError(coord.t, err) + require.NoError(coord.T, err) // ensure counterparty is up to date - path.EndpointA.UpdateClient() + err = path.EndpointA.UpdateClient() + require.NoError(coord.T, err) } // CreateMockChannels constructs and executes channel handshake messages to create OPEN @@ -148,26 +147,27 @@ func (coord *Coordinator) CreateTransferChannels(path *Path) { // opened otherwise testing will fail. func (coord *Coordinator) CreateChannels(path *Path) { err := path.EndpointA.ChanOpenInit() - require.NoError(coord.t, err) + require.NoError(coord.T, err) err = path.EndpointB.ChanOpenTry() - require.NoError(coord.t, err) + require.NoError(coord.T, err) err = path.EndpointA.ChanOpenAck() - require.NoError(coord.t, err) + require.NoError(coord.T, err) err = path.EndpointB.ChanOpenConfirm() - require.NoError(coord.t, err) + require.NoError(coord.T, err) // ensure counterparty is up to date - path.EndpointA.UpdateClient() + err = path.EndpointA.UpdateClient() + require.NoError(coord.T, err) } // GetChain returns the TestChain using the given chainID and returns an error if it does // not exist. func (coord *Coordinator) GetChain(chainID string) *TestChain { chain, found := coord.Chains[chainID] - require.True(coord.t, found, fmt.Sprintf("%s chain does not exist", chainID)) + require.True(coord.T, found, fmt.Sprintf("%s chain does not exist", chainID)) return chain } @@ -212,11 +212,7 @@ func (coord *Coordinator) ConnOpenInitOnBothChains(path *Path) error { return err } - if err := path.EndpointB.UpdateClient(); err != nil { - return err - } - - return nil + return path.EndpointB.UpdateClient() } // ChanOpenInitOnBothChains initializes a channel on the source chain and counterparty chain @@ -237,9 +233,5 @@ func (coord *Coordinator) ChanOpenInitOnBothChains(path *Path) error { return err } - if err := path.EndpointB.UpdateClient(); err != nil { - return err - } - - return nil + return path.EndpointB.UpdateClient() } diff --git a/testing/endpoint.go b/testing/endpoint.go index 962ecf5ef35..607f7a16843 100644 --- a/testing/endpoint.go +++ b/testing/endpoint.go @@ -67,7 +67,7 @@ func (endpoint *Endpoint) QueryProof(key []byte) ([]byte, clienttypes.Height) { } // QueryProofAtHeight queries proof associated with this endpoint using the proof height -// providied +// provided func (endpoint *Endpoint) QueryProofAtHeight(key []byte, height uint64) ([]byte, clienttypes.Height) { // query proof on the counterparty using the latest height of the IBC client return endpoint.Chain.QueryProofAtHeight(key, int64(height)) @@ -88,7 +88,7 @@ func (endpoint *Endpoint) CreateClient() (err error) { switch endpoint.ClientConfig.GetClientType() { case exported.Tendermint: tmConfig, ok := endpoint.ClientConfig.(*TendermintConfig) - require.True(endpoint.Chain.t, ok) + require.True(endpoint.Chain.T, ok) height := endpoint.Counterparty.Chain.LastHeader.GetHeight().(clienttypes.Height) clientState = ibctmtypes.NewClientState( @@ -98,7 +98,7 @@ func (endpoint *Endpoint) CreateClient() (err error) { consensusState = endpoint.Counterparty.Chain.LastHeader.ConsensusState() case exported.Solomachine: // TODO - // solo := NewSolomachine(chain.t, endpoint.Chain.Codec, clientID, "", 1) + // solo := NewSolomachine(endpoint.Chain.T, endpoint.Chain.Codec, clientID, "", 1) // clientState = solo.ClientState() // consensusState = solo.ConsensusState() @@ -113,7 +113,7 @@ func (endpoint *Endpoint) CreateClient() (err error) { msg, err := clienttypes.NewMsgCreateClient( clientState, consensusState, endpoint.Chain.SenderAccount.GetAddress().String(), ) - require.NoError(endpoint.Chain.t, err) + require.NoError(endpoint.Chain.T, err) res, err := endpoint.Chain.SendMsgs(msg) if err != nil { @@ -121,7 +121,7 @@ func (endpoint *Endpoint) CreateClient() (err error) { } endpoint.ClientID, err = ParseClientIDFromEvents(res.GetEvents()) - require.NoError(endpoint.Chain.t, err) + require.NoError(endpoint.Chain.T, err) return nil } @@ -131,9 +131,7 @@ func (endpoint *Endpoint) UpdateClient() (err error) { // ensure counterparty has committed state endpoint.Chain.Coordinator.CommitBlock(endpoint.Counterparty.Chain) - var ( - header exported.Header - ) + var header exported.Header switch endpoint.ClientConfig.GetClientType() { case exported.Tendermint: @@ -151,10 +149,9 @@ func (endpoint *Endpoint) UpdateClient() (err error) { endpoint.ClientID, header, endpoint.Chain.SenderAccount.GetAddress().String(), ) - require.NoError(endpoint.Chain.t, err) + require.NoError(endpoint.Chain.T, err) return endpoint.Chain.sendMsgs(msg) - } // ConnOpenInit will construct and execute a MsgConnectionOpenInit on the associated endpoint. @@ -171,14 +168,15 @@ func (endpoint *Endpoint) ConnOpenInit() error { } endpoint.ConnectionID, err = ParseConnectionIDFromEvents(res.GetEvents()) - require.NoError(endpoint.Chain.t, err) + require.NoError(endpoint.Chain.T, err) return nil } // ConnOpenTry will construct and execute a MsgConnectionOpenTry on the associated endpoint. func (endpoint *Endpoint) ConnOpenTry() error { - endpoint.UpdateClient() + err := endpoint.UpdateClient() + require.NoError(endpoint.Chain.T, err) counterpartyClient, proofClient, proofConsensus, consensusHeight, proofInit, proofHeight := endpoint.QueryConnectionHandshakeProof() @@ -197,7 +195,7 @@ func (endpoint *Endpoint) ConnOpenTry() error { if endpoint.ConnectionID == "" { endpoint.ConnectionID, err = ParseConnectionIDFromEvents(res.GetEvents()) - require.NoError(endpoint.Chain.t, err) + require.NoError(endpoint.Chain.T, err) } return nil @@ -205,7 +203,8 @@ func (endpoint *Endpoint) ConnOpenTry() error { // ConnOpenAck will construct and execute a MsgConnectionOpenAck on the associated endpoint. func (endpoint *Endpoint) ConnOpenAck() error { - endpoint.UpdateClient() + err := endpoint.UpdateClient() + require.NoError(endpoint.Chain.T, err) counterpartyClient, proofClient, proofConsensus, consensusHeight, proofTry, proofHeight := endpoint.QueryConnectionHandshakeProof() @@ -221,7 +220,8 @@ func (endpoint *Endpoint) ConnOpenAck() error { // ConnOpenConfirm will construct and execute a MsgConnectionOpenConfirm on the associated endpoint. func (endpoint *Endpoint) ConnOpenConfirm() error { - endpoint.UpdateClient() + err := endpoint.UpdateClient() + require.NoError(endpoint.Chain.T, err) connectionKey := host.ConnectionKey(endpoint.Counterparty.ConnectionID) proof, height := endpoint.Counterparty.Chain.QueryProof(connectionKey) @@ -277,14 +277,15 @@ func (endpoint *Endpoint) ChanOpenInit() error { } endpoint.ChannelID, err = ParseChannelIDFromEvents(res.GetEvents()) - require.NoError(endpoint.Chain.t, err) + require.NoError(endpoint.Chain.T, err) return nil } // ChanOpenTry will construct and execute a MsgChannelOpenTry on the associated endpoint. func (endpoint *Endpoint) ChanOpenTry() error { - endpoint.UpdateClient() + err := endpoint.UpdateClient() + require.NoError(endpoint.Chain.T, err) channelKey := host.ChannelKey(endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID) proof, height := endpoint.Counterparty.Chain.QueryProof(channelKey) @@ -303,7 +304,7 @@ func (endpoint *Endpoint) ChanOpenTry() error { if endpoint.ChannelID == "" { endpoint.ChannelID, err = ParseChannelIDFromEvents(res.GetEvents()) - require.NoError(endpoint.Chain.t, err) + require.NoError(endpoint.Chain.T, err) } // update version to selected app version @@ -315,7 +316,8 @@ func (endpoint *Endpoint) ChanOpenTry() error { // ChanOpenAck will construct and execute a MsgChannelOpenAck on the associated endpoint. func (endpoint *Endpoint) ChanOpenAck() error { - endpoint.UpdateClient() + err := endpoint.UpdateClient() + require.NoError(endpoint.Chain.T, err) channelKey := host.ChannelKey(endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID) proof, height := endpoint.Counterparty.Chain.QueryProof(channelKey) @@ -331,7 +333,8 @@ func (endpoint *Endpoint) ChanOpenAck() error { // ChanOpenConfirm will construct and execute a MsgChannelOpenConfirm on the associated endpoint. func (endpoint *Endpoint) ChanOpenConfirm() error { - endpoint.UpdateClient() + err := endpoint.UpdateClient() + require.NoError(endpoint.Chain.T, err) channelKey := host.ChannelKey(endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID) proof, height := endpoint.Counterparty.Chain.QueryProof(channelKey) @@ -449,7 +452,7 @@ func (endpoint *Endpoint) TimeoutPacket(packet channeltypes.Packet) error { proof, proofHeight := endpoint.Counterparty.QueryProof(packetKey) nextSeqRecv, found := endpoint.Counterparty.Chain.App.GetIBCKeeper().ChannelKeeper.GetNextSequenceRecv(endpoint.Counterparty.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID) - require.True(endpoint.Chain.t, found) + require.True(endpoint.Chain.T, found) timeoutMsg := channeltypes.NewMsgTimeout( packet, nextSeqRecv, @@ -459,6 +462,36 @@ func (endpoint *Endpoint) TimeoutPacket(packet channeltypes.Packet) error { return endpoint.Chain.sendMsgs(timeoutMsg) } +// TimeoutOnClose sends a MsgTimeoutOnClose to the channel associated with the endpoint. +func (endpoint *Endpoint) TimeoutOnClose(packet channeltypes.Packet) error { + // get proof for timeout based on channel order + var packetKey []byte + + switch endpoint.ChannelConfig.Order { + case channeltypes.ORDERED: + packetKey = host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel()) + case channeltypes.UNORDERED: + packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) + default: + return fmt.Errorf("unsupported order type %s", endpoint.ChannelConfig.Order) + } + + proof, proofHeight := endpoint.Counterparty.QueryProof(packetKey) + + channelKey := host.ChannelKey(packet.GetDestPort(), packet.GetDestChannel()) + proofClosed, _ := endpoint.Counterparty.QueryProof(channelKey) + + nextSeqRecv, found := endpoint.Counterparty.Chain.App.GetIBCKeeper().ChannelKeeper.GetNextSequenceRecv(endpoint.Counterparty.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID) + require.True(endpoint.Chain.T, found) + + timeoutOnCloseMsg := channeltypes.NewMsgTimeoutOnClose( + packet, nextSeqRecv, + proof, proofClosed, proofHeight, endpoint.Chain.SenderAccount.GetAddress().String(), + ) + + return endpoint.Chain.sendMsgs(timeoutOnCloseMsg) +} + // SetChannelClosed sets a channel state to CLOSED. func (endpoint *Endpoint) SetChannelClosed() error { channel := endpoint.GetChannel() @@ -486,7 +519,7 @@ func (endpoint *Endpoint) SetClientState(clientState exported.ClientState) { // The consensus state is expected to exist otherwise testing will fail. func (endpoint *Endpoint) GetConsensusState(height exported.Height) exported.ConsensusState { consensusState, found := endpoint.Chain.GetConsensusState(endpoint.ClientID, height) - require.True(endpoint.Chain.t, found) + require.True(endpoint.Chain.T, found) return consensusState } @@ -500,7 +533,7 @@ func (endpoint *Endpoint) SetConsensusState(consensusState exported.ConsensusSta // connection is expected to exist otherwise testing will fail. func (endpoint *Endpoint) GetConnection() connectiontypes.ConnectionEnd { connection, found := endpoint.Chain.App.GetIBCKeeper().ConnectionKeeper.GetConnection(endpoint.Chain.GetContext(), endpoint.ConnectionID) - require.True(endpoint.Chain.t, found) + require.True(endpoint.Chain.T, found) return connection } @@ -514,7 +547,7 @@ func (endpoint *Endpoint) SetConnection(connection connectiontypes.ConnectionEnd // is expected to exist otherwise testing will fail. func (endpoint *Endpoint) GetChannel() channeltypes.Channel { channel, found := endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.GetChannel(endpoint.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID) - require.True(endpoint.Chain.t, found) + require.True(endpoint.Chain.T, found) return channel } diff --git a/testing/events.go b/testing/events.go index 037a4c342e3..7828b42619f 100644 --- a/testing/events.go +++ b/testing/events.go @@ -2,6 +2,7 @@ package ibctesting import ( "fmt" + "strconv" sdk "github.com/cosmos/cosmos-sdk/types" @@ -56,6 +57,65 @@ func ParseChannelIDFromEvents(events sdk.Events) (string, error) { return "", fmt.Errorf("channel identifier event attribute not found") } +// ParsePacketFromEvents parses events emitted from a MsgRecvPacket and returns the +// acknowledgement. +func ParsePacketFromEvents(events sdk.Events) (channeltypes.Packet, error) { + for _, ev := range events { + if ev.Type == channeltypes.EventTypeSendPacket { + packet := channeltypes.Packet{} + for _, attr := range ev.Attributes { + + switch string(attr.Key) { + case channeltypes.AttributeKeyData: + packet.Data = attr.Value + + case channeltypes.AttributeKeySequence: + seq, err := strconv.ParseUint(string(attr.Value), 10, 64) + if err != nil { + return channeltypes.Packet{}, err + } + + packet.Sequence = seq + + case channeltypes.AttributeKeySrcPort: + packet.SourcePort = string(attr.Value) + + case channeltypes.AttributeKeySrcChannel: + packet.SourceChannel = string(attr.Value) + + case channeltypes.AttributeKeyDstPort: + packet.DestinationPort = string(attr.Value) + + case channeltypes.AttributeKeyDstChannel: + packet.DestinationChannel = string(attr.Value) + + case channeltypes.AttributeKeyTimeoutHeight: + height, err := clienttypes.ParseHeight(string(attr.Value)) + if err != nil { + return channeltypes.Packet{}, err + } + + packet.TimeoutHeight = height + + case channeltypes.AttributeKeyTimeoutTimestamp: + timestamp, err := strconv.ParseUint(string(attr.Value), 10, 64) + if err != nil { + return channeltypes.Packet{}, err + } + + packet.TimeoutTimestamp = timestamp + + default: + continue + } + } + + return packet, nil + } + } + return channeltypes.Packet{}, fmt.Errorf("acknowledgement event attribute not found") +} + // ParseAckFromEvents parses events emitted from a MsgRecvPacket and returns the // acknowledgement. func ParseAckFromEvents(events sdk.Events) ([]byte, error) { diff --git a/testing/mock/ibc_app.go b/testing/mock/ibc_app.go index a3f2db3bc6d..77eb17b8c6f 100644 --- a/testing/mock/ibc_app.go +++ b/testing/mock/ibc_app.go @@ -2,6 +2,7 @@ package mock import ( sdk "github.com/cosmos/cosmos-sdk/types" + capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" @@ -10,6 +11,9 @@ import ( // MockIBCApp contains IBC application module callbacks as defined in 05-port. type MockIBCApp struct { + PortID string + ScopedKeeper capabilitykeeper.ScopedKeeper + OnChanOpenInit func( ctx sdk.Context, order channeltypes.Order, @@ -36,6 +40,7 @@ type MockIBCApp struct { ctx sdk.Context, portID, channelID string, + counterpartyChannelID string, counterpartyVersion string, ) error @@ -81,3 +86,11 @@ type MockIBCApp struct { relayer sdk.AccAddress, ) error } + +// NewMockIBCApp returns a MockIBCApp. An empty PortID indicates the mock app doesn't bind/claim ports. +func NewMockIBCApp(portID string, scopedKeeper capabilitykeeper.ScopedKeeper) *MockIBCApp { + return &MockIBCApp{ + PortID: portID, + ScopedKeeper: scopedKeeper, + } +} diff --git a/testing/mock/ibc_module.go b/testing/mock/ibc_module.go index fb46864709b..e58f6ae7156 100644 --- a/testing/mock/ibc_module.go +++ b/testing/mock/ibc_module.go @@ -6,7 +6,6 @@ import ( "strconv" sdk "github.com/cosmos/cosmos-sdk/types" - capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" @@ -16,15 +15,16 @@ import ( // IBCModule implements the ICS26 callbacks for testing/mock. type IBCModule struct { - IBCApp *MockIBCApp // base application of an IBC middleware stack - scopedKeeper capabilitykeeper.ScopedKeeper + appModule *AppModule + IBCApp *MockIBCApp // base application of an IBC middleware stack } // NewIBCModule creates a new IBCModule given the underlying mock IBC application and scopedKeeper. -func NewIBCModule(app *MockIBCApp, scopedKeeper capabilitykeeper.ScopedKeeper) IBCModule { +func NewIBCModule(appModule *AppModule, app *MockIBCApp) IBCModule { + appModule.ibcApps = append(appModule.ibcApps, app) return IBCModule{ - IBCApp: app, - scopedKeeper: scopedKeeper, + appModule: appModule, + IBCApp: app, } } @@ -39,7 +39,7 @@ func (im IBCModule) OnChanOpenInit( } // Claim channel capability passed back by IBC module - if err := im.scopedKeeper.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil { + if err := im.IBCApp.ScopedKeeper.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil { return err } @@ -56,7 +56,7 @@ func (im IBCModule) OnChanOpenTry( } // Claim channel capability passed back by IBC module - if err := im.scopedKeeper.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil { + if err := im.IBCApp.ScopedKeeper.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil { return "", err } @@ -64,9 +64,9 @@ func (im IBCModule) OnChanOpenTry( } // OnChanOpenAck implements the IBCModule interface. -func (im IBCModule) OnChanOpenAck(ctx sdk.Context, portID string, channelID string, counterpartyVersion string) error { +func (im IBCModule) OnChanOpenAck(ctx sdk.Context, portID string, channelID string, counterpartyChannelID string, counterpartyVersion string) error { if im.IBCApp.OnChanOpenAck != nil { - return im.IBCApp.OnChanOpenAck(ctx, portID, channelID, counterpartyVersion) + return im.IBCApp.OnChanOpenAck(ctx, portID, channelID, counterpartyChannelID, counterpartyVersion) } return nil @@ -107,7 +107,7 @@ func (im IBCModule) OnRecvPacket(ctx sdk.Context, packet channeltypes.Packet, re // set state by claiming capability to check if revert happens return capName := GetMockRecvCanaryCapabilityName(packet) - if _, err := im.scopedKeeper.NewCapability(ctx, capName); err != nil { + if _, err := im.IBCApp.ScopedKeeper.NewCapability(ctx, capName); err != nil { // application callback called twice on same packet sequence // must never occur panic(err) @@ -129,7 +129,7 @@ func (im IBCModule) OnAcknowledgementPacket(ctx sdk.Context, packet channeltypes } capName := GetMockAckCanaryCapabilityName(packet) - if _, err := im.scopedKeeper.NewCapability(ctx, capName); err != nil { + if _, err := im.IBCApp.ScopedKeeper.NewCapability(ctx, capName); err != nil { // application callback called twice on same packet sequence // must never occur panic(err) @@ -145,7 +145,7 @@ func (im IBCModule) OnTimeoutPacket(ctx sdk.Context, packet channeltypes.Packet, } capName := GetMockTimeoutCanaryCapabilityName(packet) - if _, err := im.scopedKeeper.NewCapability(ctx, capName); err != nil { + if _, err := im.IBCApp.ScopedKeeper.NewCapability(ctx, capName); err != nil { // application callback called twice on same packet sequence // must never occur panic(err) diff --git a/testing/mock/mock.go b/testing/mock/mock.go index fd454aa80d9..b621a05e9f7 100644 --- a/testing/mock/mock.go +++ b/testing/mock/mock.go @@ -8,7 +8,6 @@ import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" - capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" "github.com/gorilla/mux" "github.com/grpc-ecosystem/grpc-gateway/runtime" @@ -44,6 +43,7 @@ var _ porttypes.IBCModule = IBCModule{} // PortKeeper defines the expected IBC port keeper type PortKeeper interface { BindPort(ctx sdk.Context, portID string) *capabilitytypes.Capability + IsBound(ctx sdk.Context, portID string) bool } // AppModuleBasic is the mock AppModuleBasic. @@ -89,15 +89,14 @@ func (AppModuleBasic) GetQueryCmd() *cobra.Command { // AppModule represents the AppModule for the mock module. type AppModule struct { AppModuleBasic - scopedKeeper capabilitykeeper.ScopedKeeper - portKeeper PortKeeper + ibcApps []*MockIBCApp + portKeeper PortKeeper } // NewAppModule returns a mock AppModule instance. -func NewAppModule(sk capabilitykeeper.ScopedKeeper, pk PortKeeper) AppModule { +func NewAppModule(pk PortKeeper) AppModule { return AppModule{ - scopedKeeper: sk, - portKeeper: pk, + portKeeper: pk, } } @@ -124,9 +123,13 @@ func (am AppModule) RegisterServices(module.Configurator) {} // InitGenesis implements the AppModule interface. func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate { - // bind mock port ID - cap := am.portKeeper.BindPort(ctx, ModuleName) - am.scopedKeeper.ClaimCapability(ctx, cap, host.PortPath(ModuleName)) + for _, ibcApp := range am.ibcApps { + if ibcApp.PortID != "" && !am.portKeeper.IsBound(ctx, ibcApp.PortID) { + // bind mock portID + cap := am.portKeeper.BindPort(ctx, ibcApp.PortID) + ibcApp.ScopedKeeper.ClaimCapability(ctx, cap, host.PortPath(ibcApp.PortID)) + } + } return []abci.ValidatorUpdate{} } diff --git a/testing/path.go b/testing/path.go index d447102c7b9..731d3cd5e1b 100644 --- a/testing/path.go +++ b/testing/path.go @@ -43,7 +43,9 @@ func (path *Path) RelayPacket(packet channeltypes.Packet) error { if bytes.Equal(pc, channeltypes.CommitPacket(path.EndpointA.Chain.App.AppCodec(), packet)) { // packet found, relay from A to B - path.EndpointB.UpdateClient() + if err := path.EndpointB.UpdateClient(); err != nil { + return err + } res, err := path.EndpointB.RecvPacketWithResult(packet) if err != nil { @@ -58,15 +60,17 @@ func (path *Path) RelayPacket(packet channeltypes.Packet) error { if err := path.EndpointA.AcknowledgePacket(packet, ack); err != nil { return err } - return nil + return nil } pc = path.EndpointB.Chain.App.GetIBCKeeper().ChannelKeeper.GetPacketCommitment(path.EndpointB.Chain.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) if bytes.Equal(pc, channeltypes.CommitPacket(path.EndpointB.Chain.App.AppCodec(), packet)) { // packet found, relay B to A - path.EndpointA.UpdateClient() + if err := path.EndpointA.UpdateClient(); err != nil { + return err + } res, err := path.EndpointA.RecvPacketWithResult(packet) if err != nil { diff --git a/testing/simapp/ante_handler.go b/testing/simapp/ante_handler.go index 8e3e1f069ec..04ffad13e2a 100644 --- a/testing/simapp/ante_handler.go +++ b/testing/simapp/ante_handler.go @@ -5,16 +5,15 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/auth/ante" - channelkeeper "github.com/cosmos/ibc-go/v3/modules/core/04-channel/keeper" ibcante "github.com/cosmos/ibc-go/v3/modules/core/ante" + "github.com/cosmos/ibc-go/v3/modules/core/keeper" ) -// HandlerOptions extend the SDK's AnteHandler options by requiring the IBC -// channel keeper. +// HandlerOptions extend the SDK's AnteHandler options by requiring the IBC keeper. type HandlerOptions struct { ante.HandlerOptions - IBCChannelkeeper channelkeeper.Keeper + IBCKeeper *keeper.Keeper } // NewAnteHandler creates a new ante handler @@ -49,7 +48,7 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) { ante.NewSigGasConsumeDecorator(options.AccountKeeper, sigGasConsumer), ante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler), ante.NewIncrementSequenceDecorator(options.AccountKeeper), - ibcante.NewAnteDecorator(options.IBCChannelkeeper), + ibcante.NewAnteDecorator(options.IBCKeeper), } return sdk.ChainAnteDecorators(anteDecorators...), nil diff --git a/testing/simapp/app.go b/testing/simapp/app.go index 890d7c4661d..ee148806852 100644 --- a/testing/simapp/app.go +++ b/testing/simapp/app.go @@ -350,8 +350,8 @@ func NewSimApp( // NOTE: the IBC mock keeper and application module is used only for testing core IBC. Do // not replicate if you do not need to test core IBC or light clients. - mockModule := ibcmock.NewAppModule(scopedIBCMockKeeper, &app.IBCKeeper.PortKeeper) - mockIBCModule := ibcmock.NewIBCModule(&ibcmock.MockIBCApp{}, scopedIBCMockKeeper) + mockModule := ibcmock.NewAppModule(&app.IBCKeeper.PortKeeper) + mockIBCModule := ibcmock.NewIBCModule(&mockModule, ibcmock.NewMockIBCApp(ibcmock.ModuleName, scopedIBCMockKeeper)) app.ICAControllerKeeper = icacontrollerkeeper.NewKeeper( appCodec, keys[icacontrollertypes.StoreKey], app.GetSubspace(icacontrollertypes.SubModuleName), @@ -369,7 +369,7 @@ func NewSimApp( icaModule := ica.NewAppModule(&app.ICAControllerKeeper, &app.ICAHostKeeper) // initialize ICA module with mock module as the authentication module on the controller side - icaAuthModule := ibcmock.NewIBCModule(&ibcmock.MockIBCApp{}, scopedICAMockKeeper) + icaAuthModule := ibcmock.NewIBCModule(&mockModule, ibcmock.NewMockIBCApp("", scopedICAMockKeeper)) app.ICAAuthModule = icaAuthModule icaControllerIBCModule := icacontroller.NewIBCModule(app.ICAControllerKeeper, icaAuthModule) @@ -503,7 +503,7 @@ func NewSimApp( FeegrantKeeper: app.FeeGrantKeeper, SigGasConsumer: ante.DefaultSigVerificationGasConsumer, }, - IBCChannelkeeper: app.IBCKeeper.ChannelKeeper, + IBCKeeper: app.IBCKeeper, }, ) if err != nil { @@ -571,6 +571,12 @@ func (app *SimApp) ModuleAccountAddrs() map[string]bool { return modAccAddrs } +// GetModuleManager returns the app module manager +// NOTE: used for testing purposes +func (app *SimApp) GetModuleManager() *module.Manager { + return app.mm +} + // LegacyAmino returns SimApp's amino codec. // // NOTE: This is solely to be used for testing purposes as it may be desirable