diff --git a/.changelog/unreleased/breaking-changes/3548-cometbft-0.38.md b/.changelog/unreleased/breaking-changes/3548-cometbft-0.38.md deleted file mode 100644 index d2b1f2e5bf..0000000000 --- a/.changelog/unreleased/breaking-changes/3548-cometbft-0.38.md +++ /dev/null @@ -1,2 +0,0 @@ -- Update to tendermint-rs 0.33 and ibc-proto 0.33 - ([\#3548](https://github.com/informalsystems/hermes/issues/3548)) diff --git a/.changelog/unreleased/breaking-changes/3688-msrv.md b/.changelog/unreleased/breaking-changes/3688-msrv.md new file mode 100644 index 0000000000..2d062fe92a --- /dev/null +++ b/.changelog/unreleased/breaking-changes/3688-msrv.md @@ -0,0 +1,2 @@ +- Bump MSRV to 1.71 + ([\#3688](https://github.com/informalsystems/hermes/issues/3688)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/ibc-relayer-cli/3636-config-chain-type.md b/.changelog/unreleased/breaking-changes/ibc-relayer-cli/3636-config-chain-type.md new file mode 100644 index 0000000000..601455dec7 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/ibc-relayer-cli/3636-config-chain-type.md @@ -0,0 +1,8 @@ +- The `type` key in the `[[chains]]` section is now required. ([\#3636](https://github.com/informalsystems/hermes/issues/3636)) + If you previously did not specify that key, you must now set it to `type = "CosmosSdk"`, eg. + + ```rust + [[chains]] + id = "osmosis-1" + type = "CosmosSdk" + ``` diff --git a/.changelog/unreleased/features/ibc-integration-test/3455-async-icq-test.md b/.changelog/unreleased/features/ibc-integration-test/3455-async-icq-test.md new file mode 100644 index 0000000000..8be8d1f42b --- /dev/null +++ b/.changelog/unreleased/features/ibc-integration-test/3455-async-icq-test.md @@ -0,0 +1,2 @@ +- Add a test for asynchronous Interchain Query relaying + ([\#3455](https://github.com/informalsystems/hermes/issues/3455)) \ No newline at end of file diff --git a/.changelog/unreleased/features/ibc-relayer-cli/3696-new-chain-upgrade-flag.md b/.changelog/unreleased/features/ibc-relayer-cli/3696-new-chain-upgrade-flag.md new file mode 100644 index 0000000000..125422b3d5 --- /dev/null +++ b/.changelog/unreleased/features/ibc-relayer-cli/3696-new-chain-upgrade-flag.md @@ -0,0 +1,3 @@ +- Add a `--gov-account` option to `hermes tx upgrade-chain` to specify the + authority account used to sign upgrade proposal for chains running IBC-Go v8+. + ([\#3696](https://github.com/informalsystems/hermes/issues/3696)) \ No newline at end of file diff --git a/.changelog/unreleased/features/ibc-relayer/3696-new-upgrade-proposal.md b/.changelog/unreleased/features/ibc-relayer/3696-new-upgrade-proposal.md new file mode 100644 index 0000000000..8ba9c4c22f --- /dev/null +++ b/.changelog/unreleased/features/ibc-relayer/3696-new-upgrade-proposal.md @@ -0,0 +1,3 @@ +- Use legacy `UpgradeProposal` or newer `MsgIbcSoftwareUpgrade` message when upgrading + a chain depending on whether the chain is running IBC-Go v8 or older. + ([\#3696](https://github.com/informalsystems/hermes/issues/3696)) \ No newline at end of file diff --git a/.changelog/unreleased/bug-fixes/ibc-relayer-cli/3580-docker-uid-gid.md b/.changelog/v1.7.0/bug-fixes/ibc-relayer-cli/3580-docker-uid-gid.md similarity index 100% rename from .changelog/unreleased/bug-fixes/ibc-relayer-cli/3580-docker-uid-gid.md rename to .changelog/v1.7.0/bug-fixes/ibc-relayer-cli/3580-docker-uid-gid.md diff --git a/.changelog/unreleased/bug-fixes/ibc-relayer-types/3549-ibc-relayer-types-docs.md b/.changelog/v1.7.0/bug-fixes/ibc-relayer-types/3549-ibc-relayer-types-docs.md similarity index 100% rename from .changelog/unreleased/bug-fixes/ibc-relayer-types/3549-ibc-relayer-types-docs.md rename to .changelog/v1.7.0/bug-fixes/ibc-relayer-types/3549-ibc-relayer-types-docs.md diff --git a/.changelog/unreleased/features/ibc-relayer-cli/3398-clear-packet-endpoint.md b/.changelog/v1.7.0/features/ibc-relayer-cli/3398-clear-packet-endpoint.md similarity index 100% rename from .changelog/unreleased/features/ibc-relayer-cli/3398-clear-packet-endpoint.md rename to .changelog/v1.7.0/features/ibc-relayer-cli/3398-clear-packet-endpoint.md diff --git a/.changelog/v1.7.0/features/ibc-relayer-cli/3456-evidence-command.md b/.changelog/v1.7.0/features/ibc-relayer-cli/3456-evidence-command.md new file mode 100644 index 0000000000..8daa96e334 --- /dev/null +++ b/.changelog/v1.7.0/features/ibc-relayer-cli/3456-evidence-command.md @@ -0,0 +1,4 @@ +- Add a new `evidence` command for monitoring the blocks emitted + by a chain for the presence of a misbehaviour evidence, and + report that evidence to all counteparty clients of that chain. + ([\#3456](https://github.com/informalsystems/hermes/pull/3456)) diff --git a/.changelog/unreleased/features/ibc-relayer-cli/3564-tracing-filter.md b/.changelog/v1.7.0/features/ibc-relayer-cli/3564-tracing-filter.md similarity index 100% rename from .changelog/unreleased/features/ibc-relayer-cli/3564-tracing-filter.md rename to .changelog/v1.7.0/features/ibc-relayer-cli/3564-tracing-filter.md diff --git a/.changelog/unreleased/improvements/ibc-relayer-cli/3501-listen-pull.md b/.changelog/v1.7.0/improvements/ibc-relayer-cli/3501-listen-pull.md similarity index 100% rename from .changelog/unreleased/improvements/ibc-relayer-cli/3501-listen-pull.md rename to .changelog/v1.7.0/improvements/ibc-relayer-cli/3501-listen-pull.md diff --git a/.changelog/v1.7.0/improvements/ibc-relayer/3219-ics-consumer-misbehavior.md b/.changelog/v1.7.0/improvements/ibc-relayer/3219-ics-consumer-misbehavior.md new file mode 100644 index 0000000000..eaec421cc8 --- /dev/null +++ b/.changelog/v1.7.0/improvements/ibc-relayer/3219-ics-consumer-misbehavior.md @@ -0,0 +1,4 @@ +- When Hermes detects a misbehaviour on a chain that is CCV + consumer, it will now send the misbehaviour evidence to the + provider chain using the new `IcsConsumerMisbehaviour` message. + ([\#3219](https://github.com/informalsystems/hermes/issues/3219)) \ No newline at end of file diff --git a/.changelog/v1.7.0/improvements/ibc-relayer/3223-submit-misbehavior-all-clients.md b/.changelog/v1.7.0/improvements/ibc-relayer/3223-submit-misbehavior-all-clients.md new file mode 100644 index 0000000000..c76ebb57d8 --- /dev/null +++ b/.changelog/v1.7.0/improvements/ibc-relayer/3223-submit-misbehavior-all-clients.md @@ -0,0 +1,5 @@ +- When Hermes detects a misbehaviour from a on-chain client, eg. a light + client attack or a double-sign, it will now submit the misbehaviour + evidence to all counterparty clients of the misbehaving chain + instead of to the counterparty client of the misbehaving client only. + ([\#3223](https://github.com/informalsystems/hermes/issues/3223)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/ibc-relayer/3531-fix-3531.md b/.changelog/v1.7.0/improvements/ibc-relayer/3531-fix-3531.md similarity index 100% rename from .changelog/unreleased/improvements/ibc-relayer/3531-fix-3531.md rename to .changelog/v1.7.0/improvements/ibc-relayer/3531-fix-3531.md diff --git a/.changelog/unreleased/improvements/ibc-relayer/3548-cometbft-0.38.md b/.changelog/v1.7.0/improvements/ibc-relayer/3548-cometbft-0.38.md similarity index 100% rename from .changelog/unreleased/improvements/ibc-relayer/3548-cometbft-0.38.md rename to .changelog/v1.7.0/improvements/ibc-relayer/3548-cometbft-0.38.md diff --git a/.changelog/v1.7.0/improvements/ibc-relayer/3666-default-compat-mode-to-v034.md b/.changelog/v1.7.0/improvements/ibc-relayer/3666-default-compat-mode-to-v034.md new file mode 100644 index 0000000000..b018b03a95 --- /dev/null +++ b/.changelog/v1.7.0/improvements/ibc-relayer/3666-default-compat-mode-to-v034.md @@ -0,0 +1,2 @@ +- Change fallback compatibility version for CometBFT from v0.37 to v0.34 + ([\#3666](https://github.com/informalsystems/hermes/issues/3666)) \ No newline at end of file diff --git a/.changelog/v1.7.0/summary.md b/.changelog/v1.7.0/summary.md new file mode 100644 index 0000000000..a7ebc13805 --- /dev/null +++ b/.changelog/v1.7.0/summary.md @@ -0,0 +1,25 @@ +*October 20th, 2023* + +This v1.7 release introduces new features and improvements to Hermes. + +One of the key highlights is the addition of new misbehavior detection features. + +Hermes now includes a new command called `evidence`, which monitors the blocks emitted by a chain for any presence of misbehavior evidence. + +If misbehavior is detected, the CLI will report that evidence to all counterparty clients of that chain. +On top of that, misbehavior evidence detected on a chain that is a CCV (Cross-Chain Validation) consumer +is now sent to its provider chain, alerting it directly of the misbehaving consumer chain. + +Furthermore, when misbehavior is detected from an on-chain client, such as a light client attack or a double-sign, +the evidence is now submitted to all counterparty clients of the misbehaving chain, rather than just the +counterparty client of the misbehaving client. + +In addition, the REST server of Hermes now has a `/clear_packets` endpoint which allows triggering +packet clearing for a specific chain or all chains if no specific chain is provided. + +Another notable improvement is the ability to change `tracing` directives at runtime. +This feature lets users adjust tracing settings dynamically as needed, providing a more +customizable and efficient debugging experience. + +Overall, the new misbehavior detection features in Hermes contribute to a more robust and secure environment, +enabling timely identification and response to potential misbehaving actors. diff --git a/.changelog/v1.7.1/features/ibc-relayer/3623-compat-mode-configurability.md b/.changelog/v1.7.1/features/ibc-relayer/3623-compat-mode-configurability.md new file mode 100644 index 0000000000..ca2601a602 --- /dev/null +++ b/.changelog/v1.7.1/features/ibc-relayer/3623-compat-mode-configurability.md @@ -0,0 +1,3 @@ +- Add an optional per-chain setting `compat_mode`, which can be + used to specify which CometBFT compatibility mode is used for interacting with the node over RPC. + ([\#3623](https://github.com/informalsystems/hermes/issues/3623)) \ No newline at end of file diff --git a/.changelog/v1.7.1/features/ibc-relayer/3691-per-chain-clear-interval.md b/.changelog/v1.7.1/features/ibc-relayer/3691-per-chain-clear-interval.md new file mode 100644 index 0000000000..b4bd8eb4ce --- /dev/null +++ b/.changelog/v1.7.1/features/ibc-relayer/3691-per-chain-clear-interval.md @@ -0,0 +1,2 @@ +- Add a configuration which allows to override the `clear_interval` for specific + chains ([\#3691](https://github.com/informalsystems/hermes/issues/3691)) \ No newline at end of file diff --git a/.changelog/v1.7.1/improvements/ibc-relayer/3521-client-update.md b/.changelog/v1.7.1/improvements/ibc-relayer/3521-client-update.md new file mode 100644 index 0000000000..90b8d600eb --- /dev/null +++ b/.changelog/v1.7.1/improvements/ibc-relayer/3521-client-update.md @@ -0,0 +1,3 @@ +- Hermes now saves on fees by not including a client update if the + consensus state at desired height is already present on chain. + ([\#3521](https://github.com/informalsystems/hermes/issues/3521)) \ No newline at end of file diff --git a/.changelog/v1.7.1/improvements/ibc-relayer/3636-config-enum.md b/.changelog/v1.7.1/improvements/ibc-relayer/3636-config-enum.md new file mode 100644 index 0000000000..95e1f50230 --- /dev/null +++ b/.changelog/v1.7.1/improvements/ibc-relayer/3636-config-enum.md @@ -0,0 +1,3 @@ +- Change config format to scope configs by type. This enables adding support for + more types of chain, even when those have different config options than each + other. ([\#3636](https://github.com/informalsystems/hermes/issues/3636)) \ No newline at end of file diff --git a/.changelog/v1.7.1/summary.md b/.changelog/v1.7.1/summary.md new file mode 100644 index 0000000000..28905e6542 --- /dev/null +++ b/.changelog/v1.7.1/summary.md @@ -0,0 +1,12 @@ +This patch release of Hermes now allows operators to set the clearing interval +at a different value for each chain, using the new per-chain `clear_interval` setting. +The global `clear_interval` setting is used as a default value if the per-chain +setting is not defined. + +Additionnaly, operators can now override the CometBFT compatibility mode to be used +for a chain by using the new `compat_mode` per-chain setting. The main use case for this +is to override the automatically detected compatibility mode in case Hermes gets it wrong +or encounters a non-standard version number and falls back on the wrong CometBFT version. + +On top of that, Hermes will now attempt to save on fees by not building a client update +for a given height if the consensus state for that height is already present on chain. diff --git a/.changelog/v1.7.2/features/ibc-telemetry/3707-skipped-client-update-metric.md b/.changelog/v1.7.2/features/ibc-telemetry/3707-skipped-client-update-metric.md new file mode 100644 index 0000000000..db44abf7e4 --- /dev/null +++ b/.changelog/v1.7.2/features/ibc-telemetry/3707-skipped-client-update-metric.md @@ -0,0 +1,3 @@ +- Added metric `client_updates_skipped` to track the number of client + update messages skipped due to the conscensus state existing already. + ([\#3707](https://github.com/informalsystems/hermes/issues/3707)) \ No newline at end of file diff --git a/.changelog/v1.7.2/features/ibc-telemetry/3708-add-broadcast-errors.md b/.changelog/v1.7.2/features/ibc-telemetry/3708-add-broadcast-errors.md new file mode 100644 index 0000000000..9585d6dbc3 --- /dev/null +++ b/.changelog/v1.7.2/features/ibc-telemetry/3708-add-broadcast-errors.md @@ -0,0 +1,3 @@ +- Add a new metric `broadcast_errors` which + records the number of times a specific error is observed by Hermes when broadcasting transactions + ([\#3708](https://github.com/informalsystems/hermes/issues/3708)) \ No newline at end of file diff --git a/.changelog/v1.7.2/summary.md b/.changelog/v1.7.2/summary.md new file mode 100644 index 0000000000..1fe74eaa01 --- /dev/null +++ b/.changelog/v1.7.2/summary.md @@ -0,0 +1,7 @@ +*November 28th, 2023* + +This patch release of Hermes adds a metric to improve monitoring errors and one +to measure the efficiency of the client update skip feature released in patch v1.7.1. + +* `broadcast_errors` records the number of times a specific error is observed by Hermes when broadcasting transactions. +* `client_updates_skipped` records the number of client updates skipped due to the consensus states already existing. diff --git a/.changelog/v1.7.3/bug-fixes/ibc-relayer-cli/3702-evidence-patch.md b/.changelog/v1.7.3/bug-fixes/ibc-relayer-cli/3702-evidence-patch.md new file mode 100644 index 0000000000..e927fce303 --- /dev/null +++ b/.changelog/v1.7.3/bug-fixes/ibc-relayer-cli/3702-evidence-patch.md @@ -0,0 +1,3 @@ +- Improve reliability of `evidence` command and fix a bug that was + preventing evidence to be reported, as seen on the Gaia RS testnet + ([\#3702](https://github.com/informalsystems/hermes/pull/3702)) \ No newline at end of file diff --git a/.changelog/v1.7.3/summary.md b/.changelog/v1.7.3/summary.md new file mode 100644 index 0000000000..bbd4ee5bb1 --- /dev/null +++ b/.changelog/v1.7.3/summary.md @@ -0,0 +1,5 @@ +*November 29th, 2023* + +This release improves the reliability of the `evidence` command and +fixes a bug that was preventing evidence to be reported, +as seen on the Gaia RS testnet. diff --git a/.changelog/v1.7.4/bug-fixes/ibc-relayer-cli/3697-fix-evidence-report.md b/.changelog/v1.7.4/bug-fixes/ibc-relayer-cli/3697-fix-evidence-report.md new file mode 100644 index 0000000000..232aa6c15a --- /dev/null +++ b/.changelog/v1.7.4/bug-fixes/ibc-relayer-cli/3697-fix-evidence-report.md @@ -0,0 +1,4 @@ +- Fix a bug in the `evidence` command which would sometimes + prevent the detected misbehaviour evidence from being submitted, + instead erroring out with a validator set hash mismatch. + ([\#3697](https://github.com/informalsystems/hermes/pull/3697)) diff --git a/.changelog/v1.7.4/bug-fixes/ibc-relayer/3703-avoid-returning-stopped-worker.md b/.changelog/v1.7.4/bug-fixes/ibc-relayer/3703-avoid-returning-stopped-worker.md new file mode 100644 index 0000000000..c2ab504b5d --- /dev/null +++ b/.changelog/v1.7.4/bug-fixes/ibc-relayer/3703-avoid-returning-stopped-worker.md @@ -0,0 +1,3 @@ +- Avoid retrieving a worker which is being removed by the idle worker clean-up + process. + process ([\#3703](https://github.com/informalsystems/hermes/issues/3703)) \ No newline at end of file diff --git a/.changelog/v1.7.4/bug-fixes/ibc-telemetry/3720-fix-broadcasting-errors-metric.md b/.changelog/v1.7.4/bug-fixes/ibc-telemetry/3720-fix-broadcasting-errors-metric.md new file mode 100644 index 0000000000..3da82edaf4 --- /dev/null +++ b/.changelog/v1.7.4/bug-fixes/ibc-telemetry/3720-fix-broadcasting-errors-metric.md @@ -0,0 +1,3 @@ +- Fix the issue where `broadcast_errors` metric would not correctly batch + the same errors together. + together ([\#3720](https://github.com/informalsystems/hermes/issues/3720)) \ No newline at end of file diff --git a/.changelog/v1.7.4/bug-fixes/ibc-telemetry/3723-fix-backlog-metrics.md b/.changelog/v1.7.4/bug-fixes/ibc-telemetry/3723-fix-backlog-metrics.md new file mode 100644 index 0000000000..fa95766987 --- /dev/null +++ b/.changelog/v1.7.4/bug-fixes/ibc-telemetry/3723-fix-backlog-metrics.md @@ -0,0 +1,4 @@ +- Update the values of `backlog` metrics when clearing packets. + Change the `backlog_oldest_timestamp` to `backlog_latest_update_timestamp` + which shows the last time the `backlog` metrics have been updated. + ([\#3723](https://github.com/informalsystems/hermes/issues/3723)) \ No newline at end of file diff --git a/.changelog/v1.7.4/summary.md b/.changelog/v1.7.4/summary.md new file mode 100644 index 0000000000..00b15e27f1 --- /dev/null +++ b/.changelog/v1.7.4/summary.md @@ -0,0 +1,9 @@ +*December 15th, 2023* + +This release improves the monitoring of Hermes instances by fixing the `broadcast_errors` metric so +that it correctly batches the same errors together. It also improves the metrics `backlog_*` by +updating them whenever Hermes queries pending packets. + +This release also improves the reliability of the idle worker clean-up and +fixes a bug within the `evidence` command which would sometimes prevent +the misbehaviour evidence from being reported. diff --git a/.github/codespell/codespell.ini b/.github/codespell/codespell.ini new file mode 100644 index 0000000000..c1a20a75f2 --- /dev/null +++ b/.github/codespell/codespell.ini @@ -0,0 +1,3 @@ +[codespell] +skip = *.js,*.ts,*.css,*.svg,./target +ignore-words = .github/codespell/words.txt diff --git a/.github/codespell/words.txt b/.github/codespell/words.txt new file mode 100644 index 0000000000..d15ff15549 --- /dev/null +++ b/.github/codespell/words.txt @@ -0,0 +1,4 @@ +crate +shs +ser +numer diff --git a/.github/workflows/cargo-doc.yaml b/.github/workflows/cargo-doc.yaml index cfe2f2468f..ebc03618b6 100644 --- a/.github/workflows/cargo-doc.yaml +++ b/.github/workflows/cargo-doc.yaml @@ -4,7 +4,17 @@ on: push: branches: - master - pull_request: {} + paths: + - .github/workflows/cargo-doc.yml + - Cargo.toml + - Cargo.lock + - crates/** + pull_request: + paths: + - .github/workflows/cargo-doc.yml + - Cargo.toml + - Cargo.lock + - crates/** # Cancel previous runs of this workflow when a new commit is added to the PR, branch or tag concurrency: diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml new file mode 100644 index 0000000000..b352a70858 --- /dev/null +++ b/.github/workflows/codespell.yml @@ -0,0 +1,22 @@ +name: Codespell +on: + pull_request: + push: + branches: master + +# Cancel previous runs of this workflow when a new commit is added to the PR, branch or tag +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + codespell: + name: Check spelling + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: codespell-project/actions-codespell@v2 + with: + skip: '*.js,*.ts,*.css,*.svg,./target' + ignore_words_file: .github/codespell/words.txt + diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index d46c030263..ca0e104942 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -62,7 +62,7 @@ jobs: touch "/tmp/digests/${digest#sha256:}" - name: Upload digest - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: digests path: /tmp/digests/* @@ -75,7 +75,7 @@ jobs: - docker-build steps: - name: Download digests - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: digests path: /tmp/digests diff --git a/.github/workflows/integration.yaml b/.github/workflows/integration.yaml index 0b6b60bc41..91ecaf47fe 100644 --- a/.github/workflows/integration.yaml +++ b/.github/workflows/integration.yaml @@ -45,46 +45,66 @@ jobs: fail-fast: false matrix: chain: - - package: gaia12 + - package: gaia13 command: gaiad account_prefix: cosmos - - package: ibc-go-v4-simapp - command: simd - account_prefix: cosmos - - package: ibc-go-v5-simapp - command: simd + native_token: stake + features: forward-packet,clean-workers + - package: gaia14 + command: gaiad account_prefix: cosmos + native_token: stake + features: forward-packet,clean-workers - package: ibc-go-v6-simapp command: simd account_prefix: cosmos + native_token: stake + features: ica,ics29-fee - package: ibc-go-v7-simapp command: simd account_prefix: cosmos + native_token: stake + features: ica,ics29-fee + - package: ibc-go-v8-simapp + command: simd + account_prefix: cosmos + native_token: stake + features: ica,ics29-fee - package: wasmd command: wasmd account_prefix: wasm - - package: evmos - command: evmosd - account_prefix: evmos + native_token: stake + features: '' - package: osmosis command: osmosisd account_prefix: osmo - - package: stride - command: strided - account_prefix: stride + native_token: stake + features: '' - package: juno command: junod account_prefix: juno + native_token: stake + features: juno,forward-packet + - package: provenance + command: provenanced + account_prefix: pb + native_token: nhash + features: fee-grant,async-icq + - package: migaloo + command: migalood + account_prefix: migaloo + native_token: stake + features: '' steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v22 + - uses: cachix/install-nix-action@v24 with: install_url: https://nixos-nix-install-tests.cachix.org/serve/vij683ly7sl95nnhb67bdjjfabclr85m/install install_options: '--tarball-url-prefix https://nixos-nix-install-tests.cachix.org/serve' extra_nix_config: | experimental-features = nix-command flakes - - uses: cachix/cachix-action@v12 + - uses: cachix/cachix-action@v13 with: name: cosmos - uses: actions-rs/toolchain@v1 @@ -95,7 +115,7 @@ jobs: - uses: actions-rs/cargo@v1 with: command: test - args: -p ibc-integration-test --no-fail-fast --no-run + args: -p ibc-integration-test --features=${{ matrix.chain.features }} --no-fail-fast --no-run - name: Install cargo-nextest run: curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin - name: Run integration test @@ -106,22 +126,24 @@ jobs: NEXTEST_RETRIES: 2 CHAIN_COMMAND_PATHS: ${{ matrix.chain.command }} ACCOUNT_PREFIXES: ${{ matrix.chain.account_prefix }} + NATIVE_TOKENS: ${{ matrix.chain.native_token }} run: | nix shell .#python .#${{ matrix.chain.package }} -c \ - cargo nextest run -p ibc-integration-test --no-fail-fast --failure-output final --test-threads=2 + cargo nextest run -p ibc-integration-test --no-fail-fast --failure-output final --test-threads=2 \ + --features=${{ matrix.chain.features }} ordered-channel-test: runs-on: ubuntu-20.04 timeout-minutes: 60 steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v22 + - uses: cachix/install-nix-action@v24 with: install_url: https://nixos-nix-install-tests.cachix.org/serve/vij683ly7sl95nnhb67bdjjfabclr85m/install install_options: '--tarball-url-prefix https://nixos-nix-install-tests.cachix.org/serve' extra_nix_config: | experimental-features = nix-command flakes - - uses: cachix/cachix-action@v12 + - uses: cachix/cachix-action@v13 with: name: cosmos - uses: actions-rs/toolchain@v1 @@ -145,27 +167,27 @@ jobs: cargo nextest run -p ibc-integration-test --no-fail-fast --failure-output final --test-threads=2 \ --features ordered test_ordered_channel - ica-filter-test: + interchain-security-no-ica: runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: chain: - - package: ibc-go-v6-simapp - command: simd - account_prefix: cosmos - - package: ibc-go-v7-simapp - command: simd - account_prefix: cosmos + - package: .#gaia13 .#neutron + command: gaiad,neutrond + account_prefix: cosmos,neutron + - package: .#gaia14 .#neutron + command: gaiad,neutrond + account_prefix: cosmos,neutron steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v22 + - uses: cachix/install-nix-action@v24 with: install_url: https://nixos-nix-install-tests.cachix.org/serve/vij683ly7sl95nnhb67bdjjfabclr85m/install install_options: '--tarball-url-prefix https://nixos-nix-install-tests.cachix.org/serve' extra_nix_config: | experimental-features = nix-command flakes - - uses: cachix/cachix-action@v12 + - uses: cachix/cachix-action@v13 with: name: cosmos - uses: actions-rs/toolchain@v1 @@ -176,94 +198,42 @@ jobs: - uses: actions-rs/cargo@v1 with: command: test - args: -p ibc-integration-test --no-fail-fast --no-run - - name: Install cargo-nextest - run: curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin - - env: - RUST_LOG: info - RUST_BACKTRACE: 1 - NO_COLOR_LOG: 1 - NEXTEST_RETRIES: 2 - CHAIN_COMMAND_PATHS: ${{ matrix.chain.command }} - ACCOUNT_PREFIXES: ${{ matrix.chain.account_prefix }} - run: | - nix shell .#${{ matrix.chain.package }} -c \ - cargo nextest run -p ibc-integration-test --no-fail-fast --failure-output final --test-threads=2 \ - --features ica test_ica_filter - - ics29-fee-test: - runs-on: ubuntu-20.04 - strategy: - fail-fast: false - matrix: - chain: - - package: ibc-go-v5-simapp - command: simd - account_prefix: cosmos - - package: ibc-go-v6-simapp - command: simd - account_prefix: cosmos - - package: ibc-go-v7-simapp - command: simd - account_prefix: cosmos - - package: migaloo - command: migalood - account_prefix: migaloo - steps: - - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v22 - with: - install_url: https://nixos-nix-install-tests.cachix.org/serve/vij683ly7sl95nnhb67bdjjfabclr85m/install - install_options: '--tarball-url-prefix https://nixos-nix-install-tests.cachix.org/serve' - extra_nix_config: | - experimental-features = nix-command flakes - - uses: cachix/cachix-action@v12 - with: - name: cosmos - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - - uses: Swatinem/rust-cache@v2 - - uses: actions-rs/cargo@v1 - with: - command: test - args: -p ibc-integration-test --features ics29-fee --no-fail-fast --no-run + args: -p ibc-integration-test --features interchain-security --no-fail-fast --no-run - name: Install cargo-nextest run: curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin - env: - RUST_LOG: info + RUST_LOG: trace RUST_BACKTRACE: 1 NO_COLOR_LOG: 1 NEXTEST_RETRIES: 2 CHAIN_COMMAND_PATHS: ${{ matrix.chain.command }} ACCOUNT_PREFIXES: ${{ matrix.chain.account_prefix }} run: | - nix shell .#${{ matrix.chain.package }} -c \ + nix shell ${{ matrix.chain.package }} -c \ cargo nextest run -p ibc-integration-test --no-fail-fast --failure-output final --test-threads=2 \ - --features ics29-fee fee:: + --features interchain-security interchain_security:: - forward-packet: + interchain-security-ica: runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: chain: - - package: gaia12 - command: gaiad - account_prefix: cosmos - - package: juno - command: junod - account_prefix: juno + - package: .#gaia13 .#stride-consumer + command: gaiad,strided + account_prefix: cosmos,stride + - package: .#gaia14 .#stride-consumer + command: gaiad,strided + account_prefix: cosmos,stride steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v22 + - uses: cachix/install-nix-action@v24 with: install_url: https://nixos-nix-install-tests.cachix.org/serve/vij683ly7sl95nnhb67bdjjfabclr85m/install install_options: '--tarball-url-prefix https://nixos-nix-install-tests.cachix.org/serve' extra_nix_config: | experimental-features = nix-command flakes - - uses: cachix/cachix-action@v12 + - uses: cachix/cachix-action@v13 with: name: cosmos - uses: actions-rs/toolchain@v1 @@ -274,7 +244,7 @@ jobs: - uses: actions-rs/cargo@v1 with: command: test - args: -p ibc-integration-test --features forward-packet --no-fail-fast --no-run + args: -p ibc-integration-test --features interchain-security --no-fail-fast --no-run - name: Install cargo-nextest run: curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin - env: @@ -285,28 +255,31 @@ jobs: CHAIN_COMMAND_PATHS: ${{ matrix.chain.command }} ACCOUNT_PREFIXES: ${{ matrix.chain.account_prefix }} run: | - nix shell .#${{ matrix.chain.package }} -c \ + nix shell ${{ matrix.chain.package }} -c \ cargo nextest run -p ibc-integration-test --no-fail-fast --failure-output final --test-threads=2 \ - --features forward-packet forward:: + --features interchain-security,ica interchain_security:: - ics31: + interchain-security-icq: runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: chain: - - package: .#gaia12 .#stride-no-admin + - package: .#gaia13 .#stride-consumer-no-admin + command: gaiad,strided + account_prefix: cosmos,stride + - package: .#gaia14 .#stride-consumer-no-admin command: gaiad,strided account_prefix: cosmos,stride steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v22 + - uses: cachix/install-nix-action@v24 with: install_url: https://nixos-nix-install-tests.cachix.org/serve/vij683ly7sl95nnhb67bdjjfabclr85m/install install_options: '--tarball-url-prefix https://nixos-nix-install-tests.cachix.org/serve' extra_nix_config: | experimental-features = nix-command flakes - - uses: cachix/cachix-action@v12 + - uses: cachix/cachix-action@v13 with: name: cosmos - uses: actions-rs/toolchain@v1 @@ -317,83 +290,43 @@ jobs: - uses: actions-rs/cargo@v1 with: command: test - args: -p ibc-integration-test --features ics31 --no-fail-fast --no-run + args: -p ibc-integration-test --features interchain-security --no-fail-fast --no-run - name: Install cargo-nextest run: curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin - env: RUST_LOG: info RUST_BACKTRACE: 1 NO_COLOR_LOG: 1 - NEXTEST_RETRIES: 2 CHAIN_COMMAND_PATHS: ${{ matrix.chain.command }} ACCOUNT_PREFIXES: ${{ matrix.chain.account_prefix }} run: | nix shell ${{ matrix.chain.package }} -c \ cargo nextest run -p ibc-integration-test --no-fail-fast --failure-output final --test-threads=2 \ - --features ics31 ics31:: - fee-grant: - runs-on: ubuntu-20.04 - strategy: - fail-fast: false - matrix: - chain: - - package: stride - command: strided - account_prefix: stride - - package: evmos - command: evmosd - account_prefix: evmos - steps: - - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v22 - with: - install_url: https://nixos-nix-install-tests.cachix.org/serve/vij683ly7sl95nnhb67bdjjfabclr85m/install - install_options: '--tarball-url-prefix https://nixos-nix-install-tests.cachix.org/serve' - extra_nix_config: | - experimental-features = nix-command flakes - - uses: cachix/cachix-action@v12 - with: - name: cosmos - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - - uses: Swatinem/rust-cache@v2 - - uses: actions-rs/cargo@v1 - with: - command: test - args: -p ibc-integration-test --features fee-grant --no-fail-fast --no-run - - name: Install cargo-nextest - run: curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin - - env: - RUST_LOG: info - RUST_BACKTRACE: 1 - NO_COLOR_LOG: 1 - CHAIN_COMMAND_PATHS: ${{ matrix.chain.command }} - ACCOUNT_PREFIXES: ${{ matrix.chain.account_prefix }} - run: | - nix shell .#${{ matrix.chain.package }} -c \ - cargo nextest run -p ibc-integration-test --no-fail-fast --failure-output final --test-threads=2 \ - --features fee-grant fee_grant:: + --features interchain-security,ics31 interchain_security:: - clean-workers: + celestia-to-gaia: runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: chain: - - package: gaia12 - command: gaiad - account_prefix: cosmos + - package: .#celestia .#gaia13 + command: celestia-appd,gaiad + account_prefix: celestia,cosmos + native_token: utia,stake + - package: .#celestia .#gaia14 + command: celestia-appd,gaiad + account_prefix: celestia,cosmos + native_token: utia,stake steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v22 + - uses: cachix/install-nix-action@v24 with: install_url: https://nixos-nix-install-tests.cachix.org/serve/vij683ly7sl95nnhb67bdjjfabclr85m/install install_options: '--tarball-url-prefix https://nixos-nix-install-tests.cachix.org/serve' extra_nix_config: | experimental-features = nix-command flakes - - uses: cachix/cachix-action@v12 + - uses: cachix/cachix-action@v13 with: name: cosmos - uses: actions-rs/toolchain@v1 @@ -404,148 +337,21 @@ jobs: - uses: actions-rs/cargo@v1 with: command: test - args: -p ibc-integration-test --features ics31 --no-fail-fast --no-run + args: -p ibc-integration-test --features celestia --no-fail-fast --no-run - name: Install cargo-nextest run: curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin - env: RUST_LOG: info RUST_BACKTRACE: 1 NO_COLOR_LOG: 1 - NEXTEST_RETRIES: 2 + COMPAT_MODES: 0.34 CHAIN_COMMAND_PATHS: ${{ matrix.chain.command }} ACCOUNT_PREFIXES: ${{ matrix.chain.account_prefix }} + NATIVE_TOKENS: ${{ matrix.chain.native_token }} run: | - nix shell .#${{ matrix.chain.package }} -c \ + nix shell .#python ${{ matrix.chain.package }} -c \ cargo nextest run -p ibc-integration-test --no-fail-fast --failure-output final --test-threads=2 \ - --features clean-workers clean_workers:: - - interchain-security-no-ica: - runs-on: ubuntu-20.04 - strategy: - fail-fast: false - matrix: - chain: - - package: neutron - command: neutrond - account_prefix: neutron - steps: - - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v22 - with: - install_url: https://nixos-nix-install-tests.cachix.org/serve/vij683ly7sl95nnhb67bdjjfabclr85m/install - install_options: '--tarball-url-prefix https://nixos-nix-install-tests.cachix.org/serve' - extra_nix_config: | - experimental-features = nix-command flakes - - uses: cachix/cachix-action@v12 - with: - name: cosmos - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - - uses: Swatinem/rust-cache@v2 - - uses: actions-rs/cargo@v1 - with: - command: test - args: -p ibc-integration-test --features interchain-security --no-fail-fast --no-run - - name: Install cargo-nextest - run: curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin - - env: - RUST_LOG: trace - RUST_BACKTRACE: 1 - NO_COLOR_LOG: 1 - NEXTEST_RETRIES: 2 - CHAIN_COMMAND_PATHS: gaiad,${{ matrix.chain.command }} - ACCOUNT_PREFIXES: cosmos,${{ matrix.chain.account_prefix }} - run: | - nix shell .#gaia12 .#${{ matrix.chain.package }} -c \ - cargo nextest run -p ibc-integration-test --no-fail-fast --failure-output final --test-threads=2 \ - --features interchain-security interchain_security:: - - interchain-security-ica: - runs-on: ubuntu-20.04 - strategy: - fail-fast: false - matrix: - chain: - - package: stride-consumer - command: strided - account_prefix: stride - steps: - - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v22 - with: - install_url: https://nixos-nix-install-tests.cachix.org/serve/vij683ly7sl95nnhb67bdjjfabclr85m/install - install_options: '--tarball-url-prefix https://nixos-nix-install-tests.cachix.org/serve' - extra_nix_config: | - experimental-features = nix-command flakes - - uses: cachix/cachix-action@v12 - with: - name: cosmos - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - - uses: Swatinem/rust-cache@v2 - - uses: actions-rs/cargo@v1 - with: - command: test - args: -p ibc-integration-test --features interchain-security --no-fail-fast --no-run - - name: Install cargo-nextest - run: curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin - - env: - RUST_LOG: info - RUST_BACKTRACE: 1 - NO_COLOR_LOG: 1 - NEXTEST_RETRIES: 2 - CHAIN_COMMAND_PATHS: gaiad,${{ matrix.chain.command }} - ACCOUNT_PREFIXES: cosmos,${{ matrix.chain.account_prefix }} - run: | - nix shell .#gaia12 .#${{ matrix.chain.package }} -c \ - cargo nextest run -p ibc-integration-test --no-fail-fast --failure-output final --test-threads=2 \ - --features interchain-security,ica interchain_security:: - - interchain-security-icq: - runs-on: ubuntu-20.04 - strategy: - fail-fast: false - matrix: - chain: - - package: stride-consumer-no-admin - command: strided - account_prefix: stride - steps: - - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v22 - with: - install_url: https://nixos-nix-install-tests.cachix.org/serve/vij683ly7sl95nnhb67bdjjfabclr85m/install - install_options: '--tarball-url-prefix https://nixos-nix-install-tests.cachix.org/serve' - extra_nix_config: | - experimental-features = nix-command flakes - - uses: cachix/cachix-action@v12 - with: - name: cosmos - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - - uses: Swatinem/rust-cache@v2 - - uses: actions-rs/cargo@v1 - with: - command: test - args: -p ibc-integration-test --features interchain-security --no-fail-fast --no-run - - name: Install cargo-nextest - run: curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin - - env: - RUST_LOG: info - RUST_BACKTRACE: 1 - NO_COLOR_LOG: 1 - CHAIN_COMMAND_PATHS: gaiad,${{ matrix.chain.command }} - ACCOUNT_PREFIXES: cosmos,${{ matrix.chain.account_prefix }} - run: | - nix shell .#gaia12 .#${{ matrix.chain.package }} -c \ - cargo nextest run -p ibc-integration-test --no-fail-fast --failure-output final --test-threads=2 \ - --features interchain-security,ics31 interchain_security:: + --features celestia model-based-test: runs-on: ubuntu-20.04 @@ -556,13 +362,13 @@ jobs: - gaia6 steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v22 + - uses: cachix/install-nix-action@v24 with: install_url: https://nixos-nix-install-tests.cachix.org/serve/vij683ly7sl95nnhb67bdjjfabclr85m/install install_options: '--tarball-url-prefix https://nixos-nix-install-tests.cachix.org/serve' extra_nix_config: | experimental-features = nix-command flakes - - uses: cachix/cachix-action@v12 + - uses: cachix/cachix-action@v13 with: name: cosmos - uses: actions-rs/toolchain@v1 diff --git a/.github/workflows/misbehaviour.yml b/.github/workflows/misbehaviour.yml index 8a4c4c819f..62869c4e2f 100644 --- a/.github/workflows/misbehaviour.yml +++ b/.github/workflows/misbehaviour.yml @@ -36,25 +36,25 @@ concurrency: cancel-in-progress: true jobs: - misbehaviour: + light-client-attack: runs-on: ubuntu-20.04 timeout-minutes: 20 strategy: fail-fast: false matrix: chain: - - package: gaia12 + - package: gaia14 command: gaiad account_prefix: cosmos steps: - uses: actions/checkout@v4 - name: Install Nix - uses: cachix/install-nix-action@v22 + uses: cachix/install-nix-action@v24 with: extra_nix_config: | experimental-features = nix-command flakes - name: Use cachix cache - uses: cachix/cachix-action@v12 + uses: cachix/cachix-action@v13 with: name: cosmos - name: Install sconfig @@ -91,3 +91,166 @@ jobs: run: | nix shell .#${{ matrix.chain.package }} -c bash misbehaviour_test.sh + ics-light-client-attack: + runs-on: ubuntu-20.04 + timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + chain: + - package: interchain-security + account_prefix: cosmos + steps: + - uses: actions/checkout@v4 + - name: Install Nix + uses: cachix/install-nix-action@v24 + with: + extra_nix_config: | + experimental-features = nix-command flakes + - name: Use cachix cache + uses: cachix/cachix-action@v13 + with: + name: cosmos + - name: Install sconfig + uses: jaxxstorm/action-install-gh-release@v1.10.0 + with: + repo: freshautomations/sconfig + platform: linux + arch: amd64 + extension-matching: disable + rename-to: sconfig + chmod: 0755 + - name: Install stoml + uses: jaxxstorm/action-install-gh-release@v1.10.0 + with: + repo: freshautomations/stoml + platform: linux + arch: amd64 + extension-matching: disable + rename-to: stoml + chmod: 0755 + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + - name: Use Rust cache + uses: Swatinem/rust-cache@v2 + - name: Build Hermes + uses: actions-rs/cargo@v1 + with: + command: build + - name: Run test + working-directory: ci/misbehaviour-ics + run: | + nix shell .#cometbft .#${{ matrix.chain.package }} -c bash light_client_attack_test.sh + + ics-light-client-attack-freeze: + runs-on: ubuntu-20.04 + timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + chain: + - package: interchain-security + account_prefix: cosmos + steps: + - uses: actions/checkout@v4 + - name: Install Nix + uses: cachix/install-nix-action@v24 + with: + extra_nix_config: | + experimental-features = nix-command flakes + - name: Use cachix cache + uses: cachix/cachix-action@v13 + with: + name: cosmos + - name: Install sconfig + uses: jaxxstorm/action-install-gh-release@v1.10.0 + with: + repo: freshautomations/sconfig + platform: linux + arch: amd64 + extension-matching: disable + rename-to: sconfig + chmod: 0755 + - name: Install stoml + uses: jaxxstorm/action-install-gh-release@v1.10.0 + with: + repo: freshautomations/stoml + platform: linux + arch: amd64 + extension-matching: disable + rename-to: stoml + chmod: 0755 + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + - name: Use Rust cache + uses: Swatinem/rust-cache@v2 + - name: Build Hermes + uses: actions-rs/cargo@v1 + with: + command: build + - name: Run test + working-directory: ci/misbehaviour-ics + run: | + nix shell .#${{ matrix.chain.package }} -c bash light_client_attack_freeze_test.sh + + + ics-double-sign: + runs-on: ubuntu-20.04 + timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + chain: + - package: interchain-security + account_prefix: cosmos + steps: + - uses: actions/checkout@v4 + - name: Install Nix + uses: cachix/install-nix-action@v24 + with: + extra_nix_config: | + experimental-features = nix-command flakes + - name: Use cachix cache + uses: cachix/cachix-action@v13 + with: + name: cosmos + - name: Install sconfig + uses: jaxxstorm/action-install-gh-release@v1.10.0 + with: + repo: freshautomations/sconfig + platform: linux + arch: amd64 + extension-matching: disable + rename-to: sconfig + chmod: 0755 + - name: Install stoml + uses: jaxxstorm/action-install-gh-release@v1.10.0 + with: + repo: freshautomations/stoml + platform: linux + arch: amd64 + extension-matching: disable + rename-to: stoml + chmod: 0755 + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + - name: Use Rust cache + uses: Swatinem/rust-cache@v2 + - name: Build Hermes + uses: actions-rs/cargo@v1 + with: + command: build + - name: Run test + working-directory: ci/misbehaviour-ics + run: | + nix shell .#${{ matrix.chain.package }} -c bash double_sign_test.sh + diff --git a/.github/workflows/multi-chains.yaml b/.github/workflows/multi-chains.yaml index 8aab31647d..3aa37edfb3 100644 --- a/.github/workflows/multi-chains.yaml +++ b/.github/workflows/multi-chains.yaml @@ -58,38 +58,38 @@ jobs: fail-fast: false matrix: first-package: - - package: gaia12 + - package: gaia13 + command: gaiad + account_prefix: cosmos + - package: gaia14 command: gaiad account_prefix: cosmos - package: ibc-go-v7-simapp command: simd account_prefix: cosmos - - package: wasmd - command: wasmd - account_prefix: wasm + - package: ibc-go-v8-simapp + command: simd + account_prefix: cosmos second-package: - - package: evmos - command: evmosd - account_prefix: evmos - package: osmosis command: osmosisd account_prefix: osmo - - package: stride - command: strided - account_prefix: stride - - package: juno - command: junod - account_prefix: juno + - package: migaloo + command: migalood + account_prefix: migaloo + - package: wasmd + command: wasmd + account_prefix: wasm steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v22 + - uses: cachix/install-nix-action@v24 with: install_url: https://nixos-nix-install-tests.cachix.org/serve/vij683ly7sl95nnhb67bdjjfabclr85m/install install_options: '--tarball-url-prefix https://nixos-nix-install-tests.cachix.org/serve' extra_nix_config: | experimental-features = nix-command flakes - - uses: cachix/cachix-action@v12 + - uses: cachix/cachix-action@v13 with: name: cosmos - uses: actions-rs/toolchain@v1 diff --git a/.github/workflows/specs.yml b/.github/workflows/specs.yml deleted file mode 100644 index 1e06c174a5..0000000000 --- a/.github/workflows/specs.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: TLA+ Specs -on: - pull_request: - paths: - - docs/spec/tla/** - push: - branches: master - paths: - - docs/specs/tla/** - -# Cancel previous runs of this workflow when a new commit is added to the PR, branch or tag -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -jobs: - typecheck-specs: - runs-on: ubuntu-latest - container: apalache/mc:0.15.2 - env: - working-directory: docs/spec/tla - steps: - - uses: actions/checkout@v4 - - name: IBC Core - run: apalache-mc typecheck IBCCore.tla | grep -F 'Type checker [OK]' - working-directory: ${{env.working-directory}}/ibc-core - - name: Fungible Token Transfer - run: apalache-mc typecheck IBCTokenTransfer.tla | grep -F 'Type checker [OK]' - working-directory: ${{env.working-directory}}/fungible-token-transfer - - name: ICS 02 Client / Single Chain - run: apalache-mc typecheck ICS02SingleChainEnvironment.tla | grep -F 'Type checker [OK]' - working-directory: ${{env.working-directory}}/client - - name: ICS 02 Client / Two Chains - run: apalache-mc typecheck ICS02TwoChainsEnvironment.tla | grep -F 'Type checker [OK]' - working-directory: ${{env.working-directory}}/client diff --git a/.gitignore b/.gitignore index 2e9b0e8816..edd589a061 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,6 @@ mc.log # Ignore OSX .DS_Store file .DS_Store + +# Ignore tooling Cargo.lock +tools/check-guide/Cargo.lock diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ee3332ca6..08dad0afd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,182 @@ # CHANGELOG +## v1.7.4 + +*December 15th, 2023* + +Special thanks to Yun Yeo (@beer-1) for his contributions ([#3697] and [#3703]). + +This release improves the monitoring of Hermes instances by fixing the `broadcast_errors` metric so +that it correctly batches the same errors together. It also improves the metrics `backlog_*` by +updating them whenever Hermes queries pending packets. + +This release also improves the reliability of the idle worker clean-up and +fixes a bug within the `evidence` command which would sometimes prevent +the misbehaviour evidence from being reported. + +### BUG FIXES + +- [Relayer CLI](relayer-cli) + - Fix a bug in the `evidence` command which would sometimes + prevent the detected misbehaviour evidence from being submitted, + instead erroring out with a validator set hash mismatch. + ([\#3697](https://github.com/informalsystems/hermes/pull/3697)) +- [Relayer Library](relayer) + - Avoid retrieving a worker which is being removed by the idle worker clean-up + process. ([\#3703](https://github.com/informalsystems/hermes/issues/3703)) +- [Telemetry & Metrics](telemetry) + - Fix the issue where `broadcast_errors` metric would not correctly batch + the same errors together.([\#3720](https://github.com/informalsystems/hermes/issues/3720)) + - Update the values of `backlog` metrics when clearing packets. + Change the `backlog_oldest_timestamp` to `backlog_latest_update_timestamp` + which shows the last time the `backlog` metrics have been updated. + ([\#3723](https://github.com/informalsystems/hermes/issues/3723)) + +[#3697]: https://github.com/informalsystems/hermes/issues/3697 +[#3703]: https://github.com/informalsystems/hermes/issues/3703 + +## v1.7.3 + +*November 29th, 2023* + +This release improves the reliability of the `evidence` command and +fixes a bug that was preventing evidence to be reported, +as seen on the Gaia RS testnet. + +### BUG FIXES + +- [Relayer CLI](relayer-cli) + - Improve reliability of `evidence` command and fix a bug that was + preventing evidence to be reported, as seen on the Gaia RS testnet + ([\#3702](https://github.com/informalsystems/hermes/pull/3702)) + +## v1.7.2 + +*November 28th, 2023* + +This patch release of Hermes adds a metric to improve monitoring errors and one +to measure the efficiency of the client update skip feature released in patch v1.7.1. + +* `broadcast_errors` records the number of times a specific error is observed by Hermes when broadcasting transactions. +* `client_updates_skipped` records the number of client updates skipped due to the consensus states already existing. + +### FEATURES + +- [Telemetry & Metrics](telemetry) + - Added metric `client_updates_skipped` to track the number of client + update messages skipped due to the conscensus state existing already. + ([\#3707](https://github.com/informalsystems/hermes/issues/3707)) + - Add a new metric `broadcast_errors` which + records the number of times a specific error is observed by Hermes when broadcasting transactions + ([\#3708](https://github.com/informalsystems/hermes/issues/3708)) + +## v1.7.1 + +*November 13th, 2023* + +This patch release of Hermes now allows operators to set the clearing interval +at a different value for each chain, using the new per-chain `clear_interval` setting. +The global `clear_interval` setting is used as a default value if the per-chain +setting is not defined. + +Additionally, operators can now override the CometBFT compatibility mode to be used +for a chain by using the new `compat_mode` per-chain setting. The main use case for this +is to override the automatically detected compatibility mode in case Hermes gets it wrong +or encounters a non-standard version number and falls back on the wrong CometBFT version. + +On top of that, Hermes will now attempt to save on fees by not building a client update +for a given height if the consensus state for that height is already present on chain. + +### FEATURES + +- Add an optional per-chain setting `compat_mode`, which can be +used to specify which CometBFT compatibility mode is used for interacting with the node over RPC. +([\#3623](https://github.com/informalsystems/hermes/issues/3623)) +- Add a configuration which allows to override the `clear_interval` for specific +chains ([\#3691](https://github.com/informalsystems/hermes/issues/3691)) + +### IMPROVEMENTS + +- Hermes now saves on fees by not including a client update if the +consensus state at desired height is already present on chain. +([\#3521](https://github.com/informalsystems/hermes/issues/3521)) + +## v1.7.0 + +*October 20th, 2023* + +This v1.7 release introduces new features and improvements to Hermes. + +One of the key highlights is the addition of new misbehavior detection features. + +- Hermes now includes a new command called `evidence`, which monitors the blocks emitted by a chain for any presence of misbehavior evidence. +- If misbehavior is detected, the CLI will report that evidence to all counterparty clients of that chain. +On top of that, misbehavior evidence detected on a chain that is a CCV (Cross-Chain Validation) consumer +is now sent to its provider chain, alerting it directly of the misbehaving consumer chain. +- Furthermore, when misbehavior is detected from an on-chain client, such as a light client attack or a double-sign, +the evidence is now submitted to all counterparty clients of the misbehaving chain, rather than just the +counterparty client of the misbehaving client. + +In addition, the REST server of Hermes now has a `/clear_packets` endpoint which allows triggering +packet clearing for a specific chain or all chains if no specific chain is provided. + +Another notable improvement is the ability to change `tracing` directives at runtime. +This feature lets users adjust tracing settings dynamically as needed, providing a more +customizable and efficient debugging experience. + +Overall, the new misbehavior detection features in Hermes contribute to a more robust and secure environment, +enabling timely identification and response to potential misbehaving actors. + +### FEATURES + +- [Relayer CLI](relayer-cli) + - Add a new `evidence` command for monitoring the blocks emitted + by a chain for the presence of a misbehaviour evidence, and + report that evidence to all counteparty clients of that chain. + ([\#3456](https://github.com/informalsystems/hermes/pull/3456)) + - Add a `/clear_packets?chain=CHAIN_ID` endpoint to the built-in + REST server to trigger packet clear for the chain specified in the + chain query param or for all chains if the query param is omitted. + ([\#3398](https://github.com/informalsystems/hermes/issues/3398)) + - Add support for changing `tracing` directives at runtime. + Please see the [corresponding page in the Hermes guide][tracing-guide] for more information. + ([\#3564](https://github.com/informalsystems/hermes/issues/3564)) + + [tracing-guide]: https://hermes.informal.systems/advanced/troubleshooting/log-level.html + + +### IMPROVEMENTS + +- [Relayer Library](relayer) + - When Hermes detects a misbehaviour on a chain that is CCV + consumer, it will now send the misbehaviour evidence to the + provider chain using the new `IcsConsumerMisbehaviour` message. + ([\#3219](https://github.com/informalsystems/hermes/issues/3219)) + - When Hermes detects a misbehaviour from a on-chain client, eg. a light + client attack or a double-sign, it will now submit the misbehaviour + evidence to all counterparty clients of the misbehaving chain + instead of to the counterparty client of the misbehaving client only. + ([\#3223](https://github.com/informalsystems/hermes/issues/3223)) + - Improve error message when scanning unsupported client + ([\#3531](https://github.com/informalsystems/hermes/issues/3531)) + - Regard the `finalize_block_events` field of the `block_results` RPC endpoint, added in CometBFT 0.38 + ([\#3548](https://github.com/informalsystems/hermes/issues/3548)) + - Change fallback compatibility version for CometBFT from v0.37 to v0.34 + ([\#3666](https://github.com/informalsystems/hermes/issues/3666)) +- [Relayer CLI](relayer-cli) + - The `listen` command now works with both `push` and `pull` event sources + ([\#3501](https://github.com/informalsystems/hermes/issues/3501)) + +### BUG FIXES + +- [Relayer CLI](relayer-cli) + - Revert Docker image to Ubuntu LTS and set the UID and GID explicitly + ([\#3580](https://github.com/informalsystems/hermes/issues/3580)) +- [IBC Data structures](relayer-types) + - Fix build of `ibc-relayer-types` documentation on docs.rs + ([\#3549](https://github.com/informalsystems/hermes/issues/3549)) + + ## v1.6.0 *July 19th, 2023* @@ -288,21 +465,21 @@ This patch release adds support for CometBFT in version checks. *March 27th, 2023* Hermes v1.4.0 brings compatibility with chains based on Tendermint/CometBFT 0.37, -while retaining compatiblity with Tendermint/CometBFT 0.34. This is transparent +while retaining compatibility with Tendermint/CometBFT 0.34. This is transparent and does not require any additional configuration. The relayer now supports ICS consumer chains, which only requires operators to specify the `unbonding_period` parameter in the chain settings. This is only -a temporary requirement, in the future Hermes will seamlessy support consumer +a temporary requirement, in the future Hermes will seamlessly support consumer chains with minimal changes to the configuration. This release also deprecates support for chains based on Cosmos SDK 0.43.x and lower, -and bumps the compatiblity to Cosmos SDK 0.47.x. +and bumps the compatibility to Cosmos SDK 0.47.x. The relayer now also allows operators to filter out packets to relay based on whether or not they contain a fee, and the minimal amount of such fee. Please check the relevant [documentation in the Hermes guide](fee-guide) for more information. -Additionnaly, Hermes now also tracks [metrics for ICS29 fees](fee-metrics). +Additionally, Hermes now also tracks [metrics for ICS29 fees](fee-metrics). This release includes a new `query client status` CLI to quickly check whether a client is active, expired or frozen. @@ -886,7 +1063,7 @@ This is the third release candidate for Hermes v1.0.0 🎉 - Release version 0.18.0 of `ibc-telemetry` -#### IMROVEMENTS +#### IMPROVEMENTS - Improve the metrics - Renamed `oldest_sequence` metric to `backlog_oldest_sequence` @@ -1591,7 +1768,7 @@ Before running Hermes v0.11.0, make sure you remove the `mode.packets.filter` op and consensus states ([#1481](https://github.com/informalsystems/hermes/issues/1481)) - More structural logging in relayer, using tracing spans and key-value pairs. ([#1491](https://github.com/informalsystems/hermes/pull/1491)) - - Improved documention w.r.t. keys for Ethermint-based chains + - Improved documentation w.r.t. keys for Ethermint-based chains ([#1785](https://github.com/informalsystems/hermes/issues/1785)) - [Relayer CLI](crates/relayer-cli) - Add custom options to the `create client` command. @@ -1984,7 +2161,7 @@ This release also fixes a bug where the chain runtime within the relayer would c This release of Hermes is the first to be compatible with the development version of Cosmos SDK 0.43. Hermes 0.7.0 also improves the performance and reliability of the relayer, notably by waiting asynchronously for transactions to be confirmed. -Additionnally, Hermes now includes a REST server which exposes the relayer's internal state over HTTP. +Additionally, Hermes now includes a REST server which exposes the relayer's internal state over HTTP. ### BUG FIXES @@ -2583,7 +2760,7 @@ This release also finalizes the initial implementation of all the ICS 004 handle - Fix for chains that don't have `cosmos` account prefix ([#416]) - Fix for building the `trusted_validator_set` for the header used in client updates ([#770]) - Don't send `MsgAcknowledgment` if channel is closed ([#675]) - - Fix a bug where the keys addresses had their account prefix overriden by the prefix in the configuration ([#751]) + - Fix a bug where the keys addresses had their account prefix overridden by the prefix in the configuration ([#751]) - [ibc-relayer-cli] - Hermes guide: improved installation guideline ([#672]) @@ -2721,7 +2898,7 @@ Noteworthy changes in this release include: ### FEATURES -- Continous Integration (CI) end-to-end (e2e) testing with gaia v4 ([#32], [#582], [#602]) +- Continuous Integration (CI) end-to-end (e2e) testing with gaia v4 ([#32], [#582], [#602]) - Add support for streamlining releases ([#507]) - [ibc-relayer-cli] @@ -2878,7 +3055,7 @@ Special thanks to external contributors for this release: @CharlyCst ([#102], [# - CLI for client update message ([#277]) - Implement the relayer CLI for connection handshake messages ([#358], [#359], [#360]) - Implement the relayer CLI for channel handshake messages ([#371], [#372], [#373], [#374]) - - Added basic client, connection, and channel lifecyle in relayer v0 ([#376], [#377], [#378]) + - Added basic client, connection, and channel lifecycle in relayer v0 ([#376], [#377], [#378]) - Implement commands to add and list keys for a chain ([#363]) - Allow overriding of peer_id, height and hash in light add command ([#428]) - [proto-compiler] diff --git a/Cargo.lock b/Cargo.lock index 4281f75f95..4c32bd0e16 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,7 +23,7 @@ dependencies = [ "termcolor", "toml 0.5.11", "tracing", - "tracing-log", + "tracing-log 0.1.4", "tracing-subscriber", "wait-timeout", ] @@ -43,9 +43,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -58,18 +58,18 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "1.0.2" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "arc-swap" @@ -96,18 +96,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.39", ] [[package]] name = "async-trait" -version = "0.1.72" +version = "0.1.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.39", ] [[package]] @@ -145,9 +145,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "axum" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8175979259124331c1d7bf6586ee7e0da434155e4b2d48ec2c8386281d8df39" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" dependencies = [ "async-trait", "axum-core", @@ -194,9 +194,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.68" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", @@ -221,9 +221,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.2" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" [[package]] name = "base64ct" @@ -275,9 +275,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.3" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "block-buffer" @@ -308,9 +308,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "byte-unit" @@ -324,21 +324,21 @@ dependencies = [ [[package]] name = "bytecount" -version = "0.6.3" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c" +checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" dependencies = [ "serde", ] @@ -360,9 +360,9 @@ checksum = "e6e9e01327e6c86e92ec72b1c798d4a94810f147209bbe3ffab6a86954937a6f" [[package]] name = "cargo-platform" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +checksum = "12024c4645c97566567129c204f65d5815a8c9aecf30fcbe682b2fe034996d36" dependencies = [ "serde", ] @@ -382,9 +382,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -488,9 +491,9 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747" +checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" [[package]] name = "contracts" @@ -521,9 +524,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" dependencies = [ "libc", ] @@ -589,9 +592,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" -version = "0.5.2" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4c2f4e1afd912bc40bfd6fed5d9dc1f288e0ba01bfcc835cc5bc3eb13efe15" +checksum = "28f85c3514d2a6e64160359b45a3918c3b4178bcbf4ae5d03ab2d02e521c479a" dependencies = [ "generic-array", "rand_core", @@ -611,9 +614,9 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.0.0" +version = "4.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f711ade317dd348950a9910f81c5947e3d8907ebd2b83f76203ff1807e6a2bc2" +checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -628,13 +631,13 @@ dependencies = [ [[package]] name = "curve25519-dalek-derive" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.39", ] [[package]] @@ -652,12 +655,12 @@ dependencies = [ [[package]] name = "dashmap" -version = "5.5.0" +version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6943ae99c34386c84a470c499d3414f66502a41340aa895406e0d2e4a207b91d" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if 1.0.0", - "hashbrown 0.14.0", + "hashbrown 0.14.2", "lock_api", "once_cell", "parking_lot_core", @@ -671,14 +674,23 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "der" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7ed52955ce76b1554f509074bb357d3fb8ac9b51288a65a3fd480d1dfba946" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" dependencies = [ "const-oid", "zeroize", ] +[[package]] +name = "deranged" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +dependencies = [ + "powerfmt", +] + [[package]] name = "derivation-path" version = "0.2.0" @@ -750,17 +762,11 @@ dependencies = [ "winapi", ] -[[package]] -name = "dyn-clone" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "304e6508efa593091e97a9abbc10f90aa7ca635b6d2784feff3c89d41dd12272" - [[package]] name = "ecdsa" -version = "0.16.7" +version = "0.16.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0997c976637b606099b9985693efa3581e84e41f5c11ba5255f88711058ad428" +checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" dependencies = [ "der", "digest 0.10.7", @@ -772,9 +778,9 @@ dependencies = [ [[package]] name = "ed25519" -version = "2.2.2" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60f6d271ca33075c88028be6f04d502853d63a5ece419d269c15315d4fc1cf1d" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ "pkcs8", "serde", @@ -796,15 +802,16 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7277392b266383ef8396db7fdeb1e77b6c52fed775f5df15bb24f35b72156980" +checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" dependencies = [ "curve25519-dalek", "ed25519", "rand_core", "serde", - "sha2 0.10.7", + "sha2 0.10.8", + "subtle", "zeroize", ] @@ -817,20 +824,20 @@ dependencies = [ "derivation-path", "ed25519-dalek", "hmac", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "elliptic-curve" -version = "0.13.5" +version = "0.13.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" +checksum = "e9775b22bc152ad86a0cf23f0f348b884b26add12bf741e7ffc4d4ab2ab4d205" dependencies = [ "base16ct", "crypto-bigint", @@ -853,18 +860,18 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.32" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "env_logger" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" dependencies = [ "humantime", "is-terminal", @@ -879,36 +886,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" -[[package]] -name = "erased-serde" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da96524cc884f6558f1769b6c46686af2fe8e8b4cd253bd5a3cdba8181b8e070" -dependencies = [ - "serde", -] - [[package]] name = "errno" -version = "0.3.1" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" dependencies = [ - "errno-dragonfly", "libc", "windows-sys 0.48.0", ] -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "error-chain" version = "0.12.4" @@ -930,12 +917,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.9.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "ff" @@ -949,9 +933,9 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.1.20" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77" +checksum = "53a56f0780318174bad1c127063fd0c5fdfb35398e3cd79ffaab931a6c79df80" [[package]] name = "fixed-hash" @@ -990,15 +974,18 @@ dependencies = [ [[package]] name = "fs-err" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" +checksum = "fb5fd9bcbe8b1087cbd395b51498c01bc997cef73e778a80b77a811af5e2d29f" +dependencies = [ + "autocfg", +] [[package]] name = "futures" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" dependencies = [ "futures-channel", "futures-core", @@ -1011,9 +998,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" dependencies = [ "futures-core", "futures-sink", @@ -1021,15 +1008,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" dependencies = [ "futures-core", "futures-task", @@ -1038,38 +1025,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.39", ] [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" dependencies = [ "futures-channel", "futures-core", @@ -1096,9 +1083,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -1109,9 +1096,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.3" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" [[package]] name = "glob" @@ -1152,9 +1139,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.20" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" +checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" dependencies = [ "bytes", "fnv", @@ -1162,7 +1149,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 1.9.3", + "indexmap 2.1.0", "slab", "tokio", "tokio-util", @@ -1183,9 +1170,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" [[package]] name = "hdpath" @@ -1213,9 +1200,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "hex" @@ -1240,9 +1227,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", @@ -1268,9 +1255,9 @@ checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humantime" @@ -1305,7 +1292,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.4.10", "tokio", "tower-service", "tracing", @@ -1314,9 +1301,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http", @@ -1340,7 +1327,7 @@ dependencies = [ [[package]] name = "ibc-chain-registry" -version = "0.25.0" +version = "0.26.4" dependencies = [ "async-trait", "flex-error", @@ -1348,7 +1335,7 @@ dependencies = [ "http", "ibc-proto", "ibc-relayer-types", - "itertools", + "itertools 0.10.5", "reqwest", "serde", "serde_json", @@ -1359,7 +1346,7 @@ dependencies = [ [[package]] name = "ibc-integration-test" -version = "0.25.0" +version = "0.26.4" dependencies = [ "http", "ibc-relayer", @@ -1369,18 +1356,20 @@ dependencies = [ "serde", "serde_json", "tempfile", + "tendermint", + "tendermint-rpc", "time", - "toml 0.7.6", + "toml 0.7.8", "tonic", ] [[package]] name = "ibc-proto" -version = "0.37.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "725fd83c94e9859fd967cd706996679799171eba940740f071f0046fb6f6e031" +checksum = "32b5aca9ca863246a2b358e0a1845759780860673e54c0a76335faccc504981c" dependencies = [ - "base64 0.21.2", + "base64 0.21.5", "bytes", "flex-error", "ics23", @@ -1393,7 +1382,7 @@ dependencies = [ [[package]] name = "ibc-relayer" -version = "0.25.0" +version = "0.26.4" dependencies = [ "anyhow", "async-stream", @@ -1420,7 +1409,7 @@ dependencies = [ "ibc-proto", "ibc-relayer-types", "ibc-telemetry", - "itertools", + "itertools 0.10.5", "moka", "num-bigint", "num-rational", @@ -1435,13 +1424,15 @@ dependencies = [ "serde_derive", "serde_json", "serial_test", - "sha2 0.10.7", + "sha2 0.10.8", "signature", "strum", "subtle-encoding", "tendermint", "tendermint-light-client", "tendermint-light-client-detector", + "tendermint-light-client-verifier", + "tendermint-proto", "tendermint-rpc", "tendermint-testgen", "test-log", @@ -1450,16 +1441,16 @@ dependencies = [ "tiny-keccak", "tokio", "tokio-stream", - "toml 0.7.6", + "toml 0.7.8", "tonic", "tracing", "tracing-subscriber", - "uuid 1.4.0", + "uuid 1.5.0", ] [[package]] name = "ibc-relayer-cli" -version = "1.6.0" +version = "1.7.4" dependencies = [ "abscissa_core", "clap", @@ -1480,7 +1471,7 @@ dependencies = [ "ibc-relayer-rest", "ibc-relayer-types", "ibc-telemetry", - "itertools", + "itertools 0.10.5", "once_cell", "oneline-eyre", "regex", @@ -1500,7 +1491,7 @@ dependencies = [ [[package]] name = "ibc-relayer-rest" -version = "0.25.0" +version = "0.26.4" dependencies = [ "axum", "crossbeam-channel 0.5.8", @@ -1509,23 +1500,21 @@ dependencies = [ "reqwest", "serde", "tokio", - "toml 0.7.6", + "toml 0.7.8", "tracing", ] [[package]] name = "ibc-relayer-types" -version = "0.25.0" +version = "0.26.4" dependencies = [ "bytes", "derive_more", - "dyn-clone", "env_logger", - "erased-serde", "flex-error", "ibc-proto", "ics23", - "itertools", + "itertools 0.10.5", "num-rational", "primitive-types", "prost", @@ -1548,7 +1537,7 @@ dependencies = [ [[package]] name = "ibc-telemetry" -version = "0.25.0" +version = "0.26.4" dependencies = [ "axum", "dashmap", @@ -1567,7 +1556,7 @@ dependencies = [ [[package]] name = "ibc-test-framework" -version = "0.25.0" +version = "0.26.4" dependencies = [ "color-eyre", "crossbeam-channel 0.5.8", @@ -1580,7 +1569,7 @@ dependencies = [ "ibc-relayer", "ibc-relayer-cli", "ibc-relayer-types", - "itertools", + "itertools 0.10.5", "once_cell", "prost", "rand", @@ -1588,11 +1577,11 @@ dependencies = [ "serde", "serde_json", "serde_yaml", - "sha2 0.10.7", + "sha2 0.10.8", "subtle-encoding", "tendermint-rpc", "tokio", - "toml 0.7.6", + "toml 0.7.8", "tonic", "tracing", "tracing-subscriber", @@ -1611,7 +1600,7 @@ dependencies = [ "prost", "ripemd", "serde", - "sha2 0.10.7", + "sha2 0.10.8", "sha3", ] @@ -1658,12 +1647,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown 0.14.2", ] [[package]] @@ -1676,31 +1665,11 @@ dependencies = [ "serde", ] -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.2", - "libc", - "windows-sys 0.48.0", -] - [[package]] name = "ipnet" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is-terminal" @@ -1708,8 +1677,8 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi 0.3.2", - "rustix 0.38.4", + "hermit-abi 0.3.3", + "rustix", "windows-sys 0.48.0", ] @@ -1722,31 +1691,40 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itoa" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" dependencies = [ "wasm-bindgen", ] [[package]] name = "k256" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" +checksum = "3f01b677d82ef7a676aa37e099defd83a28e15687112cafdd112d60236b6115b" dependencies = [ "cfg-if 1.0.0", "ecdsa", "elliptic-curve", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -1766,27 +1744,32 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] -name = "linux-raw-sys" -version = "0.3.8" +name = "libredox" +version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.1", + "libc", + "redox_syscall", +] [[package]] name = "linux-raw-sys" -version = "0.4.3" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -1794,9 +1777,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "mach2" @@ -1818,9 +1801,9 @@ dependencies = [ [[package]] name = "matchit" -version = "0.7.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "maybe-uninit" @@ -1830,9 +1813,9 @@ checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memchr" -version = "2.6.3" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memoffset" @@ -1860,9 +1843,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" dependencies = [ "libc", "wasi", @@ -1871,9 +1854,9 @@ dependencies = [ [[package]] name = "moka" -version = "0.11.3" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa6e72583bf6830c956235bff0d5afec8cf2952f579ebad18ae7821a917d950f" +checksum = "d8017ec3548ffe7d4cef7ac0e12b044c01164a74c0f3119420faeaf13490ad8b" dependencies = [ "crossbeam-channel 0.5.8", "crossbeam-epoch", @@ -1882,13 +1865,12 @@ dependencies = [ "parking_lot", "quanta", "rustc_version", - "scheduled-thread-pool", "skeptic", "smallvec", "tagptr", "thiserror", "triomphe", - "uuid 1.4.0", + "uuid 1.5.0", ] [[package]] @@ -1903,9 +1885,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" dependencies = [ "autocfg", "num-integer", @@ -1949,9 +1931,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", ] @@ -1962,15 +1944,15 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi 0.3.3", "libc", ] [[package]] name = "object" -version = "0.31.1" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" dependencies = [ "memchr", ] @@ -2061,9 +2043,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.5.1" +version = "6.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" [[package]] name = "overload" @@ -2089,22 +2071,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.3.5", + "redox_syscall", "smallvec", - "windows-targets 0.48.1", + "windows-targets 0.48.5", ] [[package]] name = "paste" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4b27ab7be369122c218afc2079489cdcb4b517c0a3fc386ff11e1fedfcc2b35" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "pbkdf2" @@ -2150,29 +2132,29 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pin-project" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.39", ] [[package]] name = "pin-project-lite" -version = "0.2.10" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -2192,9 +2174,15 @@ dependencies = [ [[package]] name = "platforms" -version = "3.0.2" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630" +checksum = "14e6ab3f592e6fb464fc9712d8d6e6912de6473954635fd76a589d832cffcbb0" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" @@ -2204,9 +2192,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "primitive-types" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" dependencies = [ "fixed-hash", "impl-serde", @@ -2239,9 +2227,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.64" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] @@ -2278,10 +2266,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "265baba7fabd416cf5078179f7d2cbeca4ce7a9041111900675ea7c4cb8a4c32" dependencies = [ "anyhow", - "itertools", + "itertools 0.11.0", "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.39", ] [[package]] @@ -2328,9 +2316,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.29" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -2376,43 +2364,34 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ "getrandom", - "redox_syscall 0.2.16", + "libredox", "thiserror", ] [[package]] name = "regex" -version = "1.9.5" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.3.8", - "regex-syntax 0.7.5", + "regex-automata 0.4.3", + "regex-syntax 0.8.2", ] [[package]] @@ -2426,13 +2405,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.8" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.5", + "regex-syntax 0.8.2", ] [[package]] @@ -2443,17 +2422,17 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.5" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" -version = "0.11.21" +version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78fdbab6a7e1d7b13cc8ff10197f47986b41c639300cc3c8158cac7847c9bbef" +checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ - "base64 0.21.2", + "base64 0.21.5", "bytes", "encoding_rs", "futures-core", @@ -2506,17 +2485,16 @@ dependencies = [ [[package]] name = "ring" -version = "0.16.20" +version = "0.17.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" dependencies = [ "cc", + "getrandom", "libc", - "once_cell", "spin", "untrusted", - "web-sys", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -2551,36 +2529,22 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", -] - -[[package]] -name = "rustix" -version = "0.38.4" +version = "0.38.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" +checksum = "9ad981d6c340a49cdc40a1028d9c6084ec7e9fa33fcb839cab656a267071e234" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.1", "errno", "libc", - "linux-raw-sys 0.4.3", + "linux-raw-sys", "windows-sys 0.48.0", ] [[package]] name = "rustls" -version = "0.21.7" +version = "0.21.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" +checksum = "446e14c5cda4f3f30fe71863c34ec70f5ac79d6087097ad0bb433e1be5edf04c" dependencies = [ "log", "ring", @@ -2602,18 +2566,18 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.2", + "base64 0.21.5", ] [[package]] name = "rustls-webpki" -version = "0.101.4" +version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ "ring", "untrusted", @@ -2621,15 +2585,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc31bd9b61a32c31f9650d18add92aa83a49ba979c143eefd27fe7177b05bd5f" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "same-file" @@ -2649,26 +2613,17 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "scheduled-thread-pool" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19" -dependencies = [ - "parking_lot", -] - [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sct" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ "ring", "untrusted", @@ -2676,9 +2631,9 @@ dependencies = [ [[package]] name = "sec1" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", @@ -2721,9 +2676,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -2734,9 +2689,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ "core-foundation-sys", "libc", @@ -2744,27 +2699,27 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.17" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.171" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" +checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" dependencies = [ "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.11" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a16be4fe5320ade08736447e3198294a5ea9a6d44dde6f35f0a5e06859c427a" +checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" dependencies = [ "serde", ] @@ -2781,20 +2736,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.171" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682" +checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.39", ] [[package]] name = "serde_json" -version = "1.0.102" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5062a995d481b2308b6064e9af76011f2921c35f97b0468811ed9f6cd91dfed" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa", "ryu", @@ -2803,9 +2758,9 @@ dependencies = [ [[package]] name = "serde_path_to_error" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc4422959dd87a76cb117c191dcbffc20467f06c9100b76721dab370f24d3a" +checksum = "4beec8bce849d58d06238cb50db2e1c417cfeafa4c63f692b15c82b7c80f8335" dependencies = [ "itoa", "serde", @@ -2813,20 +2768,20 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.14" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d89a8107374290037607734c0b73a85db7ed80cae314b3c5791f192a496e731" +checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.39", ] [[package]] name = "serde_spanned" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" dependencies = [ "serde", ] @@ -2845,11 +2800,11 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.22" +version = "0.9.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "452e67b9c20c37fa79df53201dc03839651086ed9bbe92b3ca585ca9fdaa7d85" +checksum = "3cc7a1570e38322cfe4154732e5110f887ea57e22b76f4bfd32b5bdd3368666c" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.1.0", "itoa", "ryu", "serde", @@ -2878,14 +2833,14 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.39", ] [[package]] name = "sha1" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -2907,9 +2862,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -2928,9 +2883,9 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] @@ -2993,34 +2948,44 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] name = "smallvec" -version = "1.11.0" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "socket2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", "winapi", ] +[[package]] +name = "socket2" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "spin" -version = "0.5.2" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "spki" @@ -3055,15 +3020,15 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.25.1" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6069ca09d878a33f883cc06aaa9718ede171841d3832450354410b718b097232" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" dependencies = [ "heck", "proc-macro2", "quote", "rustversion", - "syn 2.0.25", + "syn 2.0.39", ] [[package]] @@ -3100,9 +3065,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.25" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e3fc8c0c74267e2df136e5e5fb656a464158aa57624053375eb9c8c6e25ae2" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ "proc-macro2", "quote", @@ -3156,15 +3121,14 @@ checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" [[package]] name = "tempfile" -version = "3.6.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ - "autocfg", "cfg-if 1.0.0", "fastrand", - "redox_syscall 0.3.5", - "rustix 0.37.23", + "redox_syscall", + "rustix", "windows-sys 0.48.0", ] @@ -3190,7 +3154,7 @@ dependencies = [ "serde_bytes", "serde_json", "serde_repr", - "sha2 0.10.7", + "sha2 0.10.8", "signature", "subtle", "subtle-encoding", @@ -3344,22 +3308,22 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.2.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" dependencies = [ "winapi-util", ] [[package]] name = "test-log" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9601d162c1d77e62c1ea0bc8116cd1caf143ce3af947536c3c9052a1677fe0c" +checksum = "f66edd6b6cd810743c0c71e1d085e92b01ce6a72782032e3f794c8284fe4bcdd" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.39", ] [[package]] @@ -3370,22 +3334,22 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.43" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.43" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.39", ] [[package]] @@ -3400,10 +3364,12 @@ dependencies = [ [[package]] name = "time" -version = "0.3.22" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" +checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" dependencies = [ + "deranged", + "powerfmt", "serde", "time-core", "time-macros", @@ -3411,15 +3377,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.9" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" dependencies = [ "time-core", ] @@ -3436,7 +3402,7 @@ dependencies = [ "pbkdf2", "rand", "rustc-hash", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", "unicode-normalization", "wasm-bindgen", @@ -3469,11 +3435,10 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.29.1" +version = "1.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" dependencies = [ - "autocfg", "backtrace", "bytes", "libc", @@ -3482,7 +3447,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.5.5", "tokio-macros", "windows-sys 0.48.0", ] @@ -3499,13 +3464,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.39", ] [[package]] @@ -3531,9 +3496,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.8" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", @@ -3554,9 +3519,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" dependencies = [ "serde", "serde_spanned", @@ -3566,20 +3531,20 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.12" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c500344a19072298cd05a7224b3c0c629348b78692bf48466c5238656e315a78" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.1.0", "serde", "serde_spanned", "toml_datetime", @@ -3595,7 +3560,7 @@ dependencies = [ "async-stream", "async-trait", "axum", - "base64 0.21.2", + "base64 0.21.5", "bytes", "h2", "http", @@ -3651,11 +3616,10 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if 1.0.0", "log", "pin-project-lite", "tracing-attributes", @@ -3664,20 +3628,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.39", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -3695,12 +3659,23 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2" dependencies = [ - "lazy_static", "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", "tracing-core", ] @@ -3716,9 +3691,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers", "nu-ansi-term", @@ -3731,7 +3706,7 @@ dependencies = [ "thread_local", "tracing", "tracing-core", - "tracing-log", + "tracing-log 0.2.0", "tracing-serde", ] @@ -3769,9 +3744,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "uint" @@ -3787,9 +3762,9 @@ dependencies = [ [[package]] name = "unicase" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" dependencies = [ "version_check", ] @@ -3802,9 +3777,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.10" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" @@ -3817,9 +3792,9 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "unicode-xid" @@ -3829,15 +3804,15 @@ checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "unsafe-libyaml" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1865806a559042e51ab5414598446a5871b561d21b6764f2eabb0dd481d880a6" +checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" [[package]] name = "untrusted" -version = "0.7.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" @@ -3852,9 +3827,9 @@ dependencies = [ [[package]] name = "urlencoding" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" [[package]] name = "utf-8" @@ -3876,9 +3851,9 @@ checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" [[package]] name = "uuid" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d023da39d1fde5a8a3fe1f3e01ca9632ada0a63e9797de55a879d6e2236277be" +checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" dependencies = [ "getrandom", ] @@ -3906,9 +3881,9 @@ dependencies = [ [[package]] name = "walkdir" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" dependencies = [ "same-file", "winapi-util", @@ -3931,9 +3906,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -3941,24 +3916,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.39", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -3968,9 +3943,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3978,28 +3953,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.39", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" dependencies = [ "js-sys", "wasm-bindgen", @@ -4029,9 +4004,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -4057,7 +4032,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.48.5", ] [[package]] @@ -4077,17 +4052,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -4098,9 +4073,9 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" @@ -4110,9 +4085,9 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" @@ -4122,9 +4097,9 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" @@ -4134,9 +4109,9 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" @@ -4146,9 +4121,9 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" @@ -4158,9 +4133,9 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" @@ -4170,15 +4145,15 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.4.9" +version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81a2094c43cc94775293eaa0e499fbc30048a6d824ac82c0351a8c0bf9112529" +checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" dependencies = [ "memchr", ] @@ -4195,9 +4170,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "12a3946ecfc929b583800f4629b6c25b88ac6e92a40ea5670f77112a85d40a8b" dependencies = [ "zeroize_derive", ] @@ -4210,5 +4185,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.39", ] diff --git a/README.md b/README.md index 4c6bda0434..b816b659e0 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,10 @@ [![Cosmos ecosystem][cosmos-shield]][cosmos-link] [![Build Status][build-image]][build-link] -[![End to End testing][e2e-image]][e2e-link] +[![Integration tests][test-image]][test-link] [![Apache 2.0 Licensed][license-image]][license-link] ![Rust Stable][rustc-image] -![Rust 1.70+][rustc-version] +![Rust 1.71+][rustc-version] Rust implementation of an Inter-Blockchain Communication (IBC) relayer. @@ -46,7 +46,7 @@ The repository also includes [TLA+ specifications](docs/spec). ## Requirements -The crates in this project require Rust `1.70.0`. +The crates in this project require Rust `1.71.0`. ## Hermes Guide @@ -116,12 +116,12 @@ Unless required by applicable law or agreed to in writing, software distributed [build-image]: https://github.com/informalsystems/hermes/workflows/Rust/badge.svg [build-link]: https://github.com/informalsystems/hermes/actions?query=workflow%3ARust -[e2e-image]: https://github.com/informalsystems/hermes/workflows/End%20to%20End%20testing/badge.svg -[e2e-link]: https://github.com/informalsystems/hermes/actions?query=workflow%3A%22End+to+End+testing%22 +[test-image]: https://github.com/informalsystems/hermes/workflows/Integration/badge.svg +[test-link]: https://github.com/informalsystems/hermes/actions?query=workflow%3A%22Integration%22 [license-image]: https://img.shields.io/badge/license-Apache_2.0-blue.svg [license-link]: https://github.com/informalsystems/hermes/blob/master/LICENSE [rustc-image]: https://img.shields.io/badge/rustc-stable-blue.svg -[rustc-version]: https://img.shields.io/badge/rustc-1.70+-blue.svg +[rustc-version]: https://img.shields.io/badge/rustc-1.71+-blue.svg [cosmos-shield]: https://img.shields.io/static/v1?label=&labelColor=1B1E36&color=1B1E36&message=cosmos%20ecosystem&style=for-the-badge&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI0LjMuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAyNTAwIDI1MDAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDI1MDAgMjUwMDsiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoJLnN0MHtmaWxsOiM2RjczOTA7fQoJLnN0MXtmaWxsOiNCN0I5Qzg7fQo8L3N0eWxlPgo8cGF0aCBjbGFzcz0ic3QwIiBkPSJNMTI1Mi42LDE1OS41Yy0xMzQuOSwwLTI0NC4zLDQ4OS40LTI0NC4zLDEwOTMuMXMxMDkuNCwxMDkzLjEsMjQ0LjMsMTA5My4xczI0NC4zLTQ4OS40LDI0NC4zLTEwOTMuMQoJUzEzODcuNSwxNTkuNSwxMjUyLjYsMTU5LjV6IE0xMjY5LjQsMjI4NGMtMTUuNCwyMC42LTMwLjksNS4xLTMwLjksNS4xYy02Mi4xLTcyLTkzLjItMjA1LjgtOTMuMi0yMDUuOAoJYy0xMDguNy0zNDkuOC04Mi44LTExMDAuOC04Mi44LTExMDAuOGM1MS4xLTU5Ni4yLDE0NC03MzcuMSwxNzUuNi03NjguNGM2LjctNi42LDE3LjEtNy40LDI0LjctMmM0NS45LDMyLjUsODQuNCwxNjguNSw4NC40LDE2OC41CgljMTEzLjYsNDIxLjgsMTAzLjMsODE3LjksMTAzLjMsODE3LjljMTAuMywzNDQuNy01Ni45LDczMC41LTU2LjksNzMwLjVDMTM0MS45LDIyMjIuMiwxMjY5LjQsMjI4NCwxMjY5LjQsMjI4NHoiLz4KPHBhdGggY2xhc3M9InN0MCIgZD0iTTIyMDAuNyw3MDguNmMtNjcuMi0xMTcuMS01NDYuMSwzMS42LTEwNzAsMzMycy04OTMuNSw2MzguOS04MjYuMyw3NTUuOXM1NDYuMS0zMS42LDEwNzAtMzMyCglTMjI2Ny44LDgyNS42LDIyMDAuNyw3MDguNkwyMjAwLjcsNzA4LjZ6IE0zNjYuNCwxNzgwLjRjLTI1LjctMy4yLTE5LjktMjQuNC0xOS45LTI0LjRjMzEuNi04OS43LDEzMi0xODMuMiwxMzItMTgzLjIKCWMyNDkuNC0yNjguNCw5MTMuOC02MTkuNyw5MTMuOC02MTkuN2M1NDIuNS0yNTIuNCw3MTEuMS0yNDEuOCw3NTMuOC0yMzBjOS4xLDIuNSwxNSwxMS4yLDE0LDIwLjZjLTUuMSw1Ni0xMDQuMiwxNTctMTA0LjIsMTU3CgljLTMwOS4xLDMwOC42LTY1Ny44LDQ5Ni44LTY1Ny44LDQ5Ni44Yy0yOTMuOCwxODAuNS02NjEuOSwzMTQuMS02NjEuOSwzMTQuMUM0NTYsMTgxMi42LDM2Ni40LDE3ODAuNCwzNjYuNCwxNzgwLjRMMzY2LjQsMTc4MC40CglMMzY2LjQsMTc4MC40eiIvPgo8cGF0aCBjbGFzcz0ic3QwIiBkPSJNMjE5OC40LDE4MDAuNGM2Ny43LTExNi44LTMwMC45LTQ1Ni44LTgyMy03NTkuNVMzNzQuNCw1ODcuOCwzMDYuOCw3MDQuN3MzMDAuOSw0NTYuOCw4MjMuMyw3NTkuNQoJUzIxMzAuNywxOTE3LjQsMjE5OC40LDE4MDAuNHogTTM1MS42LDc0OS44Yy0xMC0yMy43LDExLjEtMjkuNCwxMS4xLTI5LjRjOTMuNS0xNy42LDIyNC43LDIyLjYsMjI0LjcsMjIuNgoJYzM1Ny4yLDgxLjMsOTk0LDQ4MC4yLDk5NCw0ODAuMmM0OTAuMywzNDMuMSw1NjUuNSw0OTQuMiw1NzYuOCw1MzcuMWMyLjQsOS4xLTIuMiwxOC42LTEwLjcsMjIuNGMtNTEuMSwyMy40LTE4OC4xLTExLjUtMTg4LjEtMTEuNQoJYy00MjIuMS0xMTMuMi03NTkuNi0zMjAuNS03NTkuNi0zMjAuNWMtMzAzLjMtMTYzLjYtNjAzLjItNDE1LjMtNjAzLjItNDE1LjNjLTIyNy45LTE5MS45LTI0NS0yODUuNC0yNDUtMjg1LjRMMzUxLjYsNzQ5Ljh6Ii8+CjxjaXJjbGUgY2xhc3M9InN0MSIgY3g9IjEyNTAiIGN5PSIxMjUwIiByPSIxMjguNiIvPgo8ZWxsaXBzZSBjbGFzcz0ic3QxIiBjeD0iMTc3Ny4zIiBjeT0iNzU2LjIiIHJ4PSI3NC42IiByeT0iNzcuMiIvPgo8ZWxsaXBzZSBjbGFzcz0ic3QxIiBjeD0iNTUzIiBjeT0iMTAxOC41IiByeD0iNzQuNiIgcnk9Ijc3LjIiLz4KPGVsbGlwc2UgY2xhc3M9InN0MSIgY3g9IjEwOTguMiIgY3k9IjE5NjUiIHJ4PSI3NC42IiByeT0iNzcuMiIvPgo8L3N2Zz4K [cosmos-link]: https://cosmos.network diff --git a/ci/misbehaviour-ics/double_sign_test.sh b/ci/misbehaviour-ics/double_sign_test.sh new file mode 100644 index 0000000000..3685868433 --- /dev/null +++ b/ci/misbehaviour-ics/double_sign_test.sh @@ -0,0 +1,611 @@ +#!/bin/bash +# shellcheck disable=2086,2004 + +set -eu + +DEBUG=${DEBUG:-false} + +if [ "$DEBUG" = true ]; then + set -x +fi + +# User balance of stake tokens +USER_COINS="100000000000stake" +# Amount of stake tokens staked +STAKE="100000000stake" +# Node IP address +NODE_IP="127.0.0.1" + +# Home directory +HOME_DIR="/tmp/hermes-ics-double-sign" + +# Hermes debug +if [ "$DEBUG" = true ]; then + HERMES_DEBUG="--debug=rpc" +else + HERMES_DEBUG="" +fi +# Hermes config +HERMES_CONFIG="$HOME_DIR/hermes.toml" +# Hermes binary +HERMES_BIN="cargo run -q --bin hermes -- $HERMES_DEBUG --config $HERMES_CONFIG" + +# Validator moniker +MONIKERS=("coordinator" "alice" "bob") +LEAD_VALIDATOR_MONIKER="coordinator" + +# Hermes will connect to this node on both provider and consumer +HERMES_VALIDATOR_MONIKER="bob" + +PROV_NODES_ROOT_DIR=${HOME_DIR}/nodes/provider +CONS_NODES_ROOT_DIR=${HOME_DIR}/nodes/consumer + +# Base port. Ports assigned after these ports sequentially by nodes. +RPC_LADDR_BASEPORT=29170 +P2P_LADDR_BASEPORT=29180 +GRPC_LADDR_BASEPORT=29190 +NODE_ADDRESS_BASEPORT=29200 +PPROF_LADDR_BASEPORT=29210 +CLIENT_BASEPORT=29220 + + +# Clean start +pkill -f interchain-security-pd &> /dev/null || true +pkill -f interchain-security-cd &> /dev/null || true +pkill -f hermes &> /dev/null || true +sleep 1 + +mkdir -p "${HOME_DIR}" +rm -rf "${PROV_NODES_ROOT_DIR}" +rm -rf "${CONS_NODES_ROOT_DIR}" + +# Let lead validator create genesis file +LEAD_VALIDATOR_PROV_DIR=${PROV_NODES_ROOT_DIR}/provider-${LEAD_VALIDATOR_MONIKER} +LEAD_VALIDATOR_CONS_DIR=${CONS_NODES_ROOT_DIR}/consumer-${LEAD_VALIDATOR_MONIKER} +LEAD_PROV_KEY=${LEAD_VALIDATOR_MONIKER}-key +LEAD_PROV_LISTEN_ADDR=tcp://${NODE_IP}:${RPC_LADDR_BASEPORT} + +for index in "${!MONIKERS[@]}" +do + MONIKER=${MONIKERS[$index]} + # validator key + PROV_KEY=${MONIKER}-key + PROV_KEY2=${MONIKER}-key2 + + # home directory of this validator on provider + PROV_NODE_DIR=${PROV_NODES_ROOT_DIR}/provider-${MONIKER} + + # home directory of this validator on consumer + CONS_NODE_DIR=${CONS_NODES_ROOT_DIR}/consumer-${MONIKER} + + # Build genesis file and node directory structure + interchain-security-pd init $MONIKER --chain-id provider --home ${PROV_NODE_DIR} + jq ".app_state.gov.params.voting_period = \"5s\" | .app_state.staking.params.unbonding_time = \"86400s\"" \ + ${PROV_NODE_DIR}/config/genesis.json > \ + ${PROV_NODE_DIR}/edited_genesis.json && mv ${PROV_NODE_DIR}/edited_genesis.json ${PROV_NODE_DIR}/config/genesis.json + + + sleep 1 + + # Create account keypair + interchain-security-pd keys add $PROV_KEY --home ${PROV_NODE_DIR} --keyring-backend test --output json > ${PROV_NODE_DIR}/${PROV_KEY}.json 2>&1 + interchain-security-pd keys add $PROV_KEY2 --home ${PROV_NODE_DIR} --keyring-backend test --output json > ${PROV_NODE_DIR}/${PROV_KEY2}.json 2>&1 + sleep 1 + + # copy genesis in, unless this validator is the lead validator + if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then + cp ${LEAD_VALIDATOR_PROV_DIR}/config/genesis.json ${PROV_NODE_DIR}/config/genesis.json + fi + + # Add stake to user + PROV_ACCOUNT_ADDR=$(jq -r '.address' ${PROV_NODE_DIR}/${PROV_KEY}.json) + interchain-security-pd genesis add-genesis-account $PROV_ACCOUNT_ADDR $USER_COINS --home ${PROV_NODE_DIR} --keyring-backend test + + PROV_ACCOUNT_ADDR2=$(jq -r '.address' ${PROV_NODE_DIR}/${PROV_KEY2}.json) + interchain-security-pd genesis add-genesis-account $PROV_ACCOUNT_ADDR2 $USER_COINS --home ${PROV_NODE_DIR} --keyring-backend test + sleep 1 + + # copy genesis out, unless this validator is the lead validator + if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then + cp ${PROV_NODE_DIR}/config/genesis.json ${LEAD_VALIDATOR_PROV_DIR}/config/genesis.json + fi + + PPROF_LADDR=${NODE_IP}:$(($PPROF_LADDR_BASEPORT + $index)) + P2P_LADDR_PORT=$(($P2P_LADDR_BASEPORT + $index)) + + # adjust configs of this node + sed -i -r 's/timeout_commit = "5s"/timeout_commit = "3s"/g' ${PROV_NODE_DIR}/config/config.toml + sed -i -r 's/timeout_propose = "3s"/timeout_propose = "1s"/g' ${PROV_NODE_DIR}/config/config.toml + + # make address book non-strict. necessary for this setup + sed -i -r 's/addr_book_strict = true/addr_book_strict = false/g' ${PROV_NODE_DIR}/config/config.toml + + # avoid port double binding + sed -i -r "s/pprof_laddr = \"localhost:6060\"/pprof_laddr = \"${PPROF_LADDR}\"/g" ${PROV_NODE_DIR}/config/config.toml + + # allow duplicate IP addresses (all nodes are on the same machine) + sed -i -r 's/allow_duplicate_ip = false/allow_duplicate_ip = true/g' ${PROV_NODE_DIR}/config/config.toml +done + +for MONIKER in "${MONIKERS[@]}" +do + # validator key + PROV_KEY=${MONIKER}-key + + # home directory of this validator on provider + PROV_NODE_DIR=${PROV_NODES_ROOT_DIR}/provider-${MONIKER} + + # copy genesis in, unless this validator is the lead validator + if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then + cp ${LEAD_VALIDATOR_PROV_DIR}/config/genesis.json* ${PROV_NODE_DIR}/config/genesis.json + fi + + # Stake 1/1000 user's coins + interchain-security-pd genesis gentx $PROV_KEY $STAKE --chain-id provider --home ${PROV_NODE_DIR} --keyring-backend test --moniker $MONIKER + sleep 1 + + # Copy gentxs to the lead validator for possible future collection. + # Obviously we don't need to copy the first validator's gentx to itself + if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then + cp ${PROV_NODE_DIR}/config/gentx/* ${LEAD_VALIDATOR_PROV_DIR}/config/gentx/ + fi +done + +# Collect genesis transactions with lead validator +interchain-security-pd genesis collect-gentxs --home ${LEAD_VALIDATOR_PROV_DIR} --gentx-dir ${LEAD_VALIDATOR_PROV_DIR}/config/gentx/ + +sleep 1 + + +for index in "${!MONIKERS[@]}" +do + MONIKER=${MONIKERS[$index]} + + PERSISTENT_PEERS="" + + for peer_index in "${!MONIKERS[@]}" + do + if [ $index == $peer_index ]; then + continue + fi + PEER_MONIKER=${MONIKERS[$peer_index]} + + PEER_PROV_NODE_DIR=${PROV_NODES_ROOT_DIR}/provider-${PEER_MONIKER} + + PEER_NODE_ID=$(interchain-security-pd tendermint show-node-id --home ${PEER_PROV_NODE_DIR}) + + PEER_P2P_LADDR_PORT=$(($P2P_LADDR_BASEPORT + $peer_index)) + PERSISTENT_PEERS="$PERSISTENT_PEERS,$PEER_NODE_ID@${NODE_IP}:${PEER_P2P_LADDR_PORT}" + done + + # remove trailing comma from persistent peers + PERSISTENT_PEERS=${PERSISTENT_PEERS:1} + + # validator key + PROV_KEY=${MONIKER}-key + PROV_KEY2=${MONIKER}-key2 + + # home directory of this validator on provider + PROV_NODE_DIR=${PROV_NODES_ROOT_DIR}/provider-${MONIKER} + + # home directory of this validator on consumer + CONS_NODE_DIR=${PROV_NODES_ROOT_DIR}/consumer-${MONIKER} + + # copy genesis in, unless this validator is already the lead validator and thus it already has its genesis + if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then + cp ${LEAD_VALIDATOR_PROV_DIR}/config/genesis.json ${PROV_NODE_DIR}/config/genesis.json + fi + + RPC_LADDR_PORT=$(($RPC_LADDR_BASEPORT + $index)) + P2P_LADDR_PORT=$(($P2P_LADDR_BASEPORT + $index)) + GRPC_LADDR_PORT=$(($GRPC_LADDR_BASEPORT + $index)) + NODE_ADDRESS_PORT=$(($NODE_ADDRESS_BASEPORT + $index)) + + if [ $MONIKER == $HERMES_VALIDATOR_MONIKER ]; then + PRPC_LADDR_PORT=$RPC_LADDR_PORT + PGRPC_LADDR_PORT=$GRPC_LADDR_PORT + fi + # Start gaia + interchain-security-pd start \ + --home ${PROV_NODE_DIR} \ + --p2p.persistent_peers ${PERSISTENT_PEERS} \ + --rpc.laddr tcp://${NODE_IP}:${RPC_LADDR_PORT} \ + --grpc.address ${NODE_IP}:${GRPC_LADDR_PORT} \ + --address tcp://${NODE_IP}:${NODE_ADDRESS_PORT} \ + --p2p.laddr tcp://${NODE_IP}:${P2P_LADDR_PORT} \ + --grpc-web.enable=false &> ${PROV_NODE_DIR}/logs & + + sleep 5 +done + +# Build consumer chain proposal file +tee ${LEAD_VALIDATOR_PROV_DIR}/consumer-proposal.json< ${CONS_NODE_DIR}/${PROV_KEY}.json 2>&1 + interchain-security-cd keys add $PROV_KEY2 --home ${CONS_NODE_DIR} --keyring-backend test --output json > ${CONS_NODE_DIR}/${PROV_KEY2}.json 2>&1 + sleep 1 + + # copy genesis in, unless this validator is the lead validator + if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then + cp ${LEAD_VALIDATOR_CONS_DIR}/config/genesis.json ${CONS_NODE_DIR}/config/genesis.json + fi + + # Add stake to user + CONS_ACCOUNT_ADDR=$(jq -r '.address' ${CONS_NODE_DIR}/${PROV_KEY}.json) + interchain-security-cd genesis add-genesis-account $CONS_ACCOUNT_ADDR $USER_COINS --home ${CONS_NODE_DIR} + CONS_ACCOUNT_ADDR2=$(jq -r '.address' ${CONS_NODE_DIR}/${PROV_KEY2}.json) + interchain-security-cd genesis add-genesis-account $CONS_ACCOUNT_ADDR2 $USER_COINS --home ${CONS_NODE_DIR} + sleep 10 + + ### this probably does not have to be done for each node + # Add consumer genesis states to genesis file + RPC_LADDR_PORT=$(($RPC_LADDR_BASEPORT + $index)) + RPC_LADDR=tcp://${NODE_IP}:${RPC_LADDR_PORT} + interchain-security-pd query provider consumer-genesis consumer --home ${PROV_NODE_DIR} --node ${RPC_LADDR} -o json > consumer_gen.json + jq -s '.[0].app_state.ccvconsumer = .[1] | .[0]' ${CONS_NODE_DIR}/config/genesis.json consumer_gen.json > ${CONS_NODE_DIR}/edited_genesis.json \ + && mv ${CONS_NODE_DIR}/edited_genesis.json ${CONS_NODE_DIR}/config/genesis.json + rm consumer_gen.json + ### + + # copy genesis out, unless this validator is the lead validator + if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then + cp ${CONS_NODE_DIR}/config/genesis.json ${LEAD_VALIDATOR_CONS_DIR}/config/genesis.json + fi + + PPROF_LADDR=${NODE_IP}:$(($PPROF_LADDR_BASEPORT + ${#MONIKERS[@]} + $index)) + P2P_LADDR_PORT=$(($P2P_LADDR_BASEPORT + ${#MONIKERS[@]} + $index)) + + # adjust configs of this node + sed -i -r 's/timeout_commit = "5s"/timeout_commit = "3s"/g' ${CONS_NODE_DIR}/config/config.toml + sed -i -r 's/timeout_propose = "3s"/timeout_propose = "1s"/g' ${CONS_NODE_DIR}/config/config.toml + + # make address book non-strict. necessary for this setup + sed -i -r 's/addr_book_strict = true/addr_book_strict = false/g' ${CONS_NODE_DIR}/config/config.toml + + # avoid port double binding + sed -i -r "s/pprof_laddr = \"localhost:6060\"/pprof_laddr = \"${PPROF_LADDR}\"/g" ${CONS_NODE_DIR}/config/config.toml + + # allow duplicate IP addresses (all nodes are on the same machine) + sed -i -r 's/allow_duplicate_ip = false/allow_duplicate_ip = true/g' ${CONS_NODE_DIR}/config/config.toml + + # Create validator states + echo '{"height": "0","round": 0,"step": 0}' > ${CONS_NODE_DIR}/data/priv_validator_state.json + + # Copy validator key files + cp ${PROV_NODE_DIR}/config/priv_validator_key.json ${CONS_NODE_DIR}/config/priv_validator_key.json + cp ${PROV_NODE_DIR}/config/node_key.json ${CONS_NODE_DIR}/config/node_key.json + + # Set default client port + CLIENT_PORT=$(($CLIENT_BASEPORT + ${#MONIKERS[@]} + $index)) + sed -i -r "/node =/ s/= .*/= \"tcp:\/\/${NODE_IP}:${CLIENT_PORT}\"/" ${CONS_NODE_DIR}/config/client.toml + +done + +sleep 1 + + +for index in "${!MONIKERS[@]}" +do + MONIKER=${MONIKERS[$index]} + + PERSISTENT_PEERS="" + + for peer_index in "${!MONIKERS[@]}" + do + if [ $index == $peer_index ]; then + continue + fi + PEER_MONIKER=${MONIKERS[$peer_index]} + + PEER_CONS_NODE_DIR=${CONS_NODES_ROOT_DIR}/consumer-${PEER_MONIKER} + + PEER_NODE_ID=$(interchain-security-pd tendermint show-node-id --home ${PEER_CONS_NODE_DIR}) + + PEER_P2P_LADDR_PORT=$(($P2P_LADDR_BASEPORT + ${#MONIKERS[@]} + $peer_index)) + PERSISTENT_PEERS="$PERSISTENT_PEERS,$PEER_NODE_ID@${NODE_IP}:${PEER_P2P_LADDR_PORT}" + done + + # remove trailing comma from persistent peers + PERSISTENT_PEERS=${PERSISTENT_PEERS:1} + + # validator key + PROV_KEY=${MONIKER}-key + + # home directory of this validator on provider + PROV_NODE_DIR=${PROV_NODES_ROOT_DIR}/provider-${MONIKER} + + # home directory of this validator on consumer + CONS_NODE_DIR=${CONS_NODES_ROOT_DIR}/consumer-${MONIKER} + + # copy genesis in, unless this validator is already the lead validator and thus it already has its genesis + if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then + cp ${LEAD_VALIDATOR_CONS_DIR}/config/genesis.json ${CONS_NODE_DIR}/config/genesis.json + fi + + RPC_LADDR_PORT=$(($RPC_LADDR_BASEPORT + ${#MONIKERS[@]} + $index)) + P2P_LADDR_PORT=$(($P2P_LADDR_BASEPORT + ${#MONIKERS[@]} + $index)) + GRPC_LADDR_PORT=$(($GRPC_LADDR_BASEPORT + ${#MONIKERS[@]} + $index)) + NODE_ADDRESS_PORT=$(($NODE_ADDRESS_BASEPORT + ${#MONIKERS[@]} + $index)) + + if [ $MONIKER == $HERMES_VALIDATOR_MONIKER ]; then + CRPC_LADDR_PORT=$RPC_LADDR_PORT + CGRPC_LADDR_PORT=$GRPC_LADDR_PORT + fi + # Start gaia + interchain-security-cd start \ + --home ${CONS_NODE_DIR} \ + --p2p.persistent_peers ${PERSISTENT_PEERS} \ + --rpc.laddr tcp://${NODE_IP}:${RPC_LADDR_PORT} \ + --grpc.address ${NODE_IP}:${GRPC_LADDR_PORT} \ + --address tcp://${NODE_IP}:${NODE_ADDRESS_PORT} \ + --p2p.laddr tcp://${NODE_IP}:${P2P_LADDR_PORT} \ + --grpc-web.enable=false &> ${CONS_NODE_DIR}/logs & + + sleep 6 +done + +## Cause double signing + +# create directory for double signing node +mkdir $CONS_NODES_ROOT_DIR/consumer-bob-sybil/ +cp -r $CONS_NODES_ROOT_DIR/consumer-bob/* $CONS_NODES_ROOT_DIR/consumer-bob-sybil + +# clear state in consumer-bob-sybil +echo '{"height": "0","round": 0,"step": 0,"signature":"","signbytes":""}' > $CONS_NODES_ROOT_DIR/consumer-bob-sybil/data/priv_validator_state.json + +# add new node key to sybil +# key was generated using gaiad init +# if the node key is not unique, double signing cannot be achieved +# and errors such as this can be seen in the terminal +# 5:54PM ERR found conflicting vote from ourselves; did you unsafe_reset a validator? height=1961 module=consensus round=0 type=2 +# 5:54PM ERR failed to process message err="conflicting votes from validator C888306A908A217B9A943D1DAD8790044D0947A4" +echo '{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"tj55by/yYwruSz4NxsOG9y9k2WrPvKLXKQdz/9jL9Uptmi647OYpcisjwf92TyA+wCUYVDOgW7D53Q+638l9/w=="}}' > $CONS_NODES_ROOT_DIR/consumer-bob-sybil/config/node_key.json + +# does not use persistent peers; will do a lookup in genesis.json to find peers +#ARGS="--address tcp://$CHAIN_PREFIX.252:26655 --rpc.laddr tcp://$CHAIN_PREFIX.252:26658 --grpc.address $CHAIN_PREFIX.252:9091 --log_level trace --p2p.laddr tcp://$CHAIN_PREFIX.252:26656 --grpc-web.enable=false" + +# start double signing node - it should not talk to the node with the same key +#ip netns exec $HOME/nodes/consumer/consumer-bob-sybil $BIN $ARGS --home $HOME/nodes/consumer/consumer-bob-sybil start &> $HOME/nodes/consumer/consumer-bob-sybil/logs & + +# Start gaia +interchain-security-cd start \ + --home $CONS_NODES_ROOT_DIR/consumer-bob-sybil \ + --p2p.persistent_peers ${PERSISTENT_PEERS} \ + --rpc.laddr tcp://${NODE_IP}:29179 \ + --grpc.address ${NODE_IP}:29199 \ + --address tcp://${NODE_IP}:29209 \ + --p2p.laddr tcp://${NODE_IP}:29189 \ + --grpc-web.enable=false &> $CONS_NODES_ROOT_DIR/consumer-bob-sybil/logs & + +# Setup Hermes config file + +tee $HERMES_CONFIG< $HOME_DIR/hermes-start-logs.txt & + +$HERMES_BIN evidence --chain consumer --key-name evidence &> $HOME_DIR/hermes-evidence-logs.txt & + +for _ in $(seq 1 10) +do + sleep 5 + + MSG="successfully submitted double voting evidence to chain" + + if grep -c "$MSG" $HOME_DIR/hermes-evidence-logs.txt; then + echo "[SUCCESS] Successfully submitted double voting evidence to provider chain" + exit 0 + fi +done + +echo "[ERROR] Failed to submit double voting evidence to provider chain" +echo "" +echo "---------------------------------------------------------------" +echo "Hermes start logs:" +cat $HOME_DIR/hermes-start-logs.txt +echo "---------------------------------------------------------------" +echo "Hermes evidence logs:" +cat $HOME_DIR/hermes-evidence-logs.txt +echo "---------------------------------------------------------------" + +exit 1 + diff --git a/ci/misbehaviour-ics/light_client_attack_freeze_test.sh b/ci/misbehaviour-ics/light_client_attack_freeze_test.sh new file mode 100644 index 0000000000..24661ace22 --- /dev/null +++ b/ci/misbehaviour-ics/light_client_attack_freeze_test.sh @@ -0,0 +1,539 @@ +#!/bin/bash +# shellcheck disable=2086 + +set -eu + +DEBUG=${DEBUG:-false} + +if [ "$DEBUG" = true ]; then + set -x +fi + +diag() { + echo ">> +>> $* +>>" 1>&2 +} + +waiting() { + secs=$1 + shift + msg="$*" + while [ $secs -gt 0 ] + do + echo -ne "|| Waiting $msg (${secs}s)\033[0K\r" + sleep 1 + : $((secs--)) + done + echo "|| Waiting $msg (done)" +} + + +# User balance of stake tokens +USER_COINS="100000000000stake" +# Amount of stake tokens staked +STAKE="100000000stake" +# Amount of stake tokens staked +STAKE2="4000000stake" +# Node IP address +NODE_IP="127.0.0.1" + +# Home directory +HOME_DIR=$HOME + +# Hermes debug +if [ "$DEBUG" = true ]; then + HERMES_DEBUG="--debug=rpc" +else + HERMES_DEBUG="" +fi + +# Hermes config +HERMES_CONFIG="$HOME_DIR/hermes.toml" +HERMES_CONFIG_FORK="$HOME_DIR/hermes-fork.toml" +# Hermes binary +HERMES_BIN="cargo run -q --bin hermes -- $HERMES_DEBUG --config $HERMES_CONFIG" +HERMES_BIN_FORK="cargo run -q --bin hermes -- $HERMES_DEBUG --config $HERMES_CONFIG_FORK" + +# Validator moniker +MONIKER="coordinator" +MONIKER_SUB="sub" + +# Validator directory +PROV_NODE_DIR=${HOME_DIR}/provider-${MONIKER} +PROV_NODE_SUB_DIR=${HOME_DIR}/provider-${MONIKER_SUB} +CONS_NODE_DIR=${HOME_DIR}/consumer-${MONIKER} +CONS_NODE_SUB_DIR=${HOME_DIR}/consumer-${MONIKER_SUB} +CONS_FORK_NODE_DIR=${HOME_DIR}/consumer-fork-${MONIKER} + +# Coordinator key +PROV_KEY=${MONIKER}-key +PROV_KEY_SUB=${MONIKER_SUB}-key + + +# Clean start +pkill -f interchain-security-pd &> /dev/null || true +pkill -f interchain-security-cd &> /dev/null || true +pkill -f hermes &> /dev/null || true + +mkdir -p "${HOME_DIR}" +rm -rf "${PROV_NODE_DIR}" +rm -rf "${PROV_NODE_SUB_DIR}" +rm -rf "${CONS_NODE_DIR}" +rm -rf "${CONS_NODE_SUB_DIR}" +rm -rf "${CONS_FORK_NODE_DIR}" + +# Build genesis file and node directory structure +interchain-security-pd init $MONIKER --chain-id provider --home ${PROV_NODE_DIR} +jq ".app_state.gov.params.voting_period = \"5s\" | .app_state.staking.params.unbonding_time = \"86400s\"" \ + ${PROV_NODE_DIR}/config/genesis.json > \ + ${PROV_NODE_DIR}/edited_genesis.json && mv ${PROV_NODE_DIR}/edited_genesis.json ${PROV_NODE_DIR}/config/genesis.json + +# Create account keypair +interchain-security-pd keys add $PROV_KEY --home ${PROV_NODE_DIR} --keyring-backend test --output json > ${PROV_NODE_DIR}/${PROV_KEY}.json 2>&1 + +# Add stake to user +PROV_ACCOUNT_ADDR=$(jq -r '.address' ${PROV_NODE_DIR}/${PROV_KEY}.json) +interchain-security-pd genesis add-genesis-account "$PROV_ACCOUNT_ADDR" $USER_COINS --home ${PROV_NODE_DIR} --keyring-backend test + +# Stake 1/1000 user's coins +interchain-security-pd genesis gentx $PROV_KEY $STAKE --chain-id provider --home ${PROV_NODE_DIR} --keyring-backend test --moniker $MONIKER + +## config second node + +rm -rf ${PROV_NODE_SUB_DIR} + +# Build genesis file and node directory structure +interchain-security-pd init $MONIKER_SUB --chain-id provider --home ${PROV_NODE_SUB_DIR} + +# Create account keypair +interchain-security-pd keys add $PROV_KEY_SUB --home ${PROV_NODE_SUB_DIR} --keyring-backend test --output json > ${PROV_NODE_SUB_DIR}/${PROV_KEY_SUB}.json 2>&1 + +cp ${PROV_NODE_DIR}/config/genesis.json ${PROV_NODE_SUB_DIR}/config/genesis.json + +# Add stake to user +PROV_ACCOUNT_ADDR=$(jq -r '.address' ${PROV_NODE_SUB_DIR}/${PROV_KEY_SUB}.json) +interchain-security-pd genesis add-genesis-account "$PROV_ACCOUNT_ADDR" $USER_COINS --home ${PROV_NODE_SUB_DIR} --keyring-backend test + +cp -r ${PROV_NODE_DIR}/config/gentx/ ${PROV_NODE_SUB_DIR}/config/gentx/ + +# # Stake 1/1000 user's coins +interchain-security-pd genesis gentx $PROV_KEY_SUB $STAKE2 --chain-id provider --home ${PROV_NODE_SUB_DIR} --keyring-backend test --moniker $MONIKER_SUB + +interchain-security-pd genesis collect-gentxs --home ${PROV_NODE_SUB_DIR} --gentx-dir ${PROV_NODE_SUB_DIR}/config/gentx/ + +cp ${PROV_NODE_SUB_DIR}/config/genesis.json ${PROV_NODE_DIR}/config/genesis.json + + +# Start nodes + +sed -i -r "/node =/ s/= .*/= \"tcp:\/\/${NODE_IP}:26658\"/" ${PROV_NODE_DIR}/config/client.toml +sed -i -r 's/timeout_commit = "5s"/timeout_commit = "3s"/g' ${PROV_NODE_DIR}/config/config.toml +sed -i -r 's/timeout_propose = "3s"/timeout_propose = "1s"/g' ${PROV_NODE_DIR}/config/config.toml +sed -i -r 's/block_sync = true/block_sync = false/g' ${PROV_NODE_DIR}/config/config.toml + +# Start gaia +interchain-security-pd start \ + --home ${PROV_NODE_DIR} \ + --rpc.laddr tcp://${NODE_IP}:26658 \ + --grpc.address ${NODE_IP}:9091 \ + --address tcp://${NODE_IP}:26655 \ + --p2p.laddr tcp://${NODE_IP}:26656 \ + --grpc-web.enable=false &> ${PROV_NODE_DIR}/logs & + +waiting 10 "for provider node to start" + +sed -i -r "/node =/ s/= .*/= \"tcp:\/\/${NODE_IP}:26628\"/" ${PROV_NODE_SUB_DIR}/config/client.toml +sed -i -r 's/timeout_commit = "5s"/timeout_commit = "3s"/g' ${PROV_NODE_SUB_DIR}/config/config.toml +sed -i -r 's/timeout_propose = "3s"/timeout_propose = "1s"/g' ${PROV_NODE_SUB_DIR}/config/config.toml +sed -i -r 's/block_sync = true/block_sync = false/g' ${PROV_NODE_SUB_DIR}/config/config.toml + +# Start gaia +interchain-security-pd start \ + --home ${PROV_NODE_SUB_DIR} \ + --rpc.laddr tcp://${NODE_IP}:26628 \ + --grpc.address ${NODE_IP}:9021 \ + --address tcp://${NODE_IP}:26625 \ + --p2p.laddr tcp://${NODE_IP}:26626 \ + --grpc-web.enable=false &> ${PROV_NODE_SUB_DIR}/logs & + +waiting 10 "for provider sub-node to start" + +# Build consumer chain proposal file +tee ${PROV_NODE_DIR}/consumer-proposal.json< ${CONS_NODE_DIR}/${PROV_KEY}.json 2>&1 + +# Add stake to user account +CONS_ACCOUNT_ADDR=$(jq -r '.address' ${CONS_NODE_DIR}/${PROV_KEY}.json) +interchain-security-cd genesis add-genesis-account "$CONS_ACCOUNT_ADDR" 1000000000stake --home ${CONS_NODE_DIR} + +# Add consumer genesis states to genesis file +interchain-security-pd query provider consumer-genesis consumer --home ${PROV_NODE_DIR} -o json > consumer_gen.json +jq -s '.[0].app_state.ccvconsumer = .[1] | .[0]' ${CONS_NODE_DIR}/config/genesis.json consumer_gen.json > ${CONS_NODE_DIR}/edited_genesis.json \ +&& mv ${CONS_NODE_DIR}/edited_genesis.json ${CONS_NODE_DIR}/config/genesis.json +rm consumer_gen.json + +# Create validator states +echo '{"height": "0","round": 0,"step": 0}' > ${CONS_NODE_DIR}/data/priv_validator_state.json + +# Copy validator key files +cp ${PROV_NODE_DIR}/config/priv_validator_key.json ${CONS_NODE_DIR}/config/priv_validator_key.json +cp ${PROV_NODE_DIR}/config/node_key.json ${CONS_NODE_DIR}/config/node_key.json + +# Set default client port +sed -i -r "/node =/ s/= .*/= \"tcp:\/\/${NODE_IP}:26648\"/" ${CONS_NODE_DIR}/config/client.toml +sed -i -r 's/block_sync = true/block_sync = false/g' ${CONS_NODE_DIR}/config/config.toml + + +# Start gaia +interchain-security-cd start --home ${CONS_NODE_DIR} \ + --rpc.laddr tcp://${NODE_IP}:26648 \ + --grpc.address ${NODE_IP}:9081 \ + --address tcp://${NODE_IP}:26645 \ + --p2p.laddr tcp://${NODE_IP}:26646 \ + --grpc-web.enable=false \ + &> ${CONS_NODE_DIR}/logs & + +waiting 20 "for consumer node to start" + +tee ${HERMES_CONFIG}< Height: ${height}, Hash: ${hash}" + +cp -r ${CONS_NODE_DIR} ${CONS_FORK_NODE_DIR} +# Set default client port +sed -i -r "/node =/ s/= .*/= \"tcp:\/\/${NODE_IP}:26638\"/" ${CONS_FORK_NODE_DIR}/config/client.toml +sed -i -r 's/block_sync = true/block_sync = false/g' ${CONS_FORK_NODE_DIR}/config/config.toml + + +# Start gaia +interchain-security-cd start --home ${CONS_FORK_NODE_DIR} \ + --rpc.laddr tcp://${NODE_IP}:26638 \ + --grpc.address ${NODE_IP}:9071 \ + --address tcp://${NODE_IP}:26635 \ + --p2p.laddr tcp://${NODE_IP}:26636 \ + --grpc-web.enable=false \ + &> ${CONS_FORK_NODE_DIR}/logs & + +waiting 5 "for forked consumer node to start" + +diag "Start Hermes relayer multi-chain mode" + +$HERMES_BIN start &> ${HOME_DIR}/hermes-start-logs.txt & + +# If we sleep 5 here and below, we end up on the forked block later +waiting 10 "for Hermes relayer to start" + +diag "Running Hermes relayer evidence command" + +# Run hermes in evidence mode +$HERMES_BIN evidence --chain consumer &> ${HOME_DIR}/hermes-evidence-logs.txt & + +# If we sleep 5 here and above, we end up on the forked block later +waiting 10 "for Hermes evidence monitor to start" + +diag "Updating client on forked chain using trusted height $TRUSTED_HEIGHT" +$HERMES_BIN_FORK update client --client 07-tendermint-0 --host-chain provider --trusted-height "$TRUSTED_HEIGHT" + +waiting 20 "for Hermes to detect and submit evidence" + +# Check the client state on provider and verify it is frozen +FROZEN_HEIGHT=$($HERMES_BIN --json query client state --chain provider --client 07-tendermint-0 | tail -n 1 | jq '.result.frozen_height.revision_height') + +diag "Frozen height: $FROZEN_HEIGHT" + +if [ "$FROZEN_HEIGHT" != "null" ]; then + diag "Client is frozen, as expected." +else + diag "Client is not frozen, aborting." + exit 1 +fi + +if grep -q "found light client attack evidence" ${HOME_DIR}/hermes-evidence-logs.txt; then + diag "Evidence found, proceeding." +else + diag "Evidence not found, aborting." + exit 1 +fi + +waiting 20 "for Hermes to submit evidence and freeze client" + +if grep -q "successfully submitted light client attack evidence" ${HOME_DIR}/hermes-evidence-logs.txt; then + diag "Evidence successfully submitted, success!" +else + if grep -q "provider is frozen" ${HOME_DIR}/hermes-evidence-logs.txt; then + diag "Client on provider is already frozen, as expected. Success!" + exit 0 + elif grep -q "client is frozen and does not have a consensus state at height" ${HOME_DIR}/hermes-evidence-logs.txt; then + diag "Client already frozen and does not have a consensus state at common height, cannot do anything." + exit 0 + else + diag "Evidence not submitted, failed." + echo "" + + diag "Hermes evidence logs:" + cat ${HOME_DIR}/hermes-evidence-logs.txt + + exit 1 + fi +fi diff --git a/ci/misbehaviour-ics/light_client_attack_test.sh b/ci/misbehaviour-ics/light_client_attack_test.sh new file mode 100644 index 0000000000..f42982c353 --- /dev/null +++ b/ci/misbehaviour-ics/light_client_attack_test.sh @@ -0,0 +1,582 @@ +#!/bin/bash +# shellcheck disable=2086 + +set -eu + +DEBUG=${DEBUG:-false} + +if [ "$DEBUG" = true ]; then + set -x +fi + +diag() { + echo ">> +>> $* +>>" 1>&2 +} + +waiting() { + secs=$1 + shift + msg="$*" + while [ $secs -gt 0 ] + do + echo -ne "|| Waiting $msg (${secs}s)\033[0K\r" + sleep 1 + : $((secs--)) + done + echo "|| Waiting $msg (done)" +} + + +# User balance of stake tokens +USER_COINS="100000000000stake" +# Amount of stake tokens staked +STAKE="100000000stake" +# Amount of stake tokens staked +STAKE2="4000000stake" +# Node IP address +NODE_IP="127.0.0.1" + +# Home directory +HOME_DIR="/tmp/hermes-ics-misbehaviour" + +# Hermes debug +if [ "$DEBUG" = true ]; then + HERMES_DEBUG="--debug=rpc" +else + HERMES_DEBUG="" +fi + +# Hermes config +HERMES_CONFIG="$HOME_DIR/hermes.toml" +HERMES_CONFIG_FORK="$HOME_DIR/hermes-fork.toml" +# Hermes binary +HERMES_BIN="cargo run -q --bin hermes -- $HERMES_DEBUG --config $HERMES_CONFIG" +HERMES_BIN_FORK="cargo run -q --bin hermes -- $HERMES_DEBUG --config $HERMES_CONFIG_FORK" + +# Validator moniker +MONIKER="coordinator" +MONIKER_SUB="sub" + +# Validator directory +PROV_NODE_DIR=${HOME_DIR}/provider-${MONIKER} +PROV_NODE_SUB_DIR=${HOME_DIR}/provider-${MONIKER_SUB} +CONS_NODE_DIR=${HOME_DIR}/consumer-${MONIKER} +CONS_NODE_SUB_DIR=${HOME_DIR}/consumer-${MONIKER_SUB} +CONS_FORK_NODE_DIR=${HOME_DIR}/consumer-fork-${MONIKER} + +# Coordinator key +PROV_KEY=${MONIKER}-key +PROV_KEY_SUB=${MONIKER_SUB}-key + + +# Clean start +pkill -f interchain-security-pd &> /dev/null || true +pkill -f interchain-security-cd &> /dev/null || true +pkill -f hermes &> /dev/null || true + +mkdir -p "${HOME_DIR}" +rm -rf "${PROV_NODE_DIR}" +rm -rf "${PROV_NODE_SUB_DIR}" +rm -rf "${CONS_NODE_DIR}" +rm -rf "${CONS_NODE_SUB_DIR}" +rm -rf "${CONS_FORK_NODE_DIR}" + +# Build genesis file and node directory structure +interchain-security-pd init $MONIKER --chain-id provider --home ${PROV_NODE_DIR} +jq ".app_state.gov.params.voting_period = \"5s\" | .app_state.staking.params.unbonding_time = \"86400s\"" \ + ${PROV_NODE_DIR}/config/genesis.json > \ + ${PROV_NODE_DIR}/edited_genesis.json && mv ${PROV_NODE_DIR}/edited_genesis.json ${PROV_NODE_DIR}/config/genesis.json + +# Create account keypair +interchain-security-pd keys add $PROV_KEY --home ${PROV_NODE_DIR} --keyring-backend test --output json > ${PROV_NODE_DIR}/${PROV_KEY}.json 2>&1 + +# Add stake to user +PROV_ACCOUNT_ADDR=$(jq -r '.address' ${PROV_NODE_DIR}/${PROV_KEY}.json) +interchain-security-pd genesis add-genesis-account "$PROV_ACCOUNT_ADDR" $USER_COINS --home ${PROV_NODE_DIR} --keyring-backend test + +# Stake 1/1000 user's coins +interchain-security-pd genesis gentx $PROV_KEY $STAKE --chain-id provider --home ${PROV_NODE_DIR} --keyring-backend test --moniker $MONIKER + +## config second node + +rm -rf ${PROV_NODE_SUB_DIR} + +# Build genesis file and node directory structure +interchain-security-pd init $MONIKER_SUB --chain-id provider --home ${PROV_NODE_SUB_DIR} + +waiting 1 "" + +# Create account keypair +interchain-security-pd keys add $PROV_KEY_SUB --home ${PROV_NODE_SUB_DIR} --keyring-backend test --output json > ${PROV_NODE_SUB_DIR}/${PROV_KEY_SUB}.json 2>&1 +waiting 1 "" + +cp ${PROV_NODE_DIR}/config/genesis.json ${PROV_NODE_SUB_DIR}/config/genesis.json + +# Add stake to user +PROV_ACCOUNT_ADDR=$(jq -r '.address' ${PROV_NODE_SUB_DIR}/${PROV_KEY_SUB}.json) +interchain-security-pd genesis add-genesis-account "$PROV_ACCOUNT_ADDR" $USER_COINS --home ${PROV_NODE_SUB_DIR} --keyring-backend test +waiting 1 "" + + + +cp -r ${PROV_NODE_DIR}/config/gentx/ ${PROV_NODE_SUB_DIR}/config/gentx/ + +# # Stake 1/1000 user's coins +interchain-security-pd genesis gentx $PROV_KEY_SUB $STAKE2 --chain-id provider --home ${PROV_NODE_SUB_DIR} --keyring-backend test --moniker $MONIKER_SUB +waiting 1 "" + + +interchain-security-pd genesis collect-gentxs --home ${PROV_NODE_SUB_DIR} --gentx-dir ${PROV_NODE_SUB_DIR}/config/gentx/ + +cp ${PROV_NODE_SUB_DIR}/config/genesis.json ${PROV_NODE_DIR}/config/genesis.json + +# Start nodes + +sed -i -r "/node =/ s/= .*/= \"tcp:\/\/${NODE_IP}:26658\"/" ${PROV_NODE_DIR}/config/client.toml +sed -i -r 's/timeout_commit = "5s"/timeout_commit = "3s"/g' ${PROV_NODE_DIR}/config/config.toml +sed -i -r 's/timeout_propose = "3s"/timeout_propose = "1s"/g' ${PROV_NODE_DIR}/config/config.toml +sed -i -r 's/block_sync = true/block_sync = false/g' ${PROV_NODE_DIR}/config/config.toml + + + +# Start gaia +interchain-security-pd start \ + --home ${PROV_NODE_DIR} \ + --rpc.laddr tcp://${NODE_IP}:26658 \ + --grpc.address ${NODE_IP}:9091 \ + --address tcp://${NODE_IP}:26655 \ + --p2p.laddr tcp://${NODE_IP}:26656 \ + --grpc-web.enable=false &> ${PROV_NODE_DIR}/logs & + +waiting 5 "for provider node to start" + +sed -i -r "/node =/ s/= .*/= \"tcp:\/\/${NODE_IP}:26628\"/" ${PROV_NODE_SUB_DIR}/config/client.toml +sed -i -r 's/timeout_commit = "5s"/timeout_commit = "3s"/g' ${PROV_NODE_SUB_DIR}/config/config.toml +sed -i -r 's/timeout_propose = "3s"/timeout_propose = "1s"/g' ${PROV_NODE_SUB_DIR}/config/config.toml +sed -i -r 's/block_sync = true/block_sync = false/g' ${PROV_NODE_SUB_DIR}/config/config.toml + +# # Start gaia +interchain-security-pd start \ + --home ${PROV_NODE_SUB_DIR} \ + --rpc.laddr tcp://${NODE_IP}:26628 \ + --grpc.address ${NODE_IP}:9021 \ + --address tcp://${NODE_IP}:26625 \ + --p2p.laddr tcp://${NODE_IP}:26626 \ + --grpc-web.enable=false &> ${PROV_NODE_SUB_DIR}/logs & + +waiting 5 "for provider sub-node to start" + +# Build consumer chain proposal file +tee ${PROV_NODE_DIR}/consumer-proposal.json< ${CONS_NODE_DIR}/${PROV_KEY}.json 2>&1 + +# Add stake to user account +CONS_ACCOUNT_ADDR=$(jq -r '.address' ${CONS_NODE_DIR}/${PROV_KEY}.json) +interchain-security-cd genesis add-genesis-account "$CONS_ACCOUNT_ADDR" 1000000000stake --home ${CONS_NODE_DIR} + +# Add consumer genesis states to genesis file +interchain-security-pd query provider consumer-genesis consumer --home ${PROV_NODE_DIR} -o json > consumer_gen.json +jq -s '.[0].app_state.ccvconsumer = .[1] | .[0]' ${CONS_NODE_DIR}/config/genesis.json consumer_gen.json > ${CONS_NODE_DIR}/edited_genesis.json \ +&& mv ${CONS_NODE_DIR}/edited_genesis.json ${CONS_NODE_DIR}/config/genesis.json +rm consumer_gen.json + +# Create validator states +echo '{"height": "0","round": 0,"step": 0}' > ${CONS_NODE_DIR}/data/priv_validator_state.json + +# Copy validator key files +cp ${PROV_NODE_DIR}/config/priv_validator_key.json ${CONS_NODE_DIR}/config/priv_validator_key.json +cp ${PROV_NODE_DIR}/config/node_key.json ${CONS_NODE_DIR}/config/node_key.json + +# Set default client port +sed -i -r "/node =/ s/= .*/= \"tcp:\/\/${NODE_IP}:26648\"/" ${CONS_NODE_DIR}/config/client.toml +sed -i -r 's/block_sync = true/block_sync = false/g' ${CONS_NODE_DIR}/config/config.toml + +# Start gaia +interchain-security-cd start --home ${CONS_NODE_DIR} \ + --rpc.laddr tcp://${NODE_IP}:26648 \ + --grpc.address ${NODE_IP}:9081 \ + --address tcp://${NODE_IP}:26645 \ + --p2p.laddr tcp://${NODE_IP}:26646 \ + --grpc-web.enable=false \ + &> ${CONS_NODE_DIR}/logs & + +waiting 20 "for consumer node to start" + +tee ${HERMES_CONFIG}< Height: ${height}, Hash: ${hash}" + +cp -r ${CONS_NODE_DIR} ${CONS_FORK_NODE_DIR} +# Set default client port +sed -i -r "/node =/ s/= .*/= \"tcp:\/\/${NODE_IP}:26638\"/" ${CONS_FORK_NODE_DIR}/config/client.toml +sed -i -r 's/fast_sync = true/fast_sync = false/g' ${CONS_FORK_NODE_DIR}/config/config.toml + + +# Start gaia +interchain-security-cd start --home ${CONS_FORK_NODE_DIR} \ + --rpc.laddr tcp://${NODE_IP}:26638 \ + --grpc.address ${NODE_IP}:9071 \ + --address tcp://${NODE_IP}:26635 \ + --p2p.laddr tcp://${NODE_IP}:26636 \ + --grpc-web.enable=false \ + &> ${CONS_FORK_NODE_DIR}/logs & + +waiting 5 "for forked consumer node to start" + +diag "Start Hermes relayer multi-chain mode" + +$HERMES_BIN start &> ${HOME_DIR}/hermes-start-logs.txt & + +# If we sleep 5 here and below, we end up on the forked block later +waiting 10 "for Hermes relayer to start" + +diag "Running Hermes relayer evidence command" + +# Run hermes in evidence mode +$HERMES_BIN evidence --chain consumer &> ${HOME_DIR}/hermes-evidence-logs.txt & + +# If we sleep 5 here and above, we end up on the forked block later +waiting 10 "for Hermes evidence monitor to start" + +read -r CD_HEIGHT < <( + curl -s "localhost:26638"/commit \ + | jq -r '(.result//.).signed_header.header.height') + +diag "Running light client between primary and fork as witness using trusted height $CD_TRUSTED_HEIGHT and hash $CD_TRUSTED_HASH at height $CD_HEIGHT" + +# Rust light client +# tendermint-light-client-cli \ +# --chain-id consumer \ +# --primary "http://$NODE_IP:26638" \ +# --witnesses "http://$NODE_IP:26648" \ +# --trusted-height $CD_TRUSTED_HEIGHT \ +# --trusted-hash $CD_TRUSTED_HASH \ +# --height $CD_HEIGHT + +# Go light client +rm -rf $HOME/.cometbft-light/ +cometbft light consumer \ + --primary "http://$NODE_IP:26638" \ + --witnesses "http://$NODE_IP:26648" \ + --height $CD_TRUSTED_HEIGHT \ + --hash $CD_TRUSTED_HASH > ${HOME_DIR}/light-client-logs.txt 2>&1 & + +echo $! > ${HOME_DIR}/light-client.pid + +waiting 5 "for light client to start" +BLOCK="$(curl -s "localhost:8888/block?height=$CD_HEIGHT" | jq)" +echo $BLOCK +waiting 1 "before killing light client" + +kill -9 "$(cat ${HOME_DIR}/light-client.pid)" + +waiting 20 "for Hermes to detect evidence" + +if grep -q "found light client attack evidence" ${HOME_DIR}/hermes-evidence-logs.txt; then + diag "Evidence found, proceeding!" +else + diag "Evidence not found, aborting." + exit 1 +fi + +waiting 20 "for Hermes to submit evidence and freeze client" + +if grep -q "successfully submitted light client attack evidence" ${HOME_DIR}/hermes-evidence-logs.txt; then + diag "Evidence successfully submitted, success!" +else + if grep -q "provider is frozen" ${HOME_DIR}/hermes-evidence-logs.txt; then + diag "Client on provider is already frozen, cannot do anything." + exit 0 + elif grep -q "client is frozen and does not have a consensus state at height" ${HOME_DIR}/hermes-evidence-logs.txt; then + diag "Client already frozen and does not have a consensus state at common height, cannot do anything." + exit 0 + else + diag "Evidence not submitted, failed." + echo "" + + diag "Hermes evidence logs:" + cat ${HOME_DIR}/hermes-evidence-logs.txt + + exit 1 + fi +fi + diff --git a/ci/misbehaviour/config.toml b/ci/misbehaviour/config.toml index 12bc01922c..92845f89ed 100644 --- a/ci/misbehaviour/config.toml +++ b/ci/misbehaviour/config.toml @@ -112,6 +112,9 @@ port = 3001 # Specify the chain ID. Required id = 'ibc-0' +# Specify the type of chain, currently only "CosmosSdk" is supported. +type = "CosmosSdk" + # Specify the RPC address and port where the chain RPC server listens on. Required rpc_addr = 'http://127.0.0.1:26657' @@ -133,7 +136,7 @@ account_prefix = 'cosmos' # Specify the name of the private key to use for signing transactions. Required # See the Adding Keys chapter for more information about managing signing keys: -# https://hermes.informal.systems/commands/keys/index.html#adding-keys +# https://hermes.informal.systems/documentation/commands/keys/index.html#adding-keys key_name = 'testkey' # Specify the address type which determines: @@ -291,7 +294,7 @@ memo_prefix = '' # [chains.packet_filter.min_fees.'channel-0'] # recv = [ { amount = 20, denom = 'stake' }, { amount = 10, denom = 'uatom' } ] -# Specify that the transaction fees should be payed from this fee granter's account. +# Specify that the transaction fees should be paid from this fee granter's account. # Optional. If unspecified (the default behavior), then no fee granter is used, and # the account specified in `key_name` will pay the tx fees for all transactions # submitted to this chain. @@ -299,6 +302,7 @@ memo_prefix = '' [[chains]] id = 'ibc-1' +type = "CosmosSdk" rpc_addr = 'http://127.0.0.1:26557' grpc_addr = 'http://127.0.0.1:9091' event_source = { mode = 'push', url = 'ws://127.0.0.1:26557/websocket', batch_delay = '500ms' } diff --git a/ci/misbehaviour/config_fork.toml b/ci/misbehaviour/config_fork.toml index d911b14798..060dda1566 100644 --- a/ci/misbehaviour/config_fork.toml +++ b/ci/misbehaviour/config_fork.toml @@ -112,6 +112,9 @@ port = 3001 # Specify the chain ID. Required id = 'ibc-0' +# Specify the chain type, currently only 'CosmosSdk' is supported. +type = 'CosmosSdk' + # Specify the RPC address and port where the chain RPC server listens on. Required rpc_addr = 'http://127.0.0.1:26657' @@ -132,7 +135,7 @@ account_prefix = 'cosmos' # Specify the name of the private key to use for signing transactions. Required # See the Adding Keys chapter for more information about managing signing keys: -# https://hermes.informal.systems/commands/keys/index.html#adding-keys +# https://hermes.informal.systems/documentation/commands/keys/index.html#adding-keys key_name = 'testkey' # Specify the address type which determines: @@ -290,7 +293,7 @@ memo_prefix = '' # [chains.packet_filter.min_fees.'channel-0'] # recv = [ { amount = 20, denom = 'stake' }, { amount = 10, denom = 'uatom' } ] -# Specify that the transaction fees should be payed from this fee granter's account. +# Specify that the transaction fees should be paid from this fee granter's account. # Optional. If unspecified (the default behavior), then no fee granter is used, and # the account specified in `key_name` will pay the tx fees for all transactions # submitted to this chain. @@ -298,6 +301,7 @@ memo_prefix = '' [[chains]] id = 'ibc-1' +type = 'CosmosSdk' rpc_addr = 'http://127.0.0.1:26457' grpc_addr = 'http://127.0.0.1:9092' event_source = { mode = 'push', url = 'ws://127.0.0.1:26457/websocket', batch_delay = '500ms' } diff --git a/ci/misbehaviour/misbehaviour_test.sh b/ci/misbehaviour/misbehaviour_test.sh index d79b8ca854..88e0f923f4 100755 --- a/ci/misbehaviour/misbehaviour_test.sh +++ b/ci/misbehaviour/misbehaviour_test.sh @@ -42,7 +42,7 @@ info "Update client on ibc-0 against the forked chain ibc-1-f" $HERMES --config config_fork.toml update client --client 07-tendermint-0 --host-chain ibc-0 info "Wait for chain ibc-1 to stop..." -sleep 5 +sleep 10 info "Killing Hermes" kill -9 "$HERMES_PID" @@ -55,11 +55,11 @@ cat "$HERMES_LOG" info "--------------------------------------------------" echo "" -if grep -q "Evidence succesfully submitted" "$HERMES_LOG"; then +if grep -q "Evidence successfully submitted" "$HERMES_LOG"; then + info "Misbehaviour detected and submitted successfully!" +else warn "Misbehaviour detection failed!" exit 1 -else - info "Misbehaviour detected and submitted successfully!" fi STOPPED_HEIGHT="$(curl -s http://localhost:$IBC_1_RPC_PORT/status | jq -r .result.sync_info.latest_block_height)" diff --git a/clippy.toml b/clippy.toml index 1645c19f32..8f7dac5dc3 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1 +1 @@ -msrv = "1.70.0" +msrv = "1.71.0" diff --git a/config.toml b/config.toml index 735ed50ab4..88801a955c 100644 --- a/config.toml +++ b/config.toml @@ -140,8 +140,11 @@ port = 5555 # Specify the chain ID. Required id = 'ibc-0' +# Specify the chain type, currently only `"CosmosSdk"` is supported. +type = "CosmosSdk" + # Whether or not this is a CCV consumer chain. Default: false -# Only specifiy true for CCV consumer chain, but NOT for sovereign chains. +# Only specify true for CCV consumer chain, but NOT for sovereign chains. ccv_consumer_chain = false # Specify the RPC address and port where the chain RPC server listens on. Required @@ -154,7 +157,7 @@ grpc_addr = 'http://127.0.0.1:9090' # # This setting can take two types of values, as an inline table: # -# a) Push: for receiving IBC events over WebSocket +# a) Push: for receiving IBC events over WebSocket. # # `{ mode = 'push', url = 'ws://127.0.0.1:26657/websocket', batch_delay = '500ms' }` # @@ -169,7 +172,7 @@ grpc_addr = 'http://127.0.0.1:9090' # processing, increasing the latency of Hermes, but are more likely to batch events together. # The default value provides good latency while minimizing the number of client updates needed. -# b) Pull: for polling for IBC events via the `/block_results` RPC endpoint +# b) Pull: for polling for IBC events via the `/block_results` RPC endpoint. # # `{ mode = 'pull', interval = '1s' }` # @@ -177,6 +180,11 @@ grpc_addr = 'http://127.0.0.1:9090' # # - `interval` is the interval at which to poll for blocks. Default: 1s # +# This mode should only be used in situations where Hermes misses events that it should be +# receiving, such as when relaying for CosmWasm-enabled chains which emit IBC events without +# the `message` attribute. Without this attribute, the WebSocket is not able to catch these +# events, so the `/block_results` RPC must be used instead. +# event_source = { mode = 'push', url = 'ws://127.0.0.1:26657/websocket', batch_delay = '500ms' } # Specify the maximum amount of time (duration) that the RPC requests should @@ -201,7 +209,7 @@ account_prefix = 'cosmos' # Specify the name of the private key to use for signing transactions. Required # See the Adding Keys chapter for more information about managing signing keys: -# https://hermes.informal.systems/commands/keys/index.html#adding-keys +# https://hermes.informal.systems/documentation/commands/keys/index.html#adding-keys key_name = 'testkey' # Specify the folder used to store the keys. Optional @@ -263,7 +271,7 @@ max_gas = 400000 # paid for each unit of gas per transaction. # # Required -gas_price = { price = 0.001, denom = 'stake' } +gas_price = { price = 0.025, denom = 'stake' } # Multiply this amount with the gas estimate, used to compute the fee # and account for potential estimation error. @@ -375,14 +383,28 @@ memo_prefix = '' # [chains.packet_filter.min_fees.'channel-0'] # recv = [ { amount = 20, denom = 'stake' }, { amount = 10, denom = 'uatom' } ] -# Specify that the transaction fees should be payed from this fee granter's account. +# Specify that the transaction fees should be paid from this fee granter's account. # Optional. If unspecified (the default behavior), then no fee granter is used, and # the account specified in `key_name` will pay the tx fees for all transactions # submitted to this chain. # fee_granter = '' +# Specify the CometBFT compatibility mode to use. +# The following behaviours are applied whether the `compat_mode` is configured or not: +# * compat_mode is specified and the version queried from /status is the same as the one configured: Use that version without log output +# * compat_mode is specified but the version queried from /status differs: The CompatMode configured is used, but a warning log is outputted +# * compat_mode is not specified but /status returns a correct version: The CompatMode retrieved from the endpoint is used +# * compat_mode is not specified and /status does not return a valid version: Hermes stops and outputs an error informing the user a compat_mode needs to be configured +# Possible values: [`0.34`, `0.37`] +# compat_mode = '0.34' + +# Specify the a clear interval for the chain. +# This will override the global clear interval for this chain only, allowing different intervals for each chain. +# clear_interval = 50 + [[chains]] id = 'ibc-1' +type = "CosmosSdk" rpc_addr = 'http://127.0.0.1:26557' grpc_addr = 'http://127.0.0.1:9091' event_source = { mode = 'push', url = 'ws://127.0.0.1:26557/websocket', batch_delay = '500ms' } @@ -393,7 +415,7 @@ key_name = 'testkey' store_prefix = 'ibc' default_gas = 100000 max_gas = 400000 -gas_price = { price = 0.001, denom = 'stake' } +gas_price = { price = 0.025, denom = 'stake' } gas_multiplier = 1.1 max_msg_num = 30 max_tx_size = 2097152 diff --git a/crates/chain-registry/Cargo.toml b/crates/chain-registry/Cargo.toml index 78d394b9d0..a73433059a 100644 --- a/crates/chain-registry/Cargo.toml +++ b/crates/chain-registry/Cargo.toml @@ -1,23 +1,20 @@ [package] name = "ibc-chain-registry" -version = "0.25.0" +version = "0.26.4" edition = "2021" license = "Apache-2.0" keywords = ["cosmos", "ibc", "relayer", "chain", "registry"] repository = "https://github.com/informalsystems/hermes" authors = ["Informal Systems "] -rust-version = "1.70" +rust-version = "1.71" description = """ Service to fetch data from the chain-registry """ [dependencies] -ibc-proto = { version = "0.37.0", features = ["serde"] } -ibc-relayer-types = { version = "0.25.0", path = "../relayer-types" } -tendermint-rpc = { version = "0.34.0", features = [ - "http-client", - "websocket-client", -] } +ibc-relayer-types = { version = "0.26.4", path = "../relayer-types" } +ibc-proto = { version = "0.39.0", features = ["serde"] } +tendermint-rpc = { version = "0.34.0", features = ["http-client", "websocket-client"] } async-trait = "0.1.72" flex-error = { version = "0.4.4", default-features = false } diff --git a/crates/chain-registry/src/chain.rs b/crates/chain-registry/src/chain.rs index f136d28fb0..48434c404d 100644 --- a/crates/chain-registry/src/chain.rs +++ b/crates/chain-registry/src/chain.rs @@ -152,8 +152,8 @@ pub struct Grpc { } impl Fetchable for ChainData { - fn path(ressource: &str) -> PathBuf { - [ressource, "chain.json"].iter().collect() + fn path(resource: &str) -> PathBuf { + [resource, "chain.json"].iter().collect() } } diff --git a/crates/chain-registry/src/querier.rs b/crates/chain-registry/src/querier.rs index a2f7de7685..ac5a2c385c 100644 --- a/crates/chain-registry/src/querier.rs +++ b/crates/chain-registry/src/querier.rs @@ -31,7 +31,7 @@ pub trait QueryTypes { #[async_trait] /// `QueryContext` represents the basic expectations for a query pub trait QueryContext: QueryTypes { - /// Return an error specific to the query which is retured when `query_healthy` fails + /// Return an error specific to the query which is returned when `query_healthy` fails /// /// # Arguments /// diff --git a/crates/relayer-cli/Cargo.toml b/crates/relayer-cli/Cargo.toml index d672b3855d..2421234698 100644 --- a/crates/relayer-cli/Cargo.toml +++ b/crates/relayer-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ibc-relayer-cli" -version = "1.6.0" +version = "1.7.4" edition = "2021" license = "Apache-2.0" readme = "README.md" @@ -8,7 +8,7 @@ keywords = ["blockchain", "consensus", "cosmos", "ibc", "tendermint"] homepage = "https://hermes.informal.systems/" repository = "https://github.com/informalsystems/hermes" authors = ["Informal Systems "] -rust-version = "1.70" +rust-version = "1.71" description = """ Hermes is an IBC Relayer written in Rust """ @@ -25,11 +25,11 @@ telemetry = ["ibc-relayer/telemetry", "ibc-telemetry"] rest-server = ["ibc-relayer-rest"] [dependencies] -ibc-relayer-types = { version = "0.25.0", path = "../relayer-types" } -ibc-relayer = { version = "0.25.0", path = "../relayer" } -ibc-telemetry = { version = "0.25.0", path = "../telemetry", optional = true } -ibc-relayer-rest = { version = "0.25.0", path = "../relayer-rest", optional = true } -ibc-chain-registry = { version = "0.25.0" , path = "../chain-registry" } +ibc-relayer-types = { version = "0.26.4", path = "../relayer-types" } +ibc-relayer = { version = "0.26.4", path = "../relayer" } +ibc-telemetry = { version = "0.26.4", path = "../telemetry", optional = true } +ibc-relayer-rest = { version = "0.26.4", path = "../relayer-rest", optional = true } +ibc-chain-registry = { version = "0.26.4" , path = "../chain-registry" } clap = { version = "3.2", features = ["cargo"] } clap_complete = "3.2" diff --git a/crates/relayer-cli/src/application.rs b/crates/relayer-cli/src/application.rs index 1dadc513e7..e7d524bf96 100644 --- a/crates/relayer-cli/src/application.rs +++ b/crates/relayer-cli/src/application.rs @@ -18,7 +18,6 @@ use ibc_relayer::{ use crate::{ commands::CliCmd, components::{JsonTracing, PrettyTracing}, - config::validate_config, entry::EntryPoint, tracing_handle::{spawn_reload_handler, ReloadHandle}, }; @@ -134,13 +133,13 @@ impl Application for CliApp { /// time in app lifecycle when configuration would be loaded if /// possible. fn after_config(&mut self, config: Self::Cfg) -> Result<(), FrameworkError> { - use crate::config::Diagnostic; + use ibc_relayer::config::Diagnostic; // Configure components let mut components = self.state.components_mut(); components.after_config(&config)?; - if let Err(diagnostic) = validate_config(&config) { + if let Err(diagnostic) = config.validate_config() { match diagnostic { Diagnostic::Warning(e) => { tracing::warn!("relayer may be misconfigured: {}", e); diff --git a/crates/relayer-cli/src/chain_registry.rs b/crates/relayer-cli/src/chain_registry.rs index 801ca5bad0..f7952c6981 100644 --- a/crates/relayer-cli/src/chain_registry.rs +++ b/crates/relayer-cli/src/chain_registry.rs @@ -16,6 +16,7 @@ use ibc_chain_registry::fetchable::Fetchable; use ibc_chain_registry::formatter::{SimpleGrpcFormatter, UriFormatter}; use ibc_chain_registry::paths::IBCPath; use ibc_chain_registry::querier::*; +use ibc_relayer::chain::cosmos::config::CosmosSdkConfig; use ibc_relayer::config::filter::{FilterPattern, PacketFilter}; use ibc_relayer::config::gas_multiplier::GasMultiplier; use ibc_relayer::config::types::{MaxMsgNum, MaxTxSize, Memo}; @@ -120,9 +121,8 @@ where 0.1 }; - Ok(ChainConfig { + Ok(ChainConfig::CosmosSdk(CosmosSdkConfig { id: chain_data.chain_id, - r#type: default::chain_type(), rpc_addr: rpc_data.rpc_address, grpc_addr: grpc_address, event_source: EventSourceMode::Push { @@ -161,7 +161,9 @@ where address_type: AddressType::default(), sequential_batch_tx: false, extension_options: Vec::new(), - }) + compat_mode: None, + clear_interval: None, + })) } /// Concurrent `query_healthy` might fail, this is a helper function which will retry a failed query a fixed @@ -342,7 +344,10 @@ mod tests { for config in configs { match config { Ok(config) => { - assert_eq!(config.packet_filter.channel_policy, ChannelPolicy::AllowAll); + assert_eq!( + config.packet_filter().channel_policy, + ChannelPolicy::AllowAll + ); } Err(e) => panic!( "Encountered an unexpected error in chain registry test: {}", @@ -368,9 +373,9 @@ mod tests { for config in configs { match config { - Ok(config) => match config.packet_filter.channel_policy { + Ok(config) => match &config.packet_filter().channel_policy { ChannelPolicy::Allow(channel_filter) => { - if config.id.as_str().contains("cosmoshub") { + if config.id().as_str().contains("cosmoshub") { assert!(channel_filter.is_exact()); let cosmoshub_juno = ( @@ -386,7 +391,7 @@ mod tests { assert!(channel_filter.matches(cosmoshub_juno)); assert!(channel_filter.matches(cosmoshub_osmosis)); assert!(channel_filter.len() == 2); - } else if config.id.as_str().contains("juno") { + } else if config.id().as_str().contains("juno") { assert!(channel_filter.is_exact()); let juno_cosmoshub = ( @@ -408,7 +413,7 @@ mod tests { assert!(channel_filter.matches(juno_osmosis_1)); assert!(channel_filter.matches(juno_osmosis_2)); assert!(channel_filter.len() == 3); - } else if config.id.as_str().contains("osmosis") { + } else if config.id().as_str().contains("osmosis") { assert!(channel_filter.is_exact()); let osmosis_cosmoshub = ( diff --git a/crates/relayer-cli/src/cli_utils.rs b/crates/relayer-cli/src/cli_utils.rs index 5a2aae7fc0..733914fd06 100644 --- a/crates/relayer-cli/src/cli_utils.rs +++ b/crates/relayer-cli/src/cli_utils.rs @@ -5,18 +5,13 @@ use eyre::eyre; use tokio::runtime::Runtime as TokioRuntime; use tracing::debug; +use ibc_relayer::chain::counterparty::{channel_connection_client, ChannelConnectionClient}; +use ibc_relayer::chain::handle::{BaseChainHandle, ChainHandle}; use ibc_relayer::chain::requests::{ IncludeProof, QueryChannelRequest, QueryClientStateRequest, QueryConnectionRequest, QueryHeight, }; -use ibc_relayer::{ - chain::{ - counterparty::{channel_connection_client, ChannelConnectionClient}, - handle::{BaseChainHandle, ChainHandle}, - }, - config::Config, - spawn, -}; -use ibc_relayer_types::core::ics02_client::client_state::ClientState; +use ibc_relayer::config::Config; +use ibc_relayer::spawn; use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; use crate::error::Error; @@ -64,7 +59,7 @@ pub fn spawn_chain_runtime(config: &Config, chain_id: &ChainId) -> Result(config, chain_id) } -/// Spawns a chain runtime for the chain in the configuraiton identified by the given chain identifier. +/// Spawns a chain runtime for the chain in the configuration identified by the given chain identifier. /// /// The `Handle` type parameter allows choosing which kind of [`ChainHandle`] implementation to use. /// diff --git a/crates/relayer-cli/src/commands.rs b/crates/relayer-cli/src/commands.rs index 51e7022bd6..60879018f5 100644 --- a/crates/relayer-cli/src/commands.rs +++ b/crates/relayer-cli/src/commands.rs @@ -4,6 +4,7 @@ mod clear; mod completions; mod config; mod create; +mod evidence; mod fee; mod health; mod keys; @@ -19,9 +20,9 @@ mod version; use self::{ clear::ClearCmds, completions::CompletionsCmd, config::ConfigCmd, create::CreateCmds, - fee::FeeCmd, health::HealthCheckCmd, keys::KeysCmd, listen::ListenCmd, logs::LogsCmd, - misbehaviour::MisbehaviourCmd, query::QueryCmd, start::StartCmd, tx::TxCmd, update::UpdateCmds, - upgrade::UpgradeCmds, version::VersionCmd, + evidence::EvidenceCmd, fee::FeeCmd, health::HealthCheckCmd, keys::KeysCmd, listen::ListenCmd, + logs::LogsCmd, misbehaviour::MisbehaviourCmd, query::QueryCmd, start::StartCmd, tx::TxCmd, + update::UpdateCmds, upgrade::UpgradeCmds, version::VersionCmd, }; use core::time::Duration; @@ -32,7 +33,7 @@ use abscissa_core::{config::Override, Command, Configurable, FrameworkError, Run use tracing::{error, info}; use crate::DEFAULT_CONFIG_PATH; -use ibc_relayer::config::Config; +use ibc_relayer::config::{ChainConfig, Config}; /// Default configuration file path pub fn default_config_file() -> Option { @@ -86,12 +87,15 @@ pub enum CliCmd { /// Listen to and display IBC events emitted by a chain Listen(ListenCmd), + /// Listen to client update IBC events and handle misbehaviour + Misbehaviour(MisbehaviourCmd), + /// Update tracing log directives #[clap(subcommand)] Logs(LogsCmd), - /// Listen to client update IBC events and handles misbehaviour - Misbehaviour(MisbehaviourCmd), + /// Listen to block events and handles evidence + Evidence(EvidenceCmd), /// The `version` subcommand, retained for backward compatibility. Version(VersionCmd), @@ -145,14 +149,20 @@ impl Configurable for CliCmd { let web = "https://hermes.informal.systems"; let suffix = format!("{} {} ({})", CliCmd::name(), clap::crate_version!(), web); for ccfg in config.chains.iter_mut() { - ccfg.memo_prefix.apply_suffix(&suffix); + #[allow(irrefutable_let_patterns)] + if let ChainConfig::CosmosSdk(ref mut cosmos_ccfg) = ccfg { + cosmos_ccfg.memo_prefix.apply_suffix(&suffix); + } } // For all commands except for `start` Hermes retries // for a prolonged period of time. if !matches!(self, CliCmd::Start(_)) { for c in config.chains.iter_mut() { - c.rpc_timeout = Duration::from_secs(120); + #[allow(irrefutable_let_patterns)] + if let ChainConfig::CosmosSdk(ref mut cosmos_ccfg) = c { + cosmos_ccfg.rpc_timeout = Duration::from_secs(120); + } } } diff --git a/crates/relayer-cli/src/commands/clear.rs b/crates/relayer-cli/src/commands/clear.rs index 42149e3e65..d06bd853f6 100644 --- a/crates/relayer-cli/src/commands/clear.rs +++ b/crates/relayer-cli/src/commands/clear.rs @@ -75,7 +75,12 @@ impl Override for ClearPacketsCmd { })?; if let Some(ref key_name) = self.key_name { - chain_config.key_name = key_name.to_string(); + // Q: should the key name be required across chain types, meaning that + // key management is common to all chain types, or should key management + // be the responsibility of the backend? If key management is common + // across backends, how should it be agnostic to the key type? Can it + // just be an opaque byte string handled by the backend? + chain_config.set_key_name(key_name.to_string()); } Ok(config) @@ -101,7 +106,7 @@ impl Runnable for ClearPacketsCmd { if let Some(ref counterparty_key_name) = self.counterparty_key_name { match chains.dst.config() { Ok(mut dst_chain_cfg) => { - dst_chain_cfg.key_name = counterparty_key_name.to_string(); + dst_chain_cfg.set_key_name(counterparty_key_name.to_string()); } Err(e) => Output::error(e).exit(), } diff --git a/crates/relayer-cli/src/commands/config/auto.rs b/crates/relayer-cli/src/commands/config/auto.rs index 6736f0dd76..66fbd0969c 100644 --- a/crates/relayer-cli/src/commands/config/auto.rs +++ b/crates/relayer-cli/src/commands/config/auto.rs @@ -5,14 +5,13 @@ use abscissa_core::{Command, Runnable}; use crate::conclude::Output; use ibc_relayer::config::{store, ChainConfig, Config}; -use ibc_relayer::keyring::list_keys; use std::collections::HashSet; use std::path::PathBuf; use tracing::{info, warn}; fn find_key(chain_config: &ChainConfig) -> Option { - let keys = list_keys(chain_config).ok()?; + let keys = chain_config.list_keys().ok()?; keys.into_iter().next().map(|(name, _)| name) } @@ -117,7 +116,7 @@ impl Runnable for AutoCmd { .collect(); // Determine which chains were not fetched - let fetched_chains_set = HashSet::from_iter(chain_configs.iter().map(|c| c.id.name())); + let fetched_chains_set = HashSet::from_iter(chain_configs.iter().map(|c| c.id().name())); let missing_chains_set: HashSet<_> = sorted_names_set.difference(&fetched_chains_set).collect(); @@ -128,15 +127,15 @@ impl Runnable for AutoCmd { for (chain_config, key_option) in configs_and_keys { // If a key is provided, use it if let Some(key_name) = key_option { - info!("{}: uses key \"{}\"", &chain_config.id, &key_name); - chain_config.key_name = key_name; + info!("{}: uses key \"{}\"", &chain_config.id(), &key_name); + chain_config.set_key_name(key_name); } else { // Otherwise, find the key in the keystore - let chain_id = &chain_config.id; + let chain_id = &chain_config.id(); let key = find_key(chain_config); - if let Some(key) = key { - info!("{}: uses key '{}'", &chain_id, &key); - chain_config.key_name = key; + if let Some(key_name) = key { + info!("{}: uses key '{}'", &chain_id, &key_name); + chain_config.set_key_name(key_name); } else { // If no key is found, warn the user and continue warn!("No key found for chain: {}", chain_id); diff --git a/crates/relayer-cli/src/commands/config/validate.rs b/crates/relayer-cli/src/commands/config/validate.rs index 42f015a4f9..4414bba2ab 100644 --- a/crates/relayer-cli/src/commands/config/validate.rs +++ b/crates/relayer-cli/src/commands/config/validate.rs @@ -40,7 +40,7 @@ impl Runnable for ValidateCmd { // No need to output the underlying error, this is done already when the application boots. // See `application::CliApp::after_config`. - match config::validate_config(&config) { + match config.validate_config() { Ok(_) => Output::success("configuration is valid").exit(), Err(_) => Output::error("configuration is invalid").exit(), } diff --git a/crates/relayer-cli/src/commands/create/channel.rs b/crates/relayer-cli/src/commands/create/channel.rs index 3de03a257a..98b8464ff3 100644 --- a/crates/relayer-cli/src/commands/create/channel.rs +++ b/crates/relayer-cli/src/commands/create/channel.rs @@ -11,7 +11,6 @@ use ibc_relayer::chain::requests::{ use ibc_relayer::channel::Channel; use ibc_relayer::connection::Connection; use ibc_relayer::foreign_client::ForeignClient; -use ibc_relayer_types::core::ics02_client::client_state::ClientState; use ibc_relayer_types::core::ics03_connection::connection::IdentifiedConnectionEnd; use ibc_relayer_types::core::ics04_channel::channel::Ordering; use ibc_relayer_types::core::ics04_channel::version::Version; @@ -23,7 +22,7 @@ use crate::prelude::*; use ibc_relayer::config::default::connection_delay; static PROMPT: &str = "Are you sure you want a new connection & clients to be created? Hermes will use default security parameters."; -static HINT: &str = "Consider using the default invocation\n\nhermes create channel --a-port --b-port --a-chain --a-connection \n\nto re-use a pre-existing connection."; +static HINT: &str = "Consider using the default invocation\n\nhermes create channel --a-port --b-port --a-chain --a-connection \n\nto reuse a pre-existing connection."; /// The data structure that represents all the possible options when invoking /// the `create channel` CLI command. @@ -32,7 +31,7 @@ static HINT: &str = "Consider using the default invocation\n\nhermes create chan /// /// `create channel --a-port --b-port --a-chain --a-connection ` /// is the default way in which this command should be used, specifying a `Connection-ID` -/// associated with chain A for this new channel to re-use. +/// associated with chain A for this new channel to reuse. /// /// `create channel --a-port --b-port --a-chain --b-chain --new-client-connection` /// can alternatively be used to indicate that a new connection/client pair is being diff --git a/crates/relayer-cli/src/commands/create/connection.rs b/crates/relayer-cli/src/commands/create/connection.rs index 16c0fa1e6e..052411d069 100644 --- a/crates/relayer-cli/src/commands/create/connection.rs +++ b/crates/relayer-cli/src/commands/create/connection.rs @@ -7,7 +7,6 @@ use ibc_relayer::chain::handle::ChainHandle; use ibc_relayer::chain::requests::{IncludeProof, QueryClientStateRequest, QueryHeight}; use ibc_relayer::connection::Connection; use ibc_relayer::foreign_client::ForeignClient; -use ibc_relayer_types::core::ics02_client::client_state::ClientState; use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ClientId}; use crate::cli_utils::{spawn_chain_runtime, ChainHandlePair}; diff --git a/crates/relayer-cli/src/commands/evidence.rs b/crates/relayer-cli/src/commands/evidence.rs new file mode 100644 index 0000000000..eb3bc9afe8 --- /dev/null +++ b/crates/relayer-cli/src/commands/evidence.rs @@ -0,0 +1,853 @@ +use std::collections::HashMap; +use std::ops::{ControlFlow, Deref}; +use std::sync::Arc; +use std::thread::sleep; +use std::time::Duration; + +use abscissa_core::clap::Parser; +use abscissa_core::{Command, Runnable}; +use ibc_relayer::config::{ChainConfig, Config}; +use tokio::runtime::Runtime as TokioRuntime; + +use tendermint::block::Height as TendermintHeight; +use tendermint::evidence::{DuplicateVoteEvidence, LightClientAttackEvidence}; +use tendermint::validator; +use tendermint_rpc::{Client, Paging}; + +use ibc_relayer::chain::cosmos::CosmosSdkChain; +use ibc_relayer::chain::endpoint::ChainEndpoint; +use ibc_relayer::chain::handle::{BaseChainHandle, ChainHandle}; +use ibc_relayer::chain::requests::{IncludeProof, PageRequest, QueryHeight}; +use ibc_relayer::chain::tracking::TrackedMsgs; +use ibc_relayer::foreign_client::ForeignClient; +use ibc_relayer::spawn::spawn_chain_runtime_with_modified_config; +use ibc_relayer_types::applications::ics28_ccv::msgs::ccv_double_voting::MsgSubmitIcsConsumerDoubleVoting; +use ibc_relayer_types::applications::ics28_ccv::msgs::ccv_misbehaviour::MsgSubmitIcsConsumerMisbehaviour; +use ibc_relayer_types::clients::ics07_tendermint::header::Header as TendermintHeader; +use ibc_relayer_types::clients::ics07_tendermint::misbehaviour::Misbehaviour as TendermintMisbehaviour; +use ibc_relayer_types::core::ics02_client::height::Height; +use ibc_relayer_types::core::ics02_client::msgs::misbehaviour::MsgSubmitMisbehaviour; +use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ClientId}; +use ibc_relayer_types::events::IbcEvent; +use ibc_relayer_types::tx_msg::Msg; + +use crate::conclude::Output; +use crate::prelude::*; + +#[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] +pub struct EvidenceCmd { + #[clap( + long = "chain", + required = true, + value_name = "CHAIN_ID", + help_heading = "REQUIRED", + help = "Identifier of the chain where blocks are monitored for misbehaviour" + )] + chain_id: ChainId, + + #[clap( + long = "check-past-blocks", + value_name = "NUM_BLOCKS", + help = "Check the last NUM_BLOCKS blocks for misbehaviour (default: 100)", + default_value = "100" + )] + check_past_blocks: u64, + + #[clap( + long = "key-name", + value_name = "KEY_NAME", + help = "Use the given signing key name for sending the misbehaviour evidence detected (default: `key_name` config)" + )] + key_name: Option, +} + +impl Runnable for EvidenceCmd { + fn run(&self) { + let config = app_config(); + + let mut chain_config = config + .find_chain(&self.chain_id) + .cloned() + .unwrap_or_else(|| { + Output::error(format!( + "chain `{}` not found in configuration", + self.chain_id + )) + .exit() + }); + + if !matches!(chain_config, ChainConfig::CosmosSdk(_)) { + Output::error(format!( + "chain `{}` is not a Cosmos SDK chain", + self.chain_id + )) + .exit(); + } + + if let Some(ref key_name) = self.key_name { + chain_config.set_key_name(key_name.to_string()); + } + + let rt = Arc::new( + tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .unwrap(), + ); + + let chain = CosmosSdkChain::bootstrap(chain_config, rt.clone()).unwrap(); + let res = monitor_misbehaviours( + rt, + &config, + chain, + self.key_name.as_ref(), + self.check_past_blocks, + ); + + match res { + Ok(()) => Output::success(()).exit(), + Err(e) => Output::error(e).exit(), + } + } +} + +fn monitor_misbehaviours( + rt: Arc, + config: &Config, + mut chain: CosmosSdkChain, + key_name: Option<&String>, + check_past_blocks: u64, +) -> eyre::Result<()> { + let subscription = chain.subscribe()?; + + // Check previous blocks for equivocation that may have been missed + let tm_latest_height = rt + .block_on(chain.rpc_client.status())? + .sync_info + .latest_block_height; + + let latest_height = Height::new(chain.id().version(), tm_latest_height.value()).unwrap(); + let target_height = { + let target = tm_latest_height.value().saturating_sub(check_past_blocks); + let height = std::cmp::max(1, target); + Height::new(chain.id().version(), height).unwrap() + }; + + info!( + "checking past {check_past_blocks} blocks for misbehaviour evidence: {}..{}", + latest_height, target_height + ); + + let mut height = latest_height; + + while height >= target_height { + debug!("checking for evidence at height {height}"); + + if let Err(e) = check_misbehaviour_at(rt.clone(), config, &chain, key_name, height) { + warn!("error while checking for misbehaviour at height {height}: {e}"); + } + + if height.revision_height() == 1 { + break; + } + + height = height.decrement().unwrap(); + + sleep(Duration::from_millis(100)); + } + + info!("waiting for new blocks..."); + + // process new block events + while let Ok(event_batch) = subscription.recv() { + match event_batch.deref() { + Ok(event_batch) => { + for event_with_height in &event_batch.events { + if let IbcEvent::NewBlock(new_block) = &event_with_height.event { + info!("checking for evidence at height {}", new_block.height); + + if let Err(e) = check_misbehaviour_at( + rt.clone(), + config, + &chain, + key_name, + new_block.height, + ) { + error!( + "error while checking for misbehaviour at height {}: {e}", + new_block.height + ); + } + } + } + } + Err(e) => { + error!("error while receiving event batch: {e}"); + } + } + } + + Ok(()) +} + +/// Check for misbehaviour evidence in the block at the given height. +/// If such evidence is found, handle it by submitting it to all counterparty +/// clients of the chain, freezing them. +fn check_misbehaviour_at( + rt: Arc, + config: &Config, + chain: &CosmosSdkChain, + key_name: Option<&String>, + height: Height, +) -> eyre::Result<()> { + let block = rt + .block_on(chain.rpc_client.block(TendermintHeight::from(height)))? + .block; + + for evidence in block.evidence.into_vec() { + match evidence { + tendermint::evidence::Evidence::DuplicateVote(dv) => { + warn!("found duplicate vote evidence"); + trace!("{dv:#?}"); + + handle_duplicate_vote(rt.clone(), config, chain, key_name, *dv)?; + } + tendermint::evidence::Evidence::LightClientAttack(lc) => { + warn!("found light client attack evidence"); + trace!("{lc:#?}"); + + handle_light_client_attack(rt.clone(), config, chain, key_name, *lc)?; + } + } + } + + Ok(()) +} + +fn spawn_runtime( + rt: Arc, + config: &Config, + cache: &mut HashMap, + chain_id: &ChainId, + key_name: Option<&String>, +) -> eyre::Result { + if !cache.contains_key(chain_id) { + let chain_handle = spawn_chain_runtime_with_modified_config::( + config, + chain_id, + rt, + |chain_config| { + if let Some(key_name) = key_name { + chain_config.set_key_name(key_name.to_string()); + } + }, + )?; + + cache.insert(chain_id.clone(), chain_handle); + } + + Ok(cache + .get(chain_id) + .expect("chain handle was either already there or we just inserted it") + .clone()) +} + +fn handle_duplicate_vote( + rt: Arc, + config: &Config, + chain: &CosmosSdkChain, + key_name: Option<&String>, + evidence: DuplicateVoteEvidence, +) -> eyre::Result<()> { + // Fetch all the counterparty clients of this chain. + let counterparty_clients = fetch_all_counterparty_clients(config, chain)?; + + // Cache for the chain handles + let mut chains = HashMap::new(); + + // For each counterparty client, build the double voting evidence and submit it to the chain, + // freezing that client. + for (counterparty_chain_id, counterparty_client_id) in counterparty_clients { + let counterparty_chain_handle = match spawn_runtime( + rt.clone(), + config, + &mut chains, + &counterparty_chain_id, + key_name, + ) { + Ok(chain_handle) => chain_handle, + Err(e) => { + error!("failed to spawn runtime for chain `{counterparty_chain_id}`: {e}"); + continue; + } + }; + + let next = submit_duplicate_vote_evidence( + &rt, + chain, + &counterparty_chain_handle, + &counterparty_chain_id, + &counterparty_client_id, + &evidence, + ); + + match next { + Ok(ControlFlow::Continue(())) => continue, + Ok(ControlFlow::Break(())) => break, + Err(e) => { + error!( + "failed to report double voting evidence to chain `{counterparty_chain_id}`: {e}" + ); + + continue; + } + } + } + + Ok(()) +} + +fn submit_duplicate_vote_evidence( + rt: &TokioRuntime, + chain: &CosmosSdkChain, + counterparty_chain_handle: &BaseChainHandle, + counterparty_chain_id: &ChainId, + counterparty_client_id: &ClientId, + evidence: &DuplicateVoteEvidence, +) -> eyre::Result> { + use ibc_relayer::chain::requests::QueryConsensusStateHeightsRequest; + + let signer = counterparty_chain_handle.get_signer()?; + + if !is_counterparty_provider(chain, counterparty_chain_handle, counterparty_client_id) { + debug!("counterparty client `{counterparty_client_id}` on chain `{counterparty_chain_id}` is not a CCV client, skipping..."); + return Ok(ControlFlow::Continue(())); + } + + let infraction_height = evidence.vote_a.height; + + // Get the trusted height in the same way we do for client updates, + // ie. retrieve the consensus state at the highest height smaller than the infraction height. + // + // Note: The consensus state heights are sorted in increasing order. + let consensus_state_heights = + chain.query_consensus_state_heights(QueryConsensusStateHeightsRequest { + client_id: counterparty_client_id.clone(), + pagination: Some(PageRequest::all()), + })?; + + // Retrieve the consensus state at the highest height smaller than the infraction height. + let consensus_state_height_before_infraction_height = consensus_state_heights + .into_iter() + .filter(|height| height.revision_height() < infraction_height.value()) + .last(); + + let Some(trusted_height) = consensus_state_height_before_infraction_height else { + error!( + "cannot build infraction block header for client `{counterparty_client_id}` on chain `{counterparty_chain_id}`,\ + reason: could not find consensus state at highest height smaller than infraction height {infraction_height}" + ); + + return Ok(ControlFlow::Continue(())); + }; + + // Construct the light client block header for the consumer chain at the infraction height + let infraction_block_header = + fetch_infraction_block_header(rt, chain, infraction_height, trusted_height)?; + + let submit_msg = MsgSubmitIcsConsumerDoubleVoting { + submitter: signer.clone(), + duplicate_vote_evidence: evidence.clone(), + infraction_block_header, + } + .to_any(); + + info!("submitting consumer double voting evidence to provider chain `{counterparty_chain_id}`"); + + let tracked_msgs = TrackedMsgs::new_static(vec![submit_msg], "double_voting_evidence"); + let responses = counterparty_chain_handle.send_messages_and_wait_check_tx(tracked_msgs)?; + + for response in responses { + if response.code.is_ok() { + info!("successfully submitted double voting evidence to chain `{counterparty_chain_id}`, tx hash: {}", response.hash); + } else { + error!( + "failed to submit double voting evidence to chain `{counterparty_chain_id}`: {response:?}" + ); + } + } + + // We have submitted the evidence to the provider, and because there can only be a single + // provider for a consumer chain, we can stop now. No need to check all the other + // counteparties. + Ok(ControlFlow::Break(())) +} + +fn fetch_infraction_block_header( + rt: &TokioRuntime, + chain: &CosmosSdkChain, + infraction_height: TendermintHeight, + trusted_height: Height, +) -> Result { + let signed_header = rt + .block_on(chain.rpc_client.commit(infraction_height))? + .signed_header; + + let validators = rt + .block_on(chain.rpc_client.validators(infraction_height, Paging::All))? + .validators; + + let validator_set = + validator::Set::with_proposer(validators, signed_header.header.proposer_address)?; + + let trusted_header = rt + .block_on(chain.rpc_client.commit(trusted_height))? + .signed_header; + + let trusted_validators = rt + .block_on(chain.rpc_client.validators(trusted_height, Paging::All))? + .validators; + + let trusted_validator_set = + validator::Set::with_proposer(trusted_validators, trusted_header.header.proposer_address)?; + + Ok(TendermintHeader { + signed_header, + validator_set, + trusted_height, + trusted_validator_set, + }) +} + +fn handle_light_client_attack( + rt: Arc, + config: &Config, + chain: &CosmosSdkChain, + key_name: Option<&String>, + evidence: LightClientAttackEvidence, +) -> eyre::Result<()> { + // Build the two headers to submit as part of the `MsgSubmitMisbehaviour` message. + let (header1, header2) = build_evidence_headers(rt.clone(), chain, evidence.clone())?; + + // Fetch all the counterparty clients of this chain. + let counterparty_clients = fetch_all_counterparty_clients(config, chain)?; + + // Cache for the chain handles + let mut chains = HashMap::new(); + + let chain_handle = spawn_runtime(rt.clone(), config, &mut chains, chain.id(), key_name) + .map_err(|e| { + eyre::eyre!( + "failed to spawn chain runtime for chain `{chain_id}`: {e}", + chain_id = chain.id() + ) + })?; + + // For each counterparty client, build the misbehaviour evidence and submit it to the chain, + // freezing that client. + for (counterparty_chain_id, counterparty_client_id) in counterparty_clients { + let counterparty_chain_handle = match spawn_runtime( + rt.clone(), + config, + &mut chains, + &counterparty_chain_id, + key_name, + ) { + Ok(chain_handle) => chain_handle, + Err(e) => { + error!( + "failed to spawn chain runtime for chain `{counterparty_chain_id}`: {e}", + counterparty_chain_id = counterparty_chain_id + ); + + continue; + } + }; + + let misbehaviour = TendermintMisbehaviour { + client_id: counterparty_client_id.clone(), + header1: header1.clone(), + header2: header2.clone(), + }; + + let counterparty_client = ForeignClient::restore( + counterparty_client_id.clone(), + counterparty_chain_handle.clone(), + chain_handle.clone(), + ); + + let result = submit_light_client_attack_evidence( + &evidence, + chain, + counterparty_client, + counterparty_client_id, + &counterparty_chain_handle, + misbehaviour, + ); + + if let Err(error) = result { + error!("{error}"); + } + } + + Ok(()) +} + +fn submit_light_client_attack_evidence( + evidence: &LightClientAttackEvidence, + chain: &CosmosSdkChain, + counterparty_client: ForeignClient, + counterparty_client_id: ClientId, + counterparty: &BaseChainHandle, + misbehaviour: TendermintMisbehaviour, +) -> Result<(), eyre::Error> { + info!( + "building light client attack evidence for client `{}` on counterparty chain `{}`", + counterparty_client_id, + counterparty.id(), + ); + + let counterparty_is_provider = + is_counterparty_provider(chain, counterparty, &counterparty_client_id); + + let counterparty_client_is_frozen = counterparty_client.is_frozen(); + + if !counterparty_is_provider && counterparty_client_is_frozen { + warn!( + "cannot submit light client attack evidence to client `{}` on counterparty chain `{}`", + counterparty_client_id, + counterparty.id() + ); + warn!("reason: client is frozen and chain is not a CCV provider chain"); + + return Ok(()); + } + + let signer = counterparty.get_signer()?; + let common_height = Height::from_tm(evidence.common_height, chain.id()); + + let counterparty_has_common_consensus_state = + has_consensus_state(counterparty, &counterparty_client_id, common_height); + + if counterparty_is_provider + && counterparty_client_is_frozen + && !counterparty_has_common_consensus_state + { + warn!( + "cannot submit light client attack evidence to client `{}` on provider chain `{}`", + counterparty_client_id, + counterparty.id() + ); + warn!("reason: client is frozen and does not have a consensus state at height {common_height}"); + + return Ok(()); + } + + let mut msgs = if counterparty_has_common_consensus_state { + info!( + "skip building update client message for client `{}` on counterparty chain `{}`", + counterparty_client_id, + counterparty.id() + ); + info!( + "reason: counterparty chain already has consensus state at common height {common_height}" + ); + + Vec::new() + } else { + match counterparty_client.wait_and_build_update_client(common_height) { + Ok(msgs) => msgs, + + Err(e) => { + warn!( + "skipping UpdateClient message for client `{}` on counterparty chain `{}`", + counterparty_client_id, + counterparty.id() + ); + warn!("reason: failed to build UpdateClient message: {e}"); + + Vec::new() + } + } + }; + + if counterparty_is_provider { + info!( + "will submit consumer light client attack evidence to client `{}` on provider chain `{}`", + counterparty_client_id, + counterparty.id(), + ); + + let msg = MsgSubmitIcsConsumerMisbehaviour { + submitter: signer.clone(), + misbehaviour: misbehaviour.clone(), + } + .to_any(); + + msgs.push(msg); + }; + + // We do not need to submit the misbehaviour if the client is already frozen. + if !counterparty_client_is_frozen { + info!( + "will submit light client attack evidence to client `{}` on counterparty chain `{}`", + counterparty_client_id, + counterparty.id(), + ); + + let msg = MsgSubmitMisbehaviour { + client_id: counterparty_client_id.clone(), + misbehaviour: misbehaviour.to_any(), + signer, + } + .to_any(); + + msgs.push(msg); + } + + if msgs.is_empty() { + warn!( + "skipping light client attack evidence for client `{}` on counterparty chain `{}`", + counterparty_client_id, + counterparty.id() + ); + + warn!("reason: no messages to submit"); + + return Ok(()); + } + + let tracked_msgs = TrackedMsgs::new_static(msgs, "light_client_attack_evidence"); + let responses = counterparty.send_messages_and_wait_check_tx(tracked_msgs)?; + + match responses.first() { + Some(response) if response.code.is_ok() => { + info!( + "successfully submitted light client attack evidence for client `{}` to counterparty chain `{}`, tx hash: {}", + counterparty_client_id, + counterparty.id(), + response.hash + ); + + Ok(()) + } + Some(response) => Err(eyre::eyre!( + "failed to submit light client attack evidence to counterparty chain `{}`: {response:?}", + counterparty.id() + )), + + None => Err(eyre::eyre!( + "failed to submit light client attack evidence to counterparty chain `{}`: no response from chain", + counterparty.id() + )), + } +} + +fn has_consensus_state( + chain: &BaseChainHandle, + client_id: &ClientId, + consensus_height: Height, +) -> bool { + use ibc_relayer::chain::requests::QueryConsensusStateRequest; + + let res = chain.query_consensus_state( + QueryConsensusStateRequest { + client_id: client_id.clone(), + consensus_height, + query_height: QueryHeight::Latest, + }, + IncludeProof::No, + ); + + res.is_ok() +} + +/// If the misbehaving chain is a CCV consumer chain, +/// then try fetch the consumer chains of the counterparty chains. +/// If that fails, then the counterparty chain is not a provider chain. +/// Otherwise, check if the misbehaving chain is a consumer of the counterparty chain, +/// which is then definitely a provider. +fn is_counterparty_provider( + chain: &CosmosSdkChain, + counterparty_chain_handle: &BaseChainHandle, + counterparty_client_id: &ClientId, +) -> bool { + if chain.config().ccv_consumer_chain { + let consumer_chains = counterparty_chain_handle + .query_consumer_chains() + .unwrap_or_default(); // If the query fails, use an empty list of consumers + + consumer_chains.iter().any(|(chain_id, client_id)| { + chain_id == chain.id() && client_id == counterparty_client_id + }) + } else { + false + } +} + +/// Fetch all the counterparty clients of the given chain. +/// A counterparty client is a client that has a connection with that chain. +/// +/// 1. Fetch all connections on the given chain +/// 2. For each connection: +/// 2.1. Fetch the client state of the counterparty client of that connection. +/// 2.2. From the client state, extract the chain id of the counterparty chain. +/// 4. Return a list of all counterparty chains and counterparty clients. +fn fetch_all_counterparty_clients( + config: &Config, + chain: &CosmosSdkChain, +) -> eyre::Result> { + use ibc_relayer::chain::requests::{QueryClientStateRequest, QueryConnectionsRequest}; + + let connections = chain.query_connections(QueryConnectionsRequest { + pagination: Some(PageRequest::all()), + })?; + + debug!("found {} connections", connections.len()); + + let mut counterparty_clients = vec![]; + + for connection in connections { + let client_id = connection.connection_end.client_id(); + let counterparty_client_id = connection.connection_end.counterparty().client_id(); + + debug!( + "found connection `{}` with client `{client_id}` and counterparty client `{counterparty_client_id}`", + connection.connection_id + ); + + debug!( + "fetching client state for client `{client_id}` on connection `{}`", + connection.connection_id + ); + + let client_state = chain.query_client_state( + QueryClientStateRequest { + client_id: client_id.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ); + + let client_state = match client_state { + Ok((client_state, _)) => client_state, + Err(e) => { + error!("failed to fetch client state for client `{client_id}`, skipping..."); + error!("reason: {e}"); + + continue; + } + }; + + let counterparty_chain_id = client_state.chain_id(); + + if config.find_chain(&counterparty_chain_id).is_some() { + info!("found counterparty client `{counterparty_client_id}` which lives on counterparty chain `{counterparty_chain_id}`"); + + counterparty_clients.push((counterparty_chain_id, counterparty_client_id.clone())); + } else { + debug!( + "skipping counterparty client `{client_id}` on counterparty \ + chain `{counterparty_chain_id}` which is not present in the config..." + ); + } + } + + // Remove duplicates + counterparty_clients.sort(); + counterparty_clients.dedup(); + + Ok(counterparty_clients) +} + +/// Build the two headers to submit as part of the `MsgSubmitMisbehaviour` message. +fn build_evidence_headers( + rt: Arc, + chain: &CosmosSdkChain, + lc: LightClientAttackEvidence, +) -> eyre::Result<(TendermintHeader, TendermintHeader)> { + if lc.conflicting_block.signed_header.header.height == lc.common_height { + return Err(eyre::eyre!( + "invalid evidence: header height ({}) is equal to common height ({})! cannot submit evidence", + lc.conflicting_block.signed_header.header.height, + lc.common_height + )); + } + + let trusted_height = lc.common_height; + + let trusted_validators = rt + .block_on(chain.rpc_client.validators(trusted_height, Paging::All))? + .validators; + + let trusted_header = rt + .block_on(chain.rpc_client.commit(trusted_height))? + .signed_header; + + let trusted_proposer = trusted_header.header.proposer_address; + + let trusted_validator_set = + validator::Set::with_proposer(trusted_validators, trusted_proposer)?; + + let trusted_height = Height::from_tm(trusted_height, chain.id()); + + let header1 = { + TendermintHeader { + signed_header: lc.conflicting_block.signed_header, + validator_set: lc.conflicting_block.validator_set, + trusted_height, + trusted_validator_set: trusted_validator_set.clone(), + } + }; + + let header2 = { + let signed_header = rt + .block_on(chain.rpc_client.commit(header1.signed_header.header.height))? + .signed_header; + + let validators = rt + .block_on( + chain + .rpc_client + .validators(header1.signed_header.header.height, Paging::All), + )? + .validators; + + let validator_set = + validator::Set::with_proposer(validators, signed_header.header.proposer_address)?; + + TendermintHeader { + signed_header, + validator_set, + trusted_height, + trusted_validator_set, + } + }; + + Ok((header1, header2)) +} + +#[cfg(test)] +mod tests { + use super::EvidenceCmd; + + use abscissa_core::clap::Parser; + use ibc_relayer_types::core::ics24_host::identifier::ChainId; + + #[test] + fn test_misbehaviour() { + assert_eq!( + EvidenceCmd { + chain_id: ChainId::from_string("chain_id"), + check_past_blocks: 100, + key_name: None, + }, + EvidenceCmd::parse_from(["test", "--chain", "chain_id"]) + ) + } + + #[test] + fn test_misbehaviour_no_chain() { + assert!(EvidenceCmd::try_parse_from(["test"]).is_err()) + } +} diff --git a/crates/relayer-cli/src/commands/fee/register_counterparty_payee.rs b/crates/relayer-cli/src/commands/fee/register_counterparty_payee.rs index 2105233720..de82f5a7ec 100644 --- a/crates/relayer-cli/src/commands/fee/register_counterparty_payee.rs +++ b/crates/relayer-cli/src/commands/fee/register_counterparty_payee.rs @@ -47,7 +47,11 @@ pub struct RegisterCounterpartyPayeeCmd { required = true, value_name = "COUNTERPARTY_PAYEE_ADDRESS", help_heading = "FLAGS", - help = "Address of the counterparty payee" + help = "Address of the counterparty payee.\n\nNote that there exists a configuration \ + parameter `auto_register_counterparty_payee` that can be enabled in order to have \ + Hermes automatically register the counterparty payee on the destination chain to the \ + relayer's address on the source chain. This option can be used for simple configuration \ + of the relayer to receive fees for relaying RecvPackets on fee-enabled channels." )] counterparty_payee_address: String, } diff --git a/crates/relayer-cli/src/commands/fee/transfer.rs b/crates/relayer-cli/src/commands/fee/transfer.rs index 1d93a39978..3893a2d232 100644 --- a/crates/relayer-cli/src/commands/fee/transfer.rs +++ b/crates/relayer-cli/src/commands/fee/transfer.rs @@ -159,7 +159,7 @@ impl Override for FeeTransferCmd { })?; if let Some(ref key_name) = self.key_name { - src_chain_config.key_name = key_name.to_string(); + src_chain_config.set_key_name(key_name.to_string()); } Ok(config) diff --git a/crates/relayer-cli/src/commands/health.rs b/crates/relayer-cli/src/commands/health.rs index ebd2ecab5a..8514bb087f 100644 --- a/crates/relayer-cli/src/commands/health.rs +++ b/crates/relayer-cli/src/commands/health.rs @@ -16,12 +16,12 @@ impl Runnable for HealthCheckCmd { let config = app_config(); for ch in &config.chains { - let _span = tracing::error_span!("health_check", chain = %ch.id).entered(); + let _span = tracing::error_span!("health_check", chain = %ch.id()).entered(); info!("performing health check..."); let chain = - spawn_chain_runtime(&config, &ch.id).unwrap_or_else(exit_with_unrecoverable_error); + spawn_chain_runtime(&config, ch.id()).unwrap_or_else(exit_with_unrecoverable_error); match chain.health_check() { Ok(Healthy) => info!("chain is healthy"), diff --git a/crates/relayer-cli/src/commands/keys/add.rs b/crates/relayer-cli/src/commands/keys/add.rs index 85b528b6b2..b24514d00a 100644 --- a/crates/relayer-cli/src/commands/keys/add.rs +++ b/crates/relayer-cli/src/commands/keys/add.rs @@ -10,7 +10,6 @@ use abscissa_core::{Command, Runnable}; use eyre::eyre; use hdpath::StandardHDPath; use ibc_relayer::{ - chain::ChainType, config::{ChainConfig, Config}, keyring::{ AnySigningKeyPair, KeyRing, Secp256k1KeyPair, SigningKeyPair, SigningKeyPairSized, Store, @@ -107,7 +106,7 @@ impl KeysAddCmd { let name = self .key_name .clone() - .unwrap_or_else(|| chain_config.key_name.clone()); + .unwrap_or_else(|| chain_config.key_name().to_string()); let hd_path = StandardHDPath::from_str(&self.hd_path) .map_err(|_| eyre!("invalid derivation path: {}", self.hd_path))?; @@ -151,7 +150,7 @@ impl Runnable for KeysAddCmd { "Added key '{}' ({}) on chain {}", opts.name, key.account(), - opts.config.id + opts.config.id(), )) .exit(), Err(e) => Output::error(format!( @@ -175,7 +174,7 @@ impl Runnable for KeysAddCmd { "Restored key '{}' ({}) on chain {}", opts.name, key.account(), - opts.config.id + opts.config.id() )) .exit(), Err(e) => Output::error(format!( @@ -203,8 +202,8 @@ pub fn add_key( hd_path: &StandardHDPath, overwrite: bool, ) -> eyre::Result { - let key_pair = match config.r#type { - ChainType::CosmosSdk => { + let key_pair = match config { + ChainConfig::CosmosSdk(config) => { let mut keyring = KeyRing::new_secp256k1( Store::Test, &config.account_prefix, @@ -236,8 +235,8 @@ pub fn restore_key( let mnemonic_content = fs::read_to_string(mnemonic).map_err(|_| eyre!("error reading the mnemonic file"))?; - let key_pair = match config.r#type { - ChainType::CosmosSdk => { + let key_pair = match config { + ChainConfig::CosmosSdk(config) => { let mut keyring = KeyRing::new_secp256k1( Store::Test, &config.account_prefix, diff --git a/crates/relayer-cli/src/commands/keys/balance.rs b/crates/relayer-cli/src/commands/keys/balance.rs index 5a64bea74d..b3c1edd90d 100644 --- a/crates/relayer-cli/src/commands/keys/balance.rs +++ b/crates/relayer-cli/src/commands/keys/balance.rs @@ -4,6 +4,7 @@ use abscissa_core::clap::Parser; use abscissa_core::{Command, Runnable}; use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::config::ChainConfig; use ibc_relayer_types::core::ics24_host::identifier::ChainId; use crate::application::app_config; @@ -75,7 +76,9 @@ fn get_balance(chain: impl ChainHandle, key_name: Option, denom: Option< // Retrieve the key name string to output. let key_name = key_name.unwrap_or_else(|| { let chain_config = chain.config().unwrap_or_else(exit_with_unrecoverable_error); - chain_config.key_name + match chain_config { + ChainConfig::CosmosSdk(chain_config) => chain_config.key_name, + } }); Output::success_msg(format!( @@ -95,7 +98,9 @@ fn get_balances(chain: impl ChainHandle, key_name: Option) { // Retrieve the key name string to output. let key_name = key_name.unwrap_or_else(|| { let chain_config = chain.config().unwrap_or_else(exit_with_unrecoverable_error); - chain_config.key_name + match chain_config { + ChainConfig::CosmosSdk(chain_config) => chain_config.key_name, + } }); let mut pretty_output = format!("Balances for key `{key_name}`:"); diff --git a/crates/relayer-cli/src/commands/keys/delete.rs b/crates/relayer-cli/src/commands/keys/delete.rs index fdc892afa9..fe25e8a056 100644 --- a/crates/relayer-cli/src/commands/keys/delete.rs +++ b/crates/relayer-cli/src/commands/keys/delete.rs @@ -3,7 +3,6 @@ use abscissa_core::{Command, Runnable}; use eyre::eyre; use ibc_relayer::{ - chain::ChainType, config::{ChainConfig, Config}, keyring::{KeyRing, Store}, }; @@ -95,7 +94,7 @@ impl Runnable for KeysDeleteCmd { match opts.id { KeysDeleteId::All => match delete_all_keys(&opts.config) { Ok(_) => { - Output::success_msg(format!("Removed all keys on chain {}", opts.config.id)) + Output::success_msg(format!("Removed all keys on chain {}", opts.config.id())) .exit() } Err(e) => Output::error(e).exit(), @@ -103,7 +102,8 @@ impl Runnable for KeysDeleteCmd { KeysDeleteId::Named(key_name) => match delete_key(&opts.config, key_name) { Ok(_) => Output::success_msg(format!( "Removed key ({}) on chain {}", - key_name, opts.config.id + key_name, + opts.config.id(), )) .exit(), Err(e) => Output::error(e).exit(), @@ -113,8 +113,8 @@ impl Runnable for KeysDeleteCmd { } pub fn delete_key(config: &ChainConfig, key_name: &str) -> eyre::Result<()> { - match config.r#type { - ChainType::CosmosSdk => { + match config { + ChainConfig::CosmosSdk(config) => { let mut keyring = KeyRing::new_secp256k1( Store::Test, &config.account_prefix, @@ -128,8 +128,8 @@ pub fn delete_key(config: &ChainConfig, key_name: &str) -> eyre::Result<()> { } pub fn delete_all_keys(config: &ChainConfig) -> eyre::Result<()> { - match config.r#type { - ChainType::CosmosSdk => { + match config { + ChainConfig::CosmosSdk(config) => { let mut keyring = KeyRing::new_secp256k1( Store::Test, &config.account_prefix, diff --git a/crates/relayer-cli/src/commands/keys/list.rs b/crates/relayer-cli/src/commands/keys/list.rs index 1713546a4e..cf3ec72651 100644 --- a/crates/relayer-cli/src/commands/keys/list.rs +++ b/crates/relayer-cli/src/commands/keys/list.rs @@ -6,10 +6,7 @@ use abscissa_core::{Command, Runnable}; use crate::conclude::Output; use crate::{application::app_config, conclude::json}; -use ibc_relayer::{ - config::{ChainConfig, Config}, - keyring::list_keys, -}; +use ibc_relayer::config::{ChainConfig, Config}; use ibc_relayer_types::core::ics24_host::identifier::ChainId; #[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] @@ -45,7 +42,7 @@ impl Runnable for KeysListCmd { Ok(result) => result, }; - match list_keys(&opts.chain_config) { + match opts.chain_config.list_keys() { Ok(keys) if json() => { let keys = keys.into_iter().collect::>(); Output::success(keys).exit() diff --git a/crates/relayer-cli/src/commands/listen.rs b/crates/relayer-cli/src/commands/listen.rs index 1806fc310d..68bd5c22ad 100644 --- a/crates/relayer-cli/src/commands/listen.rs +++ b/crates/relayer-cli/src/commands/listen.rs @@ -17,6 +17,7 @@ use ibc_relayer::{ chain::handle::Subscription, config::{ChainConfig, EventSourceMode}, event::source::EventSource, + util::compat_mode::compat_mode_from_version, }; use ibc_relayer_types::{core::ics24_host::identifier::ChainId, events::IbcEvent}; @@ -101,7 +102,7 @@ impl Runnable for ListenCmd { } /// Listen to events -#[instrument(skip_all, level = "error", fields(chain = %config.id))] +#[instrument(skip_all, level = "error", fields(chain = %config.id()))] pub fn listen(config: &ChainConfig, filters: &[EventFilter]) -> eyre::Result<()> { let rt = Arc::new(TokioRuntime::new()?); let compat_mode = detect_compatibility_mode(config, rt.clone())?; @@ -143,38 +144,49 @@ fn subscribe( compat_mode: CompatMode, rt: Arc, ) -> eyre::Result { - let (event_source, monitor_tx) = match &chain_config.event_source { - EventSourceMode::Push { url, batch_delay } => EventSource::websocket( - chain_config.id.clone(), - url.clone(), - compat_mode, - *batch_delay, - rt, - ), - EventSourceMode::Pull { interval } => EventSource::rpc( - chain_config.id.clone(), - HttpClient::new(chain_config.rpc_addr.clone())?, - *interval, - rt, - ), - }?; - - thread::spawn(move || event_source.run()); - - let subscription = monitor_tx.subscribe()?; - Ok(subscription) + // Q: Should this be restricted only to backends that support it, + // or are all backends expected to support subscriptions? + match chain_config { + ChainConfig::CosmosSdk(config) => { + let (event_source, monitor_tx) = match &config.event_source { + EventSourceMode::Push { url, batch_delay } => EventSource::websocket( + chain_config.id().clone(), + url.clone(), + compat_mode, + *batch_delay, + rt, + ), + EventSourceMode::Pull { interval } => EventSource::rpc( + chain_config.id().clone(), + HttpClient::new(config.rpc_addr.clone())?, + *interval, + rt, + ), + }?; + + thread::spawn(move || event_source.run()); + + let subscription = monitor_tx.subscribe()?; + Ok(subscription) + } + } } fn detect_compatibility_mode( config: &ChainConfig, rt: Arc, ) -> eyre::Result { - let client = HttpClient::new(config.rpc_addr.clone())?; + // TODO(erwan): move this to the cosmos sdk endpoint implementation + let rpc_addr = match config { + ChainConfig::CosmosSdk(config) => config.rpc_addr.clone(), + }; + let client = HttpClient::new(rpc_addr)?; let status = rt.block_on(client.status())?; - let compat_mode = CompatMode::from_version(status.node_info.version).unwrap_or_else(|e| { - warn!("Unsupported tendermint version, will use v0.37 compatibility mode but relaying might not work as desired: {e}"); - CompatMode::V0_37 - }); + let compat_mode = match config { + ChainConfig::CosmosSdk(config) => { + compat_mode_from_version(&config.compat_mode, status.node_info.version)?.into() + } + }; Ok(compat_mode) } diff --git a/crates/relayer-cli/src/commands/query/channel_ends.rs b/crates/relayer-cli/src/commands/query/channel_ends.rs index 83a94fdf76..aaa668beb1 100644 --- a/crates/relayer-cli/src/commands/query/channel_ends.rs +++ b/crates/relayer-cli/src/commands/query/channel_ends.rs @@ -9,7 +9,6 @@ use ibc_relayer::chain::requests::{ }; use ibc_relayer::client_state::AnyClientState; use ibc_relayer::registry::Registry; -use ibc_relayer_types::core::ics02_client::client_state::ClientState; use ibc_relayer_types::core::ics03_connection::connection::ConnectionEnd; use ibc_relayer_types::core::ics04_channel::channel::{ChannelEnd, State}; use ibc_relayer_types::core::ics24_host::identifier::ChainId; diff --git a/crates/relayer-cli/src/commands/query/channels.rs b/crates/relayer-cli/src/commands/query/channels.rs index fce0441b1d..a516854416 100644 --- a/crates/relayer-cli/src/commands/query/channels.rs +++ b/crates/relayer-cli/src/commands/query/channels.rs @@ -11,7 +11,6 @@ use ibc_relayer::chain::requests::{ QueryConnectionRequest, QueryHeight, }; use ibc_relayer::registry::Registry; -use ibc_relayer_types::core::ics02_client::client_state::ClientState; use ibc_relayer_types::core::ics04_channel::channel::{ChannelEnd, State}; use ibc_relayer_types::core::ics24_host::identifier::{ ChainId, ChannelId, ConnectionId, PortChannelId, PortId, diff --git a/crates/relayer-cli/src/commands/query/clients.rs b/crates/relayer-cli/src/commands/query/clients.rs index 2290b5661c..0ced719b2b 100644 --- a/crates/relayer-cli/src/commands/query/clients.rs +++ b/crates/relayer-cli/src/commands/query/clients.rs @@ -4,7 +4,6 @@ use ibc_relayer::chain::handle::ChainHandle; use serde::Serialize; use ibc_relayer::chain::requests::{PageRequest, QueryClientStatesRequest}; -use ibc_relayer_types::core::ics02_client::client_state::ClientState; use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ClientId}; use crate::cli_utils::spawn_chain_runtime; diff --git a/crates/relayer-cli/src/commands/query/connections.rs b/crates/relayer-cli/src/commands/query/connections.rs index f3a19e3585..dadef9d6a2 100644 --- a/crates/relayer-cli/src/commands/query/connections.rs +++ b/crates/relayer-cli/src/commands/query/connections.rs @@ -5,7 +5,6 @@ use ibc_relayer::chain::handle::ChainHandle; use ibc_relayer::chain::requests::{ IncludeProof, PageRequest, QueryClientStateRequest, QueryConnectionsRequest, QueryHeight, }; -use ibc_relayer_types::core::ics02_client::client_state::ClientState; use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ConnectionId}; use crate::cli_utils::spawn_chain_runtime; @@ -61,19 +60,27 @@ impl Runnable for QueryConnectionsCmd { connections.retain(|connection| { let client_id = connection.end().client_id().to_owned(); let chain_height = chain.query_latest_height(); - let (client_state, _) = chain - .query_client_state( - QueryClientStateRequest { - client_id, - height: QueryHeight::Specific(chain_height.unwrap()), - }, - IncludeProof::No, - ) - .unwrap(); - - let counterparty_chain_id = client_state.chain_id(); - - counterparty_chain_id == counterparty_filter_id + + let client_state = chain.query_client_state( + QueryClientStateRequest { + client_id: client_id.clone(), + height: QueryHeight::Specific(chain_height.unwrap()), + }, + IncludeProof::No, + ); + + match client_state { + Ok((client_state, _)) => { + let counterparty_chain_id = client_state.chain_id(); + counterparty_chain_id == counterparty_filter_id + } + Err(e) => { + warn!("failed to query client state for client {client_id}, skipping..."); + warn!("reason: {e}"); + + false + } + } }); } diff --git a/crates/relayer-cli/src/commands/start.rs b/crates/relayer-cli/src/commands/start.rs index c90ad23af9..5f0346d211 100644 --- a/crates/relayer-cli/src/commands/start.rs +++ b/crates/relayer-cli/src/commands/start.rs @@ -158,7 +158,7 @@ fn spawn_rest_server(config: &Config) -> Option { ); if let Err(e) = handle.await { - error!("REST service crashed with errror: {e}"); + error!("REST service crashed with error: {e}"); } } Err(e) => { @@ -213,7 +213,7 @@ fn spawn_telemetry_server(config: &Config) { info!("telemetry service running, exposing metrics at http://{addr}/metrics"); if let Err(e) = handle.await { - error!("telemetry service crashed with errror: {e}"); + error!("telemetry service crashed with error: {e}"); } } Err(e) => error!("telemetry service failed to start: {e}"), diff --git a/crates/relayer-cli/src/commands/tx/channel.rs b/crates/relayer-cli/src/commands/tx/channel.rs index 83b6c702de..0531c85dfe 100644 --- a/crates/relayer-cli/src/commands/tx/channel.rs +++ b/crates/relayer-cli/src/commands/tx/channel.rs @@ -1,3 +1,5 @@ +#![allow(clippy::redundant_closure_call)] + use abscissa_core::clap::Parser; use abscissa_core::{Command, Runnable}; diff --git a/crates/relayer-cli/src/commands/tx/client.rs b/crates/relayer-cli/src/commands/tx/client.rs index e528e0a4bc..827d1c5cc1 100644 --- a/crates/relayer-cli/src/commands/tx/client.rs +++ b/crates/relayer-cli/src/commands/tx/client.rs @@ -7,14 +7,16 @@ use std::thread; use abscissa_core::clap::Parser; use abscissa_core::{Command, Runnable}; -use ibc_relayer::chain::requests::{ - IncludeProof, PageRequest, QueryClientStateRequest, QueryClientStatesRequest, QueryHeight, -}; use ibc_relayer::config::Config; use ibc_relayer::event::IbcEventWithHeight; use ibc_relayer::foreign_client::{CreateOptions, ForeignClient}; use ibc_relayer::{chain::handle::ChainHandle, config::GenesisRestart}; -use ibc_relayer_types::core::ics02_client::client_state::ClientState; +use ibc_relayer::{ + chain::requests::{ + IncludeProof, PageRequest, QueryClientStateRequest, QueryClientStatesRequest, QueryHeight, + }, + config::ChainConfig, +}; use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ClientId}; use ibc_relayer_types::events::IbcEvent; use ibc_relayer_types::Height; @@ -202,8 +204,19 @@ impl Runnable for TxUpdateClientCmd { }; if let Some(restart_params) = self.genesis_restart_params() { - if let Some(c) = config.find_chain_mut(&reference_chain_id) { - c.genesis_restart = Some(restart_params); + match config.find_chain_mut(&reference_chain_id) { + Some(chain_config) => match chain_config { + ChainConfig::CosmosSdk(chain_config) => { + chain_config.genesis_restart = Some(restart_params) + } + }, + None => { + Output::error(format!( + "Chain '{}' is unsupported, or not found in the configuration", + reference_chain_id + )) + .exit(); + } } } @@ -435,15 +448,15 @@ impl Runnable for TxUpgradeClientsCmd { .chains .iter() .filter(|&chain| { - self.reference_chain_id != chain.id + self.reference_chain_id != *chain.id() && (self.host_chain_id.is_none() - || self.host_chain_id == Some(chain.id.clone())) + || self.host_chain_id == Some(chain.id().clone())) }) .map(|chain| { self.upgrade_clients_for_chain( &config, reference_chain.clone(), - &chain.id, + chain.id(), reference_upgrade_height, ) }) diff --git a/crates/relayer-cli/src/commands/tx/connection.rs b/crates/relayer-cli/src/commands/tx/connection.rs index a16484bdc3..fb88a61d2e 100644 --- a/crates/relayer-cli/src/commands/tx/connection.rs +++ b/crates/relayer-cli/src/commands/tx/connection.rs @@ -1,3 +1,5 @@ +#![allow(clippy::redundant_closure_call)] + use abscissa_core::clap::Parser; use abscissa_core::{Command, Runnable}; diff --git a/crates/relayer-cli/src/commands/tx/transfer.rs b/crates/relayer-cli/src/commands/tx/transfer.rs index 50d43a0afa..66b14026ae 100644 --- a/crates/relayer-cli/src/commands/tx/transfer.rs +++ b/crates/relayer-cli/src/commands/tx/transfer.rs @@ -131,7 +131,7 @@ impl Override for TxIcs20MsgTransferCmd { })?; if let Some(ref key_name) = self.key_name { - src_chain_config.key_name = key_name.to_string(); + src_chain_config.set_key_name(key_name.to_string()); } Ok(config) diff --git a/crates/relayer-cli/src/commands/tx/upgrade.rs b/crates/relayer-cli/src/commands/tx/upgrade.rs index e3ff636cbd..c56a60832c 100644 --- a/crates/relayer-cli/src/commands/tx/upgrade.rs +++ b/crates/relayer-cli/src/commands/tx/upgrade.rs @@ -3,6 +3,7 @@ use core::time::Duration; use abscissa_core::clap::Parser; use abscissa_core::{Command, Runnable}; +use ibc_relayer::upgrade_chain::requires_legacy_upgrade_proposal; use ibc_relayer::upgrade_chain::{build_and_send_ibc_upgrade_proposal, UpgradePlanOptions}; use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ClientId}; @@ -58,6 +59,13 @@ pub struct TxIbcUpgradeChainCmd { )] height_offset: u64, + #[clap( + long = "gov-account", + value_name = "GOV_ACCOUNT", + help = "Authority account used to sign upgrade proposal. Note: This is only used for chains with ibc-go version v8.0.0 or higher" + )] + gov_account: Option, + #[clap( long = "new-chain", value_name = "CHAIN_ID", @@ -88,7 +96,7 @@ pub struct TxIbcUpgradeChainCmd { } impl TxIbcUpgradeChainCmd { - fn validate_options(&self) -> Result { + fn validate_options(&self, gov_account: String) -> Result { let opts = UpgradePlanOptions { src_client_id: self.host_client_id.clone(), amount: self.amount, @@ -103,6 +111,7 @@ impl TxIbcUpgradeChainCmd { .upgrade_name .clone() .unwrap_or_else(|| "plan".to_string()), + gov_account, }; Ok(opts) @@ -113,17 +122,25 @@ impl Runnable for TxIbcUpgradeChainCmd { fn run(&self) { let config = app_config(); - let opts = match self.validate_options() { - Err(err) => Output::error(err).exit(), - Ok(result) => result, - }; - let host_chain = spawn_chain_runtime(&config, &self.host_chain_id) .unwrap_or_else(exit_with_unrecoverable_error); let reference_chain = spawn_chain_runtime(&config, &self.reference_chain_id) .unwrap_or_else(exit_with_unrecoverable_error); + let gov_account = if requires_legacy_upgrade_proposal(reference_chain.clone()) { + "".to_string() + } else if let Some(gov_account) = &self.gov_account { + gov_account.clone() + } else { + Output::error("The chain being upgraded uses an ibc-go version v8.0.0 or higher, which requires the governance module account to be specified using the flag `--gov-account`".to_owned()).exit(); + }; + + let opts = match self.validate_options(gov_account) { + Err(err) => Output::error(err).exit(), + Ok(result) => result, + }; + let res = build_and_send_ibc_upgrade_proposal(reference_chain, host_chain, &opts) .map_err(Error::upgrade_chain); @@ -151,6 +168,7 @@ mod tests { host_client_id: ClientId::from_str("client_sender").unwrap(), amount: 42, height_offset: 21, + gov_account: None, new_chain_id: None, new_unbonding: None, upgrade_name: None, @@ -167,7 +185,7 @@ mod tests { "--amount", "42", "--height-offset", - "21" + "21", ]) ) } @@ -181,6 +199,7 @@ mod tests { host_client_id: ClientId::from_str("client_sender").unwrap(), amount: 42, height_offset: 21, + gov_account: None, new_chain_id: None, new_unbonding: None, upgrade_name: None, @@ -213,6 +232,7 @@ mod tests { host_client_id: ClientId::from_str("client_sender").unwrap(), amount: 42, height_offset: 21, + gov_account: None, new_chain_id: Some(ChainId::from_string("new_chain")), new_unbonding: None, upgrade_name: None, @@ -245,6 +265,7 @@ mod tests { host_client_id: ClientId::from_str("client_sender").unwrap(), amount: 42, height_offset: 21, + gov_account: None, new_chain_id: None, new_unbonding: Some(17), upgrade_name: None, @@ -277,6 +298,7 @@ mod tests { host_client_id: ClientId::from_str("client_sender").unwrap(), amount: 42, height_offset: 21, + gov_account: None, new_chain_id: None, new_unbonding: None, upgrade_name: Some("upgrade_name".to_owned()), @@ -300,6 +322,39 @@ mod tests { ) } + #[test] + fn test_upgrade_chain_gov_account() { + assert_eq!( + TxIbcUpgradeChainCmd { + reference_chain_id: ChainId::from_string("chain_receiver"), + host_chain_id: ChainId::from_string("chain_sender"), + host_client_id: ClientId::from_str("client_sender").unwrap(), + amount: 42, + height_offset: 21, + gov_account: Some("gov_account".to_owned()), + new_chain_id: None, + new_unbonding: None, + upgrade_name: None, + denom: None + }, + TxIbcUpgradeChainCmd::parse_from([ + "test", + "--reference-chain", + "chain_receiver", + "--host-chain", + "chain_sender", + "--host-client", + "client_sender", + "--amount", + "42", + "--height-offset", + "21", + "--gov-account", + "gov_account" + ]) + ) + } + #[test] fn test_upgrade_chain_no_height_offset() { assert!(TxIbcUpgradeChainCmd::try_parse_from([ @@ -311,7 +366,7 @@ mod tests { "--host-client", "client_sender", "--amount", - "42" + "42", ]) .is_err()) } @@ -327,7 +382,7 @@ mod tests { "--host-client", "client_sender", "--height-offset", - "21" + "21", ]) .is_err()) } @@ -343,7 +398,7 @@ mod tests { "--amount", "42", "--height-offset", - "21" + "21", ]) .is_err()) } @@ -359,7 +414,7 @@ mod tests { "--amount", "42", "--height-offset", - "21" + "21", ]) .is_err()) } @@ -375,7 +430,7 @@ mod tests { "--amount", "42", "--height-offset", - "21" + "21", ]) .is_err()) } diff --git a/crates/relayer-cli/src/components.rs b/crates/relayer-cli/src/components.rs index ba46f7ffd2..a4751e343f 100644 --- a/crates/relayer-cli/src/components.rs +++ b/crates/relayer-cli/src/components.rs @@ -8,8 +8,8 @@ use ibc_relayer::{ util::debug_section::DebugSection, }; -use crate::config::Error; use crate::tracing_handle::ReloadHandle; +use ibc_relayer::config::Error; /// The name of the environment variable through which one can override /// the tracing filter built in [`build_tracing_filter`]. diff --git a/crates/relayer-cli/src/config.rs b/crates/relayer-cli/src/config.rs index 6e5d6218a1..39e5f9106d 100644 --- a/crates/relayer-cli/src/config.rs +++ b/crates/relayer-cli/src/config.rs @@ -1,172 +1,8 @@ -//! Validation code for the Hermes configuration file. -//! -//! See instructions in `commands.rs` to specify the path to your -//! application's configuration file and/or command-line options -//! for specifying it. - -use alloc::collections::BTreeSet; +use crate::prelude::app_reader; use std::path::PathBuf; -use flex_error::{define_error, TraceError}; -use ibc_relayer::config::{ChainConfig, Config, ModeConfig}; -use ibc_relayer_types::core::ics24_host::identifier::ChainId; -use tendermint_light_client_verifier::types::TrustThreshold; -use tracing_subscriber::filter::ParseError; - -use crate::application::app_reader; - /// Get the path to configuration file pub fn config_path() -> Option { let app = app_reader(); app.config_path().cloned() } - -// Specifies all the possible syntactic errors -// that a Hermes configuration file could contain. -define_error! { - Error { - ZeroChain - |_| { "config file does not specify any chain" }, - - InvalidLogDirective - { directive: String, } - [ TraceError ] - |e| { - format!("invalid log directive: {0:?}", e.directive) - }, - - InvalidMode - { reason: String, } - |e| { - format!("config file specifies invalid mode config, caused by: {0}", - e.reason) - }, - - DuplicateChains - { chain_id: ChainId } - |e| { - format!("config file has duplicate entry for the chain '{0}'", - e.chain_id) - }, - - InvalidTrustThreshold - { - threshold: TrustThreshold, - chain_id: ChainId, - reason: String - } - |e| { - format!("config file specifies an invalid `trust_threshold` ({0}) for the chain '{1}', caused by: {2}", - e.threshold, e.chain_id, e.reason) - }, - - DeprecatedGasAdjustment - { - gas_adjustment: f64, - gas_multiplier: f64, - chain_id: ChainId, - } - |e| { - format!( - "config file specifies deprecated setting `gas_adjustment = {1}` for the chain '{0}'; \ - to get the same behavior, use `gas_multiplier = {2}", - e.chain_id, e.gas_adjustment, e.gas_multiplier - ) - }, - } -} - -#[derive(Clone, Debug)] -pub enum Diagnostic { - Warning(E), - Error(E), -} - -/// Method for syntactic validation of the input configuration file. -pub fn validate_config(config: &Config) -> Result<(), Diagnostic> { - // Check for duplicate chain configuration and invalid trust thresholds - let mut unique_chain_ids = BTreeSet::new(); - for c in config.chains.iter() { - let already_present = !unique_chain_ids.insert(c.id.clone()); - if already_present { - return Err(Diagnostic::Error(Error::duplicate_chains(c.id.clone()))); - } - - validate_trust_threshold(&c.id, c.trust_threshold)?; - - // Validate gas-related settings - validate_gas_settings(&c.id, c)?; - } - - // Check for invalid mode config - validate_mode(&config.mode)?; - - Ok(()) -} - -fn validate_mode(mode: &ModeConfig) -> Result<(), Diagnostic> { - if mode.all_disabled() { - return Err(Diagnostic::Warning(Error::invalid_mode( - "all operation modes of Hermes are disabled, relayer won't perform any action aside from subscribing to events".to_string(), - ))); - } - - if mode.clients.enabled && !mode.clients.refresh && !mode.clients.misbehaviour { - return Err(Diagnostic::Error(Error::invalid_mode( - "either `refresh` or `misbehaviour` must be set to true if `clients.enabled` is set to true".to_string(), - ))); - } - - Ok(()) -} - -/// Check that the trust threshold is: -/// -/// a) non-zero -/// b) greater or equal to 1/3 -/// c) strictly less than 1 -fn validate_trust_threshold( - id: &ChainId, - trust_threshold: TrustThreshold, -) -> Result<(), Diagnostic> { - if trust_threshold.denominator() == 0 { - return Err(Diagnostic::Error(Error::invalid_trust_threshold( - trust_threshold, - id.clone(), - "trust threshold denominator cannot be zero".to_string(), - ))); - } - - if trust_threshold.numerator() * 3 < trust_threshold.denominator() { - return Err(Diagnostic::Error(Error::invalid_trust_threshold( - trust_threshold, - id.clone(), - "trust threshold cannot be < 1/3".to_string(), - ))); - } - - if trust_threshold.numerator() >= trust_threshold.denominator() { - return Err(Diagnostic::Error(Error::invalid_trust_threshold( - trust_threshold, - id.clone(), - "trust threshold cannot be >= 1".to_string(), - ))); - } - - Ok(()) -} - -fn validate_gas_settings(id: &ChainId, config: &ChainConfig) -> Result<(), Diagnostic> { - // Check that the gas_adjustment option is not set - if let Some(gas_adjustment) = config.gas_adjustment { - let gas_multiplier = gas_adjustment + 1.0; - - return Err(Diagnostic::Error(Error::deprecated_gas_adjustment( - gas_adjustment, - gas_multiplier, - id.clone(), - ))); - } - - Ok(()) -} diff --git a/crates/relayer-rest/Cargo.toml b/crates/relayer-rest/Cargo.toml index 17214cfa22..4b1002d2db 100644 --- a/crates/relayer-rest/Cargo.toml +++ b/crates/relayer-rest/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ibc-relayer-rest" -version = "0.25.0" +version = "0.26.4" authors = ["Informal Systems "] edition = "2021" license = "Apache-2.0" @@ -8,14 +8,14 @@ readme = "README.md" keywords = ["ibc", "rest", "api", "cosmos", "tendermint"] homepage = "https://hermes.informal.systems/" repository = "https://github.com/informalsystems/hermes" -rust-version = "1.70" +rust-version = "1.71" description = """ Rust implementation of a RESTful API server for Hermes """ [dependencies] -ibc-relayer-types = { version = "0.25.0", path = "../relayer-types" } -ibc-relayer = { version = "0.25.0", path = "../relayer" } +ibc-relayer-types = { version = "0.26.4", path = "../relayer-types" } +ibc-relayer = { version = "0.26.4", path = "../relayer" } crossbeam-channel = "0.5" serde = "1.0" diff --git a/crates/relayer-rest/README.md b/crates/relayer-rest/README.md index a9932b1c78..ee66cb6870 100644 --- a/crates/relayer-rest/README.md +++ b/crates/relayer-rest/README.md @@ -6,7 +6,7 @@ [![End to End testing][e2e-image]][e2e-link] [![Apache 2.0 Licensed][license-image]][license-link] ![Rust Stable][rustc-image] -![Rust 1.70+][rustc-version] +![Rust 1.71+][rustc-version] This is the repository for the IBC REST server for use in the Hermes IBC relayer. @@ -39,4 +39,4 @@ Unless required by applicable law or agreed to in writing, software distributed [license-image]: https://img.shields.io/badge/license-Apache2.0-blue.svg [license-link]: https://github.com/informalsystems/hermes/blob/master/LICENSE [rustc-image]: https://img.shields.io/badge/rustc-stable-blue.svg -[rustc-version]: https://img.shields.io/badge/rustc-1.70+-blue.svg +[rustc-version]: https://img.shields.io/badge/rustc-1.71+-blue.svg diff --git a/crates/relayer-rest/tests/mock.rs b/crates/relayer-rest/tests/mock.rs index 49db676549..b0f49c9bb4 100644 --- a/crates/relayer-rest/tests/mock.rs +++ b/crates/relayer-rest/tests/mock.rs @@ -64,7 +64,7 @@ async fn version() { let rest_api_version = VersionInfo { name: "ibc-relayer-rest".to_string(), - version: "0.25.0".to_string(), + version: "0.26.4".to_string(), }; let result: JsonResult<_, ()> = JsonResult::Success(vec![version.clone(), rest_api_version]); @@ -96,6 +96,7 @@ async fn get_chains() { const MOCK_CHAIN_CONFIG: &str = r#" id = 'mock-0' +type = 'CosmosSdk' rpc_addr = 'http://127.0.0.1:26557' grpc_addr = 'http://127.0.0.1:9091' event_source = { mode = 'push', url = 'ws://127.0.0.1:26557/websocket', batch_delay = '500ms' } diff --git a/crates/relayer-types/Cargo.toml b/crates/relayer-types/Cargo.toml index 0b20dc7dc4..62621654e9 100644 --- a/crates/relayer-types/Cargo.toml +++ b/crates/relayer-types/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "ibc-relayer-types" -version = "0.25.0" +version = "0.26.4" edition = "2021" license = "Apache-2.0" readme = "README.md" keywords = ["blockchain", "consensus", "cosmos", "ibc", "tendermint"] repository = "https://github.com/informalsystems/hermes" authors = ["Informal Systems "] -rust-version = "1.70" +rust-version = "1.71" description = """ Implementation of the Inter-Blockchain Communication Protocol (IBC). This crate comprises the main data structures and on-chain logic. @@ -24,13 +24,12 @@ mocks = ["tendermint-testgen", "clock"] [dependencies] # Proto definitions for all IBC-related interfaces, e.g., connections or channels. -ibc-proto = { version = "0.37.0" } +ibc-proto = { version = "0.39.0", features = ["serde"] } ics23 = { version = "0.11.0", features = ["std", "host-functions"] } time = { version = "0.3" } serde_derive = { version = "1.0.104" } serde = { version = "1.0" } serde_json = { version = "1" } -erased-serde = { version = "0.3" } prost = { version = "0.12" } bytes = { version = "1.4.0" } subtle-encoding = { version = "0.5" } @@ -39,7 +38,6 @@ derive_more = { version = "0.99.17", default-features = false, features = ["from uint = { version = "0.9" } itertools = { version = "0.10.3" } primitive-types = { version = "0.12.1", default-features = false, features = ["serde_no_std"] } -dyn-clone = "1.0.12" num-rational = "0.4.1" regex = "1" diff --git a/crates/relayer-types/src/applications/ics27_ica/cosmos_tx.rs b/crates/relayer-types/src/applications/ics27_ica/cosmos_tx.rs index 8503d027dd..f6b6043de8 100644 --- a/crates/relayer-types/src/applications/ics27_ica/cosmos_tx.rs +++ b/crates/relayer-types/src/applications/ics27_ica/cosmos_tx.rs @@ -1,6 +1,6 @@ use ibc_proto::google::protobuf::Any; use ibc_proto::ibc::applications::interchain_accounts::v1::CosmosTx as RawCosmosTx; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use serde_derive::Deserialize; use serde_derive::Serialize; diff --git a/crates/relayer-types/src/applications/ics27_ica/msgs/register.rs b/crates/relayer-types/src/applications/ics27_ica/msgs/register.rs index 67954b27d5..9c73c9de93 100644 --- a/crates/relayer-types/src/applications/ics27_ica/msgs/register.rs +++ b/crates/relayer-types/src/applications/ics27_ica/msgs/register.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use ibc_proto::ibc::applications::interchain_accounts::controller::v1::MsgRegisterInterchainAccount as RawMsgRegisterInterchainAccount; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use crate::applications::ics27_ica::error::Error; use crate::core::ics04_channel::version::Version; diff --git a/crates/relayer-types/src/applications/ics27_ica/msgs/send_tx.rs b/crates/relayer-types/src/applications/ics27_ica/msgs/send_tx.rs index 40c11a9646..72bc922a2d 100644 --- a/crates/relayer-types/src/applications/ics27_ica/msgs/send_tx.rs +++ b/crates/relayer-types/src/applications/ics27_ica/msgs/send_tx.rs @@ -1,7 +1,7 @@ use serde_derive::{Deserialize, Serialize}; use ibc_proto::ibc::applications::interchain_accounts::controller::v1::MsgSendTx as RawMsgSendTx; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use crate::applications::ics27_ica::error::Error; use crate::applications::ics27_ica::packet_data::InterchainAccountPacketData; diff --git a/crates/relayer-types/src/applications/ics28_ccv/mod.rs b/crates/relayer-types/src/applications/ics28_ccv/mod.rs new file mode 100644 index 0000000000..7ba0198166 --- /dev/null +++ b/crates/relayer-types/src/applications/ics28_ccv/mod.rs @@ -0,0 +1,4 @@ +//! The implementation of the ICS 28 Cross-Chain Validation (CCV). +//! Please see the [specification](https://github.com/cosmos/ibc/tree/main/spec/app/ics-028-cross-chain-validation#readme). + +pub mod msgs; diff --git a/crates/relayer-types/src/applications/ics28_ccv/msgs/ccv_double_voting.rs b/crates/relayer-types/src/applications/ics28_ccv/msgs/ccv_double_voting.rs new file mode 100644 index 0000000000..a1ce4291d9 --- /dev/null +++ b/crates/relayer-types/src/applications/ics28_ccv/msgs/ccv_double_voting.rs @@ -0,0 +1,85 @@ +use core::fmt; + +use ibc_proto::interchain_security::ccv::provider::v1::MsgSubmitConsumerDoubleVoting as RawIcsDoubleVoting; +use ibc_proto::Protobuf; +use tendermint::evidence::DuplicateVoteEvidence; + +use crate::clients::ics07_tendermint::header::Header; +use crate::signer::Signer; +use crate::tx_msg::Msg; + +use super::error::Error; + +pub const ICS_DOUBLE_VOTING_TYPE_URL: &str = + "/interchain_security.ccv.provider.v1.MsgSubmitConsumerDoubleVoting"; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct MsgSubmitIcsConsumerDoubleVoting { + pub submitter: Signer, + pub duplicate_vote_evidence: DuplicateVoteEvidence, + pub infraction_block_header: Header, +} + +impl Msg for MsgSubmitIcsConsumerDoubleVoting { + type ValidationError = crate::core::ics24_host::error::ValidationError; + type Raw = RawIcsDoubleVoting; + + fn route(&self) -> String { + crate::keys::ROUTER_KEY.to_string() + } + + fn type_url(&self) -> String { + ICS_DOUBLE_VOTING_TYPE_URL.to_string() + } +} + +impl Protobuf for MsgSubmitIcsConsumerDoubleVoting {} + +impl TryFrom for MsgSubmitIcsConsumerDoubleVoting { + type Error = Error; + + fn try_from(raw: RawIcsDoubleVoting) -> Result { + Ok(Self { + submitter: raw.submitter.parse().map_err(Error::signer)?, + duplicate_vote_evidence: raw + .duplicate_vote_evidence + .ok_or_else(|| Error::invalid_raw_double_voting("missing evidence".into()))? + .try_into() + .map_err(|e| { + Error::invalid_raw_double_voting(format!("cannot convert evidence: {e}")) + })?, + infraction_block_header: raw + .infraction_block_header + .ok_or_else(|| { + Error::invalid_raw_double_voting("missing infraction block header".into()) + })? + .try_into() + .map_err(|e| { + Error::invalid_raw_double_voting(format!("cannot convert header: {e}")) + })?, + }) + } +} + +impl From for RawIcsDoubleVoting { + fn from(value: MsgSubmitIcsConsumerDoubleVoting) -> Self { + RawIcsDoubleVoting { + submitter: value.submitter.to_string(), + duplicate_vote_evidence: Some(value.duplicate_vote_evidence.into()), + infraction_block_header: Some(value.infraction_block_header.into()), + } + } +} + +impl fmt::Display for MsgSubmitIcsConsumerDoubleVoting { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + f.debug_struct("MsgSubmitIcsConsumerDoubleVoting") + .field("submitter", &self.submitter) + .field("duplicate_vote_evidence", &"[...]") + .field( + "infraction_block_header", + &self.infraction_block_header.signed_header.header.height, + ) + .finish() + } +} diff --git a/crates/relayer-types/src/applications/ics28_ccv/msgs/ccv_misbehaviour.rs b/crates/relayer-types/src/applications/ics28_ccv/msgs/ccv_misbehaviour.rs new file mode 100644 index 0000000000..8b5c6c2750 --- /dev/null +++ b/crates/relayer-types/src/applications/ics28_ccv/msgs/ccv_misbehaviour.rs @@ -0,0 +1,71 @@ +use core::fmt; + +use serde::{Deserialize, Serialize}; + +use ibc_proto::interchain_security::ccv::provider::v1::MsgSubmitConsumerMisbehaviour as RawIcsMisbehaviour; +use ibc_proto::Protobuf; + +use crate::clients::ics07_tendermint::misbehaviour::Misbehaviour; +use crate::signer::Signer; +use crate::tx_msg::Msg; + +use super::error::Error; + +pub const ICS_MISBEHAVIOR_TYPE_URL: &str = + "/interchain_security.ccv.provider.v1.MsgSubmitConsumerMisbehaviour"; + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct MsgSubmitIcsConsumerMisbehaviour { + pub submitter: Signer, + pub misbehaviour: Misbehaviour, +} + +impl Msg for MsgSubmitIcsConsumerMisbehaviour { + type ValidationError = crate::core::ics24_host::error::ValidationError; + type Raw = RawIcsMisbehaviour; + + fn route(&self) -> String { + crate::keys::ROUTER_KEY.to_string() + } + + fn type_url(&self) -> String { + ICS_MISBEHAVIOR_TYPE_URL.to_string() + } +} + +impl Protobuf for MsgSubmitIcsConsumerMisbehaviour {} + +impl TryFrom for MsgSubmitIcsConsumerMisbehaviour { + type Error = Error; + + fn try_from(raw: RawIcsMisbehaviour) -> Result { + Ok(Self { + submitter: raw.submitter.parse().map_err(Error::signer)?, + misbehaviour: raw + .misbehaviour + .ok_or_else(|| Error::invalid_raw_misbehaviour("missing misbehaviour".into()))? + .try_into() + .map_err(|_e| { + Error::invalid_raw_misbehaviour("cannot convert misbehaviour".into()) + })?, + }) + } +} + +impl From for RawIcsMisbehaviour { + fn from(value: MsgSubmitIcsConsumerMisbehaviour) -> Self { + RawIcsMisbehaviour { + submitter: value.submitter.to_string(), + misbehaviour: Some(value.misbehaviour.into()), + } + } +} + +impl fmt::Display for MsgSubmitIcsConsumerMisbehaviour { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + f.debug_struct("MsgSubmitIcsConsumerMisbehaviour") + .field("submitter", &self.submitter) + .field("misbehaviour", &self.misbehaviour) + .finish() + } +} diff --git a/crates/relayer-types/src/applications/ics28_ccv/msgs/error.rs b/crates/relayer-types/src/applications/ics28_ccv/msgs/error.rs new file mode 100644 index 0000000000..ee5d3a2a36 --- /dev/null +++ b/crates/relayer-types/src/applications/ics28_ccv/msgs/error.rs @@ -0,0 +1,20 @@ +use flex_error::define_error; + +use crate::signer::SignerError; + +define_error! { + #[derive(Debug, PartialEq, Eq)] + Error { + InvalidRawMisbehaviour + { reason: String } + | e | { format_args!("invalid raw misbehaviour: {}", e.reason) }, + + InvalidRawDoubleVoting + { reason: String } + | e | { format_args!("invalid raw double voting: {}", e.reason) }, + + Signer + [ SignerError ] + | _ | { "failed to parse signer" }, + } +} diff --git a/crates/relayer-types/src/applications/ics28_ccv/msgs/mod.rs b/crates/relayer-types/src/applications/ics28_ccv/msgs/mod.rs new file mode 100644 index 0000000000..df28e4a73a --- /dev/null +++ b/crates/relayer-types/src/applications/ics28_ccv/msgs/mod.rs @@ -0,0 +1,3 @@ +pub mod ccv_double_voting; +pub mod ccv_misbehaviour; +pub mod error; diff --git a/crates/relayer-types/src/applications/ics31_icq/events.rs b/crates/relayer-types/src/applications/ics31_icq/events.rs index 307e38f1d2..739fecedba 100644 --- a/crates/relayer-types/src/applications/ics31_icq/events.rs +++ b/crates/relayer-types/src/applications/ics31_icq/events.rs @@ -101,7 +101,7 @@ fn fetch_first_element_from_events( let res = block_events .get(key) .ok_or_else(|| Error::event(format!("attribute not found for key: {key}")))? - .get(0) + .first() .ok_or_else(|| { Error::event(format!( "element at position 0, of attribute with key `{key}`, not found" diff --git a/crates/relayer-types/src/applications/mod.rs b/crates/relayer-types/src/applications/mod.rs index 539225bf08..7080c37fc4 100644 --- a/crates/relayer-types/src/applications/mod.rs +++ b/crates/relayer-types/src/applications/mod.rs @@ -1,6 +1,7 @@ //! Various packet encoding semantics which underpin the various types of transactions. pub mod ics27_ica; +pub mod ics28_ccv; pub mod ics29_fee; pub mod ics31_icq; pub mod transfer; diff --git a/crates/relayer-types/src/applications/transfer/acknowledgement.rs b/crates/relayer-types/src/applications/transfer/acknowledgement.rs index 35251d4485..2277baebd6 100644 --- a/crates/relayer-types/src/applications/transfer/acknowledgement.rs +++ b/crates/relayer-types/src/applications/transfer/acknowledgement.rs @@ -64,8 +64,8 @@ mod test { #[test] fn test_ack_ser() { fn ser_json_assert_eq(ack: Acknowledgement, json_str: &str) { - let ser = serde_json::to_string(&ack).unwrap(); - assert_eq!(ser, json_str) + let set = serde_json::to_string(&ack).unwrap(); + assert_eq!(set, json_str) } ser_json_assert_eq(Acknowledgement::success(), r#"{"result":"AQ=="}"#); diff --git a/crates/relayer-types/src/applications/transfer/denom.rs b/crates/relayer-types/src/applications/transfer/denom.rs index dbc5a4cd3a..35a5e572b1 100644 --- a/crates/relayer-types/src/applications/transfer/denom.rs +++ b/crates/relayer-types/src/applications/transfer/denom.rs @@ -196,7 +196,7 @@ pub fn is_receiver_chain_source( // A: sender chain in this transfer, port "transfer" and channel "c2b" (to B) // B: receiver chain in this transfer, port "transfer" and channel "c2a" (to A) // - // If B had originally sent the token in a previous tranfer, then A would have stored the token as + // If B had originally sent the token in a previous transfer, then A would have stored the token as // "transfer/c2b/{token_denom}". Now, A is sending to B, so to check if B is the source of the token, // we need to check if the token starts with "transfer/c2b". let prefix = TracePrefix::new(source_port, source_channel); diff --git a/crates/relayer-types/src/applications/transfer/error.rs b/crates/relayer-types/src/applications/transfer/error.rs index 5fdf2660aa..f0e52d946d 100644 --- a/crates/relayer-types/src/applications/transfer/error.rs +++ b/crates/relayer-types/src/applications/transfer/error.rs @@ -1,9 +1,10 @@ -use flex_error::{define_error, DisplayOnly, TraceError}; -use ibc_proto::protobuf::Error as TendermintProtoError; use std::convert::Infallible; use std::str::Utf8Error; use std::string::FromUtf8Error; + +use flex_error::{define_error, DisplayOnly, TraceError}; use subtle_encoding::Error as EncodingError; +use tendermint_proto::Error as TendermintProtoError; use uint::FromDecStrErr; use crate::core::ics04_channel::channel::Ordering; diff --git a/crates/relayer-types/src/applications/transfer/msgs/send.rs b/crates/relayer-types/src/applications/transfer/msgs/send.rs index 8529453880..36e71dc66b 100644 --- a/crates/relayer-types/src/applications/transfer/msgs/send.rs +++ b/crates/relayer-types/src/applications/transfer/msgs/send.rs @@ -1,7 +1,7 @@ use std::fmt::Display; use std::str::FromStr; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use serde_derive::Deserialize; use serde_derive::Serialize; diff --git a/crates/relayer-types/src/applications/transfer/msgs/transfer.rs b/crates/relayer-types/src/applications/transfer/msgs/transfer.rs index ffdbdc22e9..8bfc198b44 100644 --- a/crates/relayer-types/src/applications/transfer/msgs/transfer.rs +++ b/crates/relayer-types/src/applications/transfer/msgs/transfer.rs @@ -3,7 +3,7 @@ use ibc_proto::cosmos::base::v1beta1::Coin; use ibc_proto::google::protobuf::Any; use ibc_proto::ibc::applications::transfer::v1::MsgTransfer as RawMsgTransfer; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use crate::applications::transfer::error::Error; use crate::core::ics04_channel::timeout::TimeoutHeight; diff --git a/crates/relayer-types/src/clients/ics07_tendermint/client_state.rs b/crates/relayer-types/src/clients/ics07_tendermint/client_state.rs index 343d76af9d..9ca7c7e233 100644 --- a/crates/relayer-types/src/clients/ics07_tendermint/client_state.rs +++ b/crates/relayer-types/src/clients/ics07_tendermint/client_state.rs @@ -7,15 +7,13 @@ use serde::{Deserialize, Serialize}; use ibc_proto::google::protobuf::Any; use ibc_proto::ibc::core::client::v1::Height as RawHeight; use ibc_proto::ibc::lightclients::tendermint::v1::ClientState as RawTmClientState; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use tendermint_light_client_verifier::options::Options; use crate::clients::ics07_tendermint::error::Error; use crate::clients::ics07_tendermint::header::Header as TmHeader; -use crate::core::ics02_client::client_state::{ - ClientState as Ics2ClientState, UpgradeOptions as CoreUpgradeOptions, -}; +use crate::core::ics02_client::client_state::ClientState as Ics2ClientState; use crate::core::ics02_client::client_type::ClientType; use crate::core::ics02_client::error::Error as Ics02Error; use crate::core::ics02_client::trust_threshold::TrustThreshold; @@ -194,9 +192,9 @@ pub struct UpgradeOptions { pub unbonding_period: Duration, } -impl CoreUpgradeOptions for UpgradeOptions {} - impl Ics2ClientState for ClientState { + type UpgradeOptions = UpgradeOptions; + fn chain_id(&self) -> ChainId { self.chain_id.clone() } @@ -216,14 +214,9 @@ impl Ics2ClientState for ClientState { fn upgrade( &mut self, upgrade_height: Height, - upgrade_options: &dyn CoreUpgradeOptions, + upgrade_options: UpgradeOptions, chain_id: ChainId, ) { - let upgrade_options = upgrade_options - .as_any() - .downcast_ref::() - .expect("UpgradeOptions not of type Tendermint"); - // Reset custom fields to zero values self.trusting_period = ZERO_DURATION; self.trust_threshold = TrustThreshold::CLIENT_STATE_RESET; @@ -346,7 +339,10 @@ impl TryFrom for ClientState { TENDERMINT_CLIENT_STATE_TYPE_URL => { decode_client_state(raw.value.deref()).map_err(Into::into) } - _ => Err(Ics02Error::unknown_client_state_type(raw.type_url)), + _ => Err(Ics02Error::unexpected_client_state_type( + TENDERMINT_CLIENT_STATE_TYPE_URL.to_string(), + raw.type_url, + )), } } } @@ -355,7 +351,7 @@ impl From for Any { fn from(client_state: ClientState) -> Self { Any { type_url: TENDERMINT_CLIENT_STATE_TYPE_URL.to_string(), - value: Protobuf::::encode_vec(&client_state), + value: Protobuf::::encode_vec(client_state), } } } diff --git a/crates/relayer-types/src/clients/ics07_tendermint/consensus_state.rs b/crates/relayer-types/src/clients/ics07_tendermint/consensus_state.rs index 6ba3fceba6..5cbd77732b 100644 --- a/crates/relayer-types/src/clients/ics07_tendermint/consensus_state.rs +++ b/crates/relayer-types/src/clients/ics07_tendermint/consensus_state.rs @@ -1,6 +1,6 @@ use ibc_proto::google::protobuf::Any; use ibc_proto::ibc::lightclients::tendermint::v1::ConsensusState as RawConsensusState; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use serde::{Deserialize, Serialize}; use tendermint::{hash::Algorithm, time::Time, Hash}; use tendermint_proto::google::protobuf as tpb; @@ -123,7 +123,7 @@ impl From for Any { fn from(consensus_state: ConsensusState) -> Self { Any { type_url: TENDERMINT_CONSENSUS_STATE_TYPE_URL.to_string(), - value: Protobuf::::encode_vec(&consensus_state), + value: Protobuf::::encode_vec(consensus_state), } } } diff --git a/crates/relayer-types/src/clients/ics07_tendermint/header.rs b/crates/relayer-types/src/clients/ics07_tendermint/header.rs index a361d66737..57b99db1e9 100644 --- a/crates/relayer-types/src/clients/ics07_tendermint/header.rs +++ b/crates/relayer-types/src/clients/ics07_tendermint/header.rs @@ -3,7 +3,7 @@ use std::fmt::{Display, Error as FmtError, Formatter}; use bytes::Buf; use ibc_proto::google::protobuf::Any; use ibc_proto::ibc::lightclients::tendermint::v1::Header as RawHeader; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use prost::Message; use serde_derive::{Deserialize, Serialize}; use tendermint::block::signed_header::SignedHeader; @@ -127,7 +127,7 @@ impl From
for Any { fn from(header: Header) -> Self { Any { type_url: TENDERMINT_HEADER_TYPE_URL.to_string(), - value: Protobuf::::encode_vec(&header), + value: Protobuf::::encode_vec(header), } } } diff --git a/crates/relayer-types/src/clients/ics07_tendermint/misbehaviour.rs b/crates/relayer-types/src/clients/ics07_tendermint/misbehaviour.rs index f8d1034a3e..1336e160bf 100644 --- a/crates/relayer-types/src/clients/ics07_tendermint/misbehaviour.rs +++ b/crates/relayer-types/src/clients/ics07_tendermint/misbehaviour.rs @@ -1,10 +1,11 @@ use ibc_proto::ibc::lightclients::tendermint::v1::Misbehaviour as RawMisbehaviour; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use serde::{Deserialize, Serialize}; use crate::clients::ics07_tendermint::error::Error; use crate::clients::ics07_tendermint::header::Header; use crate::core::ics24_host::identifier::ClientId; +use crate::tx_msg::Msg; use crate::Height; pub const TENDERMINT_MISBEHAVIOR_TYPE_URL: &str = "/ibc.lightclients.tendermint.v1.Misbehaviour"; @@ -26,6 +27,19 @@ impl crate::core::ics02_client::misbehaviour::Misbehaviour for Misbehaviour { } } +impl Msg for Misbehaviour { + type ValidationError = Error; + type Raw = RawMisbehaviour; + + fn route(&self) -> String { + crate::keys::ROUTER_KEY.to_string() + } + + fn type_url(&self) -> String { + TENDERMINT_MISBEHAVIOR_TYPE_URL.to_string() + } +} + impl Protobuf for Misbehaviour {} impl TryFrom for Misbehaviour { diff --git a/crates/relayer-types/src/core/ics02_client/client_state.rs b/crates/relayer-types/src/core/ics02_client/client_state.rs index 08c6e5677c..007bc19e17 100644 --- a/crates/relayer-types/src/core/ics02_client/client_state.rs +++ b/crates/relayer-types/src/core/ics02_client/client_state.rs @@ -1,30 +1,16 @@ +use core::fmt::Debug; use std::marker::{Send, Sync}; use std::time::Duration; -use dyn_clone::DynClone; -use erased_serde::Serialize as ErasedSerialize; -use ibc_proto::google::protobuf::Any; -use ibc_proto::protobuf::Protobuf as ErasedProtobuf; - use crate::core::ics02_client::client_type::ClientType; -use crate::core::ics02_client::error::Error; use crate::core::ics24_host::identifier::ChainId; -use crate::dynamic_typing::AsAny; use crate::Height; -use super::consensus_state::ConsensusState; - -pub trait ClientState: - AsAny - + sealed::ErasedPartialEqClientState - + DynClone - + ErasedSerialize - + ErasedProtobuf - + core::fmt::Debug - + Send - + Sync +pub trait ClientState: Clone + Debug + Send + Sync // Any: From, { + type UpgradeOptions; + /// Return the chain identifier which this client is serving (i.e., the client is verifying /// consensus states from this chain). fn chain_id(&self) -> ChainId; @@ -53,65 +39,7 @@ pub trait ClientState: fn upgrade( &mut self, upgrade_height: Height, - upgrade_options: &dyn UpgradeOptions, + upgrade_options: Self::UpgradeOptions, chain_id: ChainId, ); - - /// Convert into a boxed trait object - fn into_box(self) -> Box - where - Self: Sized, - { - Box::new(self) - } -} - -// Implements `Clone` for `Box` -dyn_clone::clone_trait_object!(ClientState); - -// Implements `serde::Serialize` for all types that have ClientState as supertrait -erased_serde::serialize_trait_object!(ClientState); - -impl PartialEq for dyn ClientState { - fn eq(&self, other: &Self) -> bool { - self.eq_client_state(other) - } -} - -// see https://github.com/rust-lang/rust/issues/31740 -impl PartialEq<&Self> for Box { - fn eq(&self, other: &&Self) -> bool { - self.eq_client_state(other.as_ref()) - } -} - -pub fn downcast_client_state(h: &dyn ClientState) -> Option<&CS> { - h.as_any().downcast_ref::() -} - -pub trait UpgradeOptions: AsAny {} - -pub struct UpdatedState { - pub client_state: Box, - pub consensus_state: Box, -} - -mod sealed { - use super::*; - - pub trait ErasedPartialEqClientState { - fn eq_client_state(&self, other: &dyn ClientState) -> bool; - } - - impl ErasedPartialEqClientState for CS - where - CS: ClientState + PartialEq, - { - fn eq_client_state(&self, other: &dyn ClientState) -> bool { - other - .as_any() - .downcast_ref::() - .map_or(false, |h| self == h) - } - } } diff --git a/crates/relayer-types/src/core/ics02_client/consensus_state.rs b/crates/relayer-types/src/core/ics02_client/consensus_state.rs index 2e17d56594..fc544f800d 100644 --- a/crates/relayer-types/src/core/ics02_client/consensus_state.rs +++ b/crates/relayer-types/src/core/ics02_client/consensus_state.rs @@ -1,32 +1,18 @@ -use std::marker::{Send, Sync}; - -use dyn_clone::DynClone; -use erased_serde::Serialize as ErasedSerialize; -use ibc_proto::google::protobuf::Any; -use ibc_proto::protobuf::Protobuf as ErasedProtobuf; +use core::fmt::Debug; +use core::marker::{Send, Sync}; use crate::core::ics02_client::client_type::ClientType; -use crate::core::ics02_client::error::Error; use crate::core::ics23_commitment::commitment::CommitmentRoot; -use crate::dynamic_typing::AsAny; use crate::timestamp::Timestamp; /// Abstract of consensus state information used by the validity predicate /// to verify new commits & state roots. /// /// Users are not expected to implement sealed::ErasedPartialEqConsensusState. -/// Effectively, that trait bound mandates implementors to derive PartialEq, +/// Effectively, that trait bound mandates implementers to derive PartialEq, /// after which our blanket implementation will implement /// `ErasedPartialEqConsensusState` for their type. -pub trait ConsensusState: - AsAny - + sealed::ErasedPartialEqConsensusState - + DynClone - + ErasedSerialize - + ErasedProtobuf - + core::fmt::Debug - + Send - + Sync +pub trait ConsensusState: Clone + Debug + Send + Sync // Any: From, { /// Type of client associated with this consensus state (eg. Tendermint) fn client_type(&self) -> ClientType; @@ -36,55 +22,4 @@ pub trait ConsensusState: /// The timestamp of the consensus state fn timestamp(&self) -> Timestamp; - - /// Convert into a boxed trait object - fn into_box(self) -> Box - where - Self: Sized, - { - Box::new(self) - } -} - -// Implements `Clone` for `Box` -dyn_clone::clone_trait_object!(ConsensusState); - -// Implements `serde::Serialize` for all types that have ConsensusState as supertrait -erased_serde::serialize_trait_object!(ConsensusState); - -pub fn downcast_consensus_state(h: &dyn ConsensusState) -> Option<&CS> { - h.as_any().downcast_ref::() -} - -impl PartialEq for dyn ConsensusState { - fn eq(&self, other: &Self) -> bool { - self.eq_consensus_state(other) - } -} - -// see https://github.com/rust-lang/rust/issues/31740 -impl PartialEq<&Self> for Box { - fn eq(&self, other: &&Self) -> bool { - self.eq_consensus_state(other.as_ref()) - } -} - -mod sealed { - use super::*; - - pub trait ErasedPartialEqConsensusState { - fn eq_consensus_state(&self, other: &dyn ConsensusState) -> bool; - } - - impl ErasedPartialEqConsensusState for CS - where - CS: ConsensusState + PartialEq, - { - fn eq_consensus_state(&self, other: &dyn ConsensusState) -> bool { - other - .as_any() - .downcast_ref::() - .map_or(false, |h| self == h) - } - } } diff --git a/crates/relayer-types/src/core/ics02_client/error.rs b/crates/relayer-types/src/core/ics02_client/error.rs index c01dd19714..094a883aa6 100644 --- a/crates/relayer-types/src/core/ics02_client/error.rs +++ b/crates/relayer-types/src/core/ics02_client/error.rs @@ -1,5 +1,5 @@ use flex_error::{define_error, TraceError}; -use ibc_proto::protobuf::Error as TendermintProtoError; +use tendermint_proto::Error as TendermintProtoError; use crate::core::ics02_client::client_type::ClientType; use crate::core::ics02_client::height::HeightError; @@ -63,6 +63,13 @@ define_error! { { client_state_type: String } | e | { format_args!("unknown client state type: {0}", e.client_state_type) }, + UnexpectedClientStateType + { + expected: String, + got: String, + } + | e | { format_args!("unexpected client state type, expected: {0}, got: {1}", e.expected, e.got) }, + EmptyClientStateResponse | _ | { "the client state was not found" }, @@ -154,7 +161,7 @@ define_error! { InvalidStringAsHeight { value: String } [ HeightError ] - | e | { format_args!("String {0} cannnot be converted to height", e.value) }, + | e | { format_args!("String {0} cannot be converted to height", e.value) }, InvalidHeight | _ | { "revision height cannot be zero" }, @@ -239,7 +246,7 @@ define_error! { update_time: Timestamp, } | e | { - format_args!("header not withing trusting period: expires_at={0} now={1}", e.latest_time, e.update_time) + format_args!("header not within trusting period: expires_at={0} now={1}", e.latest_time, e.update_time) }, MissingLocalConsensusState diff --git a/crates/relayer-types/src/core/ics02_client/events.rs b/crates/relayer-types/src/core/ics02_client/events.rs index 455457fffc..3abe9b7b8d 100644 --- a/crates/relayer-types/src/core/ics02_client/events.rs +++ b/crates/relayer-types/src/core/ics02_client/events.rs @@ -3,8 +3,9 @@ use serde_derive::{Deserialize, Serialize}; use std::fmt::{Display, Error as FmtError, Formatter}; use tendermint::abci; +use tendermint_proto::Protobuf; -use super::header::Header; +use super::header::AnyHeader; use crate::core::ics02_client::client_type::ClientType; use crate::core::ics02_client::height::Height; use crate::core::ics24_host::identifier::ClientId; @@ -135,7 +136,7 @@ impl From for abci::Event { #[derive(Clone, Debug, PartialEq, Serialize)] pub struct UpdateClient { pub common: Attributes, - pub header: Option>, + pub header: Option, } impl UpdateClient { @@ -154,12 +155,7 @@ impl UpdateClient { impl Display for UpdateClient { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { - // TODO Display: Check for a solution for Box - write!( - f, - "UpdateClient {{ common: {}, header: None }}", - self.common - ) + write!(f, "UpdateClient {{ {} }}", self.common) } } @@ -178,13 +174,21 @@ impl From for IbcEvent { } } +fn encode_to_hex_string(header: AnyHeader) -> String { + let buf = header.encode_vec(); + let encoded = subtle_encoding::hex::encode(buf); + String::from_utf8(encoded).expect("hex-encoded string should always be valid UTF-8") +} + impl From for abci::Event { fn from(v: UpdateClient) -> Self { let mut attributes: Vec<_> = v.common.into(); + if let Some(h) = v.header { - let header = (HEADER_ATTRIBUTE_KEY, h.encode_to_hex_string()).into(); + let header = (HEADER_ATTRIBUTE_KEY, encode_to_hex_string(h)).into(); attributes.push(header); } + Self { kind: IbcEventType::UpdateClient.as_str().to_string(), attributes, diff --git a/crates/relayer-types/src/core/ics02_client/header.rs b/crates/relayer-types/src/core/ics02_client/header.rs index da2184d2b9..e238fe1d96 100644 --- a/crates/relayer-types/src/core/ics02_client/header.rs +++ b/crates/relayer-types/src/core/ics02_client/header.rs @@ -1,29 +1,20 @@ -use dyn_clone::DynClone; -use erased_serde::Serialize as ErasedSerialize; +use core::fmt::Debug; + +use serde::{Deserialize, Serialize}; + use ibc_proto::google::protobuf::Any; -use ibc_proto::protobuf::Protobuf as ErasedProtobuf; +use ibc_proto::Protobuf; +use crate::clients::ics07_tendermint::header::{ + decode_header as tm_decode_header, Header as TendermintHeader, TENDERMINT_HEADER_TYPE_URL, +}; use crate::core::ics02_client::client_type::ClientType; use crate::core::ics02_client::error::Error; -use crate::dynamic_typing::AsAny; use crate::timestamp::Timestamp; use crate::Height; /// Abstract of consensus state update information -/// -/// Users are not expected to implement sealed::ErasedPartialEqHeader. -/// Effectively, that trait bound mandates implementors to derive PartialEq, -/// after which our blanket implementation will implement -/// `ErasedPartialEqHeader` for their type. -pub trait Header: - AsAny - + sealed::ErasedPartialEqHeader - + DynClone - + ErasedSerialize - + ErasedProtobuf - + core::fmt::Debug - + Send - + Sync +pub trait Header: Debug + Send + Sync // Any: From, { /// The type of client (eg. Tendermint) fn client_type(&self) -> ClientType; @@ -33,48 +24,77 @@ pub trait Header: /// The timestamp of the consensus state fn timestamp(&self) -> Timestamp; - - /// Convert into a boxed trait object - fn into_box(self) -> Box - where - Self: Sized, - { - Box::new(self) - } } -// Implements `Clone` for `Box` -dyn_clone::clone_trait_object!(Header); +/// Decodes an encoded header into a known `Header` type, +pub fn decode_header(header_bytes: &[u8]) -> Result { + // For now, we only have tendermint; however when there is more than one, we + // can try decoding into all the known types, and return an error only if + // none work + let header: TendermintHeader = + Protobuf::::decode(header_bytes).map_err(Error::invalid_raw_header)?; -// Implements `serde::Serialize` for all types that have Header as supertrait -erased_serde::serialize_trait_object!(Header); + Ok(AnyHeader::Tendermint(header)) +} -pub fn downcast_header(h: &dyn Header) -> Option<&H> { - h.as_any().downcast_ref::() +#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] +#[allow(clippy::large_enum_variant)] +pub enum AnyHeader { + Tendermint(TendermintHeader), } -impl PartialEq for dyn Header { - fn eq(&self, other: &Self) -> bool { - self.eq_header(other) +impl Header for AnyHeader { + fn client_type(&self) -> ClientType { + match self { + Self::Tendermint(header) => header.client_type(), + } + } + + fn height(&self) -> Height { + match self { + Self::Tendermint(header) => header.height(), + } + } + + fn timestamp(&self) -> Timestamp { + match self { + Self::Tendermint(header) => header.timestamp(), + } } } -mod sealed { - use super::*; +impl Protobuf for AnyHeader {} + +impl TryFrom for AnyHeader { + type Error = Error; - pub trait ErasedPartialEqHeader { - fn eq_header(&self, other: &dyn Header) -> bool; + fn try_from(raw: Any) -> Result { + match raw.type_url.as_str() { + TENDERMINT_HEADER_TYPE_URL => { + let val = tm_decode_header(raw.value.as_slice())?; + Ok(AnyHeader::Tendermint(val)) + } + + _ => Err(Error::unknown_header_type(raw.type_url)), + } } +} + +impl From for Any { + fn from(value: AnyHeader) -> Self { + use ibc_proto::ibc::lightclients::tendermint::v1::Header as RawHeader; - impl ErasedPartialEqHeader for H - where - H: Header + PartialEq, - { - fn eq_header(&self, other: &dyn Header) -> bool { - other - .as_any() - .downcast_ref::() - .map_or(false, |h| self == h) + match value { + AnyHeader::Tendermint(header) => Any { + type_url: TENDERMINT_HEADER_TYPE_URL.to_string(), + value: Protobuf::::encode_vec(header), + }, } } } + +impl From for AnyHeader { + fn from(header: TendermintHeader) -> Self { + Self::Tendermint(header) + } +} diff --git a/crates/relayer-types/src/core/ics02_client/height.rs b/crates/relayer-types/src/core/ics02_client/height.rs index fb4c9c0f85..4563333244 100644 --- a/crates/relayer-types/src/core/ics02_client/height.rs +++ b/crates/relayer-types/src/core/ics02_client/height.rs @@ -3,7 +3,7 @@ use std::num::ParseIntError; use std::str::FromStr; use flex_error::{define_error, TraceError}; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use serde_derive::{Deserialize, Serialize}; use ibc_proto::ibc::core::client::v1::Height as RawHeight; diff --git a/crates/relayer-types/src/core/ics02_client/misbehaviour.rs b/crates/relayer-types/src/core/ics02_client/misbehaviour.rs index 2905ab8a68..21b296ec29 100644 --- a/crates/relayer-types/src/core/ics02_client/misbehaviour.rs +++ b/crates/relayer-types/src/core/ics02_client/misbehaviour.rs @@ -1,44 +1,12 @@ -use dyn_clone::DynClone; - -use crate::dynamic_typing::AsAny; +use core::fmt::Debug; use crate::core::ics24_host::identifier::ClientId; use crate::Height; -pub trait Misbehaviour: - AsAny + sealed::ErasedPartialEqMisbehaviour + DynClone + core::fmt::Debug + Send + Sync -{ +pub trait Misbehaviour: Clone + Debug + Send + Sync { /// The type of client (eg. Tendermint) fn client_id(&self) -> &ClientId; /// The height of the consensus state fn height(&self) -> Height; } - -// Implements `Clone` for `Box` -dyn_clone::clone_trait_object!(Misbehaviour); - -impl PartialEq for dyn Misbehaviour { - fn eq(&self, other: &Self) -> bool { - self.eq_misbehaviour(other) - } -} -mod sealed { - use super::*; - - pub trait ErasedPartialEqMisbehaviour { - fn eq_misbehaviour(&self, other: &dyn Misbehaviour) -> bool; - } - - impl ErasedPartialEqMisbehaviour for H - where - H: Misbehaviour + PartialEq, - { - fn eq_misbehaviour(&self, other: &dyn Misbehaviour) -> bool { - other - .as_any() - .downcast_ref::() - .map_or(false, |h| self == h) - } - } -} diff --git a/crates/relayer-types/src/core/ics02_client/msgs/create_client.rs b/crates/relayer-types/src/core/ics02_client/msgs/create_client.rs index 8e94a1af1c..078bce2d31 100644 --- a/crates/relayer-types/src/core/ics02_client/msgs/create_client.rs +++ b/crates/relayer-types/src/core/ics02_client/msgs/create_client.rs @@ -2,7 +2,7 @@ use ibc_proto::google::protobuf::Any; use ibc_proto::ibc::core::client::v1::MsgCreateClient as RawMsgCreateClient; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use crate::core::ics02_client::error::Error; use crate::signer::Signer; @@ -95,7 +95,7 @@ mod tests { let msg = MsgCreateClient::new( tm_client_state, - TmConsensusState::try_from(tm_header).unwrap().into(), + TmConsensusState::from(tm_header).into(), signer, ) .unwrap(); diff --git a/crates/relayer-types/src/core/ics02_client/msgs/misbehaviour.rs b/crates/relayer-types/src/core/ics02_client/msgs/misbehaviour.rs index 707ffe01cb..ae7156a834 100644 --- a/crates/relayer-types/src/core/ics02_client/msgs/misbehaviour.rs +++ b/crates/relayer-types/src/core/ics02_client/msgs/misbehaviour.rs @@ -1,6 +1,6 @@ use ibc_proto::google::protobuf::Any as ProtoAny; use ibc_proto::ibc::core::client::v1::MsgSubmitMisbehaviour as RawMsgSubmitMisbehaviour; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use crate::core::ics02_client::error::Error; use crate::core::ics24_host::identifier::ClientId; @@ -38,27 +38,25 @@ impl Protobuf for MsgSubmitMisbehaviour {} impl TryFrom for MsgSubmitMisbehaviour { type Error = Error; - // NOTE: The `MsgSubmitMisbehaviour` message is has been deprecated in IBC-Go v7 in favor of a + // NOTE: The `MsgSubmitMisbehaviour` message has been deprecated in IBC-Go v7 in favor of a // regular `MsgUpdateClient`, but will keep working for the foreseeable future. #[allow(deprecated)] fn try_from(raw: RawMsgSubmitMisbehaviour) -> Result { - let raw_misbehaviour = raw - .misbehaviour - .ok_or_else(Error::missing_raw_misbehaviour)?; - Ok(MsgSubmitMisbehaviour { client_id: raw .client_id .parse() .map_err(Error::invalid_raw_misbehaviour)?, - misbehaviour: raw_misbehaviour, + misbehaviour: raw + .misbehaviour + .ok_or_else(Error::missing_raw_misbehaviour)?, signer: raw.signer.parse().map_err(Error::signer)?, }) } } impl From for RawMsgSubmitMisbehaviour { - // NOTE: The `MsgSubmitMisbehaviour` message is has been deprecated in IBC-Go v7 in favor of a + // NOTE: The `MsgSubmitMisbehaviour` message has been deprecated in IBC-Go v7 in favor of a // regular `MsgUpdateClient`, but will keep working for the foreseeable future. #[allow(deprecated)] fn from(ics_msg: MsgSubmitMisbehaviour) -> Self { diff --git a/crates/relayer-types/src/core/ics02_client/msgs/update_client.rs b/crates/relayer-types/src/core/ics02_client/msgs/update_client.rs index 5ab3fef364..e5966b7b7c 100644 --- a/crates/relayer-types/src/core/ics02_client/msgs/update_client.rs +++ b/crates/relayer-types/src/core/ics02_client/msgs/update_client.rs @@ -2,7 +2,7 @@ use ibc_proto::google::protobuf::Any; use ibc_proto::ibc::core::client::v1::MsgUpdateClient as RawMsgUpdateClient; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use crate::core::ics02_client::error::Error; use crate::core::ics24_host::error::ValidationError; diff --git a/crates/relayer-types/src/core/ics02_client/msgs/upgrade_client.rs b/crates/relayer-types/src/core/ics02_client/msgs/upgrade_client.rs index 63cd606a41..20fcf6ccc3 100644 --- a/crates/relayer-types/src/core/ics02_client/msgs/upgrade_client.rs +++ b/crates/relayer-types/src/core/ics02_client/msgs/upgrade_client.rs @@ -5,7 +5,7 @@ use std::str::FromStr; use ibc_proto::google::protobuf::Any; use ibc_proto::ibc::core::client::v1::MsgUpgradeClient as RawMsgUpgradeClient; use ibc_proto::ibc::core::commitment::v1::MerkleProof as RawMerkleProof; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use crate::core::ics02_client::error::Error; use crate::core::ics23_commitment::commitment::CommitmentProofBytes; diff --git a/crates/relayer-types/src/core/ics02_client/trust_threshold.rs b/crates/relayer-types/src/core/ics02_client/trust_threshold.rs index 73444f4651..b2183c6f98 100644 --- a/crates/relayer-types/src/core/ics02_client/trust_threshold.rs +++ b/crates/relayer-types/src/core/ics02_client/trust_threshold.rs @@ -5,7 +5,7 @@ use std::convert::TryFrom; use std::fmt::{Display, Error as FmtError, Formatter}; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use num_rational::Ratio; use serde::{Deserialize, Serialize}; diff --git a/crates/relayer-types/src/core/ics03_connection/connection.rs b/crates/relayer-types/src/core/ics03_connection/connection.rs index a73a692949..d240eaf905 100644 --- a/crates/relayer-types/src/core/ics03_connection/connection.rs +++ b/crates/relayer-types/src/core/ics03_connection/connection.rs @@ -5,7 +5,7 @@ use std::{ u64, }; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use serde::{Deserialize, Serialize}; use ibc_proto::ibc::core::connection::v1::{ @@ -241,9 +241,9 @@ impl ConnectionEnd { #[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Counterparty { - client_id: ClientId, + pub client_id: ClientId, pub connection_id: Option, - prefix: CommitmentPrefix, + pub prefix: CommitmentPrefix, } impl Protobuf for Counterparty {} diff --git a/crates/relayer-types/src/core/ics03_connection/error.rs b/crates/relayer-types/src/core/ics03_connection/error.rs index 619f14b2e1..068b3ee30a 100644 --- a/crates/relayer-types/src/core/ics03_connection/error.rs +++ b/crates/relayer-types/src/core/ics03_connection/error.rs @@ -90,7 +90,7 @@ define_error! { VerifyConnectionState [ client_error::Error ] - | _ | { "error verifying connnection state" }, + | _ | { "error verifying connection state" }, Signer [ SignerError ] diff --git a/crates/relayer-types/src/core/ics03_connection/msgs/conn_open_ack.rs b/crates/relayer-types/src/core/ics03_connection/msgs/conn_open_ack.rs index 72798ecc2a..ff8f03028b 100644 --- a/crates/relayer-types/src/core/ics03_connection/msgs/conn_open_ack.rs +++ b/crates/relayer-types/src/core/ics03_connection/msgs/conn_open_ack.rs @@ -1,6 +1,6 @@ use ibc_proto::google::protobuf::Any; use ibc_proto::ibc::core::connection::v1::MsgConnectionOpenAck as RawMsgConnectionOpenAck; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use crate::core::ics03_connection::error::Error; use crate::core::ics03_connection::version::Version; diff --git a/crates/relayer-types/src/core/ics03_connection/msgs/conn_open_confirm.rs b/crates/relayer-types/src/core/ics03_connection/msgs/conn_open_confirm.rs index ae20b9bd5f..c7b86b4b43 100644 --- a/crates/relayer-types/src/core/ics03_connection/msgs/conn_open_confirm.rs +++ b/crates/relayer-types/src/core/ics03_connection/msgs/conn_open_confirm.rs @@ -1,4 +1,4 @@ -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use ibc_proto::ibc::core::connection::v1::MsgConnectionOpenConfirm as RawMsgConnectionOpenConfirm; diff --git a/crates/relayer-types/src/core/ics03_connection/msgs/conn_open_init.rs b/crates/relayer-types/src/core/ics03_connection/msgs/conn_open_init.rs index 0e1cb7fe3c..4bdc6db6c2 100644 --- a/crates/relayer-types/src/core/ics03_connection/msgs/conn_open_init.rs +++ b/crates/relayer-types/src/core/ics03_connection/msgs/conn_open_init.rs @@ -1,7 +1,7 @@ use std::time::Duration; use ibc_proto::ibc::core::connection::v1::MsgConnectionOpenInit as RawMsgConnectionOpenInit; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use crate::core::ics03_connection::connection::Counterparty; use crate::core::ics03_connection::error::Error; diff --git a/crates/relayer-types/src/core/ics03_connection/msgs/conn_open_try.rs b/crates/relayer-types/src/core/ics03_connection/msgs/conn_open_try.rs index 2915ff87bd..8cebee431b 100644 --- a/crates/relayer-types/src/core/ics03_connection/msgs/conn_open_try.rs +++ b/crates/relayer-types/src/core/ics03_connection/msgs/conn_open_try.rs @@ -6,7 +6,7 @@ use std::{ use ibc_proto::google::protobuf::Any; use ibc_proto::ibc::core::connection::v1::MsgConnectionOpenTry as RawMsgConnectionOpenTry; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use crate::core::ics03_connection::connection::Counterparty; use crate::core::ics03_connection::error::Error; diff --git a/crates/relayer-types/src/core/ics03_connection/version.rs b/crates/relayer-types/src/core/ics03_connection/version.rs index 5e747575d2..108665d80e 100644 --- a/crates/relayer-types/src/core/ics03_connection/version.rs +++ b/crates/relayer-types/src/core/ics03_connection/version.rs @@ -3,7 +3,7 @@ use std::fmt::Display; use crate::utils::pretty::PrettySlice; use ibc_proto::ibc::core::connection::v1::Version as RawVersion; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use serde::{Deserialize, Serialize}; use crate::core::ics03_connection::error::Error; @@ -19,7 +19,7 @@ pub struct Version { } impl Version { - /// Checks whether or not the given feature is supported in this versin + /// Checks whether or not the given feature is supported in this version pub fn is_supported_feature(&self, feature: String) -> bool { self.features.contains(&feature) } diff --git a/crates/relayer-types/src/core/ics04_channel/channel.rs b/crates/relayer-types/src/core/ics04_channel/channel.rs index dc57f69893..0205e2998a 100644 --- a/crates/relayer-types/src/core/ics04_channel/channel.rs +++ b/crates/relayer-types/src/core/ics04_channel/channel.rs @@ -3,7 +3,7 @@ use crate::utils::pretty::PrettySlice; use std::fmt::{Display, Error as FmtError, Formatter}; use std::str::FromStr; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use serde::{Deserialize, Serialize}; use ibc_proto::ibc::core::channel::v1::{ diff --git a/crates/relayer-types/src/core/ics04_channel/error.rs b/crates/relayer-types/src/core/ics04_channel/error.rs index ce07b27fca..817f0337f8 100644 --- a/crates/relayer-types/src/core/ics04_channel/error.rs +++ b/crates/relayer-types/src/core/ics04_channel/error.rs @@ -12,7 +12,7 @@ use crate::timestamp::Timestamp; use crate::Height; use flex_error::{define_error, TraceError}; -use ibc_proto::protobuf::Error as TendermintError; +use tendermint_proto::Error as TendermintError; define_error! { #[derive(Debug, PartialEq, Eq)] @@ -100,7 +100,7 @@ define_error! { | _ | { "missing channel end" }, InvalidVersionLengthConnection - | _ | { "single version must be negociated on connection before opening channel" }, + | _ | { "single version must be negotiated on connection before opening channel" }, ChannelFeatureNotSuportedByConnection | _ | { "the channel ordering is not supported by connection" }, diff --git a/crates/relayer-types/src/core/ics04_channel/msgs/acknowledgement.rs b/crates/relayer-types/src/core/ics04_channel/msgs/acknowledgement.rs index 3bb054f8cb..421342837d 100644 --- a/crates/relayer-types/src/core/ics04_channel/msgs/acknowledgement.rs +++ b/crates/relayer-types/src/core/ics04_channel/msgs/acknowledgement.rs @@ -1,6 +1,6 @@ use derive_more::{From, Into}; use ibc_proto::ibc::core::channel::v1::MsgAcknowledgement as RawMsgAcknowledgement; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use crate::core::ics04_channel::error::Error; use crate::core::ics04_channel::packet::Packet; diff --git a/crates/relayer-types/src/core/ics04_channel/msgs/chan_close_confirm.rs b/crates/relayer-types/src/core/ics04_channel/msgs/chan_close_confirm.rs index 9102a104a5..e29872320d 100644 --- a/crates/relayer-types/src/core/ics04_channel/msgs/chan_close_confirm.rs +++ b/crates/relayer-types/src/core/ics04_channel/msgs/chan_close_confirm.rs @@ -1,4 +1,4 @@ -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use ibc_proto::ibc::core::channel::v1::MsgChannelCloseConfirm as RawMsgChannelCloseConfirm; diff --git a/crates/relayer-types/src/core/ics04_channel/msgs/chan_close_init.rs b/crates/relayer-types/src/core/ics04_channel/msgs/chan_close_init.rs index 49f5208795..9e249d6137 100644 --- a/crates/relayer-types/src/core/ics04_channel/msgs/chan_close_init.rs +++ b/crates/relayer-types/src/core/ics04_channel/msgs/chan_close_init.rs @@ -1,4 +1,4 @@ -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use ibc_proto::ibc::core::channel::v1::MsgChannelCloseInit as RawMsgChannelCloseInit; diff --git a/crates/relayer-types/src/core/ics04_channel/msgs/chan_open_ack.rs b/crates/relayer-types/src/core/ics04_channel/msgs/chan_open_ack.rs index 7409775097..895ff7d204 100644 --- a/crates/relayer-types/src/core/ics04_channel/msgs/chan_open_ack.rs +++ b/crates/relayer-types/src/core/ics04_channel/msgs/chan_open_ack.rs @@ -7,7 +7,7 @@ use crate::signer::Signer; use crate::tx_msg::Msg; use ibc_proto::ibc::core::channel::v1::MsgChannelOpenAck as RawMsgChannelOpenAck; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; pub const TYPE_URL: &str = "/ibc.core.channel.v1.MsgChannelOpenAck"; diff --git a/crates/relayer-types/src/core/ics04_channel/msgs/chan_open_confirm.rs b/crates/relayer-types/src/core/ics04_channel/msgs/chan_open_confirm.rs index 6a29096945..627f320698 100644 --- a/crates/relayer-types/src/core/ics04_channel/msgs/chan_open_confirm.rs +++ b/crates/relayer-types/src/core/ics04_channel/msgs/chan_open_confirm.rs @@ -6,7 +6,7 @@ use crate::signer::Signer; use crate::tx_msg::Msg; use ibc_proto::ibc::core::channel::v1::MsgChannelOpenConfirm as RawMsgChannelOpenConfirm; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; pub const TYPE_URL: &str = "/ibc.core.channel.v1.MsgChannelOpenConfirm"; diff --git a/crates/relayer-types/src/core/ics04_channel/msgs/chan_open_init.rs b/crates/relayer-types/src/core/ics04_channel/msgs/chan_open_init.rs index 4b1920e72e..8128674f24 100644 --- a/crates/relayer-types/src/core/ics04_channel/msgs/chan_open_init.rs +++ b/crates/relayer-types/src/core/ics04_channel/msgs/chan_open_init.rs @@ -6,7 +6,7 @@ use crate::signer::Signer; use crate::tx_msg::Msg; use ibc_proto::ibc::core::channel::v1::MsgChannelOpenInit as RawMsgChannelOpenInit; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; pub const TYPE_URL: &str = "/ibc.core.channel.v1.MsgChannelOpenInit"; diff --git a/crates/relayer-types/src/core/ics04_channel/msgs/chan_open_try.rs b/crates/relayer-types/src/core/ics04_channel/msgs/chan_open_try.rs index c9b65c6772..597204e5ec 100644 --- a/crates/relayer-types/src/core/ics04_channel/msgs/chan_open_try.rs +++ b/crates/relayer-types/src/core/ics04_channel/msgs/chan_open_try.rs @@ -9,7 +9,7 @@ use crate::signer::Signer; use crate::tx_msg::Msg; use ibc_proto::ibc::core::channel::v1::MsgChannelOpenTry as RawMsgChannelOpenTry; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use core::str::FromStr; diff --git a/crates/relayer-types/src/core/ics04_channel/msgs/recv_packet.rs b/crates/relayer-types/src/core/ics04_channel/msgs/recv_packet.rs index 24d0b587ee..6d3472c4ef 100644 --- a/crates/relayer-types/src/core/ics04_channel/msgs/recv_packet.rs +++ b/crates/relayer-types/src/core/ics04_channel/msgs/recv_packet.rs @@ -1,4 +1,4 @@ -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use ibc_proto::ibc::core::channel::v1::MsgRecvPacket as RawMsgRecvPacket; diff --git a/crates/relayer-types/src/core/ics04_channel/msgs/timeout.rs b/crates/relayer-types/src/core/ics04_channel/msgs/timeout.rs index 0c8f2cc620..7407bb9908 100644 --- a/crates/relayer-types/src/core/ics04_channel/msgs/timeout.rs +++ b/crates/relayer-types/src/core/ics04_channel/msgs/timeout.rs @@ -1,4 +1,4 @@ -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use ibc_proto::ibc::core::channel::v1::MsgTimeout as RawMsgTimeout; diff --git a/crates/relayer-types/src/core/ics04_channel/msgs/timeout_on_close.rs b/crates/relayer-types/src/core/ics04_channel/msgs/timeout_on_close.rs index e4d39f956a..8d6fc5e970 100644 --- a/crates/relayer-types/src/core/ics04_channel/msgs/timeout_on_close.rs +++ b/crates/relayer-types/src/core/ics04_channel/msgs/timeout_on_close.rs @@ -1,5 +1,5 @@ use ibc_proto::ibc::core::channel::v1::MsgTimeoutOnClose as RawMsgTimeoutOnClose; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use crate::core::ics04_channel::error::Error; use crate::core::ics04_channel::packet::{Packet, Sequence}; diff --git a/crates/relayer-types/src/core/ics04_channel/timeout.rs b/crates/relayer-types/src/core/ics04_channel/timeout.rs index 076505ed49..aa33ec23b1 100644 --- a/crates/relayer-types/src/core/ics04_channel/timeout.rs +++ b/crates/relayer-types/src/core/ics04_channel/timeout.rs @@ -43,7 +43,7 @@ impl TimeoutHeight { } } - /// Check if a height is *stricly past* the timeout height, and thus is + /// Check if a height is *strictly past* the timeout height, and thus is /// deemed expired. pub fn has_expired(&self, height: Height) -> bool { match self { diff --git a/crates/relayer-types/src/core/ics23_commitment/merkle.rs b/crates/relayer-types/src/core/ics23_commitment/merkle.rs index 603374812e..64704c8bb2 100644 --- a/crates/relayer-types/src/core/ics23_commitment/merkle.rs +++ b/crates/relayer-types/src/core/ics23_commitment/merkle.rs @@ -138,8 +138,13 @@ impl MerkleProof { } // verify the absence of key in lowest subtree - let proof = self.proofs.get(0).ok_or_else(Error::invalid_merkle_proof)?; - let spec = ics23_specs.get(0).ok_or_else(Error::invalid_merkle_proof)?; + let proof = self + .proofs + .first() + .ok_or_else(Error::invalid_merkle_proof)?; + let spec = ics23_specs + .first() + .ok_or_else(Error::invalid_merkle_proof)?; // keys are represented from root-to-leaf let key = keys .key_path @@ -182,7 +187,7 @@ fn calculate_non_existence_root(proof: &NonExistenceProof) -> Result, Er // Merkle Proof serialization notes: // "Proof" id currently defined in a number of forms and included in a number of places // - TmProof: in tendermint-rs/src/merkle/proof.rs:Proof -// - RawProofOps: in tendermint-proto/tendermint.cyrpto.rs:ProofOps +// - RawProofOps: in tendermint-proto/tendermint.crypto.rs:ProofOps // - RawMerkleProof: in ibc-proto/ibc.core.commitment.v1.rs:MerkleProof // - structure that includes a RawProofOps in its only `proof` field. // #[derive(Clone, PartialEq, ::prost::Message)] diff --git a/crates/relayer-types/src/core/ics24_host/identifier.rs b/crates/relayer-types/src/core/ics24_host/identifier.rs index 0405c50b2d..e96bebfb01 100644 --- a/crates/relayer-types/src/core/ics24_host/identifier.rs +++ b/crates/relayer-types/src/core/ics24_host/identifier.rs @@ -304,6 +304,14 @@ impl PortId { Self("transfer".to_string()) } + pub fn oracle() -> Self { + Self("oracle".to_string()) + } + + pub fn icqhost() -> Self { + Self("icqhost".to_string()) + } + /// Get this identifier as a borrowed `&str` pub fn as_str(&self) -> &str { &self.0 diff --git a/crates/relayer-types/src/core/ics26_routing/error.rs b/crates/relayer-types/src/core/ics26_routing/error.rs index 5687860cf4..f51581b6e0 100644 --- a/crates/relayer-types/src/core/ics26_routing/error.rs +++ b/crates/relayer-types/src/core/ics26_routing/error.rs @@ -29,7 +29,7 @@ define_error! { | e | { format_args!("unknown type URL {0}", e.url) }, MalformedMessageBytes - [ TraceError ] + [ TraceError ] | _ | { "the message is malformed and cannot be decoded" }, } } diff --git a/crates/relayer-types/src/core/ics26_routing/msgs.rs b/crates/relayer-types/src/core/ics26_routing/msgs.rs index c6c7d72bda..68864ce23e 100644 --- a/crates/relayer-types/src/core/ics26_routing/msgs.rs +++ b/crates/relayer-types/src/core/ics26_routing/msgs.rs @@ -9,7 +9,7 @@ use crate::core::ics04_channel::msgs::{ chan_open_init, chan_open_try, recv_packet, timeout, timeout_on_close, ChannelMsg, PacketMsg, }; use crate::core::ics26_routing::error::Error; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; /// Enumeration of all messages that the local ICS26 module is capable of routing. #[derive(Clone, Debug)] diff --git a/crates/relayer-types/src/dynamic_typing.rs b/crates/relayer-types/src/dynamic_typing.rs deleted file mode 100644 index 7385b04ff5..0000000000 --- a/crates/relayer-types/src/dynamic_typing.rs +++ /dev/null @@ -1,11 +0,0 @@ -use std::any::Any; - -pub trait AsAny: Any { - fn as_any(&self) -> &dyn Any; -} - -impl AsAny for M { - fn as_any(&self) -> &dyn Any { - self - } -} diff --git a/crates/relayer-types/src/lib.rs b/crates/relayer-types/src/lib.rs index 33ef64cdf3..7684e0b41a 100644 --- a/crates/relayer-types/src/lib.rs +++ b/crates/relayer-types/src/lib.rs @@ -47,13 +47,11 @@ pub mod applications; pub mod bigint; pub mod clients; pub mod core; -pub mod dynamic_typing; pub mod events; pub mod handler; pub mod keys; pub mod macros; pub mod proofs; -pub mod relayer; pub mod signer; pub mod timestamp; pub mod tx_msg; diff --git a/crates/relayer-types/src/mock/client_state.rs b/crates/relayer-types/src/mock/client_state.rs index c4fb000f37..c4081ab3bf 100644 --- a/crates/relayer-types/src/mock/client_state.rs +++ b/crates/relayer-types/src/mock/client_state.rs @@ -1,15 +1,13 @@ -use std::collections::HashMap; use std::time::Duration; use serde::{Deserialize, Serialize}; use ibc_proto::google::protobuf::Any; use ibc_proto::ibc::mock::ClientState as RawMockClientState; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; -use crate::core::ics02_client::client_state::{ClientState, UpgradeOptions}; +use crate::core::ics02_client::client_state::ClientState; use crate::core::ics02_client::client_type::ClientType; -use crate::core::ics02_client::consensus_state::ConsensusState; use crate::core::ics02_client::error::Error; use crate::core::ics24_host::identifier::ChainId; @@ -21,20 +19,6 @@ use crate::Height; pub const MOCK_CLIENT_STATE_TYPE_URL: &str = "/ibc.mock.ClientState"; -/// A mock of an IBC client record as it is stored in a mock context. -/// For testing ICS02 handlers mostly, cf. `MockClientContext`. -#[derive(Clone, Debug)] -pub struct MockClientRecord { - /// The type of this client. - pub client_type: ClientType, - - /// The client state (representing only the latest height at the moment). - pub client_state: Option>, - - /// Mapping of heights to consensus states for this client. - pub consensus_states: HashMap>, -} - /// A mock of a client state. For an example of a real structure that this mocks, you can see /// `ClientState` of ics07_tendermint/client_state.rs. #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -97,7 +81,10 @@ impl TryFrom for MockClientState { MOCK_CLIENT_STATE_TYPE_URL => { decode_client_state(raw.value.deref()).map_err(Into::into) } - _ => Err(Error::unknown_client_state_type(raw.type_url)), + _ => Err(Error::unexpected_client_state_type( + MOCK_CLIENT_STATE_TYPE_URL.to_string(), + raw.type_url, + )), } } } @@ -106,12 +93,14 @@ impl From for Any { fn from(client_state: MockClientState) -> Self { Any { type_url: MOCK_CLIENT_STATE_TYPE_URL.to_string(), - value: Protobuf::::encode_vec(&client_state), + value: Protobuf::::encode_vec(client_state), } } } impl ClientState for MockClientState { + type UpgradeOptions = (); + fn chain_id(&self) -> ChainId { unimplemented!() } @@ -128,12 +117,7 @@ impl ClientState for MockClientState { self.frozen_height } - fn upgrade( - &mut self, - _upgrade_height: Height, - _upgrade_options: &dyn UpgradeOptions, - _chain_id: ChainId, - ) { + fn upgrade(&mut self, _upgrade_height: Height, _upgrade_options: (), _chain_id: ChainId) { unimplemented!() } diff --git a/crates/relayer-types/src/mock/consensus_state.rs b/crates/relayer-types/src/mock/consensus_state.rs index 5ee4ab94f6..0237d50074 100644 --- a/crates/relayer-types/src/mock/consensus_state.rs +++ b/crates/relayer-types/src/mock/consensus_state.rs @@ -1,6 +1,6 @@ use ibc_proto::google::protobuf::Any; use ibc_proto::ibc::mock::ConsensusState as RawMockConsensusState; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use serde::{Deserialize, Serialize}; use crate::core::ics02_client::client_type::ClientType; @@ -86,7 +86,7 @@ impl From for Any { fn from(consensus_state: MockConsensusState) -> Self { Any { type_url: MOCK_CONSENSUS_STATE_TYPE_URL.to_string(), - value: Protobuf::::encode_vec(&consensus_state), + value: Protobuf::::encode_vec(consensus_state), } } } diff --git a/crates/relayer-types/src/mock/header.rs b/crates/relayer-types/src/mock/header.rs index a3e4189621..2f5c931201 100644 --- a/crates/relayer-types/src/mock/header.rs +++ b/crates/relayer-types/src/mock/header.rs @@ -2,7 +2,7 @@ use std::fmt::{Display, Error as FmtError, Formatter}; use ibc_proto::google::protobuf::Any; use ibc_proto::ibc::mock::Header as RawMockHeader; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use serde_derive::{Deserialize, Serialize}; use crate::core::ics02_client::client_type::ClientType; @@ -114,7 +114,7 @@ impl From for Any { fn from(header: MockHeader) -> Self { Any { type_url: MOCK_HEADER_TYPE_URL.to_string(), - value: Protobuf::::encode_vec(&header), + value: Protobuf::::encode_vec(header), } } } @@ -122,12 +122,12 @@ impl From for Any { #[cfg(test)] mod tests { use super::*; - use ibc_proto::protobuf::Protobuf; + use ibc_proto::Protobuf; #[test] fn encode_any() { let header = MockHeader::new(Height::new(1, 10).unwrap()).with_timestamp(Timestamp::none()); - let bytes = >::encode_vec(&header); + let bytes = >::encode_vec(header); assert_eq!( &bytes, diff --git a/crates/relayer-types/src/mock/host.rs b/crates/relayer-types/src/mock/host.rs deleted file mode 100644 index 631af7499e..0000000000 --- a/crates/relayer-types/src/mock/host.rs +++ /dev/null @@ -1,192 +0,0 @@ -//! Host chain types and methods, used by context mock. - -use ibc_proto::google::protobuf::Any; -use ibc_proto::ibc::lightclients::tendermint::v1::Header as RawHeader; -use ibc_proto::protobuf::Protobuf as ErasedProtobuf; -use serde::Serialize; -use tendermint::block::Header as TmHeader; -use tendermint_testgen::light_block::TmLightBlock; -use tendermint_testgen::{Generator, LightBlock as TestgenLightBlock}; - -use crate::clients::ics07_tendermint::consensus_state::ConsensusState as TMConsensusState; -use crate::clients::ics07_tendermint::header::TENDERMINT_HEADER_TYPE_URL; -use crate::core::ics02_client::client_type::ClientType; -use crate::core::ics02_client::consensus_state::ConsensusState; -use crate::core::ics02_client::error::Error; -use crate::core::ics02_client::header::Header; -use crate::core::ics24_host::identifier::ChainId; -use crate::mock::consensus_state::MockConsensusState; -use crate::mock::header::MockHeader; - -use crate::timestamp::Timestamp; -use crate::Height; - -/// Defines the different types of host chains that a mock context can emulate. -/// The variants are as follows: -/// - `Mock` defines that the context history consists of `MockHeader` blocks. -/// - `SyntheticTendermint`: the context has synthetically-generated Tendermint (light) blocks. -/// See also the `HostBlock` enum to get more insights into the underlying block type. -#[derive(Clone, Debug, Copy)] -pub enum HostType { - Mock, - SyntheticTendermint, -} - -#[derive(Clone, Debug, PartialEq, Eq, Serialize)] -pub struct SyntheticTmBlock { - pub trusted_height: Height, - pub light_block: TmLightBlock, -} - -impl SyntheticTmBlock { - pub fn header(&self) -> &TmHeader { - &self.light_block.signed_header.header - } -} - -/// Depending on `HostType` (the type of host chain underlying a context mock), this enum defines -/// the type of blocks composing the history of the host chain. -#[derive(Clone, Debug, PartialEq, Eq, Serialize)] -pub enum HostBlock { - Mock(MockHeader), - SyntheticTendermint(SyntheticTmBlock), -} - -impl HostBlock { - /// Returns the height of a block. - pub fn height(&self) -> Height { - match self { - HostBlock::Mock(header) => header.height(), - HostBlock::SyntheticTendermint(light_block) => Height::new( - ChainId::chain_version(light_block.header().chain_id.as_str()), - light_block.header().height.value(), - ) - .unwrap(), - } - } - - pub fn set_trusted_height(&mut self, height: Height) { - match self { - HostBlock::Mock(_) => {} - HostBlock::SyntheticTendermint(light_block) => light_block.trusted_height = height, - } - } - - /// Returns the timestamp of a block. - pub fn timestamp(&self) -> Timestamp { - match self { - HostBlock::Mock(header) => header.timestamp, - HostBlock::SyntheticTendermint(light_block) => light_block.header().time.into(), - } - } - - /// Generates a new block at `height` for the given chain identifier and chain type. - pub fn generate_block( - chain_id: ChainId, - chain_type: HostType, - height: u64, - timestamp: Timestamp, - ) -> HostBlock { - match chain_type { - HostType::Mock => HostBlock::Mock(MockHeader { - height: Height::new(chain_id.version(), height).unwrap(), - timestamp, - }), - HostType::SyntheticTendermint => { - HostBlock::SyntheticTendermint(Self::generate_tm_block(chain_id, height, timestamp)) - } - } - } - - pub fn generate_tm_block( - chain_id: ChainId, - height: u64, - timestamp: Timestamp, - ) -> SyntheticTmBlock { - let light_block = TestgenLightBlock::new_default_with_time_and_chain_id( - chain_id.to_string(), - timestamp.into_tm_time().unwrap(), - height, - ) - .generate() - .unwrap(); - SyntheticTmBlock { - trusted_height: Height::new(chain_id.version(), 1).unwrap(), - light_block, - } - } -} - -impl From for Box { - fn from(light_block: SyntheticTmBlock) -> Self { - let cs = TMConsensusState::from(light_block.header().clone()); - cs.into_box() - } -} - -impl From for Box { - fn from(any_block: HostBlock) -> Self { - match any_block { - HostBlock::Mock(mock_header) => MockConsensusState::new(mock_header).into_box(), - HostBlock::SyntheticTendermint(light_block) => { - TMConsensusState::from(light_block.header().clone()).into_box() - } - } - } -} - -impl ErasedProtobuf for HostBlock {} - -impl TryFrom for HostBlock { - type Error = Error; - - fn try_from(_raw: Any) -> Result { - todo!() - } -} - -impl From for Any { - fn from(value: HostBlock) -> Self { - fn encode_light_block(light_block: SyntheticTmBlock) -> Vec { - use prost::Message; - - let SyntheticTmBlock { - trusted_height, - light_block, - } = light_block; - - RawHeader { - signed_header: Some(light_block.signed_header.into()), - validator_set: Some(light_block.validators.into()), - trusted_height: Some(trusted_height.into()), - trusted_validators: Some(light_block.next_validators.into()), - } - .encode_to_vec() - } - - match value { - HostBlock::Mock(mock_header) => mock_header.into(), - HostBlock::SyntheticTendermint(light_block_box) => Self { - type_url: TENDERMINT_HEADER_TYPE_URL.to_string(), - value: encode_light_block(light_block_box), - }, - } - } -} - -impl Header for HostBlock { - fn client_type(&self) -> ClientType { - match self { - HostBlock::Mock(_) => ClientType::Mock, - HostBlock::SyntheticTendermint(_) => ClientType::Tendermint, - } - } - - fn height(&self) -> Height { - HostBlock::height(self) - } - - fn timestamp(&self) -> Timestamp { - HostBlock::timestamp(self) - } -} diff --git a/crates/relayer-types/src/mock/misbehaviour.rs b/crates/relayer-types/src/mock/misbehaviour.rs index 418c187251..17e303940c 100644 --- a/crates/relayer-types/src/mock/misbehaviour.rs +++ b/crates/relayer-types/src/mock/misbehaviour.rs @@ -1,5 +1,5 @@ use ibc_proto::ibc::mock::Misbehaviour as RawMisbehaviour; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use serde::{Deserialize, Serialize}; use crate::core::ics02_client::error::Error; diff --git a/crates/relayer-types/src/mock/mod.rs b/crates/relayer-types/src/mock/mod.rs index 5c1cc333e0..340dacdaef 100644 --- a/crates/relayer-types/src/mock/mod.rs +++ b/crates/relayer-types/src/mock/mod.rs @@ -3,5 +3,4 @@ pub mod client_state; pub mod consensus_state; pub mod header; -pub mod host; pub mod misbehaviour; diff --git a/crates/relayer-types/src/relayer/ics18_relayer/context.rs b/crates/relayer-types/src/relayer/ics18_relayer/context.rs deleted file mode 100644 index c7a505914d..0000000000 --- a/crates/relayer-types/src/relayer/ics18_relayer/context.rs +++ /dev/null @@ -1,34 +0,0 @@ -use ibc_proto::google::protobuf::Any; - -use crate::core::ics02_client::client_state::ClientState; -use crate::core::ics02_client::header::Header; -use crate::events::IbcEvent; - -use crate::core::ics24_host::identifier::ClientId; -use crate::relayer::ics18_relayer::error::Error; -use crate::signer::Signer; -use crate::Height; - -/// Trait capturing all dependencies (i.e., the context) which algorithms in ICS18 require to -/// relay packets between chains. This trait comprises the dependencies towards a single chain. -/// Most of the functions in this represent wrappers over the ABCI interface. -/// This trait mimics the `Chain` trait, but at a lower level of abstraction (no networking, header -/// types, light client, RPC client, etc.) -pub trait Ics18Context { - /// Returns the latest height of the chain. - fn query_latest_height(&self) -> Height; - - /// Returns this client state for the given `client_id` on this chain. - /// Wrapper over the `/abci_query?path=..` endpoint. - fn query_client_full_state(&self, client_id: &ClientId) -> Option>; - - /// Returns the most advanced header of this chain. - fn query_latest_header(&self) -> Option>; - - /// Interface that the relayer uses to submit a datagram to this chain. - /// One can think of this as wrapping around the `/broadcast_tx_commit` ABCI endpoint. - fn send(&mut self, msgs: Vec) -> Result, Error>; - - /// Temporary solution. Similar to `CosmosSDKChain::key_and_signer()` but simpler. - fn signer(&self) -> Signer; -} diff --git a/crates/relayer-types/src/relayer/ics18_relayer/error.rs b/crates/relayer-types/src/relayer/ics18_relayer/error.rs deleted file mode 100644 index e975de5a3a..0000000000 --- a/crates/relayer-types/src/relayer/ics18_relayer/error.rs +++ /dev/null @@ -1,38 +0,0 @@ -use crate::core::ics24_host::identifier::ClientId; -use crate::core::ics26_routing::error::Error as RoutingError; -use crate::Height; -use flex_error::define_error; - -define_error! { - Error { - ClientStateNotFound - { client_id: ClientId } - | e | { format_args!("client state on destination chain not found, (client id: {0})", e.client_id) }, - - ClientAlreadyUpToDate - { - client_id: ClientId, - source_height: Height, - destination_height: Height, - } - | e | { - format_args!("the client on destination chain is already up-to-date (client id: {0}, source height: {1}, dest height: {2})", - e.client_id, e.source_height, e.destination_height) - }, - - ClientAtHigherHeight - { - client_id: ClientId, - source_height: Height, - destination_height: Height, - } - | e | { - format_args!("the client on destination chain is at a higher height (client id: {0}, source height: {1}, dest height: {2})", - e.client_id, e.source_height, e.destination_height) - }, - - TransactionFailed - [ RoutingError ] - | _ | { "transaction processing by modules failed" }, - } -} diff --git a/crates/relayer-types/src/relayer/ics18_relayer/mod.rs b/crates/relayer-types/src/relayer/ics18_relayer/mod.rs deleted file mode 100644 index 8a7f14e5b6..0000000000 --- a/crates/relayer-types/src/relayer/ics18_relayer/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -//! ICS 18: Relayer contains utilities for testing `ibc` against the Hermes relayer. - -pub mod context; -pub mod error; diff --git a/crates/relayer-types/src/relayer/mod.rs b/crates/relayer-types/src/relayer/mod.rs deleted file mode 100644 index 3749606559..0000000000 --- a/crates/relayer-types/src/relayer/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -//! Utilities for testing the `ibc` crate against the [Hermes IBC relayer][relayer-repo]. -//! -//! [relayer-repo]: https://github.com/informalsystems/hermes/tree/master/crates/relayer - -pub mod ics18_relayer; diff --git a/crates/relayer/Cargo.toml b/crates/relayer/Cargo.toml index bed5adf649..8089f4e642 100644 --- a/crates/relayer/Cargo.toml +++ b/crates/relayer/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "ibc-relayer" -version = "0.25.0" +version = "0.26.4" edition = "2021" license = "Apache-2.0" readme = "README.md" keywords = ["blockchain", "consensus", "cosmos", "ibc", "tendermint"] repository = "https://github.com/informalsystems/hermes" authors = ["Informal Systems "] -rust-version = "1.70" +rust-version = "1.71" description = """ Implementation of an IBC Relayer in Rust, as a library """ @@ -20,9 +20,9 @@ default = ["flex-error/std", "flex-error/eyre_tracer"] telemetry = ["ibc-telemetry"] [dependencies] -ibc-proto = { version = "0.37.0", features = ["serde"] } -ibc-telemetry = { version = "0.25.0", path = "../telemetry", optional = true } -ibc-relayer-types = { version = "0.25.0", path = "../relayer-types", features = ["mocks"] } +ibc-proto = { version = "0.39.0", features = ["serde"] } +ibc-telemetry = { version = "0.26.4", path = "../telemetry", optional = true } +ibc-relayer-types = { version = "0.26.4", path = "../relayer-types", features = ["mocks"] } subtle-encoding = "0.5" humantime-serde = "1.1.1" @@ -57,7 +57,7 @@ anyhow = "1.0" semver = "1.0" humantime = "2.1.0" regex = "1" -moka = "0.11.3" +moka = { version = "0.12.0", features = ["sync"] } uuid = { version = "1.4.0", features = ["v4"] } bs58 = "0.5.0" digest = "0.10.6" @@ -69,6 +69,7 @@ secp256k1 = { version = "0.27.0", features = ["rand-std"] } strum = { version = "0.25", features = ["derive"] } tokio-stream = "0.1.14" once_cell = "1.17.1" +tracing-subscriber = { version = "0.3.14", features = ["fmt", "env-filter", "json"] } [dependencies.byte-unit] version = "4.0.19" @@ -87,6 +88,9 @@ features = ["num-bigint", "serde"] version = "0.34.0" features = ["secp256k1"] +[dependencies.tendermint-proto] +version = "0.34.0" + [dependencies.tendermint-rpc] version = "0.34.0" features = ["http-client", "websocket-client"] @@ -100,11 +104,14 @@ features = ["rpc-client", "secp256k1", "unstable"] version = "0.34.0" default-features = false +[dependencies.tendermint-light-client-verifier] +version = "0.34.0" +default-features = false + [dev-dependencies] -ibc-relayer-types = { version = "0.25.0", path = "../relayer-types", features = ["mocks"] } +ibc-relayer-types = { version = "0.26.4", path = "../relayer-types", features = ["mocks"] } serial_test = "2.0.0" env_logger = "0.10.0" -tracing-subscriber = { version = "0.3.14", features = ["fmt", "env-filter", "json"] } test-log = { version = "0.2.10", features = ["trace"] } # Needed for generating (synthetic) light blocks. diff --git a/crates/relayer/src/chain.rs b/crates/relayer/src/chain.rs index 2adee44155..bcca34e85f 100644 --- a/crates/relayer/src/chain.rs +++ b/crates/relayer/src/chain.rs @@ -6,60 +6,3 @@ pub mod handle; pub mod requests; pub mod runtime; pub mod tracking; - -use serde::{de::Error, Deserialize, Serialize}; - -// NOTE(new): When adding a variant to `ChainType`, make sure to update -// the `Deserialize` implementation below and the tests. -// See the NOTE(new) comments below. - -#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize)] -/// Types of chains the relayer can relay to and from -pub enum ChainType { - /// Chains based on the Cosmos SDK - CosmosSdk, -} - -impl<'de> Deserialize<'de> for ChainType { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let original = String::deserialize(deserializer)?; - let s = original.to_ascii_lowercase().replace('-', ""); - - match s.as_str() { - "cosmossdk" => Ok(Self::CosmosSdk), - - // NOTE(new): Add a case here - _ => Err(D::Error::unknown_variant(&original, &["cosmos-sdk"])), // NOTE(new): mention the new variant here - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[derive(Copy, Clone, Debug, Serialize, Deserialize)] - pub struct Config { - tpe: ChainType, - } - - fn parse(variant: &str) -> Result { - toml::from_str::(&format!("tpe = '{variant}'")).map(|e| e.tpe) - } - - #[test] - fn deserialize() { - use ChainType::*; - - assert!(matches!(parse("CosmosSdk"), Ok(CosmosSdk))); - assert!(matches!(parse("cosmossdk"), Ok(CosmosSdk))); - assert!(matches!(parse("cosmos-sdk"), Ok(CosmosSdk))); - - // NOTE(new): Add tests here - - assert!(parse("hello-world").is_err()); - } -} diff --git a/crates/relayer/src/chain/client.rs b/crates/relayer/src/chain/client.rs index b791c9d199..6f00ec8df9 100644 --- a/crates/relayer/src/chain/client.rs +++ b/crates/relayer/src/chain/client.rs @@ -24,10 +24,18 @@ impl ClientSettings { // Currently, only Tendermint chain pairs are supported by // ForeignClient::build_create_client_and_send. Support for // heterogeneous chains is left for future revisions. - ClientSettings::Tendermint(cosmos::client::Settings::for_create_command( - options, - src_chain_config, - dst_chain_config, - )) + // + // TODO: extract Tendermint-related configs into a separate substructure + // that can be used both by CosmosSdkConfig and configs for nonSDK chains. + use ChainConfig::CosmosSdk as Csdk; + match (src_chain_config, dst_chain_config) { + (Csdk(src_chain_config), Csdk(dst_chain_config)) => { + ClientSettings::Tendermint(cosmos::client::Settings::for_create_command( + options, + src_chain_config, + dst_chain_config, + )) + } + } } } diff --git a/crates/relayer/src/chain/cosmos.rs b/crates/relayer/src/chain/cosmos.rs index b2f71a1c37..f1935d12a8 100644 --- a/crates/relayer/src/chain/cosmos.rs +++ b/crates/relayer/src/chain/cosmos.rs @@ -15,16 +15,13 @@ use tonic::codegen::http::Uri; use tonic::metadata::AsciiMetadataValue; use tracing::{debug, error, info, instrument, trace, warn}; -use ibc_proto::cosmos::{ - base::node::v1beta1::ConfigResponse, staking::v1beta1::Params as StakingParams, -}; - -use ibc_proto::interchain_security::ccv::consumer::v1::Params as CcvConsumerParams; - +use ibc_proto::cosmos::base::node::v1beta1::ConfigResponse; +use ibc_proto::cosmos::staking::v1beta1::Params as StakingParams; use ibc_proto::ibc::apps::fee::v1::{ QueryIncentivizedPacketRequest, QueryIncentivizedPacketResponse, }; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::interchain_security::ccv::v1::ConsumerParams as CcvConsumerParams; +use ibc_proto::Protobuf; use ibc_relayer_types::applications::ics31_icq::response::CrossChainQueryResponse; use ibc_relayer_types::clients::ics07_tendermint::client_state::{ AllowUpdate, ClientState as TmClientState, @@ -64,7 +61,6 @@ use tendermint_rpc::endpoint::status; use tendermint_rpc::{Client, HttpClient, Order}; use crate::account::Balance; -use crate::chain::client::ClientSettings; use crate::chain::cosmos::batch::{ send_batched_messages_and_wait_check_tx, send_batched_messages_and_wait_commit, sequential_send_batched_messages_and_wait_commit, @@ -103,15 +99,19 @@ use crate::keyring::{KeyRing, Secp256k1KeyPair, SigningKeyPair}; use crate::light_client::tendermint::LightClient as TmLightClient; use crate::light_client::{LightClient, Verified}; use crate::misbehaviour::MisbehaviourEvidence; +use crate::util::compat_mode::compat_mode_from_version; use crate::util::pretty::{ PrettyIdentifiedChannel, PrettyIdentifiedClientState, PrettyIdentifiedConnection, }; +use crate::{chain::client::ClientSettings, config::Error as ConfigError}; use self::types::app_state::GenesisAppState; +use self::version::Specs; pub mod batch; pub mod client; pub mod compatibility; +pub mod config; pub mod encode; pub mod estimate; pub mod fee; @@ -140,9 +140,9 @@ pub mod wait; /// [tm-37-max]: https://github.com/tendermint/tendermint/blob/v0.37.0-rc1/types/params.go#L79 pub const BLOCK_MAX_BYTES_MAX_FRACTION: f64 = 0.9; pub struct CosmosSdkChain { - config: ChainConfig, + config: config::CosmosSdkConfig, tx_config: TxConfig, - rpc_client: HttpClient, + pub rpc_client: HttpClient, compat_mode: CompatMode, grpc_addr: Uri, light_client: TmLightClient, @@ -157,7 +157,7 @@ pub struct CosmosSdkChain { impl CosmosSdkChain { /// Get a reference to the configuration for this chain. - pub fn config(&self) -> &ChainConfig { + pub fn config(&self) -> &config::CosmosSdkConfig { &self.config } @@ -568,7 +568,7 @@ impl CosmosSdkChain { prove, ))?; - // TODO - Verify response proof, if requested. + // TODO: Verify response proof, if requested. Ok(response) } @@ -872,19 +872,26 @@ impl ChainEndpoint for CosmosSdkChain { type Time = TmTime; type SigningKeyPair = Secp256k1KeyPair; + fn id(&self) -> &ChainId { + &self.config.id + } + fn bootstrap(config: ChainConfig, rt: Arc) -> Result { + #[allow(irrefutable_let_patterns)] + let ChainConfig::CosmosSdk(config) = config + else { + return Err(Error::config(ConfigError::wrong_type())); + }; + let mut rpc_client = HttpClient::new(config.rpc_addr.clone()) .map_err(|e| Error::rpc(config.rpc_addr.clone(), e))?; let node_info = rt.block_on(fetch_node_info(&rpc_client, &config))?; - let compat_mode = CompatMode::from_version(node_info.version).unwrap_or_else(|e| { - warn!("Unsupported tendermint version, will use v0.37 compatibility mode but relaying might not work as desired: {e}"); - CompatMode::V0_37 - }); + let compat_mode = compat_mode_from_version(&config.compat_mode, node_info.version)?.into(); rpc_client.set_compat_mode(compat_mode); - let light_client = TmLightClient::from_config(&config, node_info.id)?; + let light_client = TmLightClient::from_cosmos_sdk_config(&config, node_info.id)?; // Initialize key store and load key let keybase = KeyRing::new_secp256k1( @@ -934,6 +941,16 @@ impl ChainEndpoint for CosmosSdkChain { &mut self.keybase } + fn get_key(&self) -> Result { + // Get the key from key seed file + let key_pair = self + .keybase() + .get_key(&self.config.key_name) + .map_err(|e| Error::key_not_found(self.config().key_name.clone(), e))?; + + Ok(key_pair) + } + fn subscribe(&mut self) -> Result { let tx_monitor_cmd = match &self.tx_monitor_cmd { Some(tx_monitor_cmd) => tx_monitor_cmd, @@ -1058,13 +1075,13 @@ impl ChainEndpoint for CosmosSdkChain { } /// Get the chain configuration - fn config(&self) -> &ChainConfig { - &self.config + fn config(&self) -> ChainConfig { + ChainConfig::CosmosSdk(self.config.clone()) } - fn ibc_version(&self) -> Result, Error> { + fn version_specs(&self) -> Result { let version_specs = self.block_on(fetch_version_specs(self.id(), &self.grpc_addr))?; - Ok(version_specs.ibc_go) + Ok(version_specs) } fn query_balance(&self, key_name: Option<&str>, denom: Option<&str>) -> Result { @@ -1961,48 +1978,32 @@ impl ChainEndpoint for CosmosSdkChain { ); crate::telemetry!(query, self.id(), "query_next_sequence_receive"); - match include_proof { - IncludeProof::Yes => { - let res = self.query( - SeqRecvsPath(request.port_id, request.channel_id), - request.height, - true, - )?; - - // Note: We expect the return to be a u64 encoded in big-endian. Refer to ibc-go: - // https://github.com/cosmos/ibc-go/blob/25767f6bdb5bab2c2a116b41d92d753c93e18121/modules/core/04-channel/client/utils/utils.go#L191 - if res.value.len() != 8 { - return Err(Error::query("next_sequence_receive".into())); - } - let seq: Sequence = Bytes::from(res.value).get_u64().into(); - - let proof = res.proof.ok_or_else(Error::empty_response_proof)?; + let prove = include_proof.to_bool(); - Ok((seq, Some(proof))) - } - IncludeProof::No => { - let mut client = self - .block_on( - ibc_proto::ibc::core::channel::v1::query_client::QueryClient::connect( - self.grpc_addr.clone(), - ), - ) - .map_err(Error::grpc_transport)?; + let res = self.query( + SeqRecvsPath(request.port_id, request.channel_id), + request.height, + true, + )?; - client = client.max_decoding_message_size( - self.config().max_grpc_decoding_size.get_bytes() as usize, - ); + // Note: We expect the return to be a u64 encoded in big-endian. Refer to ibc-go: + // https://github.com/cosmos/ibc-go/blob/25767f6bdb5bab2c2a116b41d92d753c93e18121/modules/core/04-channel/client/utils/utils.go#L191 + if res.value.len() != 8 { + return Err(Error::query(format!( + "next_sequence_receive: expected a u64 but got {} bytes of data", + res.value.len() + ))); + } - let request = tonic::Request::new(request.into()); + let seq: Sequence = Bytes::from(res.value).get_u64().into(); - let response = self - .block_on(client.next_sequence_receive(request)) - .map_err(|e| Error::grpc_status(e, "query_next_sequence_receive".to_owned()))? - .into_inner(); + let proof = if prove { + Some(res.proof.ok_or_else(Error::empty_response_proof)?) + } else { + None + }; - Ok((Sequence::from(response.next_sequence_receive), None)) - } - } + Ok((seq, proof)) } /// This function queries transactions for events matching certain criteria. @@ -2028,7 +2029,7 @@ impl ChainEndpoint for CosmosSdkChain { /// Note - there is no way to format the packet query such that it asks for Tx-es with either /// sequence (the query conditions can only be AND-ed). /// There is a possibility to include "<=" and ">=" conditions but it doesn't work with - /// string attributes (sequence is emmitted as a string). + /// string attributes (sequence is emitted as a string). /// Therefore, for packets we perform one tx_search for each sequence. /// Alternatively, a single query for all packets could be performed but it would return all /// packets ever sent. @@ -2253,6 +2254,40 @@ impl ChainEndpoint for CosmosSdkChain { self.block_on(query_incentivized_packet(&self.grpc_addr, request))?; Ok(incentivized_response) } + + fn query_consumer_chains(&self) -> Result, Error> { + crate::time!( + "query_consumer_chains", + { + "src_chain": self.config().id.to_string(), + } + ); + crate::telemetry!(query, self.id(), "query_consumer_chains"); + + let mut client = self.block_on( + ibc_proto::interchain_security::ccv::provider::v1::query_client::QueryClient::connect( + self.grpc_addr.clone(), + ), + ) + .map_err(Error::grpc_transport)?; + + let request = tonic::Request::new( + ibc_proto::interchain_security::ccv::provider::v1::QueryConsumerChainsRequest {}, + ); + + let response = self + .block_on(client.query_consumer_chains(request)) + .map_err(|e| Error::grpc_status(e, "query_consumer_chains".to_owned()))? + .into_inner(); + + let result = response + .chains + .into_iter() + .map(|c| (c.chain_id.parse().unwrap(), c.client_id.parse().unwrap())) + .collect(); + + Ok(result) + } } fn sort_events_by_sequence(events: &mut [IbcEventWithHeight]) { @@ -2267,7 +2302,7 @@ fn sort_events_by_sequence(events: &mut [IbcEventWithHeight]) { async fn fetch_node_info( rpc_client: &HttpClient, - config: &ChainConfig, + config: &config::CosmosSdkConfig, ) -> Result { crate::time!("fetch_node_info", { diff --git a/crates/relayer/src/chain/cosmos/batch.rs b/crates/relayer/src/chain/cosmos/batch.rs index 747ccca360..ca82b2d5c7 100644 --- a/crates/relayer/src/chain/cosmos/batch.rs +++ b/crates/relayer/src/chain/cosmos/batch.rs @@ -332,7 +332,11 @@ mod tests { ); let config = config::load(path).expect("could not parse config"); let chain_id = ChainId::from_string("chain_A"); - let chain_config = config.find_chain(&chain_id).unwrap(); + + #[allow(irrefutable_let_patterns)] + let config::ChainConfig::CosmosSdk(chain_config) = config.find_chain(&chain_id).unwrap() else { + panic!("should be a cosmos sdk chain config"); + }; let tx_config = TxConfig::try_from(chain_config).expect("could not obtain tx config"); diff --git a/crates/relayer/src/chain/cosmos/client.rs b/crates/relayer/src/chain/cosmos/client.rs index 9196a93f87..0d3b69cdbc 100644 --- a/crates/relayer/src/chain/cosmos/client.rs +++ b/crates/relayer/src/chain/cosmos/client.rs @@ -6,8 +6,9 @@ use tracing::warn; use ibc_relayer_types::core::ics02_client::trust_threshold::TrustThreshold; -use crate::config::ChainConfig; +use crate::chain::cosmos::config::CosmosSdkConfig; use crate::foreign_client::CreateOptions; + use crate::util::pretty::PrettyDuration; /// Cosmos-specific client parameters for the `build_client_state` operation. @@ -21,8 +22,8 @@ pub struct Settings { impl Settings { pub fn for_create_command( options: CreateOptions, - src_chain_config: &ChainConfig, - dst_chain_config: &ChainConfig, + src_chain_config: &CosmosSdkConfig, + dst_chain_config: &CosmosSdkConfig, ) -> Self { let max_clock_drift = match options.max_clock_drift { None => calculate_client_state_drift(src_chain_config, dst_chain_config), @@ -55,8 +56,8 @@ impl Settings { /// chain block frequency and clock drift on source and dest. /// https://github.com/informalsystems/hermes/issues/1445 fn calculate_client_state_drift( - src_chain_config: &ChainConfig, - dst_chain_config: &ChainConfig, + src_chain_config: &CosmosSdkConfig, + dst_chain_config: &CosmosSdkConfig, ) -> Duration { src_chain_config.clock_drift + dst_chain_config.clock_drift + dst_chain_config.max_block_time } diff --git a/crates/relayer/src/chain/cosmos/config.rs b/crates/relayer/src/chain/cosmos/config.rs new file mode 100644 index 0000000000..0c73faef25 --- /dev/null +++ b/crates/relayer/src/chain/cosmos/config.rs @@ -0,0 +1,201 @@ +use crate::chain::cosmos::config::error::Error as ConfigError; +use crate::config::compat_mode::CompatMode; +use crate::config::gas_multiplier::GasMultiplier; +use crate::config::types::{MaxMsgNum, MaxTxSize, Memo}; +use crate::config::{ + self, AddressType, EventSourceMode, ExtensionOption, GasPrice, GenesisRestart, PacketFilter, +}; +use crate::config::{default, RefreshRate}; +use byte_unit::Byte; +use core::time::Duration; +use ibc_relayer_types::core::ics23_commitment::specs::ProofSpecs; +use ibc_relayer_types::core::ics24_host::identifier::ChainId; +use serde_derive::{Deserialize, Serialize}; +use std::path::PathBuf; +use tendermint_light_client::verifier::types::TrustThreshold; +use tendermint_rpc::Url; + +use crate::keyring::Store; + +pub mod error; + +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +#[serde(deny_unknown_fields)] +pub struct CosmosSdkConfig { + /// The chain's network identifier + pub id: ChainId, + + /// The RPC URL to connect to + pub rpc_addr: Url, + + /// The gRPC URL to connect to + pub grpc_addr: Url, + + /// The type of event source and associated settings + pub event_source: EventSourceMode, + + /// Timeout used when issuing RPC queries + #[serde(default = "default::rpc_timeout", with = "humantime_serde")] + pub rpc_timeout: Duration, + + /// Whether or not the full node Hermes connects to is trusted + #[serde(default = "default::trusted_node")] + pub trusted_node: bool, + + pub account_prefix: String, + pub key_name: String, + #[serde(default)] + pub key_store_type: Store, + pub key_store_folder: Option, + pub store_prefix: String, + pub default_gas: Option, + pub max_gas: Option, + + // This field is only meant to be set via the `update client` command, + // for when we need to ugprade a client across a genesis restart and + // therefore need and archive node to fetch blocks from. + pub genesis_restart: Option, + + // This field is deprecated, use `gas_multiplier` instead + pub gas_adjustment: Option, + pub gas_multiplier: Option, + + pub fee_granter: Option, + #[serde(default)] + pub max_msg_num: MaxMsgNum, + #[serde(default)] + pub max_tx_size: MaxTxSize, + #[serde(default = "default::max_grpc_decoding_size")] + pub max_grpc_decoding_size: Byte, + + /// A correction parameter that helps deal with clocks that are only approximately synchronized + /// between the source and destination chains for a client. + /// This parameter is used when deciding to accept or reject a new header + /// (originating from the source chain) for any client with the destination chain + /// that uses this configuration, unless it is overridden by the client-specific + /// clock drift option. + #[serde(default = "default::clock_drift", with = "humantime_serde")] + pub clock_drift: Duration, + + #[serde(default = "default::max_block_time", with = "humantime_serde")] + pub max_block_time: Duration, + + /// The trusting period specifies how long a validator set is trusted for + /// (must be shorter than the chain's unbonding period). + #[serde(default, with = "humantime_serde")] + pub trusting_period: Option, + + /// The rate at which to refresh the client referencing this chain, + /// expressed as a fraction of the trusting period. + #[serde(default = "default::client_refresh_rate")] + pub client_refresh_rate: RefreshRate, + + /// CCV consumer chain + #[serde(default = "default::ccv_consumer_chain")] + pub ccv_consumer_chain: bool, + + #[serde(default)] + pub memo_prefix: Memo, + + // This is an undocumented and hidden config to make the relayer wait for + // DeliverTX before sending the next transaction when sending messages in + // multiple batches. We will instruct relayer operators to turn this on + // in case relaying failed in a chain with priority mempool enabled. + // Warning: turning this on may cause degradation in performance. + #[serde(default)] + pub sequential_batch_tx: bool, + + // Note: These last few need to be last otherwise we run into `ValueAfterTable` error when serializing to TOML. + // That's because these are all tables and have to come last when serializing. + #[serde( + default, + skip_serializing_if = "Option::is_none", + with = "config::proof_specs" + )] + pub proof_specs: Option, + + // These last few need to be last otherwise we run into `ValueAfterTable` error when serializing to TOML + /// The trust threshold defines what fraction of the total voting power of a known + /// and trusted validator set is sufficient for a commit to be accepted going forward. + #[serde(default)] + pub trust_threshold: TrustThreshold, + + pub gas_price: GasPrice, + + #[serde(default)] + pub packet_filter: PacketFilter, + + #[serde(default)] + pub address_type: AddressType, + #[serde(default = "Vec::new", skip_serializing_if = "Vec::is_empty")] + pub extension_options: Vec, + pub compat_mode: Option, + pub clear_interval: Option, +} + +impl CosmosSdkConfig { + pub fn validate(&self) -> Result<(), Diagnostic> { + validate_trust_threshold(&self.id, self.trust_threshold)?; + validate_gas_settings(&self.id, self.gas_adjustment)?; + Ok(()) + } +} + +/// Check that the trust threshold is: +/// +/// a) non-zero +/// b) greater or equal to 1/3 +/// c) strictly less than 1 +fn validate_trust_threshold( + id: &ChainId, + trust_threshold: TrustThreshold, +) -> Result<(), Diagnostic> { + if trust_threshold.denominator() == 0 { + return Err(Diagnostic::Error(ConfigError::invalid_trust_threshold( + trust_threshold, + id.clone(), + "trust threshold denominator cannot be zero".to_string(), + ))); + } + + if trust_threshold.numerator() * 3 < trust_threshold.denominator() { + return Err(Diagnostic::Error(ConfigError::invalid_trust_threshold( + trust_threshold, + id.clone(), + "trust threshold cannot be < 1/3".to_string(), + ))); + } + + if trust_threshold.numerator() >= trust_threshold.denominator() { + return Err(Diagnostic::Error(ConfigError::invalid_trust_threshold( + trust_threshold, + id.clone(), + "trust threshold cannot be >= 1".to_string(), + ))); + } + + Ok(()) +} + +fn validate_gas_settings( + id: &ChainId, + gas_adjustment: Option, +) -> Result<(), Diagnostic> { + // Check that the gas_adjustment option is not set + if let Some(gas_adjustment) = gas_adjustment { + let gas_multiplier = gas_adjustment + 1.0; + + return Err(Diagnostic::Error(ConfigError::deprecated_gas_adjustment( + gas_adjustment, + gas_multiplier, + id.clone(), + ))); + } + + Ok(()) +} +#[derive(Clone, Debug)] +pub enum Diagnostic { + Warning(E), + Error(E), +} diff --git a/crates/relayer/src/chain/cosmos/config/error.rs b/crates/relayer/src/chain/cosmos/config/error.rs new file mode 100644 index 0000000000..41ee500266 --- /dev/null +++ b/crates/relayer/src/chain/cosmos/config/error.rs @@ -0,0 +1,34 @@ +use flex_error::define_error; +use ibc_relayer_types::core::ics24_host::identifier::ChainId; +use tendermint_light_client_verifier::types::TrustThreshold; + +define_error! { + + Error { + InvalidTrustThreshold + { + threshold: TrustThreshold, + chain_id: ChainId, + reason: String + } + |e| { + format!("config file specifies an invalid `trust_threshold` ({0}) for the chain '{1}', caused by: {2}", + e.threshold, e.chain_id, e.reason) + }, + +DeprecatedGasAdjustment + { + gas_adjustment: f64, + gas_multiplier: f64, + chain_id: ChainId, + } + |e| { + format!( + "config file specifies deprecated setting `gas_adjustment = {1}` for the chain '{0}'; \ + to get the same behavior, use `gas_multiplier = {2}", + e.chain_id, e.gas_adjustment, e.gas_multiplier + ) + }, + + } +} diff --git a/crates/relayer/src/chain/cosmos/query/account.rs b/crates/relayer/src/chain/cosmos/query/account.rs index 0a424d1693..e24c414ff7 100644 --- a/crates/relayer/src/chain/cosmos/query/account.rs +++ b/crates/relayer/src/chain/cosmos/query/account.rs @@ -39,9 +39,9 @@ pub async fn refresh_account<'a>( let account = query_account(grpc_address, account_address).await?; info!( - sequence = %account.sequence, - number = %account.account_number, - "refresh: retrieved account", + old = %m_account.sequence, + new = %account.sequence, + "refreshed account sequence number", ); *m_account = account.into(); diff --git a/crates/relayer/src/chain/cosmos/query/tx.rs b/crates/relayer/src/chain/cosmos/query/tx.rs index f5ad53ea6d..e6897c02a4 100644 --- a/crates/relayer/src/chain/cosmos/query/tx.rs +++ b/crates/relayer/src/chain/cosmos/query/tx.rs @@ -43,7 +43,7 @@ pub async fn query_txs( // query the first Tx that includes the event matching the client request // Note: it is possible to have multiple Tx-es for same client and consensus height. - // In this case it must be true that the client updates were performed with tha + // In this case it must be true that the client updates were performed with the // same header as the first one, otherwise a subsequent transaction would have // failed on chain. Therefore only one Tx is of interest and current API returns // the first one. @@ -102,7 +102,7 @@ pub async fn query_txs( /// Note - there is no way to format the packet query such that it asks for Tx-es with either /// sequence (the query conditions can only be AND-ed). /// There is a possibility to include "<=" and ">=" conditions but it doesn't work with -/// string attributes (sequence is emmitted as a string). +/// string attributes (sequence is emitted as a string). /// Therefore, for packets we perform one tx_search for each sequence. /// Alternatively, a single query for all packets could be performed but it would return all /// packets ever sent. diff --git a/crates/relayer/src/chain/cosmos/retry.rs b/crates/relayer/src/chain/cosmos/retry.rs index 4d0091fc92..305edf3d92 100644 --- a/crates/relayer/src/chain/cosmos/retry.rs +++ b/crates/relayer/src/chain/cosmos/retry.rs @@ -100,6 +100,9 @@ async fn do_send_tx_with_account_sequence_retry( } // Gas estimation succeeded but broadcast_tx_sync failed with a retry-able error. + // NOTE: The error code could potentially overlap between Cosmos SDK and Ibc-go channel + // error codes. This is currently not the case of incorrect account sequence error + //which is the Cosmos SDK code 32 and Ibc-go channel errors only go up to 25. Ok(ref response) if response.code == Code::from(INCORRECT_ACCOUNT_SEQUENCE_ERR) => { warn!( ?response, @@ -107,6 +110,13 @@ async fn do_send_tx_with_account_sequence_retry( refreshing account sequence number and retrying once" ); + telemetry!( + broadcast_errors, + &account.address.to_string(), + response.code.into(), + &response.log, + ); + refresh_account_and_retry_send_tx_with_account_sequence( rpc_client, config, key_pair, account, tx_memo, messages, ) @@ -119,6 +129,8 @@ async fn do_send_tx_with_account_sequence_retry( debug!("gas estimation succeeded"); // Gas estimation and broadcast_tx_sync were successful. + // NOTE: The error code could potentially overlap between Cosmos SDK and Ibc-go channel + // error codes. match response.code { Code::Ok => { let old_account_sequence = account.sequence; @@ -147,6 +159,13 @@ async fn do_send_tx_with_account_sequence_retry( "failed to broadcast tx with unrecoverable error" ); + telemetry!( + broadcast_errors, + &account.address.to_string(), + code.into(), + &response.log + ); + Ok(response) } } diff --git a/crates/relayer/src/chain/cosmos/types/config.rs b/crates/relayer/src/chain/cosmos/types/config.rs index f5a19cc3c6..a89a0ebb38 100644 --- a/crates/relayer/src/chain/cosmos/types/config.rs +++ b/crates/relayer/src/chain/cosmos/types/config.rs @@ -5,9 +5,10 @@ use ibc_proto::google::protobuf::Any; use ibc_relayer_types::core::ics24_host::identifier::ChainId; use tendermint_rpc::Url; +use crate::chain::cosmos::config::CosmosSdkConfig; use crate::chain::cosmos::types::gas::GasConfig; use crate::config::types::{MaxMsgNum, MaxTxSize}; -use crate::config::{AddressType, ChainConfig}; +use crate::config::AddressType; use crate::error::Error; #[derive(Debug, Clone)] @@ -23,10 +24,10 @@ pub struct TxConfig { pub extension_options: Vec, } -impl<'a> TryFrom<&'a ChainConfig> for TxConfig { +impl<'a> TryFrom<&'a CosmosSdkConfig> for TxConfig { type Error = Error; - fn try_from(config: &'a ChainConfig) -> Result { + fn try_from(config: &'a CosmosSdkConfig) -> Result { let grpc_address = Uri::from_str(&config.grpc_addr.to_string()) .map_err(|e| Error::invalid_uri(config.grpc_addr.to_string(), e))?; diff --git a/crates/relayer/src/chain/cosmos/types/events/channel.rs b/crates/relayer/src/chain/cosmos/types/events/channel.rs index 29730e3669..fa09493913 100644 --- a/crates/relayer/src/chain/cosmos/types/events/channel.rs +++ b/crates/relayer/src/chain/cosmos/types/events/channel.rs @@ -95,7 +95,7 @@ impl TryFrom> for WriteAcknowledgement { .into_bytes(); let mut packet = Packet::try_from(obj)?; - packet.data = Vec::from(data_str.as_str().as_bytes()); + packet.data = Vec::from(data_str.as_bytes()); Ok(Self { packet, ack }) } diff --git a/crates/relayer/src/chain/cosmos/types/gas.rs b/crates/relayer/src/chain/cosmos/types/gas.rs index e0d952796f..80291faaab 100644 --- a/crates/relayer/src/chain/cosmos/types/gas.rs +++ b/crates/relayer/src/chain/cosmos/types/gas.rs @@ -1,7 +1,8 @@ use ibc_proto::cosmos::tx::v1beta1::Fee; use crate::chain::cosmos::calculate_fee; -use crate::config::{ChainConfig, GasPrice}; +use crate::chain::cosmos::config::CosmosSdkConfig; +use crate::config::GasPrice; /// Default gas limit when submitting a transaction. const DEFAULT_MAX_GAS: u64 = 400_000; @@ -18,8 +19,8 @@ pub struct GasConfig { pub fee_granter: String, } -impl<'a> From<&'a ChainConfig> for GasConfig { - fn from(config: &'a ChainConfig) -> Self { +impl<'a> From<&'a CosmosSdkConfig> for GasConfig { + fn from(config: &'a CosmosSdkConfig) -> Self { Self { default_gas: default_gas_from_config(config), max_gas: max_gas_from_config(config), @@ -33,24 +34,24 @@ impl<'a> From<&'a ChainConfig> for GasConfig { /// The default amount of gas the relayer is willing to pay for a transaction, /// when it cannot simulate the tx and therefore estimate the gas amount needed. -pub fn default_gas_from_config(config: &ChainConfig) -> u64 { +pub fn default_gas_from_config(config: &CosmosSdkConfig) -> u64 { config .default_gas .unwrap_or_else(|| max_gas_from_config(config)) } /// The maximum amount of gas the relayer is willing to pay for a transaction -pub fn max_gas_from_config(config: &ChainConfig) -> u64 { +pub fn max_gas_from_config(config: &CosmosSdkConfig) -> u64 { config.max_gas.unwrap_or(DEFAULT_MAX_GAS) } /// The gas multiplier -pub fn gas_multiplier_from_config(config: &ChainConfig) -> f64 { +pub fn gas_multiplier_from_config(config: &CosmosSdkConfig) -> f64 { config.gas_multiplier.unwrap_or_default().to_f64() } /// Get the fee granter address -fn fee_granter_from_config(config: &ChainConfig) -> String { +fn fee_granter_from_config(config: &CosmosSdkConfig) -> String { config .fee_granter .as_deref() @@ -58,7 +59,7 @@ fn fee_granter_from_config(config: &ChainConfig) -> String { .to_string() } -fn max_fee_from_config(config: &ChainConfig) -> Fee { +fn max_fee_from_config(config: &CosmosSdkConfig) -> Fee { let max_gas = max_gas_from_config(config); // The maximum fee the relayer pays for a transaction diff --git a/crates/relayer/src/chain/counterparty.rs b/crates/relayer/src/chain/counterparty.rs index ac34d84f40..b99699d3b0 100644 --- a/crates/relayer/src/chain/counterparty.rs +++ b/crates/relayer/src/chain/counterparty.rs @@ -2,7 +2,6 @@ use std::collections::HashSet; use ibc_relayer_types::{ core::{ - ics02_client::client_state::ClientState, ics03_connection::connection::{ ConnectionEnd, IdentifiedConnectionEnd, State as ConnectionState, }, @@ -33,6 +32,7 @@ use crate::channel::ChannelError; use crate::client_state::IdentifiedAnyClientState; use crate::path::PathIdentifiers; use crate::supervisor::Error; +use crate::telemetry; pub fn counterparty_chain_from_connection( src_chain: &impl ChainHandle, @@ -503,6 +503,19 @@ pub fn unreceived_packets( &path.counterparty_channel_id, )?; + telemetry!( + update_backlog, + commit_sequences + .iter() + .map(|s| u64::from(*s)) + .collect::>() + .clone(), + &counterparty_chain.id(), + &path.counterparty_channel_id, + &path.counterparty_port_id, + &chain.id() + ); + let packet_seq_nrs = unreceived_packets_sequences(chain, &path.port_id, &path.channel_id, commit_sequences)?; diff --git a/crates/relayer/src/chain/endpoint.rs b/crates/relayer/src/chain/endpoint.rs index 4c0134dfb3..11f47a7486 100644 --- a/crates/relayer/src/chain/endpoint.rs +++ b/crates/relayer/src/chain/endpoint.rs @@ -10,7 +10,7 @@ use ibc_relayer_types::applications::ics31_icq::response::CrossChainQueryRespons use ibc_relayer_types::core::ics02_client::client_state::ClientState; use ibc_relayer_types::core::ics02_client::consensus_state::ConsensusState; use ibc_relayer_types::core::ics02_client::events::UpdateClient; -use ibc_relayer_types::core::ics02_client::header::Header; +use ibc_relayer_types::core::ics02_client::header::{AnyHeader, Header}; use ibc_relayer_types::core::ics03_connection::connection::{ ConnectionEnd, IdentifiedConnectionEnd, State, }; @@ -33,6 +33,7 @@ use tendermint_rpc::endpoint::broadcast::tx_sync::Response as TxResponse; use crate::account::Balance; use crate::chain::client::ClientSettings; +use crate::chain::cosmos::version::Specs; use crate::chain::handle::Subscription; use crate::chain::requests::*; use crate::chain::tracking::TrackedMsgs; @@ -44,7 +45,6 @@ use crate::denom::DenomTrace; use crate::error::Error; use crate::event::IbcEventWithHeight; use crate::keyring::{AnySigningKeyPair, KeyRing, SigningKeyPairSized}; -use crate::light_client::AnyHeader; use crate::misbehaviour::MisbehaviourEvidence; /// The result of a health check. @@ -82,12 +82,10 @@ pub trait ChainEndpoint: Sized { type SigningKeyPair: SigningKeyPairSized + Into; /// Returns the chain's identifier - fn id(&self) -> &ChainId { - &self.config().id - } + fn id(&self) -> &ChainId; /// Returns the chain configuration - fn config(&self) -> &ChainConfig; + fn config(&self) -> ChainConfig; // Life cycle @@ -114,15 +112,7 @@ pub trait ChainEndpoint: Sized { fn get_signer(&self) -> Result; /// Get the signing key pair - fn get_key(&mut self) -> Result { - // Get the key from key seed file - let key_pair = self - .keybase() - .get_key(&self.config().key_name) - .map_err(|e| Error::key_not_found(self.config().key_name.clone(), e))?; - - Ok(key_pair) - } + fn get_key(&self) -> Result; fn add_key(&mut self, key_name: &str, key_pair: Self::SigningKeyPair) -> Result<(), Error> { self.keybase_mut() @@ -135,7 +125,7 @@ pub trait ChainEndpoint: Sized { // Versioning /// Return the version of the IBC protocol that this chain is running, if known. - fn ibc_version(&self) -> Result, Error>; + fn version_specs(&self) -> Result; // Send transactions @@ -695,4 +685,6 @@ pub trait ChainEndpoint: Sized { &self, request: QueryIncentivizedPacketRequest, ) -> Result; + + fn query_consumer_chains(&self) -> Result, Error>; } diff --git a/crates/relayer/src/chain/handle.rs b/crates/relayer/src/chain/handle.rs index be905173cb..1ff6aae63f 100644 --- a/crates/relayer/src/chain/handle.rs +++ b/crates/relayer/src/chain/handle.rs @@ -10,7 +10,7 @@ use ibc_proto::ibc::apps::fee::v1::{ use ibc_relayer_types::{ applications::ics31_icq::response::CrossChainQueryResponse, core::{ - ics02_client::events::UpdateClient, + ics02_client::{events::UpdateClient, header::AnyHeader}, ics03_connection::{ connection::{ConnectionEnd, IdentifiedConnectionEnd}, version::Version, @@ -40,12 +40,12 @@ use crate::{ IbcEventWithHeight, }, keyring::AnySigningKeyPair, - light_client::AnyHeader, misbehaviour::MisbehaviourEvidence, }; use super::{ client::ClientSettings, + cosmos::version::Specs, endpoint::{ChainStatus, HealthCheck}, requests::*, tracking::TrackedMsgs, @@ -141,8 +141,8 @@ pub enum ChainRequest { reply_to: ReplyTo<()>, }, - IbcVersion { - reply_to: ReplyTo>, + VersionSpecs { + reply_to: ReplyTo, }, QueryBalance { @@ -367,6 +367,10 @@ pub enum ChainRequest { request: QueryIncentivizedPacketRequest, reply_to: ReplyTo, }, + + QueryConsumerChains { + reply_to: ReplyTo>, + }, } pub trait ChainHandle: Clone + Display + Send + Sync + Debug + 'static { @@ -409,7 +413,7 @@ pub trait ChainHandle: Clone + Display + Send + Sync + Debug + 'static { fn add_key(&self, key_name: String, key: AnySigningKeyPair) -> Result<(), Error>; /// Return the version of the IBC protocol that this chain is running, if known. - fn ibc_version(&self) -> Result, Error>; + fn version_specs(&self) -> Result; /// Query the balance of the given account for the given denom. /// If no account is given, behavior must be specified, e.g. retrieve it from configuration file. @@ -678,4 +682,6 @@ pub trait ChainHandle: Clone + Display + Send + Sync + Debug + 'static { &self, request: QueryIncentivizedPacketRequest, ) -> Result; + + fn query_consumer_chains(&self) -> Result, Error>; } diff --git a/crates/relayer/src/chain/handle/base.rs b/crates/relayer/src/chain/handle/base.rs index 2c2264f55c..220c9ce7a3 100644 --- a/crates/relayer/src/chain/handle/base.rs +++ b/crates/relayer/src/chain/handle/base.rs @@ -9,7 +9,7 @@ use ibc_proto::ibc::apps::fee::v1::{ use ibc_relayer_types::{ applications::ics31_icq::response::CrossChainQueryResponse, core::{ - ics02_client::events::UpdateClient, + ics02_client::{events::UpdateClient, header::AnyHeader}, ics03_connection::connection::{ConnectionEnd, IdentifiedConnectionEnd}, ics03_connection::version::Version, ics04_channel::channel::{ChannelEnd, IdentifiedChannelEnd}, @@ -26,7 +26,10 @@ use ibc_relayer_types::{ use crate::{ account::Balance, - chain::{client::ClientSettings, endpoint::ChainStatus, requests::*, tracking::TrackedMsgs}, + chain::{ + client::ClientSettings, cosmos::version::Specs, endpoint::ChainStatus, requests::*, + tracking::TrackedMsgs, + }, client_state::{AnyClientState, IdentifiedAnyClientState}, config::ChainConfig, connection::ConnectionMsgType, @@ -35,7 +38,6 @@ use crate::{ error::Error, event::IbcEventWithHeight, keyring::AnySigningKeyPair, - light_client::AnyHeader, misbehaviour::MisbehaviourEvidence, }; @@ -145,8 +147,8 @@ impl ChainHandle for BaseChainHandle { }) } - fn ibc_version(&self) -> Result, Error> { - self.send(|reply_to| ChainRequest::IbcVersion { reply_to }) + fn version_specs(&self) -> Result { + self.send(|reply_to| ChainRequest::VersionSpecs { reply_to }) } fn query_balance( @@ -515,4 +517,8 @@ impl ChainHandle for BaseChainHandle { ) -> Result { self.send(|reply_to| ChainRequest::QueryIncentivizedPacket { request, reply_to }) } + + fn query_consumer_chains(&self) -> Result, Error> { + self.send(|reply_to| ChainRequest::QueryConsumerChains { reply_to }) + } } diff --git a/crates/relayer/src/chain/handle/cache.rs b/crates/relayer/src/chain/handle/cache.rs index d09bc6927f..3c4762b3ae 100644 --- a/crates/relayer/src/chain/handle/cache.rs +++ b/crates/relayer/src/chain/handle/cache.rs @@ -1,5 +1,6 @@ use core::fmt::{Display, Error as FmtError, Formatter}; use crossbeam_channel as channel; +use ibc_relayer_types::core::ics02_client::header::AnyHeader; use tracing::Span; use ibc_proto::ibc::apps::fee::v1::QueryIncentivizedPacketRequest; @@ -24,6 +25,7 @@ use ibc_relayer_types::Height; use crate::account::Balance; use crate::cache::{Cache, CacheStatus}; use crate::chain::client::ClientSettings; +use crate::chain::cosmos::version::Specs; use crate::chain::endpoint::{ChainStatus, HealthCheck}; use crate::chain::handle::{ChainHandle, ChainRequest, Subscription}; use crate::chain::requests::*; @@ -36,7 +38,6 @@ use crate::denom::DenomTrace; use crate::error::Error; use crate::event::IbcEventWithHeight; use crate::keyring::AnySigningKeyPair; -use crate::light_client::AnyHeader; use crate::misbehaviour::MisbehaviourEvidence; use crate::telemetry; @@ -122,8 +123,8 @@ impl ChainHandle for CachingChainHandle { self.inner().add_key(key_name, key) } - fn ibc_version(&self) -> Result, Error> { - self.inner().ibc_version() + fn version_specs(&self) -> Result { + self.inner().version_specs() } fn query_balance( @@ -510,4 +511,8 @@ impl ChainHandle for CachingChainHandle { ) -> Result { self.inner.query_incentivized_packet(request) } + + fn query_consumer_chains(&self) -> Result, Error> { + self.inner.query_consumer_chains() + } } diff --git a/crates/relayer/src/chain/handle/counting.rs b/crates/relayer/src/chain/handle/counting.rs index 66b83e5686..2211cc3551 100644 --- a/crates/relayer/src/chain/handle/counting.rs +++ b/crates/relayer/src/chain/handle/counting.rs @@ -10,6 +10,7 @@ use ibc_proto::ibc::apps::fee::v1::{ }; use ibc_relayer_types::applications::ics31_icq::response::CrossChainQueryResponse; use ibc_relayer_types::core::ics02_client::events::UpdateClient; +use ibc_relayer_types::core::ics02_client::header::AnyHeader; use ibc_relayer_types::core::ics03_connection::connection::ConnectionEnd; use ibc_relayer_types::core::ics03_connection::connection::IdentifiedConnectionEnd; use ibc_relayer_types::core::ics03_connection::version::Version; @@ -27,6 +28,7 @@ use ibc_relayer_types::Height; use crate::account::Balance; use crate::chain::client::ClientSettings; +use crate::chain::cosmos::version::Specs; use crate::chain::endpoint::{ChainStatus, HealthCheck}; use crate::chain::handle::{ChainHandle, ChainRequest, Subscription}; use crate::chain::requests::*; @@ -39,7 +41,6 @@ use crate::denom::DenomTrace; use crate::error::Error; use crate::event::IbcEventWithHeight; use crate::keyring::AnySigningKeyPair; -use crate::light_client::AnyHeader; use crate::misbehaviour::MisbehaviourEvidence; use crate::util::lock::LockExt; @@ -150,9 +151,9 @@ impl ChainHandle for CountingChainHandle { self.inner().add_key(key_name, key) } - fn ibc_version(&self) -> Result, Error> { + fn version_specs(&self) -> Result { self.inc_metric("ibc_version"); - self.inner().ibc_version() + self.inner().version_specs() } fn query_balance( @@ -503,4 +504,9 @@ impl ChainHandle for CountingChainHandle { self.inc_metric("query_incentivized_packet"); self.inner.query_incentivized_packet(request) } + + fn query_consumer_chains(&self) -> Result, Error> { + self.inc_metric("query_consumer_chains"); + self.inner.query_consumer_chains() + } } diff --git a/crates/relayer/src/chain/requests.rs b/crates/relayer/src/chain/requests.rs index be6e071251..cc45908172 100644 --- a/crates/relayer/src/chain/requests.rs +++ b/crates/relayer/src/chain/requests.rs @@ -76,12 +76,18 @@ impl Display for QueryHeight { /// Defines a type to be used in select requests to specify whether or not a proof should be /// returned along with the response. -#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum IncludeProof { Yes, No, } +impl IncludeProof { + pub fn to_bool(&self) -> bool { + *self == IncludeProof::Yes + } +} + #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct PageRequest { /// key is a value returned in PageResponse.next_key to begin diff --git a/crates/relayer/src/chain/runtime.rs b/crates/relayer/src/chain/runtime.rs index 0426f6377d..d19fbd9cfe 100644 --- a/crates/relayer/src/chain/runtime.rs +++ b/crates/relayer/src/chain/runtime.rs @@ -12,6 +12,7 @@ use ibc_relayer_types::{ applications::ics31_icq::response::CrossChainQueryResponse, core::{ ics02_client::events::UpdateClient, + ics02_client::header::AnyHeader, ics03_connection::{ connection::{ConnectionEnd, IdentifiedConnectionEnd}, version::Version, @@ -21,7 +22,7 @@ use ibc_relayer_types::{ packet::{PacketMsgType, Sequence}, }, ics23_commitment::{commitment::CommitmentPrefix, merkle::MerkleProof}, - ics24_host::identifier::{ChannelId, ClientId, ConnectionId, PortId}, + ics24_host::identifier::{ChainId, ChannelId, ClientId, ConnectionId, PortId}, }, proofs::Proofs, signer::Signer, @@ -39,12 +40,12 @@ use crate::{ error::Error, event::IbcEventWithHeight, keyring::AnySigningKeyPair, - light_client::AnyHeader, misbehaviour::MisbehaviourEvidence, }; use super::{ client::ClientSettings, + cosmos::version::Specs, endpoint::{ChainEndpoint, ChainStatus, HealthCheck}, handle::{ChainHandle, ChainRequest, ReplyTo, Subscription}, requests::*, @@ -186,8 +187,8 @@ where self.add_key(key_name, key, reply_to)? }, - ChainRequest::IbcVersion { reply_to } => { - self.ibc_version(reply_to)? + ChainRequest::VersionSpecs { reply_to } => { + self.version_specs(reply_to)? }, ChainRequest::BuildHeader { trusted_height, target_height, client_state, reply_to } => { @@ -349,6 +350,10 @@ where ChainRequest::QueryIncentivizedPacket { request, reply_to } => { self.query_incentivized_packet(request, reply_to)? }, + + ChainRequest::QueryConsumerChains { reply_to } => { + self.query_consumer_chains(reply_to)? + }, } }, } @@ -445,8 +450,8 @@ where reply_to.send(result).map_err(Error::send) } - fn ibc_version(&mut self, reply_to: ReplyTo>) -> Result<(), Error> { - let result = self.chain.ibc_version(); + fn version_specs(&mut self, reply_to: ReplyTo) -> Result<(), Error> { + let result = self.chain.version_specs(); reply_to.send(result).map_err(Error::send) } @@ -850,4 +855,14 @@ where Ok(()) } + + fn query_consumer_chains( + &self, + reply_to: ReplyTo>, + ) -> Result<(), Error> { + let result = self.chain.query_consumer_chains(); + reply_to.send(result).map_err(Error::send)?; + + Ok(()) + } } diff --git a/crates/relayer/src/channel.rs b/crates/relayer/src/channel.rs index 84bce4470e..c2a9880262 100644 --- a/crates/relayer/src/channel.rs +++ b/crates/relayer/src/channel.rs @@ -481,12 +481,12 @@ impl Channel { .a_chain() .config() .map_err(ChannelError::relayer)? - .max_block_time; + .max_block_time(); let b_block_time = self .b_chain() .config() .map_err(ChannelError::relayer)? - .max_block_time; + .max_block_time(); Ok(a_block_time.max(b_block_time)) } @@ -1020,7 +1020,7 @@ impl Channel { let counterparty = Counterparty::new(self.src_port_id().clone(), self.src_channel_id().cloned()); - // Re-use the version that was either set on ChanOpenInit or overwritten by the application. + // Reuse the version that was either set on ChanOpenInit or overwritten by the application. let version = src_channel.version().clone(); let channel = ChannelEnd::new( diff --git a/crates/relayer/src/channel/error.rs b/crates/relayer/src/channel/error.rs index 7fc820ce89..c6d3b40391 100644 --- a/crates/relayer/src/channel/error.rs +++ b/crates/relayer/src/channel/error.rs @@ -196,16 +196,27 @@ define_error! { } impl HasExpiredOrFrozenError for ChannelErrorDetail { - fn is_expired_or_frozen_error(&self) -> bool { + fn is_frozen_error(&self) -> bool { match self { - Self::ClientOperation(e) => e.source.is_expired_or_frozen_error(), + Self::ClientOperation(e) => e.source.is_frozen_error(), + _ => false, + } + } + + fn is_expired_error(&self) -> bool { + match self { + Self::ClientOperation(e) => e.source.is_expired_error(), _ => false, } } } impl HasExpiredOrFrozenError for ChannelError { - fn is_expired_or_frozen_error(&self) -> bool { - self.detail().is_expired_or_frozen_error() + fn is_frozen_error(&self) -> bool { + self.detail().is_frozen_error() + } + + fn is_expired_error(&self) -> bool { + self.detail().is_expired_error() } } diff --git a/crates/relayer/src/client_state.rs b/crates/relayer/src/client_state.rs index f5e8227449..352106cf5d 100644 --- a/crates/relayer/src/client_state.rs +++ b/crates/relayer/src/client_state.rs @@ -1,31 +1,30 @@ use core::time::Duration; -use ibc_proto::ibc::core::client::v1::IdentifiedClientState; -use ibc_proto::ibc::lightclients::tendermint::v1::ClientState as RawClientState; -#[cfg(test)] -use ibc_proto::ibc::mock::ClientState as RawMockClientState; -use ibc_proto::protobuf::Protobuf; use serde::{Deserialize, Serialize}; use ibc_proto::google::protobuf::Any; +use ibc_proto::ibc::core::client::v1::IdentifiedClientState; +use ibc_proto::ibc::lightclients::tendermint::v1::ClientState as RawTmClientState; +use ibc_proto::Protobuf; use ibc_relayer_types::clients::ics07_tendermint::client_state::{ ClientState as TmClientState, UpgradeOptions as TmUpgradeOptions, TENDERMINT_CLIENT_STATE_TYPE_URL, }; -use ibc_relayer_types::core::ics02_client::client_state::{ - downcast_client_state, ClientState, UpgradeOptions, -}; +use ibc_relayer_types::core::ics02_client::client_state::ClientState; use ibc_relayer_types::core::ics02_client::client_type::ClientType; use ibc_relayer_types::core::ics02_client::error::Error; use ibc_relayer_types::core::ics02_client::trust_threshold::TrustThreshold; use ibc_relayer_types::core::ics24_host::error::ValidationError; use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ClientId}; +use ibc_relayer_types::Height; + +#[cfg(test)] +use ibc_proto::ibc::mock::ClientState as RawMockClientState; #[cfg(test)] use ibc_relayer_types::mock::client_state::MockClientState; #[cfg(test)] use ibc_relayer_types::mock::client_state::MOCK_CLIENT_STATE_TYPE_URL; -use ibc_relayer_types::Height; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(tag = "type")] @@ -37,7 +36,7 @@ pub enum AnyUpgradeOptions { } impl AnyUpgradeOptions { - fn as_tm_upgrade_options(&self) -> Option<&TmUpgradeOptions> { + fn into_tm_upgrade_options(self) -> Option { match self { AnyUpgradeOptions::Tendermint(tm) => Some(tm), #[cfg(test)] @@ -46,8 +45,6 @@ impl AnyUpgradeOptions { } } -impl UpgradeOptions for AnyUpgradeOptions {} - #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "type")] pub enum AnyClientState { @@ -58,6 +55,15 @@ pub enum AnyClientState { } impl AnyClientState { + pub fn chain_id(&self) -> ChainId { + match self { + AnyClientState::Tendermint(tm_state) => tm_state.chain_id(), + + #[cfg(test)] + AnyClientState::Mock(mock_state) => mock_state.chain_id(), + } + } + pub fn latest_height(&self) -> Height { match self { Self::Tendermint(tm_state) => tm_state.latest_height(), @@ -123,7 +129,7 @@ impl TryFrom for AnyClientState { "" => Err(Error::empty_client_state_response()), TENDERMINT_CLIENT_STATE_TYPE_URL => Ok(AnyClientState::Tendermint( - Protobuf::::decode_vec(&raw.value) + Protobuf::::decode_vec(&raw.value) .map_err(Error::decode_raw_client_state)?, )), @@ -143,18 +149,20 @@ impl From for Any { match value { AnyClientState::Tendermint(value) => Any { type_url: TENDERMINT_CLIENT_STATE_TYPE_URL.to_string(), - value: Protobuf::::encode_vec(&value), + value: Protobuf::::encode_vec(value), }, #[cfg(test)] AnyClientState::Mock(value) => Any { type_url: MOCK_CLIENT_STATE_TYPE_URL.to_string(), - value: Protobuf::::encode_vec(&value), + value: Protobuf::::encode_vec(value), }, } } } impl ClientState for AnyClientState { + type UpgradeOptions = AnyUpgradeOptions; + fn chain_id(&self) -> ChainId { match self { AnyClientState::Tendermint(tm_state) => tm_state.chain_id(), @@ -179,24 +187,21 @@ impl ClientState for AnyClientState { fn upgrade( &mut self, upgrade_height: Height, - upgrade_options: &dyn UpgradeOptions, + upgrade_options: AnyUpgradeOptions, chain_id: ChainId, ) { - let upgrade_options = upgrade_options - .as_any() - .downcast_ref::() - .expect("UpgradeOptions not of type AnyUpgradeOptions"); - match self { - AnyClientState::Tendermint(tm_state) => tm_state.upgrade( - upgrade_height, - upgrade_options.as_tm_upgrade_options().unwrap(), - chain_id, - ), + AnyClientState::Tendermint(tm_state) => { + if let Some(upgrade_options) = upgrade_options.into_tm_upgrade_options() { + tm_state.upgrade(upgrade_height, upgrade_options, chain_id); + } + // TODO: Handle case where upgrade options are not of the right type, + // not a problem in practice for now but good to have. + } #[cfg(test)] AnyClientState::Mock(mock_state) => { - mock_state.upgrade(upgrade_height, upgrade_options, chain_id) + mock_state.upgrade(upgrade_height, (), chain_id); } } } @@ -224,21 +229,6 @@ impl From for AnyClientState { } } -impl From<&dyn ClientState> for AnyClientState { - fn from(client_state: &dyn ClientState) -> Self { - #[cfg(test)] - if let Some(cs) = downcast_client_state::(client_state) { - return AnyClientState::from(*cs); - } - - if let Some(cs) = downcast_client_state::(client_state) { - AnyClientState::from(cs.clone()) - } else { - unreachable!() - } - } -} - #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "type")] pub struct IdentifiedAnyClientState { diff --git a/crates/relayer/src/config.rs b/crates/relayer/src/config.rs index 6b3cce3cd9..d0e1d83ab9 100644 --- a/crates/relayer/src/config.rs +++ b/crates/relayer/src/config.rs @@ -1,5 +1,6 @@ //! Relayer configuration +pub mod compat_mode; pub mod error; pub mod filter; pub mod gas_multiplier; @@ -17,28 +18,21 @@ use core::{ time::Duration, }; use serde_derive::{Deserialize, Serialize}; -use std::{ - fs, - fs::File, - io::Write, - ops::Range, - path::{Path, PathBuf}, -}; +use std::{fs, fs::File, io::Write, ops::Range, path::Path}; use tendermint::block::Height as BlockHeight; -use tendermint_light_client::verifier::types::TrustThreshold; -use tendermint_rpc::{Url, WebSocketClientUrl}; +use tendermint_rpc::Url; +use tendermint_rpc::WebSocketClientUrl; use ibc_proto::google::protobuf::Any; -use ibc_relayer_types::core::ics23_commitment::specs::ProofSpecs; use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; use ibc_relayer_types::timestamp::ZERO_DURATION; -use crate::chain::ChainType; -use crate::config::gas_multiplier::GasMultiplier; -use crate::config::types::{MaxMsgNum, MaxTxSize, Memo}; -use crate::error::Error as RelayerError; use crate::extension_options::ExtensionOptionDynamicFeeTx; use crate::keyring::Store; +use crate::keyring::{AnySigningKeyPair, KeyRing}; +use crate::{chain::cosmos::config::CosmosSdkConfig, error::Error as RelayerError}; + +use crate::keyring; pub use crate::config::Error as ConfigError; pub use error::Error; @@ -109,7 +103,7 @@ impl PartialOrd for GasPrice { /// the parsing of other prices. pub fn parse_gas_prices(prices: String) -> Vec { prices - .split(';') + .split(|c| c == ',' || c == ';') .filter_map(|gp| GasPrice::from_str(gp).ok()) .collect() } @@ -151,11 +145,9 @@ impl Display for ExtensionOption { /// Defaults for various fields pub mod default { - use super::*; + use ibc_relayer_types::core::ics02_client::trust_threshold::TrustThreshold; - pub fn chain_type() -> ChainType { - ChainType::CosmosSdk - } + use super::*; pub fn ccv_consumer_chain() -> bool { false @@ -258,15 +250,15 @@ pub struct Config { impl Config { pub fn has_chain(&self, id: &ChainId) -> bool { - self.chains.iter().any(|c| c.id == *id) + self.chains.iter().any(|c| c.id() == id) } pub fn find_chain(&self, id: &ChainId) -> Option<&ChainConfig> { - self.chains.iter().find(|c| c.id == *id) + self.chains.iter().find(|c| c.id() == id) } pub fn find_chain_mut(&mut self, id: &ChainId) -> Option<&mut ChainConfig> { - self.chains.iter_mut().find(|c| c.id == *id) + self.chains.iter_mut().find(|c| c.id() == id) } /// Returns true if filtering is disabled or if packets are allowed on @@ -280,7 +272,7 @@ impl Config { ) -> bool { match self.find_chain(chain_id) { Some(chain_config) => chain_config - .packet_filter + .packet_filter() .channel_policy .is_allowed(port_id, channel_id), None => false, @@ -288,7 +280,35 @@ impl Config { } pub fn chains_map(&self) -> BTreeMap<&ChainId, &ChainConfig> { - self.chains.iter().map(|c| (&c.id, c)).collect() + self.chains.iter().map(|c| (c.id(), c)).collect() + } + + /// Method for syntactic validation of the input configuration file. + pub fn validate_config(&self) -> Result<(), Diagnostic> { + use alloc::collections::BTreeSet; + // Check for duplicate chain configuration and invalid trust thresholds + let mut unique_chain_ids = BTreeSet::new(); + for chain_config in self.chains.iter() { + let already_present = !unique_chain_ids.insert(chain_config.id().clone()); + if already_present { + return Err(Diagnostic::Error(Error::duplicate_chains( + chain_config.id().clone(), + ))); + } + + match chain_config { + ChainConfig::CosmosSdk(cosmos_config) => { + cosmos_config + .validate() + .map_err(Into::>::into)?; + } + } + } + + // Check for invalid mode config + self.mode.validate()?; + + Ok(()) } } @@ -308,6 +328,22 @@ impl ModeConfig { && !self.channels.enabled && !self.packets.enabled } + + fn validate(&self) -> Result<(), Diagnostic> { + if self.all_disabled() { + return Err(Diagnostic::Warning(Error::invalid_mode( + "all operation modes of Hermes are disabled, relayer won't perform any action aside from subscribing to events".to_string(), + ))); + } + + if self.clients.enabled && !self.clients.refresh && !self.clients.misbehaviour { + return Err(Diagnostic::Error(Error::invalid_mode( + "either `refresh` or `misbehaviour` must be set to true if `clients.enabled` is set to true".to_string(), + ))); + } + + Ok(()) + } } /// # IMPORTANT: Keep the values here in sync with the values in the default config.toml. @@ -568,118 +604,67 @@ pub enum EventSourceMode { #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] #[serde(deny_unknown_fields)] -pub struct ChainConfig { - /// The chain's network identifier - pub id: ChainId, - - /// The chain type - #[serde(default = "default::chain_type")] - pub r#type: ChainType, - - /// The RPC URL to connect to - pub rpc_addr: Url, - - /// The gRPC URL to connect to - pub grpc_addr: Url, - - /// The type of event source and associated settings - pub event_source: EventSourceMode, - - /// Timeout used when issuing RPC queries - #[serde(default = "default::rpc_timeout", with = "humantime_serde")] - pub rpc_timeout: Duration, - - /// Whether or not the full node Hermes connects to is trusted - #[serde(default = "default::trusted_node")] - pub trusted_node: bool, +#[serde(tag = "type")] +pub enum ChainConfig { + CosmosSdk(CosmosSdkConfig), +} - pub account_prefix: String, - pub key_name: String, - #[serde(default)] - pub key_store_type: Store, - pub key_store_folder: Option, - pub store_prefix: String, - pub default_gas: Option, - pub max_gas: Option, - - // This field is only meant to be set via the `update client` command, - // for when we need to ugprade a client across a genesis restart and - // therefore need and archive node to fetch blocks from. - pub genesis_restart: Option, - - // This field is deprecated, use `gas_multiplier` instead - pub gas_adjustment: Option, - pub gas_multiplier: Option, - - pub fee_granter: Option, - #[serde(default)] - pub max_msg_num: MaxMsgNum, - #[serde(default)] - pub max_tx_size: MaxTxSize, - #[serde(default = "default::max_grpc_decoding_size")] - pub max_grpc_decoding_size: Byte, - - /// A correction parameter that helps deal with clocks that are only approximately synchronized - /// between the source and destination chains for a client. - /// This parameter is used when deciding to accept or reject a new header - /// (originating from the source chain) for any client with the destination chain - /// that uses this configuration, unless it is overridden by the client-specific - /// clock drift option. - #[serde(default = "default::clock_drift", with = "humantime_serde")] - pub clock_drift: Duration, - - #[serde(default = "default::max_block_time", with = "humantime_serde")] - pub max_block_time: Duration, - - /// The trusting period specifies how long a validator set is trusted for - /// (must be shorter than the chain's unbonding period). - #[serde(default, with = "humantime_serde")] - pub trusting_period: Option, - - /// The rate at which to refresh the client referencing this chain, - /// expressed as a fraction of the trusting period. - #[serde(default = "default::client_refresh_rate")] - pub client_refresh_rate: RefreshRate, - - /// CCV consumer chain - #[serde(default = "default::ccv_consumer_chain")] - pub ccv_consumer_chain: bool, +impl ChainConfig { + pub fn id(&self) -> &ChainId { + match self { + Self::CosmosSdk(config) => &config.id, + } + } - #[serde(default)] - pub memo_prefix: Memo, + pub fn packet_filter(&self) -> &PacketFilter { + match self { + Self::CosmosSdk(config) => &config.packet_filter, + } + } - // This is an undocumented and hidden config to make the relayer wait for - // DeliverTX before sending the next transaction when sending messages in - // multiple batches. We will instruct relayer operators to turn this on - // in case relaying failed in a chain with priority mempool enabled. - // Warning: turning this on may cause degradation in performance. - #[serde(default)] - pub sequential_batch_tx: bool, + pub fn max_block_time(&self) -> Duration { + match self { + Self::CosmosSdk(config) => config.max_block_time, + } + } - // Note: These last few need to be last otherwise we run into `ValueAfterTable` error when serializing to TOML. - // That's because these are all tables and have to come last when serializing. - #[serde( - default, - skip_serializing_if = "Option::is_none", - with = "self::proof_specs" - )] - pub proof_specs: Option, + pub fn key_name(&self) -> &String { + match self { + Self::CosmosSdk(config) => &config.key_name, + } + } - // These last few need to be last otherwise we run into `ValueAfterTable` error when serializing to TOML - /// The trust threshold defines what fraction of the total voting power of a known - /// and trusted validator set is sufficient for a commit to be accepted going forward. - #[serde(default = "default::trust_threshold", with = "self::trust_threshold")] - pub trust_threshold: TrustThreshold, + pub fn set_key_name(&mut self, key_name: String) { + match self { + Self::CosmosSdk(config) => config.key_name = key_name, + } + } - pub gas_price: GasPrice, + pub fn list_keys(&self) -> Result, keyring::errors::Error> { + let keys = match self { + ChainConfig::CosmosSdk(config) => { + let keyring = KeyRing::new_secp256k1( + Store::Test, + &config.account_prefix, + &config.id, + &config.key_store_folder, + )?; + keyring + .keys()? + .into_iter() + .map(|(key_name, keys)| (key_name, keys.into())) + .collect() + } + }; - #[serde(default)] - pub packet_filter: PacketFilter, + Ok(keys) + } - #[serde(default)] - pub address_type: AddressType, - #[serde(default = "Vec::new", skip_serializing_if = "Vec::is_empty")] - pub extension_options: Vec, + pub fn clear_interval(&self) -> Option { + match self { + Self::CosmosSdk(config) => config.clear_interval, + } + } } /// Attempt to load and parse the TOML config file as a `Config`. @@ -727,6 +712,29 @@ impl Default for TracingServerConfig { } } +#[derive(Clone, Debug)] +pub enum Diagnostic { + Warning(E), + Error(E), +} + +use crate::chain::cosmos::config::Diagnostic as CosmosConfigDiagnostic; +impl> From> for Diagnostic { + fn from(value: CosmosConfigDiagnostic) -> Self { + match value { + CosmosConfigDiagnostic::Warning(e) => Diagnostic::Warning(e.into()), + CosmosConfigDiagnostic::Error(e) => Diagnostic::Error(e.into()), + } + } +} + +use crate::chain::cosmos::config::error::Error as CosmosConfigError; +impl From for Error { + fn from(error: CosmosConfigError) -> Error { + Error::cosmos_config_error(error.to_string()) + } +} + #[cfg(test)] mod tests { use core::str::FromStr; @@ -818,9 +826,6 @@ mod tests { #[test] fn parse_multiple_gas_prices() { - let gas_prices = "0.25token1;0.0001token2"; - let parsed = parse_gas_prices(gas_prices.to_string()); - let expected = vec![ GasPrice { price: 0.25, @@ -832,7 +837,15 @@ mod tests { }, ]; - assert_eq!(expected, parsed); + let test_cases = vec![ + ("0.25token1;0.0001token2", expected.clone()), + ("0.25token1,0.0001token2", expected.clone()), + ]; + + for (input, expected) in test_cases { + let parsed = parse_gas_prices(input.to_string()); + assert_eq!(expected, parsed); + } } #[test] @@ -845,14 +858,18 @@ mod tests { #[test] fn malformed_gas_prices_do_not_get_parsed() { - let malformed_prices = "token1;.token2;0.25token3"; - let parsed = parse_gas_prices(malformed_prices.to_string()); - let expected = vec![GasPrice { price: 0.25, denom: "token3".to_owned(), }]; + let test_cases = vec![ + ("token1;.token2;0.25token3", expected.clone()), + ("token1,.token2,0.25token3", expected.clone()), + ]; - assert_eq!(expected, parsed); + for (input, expected) in test_cases { + let parsed = parse_gas_prices(input.to_string()); + assert_eq!(expected, parsed); + } } } diff --git a/crates/relayer/src/config/compat_mode.rs b/crates/relayer/src/config/compat_mode.rs new file mode 100644 index 0000000000..79323888f7 --- /dev/null +++ b/crates/relayer/src/config/compat_mode.rs @@ -0,0 +1,97 @@ +use core::fmt::{Display, Error as FmtError, Formatter}; +use core::str::FromStr; +use serde::Deserialize; +use serde::Deserializer; +use serde::Serialize; +use serde::Serializer; + +use tendermint_rpc::client::CompatMode as TmCompatMode; + +use crate::config::Error; + +/// CometBFT RPC compatibility mode +/// +/// Can be removed in favor of the one in tendermint-rs, once +/// is merged. +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum CompatMode { + /// Use version 0.34 of the protocol. + V0_34, + /// Use version 0.37 of the protocol. + V0_37, +} + +impl Display for CompatMode { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + match self { + Self::V0_34 => write!(f, "v0.34"), + Self::V0_37 => write!(f, "v0.37"), + } + } +} + +impl FromStr for CompatMode { + type Err = Error; + + fn from_str(s: &str) -> Result { + const VALID_COMPAT_MODES: &str = "0.34, 0.37"; + + // Trim leading 'v', if present + match s.trim_start_matches('v') { + "0.34" => Ok(CompatMode::V0_34), + "0.37" => Ok(CompatMode::V0_37), + _ => Err(Error::invalid_compat_mode( + s.to_string(), + VALID_COMPAT_MODES, + )), + } + } +} + +impl<'de> Deserialize<'de> for CompatMode { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + use serde::de; + + let s = String::deserialize(deserializer)?; + FromStr::from_str(&s).map_err(de::Error::custom) + } +} + +impl Serialize for CompatMode { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.to_string().serialize(serializer) + } +} + +impl From for CompatMode { + fn from(value: TmCompatMode) -> Self { + match value { + TmCompatMode::V0_34 => Self::V0_34, + TmCompatMode::V0_37 => Self::V0_37, + } + } +} + +impl From for TmCompatMode { + fn from(value: CompatMode) -> Self { + match value { + CompatMode::V0_34 => Self::V0_34, + CompatMode::V0_37 => Self::V0_37, + } + } +} + +impl CompatMode { + pub fn equal_to_tm_compat_mode(&self, tm_compat_mode: TmCompatMode) -> bool { + match self { + Self::V0_34 => tm_compat_mode == TmCompatMode::V0_34, + Self::V0_37 => tm_compat_mode == TmCompatMode::V0_37, + } + } +} diff --git a/crates/relayer/src/config/error.rs b/crates/relayer/src/config/error.rs index 9889e553ad..d2827f33c6 100644 --- a/crates/relayer/src/config/error.rs +++ b/crates/relayer/src/config/error.rs @@ -1,8 +1,36 @@ +use ibc_relayer_types::core::ics24_host::identifier::ChainId; + use flex_error::{define_error, TraceError}; +use tracing_subscriber::filter::ParseError; +// Specifies all the possible errors that a Hermes config file can contain. define_error! { Error { - Io + ZeroChain + |_| { "config file does not specify any chain" }, + + InvalidLogDirective + { directive: String, } + [ TraceError ] + |e| { + format!("invalid log directive: {0:?}", e.directive) + }, + + InvalidMode + { reason: String, } + |e| { + format!("config file specifies invalid mode config, caused by: {0}", + e.reason) + }, + + DuplicateChains + { chain_id: ChainId } + |e| { + format!("config file has duplicate entry for the chain '{0}'", + e.chain_id) + }, + + Io [ TraceError ] |_| { "config I/O error" }, @@ -10,12 +38,26 @@ define_error! { [ TraceError ] |_| { "invalid configuration" }, + InvalidCompatMode + { compat_mode: String, valide_modes: &'static str } + |e| { format!("invalid compatibility mode: '{}' (supported: {})", e.compat_mode, e.valide_modes) }, + Encode [ TraceError ] |_| { "invalid configuration" }, + WrongType + |_| { "wrong configuration type" }, + InvalidGasPrice { price: String } - |e| { format!("invalid gas price: {}", e.price) }, + |e| { + format!("invalid gas price: {}", e.price) + }, + + CosmosConfigError { reason: String } + |e| { + format!("invalid cosmos config: {}", e.reason) + }, } } diff --git a/crates/relayer/src/connection.rs b/crates/relayer/src/connection.rs index 341049446b..5e1ee140be 100644 --- a/crates/relayer/src/connection.rs +++ b/crates/relayer/src/connection.rs @@ -445,12 +445,12 @@ impl Connection { .a_chain() .config() .map_err(ConnectionError::relayer)? - .max_block_time; + .max_block_time(); let b_block_time = self .b_chain() .config() .map_err(ConnectionError::relayer)? - .max_block_time; + .max_block_time(); Ok(a_block_time.max(b_block_time)) } diff --git a/crates/relayer/src/connection/error.rs b/crates/relayer/src/connection/error.rs index f8f026bcfa..ee017b5cc9 100644 --- a/crates/relayer/src/connection/error.rs +++ b/crates/relayer/src/connection/error.rs @@ -187,16 +187,27 @@ define_error! { } impl HasExpiredOrFrozenError for ConnectionErrorDetail { - fn is_expired_or_frozen_error(&self) -> bool { + fn is_frozen_error(&self) -> bool { match self { - Self::ClientOperation(e) => e.source.is_expired_or_frozen_error(), + Self::ClientOperation(e) => e.source.is_frozen_error(), + _ => false, + } + } + + fn is_expired_error(&self) -> bool { + match self { + Self::ClientOperation(e) => e.source.is_expired_error(), _ => false, } } } impl HasExpiredOrFrozenError for ConnectionError { - fn is_expired_or_frozen_error(&self) -> bool { - self.detail().is_expired_or_frozen_error() + fn is_frozen_error(&self) -> bool { + self.detail().is_frozen_error() + } + + fn is_expired_error(&self) -> bool { + self.detail().is_expired_error() } } diff --git a/crates/relayer/src/consensus_state.rs b/crates/relayer/src/consensus_state.rs index 71abf1828d..c6b6f8114e 100644 --- a/crates/relayer/src/consensus_state.rs +++ b/crates/relayer/src/consensus_state.rs @@ -1,25 +1,25 @@ +use serde::{Deserialize, Serialize}; + use ibc_proto::google::protobuf::Any; use ibc_proto::ibc::core::client::v1::ConsensusStateWithHeight; use ibc_proto::ibc::lightclients::tendermint::v1::ConsensusState as RawConsensusState; -#[cfg(test)] -use ibc_proto::ibc::mock::ConsensusState as RawMockConsensusState; -use ibc_proto::protobuf::Protobuf; +use ibc_proto::Protobuf; use ibc_relayer_types::clients::ics07_tendermint::consensus_state::{ ConsensusState as TmConsensusState, TENDERMINT_CONSENSUS_STATE_TYPE_URL, }; use ibc_relayer_types::core::ics02_client::client_type::ClientType; -use ibc_relayer_types::core::ics02_client::consensus_state::{ - downcast_consensus_state, ConsensusState, -}; +use ibc_relayer_types::core::ics02_client::consensus_state::ConsensusState; use ibc_relayer_types::core::ics02_client::error::Error; use ibc_relayer_types::core::ics23_commitment::commitment::CommitmentRoot; +use ibc_relayer_types::timestamp::Timestamp; +use ibc_relayer_types::Height; + +#[cfg(test)] +use ibc_proto::ibc::mock::ConsensusState as RawMockConsensusState; #[cfg(test)] use ibc_relayer_types::mock::consensus_state::MockConsensusState; #[cfg(test)] use ibc_relayer_types::mock::consensus_state::MOCK_CONSENSUS_STATE_TYPE_URL; -use ibc_relayer_types::timestamp::Timestamp; -use ibc_relayer_types::Height; -use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(tag = "type")] @@ -81,12 +81,12 @@ impl From for Any { match value { AnyConsensusState::Tendermint(value) => Any { type_url: TENDERMINT_CONSENSUS_STATE_TYPE_URL.to_string(), - value: Protobuf::::encode_vec(&value), + value: Protobuf::::encode_vec(value), }, #[cfg(test)] AnyConsensusState::Mock(value) => Any { type_url: MOCK_CONSENSUS_STATE_TYPE_URL.to_string(), - value: Protobuf::::encode_vec(&value), + value: Protobuf::::encode_vec(value), }, } } @@ -105,21 +105,6 @@ impl From for AnyConsensusState { } } -impl From<&dyn ConsensusState> for AnyConsensusState { - fn from(cs: &dyn ConsensusState) -> Self { - #[cfg(test)] - if let Some(cs) = downcast_consensus_state::(cs) { - return AnyConsensusState::from(cs.clone()); - } - - if let Some(cs) = downcast_consensus_state::(cs) { - AnyConsensusState::from(cs.clone()) - } else { - unreachable!() - } - } -} - #[derive(Clone, Debug, PartialEq, Eq, Serialize)] pub struct AnyConsensusStateWithHeight { pub height: Height, diff --git a/crates/relayer/src/error.rs b/crates/relayer/src/error.rs index 10e97c08b7..e16a1c4e75 100644 --- a/crates/relayer/src/error.rs +++ b/crates/relayer/src/error.rs @@ -5,9 +5,13 @@ use core::time::Duration; use flex_error::{define_error, DisplayOnly, TraceError}; use http::uri::InvalidUri; use humantime::format_duration; -use ibc_proto::protobuf::Error as TendermintProtoError; use prost::{DecodeError, EncodeError}; use regex::Regex; +use tonic::{ + metadata::errors::InvalidMetadataValue, transport::Error as TransportError, + Status as GrpcStatus, +}; + use tendermint::abci; use tendermint::Error as TendermintError; use tendermint_light_client::builder::error::Error as LightClientBuilderError; @@ -15,28 +19,19 @@ use tendermint_light_client::components::io::IoError as LightClientIoError; use tendermint_light_client::errors::{ Error as LightClientError, ErrorDetail as LightClientErrorDetail, }; +use tendermint_proto::Error as TendermintProtoError; use tendermint_rpc::endpoint::abci_query::AbciQuery; use tendermint_rpc::endpoint::broadcast::tx_sync::Response as TxSyncResponse; use tendermint_rpc::Error as TendermintRpcError; -use tonic::{ - metadata::errors::InvalidMetadataValue, transport::Error as TransportError, - Status as GrpcStatus, -}; -use ibc_relayer_types::{ - applications::{ - ics29_fee::error::Error as FeeError, ics31_icq::error::Error as CrossChainQueryError, - }, - clients::ics07_tendermint::error as tendermint_error, - core::{ - ics02_client::{client_type::ClientType, error as client_error}, - ics03_connection::error as connection_error, - ics23_commitment::error as commitment_error, - ics24_host::identifier::{ChainId, ChannelId, ConnectionId}, - }, - proofs::ProofError, - relayer::ics18_relayer::error as relayer_error, -}; +use ibc_relayer_types::applications::ics29_fee::error::Error as FeeError; +use ibc_relayer_types::applications::ics31_icq::error::Error as CrossChainQueryError; +use ibc_relayer_types::clients::ics07_tendermint::error as tendermint_error; +use ibc_relayer_types::core::ics02_client::{client_type::ClientType, error as client_error}; +use ibc_relayer_types::core::ics03_connection::error as connection_error; +use ibc_relayer_types::core::ics23_commitment::error as commitment_error; +use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, ConnectionId}; +use ibc_relayer_types::proofs::ProofError; use crate::chain::cosmos::version; use crate::chain::cosmos::BLOCK_MAX_BYTES_MAX_FRACTION; @@ -281,10 +276,6 @@ define_error! { [ tendermint_error::Error ] |_| { "ICS 07 error" }, - Ics18 - [ relayer_error::Error ] - |_| { "ICS 18 error" }, - Ics23 [ commitment_error::Error ] |_| { "ICS 23 error" }, @@ -318,7 +309,7 @@ define_error! { ChannelReceiveTimeout [ TraceError ] - |_| { "timeout when waiting for reponse over inter-thread channel" }, + |_| { "timeout when waiting for response over inter-thread channel" }, InvalidInputHeader |_| { "the input header is not recognized as a header for this chain" }, @@ -591,6 +582,10 @@ define_error! { { address: String } [ TendermintRpcError ] |e| { format!("invalid archive node address {}", e.address) }, + + InvalidCompatMode + [ TendermintRpcError ] + |_| { "Invalid CompatMode queried from chain and no `compat_mode` configured in Hermes. This can be fixed by specifying a `compat_mode` in Hermes config.toml" }, } } @@ -653,7 +648,7 @@ impl GrpcStatusSubdetail { /// ## Note /// This error may happen even when packets are submitted in order when the `simulate_tx` /// gRPC endpoint is allowed to be called after a block is created and before - /// Tendermint/mempool finishes `recheck_tx`, similary to the issue described in + /// Tendermint/mempool finishes `recheck_tx`, similarly to the issue described in /// . /// /// See for more info. @@ -691,6 +686,7 @@ impl GrpcStatusSubdetail { fn parse_sequences_in_mismatch_error_message(message: &str) -> Option<(u64, u64)> { let re = Regex::new(r"account sequence mismatch, expected (?P\d+), got (?P\d+)") .unwrap(); + match re.captures(message) { None => None, Some(captures) => match (captures["expected"].parse(), captures["got"].parse()) { diff --git a/crates/relayer/src/event.rs b/crates/relayer/src/event.rs index 7d3e958505..b07ef50a84 100644 --- a/crates/relayer/src/event.rs +++ b/crates/relayer/src/event.rs @@ -8,7 +8,7 @@ use ibc_relayer_types::{ core::ics02_client::{ error::Error as ClientError, events::{self as client_events, Attributes as ClientAttributes, HEADER_ATTRIBUTE_KEY}, - header::Header, + header::{decode_header, AnyHeader}, height::HeightErrorDetail, }, core::ics03_connection::{ @@ -25,8 +25,6 @@ use ibc_relayer_types::{ Height, }; -use crate::light_client::decode_header; - pub mod bus; pub mod error; pub mod source; @@ -327,7 +325,7 @@ fn client_extract_attributes_from_tx(event: &AbciEvent) -> Result Result, ClientError> { +pub fn extract_header_from_tx(event: &AbciEvent) -> Result { for tag in &event.attributes { if tag.key == HEADER_ATTRIBUTE_KEY { let header_bytes = @@ -335,6 +333,7 @@ pub fn extract_header_from_tx(event: &AbciEvent) -> Result, Clie return decode_header(&header_bytes); } } + Err(ClientError::missing_raw_header()) } @@ -463,10 +462,9 @@ mod tests { use super::*; use ibc_proto::google::protobuf::Any; - use ibc_proto::protobuf::Protobuf; + use ibc_proto::Protobuf; use ibc_relayer_types::clients::ics07_tendermint::header::test_util::get_dummy_ics07_header; - use ibc_relayer_types::clients::ics07_tendermint::header::Header as TmHeader; - use ibc_relayer_types::core::ics02_client::header::downcast_header; + use ibc_relayer_types::core::ics02_client::header::{decode_header, AnyHeader}; use ibc_relayer_types::core::ics04_channel::packet::Sequence; use ibc_relayer_types::timestamp::Timestamp; @@ -474,12 +472,12 @@ mod tests { fn extract_header() { let header = get_dummy_ics07_header(); let mut header_bytes = Vec::new(); - Protobuf::::encode(&header, &mut header_bytes).unwrap(); + Protobuf::::encode(header.clone(), &mut header_bytes).unwrap(); let decoded_dyn_header = decode_header(&header_bytes).unwrap(); - let decoded_tm_header: &TmHeader = downcast_header(decoded_dyn_header.as_ref()).unwrap(); + let AnyHeader::Tendermint(decoded_tm_header) = decoded_dyn_header; - assert_eq!(&header, decoded_tm_header); + assert_eq!(header, decoded_tm_header); } #[test] diff --git a/crates/relayer/src/event/source/websocket/extract.rs b/crates/relayer/src/event/source/websocket/extract.rs index ad8db55b6a..18f6bfa07a 100644 --- a/crates/relayer/src/event/source/websocket/extract.rs +++ b/crates/relayer/src/event/source/websocket/extract.rs @@ -171,7 +171,7 @@ pub fn extract_events( if matches!(ibc_event, IbcEvent::SendPacket(_)) { // Should be the same as the hash of tx_result.tx? if let Some(hash) = - events.get("tx.hash").and_then(|values| values.get(0)) + events.get("tx.hash").and_then(|values| values.first()) { tracing::trace!(event = "SendPacket", "tx hash: {}", hash); } diff --git a/crates/relayer/src/foreign_client.rs b/crates/relayer/src/foreign_client.rs index 8a04b21797..46268b94d4 100644 --- a/crates/relayer/src/foreign_client.rs +++ b/crates/relayer/src/foreign_client.rs @@ -13,10 +13,11 @@ use itertools::Itertools; use tracing::{debug, error, info, instrument, trace, warn}; use flex_error::define_error; +use ibc_relayer_types::applications::ics28_ccv::msgs::ccv_misbehaviour::MsgSubmitIcsConsumerMisbehaviour; use ibc_relayer_types::core::ics02_client::client_state::ClientState; use ibc_relayer_types::core::ics02_client::error::Error as ClientError; use ibc_relayer_types::core::ics02_client::events::UpdateClient; -use ibc_relayer_types::core::ics02_client::header::Header; +use ibc_relayer_types::core::ics02_client::header::{AnyHeader, Header}; use ibc_relayer_types::core::ics02_client::msgs::create_client::MsgCreateClient; use ibc_relayer_types::core::ics02_client::msgs::misbehaviour::MsgSubmitMisbehaviour; use ibc_relayer_types::core::ics02_client::msgs::update_client::MsgUpdateClient; @@ -34,11 +35,11 @@ use crate::chain::handle::ChainHandle; use crate::chain::requests::*; use crate::chain::tracking::TrackedMsgs; use crate::client_state::AnyClientState; +use crate::config::ChainConfig; use crate::consensus_state::AnyConsensusState; use crate::error::Error as RelayerError; use crate::event::IbcEventWithHeight; -use crate::light_client::AnyHeader; -use crate::misbehaviour::MisbehaviourEvidence; +use crate::misbehaviour::{AnyMisbehaviour, MisbehaviourEvidence}; use crate::telemetry; use crate::util::collate::CollatedIterExt; use crate::util::pretty::{PrettyDuration, PrettySlice}; @@ -47,6 +48,21 @@ const MAX_MISBEHAVIOUR_CHECK_DURATION: Duration = Duration::from_secs(120); const MAX_RETRIES: usize = 5; +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum ExpiredOrFrozen { + Expired, + Frozen, +} + +impl fmt::Display for ExpiredOrFrozen { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ExpiredOrFrozen::Expired => write!(f, "expired"), + ExpiredOrFrozen::Frozen => write!(f, "frozen"), + } + } +} + define_error! { ForeignClientError { ClientCreate @@ -107,7 +123,7 @@ define_error! { height: Height, } |e| { - format_args!("client {} is already up-to-date with chain {}@{}", + format_args!("client {} is already up-to-date with chain {} at height {}", e.client_id, e.chain_id, e.height) }, @@ -224,13 +240,14 @@ define_error! { ExpiredOrFrozen { + status: ExpiredOrFrozen, client_id: ClientId, chain_id: ChainId, description: String, } |e| { - format_args!("client {0} on chain id {1} is expired or frozen: {2}", - e.client_id, e.chain_id, e.description) + format_args!("client {0} on chain id {1} is {2}: {3}", + e.client_id, e.chain_id, e.status, e.description) }, ConsensusStateNotTrusted @@ -252,6 +269,14 @@ define_error! { format_args!("error raised while checking for misbehaviour evidence: {0}", e.description) }, + MisbehaviourDesc + { + description: String, + } + |e| { + format_args!("error raised while checking for misbehaviour evidence: {0}", e.description) + }, + MisbehaviourExit { reason: String } |e| { @@ -286,18 +311,39 @@ define_error! { } pub trait HasExpiredOrFrozenError { - fn is_expired_or_frozen_error(&self) -> bool; + fn is_expired_error(&self) -> bool; + fn is_frozen_error(&self) -> bool; + + fn is_expired_or_frozen_error(&self) -> bool { + self.is_expired_error() || self.is_frozen_error() + } } impl HasExpiredOrFrozenError for ForeignClientErrorDetail { - fn is_expired_or_frozen_error(&self) -> bool { - matches!(self, Self::ExpiredOrFrozen(_)) + fn is_expired_error(&self) -> bool { + if let Self::ExpiredOrFrozen(e) = self { + e.status == ExpiredOrFrozen::Expired + } else { + false + } + } + + fn is_frozen_error(&self) -> bool { + if let Self::ExpiredOrFrozen(e) = self { + e.status == ExpiredOrFrozen::Frozen + } else { + false + } } } impl HasExpiredOrFrozenError for ForeignClientError { - fn is_expired_or_frozen_error(&self) -> bool { - self.detail().is_expired_or_frozen_error() + fn is_expired_error(&self) -> bool { + self.detail().is_expired_error() + } + + fn is_frozen_error(&self) -> bool { + self.detail().is_frozen_error() } } @@ -595,6 +641,7 @@ impl ForeignClient ForeignClient ForeignClient Ok((client_state, Some(elapsed))), @@ -787,6 +836,20 @@ impl ForeignClient bool { + match self.validated_client_state() { + Ok(_) => false, + Err(e) => e.is_frozen_error(), + } + } + + pub fn is_expired(&self) -> bool { + match self.validated_client_state() { + Ok(_) => false, + Err(e) => e.is_expired_error(), + } + } + pub fn is_expired_or_frozen(&self) -> bool { match self.validated_client_state() { Ok(_) => false, @@ -841,7 +904,10 @@ impl ForeignClient config.client_refresh_rate, + }; + let refresh_period = client_state .trusting_period() .mul_f64(refresh_rate.as_f64()); @@ -1079,6 +1145,31 @@ impl ForeignClient ForeignClient ForeignClient ForeignClient ForeignClient config.ccv_consumer_chain, + }; + let mut msgs = vec![]; for header in evidence.supporting_headers { @@ -1666,6 +1766,30 @@ impl ForeignClient Some(tm_misbehaviour.clone()), + #[cfg(test)] + _ => None, + } + .ok_or_else(|| { + ForeignClientError::misbehaviour_desc(format!( + "underlying evidence is not a Tendermint misbehaviour: {:?}", + evidence.misbehaviour + )) + })?; + + // If the misbehaving chain is a CCV consumer chain, we need to add + // the corresponding CCV message for the provider. + if is_ccv_consumer_chain { + msgs.push( + MsgSubmitIcsConsumerMisbehaviour { + submitter: signer.clone(), + misbehaviour: tm_misbehaviour, + } + .to_any(), + ); + } + msgs.push( MsgSubmitMisbehaviour { misbehaviour: evidence.misbehaviour.into(), @@ -1696,7 +1820,7 @@ impl ForeignClient ForeignClient match e.detail() { ForeignClientErrorDetail::MisbehaviourExit(s) => { - error!("misbehaviour checking is being disabled, reason: {}", s); + error!("misbehaviour checking is being disabled, reason: {s}"); MisbehaviourResults::CannotExecute } ForeignClientErrorDetail::ExpiredOrFrozen(_) => { - error!("cannot check misbehavior on frozen or expired client",); + error!("cannot check misbehavior on frozen or expired client"); MisbehaviourResults::CannotExecute } // FIXME: This is fishy - _ if update_event.is_some() => MisbehaviourResults::CannotExecute, + e if update_event.is_some() => { + error!("encountered unexpected error while checking misbehaviour: {e}"); + debug!("update event: {}", update_event.unwrap()); + + MisbehaviourResults::CannotExecute + } // FIXME: This is fishy _ => { - warn!("misbehaviour checking result: {}", e); + warn!("misbehaviour checking result: {e}"); MisbehaviourResults::ValidClient } diff --git a/crates/relayer/src/keyring.rs b/crates/relayer/src/keyring.rs index b5967b24a7..1260de235e 100644 --- a/crates/relayer/src/keyring.rs +++ b/crates/relayer/src/keyring.rs @@ -21,7 +21,6 @@ use std::path::PathBuf; use ibc_relayer_types::core::ics24_host::identifier::ChainId; use serde::{Deserialize, Serialize}; -use crate::{chain::ChainType, config::ChainConfig}; use errors::Error; pub const KEYSTORE_DEFAULT_FOLDER: &str = ".hermes/keys/"; @@ -287,24 +286,7 @@ impl KeyRing { } } -pub fn list_keys(config: &ChainConfig) -> Result, Error> { - let keys = match config.r#type { - ChainType::CosmosSdk => { - let keyring = KeyRing::new_secp256k1( - Store::Test, - &config.account_prefix, - &config.id, - &config.key_store_folder, - )?; - keyring - .keys()? - .into_iter() - .map(|(key_name, keys)| (key_name, keys.into())) - .collect() - } - }; - Ok(keys) -} +// Why is this not a method on `ChainConfig`? fn disk_store_path(folder_name: &str, keystore_folder: &Option) -> Result { let ks_folder = match keystore_folder { diff --git a/crates/relayer/src/lib.rs b/crates/relayer/src/lib.rs index 8ef35e6629..0bca2140c0 100644 --- a/crates/relayer/src/lib.rs +++ b/crates/relayer/src/lib.rs @@ -16,7 +16,7 @@ //! //! For the IBC relayer binary, please see [Hermes] (`ibc-relayer-cli` crate). //! -//! [Hermes]: https://docs.rs/ibc-relayer-cli/0.2.0/ +//! [Hermes]: https://docs.rs/ibc-relayer-cli/1.7.4/ extern crate alloc; diff --git a/crates/relayer/src/light_client.rs b/crates/relayer/src/light_client.rs index 5f19bba177..2cea5a6ac6 100644 --- a/crates/relayer/src/light_client.rs +++ b/crates/relayer/src/light_client.rs @@ -1,21 +1,8 @@ pub mod io; pub mod tendermint; -use core::ops::Deref; - -use ibc_proto::google::protobuf::Any; -use ibc_proto::ibc::lightclients::tendermint::v1::Header as RawTmHeader; -use ibc_proto::protobuf::Protobuf as ErasedProtobuf; -use ibc_relayer_types::clients::ics07_tendermint::header::{ - decode_header as tm_decode_header, Header as TendermintHeader, TENDERMINT_HEADER_TYPE_URL, -}; -use ibc_relayer_types::core::ics02_client::client_type::ClientType; -use ibc_relayer_types::core::ics02_client::error::Error; use ibc_relayer_types::core::ics02_client::events::UpdateClient; -use ibc_relayer_types::core::ics02_client::header::Header; -use ibc_relayer_types::timestamp::Timestamp; use ibc_relayer_types::Height; -use serde::{Deserialize, Serialize}; use crate::chain::endpoint::ChainEndpoint; use crate::client_state::AnyClientState; @@ -67,75 +54,3 @@ pub trait LightClient: Send + Sync { /// Fetch a header from the chain at the given height, without verifying it fn fetch(&mut self, height: Height) -> Result; } - -/// Decodes an encoded header into a known `Header` type, -pub fn decode_header(header_bytes: &[u8]) -> Result, Error> { - // For now, we only have tendermint; however when there is more than one, we - // can try decoding into all the known types, and return an error only if - // none work - let header: TendermintHeader = - ErasedProtobuf::::decode(header_bytes).map_err(Error::invalid_raw_header)?; - - Ok(Box::new(header)) -} - -#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] -#[allow(clippy::large_enum_variant)] -pub enum AnyHeader { - Tendermint(TendermintHeader), -} - -impl Header for AnyHeader { - fn client_type(&self) -> ClientType { - match self { - Self::Tendermint(header) => header.client_type(), - } - } - - fn height(&self) -> Height { - match self { - Self::Tendermint(header) => header.height(), - } - } - - fn timestamp(&self) -> Timestamp { - match self { - Self::Tendermint(header) => header.timestamp(), - } - } -} - -impl ErasedProtobuf for AnyHeader {} - -impl TryFrom for AnyHeader { - type Error = Error; - - fn try_from(raw: Any) -> Result { - match raw.type_url.as_str() { - TENDERMINT_HEADER_TYPE_URL => { - let val = tm_decode_header(raw.value.deref())?; - - Ok(AnyHeader::Tendermint(val)) - } - - _ => Err(Error::unknown_header_type(raw.type_url)), - } - } -} - -impl From for Any { - fn from(value: AnyHeader) -> Self { - match value { - AnyHeader::Tendermint(header) => Any { - type_url: TENDERMINT_HEADER_TYPE_URL.to_string(), - value: ErasedProtobuf::::encode_vec(&header), - }, - } - } -} - -impl From for AnyHeader { - fn from(header: TendermintHeader) -> Self { - Self::Tendermint(header) - } -} diff --git a/crates/relayer/src/light_client/tendermint.rs b/crates/relayer/src/light_client/tendermint.rs index 5e3d4c3fae..1927b0558e 100644 --- a/crates/relayer/src/light_client/tendermint.rs +++ b/crates/relayer/src/light_client/tendermint.rs @@ -20,23 +20,21 @@ use tendermint_light_client::{ use tendermint_light_client_detector::Divergence; use tendermint_rpc as rpc; -use ibc_relayer_types::{ - clients::ics07_tendermint::{ - header::Header as TmHeader, misbehaviour::Misbehaviour as TmMisbehaviour, - }, - core::{ - ics02_client::{client_type::ClientType, events::UpdateClient, header::downcast_header}, - ics24_host::identifier::ChainId, - }, - downcast, Height as ICSHeight, -}; +use ibc_relayer_types::clients::ics07_tendermint::header::Header as TmHeader; +use ibc_relayer_types::clients::ics07_tendermint::misbehaviour::Misbehaviour as TmMisbehaviour; +use ibc_relayer_types::core::ics02_client::events::UpdateClient; +use ibc_relayer_types::core::ics02_client::header::AnyHeader; +use ibc_relayer_types::core::ics24_host::identifier::ChainId; +use ibc_relayer_types::Height as ICSHeight; + +#[cfg(test)] +use ibc_relayer_types::core::ics02_client::client_type::ClientType; use crate::{ + chain::cosmos::config::CosmosSdkConfig, chain::cosmos::CosmosSdkChain, client_state::AnyClientState, - config::ChainConfig, error::Error, - light_client::AnyHeader, misbehaviour::{AnyMisbehaviour, MisbehaviourEvidence}, }; @@ -139,28 +137,26 @@ impl super::LightClient for LightClient { } ); - let update_header = update.header.as_ref().ok_or_else(|| { + let any_header = update.header.as_ref().ok_or_else(|| { Error::misbehaviour(format!( "missing header in update client event {}", self.chain_id )) })?; - let update_header: &TmHeader = - downcast_header(update_header.as_ref()).ok_or_else(|| { - Error::misbehaviour(format!( - "header type incompatible for chain {}", - self.chain_id - )) - })?; + let update_header: &TmHeader = match any_header { + AnyHeader::Tendermint(header) => Ok(header), + }?; - let client_state = - downcast!(client_state => AnyClientState::Tendermint).ok_or_else(|| { - Error::misbehaviour(format!( - "client type incompatible for chain {}", - self.chain_id - )) - })?; + let client_state = match client_state { + AnyClientState::Tendermint(client_state) => Ok(client_state), + + #[cfg(test)] + _ => Err(Error::misbehaviour(format!( + "client type incompatible for chain {}", + self.chain_id + ))), + }?; let next_validators = self .io @@ -177,7 +173,8 @@ impl super::LightClient for LightClient { provider: self.peer_id, }; - let trusted_block = self.fetch(update_header.trusted_height)?; + // Get the light block at trusted_height + 1 from chain. + let trusted_block = self.fetch(update_header.trusted_height.increment())?; if trusted_block.validators.hash() != update_header.trusted_validator_set.hash() { return Err(Error::misbehaviour(format!( "mismatch between the trusted validator set of the update \ @@ -207,13 +204,18 @@ impl super::LightClient for LightClient { challenging_block, })) => { warn!("misbehavior detected, reporting evidence to RPC witness node and primary chain"); + debug!("evidence: {evidence:#?}"); + debug!("challenging block: {challenging_block:#?}"); + + warn!("waiting 5 seconds before reporting evidence to RPC witness node"); + std::thread::sleep(Duration::from_secs(5)); match detector::report_evidence( self.io.rpc_client().clone(), evidence.against_primary, ) { Ok(hash) => warn!("evidence reported to RPC witness node with hash: {hash}"), - Err(e) => error!("failed to report evidence to RPC witness node: {}", e), + Err(e) => error!("failed to report evidence to RPC witness node: {e}"), } let target_block = self.fetch(update_header.height())?; @@ -267,7 +269,10 @@ fn io_for_addr( } impl LightClient { - pub fn from_config(config: &ChainConfig, peer_id: PeerId) -> Result { + pub fn from_cosmos_sdk_config( + config: &CosmosSdkConfig, + peer_id: PeerId, + ) -> Result { let live_io = io_for_addr(&config.rpc_addr, peer_id, Some(config.rpc_timeout))?; let io = match &config.genesis_restart { @@ -310,10 +315,15 @@ impl LightClient { let verifier = ProdVerifier::default(); let scheduler = components::scheduler::basic_bisecting_schedule; - let client_state = - downcast!(client_state => AnyClientState::Tendermint).ok_or_else(|| { - Error::client_type_mismatch(ClientType::Tendermint, client_state.client_type()) - })?; + let client_state = match client_state { + AnyClientState::Tendermint(client_state) => Ok(client_state), + + #[cfg(test)] + _ => Err(Error::client_type_mismatch( + ClientType::Tendermint, + client_state.client_type(), + )), + }?; Ok(TmLightClient::new( self.peer_id, diff --git a/crates/relayer/src/link/error.rs b/crates/relayer/src/link/error.rs index 697c8cf994..adf8142ec8 100644 --- a/crates/relayer/src/link/error.rs +++ b/crates/relayer/src/link/error.rs @@ -152,16 +152,27 @@ define_error! { } impl HasExpiredOrFrozenError for LinkErrorDetail { - fn is_expired_or_frozen_error(&self) -> bool { + fn is_frozen_error(&self) -> bool { match self { - Self::Client(e) => e.source.is_expired_or_frozen_error(), + Self::Client(e) => e.source.is_frozen_error(), + _ => false, + } + } + + fn is_expired_error(&self) -> bool { + match self { + Self::Client(e) => e.source.is_expired_error(), _ => false, } } } impl HasExpiredOrFrozenError for LinkError { - fn is_expired_or_frozen_error(&self) -> bool { - self.detail().is_expired_or_frozen_error() + fn is_frozen_error(&self) -> bool { + self.detail().is_frozen_error() + } + + fn is_expired_error(&self) -> bool { + self.detail().is_expired_error() } } diff --git a/crates/relayer/src/link/relay_path.rs b/crates/relayer/src/link/relay_path.rs index dc01a71f70..df23940a91 100644 --- a/crates/relayer/src/link/relay_path.rs +++ b/crates/relayer/src/link/relay_path.rs @@ -294,7 +294,7 @@ impl RelayPath { .src_chain() .config() .map_err(LinkError::relayer)? - .max_block_time) + .max_block_time()) } pub(crate) fn dst_max_block_time(&self) -> Result { @@ -302,7 +302,7 @@ impl RelayPath { .dst_chain() .config() .map_err(LinkError::relayer)? - .max_block_time) + .max_block_time()) } fn unordered_channel(&self) -> bool { @@ -513,7 +513,7 @@ impl RelayPath { .entered(); let input = events.events(); - let src_height = match input.get(0) { + let src_height = match input.first() { None => return Ok((None, None)), Some(ev) => ev.height, }; @@ -988,7 +988,7 @@ impl RelayPath { // All updates were successful, no errors and no misbehaviour. (None, Some(update_event_height), None) => Ok(update_event_height), (Some(chain_error), _, _) => { - // Atleast one chain-error so retry if possible. + // At least one chain-error so retry if possible. if retries_left == 0 { Err(LinkError::client(ForeignClientError::chain_error_event( self.dst_chain().id(), @@ -1012,7 +1012,7 @@ impl RelayPath { _ => Err(LinkError::update_client_failed()), } } - // Atleast one misbehaviour event, so don't retry. + // At least one misbehaviour event, so don't retry. (_, _, Some(_misbehaviour)) => Err(LinkError::update_client_failed()), } } @@ -1055,7 +1055,7 @@ impl RelayPath { // All updates were successful, no errors and no misbehaviour. (None, Some(update_event_height), None) => Ok(update_event_height), (Some(chain_error), _, _) => { - // Atleast one chain-error so retry if possible. + // At least one chain-error so retry if possible. if retries_left == 0 { Err(LinkError::client(ForeignClientError::chain_error_event( self.src_chain().id(), diff --git a/crates/relayer/src/misbehaviour.rs b/crates/relayer/src/misbehaviour.rs index 3b0c95b9a3..4d11974149 100644 --- a/crates/relayer/src/misbehaviour.rs +++ b/crates/relayer/src/misbehaviour.rs @@ -1,19 +1,20 @@ -use ibc_proto::{google::protobuf::Any, protobuf::Protobuf}; +use serde::{Deserialize, Serialize}; + +use ibc_proto::google::protobuf::Any; use ibc_relayer_types::clients::ics07_tendermint::misbehaviour::{ Misbehaviour as TmMisbehaviour, TENDERMINT_MISBEHAVIOR_TYPE_URL, }; -use ibc_relayer_types::core::{ - ics02_client::{error::Error, misbehaviour::Misbehaviour}, - ics24_host::identifier::ClientId, -}; +use ibc_relayer_types::core::ics02_client::error::Error; +use ibc_relayer_types::core::ics02_client::header::AnyHeader; +use ibc_relayer_types::core::ics02_client::misbehaviour::Misbehaviour; +use ibc_relayer_types::core::ics24_host::identifier::ClientId; +use ibc_relayer_types::Height; +use tendermint_proto::Protobuf; + #[cfg(test)] use ibc_relayer_types::mock::misbehaviour::Misbehaviour as MockMisbehaviour; #[cfg(test)] use ibc_relayer_types::mock::misbehaviour::MOCK_MISBEHAVIOUR_TYPE_URL; -use ibc_relayer_types::Height; -use serde::{Deserialize, Serialize}; - -use crate::light_client::AnyHeader; #[derive(Clone, Debug, PartialEq, Eq)] pub struct MisbehaviourEvidence { diff --git a/crates/relayer/src/object.rs b/crates/relayer/src/object.rs index bc1ee67591..333212c6ec 100644 --- a/crates/relayer/src/object.rs +++ b/crates/relayer/src/object.rs @@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize}; use ibc_relayer_types::applications::ics29_fee::events::IncentivizedPacket; use ibc_relayer_types::core::{ - ics02_client::{client_state::ClientState, events::UpdateClient}, + ics02_client::events::UpdateClient, ics03_connection::events::Attributes as ConnectionAttributes, ics04_channel::events::{ Attributes, CloseInit, SendPacket, TimeoutPacket, WriteAcknowledgement, diff --git a/crates/relayer/src/rest.rs b/crates/relayer/src/rest.rs index bf46c4678e..8894c58330 100644 --- a/crates/relayer/src/rest.rs +++ b/crates/relayer/src/rest.rs @@ -62,7 +62,7 @@ pub fn process_incoming_requests(config: &Config, channel: &Receiver) -> Option< trace!("GetChains"); reply_to - .send(Ok(config.chains.iter().map(|c| c.id.clone()).collect())) + .send(Ok(config.chains.iter().map(|c| c.id().clone()).collect())) .unwrap_or_else(|e| error!("error replying to a REST request {}", e)); } diff --git a/crates/relayer/src/spawn.rs b/crates/relayer/src/spawn.rs index f71a65eb70..113ac1f6a7 100644 --- a/crates/relayer/src/spawn.rs +++ b/crates/relayer/src/spawn.rs @@ -6,8 +6,8 @@ use tokio::runtime::Runtime as TokioRuntime; use ibc_relayer_types::core::ics24_host::identifier::ChainId; use crate::{ - chain::{cosmos::CosmosSdkChain, handle::ChainHandle, runtime::ChainRuntime, ChainType}, - config::Config, + chain::{cosmos::CosmosSdkChain, handle::ChainHandle, runtime::ChainRuntime}, + config::{ChainConfig, Config}, error::Error as RelayerError, }; @@ -52,8 +52,36 @@ pub fn spawn_chain_runtime( .cloned() .ok_or_else(|| SpawnError::missing_chain_config(chain_id.clone()))?; - let handle = match chain_config.r#type { - ChainType::CosmosSdk => ChainRuntime::::spawn::(chain_config, rt), + spawn_chain_runtime_with_config(chain_config, rt) +} + +/// Spawns a chain runtime from the configuration and given a chain identifier, +/// allowing the caller to modify the chain config. +/// Returns the corresponding handle if successful. +pub fn spawn_chain_runtime_with_modified_config( + config: &Config, + chain_id: &ChainId, + rt: Arc, + modify: impl FnOnce(&mut ChainConfig), +) -> Result { + let mut chain_config = config + .find_chain(chain_id) + .cloned() + .ok_or_else(|| SpawnError::missing_chain_config(chain_id.clone()))?; + + modify(&mut chain_config); + + spawn_chain_runtime_with_config(chain_config, rt) +} + +/// Spawns a chain runtime from the given chain configuration +/// Returns the corresponding handle if successful. +pub fn spawn_chain_runtime_with_config( + config: ChainConfig, + rt: Arc, +) -> Result { + let handle = match config { + ChainConfig::CosmosSdk(_) => ChainRuntime::::spawn(config, rt), } .map_err(SpawnError::relayer)?; diff --git a/crates/relayer/src/supervisor.rs b/crates/relayer/src/supervisor.rs index 8a28d07605..cab6f55c82 100644 --- a/crates/relayer/src/supervisor.rs +++ b/crates/relayer/src/supervisor.rs @@ -619,7 +619,7 @@ fn health_check(config: &Config, registry: &mut Registry( let mut subscriptions = Vec::with_capacity(chains.len()); for chain_config in chains { - let chain = match registry.get_or_spawn(&chain_config.id) { + let chain = match registry.get_or_spawn(chain_config.id()) { Ok(chain) => chain, Err(e) => { error!( "failed to spawn chain runtime for {}: {}", - chain_config.id, e + chain_config.id(), + e ); continue; @@ -667,7 +668,8 @@ fn init_subscriptions( Ok(subscription) => subscriptions.push((chain, subscription)), Err(e) => error!( "failed to subscribe to events of {}: {}", - chain_config.id, e + chain_config.id(), + e ), } } diff --git a/crates/relayer/src/supervisor/client_state_filter.rs b/crates/relayer/src/supervisor/client_state_filter.rs index 0203b563f4..87133e89b7 100644 --- a/crates/relayer/src/supervisor/client_state_filter.rs +++ b/crates/relayer/src/supervisor/client_state_filter.rs @@ -4,7 +4,6 @@ use flex_error::define_error; use ibc_relayer_types::core::ics02_client::trust_threshold::TrustThreshold; use tracing::{debug, trace}; -use ibc_relayer_types::core::ics02_client::client_state::ClientState; use ibc_relayer_types::core::ics03_connection::connection::ConnectionEnd; use ibc_relayer_types::core::ics04_channel::error::Error as ChannelError; use ibc_relayer_types::core::ics24_host::identifier::{ diff --git a/crates/relayer/src/supervisor/scan.rs b/crates/relayer/src/supervisor/scan.rs index 1b4cf705e2..d5dd77d364 100644 --- a/crates/relayer/src/supervisor/scan.rs +++ b/crates/relayer/src/supervisor/scan.rs @@ -5,7 +5,6 @@ use itertools::Itertools; use tracing::{debug, error, error_span, info, warn}; use ibc_relayer_types::core::{ - ics02_client::client_state::ClientState, ics03_connection::connection::{IdentifiedConnectionEnd, State as ConnectionState}, ics04_channel::{ channel::{IdentifiedChannelEnd, State as ChannelState}, @@ -302,14 +301,14 @@ impl<'a, Chain: ChainHandle> ChainScanner<'a, Chain> { } pub fn scan_chain(&mut self, chain_config: &ChainConfig) -> Result { - let span = error_span!("scan.chain", chain = %chain_config.id); + let span = error_span!("scan.chain", chain = %chain_config.id()); let _guard = span.enter(); info!("scanning chain..."); - telemetry!(init_per_chain, &chain_config.id); + telemetry!(init_per_chain, chain_config.id()); - let chain = match self.registry.get_or_spawn(&chain_config.id) { + let chain = match self.registry.get_or_spawn(chain_config.id()) { Ok(chain_handle) => chain_handle, Err(e) => { error!( @@ -321,7 +320,7 @@ impl<'a, Chain: ChainHandle> ChainScanner<'a, Chain> { } }; - let mut scan = ChainScan::new(chain_config.id.clone()); + let mut scan = ChainScan::new(chain_config.id().clone()); match self.use_allow_list(chain_config) { Some(spec) if self.scan_mode == ScanMode::Auto => { @@ -589,7 +588,7 @@ impl<'a, Chain: ChainHandle> ChainScanner<'a, Chain> { return None; } - match chain_config.packet_filter.channel_policy { + match chain_config.packet_filter().channel_policy { ChannelPolicy::Allow(ref filters) if filters.is_exact() => Some(filters), _ => None, } diff --git a/crates/relayer/src/supervisor/spawn.rs b/crates/relayer/src/supervisor/spawn.rs index c7ffd2a240..b1b608875c 100644 --- a/crates/relayer/src/supervisor/spawn.rs +++ b/crates/relayer/src/supervisor/spawn.rs @@ -1,7 +1,7 @@ use tracing::{error, info}; use ibc_relayer_types::core::{ - ics02_client::client_state::ClientState, ics03_connection::connection::IdentifiedConnectionEnd, + ics03_connection::connection::IdentifiedConnectionEnd, ics04_channel::channel::State as ChannelState, }; diff --git a/crates/relayer/src/upgrade_chain.rs b/crates/relayer/src/upgrade_chain.rs index d885fa5a0e..3c6b407f5c 100644 --- a/crates/relayer/src/upgrade_chain.rs +++ b/crates/relayer/src/upgrade_chain.rs @@ -8,10 +8,11 @@ use flex_error::define_error; use tendermint::Hash as TxHash; -use ibc_proto::cosmos::gov::v1beta1::MsgSubmitProposal; +use ibc_proto::cosmos::gov::v1::MsgSubmitProposal; +use ibc_proto::cosmos::gov::v1beta1::MsgSubmitProposal as LegacyMsgSubmitProposal; use ibc_proto::cosmos::upgrade::v1beta1::Plan; use ibc_proto::google::protobuf::Any; -use ibc_proto::ibc::core::client::v1::UpgradeProposal; +use ibc_proto::ibc::core::client::v1::{MsgIbcSoftwareUpgrade, UpgradeProposal}; use ibc_relayer_types::clients::ics07_tendermint::client_state::UpgradeOptions; use ibc_relayer_types::core::ics02_client::client_state::ClientState; use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ClientId}; @@ -66,6 +67,7 @@ pub struct UpgradePlanOptions { pub upgraded_chain_id: ChainId, pub upgraded_unbonding_period: Option, pub upgrade_plan_name: String, + pub gov_account: String, } pub fn build_and_send_ibc_upgrade_proposal( @@ -73,6 +75,52 @@ pub fn build_and_send_ibc_upgrade_proposal( src_chain: impl ChainHandle, // the source chain; supplies a client state for building the upgrade plan opts: &UpgradePlanOptions, ) -> Result { + let any_msg = if requires_legacy_upgrade_proposal(dst_chain.clone()) { + build_legacy_upgrade_proposal(dst_chain.clone(), src_chain, opts) + } else { + build_upgrade_proposal(dst_chain.clone(), src_chain, opts) + }?; + + // Can't use send_messages_and_wait_commit because no IBC events + // corresponding to the transaction can be recognized to confirm the + // upgrade. + // https://github.com/informalsystems/hermes/issues/1288#issuecomment-1066884163 + + let responses = dst_chain + .send_messages_and_wait_check_tx(TrackedMsgs::new_single(any_msg, "upgrade")) + .map_err(|e| UpgradeChainError::submit(dst_chain.id(), e))?; + + Ok(responses[0].hash) +} + +/// Looks at the ibc-go version to determine if the legacy `UpgradeProposal` message +/// or if the newer `MsgIBCSoftwareUpdate` message should be used to upgrade the chain. +/// If the ibc-go version returned isn't reliable, a deprecated version, then the version +/// of Cosmos SDK is used. +pub fn requires_legacy_upgrade_proposal(dst_chain: impl ChainHandle) -> bool { + let version_specs = dst_chain.version_specs().unwrap(); + match version_specs.ibc_go { + Some(ibc_version) => { + // Some ibc-go simapps return unreliable ibc-go versions, such as simapp v8.0.0 + // returns version v1.0.0. So if the ibc-go version matches which is not maintained + // anymore, use the Cosmos SDK version to determine if the legacy upgrade proposal + // has to be used + if ibc_version.major < 4 { + version_specs.cosmos_sdk.minor < 50 + } else { + ibc_version.major < 8 + } + } + None => version_specs.cosmos_sdk.minor < 50, + } +} + +/// Ibc-go versions up to v7.x.x use the deprecated `UpgradeProposal` to upgrade a chain +fn build_legacy_upgrade_proposal( + dst_chain: impl ChainHandle, // the chain which will undergo an upgrade + src_chain: impl ChainHandle, // the source chain; supplies a client state for building the upgrade plan + opts: &UpgradePlanOptions, +) -> Result { let plan_height = dst_chain .query_latest_height() // FIXME(romac): Use query_chain_latest_height once added to ChainHandle .map_err(UpgradeChainError::query)? @@ -109,7 +157,7 @@ pub fn build_and_send_ibc_upgrade_proposal( client_state.upgrade( upgraded_client_latest_height, - &upgrade_options, + upgrade_options, opts.upgraded_chain_id.clone(), ); @@ -125,7 +173,7 @@ pub fn build_and_send_ibc_upgrade_proposal( }), }; - let proposal = Proposal::Default(proposal); + let proposal = Proposal::Legacy(proposal); let mut buf_proposal = Vec::new(); proposal.encode(&mut buf_proposal); @@ -142,7 +190,7 @@ pub fn build_and_send_ibc_upgrade_proposal( amount: opts.amount.to_string(), }; - let msg = MsgSubmitProposal { + let msg = LegacyMsgSubmitProposal { content: Some(any_proposal), initial_deposit: vec![coins], proposer: proposer.to_string(), @@ -150,38 +198,121 @@ pub fn build_and_send_ibc_upgrade_proposal( let mut buf_msg = Vec::new(); prost::Message::encode(&msg, &mut buf_msg).unwrap(); - let any_msg = Any { + Ok(Any { type_url: "/cosmos.gov.v1beta1.MsgSubmitProposal".to_string(), value: buf_msg, + }) +} + +/// Since ibc-go version to v8.x.x `MsgIbcSoftwareUpgrade` is used to upgrade a chain +fn build_upgrade_proposal( + dst_chain: impl ChainHandle, // the chain which will undergo an upgrade + src_chain: impl ChainHandle, // the source chain; supplies a client state for building the upgrade plan + opts: &UpgradePlanOptions, +) -> Result { + let plan_height = dst_chain + .query_latest_height() // FIXME(romac): Use query_chain_latest_height once added to ChainHandle + .map_err(UpgradeChainError::query)? + .add(opts.height_offset); + + let upgraded_client_latest_height = + if dst_chain.id().version() == opts.upgraded_chain_id.version() { + plan_height.increment() + } else { + Height::new(opts.upgraded_chain_id.version(), 1).map_err(|_| { + UpgradeChainError::upgrade_height_revision(opts.upgraded_chain_id.version()) + })? + }; + + let (client_state, _) = src_chain + .query_client_state( + QueryClientStateRequest { + client_id: opts.src_client_id.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map_err(UpgradeChainError::query)?; + + let mut client_state = downcast!(client_state => AnyClientState::Tendermint) + .ok_or_else(UpgradeChainError::tendermint_only)?; + + // Retain the old unbonding period in case the user did not specify a new one + let upgrade_options = UpgradeOptions { + unbonding_period: opts + .upgraded_unbonding_period + .unwrap_or(client_state.unbonding_period), }; - // Can't use send_messages_and_wait_commit because no IBC events - // corresponding to the transaction can be recognized to confirm the - // upgrade. - // https://github.com/informalsystems/hermes/issues/1288#issuecomment-1066884163 + client_state.upgrade( + upgraded_client_latest_height, + upgrade_options, + opts.upgraded_chain_id.clone(), + ); - let responses = dst_chain - .send_messages_and_wait_check_tx(TrackedMsgs::new_single(any_msg, "upgrade")) - .map_err(|e| UpgradeChainError::submit(dst_chain.id(), e))?; + let proposal = MsgIbcSoftwareUpgrade { + plan: Some(Plan { + name: opts.upgrade_plan_name.clone(), + height: plan_height.revision_height() as i64, + info: "".to_string(), + ..Default::default() // deprecated fields - time & upgraded_client_state + }), + upgraded_client_state: Some(Any::from(AnyClientState::from(client_state))), + signer: opts.gov_account.clone(), + }; - Ok(responses[0].hash) + let proposal = Proposal::Default(proposal); + + let mut buf_proposal = Vec::new(); + proposal.encode(&mut buf_proposal); + let any_proposal = Any { + type_url: proposal.type_url(), + value: buf_proposal, + }; + + // build the msg submit proposal + let proposer = dst_chain.get_signer().map_err(UpgradeChainError::key)?; + + let coins = ibc_proto::cosmos::base::v1beta1::Coin { + denom: opts.denom.clone(), + amount: opts.amount.to_string(), + }; + + let msg = MsgSubmitProposal { + messages: vec![any_proposal], + initial_deposit: vec![coins], + proposer: proposer.to_string(), + metadata: "".to_string(), + title: "proposal 0".to_string(), + summary: "upgrade the chain software and unbonding period".to_string(), + }; + + let mut buf_msg = Vec::new(); + prost::Message::encode(&msg, &mut buf_msg).unwrap(); + Ok(Any { + type_url: "/cosmos.gov.v1.MsgSubmitProposal".to_string(), + value: buf_msg, + }) } enum Proposal { - Default(UpgradeProposal), + Default(MsgIbcSoftwareUpgrade), + Legacy(UpgradeProposal), } impl Proposal { fn encode(&self, buf: &mut impl BufMut) { match self { Proposal::Default(p) => prost::Message::encode(p, buf), + Proposal::Legacy(p) => prost::Message::encode(p, buf), } .unwrap() } fn type_url(&self) -> String { match self { - Proposal::Default(_) => "/ibc.core.client.v1.UpgradeProposal", + Proposal::Default(_) => "/ibc.core.client.v1.MsgIBCSoftwareUpgrade", + Proposal::Legacy(_) => "/ibc.core.client.v1.UpgradeProposal", } .to_owned() } diff --git a/crates/relayer/src/util.rs b/crates/relayer/src/util.rs index 589b2f5ff4..e944c2023a 100644 --- a/crates/relayer/src/util.rs +++ b/crates/relayer/src/util.rs @@ -2,6 +2,7 @@ mod block_on; pub use block_on::{block_on, spawn_blocking}; pub mod collate; +pub mod compat_mode; pub mod debug_section; pub mod diff; pub mod iter; diff --git a/crates/relayer/src/util/compat_mode.rs b/crates/relayer/src/util/compat_mode.rs new file mode 100644 index 0000000000..fd4bc1ed1a --- /dev/null +++ b/crates/relayer/src/util/compat_mode.rs @@ -0,0 +1,27 @@ +use tracing::warn; + +use tendermint::Version; +use tendermint_rpc::client::CompatMode as TmCompatMode; + +use crate::config::compat_mode::CompatMode; +use crate::error::Error; + +/// This is a wrapper around tendermint-rs CompatMode::from_version() method. +/// +pub fn compat_mode_from_version( + configured_version: &Option, + version: Version, +) -> Result { + let queried_version = TmCompatMode::from_version(version); + + // This will prioritize the use of the CompatMode specified in Hermes configuration file + match (configured_version, queried_version) { + (Some(configured), Ok(queried)) if !configured.equal_to_tm_compat_mode(queried) => { + warn!("be wary of potential `compat_mode` misconfiguration. Configured version: {}, chain version: {}. Hermes will use the configured `compat_mode` version `{}`. If this configuration is done on purpose this message can be ignored.", configured, queried, configured); + Ok(configured.clone()) + } + (Some(configured), _) => Ok(configured.clone()), + (_, Ok(queried)) => Ok(queried.into()), + (_, Err(e)) => Err(Error::invalid_compat_mode(e)), + } +} diff --git a/crates/relayer/src/util/pretty.rs b/crates/relayer/src/util/pretty.rs index 4ab24b4ba6..0b433bd289 100644 --- a/crates/relayer/src/util/pretty.rs +++ b/crates/relayer/src/util/pretty.rs @@ -111,7 +111,7 @@ pub struct PrettyFee<'a>(pub &'a Fee); impl Display for PrettyFee<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { - let amount = match self.0.amount.get(0) { + let amount = match self.0.amount.first() { Some(coin) => format!("{}{}", coin.amount, coin.denom), None => "".to_string(), }; diff --git a/crates/relayer/src/util/task.rs b/crates/relayer/src/util/task.rs index 3a3638b864..34e2906814 100644 --- a/crates/relayer/src/util/task.rs +++ b/crates/relayer/src/util/task.rs @@ -38,14 +38,14 @@ struct DropJoinHandle(Option>); */ pub enum TaskError { /** - Inform the background task runner that an ignorable error has occured, + Inform the background task runner that an ignorable error has occurred, and the background task runner should log the error and then continue execution. */ Ignore(E), /** - Inform the background task runner that a fatal error has occured, + Inform the background task runner that a fatal error has occurred, and the background task runner should log the error and then abort execution. */ @@ -61,7 +61,7 @@ pub enum Next { Spawn a long-running background task with the given step runner. The step runner is a `FnMut` closure that is called repeatedly and - returns a `Result<(), TaskError>`. If the step is executed successfuly, + returns a `Result<(), TaskError>`. If the step is executed successfully, the step runner should return `Ok(())` so that it will be called again. Otherwise if errors occurred or of the task needs to be aborted, diff --git a/crates/relayer/src/worker.rs b/crates/relayer/src/worker.rs index 571be7792a..915c49ce66 100644 --- a/crates/relayer/src/worker.rs +++ b/crates/relayer/src/worker.rs @@ -130,25 +130,36 @@ pub fn spawn_worker_tasks( let (cmd_tx, cmd_rx) = crossbeam_channel::unbounded(); let link = Arc::new(Mutex::new(link)); - let resubmit = Resubmit::from_clear_interval(packets_config.clear_interval); - - let src_chain_config = - config.chains.iter().find(|chain| chain.id == chains.a.id()); - - let fee_filter = match src_chain_config { - Some(chain_config) => chain_config - .packet_filter - .min_fees - .iter() - .find(|(channel, _)| channel.matches(&path.src_channel_id)) - .map(|(_, filter)| filter) - .cloned(), + + let src_chain_config = config + .chains + .iter() + .find(|chain| *chain.id() == chains.a.id()); + + let (fee_filter, clear_interval) = match src_chain_config { + Some(chain_config) => { + let chain_clear_interval = chain_config + .clear_interval() + .unwrap_or(packets_config.clear_interval); + + let fee_filter = chain_config + .packet_filter() + .min_fees + .iter() + .find(|(channel, _)| channel.matches(&path.src_channel_id)) + .map(|(_, filter)| filter) + .cloned(); + + (fee_filter, chain_clear_interval) + } None => { error!("configuration for chain {} not found", chains.a.id()); - None + (None, packets_config.clear_interval) } }; + let resubmit = Resubmit::from_clear_interval(clear_interval); + // Only spawn the incentivized worker if a fee filter is specified in the configuration let packet_task = match fee_filter { Some(filter) => packet::spawn_incentivized_packet_cmd_worker( @@ -161,7 +172,7 @@ pub fn spawn_worker_tasks( cmd_rx, link.clone(), should_clear_on_start, - packets_config.clear_interval, + clear_interval, path.clone(), ), }; diff --git a/crates/relayer/src/worker/channel.rs b/crates/relayer/src/worker/channel.rs index a6204a3df4..df80e9252b 100644 --- a/crates/relayer/src/worker/channel.rs +++ b/crates/relayer/src/worker/channel.rs @@ -19,11 +19,11 @@ fn max_block_times( ) -> Duration { let a_block_time = match chains.a.config() { Err(_e) => Duration::from_millis(500), - Ok(config) => config.max_block_time, + Ok(config) => config.max_block_time(), }; let b_block_time = match chains.b.config() { Err(_e) => Duration::from_millis(500), - Ok(config) => config.max_block_time, + Ok(config) => config.max_block_time(), }; a_block_time.max(b_block_time) } diff --git a/crates/relayer/src/worker/cross_chain_query.rs b/crates/relayer/src/worker/cross_chain_query.rs index 96aaa633e2..811bb14b36 100644 --- a/crates/relayer/src/worker/cross_chain_query.rs +++ b/crates/relayer/src/worker/cross_chain_query.rs @@ -100,7 +100,7 @@ fn handle_cross_chain_query( let target_height = Height::new( chain_b_handle.id().version(), - cross_chain_query_responses.get(0).unwrap().height as u64, + cross_chain_query_responses.first().unwrap().height as u64, ) .map_err(|_| TaskError::Fatal(RunError::query()))? .increment(); diff --git a/crates/relayer/src/worker/map.rs b/crates/relayer/src/worker/map.rs index 65d80d1af1..c5305f52cb 100644 --- a/crates/relayer/src/worker/map.rs +++ b/crates/relayer/src/worker/map.rs @@ -125,7 +125,17 @@ impl WorkerMap { config: &Config, ) -> &WorkerHandle { if self.workers.contains_key(&object) { - &self.workers[&object] + if self.workers[&object].shutdown_stopped_tasks() { + self.remove_stopped( + self.workers[&object].id(), + self.workers[&object].object().clone(), + ); + + let worker = self.spawn_worker(src, dst, &object, config); + self.workers.entry(object).or_insert(worker) + } else { + &self.workers[&object] + } } else { let worker = self.spawn_worker(src, dst, &object, config); self.workers.entry(object).or_insert(worker) diff --git a/crates/relayer/src/worker/packet.rs b/crates/relayer/src/worker/packet.rs index 828ee2251b..2eb85f633c 100644 --- a/crates/relayer/src/worker/packet.rs +++ b/crates/relayer/src/worker/packet.rs @@ -124,7 +124,7 @@ pub fn spawn_packet_cmd_worker( if is_new_batch { idle_worker_timer = 0; - trace!("packet worker processed an event batch, reseting idle timer"); + trace!("packet worker processed an event batch, resetting idle timer"); } else { idle_worker_timer += 1; trace!("packet worker has not processed an event batch after {idle_worker_timer} blocks, incrementing idle timer"); diff --git a/crates/relayer/tests/config/fixtures/relayer_conf_example.toml b/crates/relayer/tests/config/fixtures/relayer_conf_example.toml index ea41a2888f..3665bb595f 100644 --- a/crates/relayer/tests/config/fixtures/relayer_conf_example.toml +++ b/crates/relayer/tests/config/fixtures/relayer_conf_example.toml @@ -21,6 +21,7 @@ clear_on_start = true tx_confirmation = true [[chains]] +type = "CosmosSdk" id = 'chain_A' rpc_addr = 'http://127.0.0.1:26657' grpc_addr = 'http://127.0.0.1:9090' @@ -46,6 +47,7 @@ list = [ ] [[chains]] +type = "CosmosSdk" id = 'chain_B' rpc_addr = 'http://127.0.0.1:26557' grpc_addr = 'http://127.0.0.1:9090' diff --git a/crates/relayer/tests/config/fixtures/relayer_conf_example_decoding_size.toml b/crates/relayer/tests/config/fixtures/relayer_conf_example_decoding_size.toml index 6df007f2f7..254b603ad1 100644 --- a/crates/relayer/tests/config/fixtures/relayer_conf_example_decoding_size.toml +++ b/crates/relayer/tests/config/fixtures/relayer_conf_example_decoding_size.toml @@ -21,6 +21,7 @@ clear_on_start = true tx_confirmation = true [[chains]] +type = "CosmosSdk" id = 'chain_A' rpc_addr = 'http://127.0.0.1:26657' grpc_addr = 'http://127.0.0.1:9090' @@ -40,6 +41,7 @@ trust_threshold = { numerator = '1', denominator = '3' } address_type = { derivation = 'cosmos' } [[chains]] +type = "CosmosSdk" id = 'chain_B' rpc_addr = 'http://127.0.0.1:26557' grpc_addr = 'http://127.0.0.1:9090' diff --git a/crates/relayer/tests/config/fixtures/relayer_conf_example_fee_filter.toml b/crates/relayer/tests/config/fixtures/relayer_conf_example_fee_filter.toml index 60a0cc7e0c..f85cca1ca7 100644 --- a/crates/relayer/tests/config/fixtures/relayer_conf_example_fee_filter.toml +++ b/crates/relayer/tests/config/fixtures/relayer_conf_example_fee_filter.toml @@ -21,6 +21,7 @@ clear_on_start = true tx_confirmation = true [[chains]] +type = "CosmosSdk" id = 'chain_A' rpc_addr = 'http://127.0.0.1:26657' grpc_addr = 'http://127.0.0.1:9090' @@ -52,6 +53,7 @@ recv = [ { amount = 20, denom = 'stake' }, { amount = 10, denom = 'uatom' } ] recv = [ { amount = 0 }] [[chains]] +type = "CosmosSdk" id = 'chain_B' rpc_addr = 'http://127.0.0.1:26557' grpc_addr = 'http://127.0.0.1:9090' diff --git a/crates/relayer/tests/config/fixtures/relayer_conf_example_invalid_telemetry.toml b/crates/relayer/tests/config/fixtures/relayer_conf_example_invalid_telemetry.toml index 3e44c53a7d..29acbcf517 100644 --- a/crates/relayer/tests/config/fixtures/relayer_conf_example_invalid_telemetry.toml +++ b/crates/relayer/tests/config/fixtures/relayer_conf_example_invalid_telemetry.toml @@ -30,6 +30,7 @@ latency_submitted = { start = 5000, end = 1000, buckets = 10 } # start can't be latency_confirmed = { start = 5000, end = 10000, buckets = 10 } [[chains]] +type = "CosmosSdk" id = 'chain_A' rpc_addr = 'http://127.0.0.1:26657' grpc_addr = 'http://127.0.0.1:9090' @@ -55,6 +56,7 @@ list = [ ] [[chains]] +type = "CosmosSdk" id = 'chain_B' rpc_addr = 'http://127.0.0.1:26557' grpc_addr = 'http://127.0.0.1:9090' diff --git a/crates/relayer/tests/config/fixtures/relayer_conf_example_valid_telemetry.toml b/crates/relayer/tests/config/fixtures/relayer_conf_example_valid_telemetry.toml index ca0ae487ec..5e6111e61d 100644 --- a/crates/relayer/tests/config/fixtures/relayer_conf_example_valid_telemetry.toml +++ b/crates/relayer/tests/config/fixtures/relayer_conf_example_valid_telemetry.toml @@ -30,6 +30,7 @@ latency_submitted = { start = 5000, end = 10000, buckets = 10 } latency_confirmed = { start = 5000, end = 10000, buckets = 10 } [[chains]] +type = "CosmosSdk" id = 'chain_A' rpc_addr = 'http://127.0.0.1:26657' grpc_addr = 'http://127.0.0.1:9090' @@ -55,6 +56,7 @@ list = [ ] [[chains]] +type = "CosmosSdk" id = 'chain_B' rpc_addr = 'http://127.0.0.1:26557' grpc_addr = 'http://127.0.0.1:9090' diff --git a/crates/telemetry/Cargo.toml b/crates/telemetry/Cargo.toml index d519b0224c..0541016578 100644 --- a/crates/telemetry/Cargo.toml +++ b/crates/telemetry/Cargo.toml @@ -1,25 +1,25 @@ [package] name = "ibc-telemetry" -version = "0.25.0" +version = "0.26.4" edition = "2021" license = "Apache-2.0" readme = "README.md" keywords = ["cosmos", "ibc", "relayer", "telemetry"] repository = "https://github.com/informalsystems/hermes" authors = ["Informal Systems "] -rust-version = "1.70" +rust-version = "1.71" description = """ Telemetry service for the Hermes IBC relayer """ [dependencies] -ibc-relayer-types = { version = "0.25.0", path = "../relayer-types" } +ibc-relayer-types = { version = "0.26.4", path = "../relayer-types" } once_cell = "1.17.0" opentelemetry = { version = "0.19.0", features = ["metrics"] } opentelemetry-prometheus = "0.12.0" prometheus = "0.13.2" -moka = "0.11.3" +moka = { version = "0.12.0", features = ["sync"] } dashmap = "5.4.0" serde_json = "1.0.94" serde = "1.0.166" diff --git a/crates/telemetry/src/broadcast_error.rs b/crates/telemetry/src/broadcast_error.rs new file mode 100644 index 0000000000..1d092f08d6 --- /dev/null +++ b/crates/telemetry/src/broadcast_error.rs @@ -0,0 +1,429 @@ +//! The BroadcastError is used by the telemetry in order to correctly batch +//! together the error reports from ibc-go or Cosmos SDK. +//! When a broadcast error is received by Hermes it will contain a code and +//! a description, but the code description depends on the source of the error. +//! For example Cosmos SDK error code 13 is "insufficient fee", and error +//! code 13 for Ibc Go is "invalid packet". +//! The description might contain some variables for example error 32 would be: +//! "account sequence mismatch, expected 1234, got 1235: incorrect account sequence" +//! The BroadcastError will reduce the description to simple: "incorrect account sequence" +//! +//! Cosmos SDK errors: +//! Ibc Go errors: + +pub struct BroadcastError { + pub code: u32, + pub description: String, +} + +impl BroadcastError { + pub fn new(code: u32, description: &str) -> Self { + let short_description = get_short_description(code, description); + Self { + code, + description: short_description, + } + } +} + +fn get_short_description(code: u32, description: &str) -> String { + match code { + 2 => { + let sdk_error = "tx parse error"; + let ibc_go_error = "channel already exists"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 3 => { + let sdk_error = "invalid sequence"; + let ibc_go_error = "channel not found"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 4 => { + let sdk_error = "unauthorized"; + let ibc_go_error = "invalid channel"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 5 => { + let sdk_error = "insufficient funds"; + let ibc_go_error = "invalid channel state"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 6 => { + let sdk_error = "unknown request"; + let ibc_go_error = "invalid channel ordering"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 7 => { + let sdk_error = "invalid address"; + let ibc_go_error = "invalid counterparty channel"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 8 => { + let sdk_error = "invalid pubkey"; + let ibc_go_error = "invalid channel capability"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 9 => { + let sdk_error = "unknown address"; + let ibc_go_error = "channel capability not found"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 10 => { + let sdk_error = "invalid coins"; + let ibc_go_error = "sequence send not found"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 11 => { + let sdk_error = "out of gas"; + let ibc_go_error = "sequence receive not found"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 12 => { + let sdk_error = "memo too large"; + let ibc_go_error = "sequence acknowledgement not found"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 13 => { + let sdk_error = "insufficient fee"; + let ibc_go_error = "invalid packet"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 14 => { + let sdk_error = "maximum number of signatures exceeded"; + let ibc_go_error = "packet timeout"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 15 => { + let sdk_error = "no signatures supplied"; + let ibc_go_error = "too many connection hops"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 16 => { + let sdk_error = "failed to marshal JSON bytes"; + let ibc_go_error = "invalid acknowledgement"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 17 => { + let sdk_error = "failed to unmarshal JSON bytes"; + let ibc_go_error = "acknowledgement for packet already exists"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 18 => { + let sdk_error = "invalid request"; + let ibc_go_error = "invalid channel identifier"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 19 => { + let sdk_error = "tx already in mempool"; + let ibc_go_error = "packet already received"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 20 => { + let sdk_error = "mempool is full"; + let ibc_go_error = "packet commitment not found"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 21 => { + let sdk_error = "tx too large"; + let ibc_go_error = "packet sequence is out of order"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 22 => { + let sdk_error = "key not found"; + let ibc_go_error = "packet messages are redundant"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 23 => { + let sdk_error = "invalid account password"; + let ibc_go_error = "message is redundant, no-op will be performed"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 24 => { + let sdk_error = "tx intended signer does not match the given signer"; + let ibc_go_error = "invalid channel version"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 25 => { + let sdk_error = "invalid gas adjustment"; + let ibc_go_error = "packet has not been sent"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 26 => { + let sdk_error = "invalid height"; + let ibc_go_error = "invalid packet timeout"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else if description.contains(ibc_go_error) { + Some(ibc_go_error.to_owned()) + } else { + None + } + } + 27 => { + let sdk_error = "invalid version"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else { + None + } + } + 28 => { + let sdk_error = "invalid chain-id"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else { + None + } + } + 29 => { + let sdk_error = "invalid type"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else { + None + } + } + 30 => { + let sdk_error = "tx timeout height"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else { + None + } + } + 31 => { + let sdk_error = "unknown extension options"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else { + None + } + } + 32 => { + let sdk_error = "incorrect account sequence"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else { + None + } + } + 33 => { + let sdk_error = "failed packing protobuf message to Any"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else { + None + } + } + 34 => { + let sdk_error = "failed unpacking protobuf message from Any"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else { + None + } + } + 35 => { + let sdk_error = "internal logic error"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else { + None + } + } + 36 => { + let sdk_error = "conflict"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else { + None + } + } + 37 => { + let sdk_error = "feature not supported"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else { + None + } + } + 38 => { + let sdk_error = "not found"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else { + None + } + } + 39 => { + let sdk_error = "Internal IO error"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else { + None + } + } + 40 => { + let sdk_error = "error in app.toml"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else { + None + } + } + 41 => { + let sdk_error = "invalid gas limit"; + if description.contains(sdk_error) { + Some(sdk_error.to_owned()) + } else { + None + } + } + _ => None, + } + .unwrap_or_else(|| "unknown error".to_owned()) +} diff --git a/crates/telemetry/src/lib.rs b/crates/telemetry/src/lib.rs index aa2c8498ce..a26c7177e8 100644 --- a/crates/telemetry/src/lib.rs +++ b/crates/telemetry/src/lib.rs @@ -1,3 +1,4 @@ +pub mod broadcast_error; pub mod encoder; mod path_identifier; pub mod server; diff --git a/crates/telemetry/src/state.rs b/crates/telemetry/src/state.rs index 15a51f44dc..00461eb2fc 100644 --- a/crates/telemetry/src/state.rs +++ b/crates/telemetry/src/state.rs @@ -22,7 +22,7 @@ use ibc_relayer_types::{ use tendermint::Time; -use crate::path_identifier::PathIdentifier; +use crate::{broadcast_error::BroadcastError, path_identifier::PathIdentifier}; const EMPTY_BACKLOG_SYMBOL: u64 = 0; const BACKLOG_CAPACITY: usize = 1000; @@ -101,6 +101,10 @@ pub struct TelemetryState { /// Number of client update messages submitted per client client_updates_submitted: Counter, + /// Number of client update skipped due to consensus state already + /// existing + client_updates_skipped: Counter, + /// Number of misbehaviours detected and submitted per client client_misbehaviours_submitted: Counter, @@ -166,9 +170,9 @@ pub struct TelemetryState { /// SendPacket events were relayed. backlog_oldest_sequence: ObservableGauge, - /// Record the timestamp related to `backlog_oldest_sequence`. + /// Record the timestamp of the last time the `backlog_*` metrics have been updated. /// The timestamp is the time passed since since the unix epoch in seconds. - backlog_oldest_timestamp: ObservableGauge, + backlog_latest_update_timestamp: ObservableGauge, /// Records the length of the backlog, i.e., how many packets are pending. backlog_size: ObservableGauge, @@ -193,6 +197,9 @@ pub struct TelemetryState { /// Sum of rewarded fees over the past FEE_LIFETIME seconds period_fees: ObservableGauge, + + /// Number of errors observed by Hermes when broadcasting a Tx + broadcast_errors: Counter, } impl TelemetryState { @@ -233,6 +240,11 @@ impl TelemetryState { .with_description("Number of client update messages submitted") .init(), + client_updates_skipped: meter + .u64_counter("client_updates_skipped") + .with_description("Number of client update messages skipped") + .init(), + client_misbehaviours_submitted: meter .u64_counter("client_misbehaviours_submitted") .with_description("Number of misbehaviours detected and submitted") @@ -338,10 +350,10 @@ impl TelemetryState { .with_description("Sequence number of the oldest SendPacket event in the backlog") .init(), - backlog_oldest_timestamp: meter - .u64_observable_gauge("backlog_oldest_timestamp") + backlog_latest_update_timestamp: meter + .u64_observable_gauge("backlog_latest_update_timestamp") .with_unit(Unit::new("seconds")) - .with_description("Local timestamp for the oldest SendPacket event in the backlog") + .with_description("Local timestamp for the last time the backlog metrics have been updated") .init(), backlog_size: meter @@ -362,6 +374,13 @@ impl TelemetryState { .u64_observable_gauge("ics29_period_fees") .with_description("Amount of ICS29 fees rewarded over the past 7 days") .init(), + + broadcast_errors: meter + .u64_counter("broadcast_errors") + .with_description( + "Number of errors observed by Hermes when broadcasting a Tx", + ) + .init(), } } @@ -438,7 +457,7 @@ impl TelemetryState { } self.backlog_oldest_sequence.observe(&cx, 0, labels); - self.backlog_oldest_timestamp.observe(&cx, 0, labels); + self.backlog_latest_update_timestamp.observe(&cx, 0, labels); self.backlog_size.observe(&cx, 0, labels); } @@ -458,6 +477,7 @@ impl TelemetryState { ]; self.client_updates_submitted.add(&cx, 0, labels); + self.client_updates_skipped.add(&cx, 0, labels); if misbehaviour { self.client_misbehaviours_submitted.add(&cx, 0, labels); @@ -512,6 +532,25 @@ impl TelemetryState { self.client_updates_submitted.add(&cx, count, labels); } + /// Update the number of client updates skipped per client + pub fn client_updates_skipped( + &self, + src_chain: &ChainId, + dst_chain: &ChainId, + client: &ClientId, + count: u64, + ) { + let cx = Context::current(); + + let labels = &[ + KeyValue::new("src_chain", src_chain.to_string()), + KeyValue::new("dst_chain", dst_chain.to_string()), + KeyValue::new("client", client.to_string()), + ]; + + self.client_updates_skipped.add(&cx, count, labels); + } + /// Number of client misbehaviours per client pub fn client_misbehaviours_submitted( &self, @@ -883,8 +922,7 @@ impl TelemetryState { }; // Update the backlog with the incoming data and retrieve the oldest values - let (oldest_sn, oldest_ts, total) = if let Some(path_backlog) = self.backlogs.get(&path_uid) - { + let (oldest_sn, total) = if let Some(path_backlog) = self.backlogs.get(&path_uid) { // Avoid having the inner backlog map growing more than a given threshold, by removing // the oldest sequence number entry. if path_backlog.len() > BACKLOG_RESET_THRESHOLD { @@ -896,20 +934,11 @@ impl TelemetryState { // Return the oldest event information to be recorded in telemetry if let Some(min) = path_backlog.iter().map(|v| *v.key()).min() { - if let Some(oldest) = path_backlog.get(&min) { - (min, *oldest.value(), path_backlog.len() as u64) - } else { - // Timestamp was not found, this should not happen, record a 0 ts. - (min, 0, path_backlog.len() as u64) - } + (min, path_backlog.len() as u64) } else { // We just inserted a new key/value, so this else branch is unlikely to activate, // but it can happen in case of concurrent updates to the backlog. - ( - EMPTY_BACKLOG_SYMBOL, - EMPTY_BACKLOG_SYMBOL, - EMPTY_BACKLOG_SYMBOL, - ) + (EMPTY_BACKLOG_SYMBOL, EMPTY_BACKLOG_SYMBOL) } } else { // If there is no inner backlog for this path, create a new map to store it. @@ -919,16 +948,57 @@ impl TelemetryState { self.backlogs.insert(path_uid, new_path_backlog); // Return the current event information to be recorded in telemetry - (seq_nr, timestamp, 1) + (seq_nr, 1) }; // Update metrics to reflect the new state of the backlog self.backlog_oldest_sequence.observe(&cx, oldest_sn, labels); - self.backlog_oldest_timestamp - .observe(&cx, oldest_ts, labels); + self.backlog_latest_update_timestamp + .observe(&cx, timestamp, labels); self.backlog_size.observe(&cx, total, labels); } + /// Inserts in the backlog a new event for the given sequence number. + /// This happens when the relayer observed a new SendPacket event. + pub fn update_backlog( + &self, + sequences: Vec, + chain_id: &ChainId, + channel_id: &ChannelId, + port_id: &PortId, + counterparty_chain_id: &ChainId, + ) { + // Unique identifier for a chain/channel/port. + let path_uid: PathIdentifier = PathIdentifier::new( + chain_id.to_string(), + channel_id.to_string(), + port_id.to_string(), + ); + + // This condition is done in order to avoid having an incorrect `backlog_latest_update_timestamp`. + // If the sequences is an empty vector by removing the entries using `backlog_remove` the `backlog_latest_update_timestamp` + // will only be updated if the current backlog is not empty. + // If the sequences is not empty, then it is possible to simple remove the backlog for that path and insert the sequences. + if sequences.is_empty() { + if let Some(path_backlog) = self.backlogs.get(&path_uid) { + let current_keys: Vec = path_backlog + .value() + .iter() + .map(|entry| *entry.key()) + .collect(); + + for key in current_keys.iter() { + self.backlog_remove(*key, chain_id, channel_id, port_id, counterparty_chain_id) + } + } + } else { + self.backlogs.remove(&path_uid); + for key in sequences.iter() { + self.backlog_insert(*key, chain_id, channel_id, port_id, counterparty_chain_id) + } + } + } + /// Evicts from the backlog the event for the given sequence number. /// Removing events happens when the relayer observed either an acknowledgment /// or a timeout for a packet sequence number, which means that the corresponding @@ -957,25 +1027,27 @@ impl TelemetryState { KeyValue::new("port", port_id.to_string()), ]; + // Retrieve local timestamp when this SendPacket event was recorded. + let now = Time::now(); + let timestamp = match now.duration_since(Time::unix_epoch()) { + Ok(ts) => ts.as_secs(), + Err(_) => 0, + }; + if let Some(path_backlog) = self.backlogs.get(&path_uid) { if path_backlog.remove(&seq_nr).is_some() { + // If the entry was removed update the latest update timestamp. + self.backlog_latest_update_timestamp + .observe(&cx, timestamp, labels); // The oldest pending sequence number is the minimum key in the inner (path) backlog. if let Some(min_key) = path_backlog.iter().map(|v| *v.key()).min() { - if let Some(oldest) = path_backlog.get(&min_key) { - self.backlog_oldest_timestamp - .observe(&cx, *oldest.value(), labels); - } else { - self.backlog_oldest_timestamp.observe(&cx, 0, labels); - } self.backlog_oldest_sequence.observe(&cx, min_key, labels); self.backlog_size .observe(&cx, path_backlog.len() as u64, labels); } else { - // No mimimum found, update the metrics to reflect an empty backlog + // No minimum found, update the metrics to reflect an empty backlog self.backlog_oldest_sequence .observe(&cx, EMPTY_BACKLOG_SYMBOL, labels); - self.backlog_oldest_timestamp - .observe(&cx, EMPTY_BACKLOG_SYMBOL, labels); self.backlog_size.observe(&cx, EMPTY_BACKLOG_SYMBOL, labels); } } @@ -1040,6 +1112,21 @@ impl TelemetryState { pub fn add_visible_fee_address(&self, address: String) { self.visible_fee_addresses.insert(address); } + + /// Add an error and its description to the list of errors observed after broadcasting + /// a Tx with a specific account. + pub fn broadcast_errors(&self, address: &String, error_code: u32, error_description: &str) { + let cx = Context::current(); + let broadcast_error = BroadcastError::new(error_code, error_description); + + let labels = &[ + KeyValue::new("account", address.to_string()), + KeyValue::new("error_code", broadcast_error.code.to_string()), + KeyValue::new("error_description", broadcast_error.description), + ]; + + self.broadcast_errors.add(&cx, 1, labels); + } } use std::sync::Arc; @@ -1102,7 +1189,7 @@ impl AggregatorSelector for CustomAggregatorSelector { match descriptor.name() { "wallet_balance" => Some(Arc::new(last_value())), "backlog_oldest_sequence" => Some(Arc::new(last_value())), - "backlog_oldest_timestamp" => Some(Arc::new(last_value())), + "backlog_latest_update_timestamp" => Some(Arc::new(last_value())), "backlog_size" => Some(Arc::new(last_value())), // Prometheus' supports only collector for histogram, sum, and last value aggregators. // https://docs.rs/opentelemetry-prometheus/0.10.0/src/opentelemetry_prometheus/lib.rs.html#411-418 @@ -1114,3 +1201,169 @@ impl AggregatorSelector for CustomAggregatorSelector { } } } + +#[cfg(test)] +mod tests { + use prometheus::proto::Metric; + + use super::*; + + #[test] + fn insert_remove_backlog() { + let state = TelemetryState::new( + Range { + start: 0, + end: 5000, + }, + 5, + Range { + start: 0, + end: 5000, + }, + 5, + ); + + let chain_id = ChainId::from_string("chain-test"); + let counterparty_chain_id = ChainId::from_string("counterpartychain-test"); + let channel_id = ChannelId::new(0); + let port_id = PortId::transfer(); + + state.backlog_insert(1, &chain_id, &channel_id, &port_id, &counterparty_chain_id); + state.backlog_insert(2, &chain_id, &channel_id, &port_id, &counterparty_chain_id); + state.backlog_insert(3, &chain_id, &channel_id, &port_id, &counterparty_chain_id); + state.backlog_insert(4, &chain_id, &channel_id, &port_id, &counterparty_chain_id); + state.backlog_insert(5, &chain_id, &channel_id, &port_id, &counterparty_chain_id); + state.backlog_remove(3, &chain_id, &channel_id, &port_id, &counterparty_chain_id); + state.backlog_remove(1, &chain_id, &channel_id, &port_id, &counterparty_chain_id); + + let metrics = state.exporter.registry().gather().clone(); + let backlog_size = metrics + .iter() + .find(|metric| metric.get_name() == "backlog_size") + .unwrap(); + assert!( + assert_metric_value(backlog_size.get_metric(), 3), + "expected backlog_size to be 3" + ); + let backlog_oldest_sequence = metrics + .iter() + .find(|&metric| metric.get_name() == "backlog_oldest_sequence") + .unwrap(); + assert!( + assert_metric_value(backlog_oldest_sequence.get_metric(), 2), + "expected backlog_oldest_sequence to be 2" + ); + } + + #[test] + fn update_backlog() { + let state = TelemetryState::new( + Range { + start: 0, + end: 5000, + }, + 5, + Range { + start: 0, + end: 5000, + }, + 5, + ); + + let chain_id = ChainId::from_string("chain-test"); + let counterparty_chain_id = ChainId::from_string("counterpartychain-test"); + let channel_id = ChannelId::new(0); + let port_id = PortId::transfer(); + + state.backlog_insert(1, &chain_id, &channel_id, &port_id, &counterparty_chain_id); + state.backlog_insert(2, &chain_id, &channel_id, &port_id, &counterparty_chain_id); + state.backlog_insert(3, &chain_id, &channel_id, &port_id, &counterparty_chain_id); + state.backlog_insert(4, &chain_id, &channel_id, &port_id, &counterparty_chain_id); + state.backlog_insert(5, &chain_id, &channel_id, &port_id, &counterparty_chain_id); + + state.update_backlog( + vec![5], + &chain_id, + &channel_id, + &port_id, + &counterparty_chain_id, + ); + + let metrics = state.exporter.registry().gather().clone(); + let backlog_size = metrics + .iter() + .find(|&metric| metric.get_name() == "backlog_size") + .unwrap(); + assert!( + assert_metric_value(backlog_size.get_metric(), 1), + "expected backlog_size to be 1" + ); + let backlog_oldest_sequence = metrics + .iter() + .find(|&metric| metric.get_name() == "backlog_oldest_sequence") + .unwrap(); + assert!( + assert_metric_value(backlog_oldest_sequence.get_metric(), 5), + "expected backlog_oldest_sequence to be 5" + ); + } + + #[test] + fn update_backlog_empty() { + let state = TelemetryState::new( + Range { + start: 0, + end: 5000, + }, + 5, + Range { + start: 0, + end: 5000, + }, + 5, + ); + + let chain_id = ChainId::from_string("chain-test"); + let counterparty_chain_id = ChainId::from_string("counterpartychain-test"); + let channel_id = ChannelId::new(0); + let port_id = PortId::transfer(); + + state.backlog_insert(1, &chain_id, &channel_id, &port_id, &counterparty_chain_id); + state.backlog_insert(2, &chain_id, &channel_id, &port_id, &counterparty_chain_id); + state.backlog_insert(3, &chain_id, &channel_id, &port_id, &counterparty_chain_id); + state.backlog_insert(4, &chain_id, &channel_id, &port_id, &counterparty_chain_id); + state.backlog_insert(5, &chain_id, &channel_id, &port_id, &counterparty_chain_id); + + state.update_backlog( + vec![], + &chain_id, + &channel_id, + &port_id, + &counterparty_chain_id, + ); + + let metrics = state.exporter.registry().gather().clone(); + let backlog_size = metrics + .iter() + .find(|&metric| metric.get_name() == "backlog_size") + .unwrap(); + assert!( + assert_metric_value(backlog_size.get_metric(), 0), + "expected backlog_size to be 0" + ); + let backlog_oldest_sequence = metrics + .iter() + .find(|&metric| metric.get_name() == "backlog_oldest_sequence") + .unwrap(); + assert!( + assert_metric_value(backlog_oldest_sequence.get_metric(), 0), + "expected backlog_oldest_sequence to be 0" + ); + } + + fn assert_metric_value(metric: &[Metric], expected: u64) -> bool { + metric + .iter() + .any(|m| m.get_gauge().get_value() as u64 == expected) + } +} diff --git a/docs/architecture/adr-002-ibc-relayer.md b/docs/architecture/adr-002-ibc-relayer.md index fe9e4baae9..983ff24805 100644 --- a/docs/architecture/adr-002-ibc-relayer.md +++ b/docs/architecture/adr-002-ibc-relayer.md @@ -87,7 +87,7 @@ Initial version of the relayer assumes batching is supported by all chains. An o A correct relayer MUST: -- **[R-config-start]** Read, parse, validate a configuration file upon start and configure itself for the specifed chains and paths +- **[R-config-start]** Read, parse, validate a configuration file upon start and configure itself for the specified chains and paths - **[R-transport]** Have access to the networking protocols (e.g. TCP/IP, UDP/IP, or QUIC/IP) and physical transport, required to read the state of one blockchain/ machine and submit data to another - **[R-provider]** Maintain transport connections to at least one full node per chain - **[R-query]** Query IBC data on source and destination chains @@ -308,7 +308,7 @@ Future versions may create multiple relay threads. One possibility is to create A relayer algorithm is described in [relayer algorithm described in IBC Specification](https://github.com/cosmos/ibc/tree/main/spec/relayer/ics-018-relayer-algorithms/README.md#L47) and [Go relayer implementation ](https://github.com/cosmos/relayer/blob/f3a302df9e6e0c28883f5480199d3190821bcc06/relayer/strategies.go#L49.). -This section describes some of the details of the realy thread algorithm in the Rust implementation. Inputs are the IBC Events and the events of interest are described in Appendix A. +This section describes some of the details of the really thread algorithm in the Rust implementation. Inputs are the IBC Events and the events of interest are described in Appendix A. At high level, for each event from a source chain, the relayer: - queries client, connection, channels and/or packet related state on source and destination chains, @@ -318,7 +318,7 @@ At high level, for each event from a source chain, the relayer: #### Proofs The relayer must include proofs in some datagrams as required by the IBC handlers. There are two types of proofs: -- proof of some local state on source chain (A). For example, a proof of correct connection state (`ProofInit`, `ProofTry`, `ProofAck`) is included in some of the connection handshake datagrams. The `ConnOpenTry` message includes the `ProofInit` that is obtained from chain A where the connection should be in `INIT` state and have certain local and counterpary identifiers. The message specific sections below go in more details. +- proof of some local state on source chain (A). For example, a proof of correct connection state (`ProofInit`, `ProofTry`, `ProofAck`) is included in some of the connection handshake datagrams. The `ConnOpenTry` message includes the `ProofInit` that is obtained from chain A where the connection should be in `INIT` state and have certain local and counterparty identifiers. The message specific sections below go in more details. - proof that the chain A's IBC client `clB` is updated with a consensus state and height that have been stored on chain B. - these proofs are verified on chain B against the consensus state stored by the A client at `proof_height`. @@ -350,7 +350,7 @@ One proposal is shown below and described in the rest of this section. ![IBC_client_heights](assets/IBC_client_heights.jpeg) The relayer creates a light client on B with `hi` and then updates it as required by processing different IBC events. Let `ha'` be the last consensus state for client on B. -When some IBC event for X (connection, channel or packet) is received, it includes the height, let it be `hx-1` at which the event occured on A. +When some IBC event for X (connection, channel or packet) is received, it includes the height, let it be `hx-1` at which the event occurred on A. According to the proposal here, the relayer should: - get the latest consensus state height of client on B, `ha` - let `h = max(hx, ha)` @@ -793,6 +793,6 @@ The IBC Events, input to the relay thread are described here. ## References -> Are there any relevant PR comments, issues that led up to this, or articles referrenced for why we made the given design choice? If so link them here! +> Are there any relevant PR comments, issues that led up to this, or articles referenced for why we made the given design choice? If so link them here! * {reference link} diff --git a/docs/architecture/adr-003-handler-implementation.md b/docs/architecture/adr-003-handler-implementation.md index 7062c717bf..e552f7672e 100644 --- a/docs/architecture/adr-003-handler-implementation.md +++ b/docs/architecture/adr-003-handler-implementation.md @@ -309,12 +309,12 @@ pub fn keep( > This section is very much a work in progress, as further investigation into what > a production-ready implementation of the `ctx` parameter of the top-level dispatcher -> is required. As such, implementors should feel free to disregard the recommendations +> is required. As such, implementers should feel free to disregard the recommendations > below, and are encouraged to come up with amendments to this ADR to better capture > the actual requirements. Each submodule is responsible for dispatching the messages it is given to the appropriate -message processing function and, if successful, pass the resulting data to the persistance +message processing function and, if successful, pass the resulting data to the persistence function defined in the previous section. To this end, the submodule should define an enumeration of all messages, in order @@ -552,7 +552,7 @@ pub trait ClientKeeper { This way, only one implementation of the `ClientReader` and `ClientKeeper` trait is required, as it can delegate eg. the serialization of the underlying datatypes to the `Serialize` bound -of the `Any...` wrappper. +of the `Any...` wrapper. Both the `process` and `keep` function are defined to take a message generic over the actual client type: diff --git a/docs/architecture/adr-007-error.md b/docs/architecture/adr-007-error.md index 0d1a18f34f..f56dbddb65 100644 --- a/docs/architecture/adr-007-error.md +++ b/docs/architecture/adr-007-error.md @@ -37,7 +37,7 @@ impl Kind { The design above is meant to separate between two concerns: - The metadata about an error, as captured in `Kind`. - - The trace of how the error occured, as captured in `anomaly::Context`. + - The trace of how the error occurred, as captured in `anomaly::Context`. - The type `Error` is defined to be `anomaly::Error`, which is a newtype wrapper to `Box>`. There are a few issues with the original design using `anomaly`: diff --git a/docs/architecture/adr-008-ics20-implementation.md b/docs/architecture/adr-008-ics20-implementation.md index 3839a2315a..afbdaa1531 100644 --- a/docs/architecture/adr-008-ics20-implementation.md +++ b/docs/architecture/adr-008-ics20-implementation.md @@ -204,7 +204,7 @@ pub fn on_acknowledgement_packet(ctx: &Ctx, ack: ICS20Acknowledgement, data where Ctx: ICS20Context { match ack { - ICS20Acknowledgement::Sucess => Ok(()), + ICS20Acknowledgement::Success => Ok(()), _ => refund_packet_token(ctx, data) } } diff --git a/docs/architecture/adr-011-light-client-crates-extraction.md b/docs/architecture/adr-011-light-client-crates-extraction.md index f008f9e713..79465da8fa 100644 --- a/docs/architecture/adr-011-light-client-crates-extraction.md +++ b/docs/architecture/adr-011-light-client-crates-extraction.md @@ -475,7 +475,7 @@ Proposed ## References * PRs for removing `Any*` enums: - * Remove all occurences of Any* enums from light clients + * Remove all occurrences of Any* enums from light clients ([PR #2332](https://github.com/informalsystems/hermes/pull/2332)) * Remove Any* enums ([PR #2338](https://github.com/informalsystems/hermes/pull/2338)) * Experimental PR for extracting `ibc-base` crate ([PR #2327](https://github.com/informalsystems/hermes/pull/2327)) diff --git a/docs/architecture/adr-template.md b/docs/architecture/adr-template.md index 28a5ecfbbc..83d323eeec 100644 --- a/docs/architecture/adr-template.md +++ b/docs/architecture/adr-template.md @@ -31,6 +31,6 @@ If the proposed change will be large, please also indicate a way to do the chang ## References -> Are there any relevant PR comments, issues that led up to this, or articles referrenced for why we made the given design choice? If so link them here! +> Are there any relevant PR comments, issues that led up to this, or articles referenced for why we made the given design choice? If so link them here! * {reference link} diff --git a/docs/architecture/architecture.md b/docs/architecture/architecture.md index dddf2ae11a..e80c5bda79 100644 --- a/docs/architecture/architecture.md +++ b/docs/architecture/architecture.md @@ -110,7 +110,7 @@ Used by Hermes to gather telemetry data and expose it via a Prometheus endpoint. Most of the components in the `ibc` crate (i.e. the `modules` directory) have basic unit testing coverage. These unit tests make use of mocked up chain components in order to ensure that message payloads are being sent and received as expected. -We also run end-to-end tests to more thoroughly test IBC modules in a more heterogenous fashion. +We also run end-to-end tests to more thoroughly test IBC modules in a more heterogeneous fashion. ### Error Handling diff --git a/docs/spec/connection-handshake/L1_2.md b/docs/spec/connection-handshake/L1_2.md index 68bd28aa8f..dbca2591d8 100644 --- a/docs/spec/connection-handshake/L1_2.md +++ b/docs/spec/connection-handshake/L1_2.md @@ -245,7 +245,7 @@ Specifically, termination implies that each module allocates in the local store _Remarks_: -- Uniqueness property essentially provides a safeguard against overwritting a connection in the store with some new set of parameters. +- Uniqueness property essentially provides a safeguard against overwriting a connection in the store with some new set of parameters. - The integrity property, in conjunction with uniqueness, ensures that there is continuity between the connections that a module initializes and the connections that this module opens. @@ -413,7 +413,7 @@ func ConnTryHandler( ``` Preconditions: - - The input parameters should be valid; among others validation criterias, it is important that the module running this handler supports at least one of the versions supplied in the input list `remoteVersions` (see [validation](#Validation)). + - The input parameters should be valid; among others validation criteria, it is important that the module running this handler supports at least one of the versions supplied in the input list `remoteVersions` (see [validation](#Validation)). - The two proofs `remoteConnectionProof` and `remoteClientProof` should be correct. This is necessary in connection to properties [ICS3-Proto-2-ConnectionIntegrity] and [ICS3-Proto-3-StateConsistency]. Correctness of proofs means that they pass verification (`verifyProof` function). Postconditions: diff --git a/docs/spec/connection-handshake/L2-tla/Environment.tla b/docs/spec/connection-handshake/L2-tla/Environment.tla index ed05bea075..6ea00d17c2 100644 --- a/docs/spec/connection-handshake/L2-tla/Environment.tla +++ b/docs/spec/connection-handshake/L2-tla/Environment.tla @@ -183,7 +183,7 @@ InitEnv == This is part of the RelayNextEnv sub-action of the environment. This performs a basic relaying step, that is, passing a message from the - output buffer of one of the chains (paramter 'from') into the input buffer + output buffer of one of the chains (parameter 'from') into the input buffer of another chain (parameter 'to'). *) @@ -199,7 +199,7 @@ RelayMessage(from, to) == This step may change (non-deterministically) either of the store of chain A or B, by advancing the height of that chain. This can only enable if the respective chain has ample steps left, i.e., the chain height is not within 4 steps - of the maximum height. This precondition disallow continuos advancing of chain heights, + of the maximum height. This precondition disallow continuous advancing of chain heights, and therefore allows chains to take meaningful steps (executing the ICS3 protocol to completion). @@ -273,7 +273,7 @@ RelayNextEnv == the chains unless the chain has just a few (namely, `4`) heights left. 3. The environment may perform a relaying step, that is: - if there is a message in the ougoing buffer of a chain, the relayer + if there is a message in the outgoing buffer of a chain, the relayer moves this message to the ingoing buffer of the other chain, and also updates the client on the latter chain. @@ -299,7 +299,7 @@ ICS3ReachedOpenConnection == (* Enables when both chains are stuck, i.e., unable to progress while their connection is not opened. - State predicate signaling that the protocol terminated unsucessfully. + State predicate signaling that the protocol terminated unsuccessfully. *) ICS3ImpossibleToAdvance == @@ -328,7 +328,7 @@ Init == (* The two ICS3 modules and the environment alternate their steps non-deterministically. Eventually, the execution ends with either - successful (ICS3ReachedOpenConnection sub-action) or unsuccesfull + successful (ICS3ReachedOpenConnection sub-action) or unsuccessful (ICS3ImpossibleToAdvance sub-action) termination. *) Next == diff --git a/docs/spec/connection-handshake/L2-tla/README.md b/docs/spec/connection-handshake/L2-tla/README.md index 0c828bfe7f..d0572c3d38 100644 --- a/docs/spec/connection-handshake/L2-tla/README.md +++ b/docs/spec/connection-handshake/L2-tla/README.md @@ -31,7 +31,7 @@ ASSUME VersionPickMode \in ``` Typical values could be: `MaxHeight = 5` and `MaxBufLen = 2`. -The `Concurrency` flag enables/disables some non-determinsm of the environment, +The `Concurrency` flag enables/disables some non-determinism of the environment, specifically: - if TRUE, then the environment can non-deterministically update the light client of a chain. diff --git a/docs/spec/tla/fungible-token-transfer/Bank.tla b/docs/spec/tla/fungible-token-transfer/Bank.tla index 20e1af41ff..8b1630b584 100644 --- a/docs/spec/tla/fungible-token-transfer/Bank.tla +++ b/docs/spec/tla/fungible-token-transfer/Bank.tla @@ -30,7 +30,7 @@ AddCoins(accounts, accountID, amount) == ] -\* Transfer coins from senderAccounts to receiverAccounts, depeding on +\* Transfer coins from senderAccounts to receiverAccounts, depending on \* the sender addressees, receiver addressees and denomination \* - senderAccounts is a map from sender addresses and denominations \* to account balances diff --git a/docs/spec/tla/fungible-token-transfer/Chain.tla b/docs/spec/tla/fungible-token-transfer/Chain.tla index af779b2999..aeb25ea87b 100644 --- a/docs/spec/tla/fungible-token-transfer/Chain.tla +++ b/docs/spec/tla/fungible-token-transfer/Chain.tla @@ -126,7 +126,7 @@ SendPacket == LET updatedChainStore == WritePacketCommitment(chainStore, packet) IN \* if writing the packet commitment was successful /\ chainStore /= updatedChainStore - \* update chain store with packet committment + \* update chain store with packet commitment /\ chainStore' = updatedChainStore \* log sent packet /\ packetLog' = Append(packetLog, [ diff --git a/docs/spec/tla/fungible-token-transfer/IBCTokenTransferDefinitions.tla b/docs/spec/tla/fungible-token-transfer/IBCTokenTransferDefinitions.tla index 8e3f3c5641..3ce0509670 100644 --- a/docs/spec/tla/fungible-token-transfer/IBCTokenTransferDefinitions.tla +++ b/docs/spec/tla/fungible-token-transfer/IBCTokenTransferDefinitions.tla @@ -406,7 +406,7 @@ InitUnorderedChannelEnd(ChainID) == \* - height is initialized to 1 \* - counterpartyClientHeights is the set of installed client heights \* - the channelEnd is initialized to InitUnorderedChannelEnd -\* - the packet committments, receipts, acknowledgements, and packets +\* - the packet commitments, receipts, acknowledgements, and packets \* to acknowledge are empty ICS20InitChainStore(ChainID) == [ diff --git a/docs/spec/tla/fungible-token-transfer/ICS04PacketHandlers.tla b/docs/spec/tla/fungible-token-transfer/ICS04PacketHandlers.tla index cfcd4883a8..74f714434c 100644 --- a/docs/spec/tla/fungible-token-transfer/ICS04PacketHandlers.tla +++ b/docs/spec/tla/fungible-token-transfer/ICS04PacketHandlers.tla @@ -101,7 +101,7 @@ HandlePacketAck(chain, packetDatagram, log, accounts, escrowAccounts, maxBalance LET packet == packetDatagram.packet IN \* get acknowledgement LET ack == packetDatagram.acknowledgement IN - \* get packet committment that should be in chain store + \* get packet commitment that should be in chain store LET packetCommitment == [ portID |-> packet.srcPortID, channelID |-> packet.srcChannelID, @@ -141,7 +141,7 @@ HandlePacketAck(chain, packetDatagram, log, accounts, escrowAccounts, maxBalance escrowAccounts |-> escrowAccounts] -\* write packet committments to chain store +\* write packet commitments to chain store \* @type: (CHAINSTORE, PACKET) => CHAINSTORE; WritePacketCommitment(chain, packet) == \* get channel end @@ -245,7 +245,7 @@ TimeoutPacket(chain, counterpartyChain, accounts, escrowAccounts, packet, proofHeight, maxBalance) == \* get channel end LET channelEnd == chain.channelEnd IN - \* get packet committment that should be in chain store + \* get packet commitment that should be in chain store LET packetCommitment == [ portID |-> packet.srcPortID, channelID |-> packet.srcChannelID, @@ -303,7 +303,7 @@ TimeoutOnClose(chain, counterpartyChain, accounts, escrowAccounts, \* get counterparty channel end LET counterpartyChannelEnd == counterpartyChain.channelEnd IN - \* get packet committment that should be in chain store + \* get packet commitment that should be in chain store LET packetCommitment == [ portID |-> packet.srcPortID, channelID |-> packet.srcChannelID, diff --git a/docs/spec/tla/ibc-core/Chain.tla b/docs/spec/tla/ibc-core/Chain.tla index 500c985dec..5bbe315487 100644 --- a/docs/spec/tla/ibc-core/Chain.tla +++ b/docs/spec/tla/ibc-core/Chain.tla @@ -180,7 +180,7 @@ SendPacket == LET updatedChainStore == WritePacketCommitment(chainStore, packet) IN \* if writing the packet commitment was successful /\ chainStore /= updatedChainStore - \* update chain store with packet committment + \* update chain store with packet commitment /\ chainStore' = updatedChainStore \* log sent packet /\ packetLog' = Append(packetLog, [ diff --git a/docs/spec/tla/ibc-core/IBCCoreDefinitions.tla b/docs/spec/tla/ibc-core/IBCCoreDefinitions.tla index 53ee2a5731..3bd6e5bc2d 100644 --- a/docs/spec/tla/ibc-core/IBCCoreDefinitions.tla +++ b/docs/spec/tla/ibc-core/IBCCoreDefinitions.tla @@ -520,7 +520,7 @@ InitConnectionEnds(Versions, channelOrdering) == \* - height is initialized to 1 \* - the counterparty light client is uninitialized \* - the connection end is initialized to InitConnectionEnd -\* - the packet committments, receipts, acknowledgements, and +\* - the packet commitments, receipts, acknowledgements, and \* packets to acknowledge are empty \* @type: (Set(Int), Str) => Set(CHAINSTORE); InitChainStore(Versions, channelOrdering) == diff --git a/docs/spec/tla/ibc-core/ICS03ConnectionHandlers.tla b/docs/spec/tla/ibc-core/ICS03ConnectionHandlers.tla index 72fc205aa3..afe0443645 100644 --- a/docs/spec/tla/ibc-core/ICS03ConnectionHandlers.tla +++ b/docs/spec/tla/ibc-core/ICS03ConnectionHandlers.tla @@ -58,7 +58,7 @@ HandleConnOpenTry(chainID, chain, datagrams) == THEN LET connOpenTryDgr == CHOOSE dgr \in connOpenTryDgrs : TRUE IN LET versionIntersection == chain.connectionEnd.versions \intersect connOpenTryDgr.versions IN - \* if the versions from the datagram overlap with the supported versions of the connnection end + \* if the versions from the datagram overlap with the supported versions of the connection end IF /\ versionIntersection /= {} \* if the connection end is uninitialized /\ \/ chain.connectionEnd.state = "UNINIT" diff --git a/docs/spec/tla/ibc-core/ICS04PacketHandlers.tla b/docs/spec/tla/ibc-core/ICS04PacketHandlers.tla index 4e4808f040..bb08d53e22 100644 --- a/docs/spec/tla/ibc-core/ICS04PacketHandlers.tla +++ b/docs/spec/tla/ibc-core/ICS04PacketHandlers.tla @@ -93,7 +93,7 @@ HandlePacketAck(chainID, chain, packetDatagram, log) == LET channelEnd == GetChannelEnd(chain) IN \* get packet LET packet == packetDatagram.packet IN - \* get packet committment that should be in chain store + \* get packet commitment that should be in chain store LET packetCommitment == [ portID |-> packet.srcPortID, channelID |-> packet.srcChannelID, @@ -135,7 +135,7 @@ HandlePacketAck(chainID, chain, packetDatagram, log) == ELSE [chainStore |-> chain, packetLog |-> log] -\* write packet committments to chain store +\* write packet commitments to chain store \* @type: (CHAINSTORE, PACKET) => CHAINSTORE; WritePacketCommitment(chain, packet) == \* get chainID's connection end @@ -158,7 +158,7 @@ WritePacketCommitment(chain, packet) == /\ \/ packet.timeoutHeight = 0 \/ latestClientHeight < packet.timeoutHeight THEN IF \* if the channel is ordered, check if packetSeq is nextSendSeq, - \* add a packet committment in the chain store, and increase nextSendSeq + \* add a packet commitment in the chain store, and increase nextSendSeq /\ channelEnd.order = "ORDERED" /\ packet.sequence = channelEnd.nextSendSeq THEN [chain EXCEPT @@ -171,7 +171,7 @@ WritePacketCommitment(chain, packet) == ] \* otherwise, do not update the chain store ELSE IF \* if the channel is unordered, - \* add a packet committment in the chain store + \* add a packet commitment in the chain store /\ channelEnd.order = "UNORDERED" THEN [chain EXCEPT !.packetCommitments = @@ -248,7 +248,7 @@ TimeoutPacket(chain, counterpartyChain, packet, proofHeight) == \* get counterparty channel end LET counterpartyChannelEnd == GetChannelEnd(counterpartyChain) IN - \* get packet committment that should be in chain store + \* get packet commitment that should be in chain store LET packetCommitment == [ portID |-> packet.srcPortID, channelID |-> packet.srcChannelID, @@ -310,7 +310,7 @@ TimeoutOnClose(chain, counterpartyChain, packet, proofHeight) == \* get counterparty channel end LET counterpartyChannelEnd == GetChannelEnd(counterpartyChain) IN - \* get packet committment that should be in chain store + \* get packet commitment that should be in chain store LET packetCommitment == [ portID |-> packet.srcPortID, channelID |-> packet.srcChannelID, diff --git a/docs/spec/tla/packet-delay/Chain.tla b/docs/spec/tla/packet-delay/Chain.tla index c21ad200d0..f2b9f03e3c 100644 --- a/docs/spec/tla/packet-delay/Chain.tla +++ b/docs/spec/tla/packet-delay/Chain.tla @@ -90,7 +90,7 @@ SendPacket == srcChannelID |-> chainStore.channelEnd.channelID, dstPortID |-> chainStore.channelEnd.counterpartyPortID, dstChannelID |-> chainStore.channelEnd.counterpartyChannelID] IN - \* update chain store with packet committment + \* update chain store with packet commitment /\ chainStore' = WritePacketCommitment(chainStore, packet) \* log sent packet /\ packetLog' = Append(packetLog, diff --git a/docs/spec/tla/packet-delay/IBCPacketDelayDefinitions.tla b/docs/spec/tla/packet-delay/IBCPacketDelayDefinitions.tla index cad0aee7ea..915229f896 100644 --- a/docs/spec/tla/packet-delay/IBCPacketDelayDefinitions.tla +++ b/docs/spec/tla/packet-delay/IBCPacketDelayDefinitions.tla @@ -396,7 +396,7 @@ InitChannelEnd(ChainID, ChannelOrdering) == \* - timestamp is initialized to 1 \* - there are no installed client heights \* - the channel end is initialized to InitChannelEnd -\* - the packet committments, receipts, acknowledgements, and packets +\* - the packet commitments, receipts, acknowledgements, and packets \* to acknowledge are empty \* @type: (Str, Set(Int), Str, Int) => CHAINSTORE; InitChainStore(ChainID, Heights, ChannelOrdering, MaxDelay) == diff --git a/docs/spec/tla/packet-delay/ICS04PacketHandlers.tla b/docs/spec/tla/packet-delay/ICS04PacketHandlers.tla index 22a3b359be..36a5ea8379 100644 --- a/docs/spec/tla/packet-delay/ICS04PacketHandlers.tla +++ b/docs/spec/tla/packet-delay/ICS04PacketHandlers.tla @@ -111,7 +111,7 @@ HandlePacketAck(chainID, chain, packetDatagram, delay, log, datagramTimestamp) = LET channelEnd == chain.channelEnd IN \* get packet LET packet == packetDatagram.packet IN - \* get packet committment that should be in chain store + \* get packet commitment that should be in chain store LET packetCommitment == [portID |-> packet.srcPortID, channelID |-> packet.srcChannelID, sequence |-> packet.sequence, @@ -125,7 +125,7 @@ HandlePacketAck(chainID, chain, packetDatagram, delay, log, datagramTimestamp) = IF \* if the channel end is open for packet transmission /\ channelEnd.state = "OPEN" - \* if the packet committment exists in the chain store + \* if the packet commitment exists in the chain store /\ packetCommitment \in chain.packetCommitments \* if the "PacketRecv" datagram has valid port and channel IDs /\ packet.srcPortID = channelEnd.portID @@ -167,7 +167,7 @@ HandlePacketAck(chainID, chain, packetDatagram, delay, log, datagramTimestamp) = ELSE [chainStore |-> chain, packetLog |-> log, datagramTimestamp |-> datagramTimestamp] -\* write packet committments to chain store +\* write packet commitments to chain store \* @type: (CHAINSTORE, PACKET) => CHAINSTORE; WritePacketCommitment(chain, packet) == \* get channel end @@ -186,7 +186,7 @@ WritePacketCommitment(chain, packet) == /\ \/ packet.timeoutHeight = 0 \/ latestClientHeight < packet.timeoutHeight THEN IF \* if the channel is ordered, check if packetSeq is nextSendSeq, - \* add a packet committment in the chain store, and increase nextSendSeq + \* add a packet commitment in the chain store, and increase nextSendSeq /\ channelEnd.order = "ORDERED" /\ packet.sequence = channelEnd.nextSendSeq THEN [chain EXCEPT @@ -203,7 +203,7 @@ WritePacketCommitment(chain, packet) == \* otherwise, do not update the chain store ELSE chain ELSE IF \* if the channel is unordered, - \* add a packet committment in the chain store + \* add a packet commitment in the chain store /\ channelEnd.order = "UNORDERED" THEN [chain EXCEPT !.packetCommitments = @@ -282,7 +282,7 @@ TimeoutPacket(chain, counterpartyChain, packet, proofHeight) == \* get counterparty channel end LET counterpartyChannelEnd == counterpartyChain.channelEnd IN - \* get packet committment that should be in chain store + \* get packet commitment that should be in chain store LET packetCommitment == [portID |-> packet.srcPortID, channelID |-> packet.srcChannelID, sequence |-> packet.sequence, @@ -336,7 +336,7 @@ TimeoutOnClose(chain, counterpartyChain, packet, proofHeight) == \* get counterparty channel end LET counterpartyChannelEnd == counterpartyChain.channelEnd IN - \* get packet committment that should be in chain store + \* get packet commitment that should be in chain store LET packetCommitment == [portID |-> packet.srcPortID, channelID |-> packet.srcChannelID, sequence |-> packet.sequence, diff --git a/flake.lock b/flake.lock index 6c1750e11d..874e699bf9 100644 --- a/flake.lock +++ b/flake.lock @@ -51,20 +51,54 @@ "type": "github" } }, + "celestia-src": { + "flake": false, + "locked": { + "lastModified": 1700494564, + "narHash": "sha256-O6KrCStrZLmWy3xybQUNsWEb3O7vIRCFDE9MsEtsFro=", + "owner": "celestiaorg", + "repo": "celestia-app", + "rev": "2dbfabf1849e166974c1287c35b43e5e07727643", + "type": "github" + }, + "original": { + "owner": "celestiaorg", + "ref": "v1.4.0", + "repo": "celestia-app", + "type": "github" + } + }, "centauri-src": { "flake": false, "locked": { - "lastModified": 1692209286, - "narHash": "sha256-fabsZyaSCnWnhvG9nO8y39t85u+MZNyEKzU+0fSueLM=", - "owner": "dzmitry-lahoda-forks", - "repo": "composable-centauri", - "rev": "9fa53d8b47d17219d1270146a146e4e386bc2a29", + "lastModified": 1701431373, + "narHash": "sha256-EpZ1CQN0gMU8W1u3CMbqlaHeeVpQO2i1GPg6pOyOQTc=", + "owner": "ComposableFi", + "repo": "composable-cosmos", + "rev": "387c96b434db9d96b0506aa7f14536d9bdec968c", + "type": "github" + }, + "original": { + "owner": "ComposableFi", + "repo": "composable-cosmos", + "rev": "387c96b434db9d96b0506aa7f14536d9bdec968c", + "type": "github" + } + }, + "cometbft-src": { + "flake": false, + "locked": { + "lastModified": 1694550324, + "narHash": "sha256-G5gchJMn/BFzwYx8/ikPDL5fS/TuFIBF4DKJbkalp/M=", + "owner": "cometbft", + "repo": "cometbft", + "rev": "66a5a9da9f7a3306f382eb9142ccb9c9f7997d3f", "type": "github" }, "original": { - "owner": "dzmitry-lahoda-forks", - "repo": "composable-centauri", - "rev": "9fa53d8b47d17219d1270146a146e4e386bc2a29", + "owner": "cometbft", + "ref": "v0.38.0", + "repo": "cometbft", "type": "github" } }, @@ -73,16 +107,21 @@ "akash-src": "akash-src", "apalache-src": "apalache-src", "beaker-src": "beaker-src", + "celestia-src": "celestia-src", "centauri-src": "centauri-src", + "cometbft-src": "cometbft-src", "cosmos-sdk-src": "cosmos-sdk-src", "cosmwasm-src": "cosmwasm-src", "crescent-src": "crescent-src", + "cw-plus-src": "cw-plus-src", "evmos-src": "evmos-src", - "flake-utils": "flake-utils", + "flake-parts": "flake-parts", "gaia-main-src": "gaia-main-src", "gaia10-src": "gaia10-src", "gaia11-src": "gaia11-src", "gaia12-src": "gaia12-src", + "gaia13-src": "gaia13-src", + "gaia14-src": "gaia14-src", "gaia5-src": "gaia5-src", "gaia6-ordered-src": "gaia6-ordered-src", "gaia6-src": "gaia6-src", @@ -111,7 +150,7 @@ "nix-std": "nix-std", "nixpkgs": "nixpkgs", "osmosis-src": "osmosis-src", - "pre-commit-hooks": "pre-commit-hooks", + "provenance-src": "provenance-src", "regen-src": "regen-src", "relayer-src": "relayer-src", "rust-overlay": "rust-overlay", @@ -123,24 +162,24 @@ "stoml-src": "stoml-src", "stride-consumer-src": "stride-consumer-src", "stride-src": "stride-src", - "ts-relayer-src": "ts-relayer-src", "umee-src": "umee-src", "wasmd-src": "wasmd-src", "wasmd_next-src": "wasmd_next-src", - "wasmvm_0_16_3-src": "wasmvm_0_16_3-src", "wasmvm_1-src": "wasmvm_1-src", "wasmvm_1_1_1-src": "wasmvm_1_1_1-src", "wasmvm_1_1_2-src": "wasmvm_1_1_2-src", "wasmvm_1_2_3-src": "wasmvm_1_2_3-src", "wasmvm_1_2_4-src": "wasmvm_1_2_4-src", + "wasmvm_1_3_0-src": "wasmvm_1_3_0-src", + "wasmvm_1_5_0-src": "wasmvm_1_5_0-src", "wasmvm_1_beta7-src": "wasmvm_1_beta7-src" }, "locked": { - "lastModified": 1697035289, - "narHash": "sha256-2yPPi/n4IrKZ0Y0BwPSmHGP5UJoY5u5XY6BnKxsuGnc=", + "lastModified": 1701457684, + "narHash": "sha256-Tx3WsOM9scTXDHFyL5vNcQnCmT7Mx0dYg1Nmz8cFwt4=", "owner": "informalsystems", "repo": "cosmos.nix", - "rev": "e26774d7889a508ad3ac021a886bc6b8cf11cf7e", + "rev": "c0bb979a518aa08ba064112a85e03fbc7a7d2869", "type": "github" }, "original": { @@ -169,16 +208,16 @@ "cosmwasm-src": { "flake": false, "locked": { - "lastModified": 1685975182, - "narHash": "sha256-6uhJijuDPXvEZG8mKBGyswsj/JR75Ui713BVx4XD7WI=", + "lastModified": 1698745412, + "narHash": "sha256-41s5jLFzw9Jo+dirAVOad1dtUqCBY6rIz/6TRc0frMw=", "owner": "CosmWasm", "repo": "cosmwasm", - "rev": "b8e9c03e744e8b84174477e20eb934529cad41e7", + "rev": "89891f0bb2de2c83d00600208695d0d5e1b617ac", "type": "github" }, "original": { "owner": "CosmWasm", - "ref": "v1.2.6", + "ref": "v1.5.0", "repo": "cosmwasm", "type": "github" } @@ -200,6 +239,23 @@ "type": "github" } }, + "cw-plus-src": { + "flake": false, + "locked": { + "lastModified": 1700757493, + "narHash": "sha256-E5vkY+B4BDoTDtvuB+7Tm3k/5dCYPSjUujMWcgYsWf0=", + "owner": "CosmWasm", + "repo": "cw-plus", + "rev": "d33824679d5b91ca0b4615a8dede7e0028947486", + "type": "github" + }, + "original": { + "owner": "CosmWasm", + "ref": "v1.1.2", + "repo": "cw-plus", + "type": "github" + } + }, "evmos-src": { "flake": false, "locked": { @@ -217,43 +273,27 @@ "type": "github" } }, - "flake-compat": { - "flake": false, - "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-utils": { + "flake-parts": { "inputs": { - "systems": "systems" + "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1692792214, - "narHash": "sha256-voZDQOvqHsaReipVd3zTKSBwN7LZcUwi3/ThMxRZToU=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "1721b3e7c882f75f2301b00d48a2884af8c448ae", + "lastModified": 1698882062, + "narHash": "sha256-HkhafUayIqxXyHH1X8d9RDl1M2CkFgZLjKD3MzabiEo=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "8c9fa2545007b49a5db5f650ae91f227672c3877", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "hercules-ci", + "repo": "flake-parts", "type": "github" } }, - "flake-utils_2": { + "flake-utils": { "inputs": { - "systems": "systems_2" + "systems": "systems" }, "locked": { "lastModified": 1681202837, @@ -269,7 +309,7 @@ "type": "github" } }, - "flake-utils_3": { + "flake-utils_2": { "locked": { "lastModified": 1667395993, "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", @@ -284,16 +324,16 @@ "type": "github" } }, - "flake-utils_4": { + "flake-utils_3": { "inputs": { - "systems": "systems_3" + "systems": "systems_2" }, "locked": { - "lastModified": 1694529238, - "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "lastModified": 1701680307, + "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", "owner": "numtide", "repo": "flake-utils", - "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", "type": "github" }, "original": { @@ -305,11 +345,11 @@ "gaia-main-src": { "flake": false, "locked": { - "lastModified": 1692777545, - "narHash": "sha256-Gg6pqITR+aqq4FBE0h/HvXpG+whtli2gJXw+dsyoKEE=", + "lastModified": 1697456548, + "narHash": "sha256-iXcwU0/kDAGzQKYrHKTMX6/ayB6Ns0KBYMOpi5uNYJk=", "owner": "cosmos", "repo": "gaia", - "rev": "97d0a1359716c5c534053a6a15a007b740d34780", + "rev": "e6da2cc3d1602a6c64fc50c90ea60651177d911b", "type": "github" }, "original": { @@ -369,6 +409,40 @@ "type": "github" } }, + "gaia13-src": { + "flake": false, + "locked": { + "lastModified": 1699370179, + "narHash": "sha256-bvJ33JL1Fr7ilnnYEjrjnbS/dbFkyhZ2uq6u39CeTa0=", + "owner": "cosmos", + "repo": "gaia", + "rev": "2406abb61856b61904ff06c7be2a355babcc3dfc", + "type": "github" + }, + "original": { + "owner": "cosmos", + "ref": "v13.0.2", + "repo": "gaia", + "type": "github" + } + }, + "gaia14-src": { + "flake": false, + "locked": { + "lastModified": 1700067649, + "narHash": "sha256-7AnaIy/SElf/Uj2xTbHzLSgPY68SgQqqJZ2BPmt6czo=", + "owner": "cosmos", + "repo": "gaia", + "rev": "189b57be735d64d0dbf0945717b49017a1beb11e", + "type": "github" + }, + "original": { + "owner": "cosmos", + "ref": "v14.0.0", + "repo": "gaia", + "type": "github" + } + }, "gaia5-src": { "flake": false, "locked": { @@ -474,39 +548,17 @@ "gex-src": { "flake": false, "locked": { - "lastModified": 1660333522, - "narHash": "sha256-7jtCpOTHamXAInfKYkMIDFKF4lViuPkusThj4ggGUbg=", + "lastModified": 1697704475, + "narHash": "sha256-lgJVxn7Q2I8TBdvbzyn7bl1MN5StEw3NvRzCvBFFuB8=", "owner": "cosmos", "repo": "gex", - "rev": "bc168741b2019745d343606d31b5c274f216fc3f", + "rev": "233d335dc9e8c89fb318d1081fae74435f6cac11", "type": "github" }, "original": { "owner": "cosmos", "repo": "gex", - "rev": "bc168741b2019745d343606d31b5c274f216fc3f", - "type": "github" - } - }, - "gitignore": { - "inputs": { - "nixpkgs": [ - "cosmos-nix", - "pre-commit-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1660459072, - "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", + "rev": "233d335dc9e8c89fb318d1081fae74435f6cac11", "type": "github" } }, @@ -649,16 +701,16 @@ "ibc-go-v8-src": { "flake": false, "locked": { - "lastModified": 1695930850, - "narHash": "sha256-BHmsnnqB+SoS8UdfGbEk07EXGZJG9ELo4+2gAbP8LdM=", + "lastModified": 1699602904, + "narHash": "sha256-BcP3y874QviVsV+04p9CioolyvmWH82ORbb5EB2GyRI=", "owner": "cosmos", "repo": "ibc-go", - "rev": "9c7212198d0ef82b8219ea66cee9c96b40e7981d", + "rev": "2551dea41cd3c512845007ca895c8402afa9b79f", "type": "github" }, "original": { "owner": "cosmos", - "ref": "v8.0.0-beta.1", + "ref": "v8.0.0", "repo": "ibc-go", "type": "github" } @@ -683,11 +735,11 @@ "ica-src": { "flake": false, "locked": { - "lastModified": 1679480012, - "narHash": "sha256-LFyInZT7z/8/d3RYepYf95ryxA7Pbg3TMQhHrHUvlCA=", + "lastModified": 1695202199, + "narHash": "sha256-8RwZSnqqZzVjQsSMTckNhmTy3VYyubVmgE/hU6ntq9M=", "owner": "cosmos", "repo": "interchain-accounts-demo", - "rev": "fe07f304731161055cecec120e0d2de01e84bad4", + "rev": "9d9ec3f4f7e37e9d2a1c7f4a199e7d18c17e14db", "type": "github" }, "original": { @@ -716,16 +768,16 @@ "interchain-security-src": { "flake": false, "locked": { - "lastModified": 1662985265, - "narHash": "sha256-MhH5R1eEKel8nX1UIw4PAsSTPraP7ivrPU/+StqaD6U=", + "lastModified": 1697113174, + "narHash": "sha256-J+duWnA9ipgHryO5+9sv6uwcPVN2ceL0PGoCyVvN5YQ=", "owner": "cosmos", "repo": "interchain-security", - "rev": "1162655c89221588d4b440717b2ca1c65170aec2", + "rev": "28e0c14b34d5d15ea0eb19b694c74513667afe09", "type": "github" }, "original": { "owner": "cosmos", - "ref": "v0.1.4", + "ref": "feat/ics-misbehaviour-handling", "repo": "interchain-security", "type": "github" } @@ -767,16 +819,16 @@ "juno-src": { "flake": false, "locked": { - "lastModified": 1679292088, - "narHash": "sha256-9xWOnlqjJWY7dyICYjl1Fmqi27352TF9ihcbZBI/Dps=", + "lastModified": 1697166503, + "narHash": "sha256-z9TOeDyUnn1T8Z662XqQJ9ydVIKKB54YISt7ms4xvos=", "owner": "CosmosContracts", "repo": "juno", - "rev": "1f392744afd9829f3f7837fe6f13800a19bad961", + "rev": "48507ed9b83511089cbf1fdc5bae54cae4a7f4b2", "type": "github" }, "original": { "owner": "CosmosContracts", - "ref": "v13.0.1", + "ref": "v17.1.1", "repo": "juno", "type": "github" } @@ -784,16 +836,16 @@ "migaloo-src": { "flake": false, "locked": { - "lastModified": 1681833529, - "narHash": "sha256-7sOAcUcc1HpZgLjjdiNuXeXCq9vB9EXCMY4YIT1MAgU=", + "lastModified": 1699273936, + "narHash": "sha256-O+vGWFnV3+bvXinxl1QjVyDnQskp5H1VnlL+TaMfiSs=", "owner": "White-Whale-Defi-Platform", "repo": "migaloo-chain", - "rev": "129e6fecd377614123f2af33417f9e31accf195f", + "rev": "de98de2dd96917ae1ab79161d573fc0b4ee1facf", "type": "github" }, "original": { "owner": "White-Whale-Defi-Platform", - "ref": "v2.0.2", + "ref": "v3.0.2", "repo": "migaloo-chain", "type": "github" } @@ -801,16 +853,16 @@ "neutron-src": { "flake": false, "locked": { - "lastModified": 1685114240, - "narHash": "sha256-xHi4W4fOT3kTmkPEKdGp6JbzKQELdWy9PIn0qsZhprY=", + "lastModified": 1701174344, + "narHash": "sha256-NuoOlrciBeL2f/A7wlQBqYlYJhSYucXRhLgxdasfyhI=", "owner": "neutron-org", "repo": "neutron", - "rev": "3c8dde1ff524551e24295d393a3913c25199d265", + "rev": "e605ed3db4381994ee8185ba4a0ff0877d34e67f", "type": "github" }, "original": { "owner": "neutron-org", - "ref": "v1.0.2", + "ref": "v2.0.0", "repo": "neutron", "type": "github" } @@ -832,11 +884,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1692684269, - "narHash": "sha256-zJk2pyF4Cuhtor0khtPlf+hfJIh22rzAUC+KU3Ob31Q=", + "lastModified": 1701040486, + "narHash": "sha256-vawYwoHA5CwvjfqaT3A5CT9V36Eq43gxdwpux32Qkjw=", "owner": "nixos", "repo": "nixpkgs", - "rev": "9d757ec498666cc1dcc6f2be26db4fd3e1e9ab37", + "rev": "45827faa2132b8eade424f6bdd48d8828754341a", "type": "github" }, "original": { @@ -846,18 +898,20 @@ "type": "github" } }, - "nixpkgs-stable": { + "nixpkgs-lib": { "locked": { - "lastModified": 1685801374, - "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=", + "dir": "lib", + "lastModified": 1698611440, + "narHash": "sha256-jPjHjrerhYDy3q9+s5EAsuhyhuknNfowY6yt6pjn9pc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c37ca420157f4abc31e26f436c1145f8951ff373", + "rev": "0cbe9f69c234a7700596e943bfae7ef27a31b735", "type": "github" }, "original": { + "dir": "lib", "owner": "NixOS", - "ref": "nixos-23.05", + "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } @@ -896,11 +950,11 @@ }, "nixpkgs_4": { "locked": { - "lastModified": 1696757521, - "narHash": "sha256-cfgtLNCBLFx2qOzRLI6DHfqTdfWI+UbvsKYa3b3fvaA=", + "lastModified": 1701693815, + "narHash": "sha256-7BkrXykVWfkn6+c1EhFA3ko4MLi3gVG0p9G96PNnKTM=", "owner": "nixos", "repo": "nixpkgs", - "rev": "2646b294a146df2781b1ca49092450e8a32814e1", + "rev": "09ec6a0881e1a36c29d67497693a67a16f4da573", "type": "github" }, "original": { @@ -913,45 +967,34 @@ "osmosis-src": { "flake": false, "locked": { - "lastModified": 1692886846, - "narHash": "sha256-VdM6hGqcDyCNx7AR8s7SxE3pEMxHiIhCJ7592sDp3uc=", + "lastModified": 1700576443, + "narHash": "sha256-UE3XEgdSp8mlgIKQRrBfb4wiPEeagB/wNWfDvDq4up4=", "owner": "osmosis-labs", "repo": "osmosis", - "rev": "1c5f25d04f19d6302e0bdd585ba1d7a2cc96e397", + "rev": "d9965b09d3e8690c77050bb095bc5b69772ebdfb", "type": "github" }, "original": { "owner": "osmosis-labs", - "ref": "v18.0.0", + "ref": "v20.4.0", "repo": "osmosis", "type": "github" } }, - "pre-commit-hooks": { - "inputs": { - "flake-compat": "flake-compat", - "flake-utils": [ - "cosmos-nix", - "flake-utils" - ], - "gitignore": "gitignore", - "nixpkgs": [ - "cosmos-nix", - "nixpkgs" - ], - "nixpkgs-stable": "nixpkgs-stable" - }, + "provenance-src": { + "flake": false, "locked": { - "lastModified": 1692274144, - "narHash": "sha256-BxTQuRUANQ81u8DJznQyPmRsg63t4Yc+0kcyq6OLz8s=", - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "rev": "7e3517c03d46159fdbf8c0e5c97f82d5d4b0c8fa", + "lastModified": 1699901286, + "narHash": "sha256-dTX3kg2QUsC9SwsaommP4IFgIdQgWZrGQNtp/B+fzys=", + "owner": "provenance-io", + "repo": "provenance", + "rev": "91b0813de2f93d03cefe8efb226dc32f02690840", "type": "github" }, "original": { - "owner": "cachix", - "repo": "pre-commit-hooks.nix", + "owner": "provenance-io", + "ref": "v1.17.0", + "repo": "provenance", "type": "github" } }, @@ -992,41 +1035,40 @@ "root": { "inputs": { "cosmos-nix": "cosmos-nix", - "flake-utils": "flake-utils_4", + "flake-utils": "flake-utils_3", "nixpkgs": "nixpkgs_4" } }, "rust-overlay": { "inputs": { - "flake-utils": "flake-utils_2", + "flake-utils": "flake-utils", "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1688265347, - "narHash": "sha256-oe3kLnNvw2VWbG4Rp6IWUO5Uu5gF8J2oq8DbqbCsdZ4=", + "lastModified": 1701310566, + "narHash": "sha256-CL9J3xUR2Ejni4LysrEGX0IdO+Y4BXCiH/By0lmF3eQ=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "b8f3db465405014039985f1c5cea92cc29e1b3b5", + "rev": "6d3c6e185198b8bf7ad639f22404a75aa9a09bff", "type": "github" }, "original": { "owner": "oxalica", "repo": "rust-overlay", - "rev": "b8f3db465405014039985f1c5cea92cc29e1b3b5", "type": "github" } }, "sbt-derivation": { "inputs": { - "flake-utils": "flake-utils_3", + "flake-utils": "flake-utils_2", "nixpkgs": "nixpkgs_3" }, "locked": { - "lastModified": 1675083208, - "narHash": "sha256-+sSFhSpV2jckr1qYlX/SaxQ6IdpagD6o4rru/3HAl0I=", + "lastModified": 1698464090, + "narHash": "sha256-Pnej7WZIPomYWg8f/CZ65sfW85IfIUjYhphMMg7/LT0=", "owner": "zaninime", "repo": "sbt-derivation", - "rev": "92d6d6d825e3f6ae5642d1cce8ff571c3368aaf7", + "rev": "6762cf2c31de50efd9ff905cbcc87239995a4ef9", "type": "github" }, "original": { @@ -1182,38 +1224,6 @@ "type": "github" } }, - "systems_3": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "ts-relayer-src": { - "flake": false, - "locked": { - "lastModified": 1640291594, - "narHash": "sha256-mSI+qgB+e9YcFrcUAgHQnbXOQ8wxO2GmD0wNe+3ya0g=", - "owner": "confio", - "repo": "ts-relayer", - "rev": "23930794ddb64afcc80ac73ffe31ca69072c6549", - "type": "github" - }, - "original": { - "owner": "confio", - "ref": "v0.4.0", - "repo": "ts-relayer", - "type": "github" - } - }, "umee-src": { "flake": false, "locked": { @@ -1265,23 +1275,6 @@ "type": "github" } }, - "wasmvm_0_16_3-src": { - "flake": false, - "locked": { - "lastModified": 1640251271, - "narHash": "sha256-XvgAMDvAgzWaH7Q+mNZUBoaVhqAVlZ4ucIL0QFyNvWw=", - "owner": "CosmWasm", - "repo": "wasmvm", - "rev": "458e983721624548e66c0dcdd35140383966515e", - "type": "github" - }, - "original": { - "owner": "CosmWasm", - "ref": "v0.16.3", - "repo": "wasmvm", - "type": "github" - } - }, "wasmvm_1-src": { "flake": false, "locked": { @@ -1367,6 +1360,40 @@ "type": "github" } }, + "wasmvm_1_3_0-src": { + "flake": false, + "locked": { + "lastModified": 1689589428, + "narHash": "sha256-rsTYvbkYpDkUE4IvILdSL3hXMgAWxz5ltGotJB2t1e4=", + "owner": "CosmWasm", + "repo": "wasmvm", + "rev": "71a9c0dc0ecf9623148e82facb3564fbbf0a896f", + "type": "github" + }, + "original": { + "owner": "CosmWasm", + "ref": "v1.3.0", + "repo": "wasmvm", + "type": "github" + } + }, + "wasmvm_1_5_0-src": { + "flake": false, + "locked": { + "lastModified": 1698746477, + "narHash": "sha256-l0cNF0YjviEl/JLJ4VdvDtIGuAYyFfncVo83ROfQFD8=", + "owner": "CosmWasm", + "repo": "wasmvm", + "rev": "2041b184c146f278157d195361bc6cc6b56cc9d4", + "type": "github" + }, + "original": { + "owner": "CosmWasm", + "ref": "v1.5.0", + "repo": "wasmvm", + "type": "github" + } + }, "wasmvm_1_beta7-src": { "flake": false, "locked": { diff --git a/flake.nix b/flake.nix index 7cadfe5970..7e2f5756e3 100644 --- a/flake.nix +++ b/flake.nix @@ -27,25 +27,31 @@ packages = { inherit (cosmos-nix) + apalache + celestia + cometbft + evmos gaia6-ordered - gaia12 - osmosis - wasmd + gaia13 + gaia14 ibc-go-v2-simapp ibc-go-v3-simapp ibc-go-v4-simapp ibc-go-v5-simapp ibc-go-v6-simapp ibc-go-v7-simapp - apalache - evmos + ibc-go-v8-simapp + interchain-security + migaloo + neutron juno + osmosis + provenance stride stride-no-admin stride-consumer-no-admin stride-consumer - migaloo - neutron + wasmd ; python = nixpkgs.python3.withPackages (p: [ diff --git a/guide/README.md b/guide/README.md index 6d9677da15..119ddbdef2 100644 --- a/guide/README.md +++ b/guide/README.md @@ -10,7 +10,7 @@ mdBook is a utility to create modern online books from Markdown files. This guide should be permanently deployed at its latest stable version at [hermes.informal.systems](https://hermes.informal.systems). -Current version: `v1.6.0`. +Current version: `v1.7.4`. The version of this guide is aligned with the [versioning of the ibc crates](../README.md). @@ -72,4 +72,4 @@ Basically if you want to add new content to the guide, just add an entry to the If you are adding content using your favorite IDE and have a terminal opened running `mdbook serve`, it provides a convenient watch functionality, so any changes detected on local files will trigger another build and if you refresh the guide on your browser they will be shown there. #### Submit your changes -Once you finish adding the new content just commit your changes (`git commit`) and push them to the respository (`git push`). +Once you finish adding the new content just commit your changes (`git commit`) and push them to the repository (`git push`). diff --git a/guide/src/SUMMARY.md b/guide/src/SUMMARY.md index 3264a2214f..e85b810e6b 100644 --- a/guide/src/SUMMARY.md +++ b/guide/src/SUMMARY.md @@ -1,6 +1,6 @@ # Summary -# Hermes v1.6.0 +# Hermes v1.7.4 --- - [Introduction](./index.md) @@ -31,7 +31,9 @@ - [Configure Hermes](./documentation/configuration/configure-hermes.md) - [Description of the parameters](./documentation/configuration/description.md) - [Filter incentivized packets](./documentation/configuration/filter-incentivized.md) + - [Packet clearing](./documentation/configuration/packet-clearing.md) - [Performance tuning](./documentation/configuration/performance.md) + - [CometBFT Compatibility modes](./documentation/configuration/comet-compat-mode.md) - [Telemetry](./documentation/telemetry/index.md) - [Operators guide](./documentation/telemetry/operators.md) diff --git a/guide/src/advanced/features.md b/guide/src/advanced/features.md index 05d84b28a9..2f37930e9b 100644 --- a/guide/src/advanced/features.md +++ b/guide/src/advanced/features.md @@ -83,11 +83,13 @@ __Feature comparison between Hermes and the Go relayer__ | Features \ Status | Hermes | Cosmos Go | Feature Details | | ---------------------- | :---: | :----: |:-------| +| Feegrant support | ✅ | ✅ | add `feeGranter` to tx sign for sending the transactions +| | | | | Restart | ✅ | ✅ | replays any IBC events that happened before restart | Multiple_Paths | ✅ | ✅ | relays on multiple paths concurrently | | | | | Connection Delay | ✅ | ❌ | -| Cl_Misbehavior | ✅ | ❌ | monitors and submits IBC client misbehavior +| Cl_Misbehavior | ✅ | ✅ | monitors and submits IBC client misbehavior | Cl_Refresh | ✅ | ✅ | periodically refresh an on-chain client to prevent expiration | Packet Delay | ✅ | ❌ | | | | | @@ -110,6 +112,8 @@ __Feature comparison between Hermes and the Go relayer__ | | | | | FT_Transfer | ✅ | ✅ | can submit an ICS-20 fungible token transfer message | ICA_Relay | ✅ | ✅ | can relay ICS-27 Interchain account packets +| Interchain Query (ICQ) support | ✅ | ✅ | interchain querying using ABCI +| Cross-chain Queries | ✅ | ✅ | cross-chain querying between IBC-enabled chains | Packet_Recv_A | ✅ | ✅ | | Packet_Recv_P | ✅ | ✅ | | Packet_Timeout_A | ✅ | ✅ | @@ -118,8 +122,10 @@ __Feature comparison between Hermes and the Go relayer__ | Packet_TimeoutClose_P | ✅ | ✅ | | Packet_Optimistic | ❌ | ❌ | relay packets over non-Open channels | | | | +| Modular Architecture | ✅ | ✅ | defined interface can be implemented for different chain types | Cl_Non_Tendermint | ❌ | ❌ | supports non tendermint IBC light clients -| Chain_Non_Cosmos | ❌ | ❌ | supports non cosmos-SDK chains +| Chain_Non_Cosmos | ❌ | ✅ | supports non cosmos-SDK chains +| Penumbra support | ❌ | ✅ | supports Penumbra non-cosmos-SDK chain | | | | | Cfg_Static | ✅ | ✅ | provides means for configuration prior to being started | Cfg_Dynamic | ❌ | ❌ | provides means for configuration and monitoring during runtime diff --git a/guide/src/advanced/troubleshooting/cross-comp-config.md b/guide/src/advanced/troubleshooting/cross-comp-config.md index 8c6c07cd9c..f5ae0cb389 100644 --- a/guide/src/advanced/troubleshooting/cross-comp-config.md +++ b/guide/src/advanced/troubleshooting/cross-comp-config.md @@ -42,7 +42,7 @@ __Hermes vs other configuration parameters that may cause Hermes failures__ ## Recheck When relaying packets, Hermes may send up multiple transactions to the full node's mempool. Hermes uses the `broadcast_tx_sync` RPC which does some basic verification and then returns the Tx hash back. -Unless configured with `sequential_batch_tx = true`, Hermes does not wait for a transaction to be included in a block before sending the next transaction. For this to be possible, Hermes keeps track of the account sequence number locally, incrementing it after each succesfull `broadcast_tx_sync` RPC. +Unless configured with `sequential_batch_tx = true`, Hermes does not wait for a transaction to be included in a block before sending the next transaction. For this to be possible, Hermes keeps track of the account sequence number locally, incrementing it after each successful `broadcast_tx_sync` RPC. During peak periods, it is possible that not all Tx-es in the mempool are included in a block. In order for new transactions to be accepted along with the pending Tx-es, the full node must be configured with `recheck = true`. Otherwise, Hermes may get the following error: ``` @@ -284,7 +284,7 @@ Set `ccv_consumer_chain = true` in `config.toml`. If Hermes is set to query CometBFT's `/block_results` RPC endpoint (which is the case when Hermes is set to use the [pull-based event source][pull-based-event-source]), you may encounter an `Internal error: node is not persisting abci responses (code: -32603)` when clearing packets. -This is likely due to the underlying CometBFT node being configured to discard ABCI responses via the `discard_abci_responses` configuration paramter being set to `true` in the Comet config. When this option is set to `true`, Hermes will not be able to clear any packets that were sent in either a `begin_block` or an `end_block`; transactions sent using `/tx_search` should still be cleared though. In addition, Hermes will not be able to relay using the pull-based event source if ABCI responses are being discarded. +This is likely due to the underlying CometBFT node being configured to discard ABCI responses via the `discard_abci_responses` configuration parameter being set to `true` in the Comet config. When this option is set to `true`, Hermes will not be able to clear any packets that were sent in either a `begin_block` or an `end_block`; transactions sent using `/tx_search` should still be cleared though. In addition, Hermes will not be able to relay using the pull-based event source if ABCI responses are being discarded. ### Fix Set the Comet node's `discard_abci_resonses = false` in the Comet configuration file. diff --git a/guide/src/advanced/troubleshooting/genesis-restart.md b/guide/src/advanced/troubleshooting/genesis-restart.md index dfeeefc37e..6d75986645 100644 --- a/guide/src/advanced/troubleshooting/genesis-restart.md +++ b/guide/src/advanced/troubleshooting/genesis-restart.md @@ -1,4 +1,4 @@ -# Updating a client after a Genesis restart withtout IBC upgrade proposal +# Updating a client after a Genesis restart without IBC upgrade proposal If a chain went through a genesis restart without an IBC upgrade proposal updating the client can result in an error due to blocks at lower heights not being available. diff --git a/guide/src/assets/grafana_template.json b/guide/src/assets/grafana_template.json index 2d7e91454a..ae3e049667 100644 --- a/guide/src/assets/grafana_template.json +++ b/guide/src/assets/grafana_template.json @@ -958,7 +958,7 @@ }, "editorMode": "builder", "exemplar": false, - "expr": "backlog_oldest_timestamp{job=\"hermes\"}", + "expr": "backlog_latest_update_timestamp{job=\"hermes\"}", "format": "table", "hide": false, "instant": true, @@ -1715,7 +1715,7 @@ "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, - "description": "Indicates the number of `event` observed via the websocket subcription.", + "description": "Indicates the number of `event` observed via the websocket subscription.", "fieldConfig": { "defaults": { "color": { diff --git a/guide/src/documentation/commands/logs/index.md b/guide/src/documentation/commands/logs/index.md index cb94477a5c..e146314568 100644 --- a/guide/src/documentation/commands/logs/index.md +++ b/guide/src/documentation/commands/logs/index.md @@ -8,7 +8,7 @@ This command allows you to easily update the lowest log level displayed by Herme ## Set Raw Filter -This command allows you to update the tracing directive used to filter the logs. Please use this command with caution as it requires a precise syntaxe. +This command allows you to update the tracing directive used to filter the logs. Please use this command with caution as it requires a precise syntax. ```shell {{#include ../../../templates/help_templates/logs/raw.md}} diff --git a/guide/src/documentation/commands/tx/upgrade.md b/guide/src/documentation/commands/tx/upgrade.md index 950e53a3a8..07fbaa15ea 100644 --- a/guide/src/documentation/commands/tx/upgrade.md +++ b/guide/src/documentation/commands/tx/upgrade.md @@ -16,8 +16,28 @@ __Example__ An upgrade proposal is made for `ibc-0`, for height `300` blocks from the latest height, with `10000000stake` deposited. The proposal will include the upgraded client state constructed from the state of `07-tendermint-0` client on `ibc-1`. +If the chain is using ibc-go version `v8.0.0` or higher, the authority account for the governance module needs to be used. To query the account use: + +```shell + query auth module-account gov +``` + +or + +```shell + query auth module-accounts +``` + +And then + +```shell +{{#template ../../../templates/commands/hermes/tx/upgrade-chain_1.md REFERENCE_CHAIN_ID=ibc-0 HOST_CHAIN_ID=ibc-1 HOST_CLIENT_ID=07-tendermint-0 AMOUNT=10000000 HEIGHT_OFFSET=60 OPTIONS= --gov-account }} +``` + +If the ibc-go version used is lower than `v8.0.0` you can ignore the `--gov-account` flag as it will not be used. + ```shell -{{#template ../../../templates/commands/hermes/tx/upgrade-chain_1.md REFERENCE_CHAIN_ID=ibc-0 HOST_CHAIN_ID=ibc-1 HOST_CLIENT_ID=07-tendermint-0 AMOUNT=10000000 HEIGHT_OFFSET=300}} +{{#template ../../../templates/commands/hermes/tx/upgrade-chain_1.md REFERENCE_CHAIN_ID=ibc-0 HOST_CHAIN_ID=ibc-1 HOST_CLIENT_ID=07-tendermint-0 AMOUNT=10000000 HEIGHT_OFFSET=60}} ``` ``` diff --git a/guide/src/documentation/commands/upgrade/test.md b/guide/src/documentation/commands/upgrade/test.md index 47804b9dbb..65093de03a 100644 --- a/guide/src/documentation/commands/upgrade/test.md +++ b/guide/src/documentation/commands/upgrade/test.md @@ -70,10 +70,24 @@ gaiad version --log_level error --long | head -n4 Use test command to make an upgrade proposal. In the example below a software upgrade proposal is made for `ibc-0`, for the height `300` blocks from the latest height. `10000000stake` is deposited. The proposal includes the upgraded client state constructed from the state of `07-tendermint-0` client on `ibc-1` that was created in the previous step. + If the chain is using ibc-go version `v8.0.0` or higher, the authority account for the governance module needs to be used. To query the account use: + + ```shell + gaiad --node tcp://localhost:27000 --home $HOME/.gm/ibc-0/ query auth module-account gov + ``` + + ```shell + {{#template ../../../templates/commands/hermes/tx/upgrade-chain_1.md REFERENCE_CHAIN_ID=ibc-0 HOST_CHAIN_ID=ibc-1 HOST_CLIENT_ID=07-tendermint-0 AMOUNT=10000000 HEIGHT_OFFSET=60 OPTIONS= --gov-account }} + ``` + + If the ibc-go version used is lower than `v8.0.0` you can ignore the `--gov-account` flag as it will not be used. + ```shell {{#template ../../../templates/commands/hermes/tx/upgrade-chain_1.md REFERENCE_CHAIN_ID=ibc-0 HOST_CHAIN_ID=ibc-1 HOST_CLIENT_ID=07-tendermint-0 AMOUNT=10000000 HEIGHT_OFFSET=60}} ``` + For this test, the `--gov-account` can be ignored. + ```text Success: transaction::Hash(CE98D8D98091BA8016BD852D18056E54C4CB3C4525E7F40DD3C40B4FD0F2482B) ``` diff --git a/guide/src/documentation/configuration/comet-compat-mode.md b/guide/src/documentation/configuration/comet-compat-mode.md new file mode 100644 index 0000000000..5ce5e07dfe --- /dev/null +++ b/guide/src/documentation/configuration/comet-compat-mode.md @@ -0,0 +1,24 @@ +# CometBFT Compatibility modes + +## Overview + +There are two different compatibility modes for CometBFT, one for version v0.34 and one for versions v0.37 and v0.38. In order to verify the compatibility used Hermes queries the node's `/status` endpoint, which contains the CometBFT version used. This can be an issue if a chain uses a custom version which does not output the version string Hermes expects. To still be able to relay for these chains a configuration can be set in Hermes. + +## Configuration + +The configuration is set per chain and can take two values `0.34` and `0.37`, other values will be invalid: + +```toml +[[chains]] +... +compat_mode = '0.34' +``` + +Hermes will act in the following way whether or not the configuration is set: + +* `compat_mode` is specified and the version queried from `/status` is the same as the one configured: Use that version without log output +* `compat_mode` is specified but the version queried from `/status` differs: The compatibility mode configured is used, but a warning log is outputted +* `compat_mode` is not specified but /status returns a correct version: The compatibility mode retrieved from the endpoint is used +* `compat_mode` is not specified and /status does not return a valid version: Hermes stops and outputs an error informing the user that the `compat_mode` needs to be configured + +The configuration can also be found in the example [config.toml](https://github.com/informalsystems/hermes/blob/{{#include ../../templates/hermes-version.md}}/config.toml#382) \ No newline at end of file diff --git a/guide/src/documentation/configuration/configure-hermes.md b/guide/src/documentation/configuration/configure-hermes.md index 1527c9ed9d..cec76e4fb7 100644 --- a/guide/src/documentation/configuration/configure-hermes.md +++ b/guide/src/documentation/configuration/configure-hermes.md @@ -160,16 +160,17 @@ event_source = { mode = 'push', url = 'wss://hello:world@mydomain.com:26657/webs ## Configuring Support for Wasm Relaying -As of version 1.6.0, Hermes supports the relaying of wasm messages natively. This is facilitated by configuring +Hermes supports the relaying of wasm messages natively. This is facilitated by configuring Hermes to use pull-based relaying by polling for IBC events via the `/block_results` RPC endpoint. Set -the `event_source` parameter to pull mode in `config.toml`: +the `event_source` parameter to pull mode in `config.toml` like so: ```toml -event_source = 'poll' +# When specified like this, Hermes defaults to a poll interval of 1 second +event_source = { mode = 'pull' } ``` The default interval at which Hermes polls the RPC endpoint is 1 second. If you need to change the interval, -you can do so like this: +you can specify it like so: ```toml event_source = { mode = 'pull', interval = '2s' } diff --git a/guide/src/documentation/configuration/index.md b/guide/src/documentation/configuration/index.md index e8f8e04e40..49f8b5f579 100644 --- a/guide/src/documentation/configuration/index.md +++ b/guide/src/documentation/configuration/index.md @@ -15,5 +15,11 @@ This section includes everything you need to know to configure Hermes. * **[Filter incentivized packets](./filter-incentivized.md)** * Examples on how to configure Hermes in order to filter incentivized packets +* **[Packet clearing](./packet-clearing.md)** + * Description on packet clearing configurations + - **[Performance Tuning](./performance.md)** - * Learn about configurations allowing more refined performance tuning. \ No newline at end of file + * Learn about configurations allowing more refined performance tuning. + +- **[CometBFT Compatibility modes](./comet-compat-mode.md)** + * Handle different CometBFT compatibility modes. \ No newline at end of file diff --git a/guide/src/documentation/configuration/packet-clearing.md b/guide/src/documentation/configuration/packet-clearing.md new file mode 100644 index 0000000000..b12dd4d27d --- /dev/null +++ b/guide/src/documentation/configuration/packet-clearing.md @@ -0,0 +1,45 @@ +# Packet clearing + +Hermes can be configured in order to clear packets which haven't been relayed. This can happen if there wasn't a relayer instance running when the packet event was submitted or if there was an issue relaying the packet. + +There are three different configurations to determine when Hermes will clear packets. + +## Global configurations + +Two of these configurations are global to all chains and are in the `[mode.packet]` section. + +### 1. `clear_on_start` + +```toml +[mode.packet] +... +clear_on_start = true +``` + +This configuration is used to specify if Hermes should query and relay pending packets when starting the instance. If set this will only trigger once per running instance. + +>__NOTE__: If this configuration is enabled Hermes will need to scan for channels as the pending packets will require the channel worker, refer to the [Slow start section](./performance.md#3-slow-start) for more information. + +### 2. `clear_interval` + +```toml +[mode.packet] +... +clear_interval = 100 +``` + +This configuration defines how often Hermes will verify if there are pending packets and relay them. The value is the number of blocks observed, so the time between each clearing might very from chain to chain. + +## Chain specific configuration + +The third configuration is specific for each chain. + +### 3. `clear_interval` + +```toml +[[chains]] +... +clear_interval = 50 +``` + +An additional `clear_interval` can be specified for each chain, this value is also in number of blocks. This configuration will override the clear interval value for the specific chain and can be used if chains need to have different clear values. This configuration is optional, if it is not set the global value will be used. \ No newline at end of file diff --git a/guide/src/documentation/configuration/performance.md b/guide/src/documentation/configuration/performance.md index 01f0a94de5..d2f768f1f9 100644 --- a/guide/src/documentation/configuration/performance.md +++ b/guide/src/documentation/configuration/performance.md @@ -91,7 +91,7 @@ setting `clear_on_start` to `false` under the `mode.packets` section, Hermes wil relay packets on active channels, provided they match the packet filter, if present. Otherwise Hermes will relay on all active channels. -Please note that because these settings are globa, they will affect the behaviour of Hermes for all chains listed in its configuration. +Please note that because these settings are global, they will affect the behaviour of Hermes for all chains listed in its configuration. Here is how the configuration file should look like in order to disable scanning altogether. @@ -103,7 +103,7 @@ enabled = false # ... -[mode.connnections] +[mode.connections] enabled = false # ... diff --git a/guide/src/documentation/forwarding/legacy_test.md b/guide/src/documentation/forwarding/legacy_test.md index 7e28ba9fad..8f7999155d 100644 --- a/guide/src/documentation/forwarding/legacy_test.md +++ b/guide/src/documentation/forwarding/legacy_test.md @@ -201,7 +201,7 @@ gaiad version --log_level error --long | head -n4 - wallet1 (cosmos1csdnmydggcyvjd7z8l64z9lpdgmgyr4v7hw5r8) ``` -3. (Optional) Check the balance of the wallets before transfering tokens: +3. (Optional) Check the balance of the wallets before transferring tokens: ```shell {{#template ../../templates/commands/hermes/keys/balance_1.md CHAIN_ID=ibc-0 OPTIONS= --all}} diff --git a/guide/src/documentation/forwarding/test.md b/guide/src/documentation/forwarding/test.md index bf33df7e21..01ebd2562c 100644 --- a/guide/src/documentation/forwarding/test.md +++ b/guide/src/documentation/forwarding/test.md @@ -201,7 +201,7 @@ gaiad version --log_level error --long | head -n4 - wallet1 (cosmos1csdnmydggcyvjd7z8l64z9lpdgmgyr4v7hw5r8) ``` -3. (Optional) Check the balance of the wallets before transfering tokens: +3. (Optional) Check the balance of the wallets before transferring tokens: ```shell {{#template ../../templates/commands/hermes/keys/balance_1.md CHAIN_ID=ibc-0 OPTIONS= --all}} diff --git a/guide/src/documentation/telemetry/integration.md b/guide/src/documentation/telemetry/integration.md index ec67507c3c..a33af5f656 100644 --- a/guide/src/documentation/telemetry/integration.md +++ b/guide/src/documentation/telemetry/integration.md @@ -22,10 +22,10 @@ acknowledgment_packets_confirmed_total{dst_chain="ibc-1",dst_channel="channel-0" # TYPE backlog_oldest_sequence gauge backlog_oldest_sequence{chain="ibc-0",channel="channel-0",counterparty="ibc-1",port="transfer",service_name="unknown_service",otel_scope_name="hermes",otel_scope_version=""} 0 backlog_oldest_sequence{chain="ibc-1",channel="channel-0",counterparty="ibc-0",port="transfer",service_name="unknown_service",otel_scope_name="hermes",otel_scope_version=""} 0 -# HELP backlog_oldest_timestamp Local timestamp for the oldest SendPacket event in the backlog -# TYPE backlog_oldest_timestamp gauge -backlog_oldest_timestamp{chain="ibc-0",channel="channel-0",counterparty="ibc-1",port="transfer",service_name="unknown_service",otel_scope_name="hermes",otel_scope_version=""} 0 -backlog_oldest_timestamp{chain="ibc-1",channel="channel-0",counterparty="ibc-0",port="transfer",service_name="unknown_service",otel_scope_name="hermes",otel_scope_version=""} 0 +# HELP backlog_latest_update_timestamp Local timestamp for the last time the backlog metrics have been updated +# TYPE backlog_latest_update_timestamp gauge +backlog_latest_update_timestamp{chain="ibc-0",channel="channel-0",counterparty="ibc-1",port="transfer",service_name="unknown_service",otel_scope_name="hermes",otel_scope_version=""} 0 +backlog_latest_update_timestamp{chain="ibc-1",channel="channel-0",counterparty="ibc-0",port="transfer",service_name="unknown_service",otel_scope_name="hermes",otel_scope_version=""} 0 # HELP backlog_size Total number of SendPacket events in the backlog # TYPE backlog_size gauge backlog_size{chain="ibc-0",channel="channel-0",counterparty="ibc-1",port="transfer",service_name="unknown_service",otel_scope_name="hermes",otel_scope_version=""} 0 @@ -34,6 +34,10 @@ backlog_size{chain="ibc-1",channel="channel-0",counterparty="ibc-0",port="transf # TYPE client_updates_submitted_total counter client_updates_submitted_total{client="07-tendermint-0",dst_chain="ibc-0",service_name="unknown_service",src_chain="ibc-1",otel_scope_name="hermes",otel_scope_version=""} 2 client_updates_submitted_total{client="07-tendermint-0",dst_chain="ibc-1",service_name="unknown_service",src_chain="ibc-0",otel_scope_name="hermes",otel_scope_version=""} 2 +# HELP client_updates_skipped_total Number of client update messages skipped +# TYPE client_updates_skipped_total counter +client_updates_skipped_total{client="07-tendermint-0",dst_chain="ibc-0",service_name="unknown_service",src_chain="ibc-1",otel_scope_name="hermes",otel_scope_version=""} 0 +client_updates_skipped_total{client="07-tendermint-0",dst_chain="ibc-1",service_name="unknown_service",src_chain="ibc-0",otel_scope_name="hermes",otel_scope_version=""} 0 # HELP ics29_period_fees Amount of ICS29 fees rewarded over the past 7 days # TYPE ics29_period_fees gauge ics29_period_fees{chain="ibc-0",denom="stake",receiver="cosmos1j6z6q9d2gf2suav88z8g3zf726vz9ehg4hkr8x",service_name="unknown_service",otel_scope_name="hermes",otel_scope_version=""} 0 diff --git a/guide/src/documentation/telemetry/operators.md b/guide/src/documentation/telemetry/operators.md index e98d903f05..96204843c4 100644 --- a/guide/src/documentation/telemetry/operators.md +++ b/guide/src/documentation/telemetry/operators.md @@ -34,6 +34,7 @@ The metrics in the table below are design to answer this question on multiple di | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | -------------------------- | | `workers` | Number of workers per type | `i64` UpDownCounter | Corresponding workers enabled | | `client_updates_submitted_total` | Number of client update messages submitted, per sending chain, receiving chain and client | `u64` Counter | Client, Connection, Channel or Packet workers enabled | +| `client_updates_skipped_total` | Number of client update messages skipped because the consensus state already exists, per sending chain, receiving chain and client | `u64` Counter | Client, Connection, Channel or Packet workers enabled | | `wallet_balance` | The balance of each wallet Hermes uses per chain | `f64` ValueRecorder | None | | `tx_latency_submitted` | Latency for all transactions submitted to a chain | `u64` ValueRecorder | None | | `messages_submitted_total` | Number of messages submitted to a specific chain | `u64` Counter | None | @@ -120,7 +121,7 @@ Since Hermes v1, we also introduced 3 metrics that sketch the backlog status of | Name | Description | OpenTelemetry type | Configuration Dependencies | | -------------------------- | -------------------------------------------------------------- | ------------------- | -------------------------- | | `backlog_oldest_sequence` | Sequence number of the oldest SendPacket event in the backlog | `u64` ValueRecorder | Packet workers enabled | -| `backlog_oldest_timestamp` | Local timestamp for the oldest SendPacket event in the backlog | `u64` ValueRecorder | Packet workers enabled | +| `backlog_latest_update_timestamp` | Local timestamp for the last time the backlog metrics have been updated | `u64` ValueRecorder | Packet workers enabled | | `backlog_size` | Total number of SendPacket events in the backlog | `u64` ValueRecorder | Packet workers enabled | @@ -128,9 +129,8 @@ Notes: - The `backlog_size` defines how many IBC packets users sent and were not yet relayed (i.e., received on the destination network, or timed-out). If this metric is increasing, it signals that the packet queue is increasing and there may be some errors in the Hermes logs that need your attention. -- If the `backlog_oldest_sequence` remains unchanged for more than a few minutes, that means that the packet with the respective sequence number is likely blocked -and cannot be relayed. To understand for how long the packet is block, Hermes will populate `backlog_oldest_timestamp` with the local time when it first observed -the `backlog_oldest_sequence` that is blocked. +- The `backlog_latest_update_timestamp` is used to get information on the reliability of the `backlog_*` metrics. If the timestamp doesn't change it means there might be an issue with the metrics. +- __NOTE__: The Hermes instance might miss the acknowledgment of an observed IBC packets relayed, this will cause the `backlog_*` metrics to contain an invalid value. In order to minimise this issue, whenever the Hermes instance clears packets the `backlog_*` metrics will be updated using the queried pending packets. ## How efficient and how secure is the IBC status on each network? @@ -141,6 +141,7 @@ the `backlog_oldest_sequence` that is blocked. | `tx_latency_submitted` | Latency for all transactions submitted to a chain (i.e., difference between the moment when Hermes received an event until the corresponding transaction(s) were submitted), per chain, counterparty chain, channel and port | `u64` ValueRecorder | None | | `cleared_send_packet_count_total`  | Number of SendPacket events received during the initial and periodic clearing, per chain, counterparty chain, channel and port | `u64` Counter | Packet workers enabled, and periodic packet clearing or clear on start enabled | | `cleared_acknowledgment_count_total` | Number of WriteAcknowledgement events received during the initial and periodic clearing, per chain, counterparty chain, channel and port | `u64` Counter | Packet workers enabled, and periodic packet clearing or clear on start enabled | +| `broadcast_errors_total` | Number of errors observed by Hermes when broadcasting a Tx, per error type and account | `u64` Counter | Packet workers enabled | Notes: - The two metrics `cleared_send_packet_count_total` and `cleared_acknowledgment_count_total` are only populated if `tx_confirmation = true`. diff --git a/guide/src/quick-start/pre-requisites.md b/guide/src/quick-start/pre-requisites.md index aa4a067f67..aefafe2c18 100644 --- a/guide/src/quick-start/pre-requisites.md +++ b/guide/src/quick-start/pre-requisites.md @@ -12,7 +12,7 @@ The provided instructions will install all the Rust tool chain including `rustc` ### Version requirements -Hermes is developed and tested using the latest version of Rust, `1.70` at +Hermes is developed and tested using the latest version of Rust, `1.71` at the moment. To check that your tool chain is up-to-date run: ```shell diff --git a/guide/src/templates/commands/hermes/clear/packets_1.md b/guide/src/templates/commands/hermes/clear/packets_1.md index 4efdb9b81d..2799fe42d1 100644 --- a/guide/src/templates/commands/hermes/clear/packets_1.md +++ b/guide/src/templates/commands/hermes/clear/packets_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] clear packets[[#OPTIONS]] --chain [[#CHAIN_ID]] --port [[#PORT_ID]] --channel [[#CHANNEL_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] clear packets[[#OPTIONS]] --chain [[#CHAIN_ID]] --port [[#PORT_ID]] --channel [[#CHANNEL_ID]] diff --git a/guide/src/templates/commands/hermes/clear_1.md b/guide/src/templates/commands/hermes/clear_1.md index 5df52fc125..7b516a5a57 100644 --- a/guide/src/templates/commands/hermes/clear_1.md +++ b/guide/src/templates/commands/hermes/clear_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] clear [[#SUBCOMMAND]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] clear [[#SUBCOMMAND]] diff --git a/guide/src/templates/commands/hermes/completions_1.md b/guide/src/templates/commands/hermes/completions_1.md index a06d20d797..0e8ee9cd41 100644 --- a/guide/src/templates/commands/hermes/completions_1.md +++ b/guide/src/templates/commands/hermes/completions_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] completions --shell [[#SHELL]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] completions --shell [[#SHELL]] diff --git a/guide/src/templates/commands/hermes/config/auto_1.md b/guide/src/templates/commands/hermes/config/auto_1.md index 6886505229..c7c4e932b0 100644 --- a/guide/src/templates/commands/hermes/config/auto_1.md +++ b/guide/src/templates/commands/hermes/config/auto_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] config auto[[#OPTIONS]] --output [[#PATH]] --chains [[#CHAIN_NAME:OPTIONAL_KEY_NAME]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] config auto[[#OPTIONS]] --output [[#PATH]] --chains [[#CHAIN_NAME:OPTIONAL_KEY_NAME]] diff --git a/guide/src/templates/commands/hermes/config/validate_1.md b/guide/src/templates/commands/hermes/config/validate_1.md index f7ca4895e6..2c10ddddee 100644 --- a/guide/src/templates/commands/hermes/config/validate_1.md +++ b/guide/src/templates/commands/hermes/config/validate_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] config validate \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] config validate diff --git a/guide/src/templates/commands/hermes/config_1.md b/guide/src/templates/commands/hermes/config_1.md index c9bf9b3a06..c0df196bd0 100644 --- a/guide/src/templates/commands/hermes/config_1.md +++ b/guide/src/templates/commands/hermes/config_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] config [[#SUBCOMMAND]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] config [[#SUBCOMMAND]] diff --git a/guide/src/templates/commands/hermes/create/channel_1.md b/guide/src/templates/commands/hermes/create/channel_1.md index 91966e911e..f3c0134625 100644 --- a/guide/src/templates/commands/hermes/create/channel_1.md +++ b/guide/src/templates/commands/hermes/create/channel_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] create channel[[#OPTIONS]] --a-chain [[#A_CHAIN_ID]] --a-connection [[#A_CONNECTION_ID]] --a-port [[#A_PORT_ID]] --b-port [[#B_PORT_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] create channel[[#OPTIONS]] --a-chain [[#A_CHAIN_ID]] --a-connection [[#A_CONNECTION_ID]] --a-port [[#A_PORT_ID]] --b-port [[#B_PORT_ID]] diff --git a/guide/src/templates/commands/hermes/create/channel_2.md b/guide/src/templates/commands/hermes/create/channel_2.md index 57ac622e56..51384fe2d7 100644 --- a/guide/src/templates/commands/hermes/create/channel_2.md +++ b/guide/src/templates/commands/hermes/create/channel_2.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] create channel[[#OPTIONS]] --a-chain [[#A_CHAIN_ID]] --b-chain [[#B_CHAIN_ID]] --a-port [[#A_PORT_ID]] --b-port [[#B_PORT_ID]] --new-client-connection \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] create channel[[#OPTIONS]] --a-chain [[#A_CHAIN_ID]] --b-chain [[#B_CHAIN_ID]] --a-port [[#A_PORT_ID]] --b-port [[#B_PORT_ID]] --new-client-connection diff --git a/guide/src/templates/commands/hermes/create/client_1.md b/guide/src/templates/commands/hermes/create/client_1.md index b52b9d7cff..0a9015c42d 100644 --- a/guide/src/templates/commands/hermes/create/client_1.md +++ b/guide/src/templates/commands/hermes/create/client_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] create client[[#OPTIONS]] --host-chain [[#HOST_CHAIN_ID]] --reference-chain [[#REFERENCE_CHAIN_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] create client[[#OPTIONS]] --host-chain [[#HOST_CHAIN_ID]] --reference-chain [[#REFERENCE_CHAIN_ID]] diff --git a/guide/src/templates/commands/hermes/create/connection_1.md b/guide/src/templates/commands/hermes/create/connection_1.md index 019f5e2485..51c0d41fa7 100644 --- a/guide/src/templates/commands/hermes/create/connection_1.md +++ b/guide/src/templates/commands/hermes/create/connection_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] create connection[[#OPTIONS]] --a-chain [[#A_CHAIN_ID]] --b-chain [[#B_CHAIN_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] create connection[[#OPTIONS]] --a-chain [[#A_CHAIN_ID]] --b-chain [[#B_CHAIN_ID]] diff --git a/guide/src/templates/commands/hermes/create/connection_2.md b/guide/src/templates/commands/hermes/create/connection_2.md index 40d4f5ebc5..3035a7ec2b 100644 --- a/guide/src/templates/commands/hermes/create/connection_2.md +++ b/guide/src/templates/commands/hermes/create/connection_2.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] create connection[[#OPTIONS]] --a-chain [[#A_CHAIN_ID]] --a-client [[#A_CLIENT_ID]] --b-client [[#B_CLIENT_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] create connection[[#OPTIONS]] --a-chain [[#A_CHAIN_ID]] --a-client [[#A_CLIENT_ID]] --b-client [[#B_CLIENT_ID]] diff --git a/guide/src/templates/commands/hermes/create_1.md b/guide/src/templates/commands/hermes/create_1.md index 3fe37680fb..24f9bef0f4 100644 --- a/guide/src/templates/commands/hermes/create_1.md +++ b/guide/src/templates/commands/hermes/create_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] create [[#SUBCOMMAND]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] create [[#SUBCOMMAND]] diff --git a/guide/src/templates/commands/hermes/evidence_1.md b/guide/src/templates/commands/hermes/evidence_1.md new file mode 100644 index 0000000000..5a08ef4c71 --- /dev/null +++ b/guide/src/templates/commands/hermes/evidence_1.md @@ -0,0 +1 @@ +[[#BINARY hermes]][[#GLOBALOPTIONS]] evidence[[#OPTIONS]] --chain [[#CHAIN_ID]] diff --git a/guide/src/templates/commands/hermes/fee/register-counterparty-payee_1.md b/guide/src/templates/commands/hermes/fee/register-counterparty-payee_1.md index 16ba2d7833..efe09b308e 100644 --- a/guide/src/templates/commands/hermes/fee/register-counterparty-payee_1.md +++ b/guide/src/templates/commands/hermes/fee/register-counterparty-payee_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] fee register-counterparty-payee --chain [[#CHAIN_ID]] --channel [[#CHANNEL_ID]] --port [[#PORT_ID]] --counterparty-payee [[#COUNTERPARTY_PAYEE_ADDRESS]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] fee register-counterparty-payee --chain [[#CHAIN_ID]] --channel [[#CHANNEL_ID]] --port [[#PORT_ID]] --counterparty-payee [[#COUNTERPARTY_PAYEE_ADDRESS]] diff --git a/guide/src/templates/commands/hermes/fee/register-payee_1.md b/guide/src/templates/commands/hermes/fee/register-payee_1.md index aa6093733f..115f865185 100644 --- a/guide/src/templates/commands/hermes/fee/register-payee_1.md +++ b/guide/src/templates/commands/hermes/fee/register-payee_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] fee register-payee --chain [[#CHAIN_ID]] --channel [[#CHANNEL_ID]] --port [[#PORT_ID]] --payee [[#PAYEE_ADDRESS]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] fee register-payee --chain [[#CHAIN_ID]] --channel [[#CHANNEL_ID]] --port [[#PORT_ID]] --payee [[#PAYEE_ADDRESS]] diff --git a/guide/src/templates/commands/hermes/fee/transfer_1.md b/guide/src/templates/commands/hermes/fee/transfer_1.md index ebd0e125c2..b45b830f42 100644 --- a/guide/src/templates/commands/hermes/fee/transfer_1.md +++ b/guide/src/templates/commands/hermes/fee/transfer_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] fee transfer[[#OPTIONS]] --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --src-port [[#SRC_PORT_ID]] --src-channel [[#SRC_CHANNEL_ID]] --amount [[#AMOUNT]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] fee transfer[[#OPTIONS]] --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --src-port [[#SRC_PORT_ID]] --src-channel [[#SRC_CHANNEL_ID]] --amount [[#AMOUNT]] diff --git a/guide/src/templates/commands/hermes/fee_1.md b/guide/src/templates/commands/hermes/fee_1.md index 0020a68d1c..c1d759e6ca 100644 --- a/guide/src/templates/commands/hermes/fee_1.md +++ b/guide/src/templates/commands/hermes/fee_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] fee [[#SUBCOMMAND]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] fee [[#SUBCOMMAND]] diff --git a/guide/src/templates/commands/hermes/health-check_1.md b/guide/src/templates/commands/hermes/health-check_1.md index 3d9d581618..7db1cbe8d6 100644 --- a/guide/src/templates/commands/hermes/health-check_1.md +++ b/guide/src/templates/commands/hermes/health-check_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] health-check \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] health-check diff --git a/guide/src/templates/commands/hermes/help_1.md b/guide/src/templates/commands/hermes/help_1.md index 9753c06c15..6a007e56db 100644 --- a/guide/src/templates/commands/hermes/help_1.md +++ b/guide/src/templates/commands/hermes/help_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]][[#OPTIONS]][[#SUBCOMMAND]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]][[#OPTIONS]][[#SUBCOMMAND]] diff --git a/guide/src/templates/commands/hermes/keys/add_1.md b/guide/src/templates/commands/hermes/keys/add_1.md index 2231677013..087039e1fa 100644 --- a/guide/src/templates/commands/hermes/keys/add_1.md +++ b/guide/src/templates/commands/hermes/keys/add_1.md @@ -1 +1 @@ -Add a key from a Comet keyring file: \ No newline at end of file +Add a key from a Comet keyring file: diff --git a/guide/src/templates/commands/hermes/keys/add_2.md b/guide/src/templates/commands/hermes/keys/add_2.md index 8cec138867..9a4899358b 100644 --- a/guide/src/templates/commands/hermes/keys/add_2.md +++ b/guide/src/templates/commands/hermes/keys/add_2.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] keys add[[#OPTIONS]] --chain [[#CHAIN_ID]] --key-file [[#KEY_FILE]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] keys add[[#OPTIONS]] --chain [[#CHAIN_ID]] --key-file [[#KEY_FILE]] diff --git a/guide/src/templates/commands/hermes/keys/add_3.md b/guide/src/templates/commands/hermes/keys/add_3.md index 7fb69f8bb9..3bb7522ed4 100644 --- a/guide/src/templates/commands/hermes/keys/add_3.md +++ b/guide/src/templates/commands/hermes/keys/add_3.md @@ -1 +1 @@ -Add a key from a file containing its mnemonic: \ No newline at end of file +Add a key from a file containing its mnemonic: diff --git a/guide/src/templates/commands/hermes/keys/add_4.md b/guide/src/templates/commands/hermes/keys/add_4.md index 75c51f8afb..fbb33ef2b7 100644 --- a/guide/src/templates/commands/hermes/keys/add_4.md +++ b/guide/src/templates/commands/hermes/keys/add_4.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] keys add[[#OPTIONS]] --chain [[#CHAIN_ID]] --mnemonic-file [[#MNEMONIC_FILE]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] keys add[[#OPTIONS]] --chain [[#CHAIN_ID]] --mnemonic-file [[#MNEMONIC_FILE]] diff --git a/guide/src/templates/commands/hermes/keys/add_5.md b/guide/src/templates/commands/hermes/keys/add_5.md index 4c46acd7fd..e44c2b922b 100644 --- a/guide/src/templates/commands/hermes/keys/add_5.md +++ b/guide/src/templates/commands/hermes/keys/add_5.md @@ -1 +1 @@ -On flake.nix platforms, both flags also accept `/dev/stdin` as a value, which will read the key or the mnemonic from stdin. \ No newline at end of file +On flake.nix platforms, both flags also accept `/dev/stdin` as a value, which will read the key or the mnemonic from stdin. diff --git a/guide/src/templates/commands/hermes/keys/balance_1.md b/guide/src/templates/commands/hermes/keys/balance_1.md index c946f3c227..60c9ab52f7 100644 --- a/guide/src/templates/commands/hermes/keys/balance_1.md +++ b/guide/src/templates/commands/hermes/keys/balance_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] keys balance[[#OPTIONS]] --chain [[#CHAIN_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] keys balance[[#OPTIONS]] --chain [[#CHAIN_ID]] diff --git a/guide/src/templates/commands/hermes/keys/delete_1.md b/guide/src/templates/commands/hermes/keys/delete_1.md index 235209dbf6..d3023a493c 100644 --- a/guide/src/templates/commands/hermes/keys/delete_1.md +++ b/guide/src/templates/commands/hermes/keys/delete_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] keys delete --chain [[#CHAIN_ID]] --key-name [[#KEY_NAME]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] keys delete --chain [[#CHAIN_ID]] --key-name [[#KEY_NAME]] diff --git a/guide/src/templates/commands/hermes/keys/delete_2.md b/guide/src/templates/commands/hermes/keys/delete_2.md index e32669c4f3..7c3dba6638 100644 --- a/guide/src/templates/commands/hermes/keys/delete_2.md +++ b/guide/src/templates/commands/hermes/keys/delete_2.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] keys delete --chain [[#CHAIN_ID]] --all \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] keys delete --chain [[#CHAIN_ID]] --all diff --git a/guide/src/templates/commands/hermes/keys/list_1.md b/guide/src/templates/commands/hermes/keys/list_1.md index a1887c6b3e..52a6aa7c6a 100644 --- a/guide/src/templates/commands/hermes/keys/list_1.md +++ b/guide/src/templates/commands/hermes/keys/list_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] keys list --chain [[#CHAIN_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] keys list --chain [[#CHAIN_ID]] diff --git a/guide/src/templates/commands/hermes/keys_1.md b/guide/src/templates/commands/hermes/keys_1.md index 2fa18be15c..d5f2d2416c 100644 --- a/guide/src/templates/commands/hermes/keys_1.md +++ b/guide/src/templates/commands/hermes/keys_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] keys [[#SUBCOMMAND]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] keys [[#SUBCOMMAND]] diff --git a/guide/src/templates/commands/hermes/listen_1.md b/guide/src/templates/commands/hermes/listen_1.md index b596520871..7c040d78a1 100644 --- a/guide/src/templates/commands/hermes/listen_1.md +++ b/guide/src/templates/commands/hermes/listen_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] listen[[#OPTIONS]] --chain [[#CHAIN_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] listen[[#OPTIONS]] --chain [[#CHAIN_ID]] diff --git a/guide/src/templates/commands/hermes/logs/reset_1.md b/guide/src/templates/commands/hermes/logs/reset_1.md index f5ab35bf6d..dadb22dbe0 100644 --- a/guide/src/templates/commands/hermes/logs/reset_1.md +++ b/guide/src/templates/commands/hermes/logs/reset_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] logs reset \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] logs reset diff --git a/guide/src/templates/commands/hermes/logs/set-log-level_1.md b/guide/src/templates/commands/hermes/logs/set-log-level_1.md index 5485b576de..164fe55d1b 100644 --- a/guide/src/templates/commands/hermes/logs/set-log-level_1.md +++ b/guide/src/templates/commands/hermes/logs/set-log-level_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] logs set-log-level[[#OPTIONS]] --log-level [[#LOG_LEVEL]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] logs set-log-level[[#OPTIONS]] --log-level [[#LOG_LEVEL]] diff --git a/guide/src/templates/commands/hermes/logs/set-raw-filter_1.md b/guide/src/templates/commands/hermes/logs/set-raw-filter_1.md index eeabc079e5..53cb0bd24c 100644 --- a/guide/src/templates/commands/hermes/logs/set-raw-filter_1.md +++ b/guide/src/templates/commands/hermes/logs/set-raw-filter_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] logs set-raw-filter --raw-filter [[#RAW_FILTER]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] logs set-raw-filter --raw-filter [[#RAW_FILTER]] diff --git a/guide/src/templates/commands/hermes/logs_1.md b/guide/src/templates/commands/hermes/logs_1.md index fd983789c1..d8377bcf68 100644 --- a/guide/src/templates/commands/hermes/logs_1.md +++ b/guide/src/templates/commands/hermes/logs_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] logs [[#SUBCOMMAND]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] logs [[#SUBCOMMAND]] diff --git a/guide/src/templates/commands/hermes/misbehaviour_1.md b/guide/src/templates/commands/hermes/misbehaviour_1.md index 93118a0269..96a77cba42 100644 --- a/guide/src/templates/commands/hermes/misbehaviour_1.md +++ b/guide/src/templates/commands/hermes/misbehaviour_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] misbehaviour --chain [[#CHAIN_ID]] --client [[#CLIENT_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] misbehaviour --chain [[#CHAIN_ID]] --client [[#CLIENT_ID]] diff --git a/guide/src/templates/commands/hermes/query/channel/client_1.md b/guide/src/templates/commands/hermes/query/channel/client_1.md index 775d1a558c..eb85e91db8 100644 --- a/guide/src/templates/commands/hermes/query/channel/client_1.md +++ b/guide/src/templates/commands/hermes/query/channel/client_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query channel client --chain [[#CHAIN_ID]] --port [[#PORT_ID]] --channel [[#CHANNEL_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query channel client --chain [[#CHAIN_ID]] --port [[#PORT_ID]] --channel [[#CHANNEL_ID]] diff --git a/guide/src/templates/commands/hermes/query/channel/end_1.md b/guide/src/templates/commands/hermes/query/channel/end_1.md index 4ae001d634..e6e07b133d 100644 --- a/guide/src/templates/commands/hermes/query/channel/end_1.md +++ b/guide/src/templates/commands/hermes/query/channel/end_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query channel end[[#OPTIONS]] --chain [[#CHAIN_ID]] --port [[#PORT_ID]] --channel [[#CHANNEL_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query channel end[[#OPTIONS]] --chain [[#CHAIN_ID]] --port [[#PORT_ID]] --channel [[#CHANNEL_ID]] diff --git a/guide/src/templates/commands/hermes/query/channel/ends_1.md b/guide/src/templates/commands/hermes/query/channel/ends_1.md index fa0bdd8cdc..241db662e6 100644 --- a/guide/src/templates/commands/hermes/query/channel/ends_1.md +++ b/guide/src/templates/commands/hermes/query/channel/ends_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query channel ends[[#OPTIONS]] --chain [[#CHAIN_ID]] --port [[#PORT_ID]] --channel [[#CHANNEL_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query channel ends[[#OPTIONS]] --chain [[#CHAIN_ID]] --port [[#PORT_ID]] --channel [[#CHANNEL_ID]] diff --git a/guide/src/templates/commands/hermes/query/channel_1.md b/guide/src/templates/commands/hermes/query/channel_1.md index 56adaeab53..330cf87fee 100644 --- a/guide/src/templates/commands/hermes/query/channel_1.md +++ b/guide/src/templates/commands/hermes/query/channel_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query channel [[#SUBCOMMAND]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query channel [[#SUBCOMMAND]] diff --git a/guide/src/templates/commands/hermes/query/channels_1.md b/guide/src/templates/commands/hermes/query/channels_1.md index ca716b9afd..245229e3a7 100644 --- a/guide/src/templates/commands/hermes/query/channels_1.md +++ b/guide/src/templates/commands/hermes/query/channels_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query channels[[#OPTIONS]] --chain [[#CHAIN_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query channels[[#OPTIONS]] --chain [[#CHAIN_ID]] diff --git a/guide/src/templates/commands/hermes/query/client/connections_1.md b/guide/src/templates/commands/hermes/query/client/connections_1.md index c424906882..c106c18560 100644 --- a/guide/src/templates/commands/hermes/query/client/connections_1.md +++ b/guide/src/templates/commands/hermes/query/client/connections_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query client connections[[#OPTIONS]] --chain [[#CHAIN_ID]] --client [[#CLIENT_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query client connections[[#OPTIONS]] --chain [[#CHAIN_ID]] --client [[#CLIENT_ID]] diff --git a/guide/src/templates/commands/hermes/query/client/consensus_1.md b/guide/src/templates/commands/hermes/query/client/consensus_1.md index 330ee1b64e..66b04bde7c 100644 --- a/guide/src/templates/commands/hermes/query/client/consensus_1.md +++ b/guide/src/templates/commands/hermes/query/client/consensus_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query client consensus[[#OPTIONS]] --chain [[#CHAIN_ID]] --client [[#CLIENT_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query client consensus[[#OPTIONS]] --chain [[#CHAIN_ID]] --client [[#CLIENT_ID]] diff --git a/guide/src/templates/commands/hermes/query/client/header_1.md b/guide/src/templates/commands/hermes/query/client/header_1.md index b0738bd191..ab1ba2afbf 100644 --- a/guide/src/templates/commands/hermes/query/client/header_1.md +++ b/guide/src/templates/commands/hermes/query/client/header_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query client header[[#OPTIONS]] --chain [[#CHAIN_ID]] --client [[#CLIENT_ID]] --consensus-height [[#CONSENSUS_HEIGHT]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query client header[[#OPTIONS]] --chain [[#CHAIN_ID]] --client [[#CLIENT_ID]] --consensus-height [[#CONSENSUS_HEIGHT]] diff --git a/guide/src/templates/commands/hermes/query/client/state_1.md b/guide/src/templates/commands/hermes/query/client/state_1.md index df51c517ac..372d2d04ec 100644 --- a/guide/src/templates/commands/hermes/query/client/state_1.md +++ b/guide/src/templates/commands/hermes/query/client/state_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query client state[[#OPTIONS]] --chain [[#CHAIN_ID]] --client [[#CLIENT_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query client state[[#OPTIONS]] --chain [[#CHAIN_ID]] --client [[#CLIENT_ID]] diff --git a/guide/src/templates/commands/hermes/query/client/status_1.md b/guide/src/templates/commands/hermes/query/client/status_1.md index 7d1ff654ed..b4f56996ed 100644 --- a/guide/src/templates/commands/hermes/query/client/status_1.md +++ b/guide/src/templates/commands/hermes/query/client/status_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query client status --chain [[#CHAIN_ID]] --client [[#CLIENT_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query client status --chain [[#CHAIN_ID]] --client [[#CLIENT_ID]] diff --git a/guide/src/templates/commands/hermes/query/client_1.md b/guide/src/templates/commands/hermes/query/client_1.md index 4bab05d621..d2621fa192 100644 --- a/guide/src/templates/commands/hermes/query/client_1.md +++ b/guide/src/templates/commands/hermes/query/client_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query client [[#SUBCOMMAND]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query client [[#SUBCOMMAND]] diff --git a/guide/src/templates/commands/hermes/query/clients_1.md b/guide/src/templates/commands/hermes/query/clients_1.md index e8d7359e6a..3daedb2a1e 100644 --- a/guide/src/templates/commands/hermes/query/clients_1.md +++ b/guide/src/templates/commands/hermes/query/clients_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query clients[[#OPTIONS]] --host-chain [[#HOST_CHAIN_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query clients[[#OPTIONS]] --host-chain [[#HOST_CHAIN_ID]] diff --git a/guide/src/templates/commands/hermes/query/connection/channels_1.md b/guide/src/templates/commands/hermes/query/connection/channels_1.md index bd25265ff4..6125e9e967 100644 --- a/guide/src/templates/commands/hermes/query/connection/channels_1.md +++ b/guide/src/templates/commands/hermes/query/connection/channels_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query connection channels --chain [[#CHAIN_ID]] --connection [[#CONNECTION_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query connection channels --chain [[#CHAIN_ID]] --connection [[#CONNECTION_ID]] diff --git a/guide/src/templates/commands/hermes/query/connection/end_1.md b/guide/src/templates/commands/hermes/query/connection/end_1.md index 950e792e2a..0c5400ae39 100644 --- a/guide/src/templates/commands/hermes/query/connection/end_1.md +++ b/guide/src/templates/commands/hermes/query/connection/end_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query connection end[[#OPTIONS]] --chain [[#CHAIN_ID]] --connection [[#CONNECTION_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query connection end[[#OPTIONS]] --chain [[#CHAIN_ID]] --connection [[#CONNECTION_ID]] diff --git a/guide/src/templates/commands/hermes/query/connection_1.md b/guide/src/templates/commands/hermes/query/connection_1.md index cf99893668..d1bc7e1515 100644 --- a/guide/src/templates/commands/hermes/query/connection_1.md +++ b/guide/src/templates/commands/hermes/query/connection_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query connection [[#SUBCOMMAND]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query connection [[#SUBCOMMAND]] diff --git a/guide/src/templates/commands/hermes/query/connections_1.md b/guide/src/templates/commands/hermes/query/connections_1.md index 56be68f377..0319641ecd 100644 --- a/guide/src/templates/commands/hermes/query/connections_1.md +++ b/guide/src/templates/commands/hermes/query/connections_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query connections[[#OPTIONS]] --chain [[#CHAIN_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query connections[[#OPTIONS]] --chain [[#CHAIN_ID]] diff --git a/guide/src/templates/commands/hermes/query/packet/ack_1.md b/guide/src/templates/commands/hermes/query/packet/ack_1.md index e264dc1b7a..f719128c22 100644 --- a/guide/src/templates/commands/hermes/query/packet/ack_1.md +++ b/guide/src/templates/commands/hermes/query/packet/ack_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query packet ack[[#OPTIONS]] --chain [[#CHAIN_ID]] --port [[#PORT_ID]] --channel [[#CHANNEL_ID]] --sequence [[#SEQUENCE]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query packet ack[[#OPTIONS]] --chain [[#CHAIN_ID]] --port [[#PORT_ID]] --channel [[#CHANNEL_ID]] --sequence [[#SEQUENCE]] diff --git a/guide/src/templates/commands/hermes/query/packet/acks_1.md b/guide/src/templates/commands/hermes/query/packet/acks_1.md index 7463c22a19..3b0d5143ec 100644 --- a/guide/src/templates/commands/hermes/query/packet/acks_1.md +++ b/guide/src/templates/commands/hermes/query/packet/acks_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query packet acks --chain [[#CHAIN_ID]] --port [[#PORT_ID]] --channel [[#CHANNEL_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query packet acks --chain [[#CHAIN_ID]] --port [[#PORT_ID]] --channel [[#CHANNEL_ID]] diff --git a/guide/src/templates/commands/hermes/query/packet/commitment_1.md b/guide/src/templates/commands/hermes/query/packet/commitment_1.md index 51f7b4ab0f..fdf68791ce 100644 --- a/guide/src/templates/commands/hermes/query/packet/commitment_1.md +++ b/guide/src/templates/commands/hermes/query/packet/commitment_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query packet commitment[[#OPTIONS]] --chain [[#CHAIN_ID]] --port [[#PORT_ID]] --channel [[#CHANNEL_ID]] --sequence [[#SEQUENCE]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query packet commitment[[#OPTIONS]] --chain [[#CHAIN_ID]] --port [[#PORT_ID]] --channel [[#CHANNEL_ID]] --sequence [[#SEQUENCE]] diff --git a/guide/src/templates/commands/hermes/query/packet/commitments_1.md b/guide/src/templates/commands/hermes/query/packet/commitments_1.md index c76599c8b6..57b807de52 100644 --- a/guide/src/templates/commands/hermes/query/packet/commitments_1.md +++ b/guide/src/templates/commands/hermes/query/packet/commitments_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query packet commitments --chain [[#CHAIN_ID]] --port [[#PORT_ID]] --channel [[#CHANNEL_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query packet commitments --chain [[#CHAIN_ID]] --port [[#PORT_ID]] --channel [[#CHANNEL_ID]] diff --git a/guide/src/templates/commands/hermes/query/packet/pending-acks_1.md b/guide/src/templates/commands/hermes/query/packet/pending-acks_1.md index 4295fb7a63..28abad7ab1 100644 --- a/guide/src/templates/commands/hermes/query/packet/pending-acks_1.md +++ b/guide/src/templates/commands/hermes/query/packet/pending-acks_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query packet pending-acks --chain [[#CHAIN_ID]] --port [[#PORT_ID]] --channel [[#CHANNEL_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query packet pending-acks --chain [[#CHAIN_ID]] --port [[#PORT_ID]] --channel [[#CHANNEL_ID]] diff --git a/guide/src/templates/commands/hermes/query/packet/pending-sends_1.md b/guide/src/templates/commands/hermes/query/packet/pending-sends_1.md index ba812f7f55..db32ee3c67 100644 --- a/guide/src/templates/commands/hermes/query/packet/pending-sends_1.md +++ b/guide/src/templates/commands/hermes/query/packet/pending-sends_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query packet pending-sends --chain [[#CHAIN_ID]] --port [[#PORT_ID]] --channel [[#CHANNEL_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query packet pending-sends --chain [[#CHAIN_ID]] --port [[#PORT_ID]] --channel [[#CHANNEL_ID]] diff --git a/guide/src/templates/commands/hermes/query/packet/pending_1.md b/guide/src/templates/commands/hermes/query/packet/pending_1.md index 8c5ffdac8e..d44ecfd5d0 100644 --- a/guide/src/templates/commands/hermes/query/packet/pending_1.md +++ b/guide/src/templates/commands/hermes/query/packet/pending_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query packet pending --chain [[#CHAIN_ID]] --port [[#PORT_ID]] --channel [[#CHANNEL_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query packet pending --chain [[#CHAIN_ID]] --port [[#PORT_ID]] --channel [[#CHANNEL_ID]] diff --git a/guide/src/templates/commands/hermes/query/packet_1.md b/guide/src/templates/commands/hermes/query/packet_1.md index e01562e4ec..90d389b6a6 100644 --- a/guide/src/templates/commands/hermes/query/packet_1.md +++ b/guide/src/templates/commands/hermes/query/packet_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query packet [[#SUBCOMMAND]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query packet [[#SUBCOMMAND]] diff --git a/guide/src/templates/commands/hermes/query/transfer/denom-trace_1.md b/guide/src/templates/commands/hermes/query/transfer/denom-trace_1.md index 892ff84086..030469df6d 100644 --- a/guide/src/templates/commands/hermes/query/transfer/denom-trace_1.md +++ b/guide/src/templates/commands/hermes/query/transfer/denom-trace_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query transfer denom-trace --chain [[#CHAIN_ID]] --hash [[#HASH]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query transfer denom-trace --chain [[#CHAIN_ID]] --hash [[#HASH]] diff --git a/guide/src/templates/commands/hermes/query/transfer_1.md b/guide/src/templates/commands/hermes/query/transfer_1.md index 75329ad655..373bdebdcc 100644 --- a/guide/src/templates/commands/hermes/query/transfer_1.md +++ b/guide/src/templates/commands/hermes/query/transfer_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query transfer [[#SUBCOMMAND]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query transfer [[#SUBCOMMAND]] diff --git a/guide/src/templates/commands/hermes/query/tx/events_1.md b/guide/src/templates/commands/hermes/query/tx/events_1.md index 75fad32a46..7f732710c5 100644 --- a/guide/src/templates/commands/hermes/query/tx/events_1.md +++ b/guide/src/templates/commands/hermes/query/tx/events_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query tx events --chain [[#CHAIN_ID]] --hash [[#HASH]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query tx events --chain [[#CHAIN_ID]] --hash [[#HASH]] diff --git a/guide/src/templates/commands/hermes/query/tx_1.md b/guide/src/templates/commands/hermes/query/tx_1.md index fa8e272808..c1ceebdd7c 100644 --- a/guide/src/templates/commands/hermes/query/tx_1.md +++ b/guide/src/templates/commands/hermes/query/tx_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query tx [[#SUBCOMMAND]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query tx [[#SUBCOMMAND]] diff --git a/guide/src/templates/commands/hermes/query_1.md b/guide/src/templates/commands/hermes/query_1.md index 642eb68ddb..02b47178b8 100644 --- a/guide/src/templates/commands/hermes/query_1.md +++ b/guide/src/templates/commands/hermes/query_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] query [[#SUBCOMMAND]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] query [[#SUBCOMMAND]] diff --git a/guide/src/templates/commands/hermes/start_1.md b/guide/src/templates/commands/hermes/start_1.md index 7ca2807b18..ea42387c81 100644 --- a/guide/src/templates/commands/hermes/start_1.md +++ b/guide/src/templates/commands/hermes/start_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] start[[#OPTIONS]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] start[[#OPTIONS]] diff --git a/guide/src/templates/commands/hermes/tx/chan-close-confirm_1.md b/guide/src/templates/commands/hermes/tx/chan-close-confirm_1.md index a709e4ca61..7946270032 100644 --- a/guide/src/templates/commands/hermes/tx/chan-close-confirm_1.md +++ b/guide/src/templates/commands/hermes/tx/chan-close-confirm_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] tx chan-close-confirm --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --dst-connection [[#DST_CONNECTION_ID]] --dst-port [[#DST_PORT_ID]] --src-port [[#SRC_PORT_ID]] --dst-channel [[#DST_CHANNEL_ID]] --src-channel [[#SRC_CHANNEL_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] tx chan-close-confirm --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --dst-connection [[#DST_CONNECTION_ID]] --dst-port [[#DST_PORT_ID]] --src-port [[#SRC_PORT_ID]] --dst-channel [[#DST_CHANNEL_ID]] --src-channel [[#SRC_CHANNEL_ID]] diff --git a/guide/src/templates/commands/hermes/tx/chan-close-init_1.md b/guide/src/templates/commands/hermes/tx/chan-close-init_1.md index e056033eeb..3e3385a0d7 100644 --- a/guide/src/templates/commands/hermes/tx/chan-close-init_1.md +++ b/guide/src/templates/commands/hermes/tx/chan-close-init_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] tx chan-close-init --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --dst-connection [[#DST_CONNECTION_ID]] --dst-port [[#DST_PORT_ID]] --src-port [[#SRC_PORT_ID]] --dst-channel [[#DST_CHANNEL_ID]] --src-channel [[#SRC_CHANNEL_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] tx chan-close-init --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --dst-connection [[#DST_CONNECTION_ID]] --dst-port [[#DST_PORT_ID]] --src-port [[#SRC_PORT_ID]] --dst-channel [[#DST_CHANNEL_ID]] --src-channel [[#SRC_CHANNEL_ID]] diff --git a/guide/src/templates/commands/hermes/tx/chan-open-ack_1.md b/guide/src/templates/commands/hermes/tx/chan-open-ack_1.md index c9ad37a8c6..4f4ad5367d 100644 --- a/guide/src/templates/commands/hermes/tx/chan-open-ack_1.md +++ b/guide/src/templates/commands/hermes/tx/chan-open-ack_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] tx chan-open-ack --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --dst-connection [[#DST_CONNECTION_ID]] --dst-port [[#DST_PORT_ID]] --src-port [[#SRC_PORT_ID]] --dst-channel [[#DST_CHANNEL_ID]] --src-channel [[#SRC_CHANNEL_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] tx chan-open-ack --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --dst-connection [[#DST_CONNECTION_ID]] --dst-port [[#DST_PORT_ID]] --src-port [[#SRC_PORT_ID]] --dst-channel [[#DST_CHANNEL_ID]] --src-channel [[#SRC_CHANNEL_ID]] diff --git a/guide/src/templates/commands/hermes/tx/chan-open-confirm_1.md b/guide/src/templates/commands/hermes/tx/chan-open-confirm_1.md index 0016c1871a..a415d2f369 100644 --- a/guide/src/templates/commands/hermes/tx/chan-open-confirm_1.md +++ b/guide/src/templates/commands/hermes/tx/chan-open-confirm_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] tx chan-open-confirm --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --dst-connection [[#DST_CONNECTION_ID]] --dst-port [[#DST_PORT_ID]] --src-port [[#SRC_PORT_ID]] --dst-channel [[#DST_CHANNEL_ID]] --src-channel [[#SRC_CHANNEL_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] tx chan-open-confirm --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --dst-connection [[#DST_CONNECTION_ID]] --dst-port [[#DST_PORT_ID]] --src-port [[#SRC_PORT_ID]] --dst-channel [[#DST_CHANNEL_ID]] --src-channel [[#SRC_CHANNEL_ID]] diff --git a/guide/src/templates/commands/hermes/tx/chan-open-init_1.md b/guide/src/templates/commands/hermes/tx/chan-open-init_1.md index 6b6d67c4e1..ff22d6c62a 100644 --- a/guide/src/templates/commands/hermes/tx/chan-open-init_1.md +++ b/guide/src/templates/commands/hermes/tx/chan-open-init_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] tx chan-open-init[[#OPTIONS]] --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --dst-connection [[#DST_CONNECTION_ID]] --dst-port [[#DST_PORT_ID]] --src-port [[#SRC_PORT_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] tx chan-open-init[[#OPTIONS]] --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --dst-connection [[#DST_CONNECTION_ID]] --dst-port [[#DST_PORT_ID]] --src-port [[#SRC_PORT_ID]] diff --git a/guide/src/templates/commands/hermes/tx/chan-open-try_1.md b/guide/src/templates/commands/hermes/tx/chan-open-try_1.md index eb4df9cd61..8d8c6dfe55 100644 --- a/guide/src/templates/commands/hermes/tx/chan-open-try_1.md +++ b/guide/src/templates/commands/hermes/tx/chan-open-try_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] tx chan-open-try[[#OPTIONS]] --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --dst-connection [[#DST_CONNECTION_ID]] --dst-port [[#DST_PORT_ID]] --src-port [[#SRC_PORT_ID]] --src-channel [[#SRC_CHANNEL_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] tx chan-open-try[[#OPTIONS]] --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --dst-connection [[#DST_CONNECTION_ID]] --dst-port [[#DST_PORT_ID]] --src-port [[#SRC_PORT_ID]] --src-channel [[#SRC_CHANNEL_ID]] diff --git a/guide/src/templates/commands/hermes/tx/conn-ack_1.md b/guide/src/templates/commands/hermes/tx/conn-ack_1.md index 94528b9445..95382a52c0 100644 --- a/guide/src/templates/commands/hermes/tx/conn-ack_1.md +++ b/guide/src/templates/commands/hermes/tx/conn-ack_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] tx conn-ack --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --dst-client [[#DST_CLIENT_ID]] --src-client [[#SRC_CLIENT_ID]] --dst-connection [[#DST_CONNECTION_ID]] --src-connection [[#SRC_CONNECTION_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] tx conn-ack --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --dst-client [[#DST_CLIENT_ID]] --src-client [[#SRC_CLIENT_ID]] --dst-connection [[#DST_CONNECTION_ID]] --src-connection [[#SRC_CONNECTION_ID]] diff --git a/guide/src/templates/commands/hermes/tx/conn-confirm_1.md b/guide/src/templates/commands/hermes/tx/conn-confirm_1.md index f356aa953e..e7b7c6ae54 100644 --- a/guide/src/templates/commands/hermes/tx/conn-confirm_1.md +++ b/guide/src/templates/commands/hermes/tx/conn-confirm_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] tx conn-confirm --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --dst-client [[#DST_CLIENT_ID]] --src-client [[#SRC_CLIENT_ID]] --dst-connection [[#DST_CONNECTION_ID]] --src-connection [[#SRC_CONNECTION_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] tx conn-confirm --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --dst-client [[#DST_CLIENT_ID]] --src-client [[#SRC_CLIENT_ID]] --dst-connection [[#DST_CONNECTION_ID]] --src-connection [[#SRC_CONNECTION_ID]] diff --git a/guide/src/templates/commands/hermes/tx/conn-init_1.md b/guide/src/templates/commands/hermes/tx/conn-init_1.md index 12add1670d..b8cf68ee2c 100644 --- a/guide/src/templates/commands/hermes/tx/conn-init_1.md +++ b/guide/src/templates/commands/hermes/tx/conn-init_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] tx conn-init --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --dst-client [[#DST_CLIENT_ID]] --src-client [[#SRC_CLIENT_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] tx conn-init --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --dst-client [[#DST_CLIENT_ID]] --src-client [[#SRC_CLIENT_ID]] diff --git a/guide/src/templates/commands/hermes/tx/conn-try_1.md b/guide/src/templates/commands/hermes/tx/conn-try_1.md index 3cd0532eeb..772d25d5af 100644 --- a/guide/src/templates/commands/hermes/tx/conn-try_1.md +++ b/guide/src/templates/commands/hermes/tx/conn-try_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] tx conn-try[[#OPTIONS]] --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --dst-client [[#DST_CLIENT_ID]] --src-client [[#SRC_CLIENT_ID]] --src-connection [[#SRC_CONNECTION_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] tx conn-try[[#OPTIONS]] --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --dst-client [[#DST_CLIENT_ID]] --src-client [[#SRC_CLIENT_ID]] --src-connection [[#SRC_CONNECTION_ID]] diff --git a/guide/src/templates/commands/hermes/tx/ft-transfer_1.md b/guide/src/templates/commands/hermes/tx/ft-transfer_1.md index 4cb657344a..0f75e26c48 100644 --- a/guide/src/templates/commands/hermes/tx/ft-transfer_1.md +++ b/guide/src/templates/commands/hermes/tx/ft-transfer_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] tx ft-transfer[[#OPTIONS]] --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --src-port [[#SRC_PORT_ID]] --src-channel [[#SRC_CHANNEL_ID]] --amount [[#AMOUNT]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] tx ft-transfer[[#OPTIONS]] --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --src-port [[#SRC_PORT_ID]] --src-channel [[#SRC_CHANNEL_ID]] --amount [[#AMOUNT]] diff --git a/guide/src/templates/commands/hermes/tx/packet-ack_1.md b/guide/src/templates/commands/hermes/tx/packet-ack_1.md index 8002a26bf9..0ae1302cd4 100644 --- a/guide/src/templates/commands/hermes/tx/packet-ack_1.md +++ b/guide/src/templates/commands/hermes/tx/packet-ack_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] tx packet-ack[[#OPTIONS]] --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --src-port [[#SRC_PORT_ID]] --src-channel [[#SRC_CHANNEL_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] tx packet-ack[[#OPTIONS]] --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --src-port [[#SRC_PORT_ID]] --src-channel [[#SRC_CHANNEL_ID]] diff --git a/guide/src/templates/commands/hermes/tx/packet-recv_1.md b/guide/src/templates/commands/hermes/tx/packet-recv_1.md index 7e7242f6db..391607bf19 100644 --- a/guide/src/templates/commands/hermes/tx/packet-recv_1.md +++ b/guide/src/templates/commands/hermes/tx/packet-recv_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] tx packet-recv[[#OPTIONS]] --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --src-port [[#SRC_PORT_ID]] --src-channel [[#SRC_CHANNEL_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] tx packet-recv[[#OPTIONS]] --dst-chain [[#DST_CHAIN_ID]] --src-chain [[#SRC_CHAIN_ID]] --src-port [[#SRC_PORT_ID]] --src-channel [[#SRC_CHANNEL_ID]] diff --git a/guide/src/templates/commands/hermes/tx/upgrade-chain_1.md b/guide/src/templates/commands/hermes/tx/upgrade-chain_1.md index aceb9f48c1..8151701a16 100644 --- a/guide/src/templates/commands/hermes/tx/upgrade-chain_1.md +++ b/guide/src/templates/commands/hermes/tx/upgrade-chain_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] tx upgrade-chain[[#OPTIONS]] --reference-chain [[#REFERENCE_CHAIN_ID]] --host-chain [[#HOST_CHAIN_ID]] --host-client [[#HOST_CLIENT_ID]] --amount [[#AMOUNT]] --height-offset [[#HEIGHT_OFFSET]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] tx upgrade-chain[[#OPTIONS]] --reference-chain [[#REFERENCE_CHAIN_ID]] --host-chain [[#HOST_CHAIN_ID]] --host-client [[#HOST_CLIENT_ID]] --amount [[#AMOUNT]] --height-offset [[#HEIGHT_OFFSET]] diff --git a/guide/src/templates/commands/hermes/tx_1.md b/guide/src/templates/commands/hermes/tx_1.md index eca9bc54c0..2619d479d0 100644 --- a/guide/src/templates/commands/hermes/tx_1.md +++ b/guide/src/templates/commands/hermes/tx_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] tx [[#SUBCOMMAND]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] tx [[#SUBCOMMAND]] diff --git a/guide/src/templates/commands/hermes/update/client_1.md b/guide/src/templates/commands/hermes/update/client_1.md index 242df424bd..7cfb119475 100644 --- a/guide/src/templates/commands/hermes/update/client_1.md +++ b/guide/src/templates/commands/hermes/update/client_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] update client[[#OPTIONS]] --host-chain [[#HOST_CHAIN_ID]] --client [[#CLIENT_ID]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] update client[[#OPTIONS]] --host-chain [[#HOST_CHAIN_ID]] --client [[#CLIENT_ID]] diff --git a/guide/src/templates/commands/hermes/update_1.md b/guide/src/templates/commands/hermes/update_1.md index f2a78315ec..7b0b60456b 100644 --- a/guide/src/templates/commands/hermes/update_1.md +++ b/guide/src/templates/commands/hermes/update_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] update [[#SUBCOMMAND]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] update [[#SUBCOMMAND]] diff --git a/guide/src/templates/commands/hermes/upgrade/client_1.md b/guide/src/templates/commands/hermes/upgrade/client_1.md index 9952a4147b..2577c7c284 100644 --- a/guide/src/templates/commands/hermes/upgrade/client_1.md +++ b/guide/src/templates/commands/hermes/upgrade/client_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] upgrade client --host-chain [[#HOST_CHAIN_ID]] --client [[#CLIENT_ID]] --upgrade-height [[#REFERENCE_UPGRADE_HEIGHT]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] upgrade client --host-chain [[#HOST_CHAIN_ID]] --client [[#CLIENT_ID]] --upgrade-height [[#REFERENCE_UPGRADE_HEIGHT]] diff --git a/guide/src/templates/commands/hermes/upgrade/clients_1.md b/guide/src/templates/commands/hermes/upgrade/clients_1.md index 0d9cd56554..d9853d84e4 100644 --- a/guide/src/templates/commands/hermes/upgrade/clients_1.md +++ b/guide/src/templates/commands/hermes/upgrade/clients_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] upgrade clients[[#OPTIONS]] --reference-chain [[#REFERENCE_CHAIN_ID]] --upgrade-height [[#REFERENCE_UPGRADE_HEIGHT]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] upgrade clients[[#OPTIONS]] --reference-chain [[#REFERENCE_CHAIN_ID]] --upgrade-height [[#REFERENCE_UPGRADE_HEIGHT]] diff --git a/guide/src/templates/commands/hermes/upgrade_1.md b/guide/src/templates/commands/hermes/upgrade_1.md index 0fc1bac6f8..35da035cf5 100644 --- a/guide/src/templates/commands/hermes/upgrade_1.md +++ b/guide/src/templates/commands/hermes/upgrade_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] upgrade [[#SUBCOMMAND]] \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] upgrade [[#SUBCOMMAND]] diff --git a/guide/src/templates/commands/hermes/version_1.md b/guide/src/templates/commands/hermes/version_1.md index ad6c83dabf..1623e03d4c 100644 --- a/guide/src/templates/commands/hermes/version_1.md +++ b/guide/src/templates/commands/hermes/version_1.md @@ -1 +1 @@ -[[#BINARY hermes]][[#GLOBALOPTIONS]] version \ No newline at end of file +[[#BINARY hermes]][[#GLOBALOPTIONS]] version diff --git a/guide/src/templates/files/hermes/local-chains/config.toml b/guide/src/templates/files/hermes/local-chains/config.toml index 04893b2475..c0730f2a36 100644 --- a/guide/src/templates/files/hermes/local-chains/config.toml +++ b/guide/src/templates/files/hermes/local-chains/config.toml @@ -27,6 +27,7 @@ port = 3001 [[chains]] id = 'ibc-0' +type = "CosmosSdk" rpc_addr = 'http://localhost:27030' grpc_addr = 'http://localhost:27032' event_source = { mode = 'push', url = 'ws://localhost:27030/websocket', batch_delay = '200ms' } @@ -36,7 +37,7 @@ account_prefix = 'cosmos' key_name = 'wallet' store_prefix = 'ibc' gas_price = { price = 0.001, denom = 'stake' } -gas_multiplier = 1.1 +gas_multiplier = 1.2 default_gas = 1000000 max_gas = 10000000 max_msg_num = 30 @@ -55,6 +56,7 @@ trust_threshold = { numerator = '2', denominator = '3' } [[chains]] id = 'ibc-1' +type = "CosmosSdk" rpc_addr = 'http://localhost:27040' grpc_addr = 'http://localhost:27042' event_source = { mode = 'push', url = 'ws://localhost:27040/websocket', batch_delay = '200ms' } @@ -64,7 +66,7 @@ account_prefix = 'cosmos' key_name = 'wallet' store_prefix = 'ibc' gas_price = { price = 0.001, denom = 'stake' } -gas_multiplier = 1.1 +gas_multiplier = 1.2 default_gas = 1000000 max_gas = 10000000 max_msg_num = 30 @@ -80,4 +82,3 @@ trust_threshold = { numerator = '2', denominator = '3' } # ['ica*', '*'], # ['transfer', 'channel-0'], # ] - diff --git a/guide/src/templates/files/hermes/more-chains/config_with_filters.toml b/guide/src/templates/files/hermes/more-chains/config_with_filters.toml index 59899f8b91..c74bab9a21 100644 --- a/guide/src/templates/files/hermes/more-chains/config_with_filters.toml +++ b/guide/src/templates/files/hermes/more-chains/config_with_filters.toml @@ -27,18 +27,25 @@ port = 3001 [[chains]] id = 'ibc-0' +type = 'CosmosSdk' rpc_addr = 'http://localhost:27050' grpc_addr = 'http://localhost:27052' -event_source = { mode = 'push', url = 'ws://localhost:27050/websocket', batch_delay = '500ms' } +event_source = { mode = 'push', url = 'ws://localhost:27050/websocket', batch_delay = '200ms' } rpc_timeout = '15s' +trusted_node = true account_prefix = 'cosmos' key_name = 'wallet' store_prefix = 'ibc' -gas_price = { price = 0.01, denom = 'stake' } +gas_price = { price = 0.001, denom = 'stake' } +gas_multiplier = 1.2 +default_gas = 1000000 max_gas = 10000000 +max_msg_num = 30 +max_tx_size = 2097152 clock_drift = '5s' +max_block_time = '30s' trusting_period = '14days' -trust_threshold = { numerator = '1', denominator = '3' } +trust_threshold = { numerator = '2', denominator = '3' } [chains.packet_filter] policy = 'allow' @@ -49,18 +56,25 @@ list = [ [[chains]] id = 'ibc-1' +type = 'CosmosSdk' rpc_addr = 'http://localhost:27060' grpc_addr = 'http://localhost:27062' -event_source = { mode = 'push', url = 'ws://localhost:27060/websocket', batch_delay = '500ms' } +event_source = { mode = 'push', url = 'ws://localhost:27060/websocket', batch_delay = '200ms' } rpc_timeout = '15s' +trusted_node = true account_prefix = 'cosmos' key_name = 'wallet' store_prefix = 'ibc' -gas_price = { price = 0.01, denom = 'stake' } +gas_price = { price = 0.001, denom = 'stake' } +gas_multiplier = 1.2 +default_gas = 1000000 max_gas = 10000000 +max_msg_num = 30 +max_tx_size = 2097152 clock_drift = '5s' +max_block_time = '30s' trusting_period = '14days' -trust_threshold = { numerator = '1', denominator = '3' } +trust_threshold = { numerator = '2', denominator = '3' } [chains.packet_filter] @@ -72,18 +86,25 @@ list = [ [[chains]] id = 'ibc-2' +type = 'CosmosSdk' rpc_addr = 'http://localhost:27070' grpc_addr = 'http://localhost:27072' -event_source = { mode = 'push', url = 'ws://localhost:27070/websocket', batch_delay = '500ms' } +event_source = { mode = 'push', url = 'ws://localhost:27070/websocket', batch_delay = '200ms' } rpc_timeout = '15s' +trusted_node = true account_prefix = 'cosmos' key_name = 'wallet' store_prefix = 'ibc' -gas_price = { price = 0.01, denom = 'stake' } +gas_price = { price = 0.001, denom = 'stake' } +gas_multiplier = 1.2 +default_gas = 1000000 max_gas = 10000000 +max_msg_num = 30 +max_tx_size = 2097152 clock_drift = '5s' +max_block_time = '30s' trusting_period = '14days' -trust_threshold = { numerator = '1', denominator = '3' } +trust_threshold = { numerator = '2', denominator = '3' } [chains.packet_filter] policy = 'allow' @@ -94,22 +115,29 @@ list = [ [[chains]] id = 'ibc-3' +type = 'CosmosSdk' rpc_addr = 'http://localhost:27080' grpc_addr = 'http://localhost:27082' -event_source = { mode = 'push', url = 'ws://localhost:27080/websocket', batch_delay = '500ms' } +event_source = { mode = 'push', url = 'ws://localhost:27080/websocket', batch_delay = '200ms' } rpc_timeout = '15s' +trusted_node = true account_prefix = 'cosmos' key_name = 'wallet' store_prefix = 'ibc' -gas_price = { price = 0.01, denom = 'stake' } +gas_price = { price = 0.001, denom = 'stake' } +gas_multiplier = 1.2 +default_gas = 1000000 max_gas = 10000000 +max_msg_num = 30 +max_tx_size = 2097152 clock_drift = '5s' +max_block_time = '30s' trusting_period = '14days' -trust_threshold = { numerator = '1', denominator = '3' } +trust_threshold = { numerator = '2', denominator = '3' } [chains.packet_filter] policy = 'allow' list = [ ['transfer', 'channel-0'], ['transfer', 'channel-2'], -] \ No newline at end of file +] diff --git a/guide/src/templates/files/hermes/more-chains/config_without_filters.toml b/guide/src/templates/files/hermes/more-chains/config_without_filters.toml index fff4a5100d..93b1959d9e 100644 --- a/guide/src/templates/files/hermes/more-chains/config_without_filters.toml +++ b/guide/src/templates/files/hermes/more-chains/config_without_filters.toml @@ -27,60 +27,88 @@ port = 3001 [[chains]] id = 'ibc-0' +type = 'CosmosSdk' rpc_addr = 'http://localhost:27050' grpc_addr = 'http://localhost:27052' -event_source = { mode = 'push', url = 'ws://localhost:27050/websocket', batch_delay = '500ms' } +event_source = { mode = 'push', url = 'ws://localhost:27050/websocket', batch_delay = '200ms' } rpc_timeout = '15s' +trusted_node = true account_prefix = 'cosmos' key_name = 'wallet' store_prefix = 'ibc' -gas_price = { price = 0.01, denom = 'stake' } +gas_price = { price = 0.001, denom = 'stake' } +gas_multiplier = 1.2 +default_gas = 1000000 max_gas = 10000000 +max_msg_num = 30 +max_tx_size = 2097152 clock_drift = '5s' +max_block_time = '30s' trusting_period = '14days' -trust_threshold = { numerator = '1', denominator = '3' } +trust_threshold = { numerator = '2', denominator = '3' } [[chains]] id = 'ibc-1' +type = 'CosmosSdk' rpc_addr = 'http://localhost:27060' grpc_addr = 'http://localhost:27062' -event_source = { mode = 'push', url = 'ws://localhost:27060/websocket', batch_delay = '500ms' } +event_source = { mode = 'push', url = 'ws://localhost:27060/websocket', batch_delay = '200ms' } rpc_timeout = '15s' +trusted_node = true account_prefix = 'cosmos' key_name = 'wallet' store_prefix = 'ibc' -gas_price = { price = 0.01, denom = 'stake' } +gas_price = { price = 0.001, denom = 'stake' } +gas_multiplier = 1.2 +default_gas = 1000000 max_gas = 10000000 +max_msg_num = 30 +max_tx_size = 2097152 clock_drift = '5s' +max_block_time = '30s' trusting_period = '14days' -trust_threshold = { numerator = '1', denominator = '3' } +trust_threshold = { numerator = '2', denominator = '3' } [[chains]] id = 'ibc-2' +type = 'CosmosSdk' rpc_addr = 'http://localhost:27070' grpc_addr = 'http://localhost:27072' -event_source = { mode = 'push', url = 'ws://localhost:27070/websocket', batch_delay = '500ms' } +event_source = { mode = 'push', url = 'ws://localhost:27070/websocket', batch_delay = '200ms' } rpc_timeout = '15s' +trusted_node = true account_prefix = 'cosmos' key_name = 'wallet' store_prefix = 'ibc' -gas_price = { price = 0.01, denom = 'stake' } +gas_price = { price = 0.001, denom = 'stake' } +gas_multiplier = 1.2 +default_gas = 1000000 max_gas = 10000000 +max_msg_num = 30 +max_tx_size = 2097152 clock_drift = '5s' +max_block_time = '30s' trusting_period = '14days' -trust_threshold = { numerator = '1', denominator = '3' } +trust_threshold = { numerator = '2', denominator = '3' } [[chains]] id = 'ibc-3' +type = 'CosmosSdk' rpc_addr = 'http://localhost:27080' grpc_addr = 'http://localhost:27082' -event_source = { mode = 'push', url = 'ws://localhost:27080/websocket', batch_delay = '500ms' } +event_source = { mode = 'push', url = 'ws://localhost:27080/websocket', batch_delay = '200ms' } rpc_timeout = '15s' +trusted_node = true account_prefix = 'cosmos' key_name = 'wallet' store_prefix = 'ibc' -gas_price = { price = 0.01, denom = 'stake' } +gas_price = { price = 0.001, denom = 'stake' } +gas_multiplier = 1.2 +default_gas = 1000000 max_gas = 10000000 +max_msg_num = 30 +max_tx_size = 2097152 clock_drift = '5s' +max_block_time = '30s' trusting_period = '14days' -trust_threshold = { numerator = '1', denominator = '3' } \ No newline at end of file +trust_threshold = { numerator = '2', denominator = '3' } diff --git a/guide/src/templates/files/hermes/more-chains/hermes_second_instance.toml b/guide/src/templates/files/hermes/more-chains/hermes_second_instance.toml index 3d50e4836a..5acc3944a7 100644 --- a/guide/src/templates/files/hermes/more-chains/hermes_second_instance.toml +++ b/guide/src/templates/files/hermes/more-chains/hermes_second_instance.toml @@ -27,18 +27,25 @@ port = 3002 [[chains]] id = 'ibc-0' +type = 'CosmosSdk' rpc_addr = 'http://localhost:27050' grpc_addr = 'http://localhost:27052' -event_source = { mode = 'push', url = 'ws://localhost:27050/websocket', batch_delay = '500ms' } +event_source = { mode = 'push', url = 'ws://localhost:27050/websocket', batch_delay = '200ms' } rpc_timeout = '15s' +trusted_node = true account_prefix = 'cosmos' -key_name = 'wallet1' +key_name = 'wallet' store_prefix = 'ibc' -gas_price = { price = 0.01, denom = 'stake' } +gas_price = { price = 0.001, denom = 'stake' } +gas_multiplier = 1.2 +default_gas = 1000000 max_gas = 10000000 +max_msg_num = 30 +max_tx_size = 2097152 clock_drift = '5s' +max_block_time = '30s' trusting_period = '14days' -trust_threshold = { numerator = '1', denominator = '3' } +trust_threshold = { numerator = '2', denominator = '3' } [chains.packet_filter] policy = 'allow' @@ -48,19 +55,25 @@ list = [ [[chains]] id = 'ibc-1' +type = 'CosmosSdk' rpc_addr = 'http://localhost:27060' grpc_addr = 'http://localhost:27062' -event_source = { mode = 'push', url = 'ws://localhost:27060/websocket', batch_delay = '500ms' } +event_source = { mode = 'push', url = 'ws://localhost:27060/websocket', batch_delay = '200ms' } rpc_timeout = '15s' +trusted_node = true account_prefix = 'cosmos' -key_name = 'wallet1' +key_name = 'wallet' store_prefix = 'ibc' -gas_price = { price = 0.01, denom = 'stake' } +gas_price = { price = 0.001, denom = 'stake' } +gas_multiplier = 1.2 +default_gas = 1000000 max_gas = 10000000 +max_msg_num = 30 +max_tx_size = 2097152 clock_drift = '5s' +max_block_time = '30s' trusting_period = '14days' -trust_threshold = { numerator = '1', denominator = '3' } - +trust_threshold = { numerator = '2', denominator = '3' } [chains.packet_filter] policy = 'allow' @@ -70,18 +83,25 @@ list = [ [[chains]] id = 'ibc-2' +type = 'CosmosSdk' rpc_addr = 'http://localhost:27070' grpc_addr = 'http://localhost:27072' -event_source = { mode = 'push', url = 'ws://localhost:27070/websocket', batch_delay = '500ms' } +event_source = { mode = 'push', url = 'ws://localhost:27070/websocket', batch_delay = '200ms' } rpc_timeout = '15s' +trusted_node = true account_prefix = 'cosmos' -key_name = 'wallet1' +key_name = 'wallet' store_prefix = 'ibc' -gas_price = { price = 0.01, denom = 'stake' } +gas_price = { price = 0.001, denom = 'stake' } +gas_multiplier = 1.2 +default_gas = 1000000 max_gas = 10000000 +max_msg_num = 30 +max_tx_size = 2097152 clock_drift = '5s' +max_block_time = '30s' trusting_period = '14days' -trust_threshold = { numerator = '1', denominator = '3' } +trust_threshold = { numerator = '2', denominator = '3' } [chains.packet_filter] policy = 'allow' @@ -91,21 +111,28 @@ list = [ [[chains]] id = 'ibc-3' +type = 'CosmosSdk' rpc_addr = 'http://localhost:27080' grpc_addr = 'http://localhost:27082' -event_source = { mode = 'push', url = 'ws://localhost:27080/websocket', batch_delay = '500ms' } +event_source = { mode = 'push', url = 'ws://localhost:27080/websocket', batch_delay = '200ms' } rpc_timeout = '15s' +trusted_node = true account_prefix = 'cosmos' -key_name = 'wallet1' +key_name = 'wallet' store_prefix = 'ibc' -gas_price = { price = 0.01, denom = 'stake' } +gas_price = { price = 0.001, denom = 'stake' } +gas_multiplier = 1.2 +default_gas = 1000000 max_gas = 10000000 +max_msg_num = 30 +max_tx_size = 2097152 clock_drift = '5s' +max_block_time = '30s' trusting_period = '14days' -trust_threshold = { numerator = '1', denominator = '3' } +trust_threshold = { numerator = '2', denominator = '3' } [chains.packet_filter] policy = 'allow' list = [ ['transfer', 'channel-1'], -] \ No newline at end of file +] diff --git a/guide/src/templates/files/hermes/production/config.toml b/guide/src/templates/files/hermes/production/config.toml index 90f4a1cca8..ad6c2d5808 100644 --- a/guide/src/templates/files/hermes/production/config.toml +++ b/guide/src/templates/files/hermes/production/config.toml @@ -103,4 +103,4 @@ list = [[ ]] [chains.address_type] -derivation = 'cosmos' \ No newline at end of file +derivation = 'cosmos' diff --git a/guide/src/templates/help_templates/evidence.md b/guide/src/templates/help_templates/evidence.md new file mode 100644 index 0000000000..a8a2cdea05 --- /dev/null +++ b/guide/src/templates/help_templates/evidence.md @@ -0,0 +1,19 @@ +DESCRIPTION: +Listen to block events and handles evidence + +USAGE: + hermes evidence [OPTIONS] --chain + +OPTIONS: + --check-past-blocks + Check the last NUM_BLOCKS blocks for misbehaviour (default: 100) [default: 100] + + -h, --help + Print help information + + --key-name + Use the given signing key name for sending the misbehaviour evidence detected (default: + `key_name` config) + +REQUIRED: + --chain Identifier of the chain where blocks are monitored for misbehaviour diff --git a/guide/src/templates/help_templates/fee/register-counterparty-payee.md b/guide/src/templates/help_templates/fee/register-counterparty-payee.md index cd1ba0d1bc..afbd774b4c 100644 --- a/guide/src/templates/help_templates/fee/register-counterparty-payee.md +++ b/guide/src/templates/help_templates/fee/register-counterparty-payee.md @@ -15,7 +15,13 @@ FLAGS: Identifier of the channel [aliases: chan] --counterparty-payee - Address of the counterparty payee + Address of the counterparty payee. + + Note that there exists a configuration parameter `auto_register_counterparty_payee` that + can be enabled in order to have Hermes automatically register the counterparty payee on + the destination chain to the relayer's address on the source chain. This option can be + used for simple configuration of the relayer to receive fees for relaying RecvPackets on + fee-enabled channels. --port Identifier of the port diff --git a/guide/src/templates/help_templates/help.md b/guide/src/templates/help_templates/help.md index 11aa32e2af..8a0011bd76 100644 --- a/guide/src/templates/help_templates/help.md +++ b/guide/src/templates/help_templates/help.md @@ -17,13 +17,14 @@ SUBCOMMANDS: clear Clear objects, such as outstanding packets on a channel config Generate a new Hermes configuration file or validate an existing one create Create objects (client, connection, or channel) on chains + evidence Listen to block events and handles evidence fee Interact with the fee middleware health-check Performs a health check of all chains in the the config help Print this message or the help of the given subcommand(s) keys Manage keys in the relayer for each chain listen Listen to and display IBC events emitted by a chain logs Update tracing log directives - misbehaviour Listen to client update IBC events and handles misbehaviour + misbehaviour Listen to client update IBC events and handle misbehaviour query Query objects from the chain start Start the relayer in multi-chain mode tx Create and send IBC transactions diff --git a/guide/src/templates/help_templates/misbehaviour.md b/guide/src/templates/help_templates/misbehaviour.md index 5344c12d13..e669d63344 100644 --- a/guide/src/templates/help_templates/misbehaviour.md +++ b/guide/src/templates/help_templates/misbehaviour.md @@ -1,5 +1,5 @@ DESCRIPTION: -Listen to client update IBC events and handles misbehaviour +Listen to client update IBC events and handle misbehaviour USAGE: hermes misbehaviour --chain --client diff --git a/guide/src/templates/help_templates/tx/upgrade-chain.md b/guide/src/templates/help_templates/tx/upgrade-chain.md index ed5dc6ac29..444afc3fdf 100644 --- a/guide/src/templates/help_templates/tx/upgrade-chain.md +++ b/guide/src/templates/help_templates/tx/upgrade-chain.md @@ -8,6 +8,10 @@ OPTIONS: --denom Denomination for the deposit (default: 'stake') + --gov-account + Authority account used to sign upgrade proposal. Note: This is only used for chains with + ibc-go version v8.0.0 or higher + -h, --help Print help information diff --git a/guide/src/templates/hermes-version.md b/guide/src/templates/hermes-version.md index a7e7c99725..a9bbd79f98 100644 --- a/guide/src/templates/hermes-version.md +++ b/guide/src/templates/hermes-version.md @@ -1 +1 @@ -v1.6.0+1c1cf02 +v1.7.4 diff --git a/guide/src/tutorials/local-chains/start-relaying.md b/guide/src/tutorials/local-chains/start-relaying.md index ac980e0e38..6f5c7f0eef 100644 --- a/guide/src/tutorials/local-chains/start-relaying.md +++ b/guide/src/tutorials/local-chains/start-relaying.md @@ -105,8 +105,6 @@ Now, let's exchange `samoleans` between two chains. - Balances on ibc-1: ``` balances: - - amount: "0" - denom: ibc/C1840BD16FCFA8F421DAA0DAAB08B9C323FC7685D0D7951DC37B3F9ECB08A199 - amount: "100000000" denom: samoleans - amount: "99983879" diff --git a/guide/src/tutorials/more-chains/start-relaying.md b/guide/src/tutorials/more-chains/start-relaying.md index 9890a8745e..27aee65296 100644 --- a/guide/src/tutorials/more-chains/start-relaying.md +++ b/guide/src/tutorials/more-chains/start-relaying.md @@ -165,8 +165,6 @@ Now, let's exchange `samoleans` between chains. - Balances on `ibc-2`: ``` balances: - - amount: "0" - denom: ibc/C1840BD16FCFA8F421DAA0DAAB08B9C323FC7685D0D7951DC37B3F9ECB08A199 - amount: "100000000" denom: samoleans - amount: "99977059" @@ -247,8 +245,6 @@ A((ibc-3)) --> B((ibc-0)) --> C((ibc-1)); - Balances on `ibc-0`: ``` balances: - - amount: "0" - denom: ibc/563FDAE5A0D8C15013E4485134A2D2EE3317452278B56B2ED63DDB4EB677DF84 - amount: "100000000" denom: samoleans - amount: "99978828" @@ -306,8 +302,6 @@ A((ibc-3))-->B((ibc-2))-->C((ibc-1)); - Balances at ibc-3: ``` balances: - - amount: "0" - denom: ibc/C658F0EB9DE176E080B586D634004141239C3E55676462C976266DB54C56EBE4 - amount: "100000000" denom: samoleans - amount: "99973935" @@ -340,8 +334,6 @@ A((ibc-3))-->B((ibc-2))-->C((ibc-1)); - Balances on `ibc-2`: ``` balances: - - amount: "0" - denom: ibc/C1840BD16FCFA8F421DAA0DAAB08B9C323FC7685D0D7951DC37B3F9ECB08A199 - amount: "100000000" denom: samoleans - amount: "99974602" diff --git a/guide/src/tutorials/production/start-relaying.md b/guide/src/tutorials/production/start-relaying.md index 38df477571..90b7e4c6b7 100644 --- a/guide/src/tutorials/production/start-relaying.md +++ b/guide/src/tutorials/production/start-relaying.md @@ -33,7 +33,7 @@ Finally, Hermes is designed to relay without any intervention, however, you migh ## Next steps -Visit the [Telemetry](../../documentation/telemetry/index.md) section to learn how to use the metrics and the [Avanced](../../advanced/index.md) section to learn about Hermes' features and general guidelines for troubleshooting. +Visit the [Telemetry](../../documentation/telemetry/index.md) section to learn how to use the metrics and the [Advanced](../../advanced/index.md) section to learn about Hermes' features and general guidelines for troubleshooting. You can also learn more about [Grafana's features](https://grafana.com/tutorials/grafana-fundamentals/) and learn how to create a [Grafana Managed Alert](https://grafana.com/docs/grafana/latest/alerting/alerting-rules/create-grafana-managed-rule/). diff --git a/scripts/auto_gen_templates.sh b/scripts/auto_gen_templates.sh old mode 100644 new mode 100755 index d7eb557357..aaf0c605d8 --- a/scripts/auto_gen_templates.sh +++ b/scripts/auto_gen_templates.sh @@ -192,7 +192,7 @@ function generate_templates(){ do # Create a template for every usage filename=$COMMAND_DIR$path"_$cpt.md" - echo -n $line > $TMP_PATH + echo $line > $TMP_PATH local cpt=$((cpt+1)) if ! cmp -s $TMP_PATH $filename; then if [ $MODE = "update" ]; then diff --git a/scripts/one-chain b/scripts/one-chain index 30a1af787b..47bf41365e 100755 --- a/scripts/one-chain +++ b/scripts/one-chain @@ -146,7 +146,7 @@ fi # Start gaia echo "Start gaia on grpc port: $GRPC_PORT..." -$BINARY --home $CHAIN_DIR/$CHAIN_ID start --pruning=nothing --grpc.address="0.0.0.0:$GRPC_PORT" --log_level error > $CHAIN_DIR/$CHAIN_ID.log 2>&1 & +$BINARY --home $CHAIN_DIR/$CHAIN_ID start --pruning=nothing --grpc.address="0.0.0.0:$GRPC_PORT" --log_level info > $CHAIN_DIR/$CHAIN_ID.log 2>&1 & # Show validator's and user's balance sleep 3 diff --git a/tools/check-guide/Cargo.lock b/tools/check-guide/Cargo.lock index b6e0dbe517..735f88c9a3 100644 --- a/tools/check-guide/Cargo.lock +++ b/tools/check-guide/Cargo.lock @@ -43,9 +43,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -58,18 +58,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "0.7.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" -dependencies = [ - "memchr", -] - -[[package]] -name = "aho-corasick" -version = "1.0.2" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" dependencies = [ "memchr", ] @@ -104,30 +95,29 @@ dependencies = [ [[package]] name = "anstream" -version = "0.3.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", - "is-terminal", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" dependencies = [ "utf8parse", ] @@ -143,9 +133,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "1.0.1" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" dependencies = [ "anstyle", "windows-sys 0.48.0", @@ -153,9 +143,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "arc-swap" @@ -182,18 +172,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.37", ] [[package]] name = "async-trait" -version = "0.1.72" +version = "0.1.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" +checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.37", ] [[package]] @@ -209,7 +199,7 @@ dependencies = [ "rustls-native-certs", "tokio", "tokio-rustls", - "tungstenite 0.20.1", + "tungstenite", ] [[package]] @@ -231,9 +221,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "axum" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8175979259124331c1d7bf6586ee7e0da434155e4b2d48ec2c8386281d8df39" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" dependencies = [ "async-trait", "axum-core", @@ -280,9 +270,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.68" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", @@ -307,9 +297,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.2" +version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" [[package]] name = "base64ct" @@ -376,9 +366,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" [[package]] name = "block-buffer" @@ -409,9 +399,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.6.0" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" +checksum = "4c2f7349907b712260e64b0afe2f84692af14a454be26187d9df565c7f69266a" dependencies = [ "memchr", "regex-automata 0.3.9", @@ -420,9 +410,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "byte-unit" @@ -436,9 +426,9 @@ dependencies = [ [[package]] name = "bytecount" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c" +checksum = "ad152d03a2c813c80bb94fedbf3a3f02b28f793e39e7c214c8a0bcc196343de7" [[package]] name = "byteorder" @@ -448,9 +438,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" dependencies = [ "serde", ] @@ -472,9 +462,9 @@ checksum = "e6e9e01327e6c86e92ec72b1c798d4a94810f147209bbe3ffab6a86954937a6f" [[package]] name = "cargo-platform" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" dependencies = [ "serde", ] @@ -494,9 +484,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -524,14 +517,14 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.26" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" dependencies = [ "android-tzdata", "iana-time-zone", "num-traits", - "winapi", + "windows-targets 0.48.5", ] [[package]] @@ -553,23 +546,22 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.11" +version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1640e5cc7fb47dbb8338fd471b105e7ed6c3cb2aeb00c2e067127ffd3764a05d" +checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.3.11" +version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98c59138d527eeaf9b53f35a77fcc1fad9d883116070c63d5de1c7dc7b00c72b" +checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" dependencies = [ "anstream", "anstyle", - "clap_lex 0.5.0", - "once_cell", + "clap_lex 0.5.1", "strsim", "terminal_size", ] @@ -585,11 +577,11 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.3.2" +version = "4.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc443334c81a804575546c5a8a79b4913b50e28d69232903604cada1de817ce" +checksum = "e3ae8ba90b9d8b007efe66e55e48fb936272f5ca00349b5b0e89877520d35ea7" dependencies = [ - "clap 4.3.11", + "clap 4.4.6", ] [[package]] @@ -616,9 +608,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" [[package]] name = "color-eyre" @@ -668,9 +660,9 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747" +checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" [[package]] name = "contracts" @@ -769,9 +761,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4c2f4e1afd912bc40bfd6fed5d9dc1f288e0ba01bfcc835cc5bc3eb13efe15" +checksum = "740fe28e594155f10cfc383984cbefd529d7396050557148f79cb0f621204124" dependencies = [ "generic-array", "rand_core", @@ -791,9 +783,9 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.0.0" +version = "4.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f711ade317dd348950a9910f81c5947e3d8907ebd2b83f76203ff1807e6a2bc2" +checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -814,7 +806,7 @@ checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.37", ] [[package]] @@ -832,12 +824,12 @@ dependencies = [ [[package]] name = "dashmap" -version = "5.5.0" +version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6943ae99c34386c84a470c499d3414f66502a41340aa895406e0d2e4a207b91d" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if 1.0.0", - "hashbrown 0.14.0", + "hashbrown 0.14.1", "lock_api", "once_cell", "parking_lot_core", @@ -851,14 +843,20 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "der" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7ed52955ce76b1554f509074bb357d3fb8ac9b51288a65a3fd480d1dfba946" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" dependencies = [ "const-oid", "zeroize", ] +[[package]] +name = "deranged" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" + [[package]] name = "derivation-path" version = "0.2.0" @@ -930,17 +928,11 @@ dependencies = [ "winapi", ] -[[package]] -name = "dyn-clone" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "304e6508efa593091e97a9abbc10f90aa7ca635b6d2784feff3c89d41dd12272" - [[package]] name = "ecdsa" -version = "0.16.7" +version = "0.16.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0997c976637b606099b9985693efa3581e84e41f5c11ba5255f88711058ad428" +checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" dependencies = [ "der", "digest 0.10.7", @@ -984,7 +976,7 @@ dependencies = [ "ed25519", "rand_core", "serde", - "sha2 0.10.7", + "sha2 0.10.8", "zeroize", ] @@ -997,14 +989,14 @@ dependencies = [ "derivation-path", "ed25519-dalek", "hmac", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "elasticlunr-rs" @@ -1020,9 +1012,9 @@ dependencies = [ [[package]] name = "elliptic-curve" -version = "0.13.5" +version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" +checksum = "d97ca172ae9dc9f9b779a6e3a65d308f2af74e5b8c921299075bdb4a0370e914" dependencies = [ "base16ct", "crypto-bigint", @@ -1045,9 +1037,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.32" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ "cfg-if 1.0.0", ] @@ -1084,20 +1076,11 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" -[[package]] -name = "erased-serde" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f94c0e13118e7d7533271f754a168ae8400e6a1cc043f2bfd53cc7290f1a1de3" -dependencies = [ - "serde", -] - [[package]] name = "errno" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" dependencies = [ "errno-dragonfly", "libc", @@ -1145,12 +1128,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.9.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "ff" @@ -1164,19 +1144,19 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.1.20" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77" +checksum = "d0870c84016d4b481be5c9f323c24f65e31e901ae618f0e80f4308fb00de1d2d" [[package]] name = "filetime" -version = "0.2.21" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" +checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.2.16", + "redox_syscall 0.3.5", "windows-sys 0.48.0", ] @@ -1296,7 +1276,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.37", ] [[package]] @@ -1355,9 +1335,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.3" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" [[package]] name = "glob" @@ -1367,11 +1347,11 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.10" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" +checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" dependencies = [ - "aho-corasick 0.7.20", + "aho-corasick", "bstr", "fnv", "log", @@ -1411,9 +1391,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.20" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" +checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" dependencies = [ "bytes", "fnv", @@ -1436,9 +1416,9 @@ checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "handlebars" -version = "4.3.7" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c3372087601b532857d332f5957cbae686da52bb7810bf038c3e3c3cc2fa0d" +checksum = "c39b3bc2a8f715298032cf5087e58573809374b08160aa7d750582bdb82d2683" dependencies = [ "log", "pest", @@ -1456,9 +1436,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" [[package]] name = "hdpath" @@ -1471,12 +1451,11 @@ dependencies = [ [[package]] name = "headers" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" +checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" dependencies = [ - "base64 0.13.1", - "bitflags 1.3.2", + "base64 0.21.4", "bytes", "headers-core", "http", @@ -1511,9 +1490,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "hex" @@ -1580,9 +1559,9 @@ checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humantime" @@ -1617,7 +1596,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.4.9", "tokio", "tower-service", "tracing", @@ -1675,7 +1654,7 @@ dependencies = [ [[package]] name = "ibc-chain-registry" -version = "0.25.0" +version = "0.26.1" dependencies = [ "async-trait", "flex-error", @@ -1683,7 +1662,7 @@ dependencies = [ "http", "ibc-proto", "ibc-relayer-types", - "itertools", + "itertools 0.10.5", "reqwest", "serde", "serde_json", @@ -1694,11 +1673,11 @@ dependencies = [ [[package]] name = "ibc-proto" -version = "0.37.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "725fd83c94e9859fd967cd706996679799171eba940740f071f0046fb6f6e031" +checksum = "32b5aca9ca863246a2b358e0a1845759780860673e54c0a76335faccc504981c" dependencies = [ - "base64 0.21.2", + "base64 0.21.4", "bytes", "flex-error", "ics23", @@ -1711,7 +1690,7 @@ dependencies = [ [[package]] name = "ibc-relayer" -version = "0.25.0" +version = "0.26.1" dependencies = [ "anyhow", "async-stream", @@ -1737,7 +1716,7 @@ dependencies = [ "ibc-proto", "ibc-relayer-types", "ibc-telemetry", - "itertools", + "itertools 0.10.5", "moka", "num-bigint", "num-rational", @@ -1751,28 +1730,31 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "signature", "strum", "subtle-encoding", "tendermint", "tendermint-light-client", "tendermint-light-client-detector", + "tendermint-light-client-verifier", + "tendermint-proto", "tendermint-rpc", "thiserror", "tiny-bip39", "tiny-keccak", "tokio", "tokio-stream", - "toml 0.7.6", + "toml 0.7.8", "tonic", "tracing", - "uuid 1.4.0", + "tracing-subscriber", + "uuid 1.4.1", ] [[package]] name = "ibc-relayer-cli" -version = "1.6.0" +version = "1.7.1" dependencies = [ "abscissa_core", "clap 3.2.25", @@ -1793,7 +1775,7 @@ dependencies = [ "ibc-relayer-rest", "ibc-relayer-types", "ibc-telemetry", - "itertools", + "itertools 0.10.5", "oneline-eyre", "regex", "serde", @@ -1811,7 +1793,7 @@ dependencies = [ [[package]] name = "ibc-relayer-rest" -version = "0.25.0" +version = "0.26.1" dependencies = [ "axum", "crossbeam-channel 0.5.8", @@ -1824,16 +1806,14 @@ dependencies = [ [[package]] name = "ibc-relayer-types" -version = "0.25.0" +version = "0.26.1" dependencies = [ "bytes", "derive_more", - "dyn-clone", - "erased-serde", "flex-error", "ibc-proto", "ics23", - "itertools", + "itertools 0.10.5", "num-rational", "primitive-types", "prost", @@ -1852,7 +1832,7 @@ dependencies = [ [[package]] name = "ibc-telemetry" -version = "0.25.0" +version = "0.26.1" dependencies = [ "axum", "dashmap", @@ -1882,7 +1862,7 @@ dependencies = [ "prost", "ripemd", "serde", - "sha2 0.10.7", + "sha2 0.10.8", "sha3", ] @@ -1946,12 +1926,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown 0.14.1", ] [[package]] @@ -1984,26 +1964,6 @@ dependencies = [ "libc", ] -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.2", - "libc", - "windows-sys 0.48.0", -] - [[package]] name = "ipnet" version = "2.8.0" @@ -2016,8 +1976,8 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi 0.3.2", - "rustix 0.38.4", + "hermit-abi 0.3.3", + "rustix", "windows-sys 0.48.0", ] @@ -2030,11 +1990,20 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itoa" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "js-sys" @@ -2054,7 +2023,7 @@ dependencies = [ "cfg-if 1.0.0", "ecdsa", "elliptic-curve", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -2068,9 +2037,9 @@ dependencies = [ [[package]] name = "kqueue" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" dependencies = [ "kqueue-sys", "libc", @@ -2078,9 +2047,9 @@ dependencies = [ [[package]] name = "kqueue-sys" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" dependencies = [ "bitflags 1.3.2", "libc", @@ -2094,21 +2063,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.147" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - -[[package]] -name = "linux-raw-sys" -version = "0.3.8" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "linux-raw-sys" -version = "0.4.3" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" +checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" [[package]] name = "lock_api" @@ -2122,9 +2085,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "mac" @@ -2172,9 +2135,9 @@ dependencies = [ [[package]] name = "matchit" -version = "0.7.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "maybe-uninit" @@ -2184,15 +2147,15 @@ checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "mdbook" -version = "0.4.31" +version = "0.4.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b67ee4a744f36e6280792016c17e69921b51df357181d1eb17d620fcc3609f3" +checksum = "1c3f88addd34930bc5f01b9dc19f780447e51c92bf2536e3ded058018271775d" dependencies = [ "ammonia", "anyhow", "chrono", - "clap 4.3.11", - "clap_complete 4.3.2", + "clap 4.4.6", + "clap_complete 4.4.3", "elasticlunr-rs", "env_logger 0.10.0", "futures-util", @@ -2287,9 +2250,9 @@ dependencies = [ [[package]] name = "moka" -version = "0.11.3" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa6e72583bf6830c956235bff0d5afec8cf2952f579ebad18ae7821a917d950f" +checksum = "d8017ec3548ffe7d4cef7ac0e12b044c01164a74c0f3119420faeaf13490ad8b" dependencies = [ "crossbeam-channel 0.5.8", "crossbeam-epoch", @@ -2298,13 +2261,12 @@ dependencies = [ "parking_lot", "quanta", "rustc_version", - "scheduled-thread-pool", "skeptic", "smallvec", "tagptr", "thiserror", "triomphe", - "uuid 1.4.0", + "uuid 1.4.1", ] [[package]] @@ -2313,29 +2275,39 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" +[[package]] +name = "normpath" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec60c60a693226186f5d6edf073232bfb6464ed97eb22cf3b01c1e8198fd97f5" +dependencies = [ + "windows-sys 0.48.0", +] + [[package]] name = "notify" -version = "5.2.0" +version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "729f63e1ca555a43fe3efa4f3efdf4801c479da85b432242a7b726f353c88486" +checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.0", "crossbeam-channel 0.5.8", "filetime", "fsevent-sys", "inotify", "kqueue", "libc", + "log", "mio", "walkdir", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] name = "notify-debouncer-mini" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e23e9fa24f094b143c1eb61f90ac6457de87be6987bc70746e0179f7dbc9007b" +checksum = "e55ee272914f4563a2f8b8553eb6811f3c0caea81c756346bad15b7e3ef969f0" dependencies = [ "crossbeam-channel 0.5.8", "notify", @@ -2353,9 +2325,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" dependencies = [ "autocfg", "num-integer", @@ -2399,9 +2371,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] @@ -2412,15 +2384,15 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi 0.3.3", "libc", ] [[package]] name = "object" -version = "0.31.1" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" dependencies = [ "memchr", ] @@ -2448,11 +2420,12 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "opener" -version = "0.5.2" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "293c15678e37254c15bd2f092314abb4e51d7fdde05c2021279c12631b54f005" +checksum = "6c62dcb6174f9cb326eac248f07e955d5d559c272730b6c03e396b443b562788" dependencies = [ "bstr", + "normpath", "winapi", ] @@ -2557,14 +2530,14 @@ dependencies = [ "libc", "redox_syscall 0.3.5", "smallvec", - "windows-targets 0.48.1", + "windows-targets 0.48.5", ] [[package]] name = "paste" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4b27ab7be369122c218afc2079489cdcb4b517c0a3fc386ff11e1fedfcc2b35" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "pbkdf2" @@ -2610,19 +2583,20 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pest" -version = "2.7.0" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73935e4d55e2abf7f130186537b19e7a4abc886a0252380b59248af473a3fc9" +checksum = "c022f1e7b65d6a24c0dbbd5fb344c66881bc01f3e5ae74a1c8100f2f985d98a4" dependencies = [ + "memchr", "thiserror", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.7.0" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aef623c9bbfa0eedf5a0efba11a5ee83209c326653ca31ff019bec3a95bfff2b" +checksum = "35513f630d46400a977c4cb58f78e1bfbe01434316e60c37d27b9ad6139c66d8" dependencies = [ "pest", "pest_generator", @@ -2630,26 +2604,26 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.0" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e8cba4ec22bada7fc55ffe51e2deb6a0e0db2d0b7ab0b103acc80d2510c190" +checksum = "bc9fc1b9e7057baba189b5c626e2d6f40681ae5b6eb064dc7c7834101ec8123a" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.37", ] [[package]] name = "pest_meta" -version = "2.7.0" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01f71cb40bd8bb94232df14b946909e14660e33fc05db3e50ae2a82d7ea0ca0" +checksum = "1df74e9e7ec4053ceb980e7c0c8bd3594e977fde1af91daba9c928e8e8c6708d" dependencies = [ "once_cell", "pest", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -2692,29 +2666,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.37", ] [[package]] name = "pin-project-lite" -version = "0.2.10" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -2734,9 +2708,9 @@ dependencies = [ [[package]] name = "platforms" -version = "3.0.2" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630" +checksum = "4503fa043bf02cee09a9582e9554b4c6403b2ef55e4612e96561d294419429f8" [[package]] name = "ppv-lite86" @@ -2787,9 +2761,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.64" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] @@ -2826,10 +2800,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "265baba7fabd416cf5078179f7d2cbeca4ce7a9041111900675ea7c4cb8a4c32" dependencies = [ "anyhow", - "itertools", + "itertools 0.11.0", "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.37", ] [[package]] @@ -2876,9 +2850,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.29" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -2957,7 +2931,7 @@ version = "1.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" dependencies = [ - "aho-corasick 1.0.2", + "aho-corasick", "memchr", "regex-automata 0.3.9", "regex-syntax 0.7.5", @@ -2978,7 +2952,7 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" dependencies = [ - "aho-corasick 1.0.2", + "aho-corasick", "memchr", "regex-syntax 0.7.5", ] @@ -3001,7 +2975,7 @@ version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ - "base64 0.21.2", + "base64 0.21.4", "bytes", "encoding_rs", "futures-core", @@ -3099,28 +3073,14 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.23" +version = "0.38.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" +checksum = "f25469e9ae0f3d0047ca8b93fc56843f38e6774f0914a107ff8b41be8be8e0b7" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.0", "errno", - "io-lifetimes", "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", -] - -[[package]] -name = "rustix" -version = "0.38.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" -dependencies = [ - "bitflags 2.3.3", - "errno", - "libc", - "linux-raw-sys 0.4.3", + "linux-raw-sys", "windows-sys 0.48.0", ] @@ -3154,7 +3114,7 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ - "base64 0.21.2", + "base64 0.21.4", ] [[package]] @@ -3169,15 +3129,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc31bd9b61a32c31f9650d18add92aa83a49ba979c143eefd27fe7177b05bd5f" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "same-file" @@ -3197,15 +3157,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "scheduled-thread-pool" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19" -dependencies = [ - "parking_lot", -] - [[package]] name = "scoped-tls" version = "1.0.1" @@ -3214,9 +3165,9 @@ checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sct" @@ -3230,9 +3181,9 @@ dependencies = [ [[package]] name = "sec1" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", @@ -3275,9 +3226,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -3288,9 +3239,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ "core-foundation-sys", "libc", @@ -3298,27 +3249,27 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.17" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.171" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.11" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a16be4fe5320ade08736447e3198294a5ea9a6d44dde6f35f0a5e06859c427a" +checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" dependencies = [ "serde", ] @@ -3335,20 +3286,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.171" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.37", ] [[package]] name = "serde_json" -version = "1.0.102" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5062a995d481b2308b6064e9af76011f2921c35f97b0468811ed9f6cd91dfed" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ "itoa", "ryu", @@ -3357,9 +3308,9 @@ dependencies = [ [[package]] name = "serde_path_to_error" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc4422959dd87a76cb117c191dcbffc20467f06c9100b76721dab370f24d3a" +checksum = "4beec8bce849d58d06238cb50db2e1c417cfeafa4c63f692b15c82b7c80f8335" dependencies = [ "itoa", "serde", @@ -3367,13 +3318,13 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d89a8107374290037607734c0b73a85db7ed80cae314b3c5791f192a496e731" +checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.37", ] [[package]] @@ -3399,9 +3350,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -3423,9 +3374,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -3444,9 +3395,9 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] @@ -3459,9 +3410,9 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "shlex" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" [[package]] name = "signal-hook" @@ -3500,9 +3451,9 @@ checksum = "cc47a29ce97772ca5c927f75bac34866b16d64e07f330c3248e2d7226623901b" [[package]] name = "siphasher" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "skeptic" @@ -3521,18 +3472,18 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] name = "smallvec" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "socket2" @@ -3544,6 +3495,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "socket2" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "spin" version = "0.5.2" @@ -3609,15 +3570,15 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.25.1" +version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6069ca09d878a33f883cc06aaa9718ede171841d3832450354410b718b097232" +checksum = "ad8d03b598d3d0fff69bf533ee3ef19b8eeb342729596df84bcc7e1f96ec4059" dependencies = [ "heck", "proc-macro2", "quote", "rustversion", - "syn 2.0.25", + "syn 2.0.37", ] [[package]] @@ -3654,9 +3615,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.25" +version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e3fc8c0c74267e2df136e5e5fb656a464158aa57624053375eb9c8c6e25ae2" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ "proc-macro2", "quote", @@ -3710,15 +3671,14 @@ checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" [[package]] name = "tempfile" -version = "3.6.0" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ - "autocfg", "cfg-if 1.0.0", "fastrand", "redox_syscall 0.3.5", - "rustix 0.37.23", + "rustix", "windows-sys 0.48.0", ] @@ -3744,7 +3704,7 @@ dependencies = [ "serde_bytes", "serde_json", "serde_repr", - "sha2 0.10.7", + "sha2 0.10.8", "signature", "subtle", "subtle-encoding", @@ -3909,20 +3869,20 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" dependencies = [ "winapi-util", ] [[package]] name = "terminal_size" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237" +checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" dependencies = [ - "rustix 0.37.23", + "rustix", "windows-sys 0.48.0", ] @@ -3934,22 +3894,22 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.43" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.43" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.37", ] [[package]] @@ -3964,10 +3924,11 @@ dependencies = [ [[package]] name = "time" -version = "0.3.23" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446" +checksum = "426f806f4089c493dcac0d24c29c01e2c38baf8e30f1b716ee37e83d200b18fe" dependencies = [ + "deranged", "serde", "time-core", "time-macros", @@ -3975,15 +3936,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.10" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4" +checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" dependencies = [ "time-core", ] @@ -4000,7 +3961,7 @@ dependencies = [ "pbkdf2", "rand", "rustc-hash", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", "unicode-normalization", "wasm-bindgen", @@ -4033,11 +3994,10 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.29.1" +version = "1.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" dependencies = [ - "autocfg", "backtrace", "bytes", "libc", @@ -4046,7 +4006,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.5.4", "tokio-macros", "windows-sys 0.48.0", ] @@ -4069,7 +4029,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.37", ] [[package]] @@ -4095,21 +4055,21 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.18.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd" +checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" dependencies = [ "futures-util", "log", "tokio", - "tungstenite 0.18.0", + "tungstenite", ] [[package]] name = "tokio-util" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" dependencies = [ "bytes", "futures-core", @@ -4130,9 +4090,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" dependencies = [ "serde", "serde_spanned", @@ -4151,11 +4111,11 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.19.12" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c500344a19072298cd05a7224b3c0c629348b78692bf48466c5238656e315a78" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.0.2", "serde", "serde_spanned", "toml_datetime", @@ -4171,7 +4131,7 @@ dependencies = [ "async-stream", "async-trait", "axum", - "base64 0.21.2", + "base64 0.21.4", "bytes", "h2", "http", @@ -4252,7 +4212,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.37", ] [[package]] @@ -4329,25 +4289,6 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" -[[package]] -name = "tungstenite" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788" -dependencies = [ - "base64 0.13.1", - "byteorder", - "bytes", - "http", - "httparse", - "log", - "rand", - "sha1", - "thiserror", - "url", - "utf-8", -] - [[package]] name = "tungstenite" version = "0.20.1" @@ -4370,9 +4311,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ucd-trie" @@ -4394,9 +4335,9 @@ dependencies = [ [[package]] name = "unicase" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" dependencies = [ "version_check", ] @@ -4409,9 +4350,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.10" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" @@ -4424,9 +4365,9 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "unicode-xid" @@ -4453,9 +4394,9 @@ dependencies = [ [[package]] name = "urlencoding" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" [[package]] name = "utf-8" @@ -4483,9 +4424,9 @@ checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" [[package]] name = "uuid" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d023da39d1fde5a8a3fe1f3e01ca9632ada0a63e9797de55a879d6e2236277be" +checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" dependencies = [ "getrandom", ] @@ -4513,9 +4454,9 @@ dependencies = [ [[package]] name = "walkdir" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" dependencies = [ "same-file", "winapi-util", @@ -4532,9 +4473,9 @@ dependencies = [ [[package]] name = "warp" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba431ef570df1287f7f8b07e376491ad54f84d26ac473489427231e1718e1f69" +checksum = "c1e92e22e03ff1230c03a1a8ee37d2f89cd489e2e541b7550d6afad96faed169" dependencies = [ "bytes", "futures-channel", @@ -4587,7 +4528,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.37", "wasm-bindgen-shared", ] @@ -4621,7 +4562,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.37", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4666,9 +4607,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -4685,7 +4626,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.48.5", ] [[package]] @@ -4703,7 +4644,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.48.5", ] [[package]] @@ -4723,17 +4664,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -4744,9 +4685,9 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" @@ -4756,9 +4697,9 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" @@ -4768,9 +4709,9 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" @@ -4780,9 +4721,9 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" @@ -4792,9 +4733,9 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" @@ -4804,9 +4745,9 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" @@ -4816,15 +4757,15 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.4.9" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81a2094c43cc94775293eaa0e499fbc30048a6d824ac82c0351a8c0bf9112529" +checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc" dependencies = [ "memchr", ] @@ -4856,5 +4797,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.37", ] diff --git a/tools/check-guide/Cargo.toml b/tools/check-guide/Cargo.toml index 59b5956262..a69316ec10 100644 --- a/tools/check-guide/Cargo.toml +++ b/tools/check-guide/Cargo.toml @@ -13,3 +13,4 @@ lazy_static = "1.4.0" mdbook-template = "1.1.0" regex = "1" walkdir = "2.3.3" + diff --git a/tools/integration-test/Cargo.toml b/tools/integration-test/Cargo.toml index f5d69d9132..e93ec8ece7 100644 --- a/tools/integration-test/Cargo.toml +++ b/tools/integration-test/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "ibc-integration-test" -version = "0.25.0" +version = "0.26.4" edition = "2021" -rust-version = "1.70" +rust-version = "1.71" license = "Apache-2.0" readme = "README.md" keywords = ["blockchain", "consensus", "cosmos", "ibc", "tendermint"] @@ -39,6 +39,9 @@ ics31 = [] clean-workers = [] fee-grant = [] interchain-security = [] +celestia = [] +async-icq = [] +juno = [] [[bin]] name = "test_setup_with_binary_channel" @@ -46,3 +49,10 @@ doc = true [dev-dependencies] tempfile = "3.6.0" + +[dependencies.tendermint] +version = "0.34.0" + +[dependencies.tendermint-rpc] +version = "0.34.0" +features = ["http-client"] diff --git a/tools/integration-test/src/bin/test_setup_with_binary_channel.rs b/tools/integration-test/src/bin/test_setup_with_binary_channel.rs index d2710d2ee9..336b0c1b23 100644 --- a/tools/integration-test/src/bin/test_setup_with_binary_channel.rs +++ b/tools/integration-test/src/bin/test_setup_with_binary_channel.rs @@ -25,6 +25,7 @@ ``` */ +use ibc_relayer::config::ChainConfig; use ibc_relayer::keyring::Store; use ibc_test_framework::prelude::*; use std::env; @@ -41,10 +42,14 @@ impl TestOverrides for Test { fn modify_relayer_config(&self, config: &mut Config) { for chain in config.chains.iter_mut() { - // Modify the key store type to `Store::Test` so that the wallet - // keys are stored to ~/.hermes/keys so that we can use them - // with external relayer commands. - chain.key_store_type = Store::Test; + match chain { + ChainConfig::CosmosSdk(chain_config) => { + // Modify the key store type to `Store::Test` so that the wallet + // keys are stored to ~/.hermes/keys so that we can use them + // with external relayer commands. + chain_config.key_store_type = Store::Test; + } + } } } diff --git a/tools/integration-test/src/bin/test_setup_with_fee_enabled_binary_channel.rs b/tools/integration-test/src/bin/test_setup_with_fee_enabled_binary_channel.rs index 77172a4c44..d7e7c5456f 100644 --- a/tools/integration-test/src/bin/test_setup_with_fee_enabled_binary_channel.rs +++ b/tools/integration-test/src/bin/test_setup_with_fee_enabled_binary_channel.rs @@ -25,6 +25,7 @@ ``` */ +use ibc_relayer::config::ChainConfig; use ibc_relayer::keyring::Store; use ibc_relayer_types::core::ics04_channel::version::Version; use ibc_test_framework::prelude::*; @@ -42,10 +43,14 @@ impl TestOverrides for Test { fn modify_relayer_config(&self, config: &mut Config) { for chain in config.chains.iter_mut() { - // Modify the key store type to `Store::Test` so that the wallet - // keys are stored to ~/.hermes/keys so that we can use them - // with external relayer commands. - chain.key_store_type = Store::Test; + match chain { + ChainConfig::CosmosSdk(chain_config) => { + // Modify the key store type to `Store::Test` so that the wallet + // keys are stored to ~/.hermes/keys so that we can use them + // with external relayer commands. + chain_config.key_store_type = Store::Test; + } + } } } diff --git a/tools/integration-test/src/bin/test_setup_with_ternary_channel.rs b/tools/integration-test/src/bin/test_setup_with_ternary_channel.rs index 79b4914592..050c81cdcd 100644 --- a/tools/integration-test/src/bin/test_setup_with_ternary_channel.rs +++ b/tools/integration-test/src/bin/test_setup_with_ternary_channel.rs @@ -25,6 +25,7 @@ ``` */ +use ibc_relayer::config::ChainConfig; use ibc_relayer::keyring::Store; use ibc_test_framework::prelude::*; use std::env; @@ -41,10 +42,14 @@ impl TestOverrides for Test { fn modify_relayer_config(&self, config: &mut Config) { for chain in config.chains.iter_mut() { - // Modify the key store type to `Store::Test` so that the wallet - // keys are stored to ~/.hermes/keys so that we can use them - // with external relayer commands. - chain.key_store_type = Store::Test; + match chain { + ChainConfig::CosmosSdk(chain_config) => { + // Modify the key store type to `Store::Test` so that the wallet + // keys are stored to ~/.hermes/keys so that we can use them + // with external relayer commands. + chain_config.key_store_type = Store::Test; + } + } } } diff --git a/tools/integration-test/src/mbt/transfer.rs b/tools/integration-test/src/mbt/transfer.rs index b2156a04da..846edc822f 100644 --- a/tools/integration-test/src/mbt/transfer.rs +++ b/tools/integration-test/src/mbt/transfer.rs @@ -2,8 +2,8 @@ use std::io::Write; use std::panic::{RefUnwindSafe, UnwindSafe}; use ibc_relayer::config::{ - Channels as ConfigChannels, Clients as ConfigClients, Connections as ConfigConnections, - ModeConfig, Packets as ConfigPackets, + ChainConfig, Channels as ConfigChannels, Clients as ConfigClients, + Connections as ConfigConnections, ModeConfig, Packets as ConfigPackets, }; use ibc_test_framework::prelude::*; @@ -158,7 +158,11 @@ impl TestOverrides for IbcTransferMBT { }; for chain_config in config.chains.iter_mut() { - chain_config.trusting_period = Some(CLIENT_EXPIRY); + match chain_config { + ChainConfig::CosmosSdk(chain_config) => { + chain_config.trusting_period = Some(CLIENT_EXPIRY); + } + } } } diff --git a/tools/integration-test/src/tests/async_icq/mod.rs b/tools/integration-test/src/tests/async_icq/mod.rs new file mode 100644 index 0000000000..5123bee973 --- /dev/null +++ b/tools/integration-test/src/tests/async_icq/mod.rs @@ -0,0 +1 @@ +pub mod simple_query; diff --git a/tools/integration-test/src/tests/async_icq/simple_query.rs b/tools/integration-test/src/tests/async_icq/simple_query.rs new file mode 100644 index 0000000000..4d2824d344 --- /dev/null +++ b/tools/integration-test/src/tests/async_icq/simple_query.rs @@ -0,0 +1,209 @@ +use ibc_relayer::channel::version::Version; +use ibc_relayer::config::ChainConfig; +use ibc_test_framework::chain::config::{set_max_deposit_period, set_voting_period}; +use ibc_test_framework::chain::ext::async_icq::AsyncIcqMethodsExt; +use ibc_test_framework::chain::ext::bootstrap::ChainBootstrapMethodsExt; +use ibc_test_framework::prelude::*; +use ibc_test_framework::relayer::channel::{ + assert_eventually_channel_established, init_channel_version, +}; +use ibc_test_framework::util::proposal_status::ProposalStatus; +use tendermint::abci::Event; +use tendermint_rpc::{Client, HttpClient}; + +#[test] +fn test_async_icq() -> Result<(), Error> { + run_binary_connection_test(&AsyncIcqTest) +} + +const MAX_DEPOSIT_PERIOD: &str = "10s"; +const VOTING_PERIOD: u64 = 10; +const MAX_RETRIES: usize = 10; + +pub struct AsyncIcqTest; + +impl TestOverrides for AsyncIcqTest { + fn modify_relayer_config(&self, config: &mut Config) { + config.mode.channels.enabled = true; + config.mode.clients.misbehaviour = false; + } + + // Allow Oracle message on host side + fn modify_genesis_file(&self, genesis: &mut serde_json::Value) -> Result<(), Error> { + use serde_json::Value; + + set_max_deposit_period(genesis, MAX_DEPOSIT_PERIOD)?; + set_voting_period(genesis, VOTING_PERIOD)?; + + let allow_messages = genesis + .get_mut("app_state") + .and_then(|app_state| app_state.get_mut("interchainquery")) + .and_then(|ica| ica.get_mut("params")) + .and_then(|params| params.get_mut("allow_queries")) + .and_then(|allow_messages| allow_messages.as_array_mut()); + + if let Some(allow_messages) = allow_messages { + allow_messages.push(Value::String( + "/provenance.oracle.v1.Query/Oracle".to_string(), + )); + Ok(()) + } else { + Err(Error::generic(eyre!("failed to update genesis file"))) + } + } + + fn channel_version(&self) -> Version { + Version::new("icq-1".to_owned()) + } +} + +impl BinaryConnectionTest for AsyncIcqTest { + fn run( + &self, + config: &TestConfig, + relayer: RelayerDriver, + chains: ConnectedChains, + connection: ConnectedConnection, + ) -> Result<(), Error> { + let fee_denom_a: MonoTagged = + MonoTagged::new(Denom::base(&config.native_tokens[0])); + let port_a = DualTagged::new(PortId::oracle()); + let port_b = DualTagged::new(PortId::icqhost()); + let (channel_id_b, channel_id_a) = init_channel_version( + &chains.handle_a, + &chains.handle_b, + &chains.client_id_a(), + &chains.client_id_b(), + &connection.connection_id_a.as_ref(), + &connection.connection_id_b.as_ref(), + &port_a.as_ref(), + &port_b.as_ref(), + Version::new("icq-1".to_owned()), + )?; + + // Check that the oracle channel is eventually established + let _counterparty_channel_id = assert_eventually_channel_established( + chains.handle_b(), + chains.handle_a(), + &channel_id_b.as_ref(), + &port_b.as_ref(), + )?; + + let driver = chains.node_a.chain_driver(); + + let wallet_a = chains.node_a.wallets().user1().cloned(); + + let relayer_a = chains.node_a.wallets().relayer().cloned(); + + driver.update_oracle( + &relayer_a.address().to_string(), + &wallet_a.address().to_string(), + )?; + + driver.value().assert_proposal_status( + driver.value().chain_id.as_str(), + &driver.value().command_path, + &driver.value().home_path, + &driver.value().rpc_listen_address(), + ProposalStatus::VotingPeriod, + "1", + )?; + + driver.vote_proposal(&fee_denom_a.with_amount(381000000u64).to_string())?; + + info!("Assert that the update oracle proposal is eventually passed"); + + driver.value().assert_proposal_status( + driver.value().chain_id.as_str(), + &driver.value().command_path, + &driver.value().home_path, + &driver.value().rpc_listen_address(), + ProposalStatus::Passed, + "1", + )?; + + let query = r#"{"query_version":{}}"#; + chains.node_a.chain_driver().async_icq( + channel_id_a.a_side.channel_id().unwrap(), + query, + &wallet_a.address().to_string(), + )?; + + assert_eventual_async_icq_success(&chains, &relayer)?; + + Ok(()) + } +} + +/// Listen to events on the controller side to assert if the async ICQ is eventually +/// successful +fn assert_eventual_async_icq_success( + chains: &ConnectedChains, + relayer: &RelayerDriver, +) -> Result<(), Error> { + let rpc_addr = match relayer.config.chains.first().unwrap() { + ChainConfig::CosmosSdk(c) => c.rpc_addr.clone(), + }; + + let mut rpc_client = HttpClient::new(rpc_addr).unwrap(); + rpc_client.set_compat_mode(tendermint_rpc::client::CompatMode::V0_34); + + for _ in 0..MAX_RETRIES { + if check_events(chains, &rpc_client).is_ok() { + return Ok(()); + } + sleep(Duration::from_secs(1)); + } + + Err(Error::generic(eyre!( + "failed to find EventOracleQueryError or EventOracleQuerySuccess after {MAX_RETRIES} tries" + ))) +} + +/// Checks if there is an Oracle event in the given events +fn check_events( + chains: &ConnectedChains, + rpc_client: &HttpClient, +) -> Result<(), Error> { + let response = chains + .node_a + .chain_driver() + .value() + .runtime + .block_on(rpc_client.latest_block_results()) + .map_err(|err| Error::generic(eyre!("Failed to fetch block results: {}", err)))?; + + if let Some(txs_results) = response.txs_results { + if let Some(events) = txs_results + .iter() + .find_map(|v| find_oracle_event(&v.events)) + { + return assert_async_icq_success(events); + } + } + + Err(Error::generic(eyre!( + "No EventOracleQueryError or EventOracleQuerySuccess" + ))) +} + +/// This method is used to find the Oracle event triggered by relaying +/// the acknowledgment of the async ICQ +fn find_oracle_event(event: &[Event]) -> Option { + event + .iter() + .find(|&e| e.kind.contains("provenance.oracle.v1.EventOracleQuery")) + .cloned() +} + +/// This method is used to assert if the found Oracle event is successful or not +fn assert_async_icq_success(event: Event) -> Result<(), Error> { + if event.kind == "provenance.oracle.v1.EventOracleQuerySuccess" { + debug!("async query successful with event: {event:#?}"); + Ok(()) + } else { + Err(Error::generic(eyre!( + "async query failed with response event: {event:#?}" + ))) + } +} diff --git a/tools/integration-test/src/tests/clear_packet.rs b/tools/integration-test/src/tests/clear_packet.rs index 9eef3f6c26..5bff304825 100644 --- a/tools/integration-test/src/tests/clear_packet.rs +++ b/tools/integration-test/src/tests/clear_packet.rs @@ -1,5 +1,6 @@ use std::thread; +use ibc_relayer::config::ChainConfig; use ibc_test_framework::prelude::*; use ibc_test_framework::util::random::random_u128_range; @@ -18,6 +19,11 @@ fn test_clear_packet_no_scan() -> Result<(), Error> { run_binary_channel_test(&ClearPacketNoScanTest) } +#[test] +fn test_clear_packet_override() -> Result<(), Error> { + run_binary_channel_test(&ClearPacketOverrideTest) +} + pub struct ClearPacketTest; pub struct ClearPacketRecoveryTest; @@ -90,7 +96,7 @@ impl BinaryChannelTest for ClearPacketTest { sleep(Duration::from_secs(1)); - // Spawn the supervisor only after the first IBC trasnfer + // Spawn the supervisor only after the first IBC transfer relayer.with_supervisor(|| { sleep(Duration::from_secs(1)); @@ -204,12 +210,134 @@ impl TestOverrides for ClearPacketNoScanTest { impl BinaryChannelTest for ClearPacketNoScanTest { fn run( &self, - _config: &TestConfig, + config: &TestConfig, + relayer: RelayerDriver, + chains: ConnectedChains, + channel: ConnectedChannel, + ) -> Result<(), Error> { + let denom_a = chains.node_a.denom(); + let fee_denom_a = MonoTagged::new(Denom::base(&config.native_tokens[0])); + + let wallet_a = chains.node_a.wallets().user1().cloned(); + let wallet_b = chains.node_b.wallets().user1().cloned(); + + let amount1 = random_u128_range(1000, 5000); + + let balance_a = chains + .node_a + .chain_driver() + .query_balance(&wallet_a.address(), &denom_a)?; + + chains.node_a.chain_driver().ibc_transfer_token( + &channel.port_a.as_ref(), + &channel.channel_id_a.as_ref(), + &wallet_a.as_ref(), + &wallet_b.address(), + &denom_a.with_amount(amount1).as_ref(), + )?; + + let denom_b2 = derive_ibc_denom( + &channel.port_b.as_ref(), + &channel.channel_id_b.as_ref(), + &denom_a, + )?; + + thread::sleep(Duration::from_secs(5)); + + relayer.with_supervisor(|| { + info!("Assert clear on start does not trigger"); + chains.node_a.chain_driver().assert_eventual_wallet_amount( + &wallet_a.address(), + &(balance_a.clone() - amount1).as_ref(), + )?; + + // Clear on start is disabled, packets will not be cleared + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &wallet_b.address(), + &denom_b2.with_amount(0u128).as_ref(), + )?; + + // Wait for clear interval to trigger + thread::sleep(Duration::from_secs(20)); + + info!("Assert clear interval does not trigger"); + + // Channel is not discovered, packets won't be cleared + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &wallet_b.address(), + &denom_b2.with_amount(0u128).as_ref(), + )?; + + info!("Trigger a transfer"); + + let dst_height = chains.handle_b().query_latest_height()?; + + // Trigger a transfer from chain + chains.node_a.chain_driver().transfer_from_chain( + &chains.node_a.wallets().user1(), + &chains.node_b.wallets().user1().address(), + &channel.port_a.0, + &channel.channel_id_a.0, + &denom_a.with_amount(amount1).as_ref(), + &fee_denom_a.with_amount(381000000u64).as_ref(), + &dst_height, + )?; + + info!("Assert clear interval correctly triggers"); + + chains.node_a.chain_driver().assert_eventual_wallet_amount( + &wallet_a.address(), + &(balance_a - amount1 - amount1).as_ref(), + )?; + + // Wait for clear interval to clear packets + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &wallet_b.address(), + &denom_b2.with_amount(amount1 + amount1).as_ref(), + )?; + + Ok(()) + }) + } +} +pub struct ClearPacketOverrideTest; + +impl TestOverrides for ClearPacketOverrideTest { + fn modify_relayer_config(&self, config: &mut Config) { + // Disabling client workers and clear_on_start should make the relayer not + // relay any packet it missed before starting. + config.mode.clients.enabled = false; + config.mode.connections.enabled = false; + config.mode.channels.enabled = false; + + config.mode.packets.enabled = true; + config.mode.packets.clear_on_start = false; + // Set a very high global clear interval + config.mode.packets.clear_interval = 10000; + + for chain_config in config.chains.iter_mut() { + match chain_config { + // Use a small clear interval in the chain configurations to override the global high interval + ChainConfig::CosmosSdk(chain_config) => chain_config.clear_interval = Some(10), + } + } + } + + fn should_spawn_supervisor(&self) -> bool { + false + } +} + +impl BinaryChannelTest for ClearPacketOverrideTest { + fn run( + &self, + config: &TestConfig, relayer: RelayerDriver, chains: ConnectedChains, channel: ConnectedChannel, ) -> Result<(), Error> { let denom_a = chains.node_a.denom(); + let fee_denom_a = MonoTagged::new(Denom::base(&config.native_tokens[0])); let wallet_a = chains.node_a.wallets().user1().cloned(); let wallet_b = chains.node_b.wallets().user1().cloned(); @@ -272,6 +400,7 @@ impl BinaryChannelTest for ClearPacketNoScanTest { &channel.port_a.0, &channel.channel_id_a.0, &denom_a.with_amount(amount1).as_ref(), + &fee_denom_a.with_amount(381000000u64).as_ref(), &dst_height, )?; diff --git a/tools/integration-test/src/tests/client_expiration.rs b/tools/integration-test/src/tests/client_expiration.rs index acac61f055..007ac0b459 100644 --- a/tools/integration-test/src/tests/client_expiration.rs +++ b/tools/integration-test/src/tests/client_expiration.rs @@ -1,7 +1,7 @@ use core::time::Duration; use std::thread::sleep; -use ibc_relayer::config::{self, Config, ModeConfig}; +use ibc_relayer::config::{self, ChainConfig, Config, ModeConfig}; use ibc_relayer_types::core::ics03_connection::connection::State as ConnectionState; use ibc_relayer_types::core::ics04_channel::channel::State as ChannelState; @@ -116,7 +116,11 @@ impl TestOverrides for ExpirationTestOverrides { }; for chain_config in config.chains.iter_mut() { - chain_config.trusting_period = Some(CLIENT_EXPIRY); + match chain_config { + ChainConfig::CosmosSdk(chain_config) => { + chain_config.trusting_period = Some(CLIENT_EXPIRY); + } + } } } diff --git a/tools/integration-test/src/tests/client_refresh.rs b/tools/integration-test/src/tests/client_refresh.rs index c5e79c2e71..24df985574 100644 --- a/tools/integration-test/src/tests/client_refresh.rs +++ b/tools/integration-test/src/tests/client_refresh.rs @@ -1,5 +1,6 @@ use std::time::Duration; +use ibc_relayer::config::ChainConfig; use ibc_relayer_types::core::ics02_client::trust_threshold::TrustThreshold; use ibc_relayer::config::gas_multiplier::GasMultiplier; @@ -127,8 +128,13 @@ impl BinaryChainTest for ClientFailsTest { let chains2 = override_connected_chains( chains, |config| { - config.chains[0].gas_multiplier = Some(GasMultiplier::unsafe_new(0.8)); - config.chains[1].gas_multiplier = Some(GasMultiplier::unsafe_new(0.8)); + { + let ChainConfig::CosmosSdk(config_chain_a) = &mut config.chains[0]; + config_chain_a.gas_multiplier = Some(GasMultiplier::unsafe_new(0.8)); + } + + let ChainConfig::CosmosSdk(config_chain_b) = &mut config.chains[1]; + config_chain_b.gas_multiplier = Some(GasMultiplier::unsafe_new(0.8)); }, config, )?; @@ -168,8 +174,8 @@ where { let mut config = Config::default(); - add_chain_config(&mut config, chains.node_a.value(), test_config)?; - add_chain_config(&mut config, chains.node_b.value(), test_config)?; + add_chain_config(&mut config, chains.node_a.value(), test_config, 0)?; + add_chain_config(&mut config, chains.node_b.value(), test_config, 1)?; config_modifier(&mut config); diff --git a/tools/integration-test/src/tests/client_settings.rs b/tools/integration-test/src/tests/client_settings.rs index 7df6858101..bfd18ae66d 100644 --- a/tools/integration-test/src/tests/client_settings.rs +++ b/tools/integration-test/src/tests/client_settings.rs @@ -1,5 +1,6 @@ use std::time::Duration; +use ibc_relayer::config::ChainConfig; use ibc_relayer_types::core::ics02_client::trust_threshold::TrustThreshold; use ibc_relayer::chain::requests::{IncludeProof, QueryClientStateRequest, QueryHeight}; @@ -27,15 +28,23 @@ struct ClientOptionsTest; impl TestOverrides for ClientDefaultsTest { fn modify_relayer_config(&self, config: &mut Config) { - config.chains[0].clock_drift = Duration::from_secs(3); - config.chains[0].max_block_time = Duration::from_secs(5); - config.chains[0].trusting_period = Some(Duration::from_secs(120_000)); - config.chains[0].trust_threshold = TrustThreshold::new(13, 23).unwrap().try_into().unwrap(); - - config.chains[1].clock_drift = Duration::from_secs(6); - config.chains[1].max_block_time = Duration::from_secs(15); - config.chains[1].trusting_period = Some(Duration::from_secs(340_000)); - config.chains[1].trust_threshold = TrustThreshold::TWO_THIRDS.try_into().unwrap(); + match &mut config.chains[0] { + ChainConfig::CosmosSdk(chain_config_a) => { + chain_config_a.clock_drift = Duration::from_secs(3); + chain_config_a.max_block_time = Duration::from_secs(5); + chain_config_a.trusting_period = Some(Duration::from_secs(120_000)); + chain_config_a.trust_threshold = TrustThreshold::new(13, 23).unwrap().into(); + } + } + + match &mut config.chains[1] { + ChainConfig::CosmosSdk(chain_config_b) => { + chain_config_b.clock_drift = Duration::from_secs(6); + chain_config_b.max_block_time = Duration::from_secs(15); + chain_config_b.trusting_period = Some(Duration::from_secs(340_000)); + chain_config_b.trust_threshold = TrustThreshold::TWO_THIRDS.into(); + } + } } } diff --git a/tools/integration-test/src/tests/client_upgrade.rs b/tools/integration-test/src/tests/client_upgrade.rs index 588e9992d5..01731e6d8b 100644 --- a/tools/integration-test/src/tests/client_upgrade.rs +++ b/tools/integration-test/src/tests/client_upgrade.rs @@ -15,21 +15,24 @@ use http::Uri; use std::str::FromStr; +use ibc_relayer::chain::requests::IncludeProof; +use ibc_relayer::chain::requests::QueryClientStateRequest; +use ibc_relayer::chain::requests::QueryHeight; +use ibc_relayer::client_state::AnyClientState; use ibc_relayer::upgrade_chain::{build_and_send_ibc_upgrade_proposal, UpgradePlanOptions}; use ibc_relayer_types::core::ics02_client::height::Height; -use ibc_test_framework::{ - chain::{ - config::{set_max_deposit_period, set_voting_period}, - ext::wait_chain::wait_for_chain_height, - }, - prelude::*, +use ibc_test_framework::chain::config::{ + set_max_deposit_period, set_min_deposit_amount, set_voting_period, }; +use ibc_test_framework::chain::ext::bootstrap::ChainBootstrapMethodsExt; +use ibc_test_framework::prelude::*; +use ibc_test_framework::util::proposal_status::ProposalStatus; const MAX_DEPOSIT_PERIOD: &str = "10s"; -const VOTING_PERIOD: &str = "10s"; +const VOTING_PERIOD: u64 = 10; const DELTA_HEIGHT: u64 = 15; const WAIT_CHAIN_UPGRADE: Duration = Duration::from_secs(4); -const MAX_WAIT_FOR_CHAIN_HEIGHT: Duration = Duration::from_secs(60); +const MIN_DEPOSIT: u64 = 10000000u64; #[test] fn test_client_upgrade() -> Result<(), Error> { @@ -60,6 +63,9 @@ impl TestOverrides for ClientUpgradeTestOverrides { fn modify_genesis_file(&self, genesis: &mut serde_json::Value) -> Result<(), Error> { set_max_deposit_period(genesis, MAX_DEPOSIT_PERIOD)?; set_voting_period(genesis, VOTING_PERIOD)?; + // Set the min deposit amount the same as the deposit of the Upgrade proposal to + // assure that the proposal will go to voting period + set_min_deposit_amount(genesis, MIN_DEPOSIT)?; Ok(()) } } @@ -70,26 +76,17 @@ impl BinaryChainTest for ClientUpgradeTest { ChainB: ibc_test_framework::prelude::ChainHandle, >( &self, - _config: &ibc_test_framework::prelude::TestConfig, + config: &ibc_test_framework::prelude::TestConfig, _relayer: ibc_test_framework::prelude::RelayerDriver, chains: ibc_test_framework::prelude::ConnectedChains, ) -> Result<(), ibc_test_framework::prelude::Error> { + let upgraded_chain_id = ChainId::new("upgradedibc".to_owned(), 1); + let fee_denom_a: MonoTagged = + MonoTagged::new(Denom::base(&config.native_tokens[0])); let foreign_clients = chains.clone().foreign_clients; - let upgraded_chain_id = chains.chain_id_a().0.clone(); - - let src_client_id = foreign_clients.client_id_b().0.clone(); - // Create and send an chain upgrade proposal - let opts = UpgradePlanOptions { - src_client_id, - amount: 10000000u64, - denom: "stake".to_string(), - height_offset: DELTA_HEIGHT, - upgraded_chain_id, - upgraded_unbonding_period: None, - upgrade_plan_name: "plan".to_string(), - }; + let opts = create_upgrade_plan(config, &chains, &upgraded_chain_id)?; build_and_send_ibc_upgrade_proposal( chains.handle_a().clone(), @@ -98,14 +95,22 @@ impl BinaryChainTest for ClientUpgradeTest { ) .map_err(Error::upgrade_chain)?; - // Wait for the proposal to be processed - std::thread::sleep(Duration::from_secs(2)); + info!("Assert that the chain upgrade proposal is eventually in voting period"); let driver = chains.node_a.chain_driver(); + driver.value().assert_proposal_status( + driver.value().chain_id.as_str(), + &driver.value().command_path, + &driver.value().home_path, + &driver.value().rpc_listen_address(), + ProposalStatus::VotingPeriod, + "1", + )?; + // Retrieve the height which should be used to upgrade the client let upgrade_height = driver.query_upgrade_proposal_height( - &Uri::from_str(&driver.0.grpc_address()).map_err(handle_generic_error)?, + &Uri::from_str(&driver.value().grpc_address()).map_err(handle_generic_error)?, 1, )?; @@ -116,29 +121,43 @@ impl BinaryChainTest for ClientUpgradeTest { .map_err(handle_generic_error)?; // Vote on the proposal so the chain will upgrade - driver.vote_proposal("1200stake")?; + driver.vote_proposal(&fee_denom_a.with_amount(381000000u64).to_string())?; - // The application height reports a height of 1 less than the height according to Tendermint - let target_reference_application_height = client_upgrade_height - .decrement() - .expect("Upgrade height cannot be 1"); + info!("Assert that the chain upgrade proposal is eventually passed"); - assert!(wait_for_chain_height( - &foreign_clients, - target_reference_application_height, - MAX_WAIT_FOR_CHAIN_HEIGHT - ) - .is_ok()); + driver.value().assert_proposal_status( + driver.value().chain_id.as_str(), + &driver.value().command_path, + &driver.value().home_path, + &driver.value().rpc_listen_address(), + ProposalStatus::Passed, + "1", + )?; // Wait for the chain to upgrade std::thread::sleep(WAIT_CHAIN_UPGRADE); // Trigger the client upgrade - let outcome = foreign_clients.client_a_to_b.upgrade(client_upgrade_height); + // The error is ignored as the client state will be asserted afterwards. + let _ = foreign_clients.client_a_to_b.upgrade(client_upgrade_height); + + // Wait to seconds before querying the client state + std::thread::sleep(Duration::from_secs(2)); - assert!(outcome.is_ok(), "{outcome:?}"); + let (state, _) = chains.handle_b().query_client_state( + QueryClientStateRequest { + client_id: foreign_clients.client_a_to_b.id().clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + )?; - Ok(()) + match state { + AnyClientState::Tendermint(client_state) => { + assert_eq!(client_state.chain_id, upgraded_chain_id); + Ok(()) + } + } } } @@ -159,7 +178,7 @@ impl BinaryChainTest for InvalidClientUpgradeTest { chains: ibc_test_framework::prelude::ConnectedChains, ) -> Result<(), ibc_test_framework::prelude::Error> { let arbitrary_height = 5u64; - let foreign_clients = chains.foreign_clients; + let foreign_clients = &chains.foreign_clients; // Wait for the chain to reach a given height let client_upgrade_height = Height::new( @@ -172,11 +191,26 @@ impl BinaryChainTest for InvalidClientUpgradeTest { std::thread::sleep(Duration::from_secs(2)); // Trigger the client upgrade - let outcome = foreign_clients.client_a_to_b.upgrade(client_upgrade_height); + // The error is ignored as the client state will be asserted afterwards. + let _ = foreign_clients.client_a_to_b.upgrade(client_upgrade_height); - assert!(outcome.is_err(), "{outcome:?}"); + // Wait to seconds before querying the client state + std::thread::sleep(Duration::from_secs(2)); - Ok(()) + let (state, _) = chains.handle_b().query_client_state( + QueryClientStateRequest { + client_id: foreign_clients.client_a_to_b.id().clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + )?; + + match state { + AnyClientState::Tendermint(client_state) => { + assert_eq!(client_state.chain_id, chains.handle_a().id()); + Ok(()) + } + } } } @@ -188,26 +222,17 @@ impl BinaryChainTest for HeightTooHighClientUpgradeTest { ChainB: ibc_test_framework::prelude::ChainHandle, >( &self, - _config: &ibc_test_framework::prelude::TestConfig, + config: &ibc_test_framework::prelude::TestConfig, _relayer: ibc_test_framework::prelude::RelayerDriver, chains: ibc_test_framework::prelude::ConnectedChains, ) -> Result<(), ibc_test_framework::prelude::Error> { + let upgraded_chain_id = ChainId::new("upgradedibc".to_owned(), 1); + let fee_denom_a: MonoTagged = + MonoTagged::new(Denom::base(&config.native_tokens[0])); let foreign_clients = chains.clone().foreign_clients; - let upgraded_chain_id = chains.chain_id_a().0.clone(); - - let src_client_id = foreign_clients.client_id_b().0.clone(); - // Create and send an chain upgrade proposal - let opts = UpgradePlanOptions { - src_client_id, - amount: 10000000u64, - denom: "stake".to_string(), - height_offset: DELTA_HEIGHT, - upgraded_chain_id, - upgraded_unbonding_period: None, - upgrade_plan_name: "plan".to_string(), - }; + let opts = create_upgrade_plan(config, &chains, &upgraded_chain_id)?; build_and_send_ibc_upgrade_proposal( chains.handle_a().clone(), @@ -216,11 +241,19 @@ impl BinaryChainTest for HeightTooHighClientUpgradeTest { ) .map_err(Error::upgrade_chain)?; - // Wait for the proposal to be processed - std::thread::sleep(Duration::from_secs(2)); + info!("Assert that the chain upgrade proposal is eventually in voting period"); let driver = chains.node_a.chain_driver(); + driver.value().assert_proposal_status( + driver.value().chain_id.as_str(), + &driver.value().command_path, + &driver.value().home_path, + &driver.value().rpc_listen_address(), + ProposalStatus::VotingPeriod, + "1", + )?; + // Retrieve the height which should be used to upgrade the client let upgrade_height = driver.query_upgrade_proposal_height( &Uri::from_str(&driver.0.grpc_address()).map_err(handle_generic_error)?, @@ -234,31 +267,48 @@ impl BinaryChainTest for HeightTooHighClientUpgradeTest { .map_err(handle_generic_error)?; // Vote on the proposal so the chain will upgrade - driver.vote_proposal("1200stake")?; + driver.vote_proposal(&fee_denom_a.with_amount(381000000u64).to_string())?; // The application height reports a height of 1 less than the height according to Tendermint - let target_reference_application_height = client_upgrade_height - .decrement() - .expect("Upgrade height cannot be 1"); + client_upgrade_height.increment(); - assert!(wait_for_chain_height( - &foreign_clients, - target_reference_application_height, - MAX_WAIT_FOR_CHAIN_HEIGHT - ) - .is_ok()); + info!("Assert that the chain upgrade proposal is eventually passed"); + + driver.value().assert_proposal_status( + driver.value().chain_id.as_str(), + &driver.value().command_path, + &driver.value().home_path, + &driver.value().rpc_listen_address(), + ProposalStatus::Passed, + "1", + )?; // Wait for the chain to upgrade std::thread::sleep(WAIT_CHAIN_UPGRADE); // Trigger the client upgrade using client_upgrade_height + 1. - let outcome = foreign_clients + // The error is ignored as the client state will be asserted afterwards. + let _ = foreign_clients .client_a_to_b .upgrade(client_upgrade_height.increment()); - assert!(outcome.is_err(), "{outcome:?}"); + // Wait to seconds before querying the client state + std::thread::sleep(Duration::from_secs(2)); - Ok(()) + let (state, _) = chains.handle_b().query_client_state( + QueryClientStateRequest { + client_id: foreign_clients.client_a_to_b.id().clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + )?; + + match state { + AnyClientState::Tendermint(client_state) => { + assert_eq!(client_state.chain_id, chains.handle_a().id()); + Ok(()) + } + } } } @@ -270,26 +320,16 @@ impl BinaryChainTest for HeightTooLowClientUpgradeTest { ChainB: ibc_test_framework::prelude::ChainHandle, >( &self, - _config: &ibc_test_framework::prelude::TestConfig, + config: &ibc_test_framework::prelude::TestConfig, _relayer: ibc_test_framework::prelude::RelayerDriver, chains: ibc_test_framework::prelude::ConnectedChains, ) -> Result<(), ibc_test_framework::prelude::Error> { + let upgraded_chain_id = ChainId::new("upgradedibc".to_owned(), 1); + let fee_denom_a: MonoTagged = + MonoTagged::new(Denom::base(&config.native_tokens[0])); let foreign_clients = chains.clone().foreign_clients; - let upgraded_chain_id = chains.chain_id_a().0.clone(); - - let src_client_id = foreign_clients.client_id_b().0.clone(); - - // Create and send an chain upgrade proposal - let opts = UpgradePlanOptions { - src_client_id, - amount: 10000000u64, - denom: "stake".to_string(), - height_offset: DELTA_HEIGHT, - upgraded_chain_id, - upgraded_unbonding_period: None, - upgrade_plan_name: "plan".to_string(), - }; + let opts = create_upgrade_plan(config, &chains, &upgraded_chain_id)?; build_and_send_ibc_upgrade_proposal( chains.handle_a().clone(), @@ -298,14 +338,22 @@ impl BinaryChainTest for HeightTooLowClientUpgradeTest { ) .map_err(Error::upgrade_chain)?; - // Wait for the proposal to be processed - std::thread::sleep(Duration::from_secs(2)); + info!("Assert that the chain upgrade proposal is eventually in voting period"); let driver = chains.node_a.chain_driver(); + driver.value().assert_proposal_status( + driver.value().chain_id.as_str(), + &driver.value().command_path, + &driver.value().home_path, + &driver.value().rpc_listen_address(), + ProposalStatus::VotingPeriod, + "1", + )?; + // Retrieve the height which should be used to upgrade the client let upgrade_height = driver.query_upgrade_proposal_height( - &Uri::from_str(&driver.0.grpc_address()).map_err(handle_generic_error)?, + &Uri::from_str(&driver.value().grpc_address()).map_err(handle_generic_error)?, 1, )?; @@ -316,36 +364,80 @@ impl BinaryChainTest for HeightTooLowClientUpgradeTest { .map_err(handle_generic_error)?; // Vote on the proposal so the chain will upgrade - driver.vote_proposal("1200stake")?; + driver.vote_proposal(&fee_denom_a.with_amount(381000000u64).to_string())?; // The application height reports a height of 1 less than the height according to Tendermint - let target_reference_application_height = client_upgrade_height + client_upgrade_height .decrement() .expect("Upgrade height cannot be 1"); - assert!(wait_for_chain_height( - &foreign_clients, - target_reference_application_height, - MAX_WAIT_FOR_CHAIN_HEIGHT - ) - .is_ok()); + info!("Assert that the chain upgrade proposal is eventually passed"); + + driver.value().assert_proposal_status( + driver.value().chain_id.as_str(), + &driver.value().command_path, + &driver.value().home_path, + &driver.value().rpc_listen_address(), + ProposalStatus::Passed, + "1", + )?; // Wait for the chain to upgrade std::thread::sleep(WAIT_CHAIN_UPGRADE); // Trigger the client upgrade using client_upgrade_height - 1. - let outcome = foreign_clients.client_a_to_b.upgrade( + // The error is ignored as the client state will be asserted afterwards. + let _ = foreign_clients.client_a_to_b.upgrade( client_upgrade_height .decrement() .map_err(handle_generic_error)?, ); - assert!(outcome.is_err(), "{outcome:?}"); + // Wait to seconds before querying the client state + std::thread::sleep(Duration::from_secs(2)); - Ok(()) + let (state, _) = chains.handle_b().query_client_state( + QueryClientStateRequest { + client_id: foreign_clients.client_a_to_b.id().clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + )?; + + match state { + AnyClientState::Tendermint(client_state) => { + assert_eq!(client_state.chain_id, chains.handle_a().id()); + Ok(()) + } + } } } +fn create_upgrade_plan( + config: &ibc_test_framework::prelude::TestConfig, + chains: &ibc_test_framework::prelude::ConnectedChains, + upgraded_chain_id: &ChainId, +) -> Result { + let fee_denom_a: MonoTagged = + MonoTagged::new(Denom::base(&config.native_tokens[0])); + let foreign_clients = chains.clone().foreign_clients; + + let src_client_id = foreign_clients.client_id_b().0.clone(); + + let gov_account = chains.node_a.chain_driver().query_auth_module("gov")?; + // Create and send an chain upgrade proposal + Ok(UpgradePlanOptions { + src_client_id, + amount: MIN_DEPOSIT, + denom: fee_denom_a.to_string(), + height_offset: DELTA_HEIGHT, + upgraded_chain_id: upgraded_chain_id.clone(), + upgraded_unbonding_period: None, + upgrade_plan_name: "plan".to_string(), + gov_account, + }) +} + impl HasOverrides for ClientUpgradeTest { type Overrides = ClientUpgradeTestOverrides; diff --git a/tools/integration-test/src/tests/connection_delay.rs b/tools/integration-test/src/tests/connection_delay.rs index db73cfe7ee..d39da949da 100644 --- a/tools/integration-test/src/tests/connection_delay.rs +++ b/tools/integration-test/src/tests/connection_delay.rs @@ -90,7 +90,7 @@ impl BinaryChannelTest for ConnectionDelayTest { assert_gt( &format!( - "Expect IBC transfer to only be successfull after {}s", + "Expect IBC transfer to only be successful after {}s", CONNECTION_DELAY.as_secs() ), &(time2 - time1).try_into().unwrap(), diff --git a/tools/integration-test/src/tests/denom_trace.rs b/tools/integration-test/src/tests/denom_trace.rs index 5c53a22f1a..695efe2876 100644 --- a/tools/integration-test/src/tests/denom_trace.rs +++ b/tools/integration-test/src/tests/denom_trace.rs @@ -11,7 +11,7 @@ pub struct IbcDenomTraceTest; impl TestOverrides for IbcDenomTraceTest {} /// In order to test the denom_trace at first transfer IBC tokens from Chain A -/// to Chain B, and then retrieving the trace hash of the transfered tokens. +/// to Chain B, and then retrieving the trace hash of the transferred tokens. /// The trace hash is used to query the denom_trace and the result is verified. impl BinaryChannelTest for IbcDenomTraceTest { fn run( diff --git a/tools/integration-test/src/tests/fee/filter_fees.rs b/tools/integration-test/src/tests/fee/filter_fees.rs index 64a4c00504..a6cd76b37d 100644 --- a/tools/integration-test/src/tests/fee/filter_fees.rs +++ b/tools/integration-test/src/tests/fee/filter_fees.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use ibc_relayer::config::filter::{ChannelPolicy, FeePolicy, FilterPattern, MinFee}; -use ibc_relayer::config::PacketFilter; +use ibc_relayer::config::{ChainConfig, PacketFilter}; use ibc_relayer_types::core::ics04_channel::version::Version; use ibc_test_framework::prelude::*; use ibc_test_framework::util::random::random_u128_range; @@ -27,7 +27,11 @@ impl TestOverrides for FilterIncentivizedFeesRelayerTest { HashMap::from([(FilterPattern::Wildcard("*".parse().unwrap()), fees_filters)]); let packet_filter = PacketFilter::new(ChannelPolicy::default(), min_fees); for chain_config in config.chains.iter_mut() { - chain_config.packet_filter = packet_filter.clone(); + match chain_config { + ChainConfig::CosmosSdk(chain_config) => { + chain_config.packet_filter = packet_filter.clone(); + } + } } } @@ -175,7 +179,11 @@ impl TestOverrides for FilterByChannelIncentivizedFeesRelayerTest { )]); let packet_filter = PacketFilter::new(ChannelPolicy::default(), min_fees); for chain_config in config.chains.iter_mut() { - chain_config.packet_filter = packet_filter.clone(); + match chain_config { + ChainConfig::CosmosSdk(chain_config) => { + chain_config.packet_filter = packet_filter.clone(); + } + } } } diff --git a/tools/integration-test/src/tests/fee_grant.rs b/tools/integration-test/src/tests/fee_grant.rs index 39a3984a73..f12e30a981 100644 --- a/tools/integration-test/src/tests/fee_grant.rs +++ b/tools/integration-test/src/tests/fee_grant.rs @@ -34,7 +34,7 @@ impl TestOverrides for FeeGrantTest {} impl BinaryChannelTest for FeeGrantTest { fn run( &self, - _config: &TestConfig, + config: &TestConfig, relayer: RelayerDriver, chains: ConnectedChains, channels: ConnectedChannel, @@ -42,6 +42,7 @@ impl BinaryChannelTest for FeeGrantTest { let denom_a = chains.node_a.denom(); let wallet_a = chains.node_a.wallets().user1().cloned(); let wallet_b = chains.node_b.wallets().user1().cloned(); + let fee_denom_a = MonoTagged::new(Denom::base(&config.native_tokens[0])); let a_to_b_amount = 12345u64; let granter = chains @@ -59,10 +60,11 @@ impl BinaryChannelTest for FeeGrantTest { .value() .to_string(); - chains - .node_a - .chain_driver() - .feegrant_grant(&granter, &grantee)?; + chains.node_a.chain_driver().feegrant_grant( + &granter, + &grantee, + &fee_denom_a.with_amount(381000000u64).as_ref(), + )?; // Wait for the feegrant to be processed thread::sleep(Duration::from_secs(5)); @@ -73,7 +75,16 @@ impl BinaryChannelTest for FeeGrantTest { &denom_a, )?; - let gas_denom: MonoTagged = MonoTagged::new(Denom::Base("stake".to_owned())); + let gas_denom_str = match relayer + .config + .chains + .first() + .ok_or_else(|| eyre!("chain configuration is empty"))? + { + ChainConfig::CosmosSdk(chain_config) => chain_config.gas_price.denom.clone(), + }; + + let gas_denom: MonoTagged = MonoTagged::new(Denom::Base(gas_denom_str)); let balance_user1_before = chains .node_a @@ -86,19 +97,19 @@ impl BinaryChannelTest for FeeGrantTest { let mut modified_relayer = relayer; - let new_chain_configs: Vec = modified_relayer + modified_relayer .config .chains .iter_mut() - .map(|c| { - if c.id == chains.node_a.chain_id().0.clone() { - c.fee_granter = Some("user2".to_owned()); + .for_each(|chain_config| { + if chain_config.id() == chains.node_a.chain_id().0 { + match chain_config { + ChainConfig::CosmosSdk(c) => { + c.fee_granter = Some("user2".to_owned()); + } + } } - c.clone() - }) - .collect(); - - modified_relayer.config.chains = new_chain_configs; + }); let mut modified_driver = chains.node_a.chain_driver().0.clone(); @@ -165,8 +176,8 @@ impl TestOverrides for NoFeeGrantTest {} impl BinaryChannelTest for NoFeeGrantTest { fn run( &self, - _config: &TestConfig, - _relayer: RelayerDriver, + config: &TestConfig, + relayer: RelayerDriver, chains: ConnectedChains, channels: ConnectedChannel, ) -> Result<(), Error> { @@ -174,6 +185,7 @@ impl BinaryChannelTest for NoFeeGrantTest { let wallet_a = chains.node_a.wallets().user1().cloned(); let wallet_a2 = chains.node_a.wallets().user2().cloned(); let wallet_b = chains.node_b.wallets().user1().cloned(); + let fee_denom_a = MonoTagged::new(Denom::base(&config.native_tokens[0])); let a_to_b_amount = 12345u64; let granter = chains @@ -191,10 +203,11 @@ impl BinaryChannelTest for NoFeeGrantTest { .value() .to_string(); - chains - .node_a - .chain_driver() - .feegrant_grant(&granter, &grantee)?; + chains.node_a.chain_driver().feegrant_grant( + &granter, + &grantee, + &fee_denom_a.with_amount(381000000u64).as_ref(), + )?; // Wait for the feegrant to be processed thread::sleep(Duration::from_secs(5)); @@ -205,7 +218,16 @@ impl BinaryChannelTest for NoFeeGrantTest { &denom_a, )?; - let gas_denom: MonoTagged = MonoTagged::new(Denom::Base("stake".to_owned())); + let gas_denom_str = match relayer + .config + .chains + .first() + .ok_or_else(|| eyre!("chain configuration is empty"))? + { + ChainConfig::CosmosSdk(chain_config) => chain_config.gas_price.denom.clone(), + }; + + let gas_denom: MonoTagged = MonoTagged::new(Denom::Base(gas_denom_str)); let balance_user1_before = chains .node_a diff --git a/tools/integration-test/src/tests/forward/forward_transfer.rs b/tools/integration-test/src/tests/forward/forward_transfer.rs index 3447a02171..4830ee43b6 100644 --- a/tools/integration-test/src/tests/forward/forward_transfer.rs +++ b/tools/integration-test/src/tests/forward/forward_transfer.rs @@ -5,7 +5,7 @@ //! //! - The `MisspelledMemoFieldsIbcForwardTransferTest` tests the case where the //! fields inside the memo are misspelled: -//! - Misspelled `forward`: The intemediary chain will not understand the transfer +//! - Misspelled `forward`: The intermediary chain will not understand the transfer //! must be forwarded, and will thus keep the tokens. //! - Misspelled `receiver`: The intermediary chain will not find the receiver field //! and will thus refund the sender. @@ -383,7 +383,7 @@ impl NaryChannelTest<3> for MisspelledMemoFieldsIbcForwardTransferTest { )?; info!( - "check that only the sender lost {} tokens and the intemediary chain received {} tokens", + "check that only the sender lost {} tokens and the intermediary chain received {} tokens", a_to_c_amount, a_to_c_amount ); diff --git a/tools/integration-test/src/tests/ica.rs b/tools/integration-test/src/tests/ica.rs index dfcda16cea..8a7169ab0c 100644 --- a/tools/integration-test/src/tests/ica.rs +++ b/tools/integration-test/src/tests/ica.rs @@ -5,7 +5,7 @@ use ibc_relayer::chain::handle::ChainHandle; use ibc_relayer::chain::tracking::TrackedMsgs; use ibc_relayer::config::{ filter::{ChannelFilters, ChannelPolicy, FilterPattern}, - PacketFilter, + ChainConfig, PacketFilter, }; use ibc_relayer::event::IbcEventWithHeight; use ibc_relayer_types::applications::ics27_ica::msgs::send_tx::MsgSendTx; @@ -59,7 +59,11 @@ impl TestOverrides for IcaFilterTestAllow { config.mode.channels.enabled = true; for chain in &mut config.chains { - chain.packet_filter = self.packet_filter.clone(); + match chain { + ChainConfig::CosmosSdk(chain_config) => { + chain_config.packet_filter = self.packet_filter.clone(); + } + } } } @@ -210,10 +214,15 @@ impl TestOverrides for IcaFilterTestDeny { config.mode.channels.enabled = true; for chain in &mut config.chains { - chain.packet_filter.channel_policy = ChannelPolicy::Deny(ChannelFilters::new(vec![( - FilterPattern::Wildcard("ica*".parse().unwrap()), - FilterPattern::Wildcard("*".parse().unwrap()), - )])); + match chain { + ChainConfig::CosmosSdk(chain_config) => { + chain_config.packet_filter.channel_policy = + ChannelPolicy::Deny(ChannelFilters::new(vec![( + FilterPattern::Wildcard("ica*".parse().unwrap()), + FilterPattern::Wildcard("*".parse().unwrap()), + )])); + } + } } } } diff --git a/tools/integration-test/src/tests/ics31.rs b/tools/integration-test/src/tests/ics31.rs index 93454b0820..33065dc091 100644 --- a/tools/integration-test/src/tests/ics31.rs +++ b/tools/integration-test/src/tests/ics31.rs @@ -51,7 +51,7 @@ impl TestOverrides for ICS31Test { *duration = serde_json::Value::String("20s".to_owned()); } } - set_voting_period(genesis, "20s")?; + set_voting_period(genesis, 20)?; set_staking_max_entries(genesis, "10")?; set_staking_bond_denom(genesis, "stake")?; set_mint_mint_denom(genesis, "stake")?; diff --git a/tools/integration-test/src/tests/interchain_security/icq.rs b/tools/integration-test/src/tests/interchain_security/icq.rs index 8b305f92e2..d1fde8a0c9 100644 --- a/tools/integration-test/src/tests/interchain_security/icq.rs +++ b/tools/integration-test/src/tests/interchain_security/icq.rs @@ -57,7 +57,7 @@ impl TestOverrides for InterchainSecurityIcqTest { *duration = serde_json::Value::String("20s".to_owned()); } } - set_voting_period(genesis, "10s")?; + set_voting_period(genesis, 10)?; set_staking_max_entries(genesis, "10")?; set_staking_bond_denom(genesis, "stake")?; set_mint_mint_denom(genesis, "stake")?; diff --git a/tools/integration-test/src/tests/manual/simulation.rs b/tools/integration-test/src/tests/manual/simulation.rs index 76442747e9..71feb2ad6d 100644 --- a/tools/integration-test/src/tests/manual/simulation.rs +++ b/tools/integration-test/src/tests/manual/simulation.rs @@ -12,7 +12,7 @@ */ use core::time::Duration; -use ibc_relayer::config::{types::MaxMsgNum, Config}; +use ibc_relayer::config::{types::MaxMsgNum, ChainConfig, Config}; use ibc_relayer::transfer::{build_and_send_transfer_messages, TransferOptions}; use ibc_relayer_types::events::IbcEvent; use ibc_test_framework::prelude::*; @@ -29,7 +29,11 @@ pub struct SimulationTest; impl TestOverrides for SimulationTest { fn modify_relayer_config(&self, config: &mut Config) { for chain in config.chains.iter_mut() { - chain.max_msg_num = MaxMsgNum::new(MAX_MSGS).unwrap(); + match chain { + ChainConfig::CosmosSdk(chain_config) => { + chain_config.max_msg_num = MaxMsgNum::new(MAX_MSGS).unwrap(); + } + } } } } diff --git a/tools/integration-test/src/tests/memo.rs b/tools/integration-test/src/tests/memo.rs index 9ad439cf95..2b44b90d48 100644 --- a/tools/integration-test/src/tests/memo.rs +++ b/tools/integration-test/src/tests/memo.rs @@ -4,6 +4,7 @@ //! You can find a more thorough walkthrough of this test at //! `tools/test-framework/src/docs/walkthroughs/memo.rs`. +use ibc_relayer::config::ChainConfig; use ibc_relayer::config::{types::Memo, Config}; use serde_json as json; @@ -25,7 +26,11 @@ pub struct MemoTest { impl TestOverrides for MemoTest { fn modify_relayer_config(&self, config: &mut Config) { for chain in config.chains.iter_mut() { - chain.memo_prefix = self.memo.clone(); + match chain { + ChainConfig::CosmosSdk(chain_config) => { + chain_config.memo_prefix = self.memo.clone(); + } + } } } } diff --git a/tools/integration-test/src/tests/mod.rs b/tools/integration-test/src/tests/mod.rs index 57526ac08b..225c2bab19 100644 --- a/tools/integration-test/src/tests/mod.rs +++ b/tools/integration-test/src/tests/mod.rs @@ -10,6 +10,7 @@ pub mod client_expiration; pub mod client_filter; pub mod client_refresh; pub mod client_settings; +#[cfg(not(any(feature = "celestia", feature = "juno")))] pub mod client_upgrade; pub mod connection_delay; pub mod consensus_states; @@ -22,9 +23,13 @@ pub mod python; pub mod query_packet; pub mod supervisor; pub mod tendermint; +#[cfg(not(feature = "celestia"))] pub mod ternary_transfer; pub mod transfer; +#[cfg(any(doc, feature = "async-icq"))] +pub mod async_icq; + #[cfg(any(doc, feature = "ics29-fee"))] pub mod fee; diff --git a/tools/integration-test/src/tests/ordered_channel_clear.rs b/tools/integration-test/src/tests/ordered_channel_clear.rs index 5590812164..696a536a27 100644 --- a/tools/integration-test/src/tests/ordered_channel_clear.rs +++ b/tools/integration-test/src/tests/ordered_channel_clear.rs @@ -1,4 +1,4 @@ -use ibc_relayer::config::types::MaxMsgNum; +use ibc_relayer::config::{types::MaxMsgNum, ChainConfig}; use ibc_relayer::link::{Link, LinkParameters}; use ibc_relayer::transfer::{build_and_send_transfer_messages, TransferOptions}; use ibc_relayer_types::events::IbcEvent; @@ -48,8 +48,21 @@ impl OrderedChannelClearTest { impl TestOverrides for OrderedChannelClearTest { fn modify_relayer_config(&self, config: &mut Config) { config.mode.packets.tx_confirmation = self.tx_confirmation; - config.chains[0].sequential_batch_tx = self.sequential_batch_tx; - config.chains[1].sequential_batch_tx = self.sequential_batch_tx; + { + let chain_a = &mut config.chains[0]; + match chain_a { + ChainConfig::CosmosSdk(chain_config) => { + chain_config.sequential_batch_tx = self.sequential_batch_tx; + } + } + } + + let chain_b = &mut config.chains[1]; + match chain_b { + ChainConfig::CosmosSdk(chain_config) => { + chain_config.sequential_batch_tx = self.sequential_batch_tx; + } + } } fn should_spawn_supervisor(&self) -> bool { @@ -171,12 +184,23 @@ pub struct OrderedChannelClearEqualCLITest; impl TestOverrides for OrderedChannelClearEqualCLITest { fn modify_relayer_config(&self, config: &mut Config) { config.mode.packets.tx_confirmation = true; + { + let chain_a = &mut config.chains[0]; + match chain_a { + ChainConfig::CosmosSdk(chain_config) => { + chain_config.sequential_batch_tx = true; + chain_config.max_msg_num = MaxMsgNum::new(3).unwrap(); + } + } + } - config.chains[0].sequential_batch_tx = true; - config.chains[0].max_msg_num = MaxMsgNum::new(3).unwrap(); - - config.chains[1].sequential_batch_tx = true; - config.chains[1].max_msg_num = MaxMsgNum::new(3).unwrap(); + let chain_b = &mut config.chains[1]; + match chain_b { + ChainConfig::CosmosSdk(chain_config) => { + chain_config.sequential_batch_tx = true; + chain_config.max_msg_num = MaxMsgNum::new(3).unwrap(); + } + } } fn should_spawn_supervisor(&self) -> bool { diff --git a/tools/integration-test/src/tests/python.rs b/tools/integration-test/src/tests/python.rs index 0fe5cff5ae..29d6457885 100644 --- a/tools/integration-test/src/tests/python.rs +++ b/tools/integration-test/src/tests/python.rs @@ -1,3 +1,4 @@ +use ibc_relayer::config::ChainConfig; use ibc_relayer::keyring::Store; use ibc_test_framework::prelude::*; use std::env; @@ -8,10 +9,14 @@ struct PythonTest; impl TestOverrides for PythonTest { fn modify_relayer_config(&self, config: &mut Config) { for chain in config.chains.iter_mut() { - // Modify the key store type to `Store::Test` so that the wallet - // keys are stored to ~/.hermes/keys so that we can use them - // with external relayer commands. - chain.key_store_type = Store::Test; + match chain { + ChainConfig::CosmosSdk(chain_config) => { + // Modify the key store type to `Store::Test` so that the wallet + // keys are stored to ~/.hermes/keys so that we can use them + // with external relayer commands. + chain_config.key_store_type = Store::Test; + } + } } } diff --git a/tools/integration-test/src/tests/supervisor.rs b/tools/integration-test/src/tests/supervisor.rs index c934d7a659..38daad74ed 100644 --- a/tools/integration-test/src/tests/supervisor.rs +++ b/tools/integration-test/src/tests/supervisor.rs @@ -188,12 +188,13 @@ impl TestOverrides for SupervisorScanTest { impl BinaryChannelTest for SupervisorScanTest { fn run( &self, - _config: &TestConfig, + config: &TestConfig, _relayer: RelayerDriver, chains: ConnectedChains, channels: ConnectedChannel, ) -> Result<(), Error> { let denom_a = chains.node_a.denom(); + let fee_denom_a = MonoTagged::new(Denom::base(&config.native_tokens[0])); let denom_b = derive_ibc_denom( &channels.port_b.as_ref(), @@ -229,6 +230,7 @@ impl BinaryChannelTest for SupervisorScanTest { &channels.port_a.0, &channels.channel_id_a.0, &denom_a.with_amount(1000u64).as_ref(), + &fee_denom_a.with_amount(381000000u64).as_ref(), &dst_height, )?; diff --git a/tools/integration-test/src/tests/tendermint/mod.rs b/tools/integration-test/src/tests/tendermint/mod.rs index 7b0ee374b1..7a53c41416 100644 --- a/tools/integration-test/src/tests/tendermint/mod.rs +++ b/tools/integration-test/src/tests/tendermint/mod.rs @@ -1 +1,5 @@ +/// Juno v17.1.1 forces a 2 second block time, which causes this test +/// to fail. +/// https://github.com/CosmosContracts/juno/blob/v17.1.1/cmd/junod/cmd/root.go#L93 +#[cfg(not(feature = "juno"))] pub mod sequential; diff --git a/tools/integration-test/src/tests/tendermint/sequential.rs b/tools/integration-test/src/tests/tendermint/sequential.rs index b74d2ee366..be9d254873 100644 --- a/tools/integration-test/src/tests/tendermint/sequential.rs +++ b/tools/integration-test/src/tests/tendermint/sequential.rs @@ -2,6 +2,7 @@ use std::time::Instant; use ibc_relayer::chain::tracking::TrackedMsgs; use ibc_relayer::config::types::max_msg_num::MaxMsgNum; +use ibc_relayer::config::ChainConfig; use ibc_test_framework::chain::config; use ibc_test_framework::prelude::*; use ibc_test_framework::relayer::transfer::build_transfer_message; @@ -32,14 +33,19 @@ impl TestOverrides for SequentialCommitTest { fn modify_relayer_config(&self, config: &mut Config) { // Use sequential batching for chain A, and default parallel batching for chain B - - let chain_config_a = &mut config.chains[0]; - chain_config_a.max_msg_num = MaxMsgNum::new(MESSAGES_PER_BATCH).unwrap(); - chain_config_a.sequential_batch_tx = true; - - let chain_config_b = &mut config.chains[1]; - chain_config_b.max_msg_num = MaxMsgNum::new(MESSAGES_PER_BATCH).unwrap(); - chain_config_b.sequential_batch_tx = false; + match &mut config.chains[0] { + ChainConfig::CosmosSdk(chain_config_a) => { + chain_config_a.max_msg_num = MaxMsgNum::new(MESSAGES_PER_BATCH).unwrap(); + chain_config_a.sequential_batch_tx = true; + } + }; + + match &mut config.chains[1] { + ChainConfig::CosmosSdk(chain_config_b) => { + chain_config_b.max_msg_num = MaxMsgNum::new(MESSAGES_PER_BATCH).unwrap(); + chain_config_b.sequential_batch_tx = false; + } + }; } fn should_spawn_supervisor(&self) -> bool { diff --git a/tools/integration-test/src/tests/transfer.rs b/tools/integration-test/src/tests/transfer.rs index d51e3be616..f117dc742f 100644 --- a/tools/integration-test/src/tests/transfer.rs +++ b/tools/integration-test/src/tests/transfer.rs @@ -10,6 +10,7 @@ fn test_ibc_transfer() -> Result<(), Error> { Test that IBC token transfer can still work with a single chain that is connected to itself. */ +#[cfg(not(feature = "celestia"))] #[test] fn test_self_connected_ibc_transfer() -> Result<(), Error> { run_self_connected_binary_chain_test(&RunBinaryConnectionTest::new(&RunBinaryChannelTest::new( @@ -24,11 +25,13 @@ fn test_self_connected_ibc_transfer() -> Result<(), Error> { this behind the "experimental" feature flag so that normal developers are not obligated to understand how this test works yet. */ +#[cfg(not(feature = "celestia"))] #[test] fn test_nary_ibc_transfer() -> Result<(), Error> { run_binary_as_nary_channel_test(&IbcTransferTest) } +#[cfg(not(feature = "celestia"))] #[test] fn test_self_connected_nary_ibc_transfer() -> Result<(), Error> { run_self_connected_nary_chain_test(&RunNaryConnectionTest::new(&RunNaryChannelTest::new( diff --git a/tools/test-framework/Cargo.toml b/tools/test-framework/Cargo.toml index b9540e1141..1da6423a4c 100644 --- a/tools/test-framework/Cargo.toml +++ b/tools/test-framework/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ibc-test-framework" -version = "0.25.0" +version = "0.26.4" edition = "2021" license = "Apache-2.0" readme = "README.md" @@ -14,10 +14,10 @@ description = """ """ [dependencies] -ibc-relayer-types = { version = "=0.25.0", path = "../../crates/relayer-types" } -ibc-relayer = { version = "=0.25.0", path = "../../crates/relayer" } -ibc-relayer-cli = { version = "=1.6.0", path = "../../crates/relayer-cli" } -ibc-proto = { version = "0.37.0", features = ["serde"] } +ibc-relayer-types = { version = "=0.26.4", path = "../../crates/relayer-types" } +ibc-relayer = { version = "=0.26.4", path = "../../crates/relayer" } +ibc-relayer-cli = { version = "=1.7.4", path = "../../crates/relayer-cli" } +ibc-proto = { version = "0.39.0", features = ["serde"] } tendermint-rpc = { version = "0.34.0", features = ["http-client", "websocket-client"] } http = "0.2.9" diff --git a/tools/test-framework/src/bootstrap/binary/chain.rs b/tools/test-framework/src/bootstrap/binary/chain.rs index 386e743b28..365c079e8c 100644 --- a/tools/test-framework/src/bootstrap/binary/chain.rs +++ b/tools/test-framework/src/bootstrap/binary/chain.rs @@ -56,8 +56,8 @@ pub fn bootstrap_chains_with_full_nodes( > { let mut config = Config::default(); - add_chain_config(&mut config, &node_a, test_config)?; - add_chain_config(&mut config, &node_b, test_config)?; + add_chain_config(&mut config, &node_a, test_config, 0)?; + add_chain_config(&mut config, &node_b, test_config, 1)?; config_modifier(&mut config); @@ -165,7 +165,7 @@ pub fn pad_client_ids( [`FullNode`]. The function accepts a proxy type `Seed` that should be unique - accross multiple calls so that the returned [`ChainHandle`] + across multiple calls so that the returned [`ChainHandle`] have a unique type. For example, the following test should fail to compile: @@ -257,9 +257,13 @@ pub fn add_chain_config( config: &mut Config, running_node: &FullNode, test_config: &TestConfig, + chain_number: usize, ) -> Result<(), Error> { - let chain_config = - running_node.generate_chain_config(&running_node.chain_driver.chain_type, test_config)?; + let chain_config = running_node.generate_chain_config( + &running_node.chain_driver.chain_type, + test_config, + chain_number, + )?; config.chains.push(chain_config); Ok(()) diff --git a/tools/test-framework/src/bootstrap/consumer.rs b/tools/test-framework/src/bootstrap/consumer.rs index d60d9ab07b..1c46b7e600 100644 --- a/tools/test-framework/src/bootstrap/consumer.rs +++ b/tools/test-framework/src/bootstrap/consumer.rs @@ -65,8 +65,16 @@ pub fn bootstrap_consumer_node( chain_driver.update_genesis_file("genesis.json", genesis_modifier)?; // The configuration `soft_opt_out_threshold` might be missing and is required // for chains such as Neutron + let globalfee_minimum_gas = serde_json::json!([ + { + "denom": "stake", + "amount": "0", + } + ]); chain_driver.update_genesis_file("genesis.json", |genesis| { config::set_soft_opt_out_threshold(genesis, "0.05")?; + config::consensus_params_max_gas(genesis, "3000000")?; + config::globalfee_minimum_gas_prices(genesis, globalfee_minimum_gas)?; Ok(()) })?; diff --git a/tools/test-framework/src/bootstrap/init.rs b/tools/test-framework/src/bootstrap/init.rs index 45a102127f..795f19787c 100644 --- a/tools/test-framework/src/bootstrap/init.rs +++ b/tools/test-framework/src/bootstrap/init.rs @@ -46,8 +46,14 @@ pub fn init_test() -> Result { let account_prefix = env::var("ACCOUNT_PREFIXES").unwrap_or_else(|_| "cosmos".to_string()); + let native_token = env::var("NATIVE_TOKENS").unwrap_or_else(|_| "stake".to_string()); + + let compat_modes = env::var("COMPAT_MODES").ok().map(parse_chain_command_paths); + let account_prefixes = parse_chain_command_paths(account_prefix); + let native_tokens = parse_chain_command_paths(native_token); + let chain_store_dir = format!("{}/test-{}", base_chain_store_dir, random_u32()); fs::create_dir_all(&chain_store_dir)?; @@ -65,6 +71,8 @@ pub fn init_test() -> Result { account_prefixes, hang_on_fail, bootstrap_with_random_ids: false, + native_tokens, + compat_modes, }) } diff --git a/tools/test-framework/src/bootstrap/nary/chain.rs b/tools/test-framework/src/bootstrap/nary/chain.rs index b0233ecdf5..795ec74e69 100644 --- a/tools/test-framework/src/bootstrap/nary/chain.rs +++ b/tools/test-framework/src/bootstrap/nary/chain.rs @@ -59,8 +59,8 @@ pub fn boostrap_chains_with_any_nodes( ) -> Result<(RelayerDriver, DynamicConnectedChains), Error> { let mut config = Config::default(); - for node in full_nodes.iter() { - add_chain_config(&mut config, node, test_config)?; + for (i, node) in full_nodes.iter().enumerate() { + add_chain_config(&mut config, node, test_config, i)?; } config_modifier(&mut config); diff --git a/tools/test-framework/src/bootstrap/nary/channel.rs b/tools/test-framework/src/bootstrap/nary/channel.rs index e2d2697b88..a954c23ed7 100644 --- a/tools/test-framework/src/bootstrap/nary/channel.rs +++ b/tools/test-framework/src/bootstrap/nary/channel.rs @@ -1,5 +1,5 @@ /*! - Functions for bootstrapping N-ary number of chanels. + Functions for bootstrapping N-ary number of channels. */ use core::convert::TryInto; @@ -100,7 +100,7 @@ pub fn bootstrap_channels_with_connections Result<(), Error>, chain_number: usize, ) -> Result { - let stake_denom = Denom::base("stake"); + let native_token_number = chain_number % builder.native_tokens.len(); + let native_token = &builder.native_tokens[native_token_number]; + let native_denom = Denom::base(native_token); let denom = if use_random_id { Denom::base(&format!("coin{:x}", random_u32())) @@ -58,12 +60,13 @@ pub fn bootstrap_single_node( // when running `evmosd start`. let initial_amount = random_u128_range(1_000_000_000_000_000_000, 2_000_000_000_000_000_000); - let initial_stake = Token::new(stake_denom, initial_amount); - let additional_initial_stake = initial_stake + let initial_native_token = Token::new(native_denom, initial_amount); + let additional_native_token = initial_native_token .clone() .checked_add(1_000_000_000_000u64) .ok_or(Error::generic(eyre!( - "error creating initial stake with additional amount" + "error creating initial {} with additional amount", + native_token )))?; let initial_coin = Token::new(denom.clone(), initial_amount); @@ -79,15 +82,15 @@ pub fn bootstrap_single_node( let user2 = add_wallet(&chain_driver, "user2", use_random_id)?; // Validator is given more tokens as they are required to vote on upgrade chain - chain_driver.add_genesis_account(&validator.address, &[&additional_initial_stake])?; + chain_driver.add_genesis_account(&validator.address, &[&additional_native_token])?; - chain_driver.add_genesis_validator(&validator.id, &initial_stake)?; + chain_driver.add_genesis_validator(&validator.id, &initial_native_token)?; - chain_driver.add_genesis_account(&user1.address, &[&initial_stake, &initial_coin])?; + chain_driver.add_genesis_account(&user1.address, &[&initial_native_token, &initial_coin])?; - chain_driver.add_genesis_account(&user2.address, &[&initial_stake, &initial_coin])?; + chain_driver.add_genesis_account(&user2.address, &[&initial_native_token, &initial_coin])?; - chain_driver.add_genesis_account(&relayer.address, &[&initial_stake, &initial_coin])?; + chain_driver.add_genesis_account(&relayer.address, &[&initial_native_token, &initial_coin])?; chain_driver.collect_gen_txs()?; @@ -101,17 +104,20 @@ pub fn bootstrap_single_node( config::set_timeout_commit(config, Duration::from_secs(1))?; config::set_timeout_propose(config, Duration::from_secs(1))?; config::set_mode(config, "validator")?; + config::set_indexer(config, "kv")?; config_modifier(config)?; Ok(()) })?; + let minimum_gas = format!("0{}", native_token); chain_driver.update_chain_config("app.toml", |config| { config::set_grpc_port(config, chain_driver.grpc_port)?; + config::enable_grpc(config)?; config::disable_grpc_web(config)?; config::disable_api(config)?; - config::set_minimum_gas_price(config, "0stake")?; + config::set_minimum_gas_price(config, &minimum_gas)?; Ok(()) })?; diff --git a/tools/test-framework/src/chain/builder.rs b/tools/test-framework/src/chain/builder.rs index d78fe390ac..ff23be521f 100644 --- a/tools/test-framework/src/chain/builder.rs +++ b/tools/test-framework/src/chain/builder.rs @@ -2,9 +2,11 @@ Builder construct that spawn new chains with some common parameters. */ +use eyre::eyre; use std::str::FromStr; use alloc::sync::Arc; +use ibc_relayer::config::compat_mode::CompatMode; use tokio::runtime::Runtime; use crate::chain::driver::ChainDriver; @@ -39,6 +41,10 @@ pub struct ChainBuilder { pub account_prefixes: Vec, + pub native_tokens: Vec, + + pub compat_modes: Option>, + pub runtime: Arc, } @@ -50,12 +56,16 @@ impl ChainBuilder { command_paths: Vec, base_store_dir: &str, account_prefixes: Vec, + native_tokens: Vec, + compat_modes: Option>, runtime: Arc, ) -> Self { Self { command_paths, base_store_dir: base_store_dir.to_string(), account_prefixes, + native_tokens, + compat_modes, runtime, } } @@ -68,6 +78,8 @@ impl ChainBuilder { config.chain_command_paths.clone(), &format!("{}", config.chain_store_dir.display()), config.account_prefixes.clone(), + config.native_tokens.clone(), + config.compat_modes.clone(), runtime, ) } @@ -77,7 +89,7 @@ impl ChainBuilder { given prefix. Note that this only configures the [`ChainDriver`] without - the actual chain being intitialized or spawned. + the actual chain being initialized or spawned. The `ChainBuilder` will configure the [`ChainDriver`] with random unused ports, and add a random suffix to the chain ID. @@ -96,6 +108,17 @@ impl ChainBuilder { // the number of chain binaries given. Same for account prefix. let chain_number = chain_number % self.command_paths.len(); let account_number = chain_number % self.account_prefixes.len(); + let native_token_number = chain_number % self.native_tokens.len(); + let compat_mode = if let Some(modes) = &self.compat_modes { + let mode_str = &modes[chain_number % modes.len()]; + Some(CompatMode::from_str(mode_str).map_err(|e| { + Error::generic(eyre!( + "Invalid CompatMode environment variable `{mode_str}`: {e}" + )) + })?) + } else { + None + }; let chain_type = ChainType::from_str(&self.command_paths[chain_number])?; @@ -121,6 +144,8 @@ impl ChainBuilder { p2p_port, pprof_port, self.runtime.clone(), + self.native_tokens[native_token_number].clone(), + compat_mode, )?; Ok(driver) diff --git a/tools/test-framework/src/chain/chain_type.rs b/tools/test-framework/src/chain/chain_type.rs index 2d39f8f811..5d5e6bfd08 100644 --- a/tools/test-framework/src/chain/chain_type.rs +++ b/tools/test-framework/src/chain/chain_type.rs @@ -7,11 +7,13 @@ use crate::util::random::{random_u32, random_unused_tcp_port}; const COSMOS_HD_PATH: &str = "m/44'/118'/0'/0/0"; const EVMOS_HD_PATH: &str = "m/44'/60'/0'/0/0"; +const PROVENANCE_HD_PATH: &str = "m/44'/505'/0'/0/0"; #[derive(Clone, Debug)] pub enum ChainType { Cosmos, Evmos, + Provenance, } impl ChainType { @@ -19,6 +21,7 @@ impl ChainType { match self { Self::Cosmos => COSMOS_HD_PATH, Self::Evmos => EVMOS_HD_PATH, + Self::Provenance => PROVENANCE_HD_PATH, } } @@ -32,6 +35,7 @@ impl ChainType { } } Self::Evmos => ChainId::from_string(&format!("evmos_9000-{prefix}")), + Self::Provenance => ChainId::from_string(&format!("pio-mainnet-{prefix}")), } } @@ -45,6 +49,7 @@ impl ChainType { res.push("--json-rpc.address".to_owned()); res.push(format!("localhost:{json_rpc_port}")); } + Self::Provenance => {} } res } @@ -55,6 +60,7 @@ impl ChainType { Self::Evmos => AddressType::Ethermint { pk_type: "/ethermint.crypto.v1.ethsecp256k1.PubKey".to_string(), }, + Self::Provenance => AddressType::default(), } } } @@ -69,6 +75,7 @@ impl FromStr for ChainType { name if name.contains("wasmd") => Ok(ChainType::Cosmos), name if name.contains("icad") => Ok(ChainType::Cosmos), name if name.contains("evmosd") => Ok(ChainType::Evmos), + name if name.contains("provenanced") => Ok(ChainType::Provenance), _ => Ok(ChainType::Cosmos), } } diff --git a/tools/test-framework/src/chain/cli/async_icq.rs b/tools/test-framework/src/chain/cli/async_icq.rs new file mode 100644 index 0000000000..f662a4beb9 --- /dev/null +++ b/tools/test-framework/src/chain/cli/async_icq.rs @@ -0,0 +1,105 @@ +use std::str; + +use crate::chain::exec::simple_exec; +use crate::error::Error; + +pub fn update_oracle( + chain_id: &str, + command_path: &str, + home_path: &str, + rpc_listen_address: &str, + account: &str, + relayer: &str, +) -> Result<(), Error> { + simple_exec( + chain_id, + command_path, + &[ + "--home", + home_path, + "--chain-id", + chain_id, + "--node", + rpc_listen_address, + "-b", + "block", + "tx", + "oracle", + "update", + account, + "--deposit", + "1000000000000nhash", + "--from", + relayer, + "--fees", + "381000000nhash", + "--yes", + ], + )?; + + Ok(()) +} + +pub fn async_icq( + chain_id: &str, + command_path: &str, + home_path: &str, + rpc_listen_address: &str, + channel_id: &str, + query_json: &str, + from: &str, +) -> Result<(), Error> { + simple_exec( + chain_id, + command_path, + &[ + "--home", + home_path, + "--chain-id", + chain_id, + "--node", + rpc_listen_address, + "tx", + "oracle", + "send-query", + channel_id, + query_json, + "-b", + "block", + "--from", + from, + "--fees", + "381000000nhash", + "--yes", + ], + )?; + + Ok(()) +} + +pub fn query_oracle_address( + chain_id: &str, + command_path: &str, + home_path: &str, + rpc_listen_address: &str, +) -> Result { + let exec_output = simple_exec( + chain_id, + command_path, + &[ + "--home", + home_path, + "--chain-id", + chain_id, + "--node", + rpc_listen_address, + "query", + "oracle", + "address", + ], + )?; + let mut address = exec_output.stdout.replace("address: ", ""); + address.pop(); + + Ok(address) +} diff --git a/tools/test-framework/src/chain/cli/bootstrap.rs b/tools/test-framework/src/chain/cli/bootstrap.rs index 15d7f9f71d..65dc1e9ed4 100644 --- a/tools/test-framework/src/chain/cli/bootstrap.rs +++ b/tools/test-framework/src/chain/cli/bootstrap.rs @@ -64,20 +64,36 @@ pub fn add_genesis_account( amounts: &[String], ) -> Result<(), Error> { let amounts_str = itertools::join(amounts, ","); - - simple_exec( + // Cosmos SDK v0.47.0 introduced the `genesis` subcommand, this match is required to + // support pre and post SDK v0.47.0. https://github.com/cosmos/cosmos-sdk/pull/14149 + match simple_exec( chain_id, command_path, &[ "--home", home_path, + "genesis", "add-genesis-account", wallet_address, &amounts_str, ], - )?; - - Ok(()) + ) { + Ok(_) => Ok(()), + Err(_) => { + simple_exec( + chain_id, + command_path, + &[ + "--home", + home_path, + "add-genesis-account", + wallet_address, + &amounts_str, + ], + )?; + Ok(()) + } + } } pub fn add_genesis_validator( @@ -87,12 +103,15 @@ pub fn add_genesis_validator( wallet_id: &str, amount: &str, ) -> Result<(), Error> { - simple_exec( + // Cosmos SDK v0.47.0 introduced the `genesis` subcommand, this match is required to + // support pre and post SDK v0.47.0. https://github.com/cosmos/cosmos-sdk/pull/14149 + match simple_exec( chain_id, command_path, &[ "--home", home_path, + "genesis", "gentx", wallet_id, "--keyring-backend", @@ -101,19 +120,47 @@ pub fn add_genesis_validator( chain_id, amount, ], - )?; - - Ok(()) + ) { + Ok(_) => Ok(()), + Err(_) => { + simple_exec( + chain_id, + command_path, + &[ + "--home", + home_path, + "gentx", + wallet_id, + "--keyring-backend", + "test", + "--chain-id", + chain_id, + amount, + ], + )?; + Ok(()) + } + } } pub fn collect_gen_txs(chain_id: &str, command_path: &str, home_path: &str) -> Result<(), Error> { - simple_exec( + // Cosmos SDK v0.47.0 introduced the `genesis` subcommand, this match is required to + // support pre and post SDK v0.47.0. https://github.com/cosmos/cosmos-sdk/pull/14149 + match simple_exec( chain_id, command_path, - &["--home", home_path, "collect-gentxs"], - )?; - - Ok(()) + &["--home", home_path, "genesis", "collect-gentxs"], + ) { + Ok(_) => Ok(()), + Err(_) => { + simple_exec( + chain_id, + command_path, + &["--home", home_path, "collect-gentxs"], + )?; + Ok(()) + } + } } pub fn start_chain( diff --git a/tools/test-framework/src/chain/cli/fee_grant.rs b/tools/test-framework/src/chain/cli/fee_grant.rs index 3fe484aca2..b20e425d90 100644 --- a/tools/test-framework/src/chain/cli/fee_grant.rs +++ b/tools/test-framework/src/chain/cli/fee_grant.rs @@ -8,6 +8,7 @@ pub fn feegrant_grant( rpc_listen_address: &str, granter: &str, grantee: &str, + fees: &str, ) -> Result<(), Error> { simple_exec( chain_id, @@ -26,6 +27,8 @@ pub fn feegrant_grant( "grant", granter, grantee, + "--fees", + fees, "--yes", ], )?; diff --git a/tools/test-framework/src/chain/cli/mod.rs b/tools/test-framework/src/chain/cli/mod.rs index 88ac42bf9e..5b2415d964 100644 --- a/tools/test-framework/src/chain/cli/mod.rs +++ b/tools/test-framework/src/chain/cli/mod.rs @@ -1,3 +1,4 @@ +pub mod async_icq; pub mod bootstrap; pub mod fee_grant; pub mod host_zone; diff --git a/tools/test-framework/src/chain/cli/provider.rs b/tools/test-framework/src/chain/cli/provider.rs index e7f0a15522..6a1c7c34f3 100644 --- a/tools/test-framework/src/chain/cli/provider.rs +++ b/tools/test-framework/src/chain/cli/provider.rs @@ -41,11 +41,12 @@ pub fn submit_consumer_chain_proposal( Ok(()) } -pub fn query_consumer_proposal( +pub fn query_gov_proposal( chain_id: &str, command_path: &str, home_path: &str, rpc_listen_address: &str, + proposal_id: &str, ) -> Result { simple_exec( chain_id, @@ -58,7 +59,7 @@ pub fn query_consumer_proposal( "query", "gov", "proposal", - "1", + proposal_id, "--output", "json", ], diff --git a/tools/test-framework/src/chain/cli/query.rs b/tools/test-framework/src/chain/cli/query.rs index 8029d23929..5bfb0801b5 100644 --- a/tools/test-framework/src/chain/cli/query.rs +++ b/tools/test-framework/src/chain/cli/query.rs @@ -3,6 +3,8 @@ use eyre::eyre; use ibc_relayer_types::applications::transfer::amount::Amount; use serde_json as json; use serde_yaml as yaml; +use std::collections::HashMap; +use tracing::debug; use crate::chain::exec::simple_exec; use crate::error::{handle_generic_error, Error}; @@ -14,7 +16,9 @@ pub fn query_balance( wallet_id: &str, denom: &str, ) -> Result { - let res = simple_exec( + // SDK v0.50 has removed the `--denom` flag from the `query bank balances` CLI. + // It also changed the JSON output. + match simple_exec( chain_id, command_path, &[ @@ -29,20 +33,73 @@ pub fn query_balance( "--output", "json", ], - )? - .stdout; + ) { + Ok(output) => { + let amount_str = json::from_str::(&output.stdout) + .map_err(handle_generic_error)? + .get("amount") + .ok_or_else(|| eyre!("expected amount field"))? + .as_str() + .ok_or_else(|| eyre!("expected string field"))? + .to_string(); - let amount_str = json::from_str::(&res) - .map_err(handle_generic_error)? - .get("amount") - .ok_or_else(|| eyre!("expected amount field"))? - .as_str() - .ok_or_else(|| eyre!("expected string field"))? - .to_string(); + let amount = Amount::from_str(&amount_str).map_err(handle_generic_error)?; + + Ok(amount) + } + Err(_) => { + let res = simple_exec( + chain_id, + command_path, + &[ + "--node", + rpc_listen_address, + "query", + "bank", + "balances", + wallet_id, + "--output", + "json", + ], + )? + .stdout; + let amounts_array = + json::from_str::(&res).map_err(handle_generic_error)?; - let amount = Amount::from_str(&amount_str).map_err(handle_generic_error)?; + let balances = amounts_array + .get("balances") + .ok_or_else(|| eyre!("expected balances field"))? + .as_array() + .ok_or_else(|| eyre!("expected array field"))?; - Ok(amount) + let amount_str = balances.iter().find(|a| { + a.get("denom") + .ok_or_else(|| eyre!("expected denom field")) + .unwrap() + == denom + }); + + match amount_str { + Some(amount_str) => { + let amount_str = amount_str + .get("amount") + .ok_or_else(|| eyre!("expected amount field"))? + .as_str() + .ok_or_else(|| eyre!("expected amount to be in string format"))?; + + let amount = Amount::from_str(amount_str).map_err(handle_generic_error)?; + + Ok(amount) + } + None => { + debug!( + "Denom `{denom}` not found when querying for balance, will return 0{denom}" + ); + Ok(Amount::from_str("0").map_err(handle_generic_error)?) + } + } + } + } } /** @@ -55,7 +112,7 @@ pub fn query_recipient_transactions( rpc_listen_address: &str, recipient_address: &str, ) -> Result { - let res = simple_exec( + let res = match simple_exec( chain_id, command_path, &[ @@ -66,8 +123,25 @@ pub fn query_recipient_transactions( "--events", &format!("transfer.recipient={recipient_address}"), ], - )? - .stdout; + ) { + Ok(output) => output.stdout, + // Cosmos SDK v0.50.1 changed the `query txs` CLI flag from `--events` to `--query` + Err(_) => { + simple_exec( + chain_id, + command_path, + &[ + "--node", + rpc_listen_address, + "query", + "txs", + "--query", + &format!("transfer.recipient='{recipient_address}'"), + ], + )? + .stdout + } + }; tracing::debug!("parsing tx result: {}", res); @@ -120,3 +194,101 @@ pub fn query_cross_chain_query( Ok(res) } + +/// Query authority account for a specific module +pub fn query_auth_module( + chain_id: &str, + command_path: &str, + home_path: &str, + rpc_listen_address: &str, + module_name: &str, +) -> Result { + let account = match simple_exec( + chain_id, + command_path, + &[ + "--home", + home_path, + "--node", + rpc_listen_address, + "query", + "auth", + "module-account", + module_name, + "--output", + "json", + ], + ) { + Ok(output) => { + let json_res: HashMap = + serde_json::from_str(&output.stdout).map_err(handle_generic_error)?; + + json_res + .get("account") + .ok_or_else(|| eyre!("expect `account` string field to be present in json result"))? + .clone() + } + Err(e) => { + debug!("CLI `query auth module-account` failed, will try with `query auth module-accounts`: {e}"); + let output = simple_exec( + chain_id, + command_path, + &[ + "--home", + home_path, + "--node", + rpc_listen_address, + "query", + "auth", + "module-accounts", + "--output", + "json", + ], + )? + .stdout; + let json_res: HashMap = + serde_json::from_str(&output).map_err(handle_generic_error)?; + + let accounts = json_res + .get("accounts") + .ok_or_else(|| { + eyre!("expect `accounts` string field to be present in json result") + })? + .as_array() + .ok_or_else(|| eyre!("expected `accounts` to be an array"))?; + + accounts + .iter() + .find(|&account| { + if let Some(name) = account.get("name") { + name == module_name + } else { + false + } + }) + .ok_or_else(|| { + eyre!("expected to find the account for the `{module_name}` module") + })? + .clone() + } + }; + + // Depending on the version used the CLI `query auth module-account` will have a field `base_account` or + // or a field `value` containing the address. + let res = match account.get("base_account") { + Some(base_account) => base_account + .get("address") + .ok_or_else(|| eyre!("expect `address` string field to be present in json result"))? + .as_str() + .ok_or_else(|| eyre!("failed to convert value to &str"))?, + None => account + .get("value") + .ok_or_else(|| eyre!("expect `value` string field to be present in json result"))? + .get("address") + .ok_or_else(|| eyre!("expect `address` string field to be present in json result"))? + .as_str() + .ok_or_else(|| eyre!("failed to convert value to &str"))?, + }; + + Ok(res.to_owned()) +} diff --git a/tools/test-framework/src/chain/cli/transfer.rs b/tools/test-framework/src/chain/cli/transfer.rs index b91297db12..53457c04ab 100644 --- a/tools/test-framework/src/chain/cli/transfer.rs +++ b/tools/test-framework/src/chain/cli/transfer.rs @@ -49,6 +49,7 @@ pub fn transfer_from_chain( src_channel: &str, recipient: &str, token: &str, + fees: &str, timeout_height: &str, ) -> Result<(), Error> { simple_exec( @@ -73,7 +74,7 @@ pub fn transfer_from_chain( "--keyring-backend", "test", "--fees", - "1200stake", + fees, "--timeout-height", timeout_height, "--yes", diff --git a/tools/test-framework/src/chain/config.rs b/tools/test-framework/src/chain/config.rs index 617485e04a..66f4f3a02d 100644 --- a/tools/test-framework/src/chain/config.rs +++ b/tools/test-framework/src/chain/config.rs @@ -9,6 +9,7 @@ use core::time::Duration; use eyre::{eyre, Report as Error}; use toml::Value; +use tracing::debug; /// Set the `rpc` field in the full node config. pub fn set_rpc_port(config: &mut Value, port: u16) -> Result<(), Error> { @@ -22,6 +23,17 @@ pub fn set_rpc_port(config: &mut Value, port: u16) -> Result<(), Error> { Ok(()) } +pub fn enable_grpc(config: &mut Value) -> Result<(), Error> { + config + .get_mut("grpc") + .ok_or_else(|| eyre!("expect grpc section"))? + .as_table_mut() + .ok_or_else(|| eyre!("expect object"))? + .insert("enable".to_string(), true.into()); + + Ok(()) +} + pub fn set_grpc_port(config: &mut Value, port: u16) -> Result<(), Error> { config .get_mut("grpc") @@ -149,6 +161,17 @@ pub fn set_mode(config: &mut Value, mode: &str) -> Result<(), Error> { Ok(()) } +pub fn set_indexer(config: &mut Value, mode: &str) -> Result<(), Error> { + config + .get_mut("tx_index") + .ok_or_else(|| eyre!("expect tx_index section"))? + .as_table_mut() + .ok_or_else(|| eyre!("expect object"))? + .insert("indexer".to_string(), mode.into()); + + Ok(()) +} + pub fn set_max_deposit_period(genesis: &mut serde_json::Value, period: &str) -> Result<(), Error> { let max_deposit_period = genesis .get_mut("app_state") @@ -167,6 +190,31 @@ pub fn set_max_deposit_period(genesis: &mut serde_json::Value, period: &str) -> Ok(()) } +pub fn set_min_deposit_amount( + genesis: &mut serde_json::Value, + min_deposit_amount: u64, +) -> Result<(), Error> { + let min_deposit = genesis + .get_mut("app_state") + .and_then(|app_state| app_state.get_mut("gov")) + .and_then(|gov| get_mut_with_fallback(gov, "params", "deposit_params")) + .and_then(|deposit_params| deposit_params.get_mut("min_deposit")) + .and_then(|min_deposit| min_deposit.as_array_mut()) + .ok_or_else(|| eyre!("failed to find min_deposit in genesis file"))? + .get_mut(0) + .and_then(|min_deposit_entry| min_deposit_entry.as_object_mut()) + .ok_or_else(|| eyre!("failed to find first entry of min_deposit in genesis file"))?; + + min_deposit + .insert( + "amount".to_owned(), + serde_json::Value::String(min_deposit_amount.to_string()), + ) + .ok_or_else(|| eyre!("failed to update deposit_params amount in genesis file"))?; + + Ok(()) +} + pub fn set_staking_bond_denom(genesis: &mut serde_json::Value, denom: &str) -> Result<(), Error> { let bond_denom = genesis .get_mut("app_state") @@ -242,7 +290,10 @@ pub fn set_crisis_denom(genesis: &mut serde_json::Value, crisis_denom: &str) -> Ok(()) } -pub fn set_voting_period(genesis: &mut serde_json::Value, period: &str) -> Result<(), Error> { +pub fn set_voting_period(genesis: &mut serde_json::Value, period: u64) -> Result<(), Error> { + // Expedited voting period must be strictly less that the regular voting period + let regular_period = format!("{period}s"); + let expedited_period = format!("{}s", period - 1); let voting_period = genesis .get_mut("app_state") .and_then(|app_state| app_state.get_mut("gov")) @@ -253,10 +304,34 @@ pub fn set_voting_period(genesis: &mut serde_json::Value, period: &str) -> Resul voting_period .insert( "voting_period".to_owned(), - serde_json::Value::String(period.to_string()), + serde_json::Value::String(regular_period), ) .ok_or_else(|| eyre!("failed to update voting_period in genesis file"))?; + let maybe_expedited_voting_period = genesis + .get_mut("app_state") + .and_then(|app_state| app_state.get_mut("gov")) + .and_then(|gov| get_mut_with_fallback(gov, "params", "expedited_voting_period")); + + if let Some(expedited_voting_period) = maybe_expedited_voting_period { + let expedited_voting_period = expedited_voting_period + .as_object_mut() + .ok_or_else(|| eyre!("failed to get voting_params in genesis file"))?; + + // Only insert `expedited_voting_period` if it already exists in order to avoid adding an unknown configuration in + // chains using Cosmos SDK pre v0.50 + match expedited_voting_period.get("expedited_voting_period") { + Some(_) => { + expedited_voting_period + .insert( + "expedited_voting_period".to_owned(), + serde_json::Value::String(expedited_period), + ).ok_or_else(|| eyre!("failed to update expedited_voting_period in genesis file"))?; + }, + None => debug!("`expedited_voting_period` was not updated, this configuration was introduced in Cosmos SDK v0.50"), + } + } + Ok(()) } @@ -280,6 +355,48 @@ pub fn set_soft_opt_out_threshold( Ok(()) } +pub fn consensus_params_max_gas( + genesis: &mut serde_json::Value, + max_gas: &str, +) -> Result<(), Error> { + let block = genesis + .get_mut("consensus_params") + .and_then(|consensus_params| consensus_params.get_mut("block")) + .and_then(|block| block.as_object_mut()) + .ok_or_else(|| eyre!("failed to get `block` field in genesis file"))?; + + block.insert( + "max_gas".to_owned(), + serde_json::Value::String(max_gas.to_string()), + ); + + Ok(()) +} + +pub fn globalfee_minimum_gas_prices( + genesis: &mut serde_json::Value, + minimum_gas_prices: serde_json::Value, +) -> Result<(), Error> { + let globalfee = genesis + .get_mut("app_state") + .and_then(|app_state| app_state.get_mut("globalfee")); + + // Only update `minimum_gas_prices` if `globalfee` is enabled + match globalfee { + Some(globalfee) => { + let params = globalfee + .get_mut("params") + .and_then(|params| params.as_object_mut()) + .ok_or_else(|| eyre!("failed to get `params` fields in genesis file"))?; + + params.insert("minimum_gas_prices".to_owned(), minimum_gas_prices); + } + None => debug!("chain doesn't have `globalfee`"), + } + + Ok(()) +} + /// Look up a key in a JSON object, falling back to the second key if the first one cannot be found. /// /// This lets us support both Tendermint 0.34 and 0.37, which sometimes use different keys for the diff --git a/tools/test-framework/src/chain/driver.rs b/tools/test-framework/src/chain/driver.rs index f853ad10b9..4b3414c554 100644 --- a/tools/test-framework/src/chain/driver.rs +++ b/tools/test-framework/src/chain/driver.rs @@ -6,6 +6,7 @@ use core::time::Duration; use alloc::sync::Arc; use eyre::eyre; +use ibc_relayer::config::compat_mode::CompatMode; use tokio::runtime::Runtime; use ibc_relayer::chain::cosmos::types::config::TxConfig; @@ -95,6 +96,8 @@ pub struct ChainDriver { pub tx_config: TxConfig, pub runtime: Arc, + + pub compat_mode: Option, } impl ExportEnv for ChainDriver { @@ -120,12 +123,15 @@ impl ChainDriver { p2p_port: u16, pprof_port: u16, runtime: Arc, + native_token: String, + compat_mode: Option, ) -> Result { let tx_config = new_tx_config_for_test( chain_id.clone(), format!("http://localhost:{rpc_port}"), format!("http://localhost:{grpc_port}"), chain_type.address_type(), + native_token, )?; Ok(Self { @@ -141,6 +147,7 @@ impl ChainDriver { pprof_port, tx_config, runtime, + compat_mode, }) } diff --git a/tools/test-framework/src/chain/ext/async_icq.rs b/tools/test-framework/src/chain/ext/async_icq.rs new file mode 100644 index 0000000000..60998ea5d3 --- /dev/null +++ b/tools/test-framework/src/chain/ext/async_icq.rs @@ -0,0 +1,38 @@ +use crate::chain::cli::async_icq::{async_icq, update_oracle}; +use crate::chain::driver::ChainDriver; +use crate::error::Error; +use crate::prelude::*; +use crate::types::tagged::*; + +pub trait AsyncIcqMethodsExt { + fn update_oracle(&self, relayer: &str, account: &str) -> Result<(), Error>; + + fn async_icq(&self, channel_id: &ChannelId, query_json: &str, from: &str) -> Result<(), Error>; +} + +impl<'a, Chain: Send> AsyncIcqMethodsExt for MonoTagged { + fn update_oracle(&self, relayer: &str, account: &str) -> Result<(), Error> { + let driver = *self.value(); + update_oracle( + driver.chain_id.as_str(), + &driver.command_path, + &driver.home_path, + &driver.rpc_listen_address(), + account, + relayer, + ) + } + + fn async_icq(&self, channel_id: &ChannelId, query_json: &str, from: &str) -> Result<(), Error> { + let driver = *self.value(); + async_icq( + driver.chain_id.as_str(), + &driver.command_path, + &driver.home_path, + &driver.rpc_listen_address(), + channel_id.as_str(), + query_json, + from, + ) + } +} diff --git a/tools/test-framework/src/chain/ext/bootstrap.rs b/tools/test-framework/src/chain/ext/bootstrap.rs index 72fc668e38..37f7818d75 100644 --- a/tools/test-framework/src/chain/ext/bootstrap.rs +++ b/tools/test-framework/src/chain/ext/bootstrap.rs @@ -16,8 +16,8 @@ use crate::chain::cli::bootstrap::{ start_chain, }; use crate::chain::cli::provider::{ - copy_validator_key_pair, query_consumer_genesis, query_consumer_proposal, - replace_genesis_state, submit_consumer_chain_proposal, + copy_validator_key_pair, query_consumer_genesis, query_gov_proposal, replace_genesis_state, + submit_consumer_chain_proposal, }; use crate::chain::driver::ChainDriver; use crate::chain::exec::simple_exec; @@ -26,6 +26,7 @@ use crate::ibc::token::Token; use crate::prelude::assert_eventually_succeed; use crate::types::process::ChildProcess; use crate::types::wallet::{Wallet, WalletAddress, WalletId}; +use crate::util::proposal_status::ProposalStatus; pub trait ChainBootstrapMethodsExt { /** @@ -110,25 +111,16 @@ pub trait ChainBootstrapMethodsExt { ) -> Result<(), Error>; /** - Assert that the consumer chain proposal is eventually submitted. + Assert that the proposal is eventually in the desired state. */ - fn assert_consumer_chain_proposal_submitted( - &self, - chain_id: &str, - command_path: &str, - home_path: &str, - rpc_listen_address: &str, - ) -> Result<(), Error>; - - /** - Assert that the consumer chain proposal eventually passes. - */ - fn assert_consumer_chain_proposal_passed( + fn assert_proposal_status( &self, chain_id: &str, command_path: &str, home_path: &str, rpc_listen_address: &str, + status: ProposalStatus, + proposal_id: &str, ) -> Result<(), Error>; /** @@ -330,66 +322,59 @@ impl ChainBootstrapMethodsExt for ChainDriver { ) } - fn assert_consumer_chain_proposal_submitted( + fn assert_proposal_status( &self, chain_id: &str, command_path: &str, home_path: &str, rpc_listen_address: &str, + status: ProposalStatus, + proposal_id: &str, ) -> Result<(), Error> { assert_eventually_succeed( - "consumer chain proposal submitted", + &format!("proposal `{}` status: {}", proposal_id, status.as_str()), 10, - Duration::from_secs(1), - || { - match query_consumer_proposal(chain_id, command_path, home_path, rpc_listen_address) { - Ok(exec_output) => { - let json_res = json::from_str::(&exec_output.stdout).map_err(handle_generic_error)?; - let proposal_status = json_res.get("status") + Duration::from_secs(2), + || match query_gov_proposal( + chain_id, + command_path, + home_path, + rpc_listen_address, + proposal_id, + ) { + Ok(exec_output) => { + let json_res = json::from_str::(&exec_output.stdout) + .map_err(handle_generic_error)?; + // Cosmos SDK v0.50.1 outputs the status of the proposal using an integer code + let proposal_status: ProposalStatus = match json_res.get("proposal") { + Some(proposal_status) => proposal_status + .get("status") + .ok_or_else(|| eyre!("expected `status` field"))? + .try_into()?, + None => json_res + .get("status") .ok_or_else(|| eyre!("expected `status` field"))? - .as_str() - .ok_or_else(|| eyre!("expected string field"))?; - if proposal_status == "PROPOSAL_STATUS_VOTING_PERIOD" { - Ok(()) - } else { - Err(Error::generic(eyre!("consumer chain proposal is not in voting period. Proposal status: {proposal_status}"))) - } - }, - Err(e) => Err(Error::generic(eyre!("Error querying the consumer chain proposal. Potential issues could be due to not using enough gas or the proposal submitted is invalid. Error: {e}"))), + .try_into()?, + }; + + if proposal_status == status { + Ok(()) + } else { + Err(Error::generic(eyre!( + "proposal is not in `{}`. Proposal status: {}", + status.as_str(), + proposal_status.as_str() + ))) + } } - }, - )?; - Ok(()) - } - - fn assert_consumer_chain_proposal_passed( - &self, - chain_id: &str, - command_path: &str, - home_path: &str, - rpc_listen_address: &str, - ) -> Result<(), Error> { - assert_eventually_succeed( - "consumer chain proposal passed", - 10, - Duration::from_secs(5), - || { - match query_consumer_proposal(chain_id, command_path, home_path, rpc_listen_address) { - Ok(exec_output) => { - let json_res = json::from_str::(&exec_output.stdout).map_err(handle_generic_error)?; - let proposal_status = json_res.get("status") - .ok_or_else(|| eyre!("expected `status` field"))? - .as_str() - .ok_or_else(|| eyre!("expected string field"))?; - - if proposal_status == "PROPOSAL_STATUS_PASSED" { - Ok(()) - } else { - Err(Error::generic(eyre!("consumer chain proposal has not passed. Proposal status: {proposal_status}"))) - } - }, - Err(e) => Err(Error::generic(eyre!("Error querying the consumer chain proposal. Potential issues could be due to not using enough gas or the proposal submitted is invalid. Error: {e}"))), + Err(e) => { + let msg = e.to_string(); + if msg.contains(&format!("status:{}", status.as_str())) { + Ok(()) + } else { + Err(Error::generic(eyre!("Error querying proposal `{proposal_id}`. Potential issues could be due to not using enough gas or the proposal submitted is invalid. Error: {e}"))) } + } }, )?; Ok(()) diff --git a/tools/test-framework/src/chain/ext/fee_grant.rs b/tools/test-framework/src/chain/ext/fee_grant.rs index 15cdcd5c4d..ca8dcb156e 100644 --- a/tools/test-framework/src/chain/ext/fee_grant.rs +++ b/tools/test-framework/src/chain/ext/fee_grant.rs @@ -1,13 +1,23 @@ use crate::chain::cli::fee_grant::feegrant_grant; use crate::error::Error; -use crate::prelude::ChainDriver; +use crate::prelude::{ChainDriver, TaggedTokenRef}; use crate::types::tagged::MonoTagged; pub trait FeeGrantMethodsExt { - fn feegrant_grant(&self, granter: &str, grantee: &str) -> Result<(), Error>; + fn feegrant_grant( + &self, + granter: &str, + grantee: &str, + fees: &TaggedTokenRef, + ) -> Result<(), Error>; } impl<'a, Chain: Send> FeeGrantMethodsExt for MonoTagged { - fn feegrant_grant(&self, granter: &str, grantee: &str) -> Result<(), Error> { + fn feegrant_grant( + &self, + granter: &str, + grantee: &str, + fees: &TaggedTokenRef, + ) -> Result<(), Error> { feegrant_grant( self.value().chain_id.as_str(), &self.value().command_path, @@ -15,6 +25,7 @@ impl<'a, Chain: Send> FeeGrantMethodsExt for MonoTagged { + let upgrade_plan = MsgIbcSoftwareUpgrade::decode(&proposal_content.value as &[u8]) + .map_err(handle_generic_error)?; + + let plan = upgrade_plan + .plan + .ok_or_else(|| eyre!("failed to plan from MsgIbcSoftwareUpgrade"))?; + + plan.height as u64 + } + "/ibc.core.client.v1.UpgradeProposal" => { + let upgrade_plan = UpgradeProposal::decode(&proposal_content.value as &[u8]) + .map_err(handle_generic_error)?; - let upgrade_plan = - UpgradeProposal::decode(&proposal_content.value as &[u8]).map_err(handle_generic_error)?; + let plan = upgrade_plan + .plan + .ok_or_else(|| eyre!("failed to plan from MsgIbcSoftwareUpgrade"))?; - let plan = upgrade_plan - .plan - .ok_or_else(|| eyre!("failed to plan from UpgradeProposal"))?; + plan.height as u64 + } + _ => { + return Err(Error::incorrect_proposal_type_url( + proposal_content.type_url, + )) + } + }; - Ok(plan.height as u64) + Ok(height) } diff --git a/tools/test-framework/src/chain/ext/transfer.rs b/tools/test-framework/src/chain/ext/transfer.rs index 58b85ccc46..94707ff8da 100644 --- a/tools/test-framework/src/chain/ext/transfer.rs +++ b/tools/test-framework/src/chain/ext/transfer.rs @@ -80,6 +80,7 @@ pub trait ChainTransferMethodsExt { port: &PortId, channel: &ChannelId, token: &TaggedTokenRef, + fees: &TaggedTokenRef, timeout_height: &Height, ) -> Result<(), Error>; } @@ -180,6 +181,7 @@ impl<'a, Chain: Send> ChainTransferMethodsExt for MonoTagged, + fees: &TaggedTokenRef, timeout_height: &Height, ) -> Result<(), Error> { let driver = *self.value(); @@ -194,6 +196,7 @@ impl<'a, Chain: Send> ChainTransferMethodsExt for MonoTagged { ) -> Result<(), Error>; /** - Taggged version of [`query_recipient_transactions`]. + Tagged version of [`query_recipient_transactions`]. Query for the transactions related to a wallet on `Chain` receiving token transfer from others. @@ -79,6 +81,13 @@ pub trait TaggedChainDriverExt { &self, recipient_address: &MonoTagged, ) -> Result; + + /** + Tagged version of [`query_auth_module`]. + + Query for the authority account for a specific module. + */ + fn query_auth_module(&self, module_name: &str) -> Result; } impl<'a, Chain: Send> TaggedChainDriverExt for MonoTagged { @@ -98,7 +107,7 @@ impl<'a, Chain: Send> TaggedChainDriverExt for MonoTagged TaggedChainDriverExt for MonoTagged Result { + let driver = *self.value(); + query_auth_module( + driver.chain_id.as_str(), + &driver.command_path, + &driver.home_path, + &driver.rpc_listen_address(), + module_name, + ) + } } diff --git a/tools/test-framework/src/docs/walkthroughs/ordered_channel.rs b/tools/test-framework/src/docs/walkthroughs/ordered_channel.rs index c4ef2c4616..36c04807a6 100644 --- a/tools/test-framework/src/docs/walkthroughs/ordered_channel.rs +++ b/tools/test-framework/src/docs/walkthroughs/ordered_channel.rs @@ -135,7 +135,7 @@ //! The logic of the test itself is defined in the `run` function of the //! `BinaryChannelTest` trait. In this function, we first set up the two wallets, //! the sending wallet, `wallet_a`, which is associated with chain A, and the -//! receiving wallet, `wallet_b`, which is associated iwth chain B. The balance +//! receiving wallet, `wallet_b`, which is associated with chain B. The balance //! of `wallet_a` is also saved. An IBC transfer is then made from chain A to chain //! B. At this point, because no relayer has been initialized yet, the transaction //! is in a pending state. diff --git a/tools/test-framework/src/docs/walkthroughs/simple.rs b/tools/test-framework/src/docs/walkthroughs/simple.rs index bd7b8d0bf2..18c3d8a5a9 100644 --- a/tools/test-framework/src/docs/walkthroughs/simple.rs +++ b/tools/test-framework/src/docs/walkthroughs/simple.rs @@ -45,7 +45,7 @@ //! //! This example tests showcases implementing the `TestOverrides` trait, which is used to set //! configuration and initialization values for the relayer instance that is being tested (in -//! this case though, nothing is being overriden). +//! this case though, nothing is being overridden). //! //! The main logic of the test is implemented in the `run` function of the `BinaryChannelTest` //! trait. This trait is implemented for our empty test struct since we're choosing to run a diff --git a/tools/test-framework/src/error.rs b/tools/test-framework/src/error.rs index 8a0fb932e1..d438f88bd9 100644 --- a/tools/test-framework/src/error.rs +++ b/tools/test-framework/src/error.rs @@ -65,7 +65,7 @@ define_error! { } | e | { format_args!( - "Expected task to eventually succeeed, but failed after {} attempts: {}", + "Expected task to eventually succeed, but failed after {} attempts: {}", e.attempts, e.task_name ) @@ -87,7 +87,7 @@ define_error! { IncorrectProposalTypeUrl { type_url: String } - | e | format_args!("expected /ibc.core.client.v1.UpgradeProposal but got {}", e.type_url), + | e | format_args!("expected /ibc.core.client.v1.UpgradeProposal or /ibc.core.client.v1.MsgIBCSoftwareUpgrade but got {}", e.type_url), EmptyProposal | _ | { "the Proposal content is empty" }, diff --git a/tools/test-framework/src/framework/binary/ics.rs b/tools/test-framework/src/framework/binary/ics.rs index 8287353872..8125a541f9 100644 --- a/tools/test-framework/src/framework/binary/ics.rs +++ b/tools/test-framework/src/framework/binary/ics.rs @@ -11,6 +11,7 @@ use crate::framework::base::{run_basic_test, BasicTest, HasOverrides, TestConfig use crate::framework::binary::node::{NodeConfigOverride, NodeGenesisOverride}; use crate::prelude::FullNode; use crate::types::config::TestConfig; +use crate::util::proposal_status::ProposalStatus; /** Runs a test case that implements [`InterchainSecurityChainTest`]. @@ -63,6 +64,8 @@ where |genesis| self.test.get_overrides().modify_genesis_file(genesis), 0, )?; + let provider_native_token = builder.native_tokens[0].clone(); + let provider_fee = format!("1200{}", provider_native_token); // Get consumer chain id let chain_type = ChainType::from_str(&builder.command_paths[1])?; @@ -72,28 +75,30 @@ where .chain_driver .submit_consumer_chain_proposal(chain_id.as_str(), "2023-05-31T12:09:47.048227Z")?; - node_a - .chain_driver - .assert_consumer_chain_proposal_submitted( - node_a.chain_driver.chain_id.as_str(), - &node_a.chain_driver.command_path, - &node_a.chain_driver.home_path, - &node_a.chain_driver.rpc_listen_address(), - )?; + node_a.chain_driver.assert_proposal_status( + node_a.chain_driver.chain_id.as_str(), + &node_a.chain_driver.command_path, + &node_a.chain_driver.home_path, + &node_a.chain_driver.rpc_listen_address(), + ProposalStatus::VotingPeriod, + "1", + )?; vote_proposal( node_a.chain_driver.chain_id.as_str(), &node_a.chain_driver.command_path, &node_a.chain_driver.home_path, &node_a.chain_driver.rpc_listen_address(), - "1200stake", + &provider_fee, )?; - node_a.chain_driver.assert_consumer_chain_proposal_passed( + node_a.chain_driver.assert_proposal_status( node_a.chain_driver.chain_id.as_str(), &node_a.chain_driver.command_path, &node_a.chain_driver.home_path, &node_a.chain_driver.rpc_listen_address(), + ProposalStatus::Passed, + "1", )?; let node_b = bootstrap_consumer_node( diff --git a/tools/test-framework/src/framework/nary/chain.rs b/tools/test-framework/src/framework/nary/chain.rs index 540e71d12d..392114cc5e 100644 --- a/tools/test-framework/src/framework/nary/chain.rs +++ b/tools/test-framework/src/framework/nary/chain.rs @@ -55,7 +55,7 @@ where /** Runs a test case that implements [`NaryChainTest`], with one self-connected chain used - to emulate many connnections. + to emulate many connections. This works because IBC allows a chain to connect back to itself without the chain knowing it. Using this, we can emulate N-ary chain tests using only one chain diff --git a/tools/test-framework/src/relayer/chain.rs b/tools/test-framework/src/relayer/chain.rs index f4913315ec..a5c9fac652 100644 --- a/tools/test-framework/src/relayer/chain.rs +++ b/tools/test-framework/src/relayer/chain.rs @@ -9,7 +9,7 @@ This is the case for creating N-ary chains, because we cannot rely on the existential type encapsulation of `impl ChainHandle` to turn the [`CountingAndCachingChainHandle`](ibc_relayer::chain::handle::CountingAndCachingChainHandle) to turn - them into unqiue types. + them into unique types. A workaround for this is to add a unique tag to `CountingAndCachingChainHandle` itself, so that the type `MonoTagged` becomes a unique chain @@ -21,6 +21,7 @@ */ use crossbeam_channel as channel; +use ibc_relayer::chain::cosmos::version::Specs; use tracing::Span; use ibc_proto::ibc::apps::fee::v1::{ @@ -40,10 +41,10 @@ use ibc_relayer::denom::DenomTrace; use ibc_relayer::error::Error; use ibc_relayer::event::IbcEventWithHeight; use ibc_relayer::keyring::AnySigningKeyPair; -use ibc_relayer::light_client::AnyHeader; use ibc_relayer::misbehaviour::MisbehaviourEvidence; use ibc_relayer_types::applications::ics31_icq::response::CrossChainQueryResponse; use ibc_relayer_types::core::ics02_client::events::UpdateClient; +use ibc_relayer_types::core::ics02_client::header::AnyHeader; use ibc_relayer_types::core::ics03_connection::connection::ConnectionEnd; use ibc_relayer_types::core::ics03_connection::connection::IdentifiedConnectionEnd; use ibc_relayer_types::core::ics03_connection::version::Version; @@ -121,8 +122,8 @@ where self.value().add_key(key_name, key) } - fn ibc_version(&self) -> Result, Error> { - self.value().ibc_version() + fn version_specs(&self) -> Result { + self.value().version_specs() } fn query_application_status(&self) -> Result { @@ -430,4 +431,8 @@ where ) -> Result { self.value().query_incentivized_packet(request) } + + fn query_consumer_chains(&self) -> Result, Error> { + self.value().query_consumer_chains() + } } diff --git a/tools/test-framework/src/relayer/channel.rs b/tools/test-framework/src/relayer/channel.rs index 5dc01da72d..391a3b10f7 100644 --- a/tools/test-framework/src/relayer/channel.rs +++ b/tools/test-framework/src/relayer/channel.rs @@ -2,6 +2,7 @@ use core::time::Duration; use eyre::eyre; use ibc_relayer::chain::handle::ChainHandle; use ibc_relayer::chain::requests::{IncludeProof, QueryChannelRequest, QueryHeight}; +use ibc_relayer::channel::version::Version; use ibc_relayer::channel::{extract_channel_id, Channel, ChannelSide}; use ibc_relayer_types::core::ics04_channel::channel::State as ChannelState; use ibc_relayer_types::core::ics04_channel::channel::{ChannelEnd, IdentifiedChannelEnd, Ordering}; @@ -71,6 +72,45 @@ pub fn init_channel( Ok((DualTagged::new(channel_id), channel2)) } +pub fn init_channel_version( + handle_a: &ChainA, + handle_b: &ChainB, + client_id_a: &TaggedClientIdRef, + client_id_b: &TaggedClientIdRef, + connection_id_a: &TaggedConnectionIdRef, + connection_id_b: &TaggedConnectionIdRef, + src_port_id: &TaggedPortIdRef, + dst_port_id: &TaggedPortIdRef, + version: Version, +) -> Result<(TaggedChannelId, Channel), Error> { + let channel = Channel { + connection_delay: Default::default(), + ordering: Ordering::Unordered, + a_side: ChannelSide::new( + handle_a.clone(), + client_id_a.cloned_value(), + connection_id_a.cloned_value(), + src_port_id.cloned_value(), + None, + Some(version.clone()), + ), + b_side: ChannelSide::new( + handle_b.clone(), + client_id_b.cloned_value(), + connection_id_b.cloned_value(), + dst_port_id.cloned_value(), + None, + Some(version), + ), + }; + + let event = channel.build_chan_open_init_and_send()?; + let channel_id = extract_channel_id(&event)?.clone(); + let channel2 = Channel::restore_from_event(handle_b.clone(), handle_a.clone(), event)?; + + Ok((DualTagged::new(channel_id), channel2)) +} + pub fn init_channel_optimistic( handle_a: &ChainA, handle_b: &ChainB, @@ -176,7 +216,7 @@ pub fn assert_eventually_channel_established, diff --git a/tools/test-framework/src/relayer/transfer.rs b/tools/test-framework/src/relayer/transfer.rs index c767d24d36..26595051a5 100644 --- a/tools/test-framework/src/relayer/transfer.rs +++ b/tools/test-framework/src/relayer/transfer.rs @@ -72,7 +72,7 @@ pub fn build_transfer_message( for testing. During test, all chains should have the same local clock. We are also not really interested in setting a timeout for most tests, so we just put an approximate 1 minute timeout as the timeout - field is compulsary, and we want to avoid IBC timeout on CI. + field is compulsory, and we want to avoid IBC timeout on CI. The other reason we do not allow precise timeout to be specified is because it requires accessing the counterparty chain to query for diff --git a/tools/test-framework/src/relayer/tx.rs b/tools/test-framework/src/relayer/tx.rs index 5fda1813fd..94a8d8cf80 100644 --- a/tools/test-framework/src/relayer/tx.rs +++ b/tools/test-framework/src/relayer/tx.rs @@ -13,10 +13,18 @@ use tendermint_rpc::Url; use crate::error::{handle_generic_error, Error}; -pub fn gas_config_for_test() -> GasConfig { +pub fn gas_config_for_test(native_token: String) -> GasConfig { let max_gas = 3000000; - let gas_multiplier = 1.1; - let gas_price = GasPrice::new(0.003, "stake".to_string()); + let gas_multiplier = 1.5; + + // Provenance requires a high gas price + let price = if native_token == "nhash" { + 5000.0 + } else { + 0.003 + }; + + let gas_price = GasPrice::new(price, native_token); let default_gas = max_gas; let fee_granter = "".to_string(); @@ -43,10 +51,11 @@ pub fn new_tx_config_for_test( raw_rpc_address: String, raw_grpc_address: String, address_type: AddressType, + native_token: String, ) -> Result { let rpc_address = Url::from_str(&raw_rpc_address).map_err(handle_generic_error)?; let grpc_address = Uri::from_str(&raw_grpc_address).map_err(handle_generic_error)?; - let gas_config = gas_config_for_test(); + let gas_config = gas_config_for_test(native_token); let rpc_timeout = Duration::from_secs(30); let max_msg_num = Default::default(); let max_tx_size = Default::default(); diff --git a/tools/test-framework/src/types/binary/chains.rs b/tools/test-framework/src/types/binary/chains.rs index 1f00577603..f195866e17 100644 --- a/tools/test-framework/src/types/binary/chains.rs +++ b/tools/test-framework/src/types/binary/chains.rs @@ -159,7 +159,7 @@ impl ExportEnv for ConnectedChains, + pub native_tokens: Vec, + + pub compat_modes: Option>, + /** The directory path for storing the chain and relayer files. Defaults to `"data"`. This can be overridden with the `$CHAIN_STORE_DIR` diff --git a/tools/test-framework/src/types/id.rs b/tools/test-framework/src/types/id.rs index 8d5884aa8a..d103a7ab5b 100644 --- a/tools/test-framework/src/types/id.rs +++ b/tools/test-framework/src/types/id.rs @@ -37,7 +37,7 @@ pub type TaggedClientIdRef<'a, ChainA, ChainB> = DualTagged = DualTagged; /** - A reference to [`PortId`](PortId) tagged with first, the host chain + A reference to [`PortId`] tagged with first, the host chain that has the port ID, and second, the counterparty chain that the port ID corresponds to. */ diff --git a/tools/test-framework/src/types/nary/mod.rs b/tools/test-framework/src/types/nary/mod.rs index 04bc360fd2..28fea7b782 100644 --- a/tools/test-framework/src/types/nary/mod.rs +++ b/tools/test-framework/src/types/nary/mod.rs @@ -55,7 +55,7 @@ [`NthChainHandle`](aliases::NthChainHandle) and [`NthForeignClient`](foreign_client::NthForeignClient). This would still result in overly verbose messages in type errors involving - these types. If necessary, we will refactor these defintions as newtypes + these types. If necessary, we will refactor these definitions as newtypes so that they can be used and shown in a cleaner form. */ diff --git a/tools/test-framework/src/types/single/node.rs b/tools/test-framework/src/types/single/node.rs index a7c9675521..56ed9c0d1a 100644 --- a/tools/test-framework/src/types/single/node.rs +++ b/tools/test-framework/src/types/single/node.rs @@ -6,8 +6,9 @@ use core::str::FromStr; use core::time::Duration; use eyre::eyre; use eyre::Report as Error; -use ibc_relayer::chain::ChainType; +use ibc_relayer::chain::cosmos::config::CosmosSdkConfig; use ibc_relayer::config; +use ibc_relayer::config::compat_mode::CompatMode; use ibc_relayer::config::gas_multiplier::GasMultiplier; use ibc_relayer::keyring::Store; use ibc_relayer_types::core::ics24_host::identifier::ChainId; @@ -126,7 +127,9 @@ impl FullNode { &self, chain_type: &TestedChainType, test_config: &TestConfig, + chain_number: usize, ) -> Result { + let native_token_number = chain_number % test_config.native_tokens.len(); let hermes_keystore_dir = test_config .chain_store_dir .join("hermes_keyring") @@ -134,9 +137,25 @@ impl FullNode { .display() .to_string(); - Ok(config::ChainConfig { + let compat_mode = test_config.compat_modes.as_ref().map(|modes| { + let mode = &modes[chain_number % modes.len()]; + CompatMode::from_str(mode).unwrap() + }); + + // Provenance requires a very high gas price + let gas_price = match chain_type { + TestedChainType::Provenance => config::GasPrice::new( + 5000.0, + test_config.native_tokens[native_token_number].clone(), + ), + _ => config::GasPrice::new( + 0.003, + test_config.native_tokens[native_token_number].clone(), + ), + }; + + Ok(config::ChainConfig::CosmosSdk(CosmosSdkConfig { id: self.chain_driver.chain_id.clone(), - r#type: ChainType::CosmosSdk, rpc_addr: Url::from_str(&self.chain_driver.rpc_address())?, grpc_addr: Url::from_str(&self.chain_driver.grpc_address())?, event_source: config::EventSourceMode::Push { @@ -154,7 +173,7 @@ impl FullNode { default_gas: None, max_gas: Some(3000000), gas_adjustment: None, - gas_multiplier: Some(GasMultiplier::unsafe_new(1.2)), + gas_multiplier: Some(GasMultiplier::unsafe_new(1.5)), fee_granter: None, max_msg_num: Default::default(), max_tx_size: Default::default(), @@ -165,14 +184,16 @@ impl FullNode { client_refresh_rate: config::default::client_refresh_rate(), ccv_consumer_chain: false, trust_threshold: Default::default(), - gas_price: config::GasPrice::new(0.003, "stake".to_string()), + gas_price, packet_filter: Default::default(), address_type: chain_type.address_type(), memo_prefix: Default::default(), proof_specs: Default::default(), extension_options: Default::default(), sequential_batch_tx: false, - }) + compat_mode, + clear_interval: None, + })) } /** diff --git a/tools/test-framework/src/util/interchain_security.rs b/tools/test-framework/src/util/interchain_security.rs index ab7d4e8254..035efb3c84 100644 --- a/tools/test-framework/src/util/interchain_security.rs +++ b/tools/test-framework/src/util/interchain_security.rs @@ -1,3 +1,5 @@ +use ibc_relayer::config::ChainConfig; + use crate::chain::config::set_voting_period; use crate::prelude::*; @@ -8,7 +10,7 @@ pub fn update_genesis_for_consumer_chain(genesis: &mut serde_json::Value) -> Res .and_then(|app_state| app_state.get("gov")) .is_some() { - set_voting_period(genesis, "10s")?; + set_voting_period(genesis, 10)?; } Ok(()) } @@ -19,9 +21,14 @@ pub fn update_relayer_config_for_consumer_chain(config: &mut Config) { // specified in the Consumer chain proposal. The test framework uses 100s in // the proposal. for chain_config in config.chains.iter_mut() { - if chain_config.id == ChainId::from_string("ibcconsumer") { - chain_config.ccv_consumer_chain = true; - chain_config.trusting_period = Some(Duration::from_secs(99)); + match chain_config { + ChainConfig::CosmosSdk(chain_config) + if chain_config.id == ChainId::from_string("ibcconsumer") => + { + chain_config.ccv_consumer_chain = true; + chain_config.trusting_period = Some(Duration::from_secs(99)); + } + ChainConfig::CosmosSdk(_) => {} } } } diff --git a/tools/test-framework/src/util/mod.rs b/tools/test-framework/src/util/mod.rs index bb1d92e67e..8fcd82a5dc 100644 --- a/tools/test-framework/src/util/mod.rs +++ b/tools/test-framework/src/util/mod.rs @@ -6,6 +6,7 @@ pub mod array; pub mod assert; pub mod file; pub mod interchain_security; +pub mod proposal_status; pub mod random; pub mod retry; pub mod suspend; diff --git a/tools/test-framework/src/util/proposal_status.rs b/tools/test-framework/src/util/proposal_status.rs new file mode 100644 index 0000000000..5c1e63df5e --- /dev/null +++ b/tools/test-framework/src/util/proposal_status.rs @@ -0,0 +1,80 @@ +use serde_json::Value; +use std::str::FromStr; + +use crate::prelude::*; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum ProposalStatus { + Unspecified = 0, + DepositPeriod = 1, + VotingPeriod = 2, + Passed = 3, + Rejected = 4, + Failed = 5, +} + +impl TryFrom for ProposalStatus { + type Error = Error; + + fn try_from(value: i64) -> Result { + match value { + 0 => Ok(Self::Unspecified), + 1 => Ok(Self::DepositPeriod), + 2 => Ok(Self::VotingPeriod), + 3 => Ok(Self::Passed), + 4 => Ok(Self::Rejected), + 5 => Ok(Self::Failed), + _ => Err(Error::generic(eyre!( + "unknown value for proposal status: `{value}`" + ))), + } + } +} + +impl FromStr for ProposalStatus { + type Err = Error; + + fn from_str(s: &str) -> Result { + match s { + "PROPOSAL_STATUS_UNSPECIFIED" => Ok(Self::Unspecified), + "PROPOSAL_STATUS_DEPOSIT_PERIOD" => Ok(Self::DepositPeriod), + "PROPOSAL_STATUS_VOTING_PERIOD" => Ok(Self::VotingPeriod), + "PROPOSAL_STATUS_PASSED" => Ok(Self::Passed), + "PROPOSAL_STATUS_REJECTED" => Ok(Self::Rejected), + "PROPOSAL_STATUS_FAILED" => Ok(Self::Failed), + _ => Err(Error::generic(eyre!( + "unknown value for proposal status: `{s}`" + ))), + } + } +} + +impl ProposalStatus { + pub fn as_str(&self) -> &'static str { + match self { + Self::Unspecified => "PROPOSAL_STATUS_UNSPECIFIED", + Self::DepositPeriod => "PROPOSAL_STATUS_DEPOSIT_PERIOD", + Self::VotingPeriod => "PROPOSAL_STATUS_VOTING_PERIOD", + Self::Passed => "PROPOSAL_STATUS_PASSED", + Self::Rejected => "PROPOSAL_STATUS_REJECTED", + Self::Failed => "PROPOSAL_STATUS_FAILED", + } + } +} + +impl TryFrom<&Value> for ProposalStatus { + type Error = Error; + + fn try_from(value: &Value) -> Result { + if let Some(numeric_value) = value.as_i64() { + ProposalStatus::try_from(numeric_value) + } else { + // If .to_string() is used directly on a serde_json::Value the double quotes are kept in the string. + // Example: would result in `\"PROPOSAL_STATUS_VOTING_PERIOD\"` instead of `PROPOSAL_STATUS_VOTING_PERIOD` + let str_value = value + .as_str() + .ok_or_else(|| eyre!("error converting value to str: `{value}`"))?; + ProposalStatus::from_str(str_value) + } + } +} diff --git a/tools/test-framework/src/util/suspend.rs b/tools/test-framework/src/util/suspend.rs index 40272c7e26..edd6adca5e 100644 --- a/tools/test-framework/src/util/suspend.rs +++ b/tools/test-framework/src/util/suspend.rs @@ -52,12 +52,12 @@ pub fn hang_on_error( } Ok(Err(e)) => { if hang_on_fail { - error!("test failure occured with HANG_ON_FAIL=1, suspending the test to allow debugging: {:?}", + error!("test failure occurred with HANG_ON_FAIL=1, suspending the test to allow debugging: {:?}", e); suspend() } else { - error!("test failure occured. set HANG_ON_FAIL=1 to suspend the test on failure for debugging: {:?}", + error!("test failure occurred. set HANG_ON_FAIL=1 to suspend the test on failure for debugging: {:?}", e); Err(e)