diff --git a/.changelog/epilogue.md b/.changelog/epilogue.md index c10d8dd22f..ac2d169412 100644 --- a/.changelog/epilogue.md +++ b/.changelog/epilogue.md @@ -504,7 +504,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]) @@ -642,7 +642,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] @@ -799,7 +799,7 @@ Special thanks to external contributors for this release: @CharlyCst ([#347], [# - 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/.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 deleted file mode 100644 index 601455dec7..0000000000 --- a/.changelog/unreleased/breaking-changes/ibc-relayer-cli/3636-config-chain-type.md +++ /dev/null @@ -1,8 +0,0 @@ -- 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/v0.11.0/improvements/ibc-relayer/1785-clarify-ethermint-keys.md b/.changelog/v0.11.0/improvements/ibc-relayer/1785-clarify-ethermint-keys.md index 94e4e72be4..9f337b3a5a 100644 --- a/.changelog/v0.11.0/improvements/ibc-relayer/1785-clarify-ethermint-keys.md +++ b/.changelog/v0.11.0/improvements/ibc-relayer/1785-clarify-ethermint-keys.md @@ -1,2 +1,2 @@ -- 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/ibc-rs/issues/1785)) \ No newline at end of file diff --git a/.changelog/v0.7.0/summary.md b/.changelog/v0.7.0/summary.md index e098cdbc39..33611b8472 100644 --- a/.changelog/v0.7.0/summary.md +++ b/.changelog/v0.7.0/summary.md @@ -1,3 +1,3 @@ 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. diff --git a/.changelog/v1.10.0/bug-fixes/4034-ensure-no-dropped-events.md b/.changelog/v1.10.0/bug-fixes/4034-ensure-no-dropped-events.md new file mode 100644 index 0000000000..d0943e5245 --- /dev/null +++ b/.changelog/v1.10.0/bug-fixes/4034-ensure-no-dropped-events.md @@ -0,0 +1,3 @@ +- Fix a bug where in some cases, Hermes would drop all events in a + batch that came after an event rejected by the filtering policy + ([\#4034](https://github.com/informalsystems/hermes/issues/4034)) \ No newline at end of file diff --git a/.changelog/v1.10.0/bug-fixes/ibc-relayer/4021-chain-level-ccq-filter.md b/.changelog/v1.10.0/bug-fixes/ibc-relayer/4021-chain-level-ccq-filter.md new file mode 100644 index 0000000000..d3b2c7f51f --- /dev/null +++ b/.changelog/v1.10.0/bug-fixes/ibc-relayer/4021-chain-level-ccq-filter.md @@ -0,0 +1,2 @@ +- Discard CrossChain queries intended for unconfigured chains. + ([\#4021](https://github.com/informalsystems/hermes/issues/4021)) \ No newline at end of file diff --git a/.changelog/v1.10.0/features/ibc-integration-test/4046-test-authz.md b/.changelog/v1.10.0/features/ibc-integration-test/4046-test-authz.md new file mode 100644 index 0000000000..3082b737f2 --- /dev/null +++ b/.changelog/v1.10.0/features/ibc-integration-test/4046-test-authz.md @@ -0,0 +1,3 @@ +- Add tests to ensure that Hermes correctly relays transfer messages + from a grantee address with granted authorisation using `authz` module. + ([\#4046](https://github.com/informalsystems/hermes/issues/4046)) \ No newline at end of file diff --git a/.changelog/v1.10.0/features/ibc-relayer/4040-disable-ics31-icqs.md b/.changelog/v1.10.0/features/ibc-relayer/4040-disable-ics31-icqs.md new file mode 100644 index 0000000000..98ea3ddc6d --- /dev/null +++ b/.changelog/v1.10.0/features/ibc-relayer/4040-disable-ics31-icqs.md @@ -0,0 +1,3 @@ +- Add a new per-chain configuration `allow_ccq` to enable or disable + relaying of ICS31 Cross Chain Query packets. + ([\#4040](https://github.com/informalsystems/hermes/issues/4040)) \ No newline at end of file diff --git a/.changelog/v1.10.0/improvements/ibc-integration-test/4023-update-gaia-to-v17.md b/.changelog/v1.10.0/improvements/ibc-integration-test/4023-update-gaia-to-v17.md new file mode 100644 index 0000000000..4d833215f5 --- /dev/null +++ b/.changelog/v1.10.0/improvements/ibc-integration-test/4023-update-gaia-to-v17.md @@ -0,0 +1,2 @@ +- Update the version of Gaia running the integration tests in the CI from `v15.2.0` + to `v17.2.0` ([\#4023](https://github.com/informalsystems/hermes/issues/4023)) \ No newline at end of file diff --git a/.changelog/v1.10.0/improvements/ibc-integration-test/4024-update-osmosis-to-v25.md b/.changelog/v1.10.0/improvements/ibc-integration-test/4024-update-osmosis-to-v25.md new file mode 100644 index 0000000000..f1cbc137bc --- /dev/null +++ b/.changelog/v1.10.0/improvements/ibc-integration-test/4024-update-osmosis-to-v25.md @@ -0,0 +1,2 @@ +- Update the version of Osmosis running the integration tests in the CI from `v24.0.1` + to `v25.0.0` ([\#4024](https://github.com/informalsystems/hermes/issues/4024)) \ No newline at end of file diff --git a/.changelog/v1.10.0/improvements/ibc-integration-test/4025-update-juno-to-v22.md b/.changelog/v1.10.0/improvements/ibc-integration-test/4025-update-juno-to-v22.md new file mode 100644 index 0000000000..4744857094 --- /dev/null +++ b/.changelog/v1.10.0/improvements/ibc-integration-test/4025-update-juno-to-v22.md @@ -0,0 +1,2 @@ +- Update the version of Juno running the integration tests in the CI from `v21.0.0` + to `v22.0.0` ([\#4025](https://github.com/informalsystems/hermes/issues/4025)) \ No newline at end of file diff --git a/.changelog/v1.10.0/improvements/ibc-integration-test/4026-update-neutron-to-v305.md b/.changelog/v1.10.0/improvements/ibc-integration-test/4026-update-neutron-to-v305.md new file mode 100644 index 0000000000..360d0985eb --- /dev/null +++ b/.changelog/v1.10.0/improvements/ibc-integration-test/4026-update-neutron-to-v305.md @@ -0,0 +1,2 @@ +- Update the version of Neutron running the integration tests in the CI from `v3.0.2` + to `v3.0.5` ([\#4026](https://github.com/informalsystems/hermes/issues/4026)) \ No newline at end of file diff --git a/.changelog/v1.10.0/improvements/ibc-integration-test/4027-update-celestia-to-v1-11.md b/.changelog/v1.10.0/improvements/ibc-integration-test/4027-update-celestia-to-v1-11.md new file mode 100644 index 0000000000..0cd4d5746b --- /dev/null +++ b/.changelog/v1.10.0/improvements/ibc-integration-test/4027-update-celestia-to-v1-11.md @@ -0,0 +1,2 @@ +- Update the version of Celestia app running the integration tests in the CI from `v1.4.0` + to `v1.11.0` ([\#4027](https://github.com/informalsystems/hermes/issues/4027)) \ No newline at end of file diff --git a/.changelog/v1.10.0/improvements/ibc-integration-test/4029-update-wasmd-to-v051.md b/.changelog/v1.10.0/improvements/ibc-integration-test/4029-update-wasmd-to-v051.md new file mode 100644 index 0000000000..d9e00a1898 --- /dev/null +++ b/.changelog/v1.10.0/improvements/ibc-integration-test/4029-update-wasmd-to-v051.md @@ -0,0 +1,2 @@ +- Update the version of `wasmd` running the integration tests in the CI from `v0.50.0` + to `v0.51.0` ([\#4029](https://github.com/informalsystems/hermes/issues/4029)) \ No newline at end of file diff --git a/.changelog/v1.10.0/improvements/ibc-integration-test/4053-reduce-ics29-tests-run-time.md b/.changelog/v1.10.0/improvements/ibc-integration-test/4053-reduce-ics29-tests-run-time.md new file mode 100644 index 0000000000..88e727e88d --- /dev/null +++ b/.changelog/v1.10.0/improvements/ibc-integration-test/4053-reduce-ics29-tests-run-time.md @@ -0,0 +1,4 @@ +- Reduce run time for ICS29 tests by immediately verifying if either + the legacy fees, `recv_fee + ack_fee + timeout_fee` or current + fees, `max(recv_fee + ack_fee, timeout_fee)` have been escrowed. + ([\#4053](https://github.com/informalsystems/hermes/issues/4053)) \ No newline at end of file diff --git a/.changelog/v1.10.0/improvements/ibc-integration-test/4099-specify-topology-for-nary-tests.md b/.changelog/v1.10.0/improvements/ibc-integration-test/4099-specify-topology-for-nary-tests.md new file mode 100644 index 0000000000..b920789213 --- /dev/null +++ b/.changelog/v1.10.0/improvements/ibc-integration-test/4099-specify-topology-for-nary-tests.md @@ -0,0 +1,4 @@ +- Refactored the test-framework bootstrapping for n-ary chain tests + to utilize the specified topology. + * Currently, only linear, cyclic and fully connected topologies are supported. + ([\#4038](https://github.com/informalsystems/hermes/issues/4038)) \ No newline at end of file diff --git a/.changelog/v1.10.0/improvements/ibc-relayer/3979-add-custom-user-agent.md b/.changelog/v1.10.0/improvements/ibc-relayer/3979-add-custom-user-agent.md new file mode 100644 index 0000000000..4854632ae5 --- /dev/null +++ b/.changelog/v1.10.0/improvements/ibc-relayer/3979-add-custom-user-agent.md @@ -0,0 +1,2 @@ +- Use custom User-Agent for Hermes queries + ([\#3979](https://github.com/informalsystems/hermes/issues/3979)) diff --git a/.changelog/v1.10.0/improvements/ibc-relayer/4045-trim-whitespaces-channel-port-filter.md b/.changelog/v1.10.0/improvements/ibc-relayer/4045-trim-whitespaces-channel-port-filter.md new file mode 100644 index 0000000000..8cfcd2c1bc --- /dev/null +++ b/.changelog/v1.10.0/improvements/ibc-relayer/4045-trim-whitespaces-channel-port-filter.md @@ -0,0 +1,5 @@ +- Updated the channel and port filter parsing to ignore whitespaces. + This will prevent unintended channel scanning due to accidental + whitespaces when exact matches are specified in the `packet_filter` + configuration. + ([\#4045](https://github.com/informalsystems/hermes/issues/4045)) \ No newline at end of file diff --git a/.changelog/v1.10.0/improvements/ibc-relayer/4047-improve-excluded-sequences-config.md b/.changelog/v1.10.0/improvements/ibc-relayer/4047-improve-excluded-sequences-config.md new file mode 100644 index 0000000000..19de3111df --- /dev/null +++ b/.changelog/v1.10.0/improvements/ibc-relayer/4047-improve-excluded-sequences-config.md @@ -0,0 +1,11 @@ +- Improve the `excluded_sequences` configuration so that it now accepts + ranges of sequence values in addition to exact values. + Accepted format: + * Exact sequence, e.g. [1, 2, 3] + * "-" separator, e.g. ["1-3"] + + These can be combined making the following configurations equivalent: + * `excluded_sequences = { 'channel-0' = [1, "3-5", 7, "9-12"] }` + * `excluded_sequences = { 'channel-0' = [1, 3, 4, 5, 7, 9, 10, 11, 12] }` + + ([\#4047](https://github.com/informalsystems/hermes/issues/4047)) \ No newline at end of file diff --git a/.changelog/v1.10.0/summary.md b/.changelog/v1.10.0/summary.md new file mode 100644 index 0000000000..8da54c60a8 --- /dev/null +++ b/.changelog/v1.10.0/summary.md @@ -0,0 +1,11 @@ +*June 24th, 2024* + +This release enhances filter configurations and includes the following updates: + +1. `excluded_sequences` supports sequence ranges in addition to exact values, + e.g. `[1, 2, "5-10", 13]` is now valid. +2. `packet_filter` now ignores unintended whitespace. +3. A new `allow_ccq` per-chain configuration has been added to skip the relaying of + ICS31 Cross Chain Queries. + +Additionally, various improvements to testing and bug fixes have been implemented. diff --git a/.changelog/v1.10.1/breaking-changes/4093-update-ibc-proto-and-tendermint-rs.md b/.changelog/v1.10.1/breaking-changes/4093-update-ibc-proto-and-tendermint-rs.md new file mode 100644 index 0000000000..f87427d3a2 --- /dev/null +++ b/.changelog/v1.10.1/breaking-changes/4093-update-ibc-proto-and-tendermint-rs.md @@ -0,0 +1,3 @@ +- Bump version of `ibc-proto` from `v0.46.0` to `v0.47.0` and + version of `tendermint-rs` from `v0.37.0` to `v0.38.1`. + ([\#4093](https://github.com/informalsystems/hermes/issues/4093)) \ No newline at end of file diff --git a/.changelog/v1.10.1/improvements/ibc-integration-test/3195-add-pfm-ica-features-to-osmosis.md b/.changelog/v1.10.1/improvements/ibc-integration-test/3195-add-pfm-ica-features-to-osmosis.md new file mode 100644 index 0000000000..073bd29431 --- /dev/null +++ b/.changelog/v1.10.1/improvements/ibc-integration-test/3195-add-pfm-ica-features-to-osmosis.md @@ -0,0 +1,3 @@ +- Add the features `packet-forward` and `ica` to enable + Packet Forward Middleware and ICA when running tests with Osmosis + ([\#3195](https://github.com/informalsystems/hermes/issues/3195)) \ No newline at end of file diff --git a/.changelog/v1.10.1/improvements/ibc-relayer/4072-packet-clear-logs.md b/.changelog/v1.10.1/improvements/ibc-relayer/4072-packet-clear-logs.md new file mode 100644 index 0000000000..3ed50bd279 --- /dev/null +++ b/.changelog/v1.10.1/improvements/ibc-relayer/4072-packet-clear-logs.md @@ -0,0 +1,6 @@ +- Improve logs when clearing packet. + * When Hermes doesn't pull packet data it will now warn the user + instead of logging `pulled packet data for 0 events out of X` + * When ICS20 packets are filtered due to having a receiver or memo + field too big, the log will be at `warn` level instead of `debug`. + ([\#4072](https://github.com/informalsystems/hermes/issues/4072)) \ No newline at end of file diff --git a/.changelog/v1.10.1/summary.md b/.changelog/v1.10.1/summary.md new file mode 100644 index 0000000000..1d39539dad --- /dev/null +++ b/.changelog/v1.10.1/summary.md @@ -0,0 +1,5 @@ +*July 23th, 2024* + +In this release `tendermint-rs` has been updated to the latest version, addressing issues with the `/block_results` response. This ensures compatibility with CometBFT v0.38.10. + +And enhancements have been made to the logs regarding packet clearing, providing better insights and warnings for users. diff --git a/.changelog/v1.10.2/bug-fixes/ibc-relayer/4104-memo-overwrite-bug.md b/.changelog/v1.10.2/bug-fixes/ibc-relayer/4104-memo-overwrite-bug.md new file mode 100644 index 0000000000..785c896cc6 --- /dev/null +++ b/.changelog/v1.10.2/bug-fixes/ibc-relayer/4104-memo-overwrite-bug.md @@ -0,0 +1,3 @@ +- Fix the `memo_overwrite` configuration to correctly apply the + overwrite if it is configured. + ([\#4104](https://github.com/informalsystems/hermes/issues/4104)) \ No newline at end of file diff --git a/.changelog/v1.10.2/bug-fixes/ibc-telemetry/4145-fix-dynamic-gas-price-metric-name.md b/.changelog/v1.10.2/bug-fixes/ibc-telemetry/4145-fix-dynamic-gas-price-metric-name.md new file mode 100644 index 0000000000..fc0b9f836c --- /dev/null +++ b/.changelog/v1.10.2/bug-fixes/ibc-telemetry/4145-fix-dynamic-gas-price-metric-name.md @@ -0,0 +1,3 @@ +- Fix the `dynamic_gas_queried_success_fees` Prometheus metric name. + ([\#4104](https://github.com/informalsystems/hermes/issues/4104)) + \ No newline at end of file diff --git a/.changelog/v1.10.2/improvements/ibc-integration-test/4114-update-gaia-to-v18.md b/.changelog/v1.10.2/improvements/ibc-integration-test/4114-update-gaia-to-v18.md new file mode 100644 index 0000000000..eeb9978ca4 --- /dev/null +++ b/.changelog/v1.10.2/improvements/ibc-integration-test/4114-update-gaia-to-v18.md @@ -0,0 +1,2 @@ +- Update the version of Gaia running the integration tests in the CI from `v17.2.1` + to `v18.1.0` ([\#4114](https://github.com/informalsystems/hermes/issues/4114)) \ No newline at end of file diff --git a/.changelog/v1.10.2/improvements/ibc-integration-test/4115-update-provenance-to-v1-19-1.md b/.changelog/v1.10.2/improvements/ibc-integration-test/4115-update-provenance-to-v1-19-1.md new file mode 100644 index 0000000000..f09668d2fc --- /dev/null +++ b/.changelog/v1.10.2/improvements/ibc-integration-test/4115-update-provenance-to-v1-19-1.md @@ -0,0 +1,2 @@ +- Update the version of Provenance running the integration tests in the CI from `v1.17.0` + to `v1.19.1` ([\#4115](https://github.com/informalsystems/hermes/issues/4115)) \ No newline at end of file diff --git a/.changelog/v1.10.2/improvements/ibc-integration-test/4116-update-osmosis-to-v25-2-0.md b/.changelog/v1.10.2/improvements/ibc-integration-test/4116-update-osmosis-to-v25-2-0.md new file mode 100644 index 0000000000..c97282cd12 --- /dev/null +++ b/.changelog/v1.10.2/improvements/ibc-integration-test/4116-update-osmosis-to-v25-2-0.md @@ -0,0 +1,2 @@ +- Update the version of Osmosis running the integration tests in the CI from `v25.0.0` + to `v25.2.0` ([\#4116](https://github.com/informalsystems/hermes/issues/4116)) \ No newline at end of file diff --git a/.changelog/v1.10.2/improvements/ibc-integration-test/4117-update-juno-to-v23.md b/.changelog/v1.10.2/improvements/ibc-integration-test/4117-update-juno-to-v23.md new file mode 100644 index 0000000000..c2f08e7bec --- /dev/null +++ b/.changelog/v1.10.2/improvements/ibc-integration-test/4117-update-juno-to-v23.md @@ -0,0 +1,2 @@ +- Update the version of Juno running the integration tests in the CI from `v22.0.0` + to `v23.0.0` ([\#4117](https://github.com/informalsystems/hermes/issues/4117)) \ No newline at end of file diff --git a/.changelog/v1.10.2/improvements/ibc-integration-test/4118-update-migaloo-to-v4-2-0.md b/.changelog/v1.10.2/improvements/ibc-integration-test/4118-update-migaloo-to-v4-2-0.md new file mode 100644 index 0000000000..772a0edc72 --- /dev/null +++ b/.changelog/v1.10.2/improvements/ibc-integration-test/4118-update-migaloo-to-v4-2-0.md @@ -0,0 +1,2 @@ +- Update the version of Migaloo Chain running the integration tests in the CI from `v4.1.3` + to `v4.2.0` ([\#4118](https://github.com/informalsystems/hermes/issues/4118)) \ No newline at end of file diff --git a/.changelog/v1.10.2/improvements/ibc-integration-test/4120-update-wasmd-to-v0-52.md b/.changelog/v1.10.2/improvements/ibc-integration-test/4120-update-wasmd-to-v0-52.md new file mode 100644 index 0000000000..d281b1a3ee --- /dev/null +++ b/.changelog/v1.10.2/improvements/ibc-integration-test/4120-update-wasmd-to-v0-52.md @@ -0,0 +1,2 @@ +- Update the version of `wasmd` running the integration tests in the CI from `v0.51.0` + to `v0.52.0` ([\#4120](https://github.com/informalsystems/hermes/issues/4120)) \ No newline at end of file diff --git a/.changelog/v1.10.2/improvements/ibc-integration-test/4121-update-stride-to-v23.md b/.changelog/v1.10.2/improvements/ibc-integration-test/4121-update-stride-to-v23.md new file mode 100644 index 0000000000..d867eefd47 --- /dev/null +++ b/.changelog/v1.10.2/improvements/ibc-integration-test/4121-update-stride-to-v23.md @@ -0,0 +1,2 @@ +- Update the version of Stride running the integration tests in the CI from `v21.0.0` + to `v23.0.1` ([\#4121](https://github.com/informalsystems/hermes/issues/4121)) \ No newline at end of file diff --git a/.changelog/v1.10.2/improvements/ibc-integration-test/4122-update-neutron-to-v4.md b/.changelog/v1.10.2/improvements/ibc-integration-test/4122-update-neutron-to-v4.md new file mode 100644 index 0000000000..009d9cc047 --- /dev/null +++ b/.changelog/v1.10.2/improvements/ibc-integration-test/4122-update-neutron-to-v4.md @@ -0,0 +1,2 @@ +- Update the version of Neutron running the integration tests in the CI from `v3.0.5` + to `v4.1.0` ([\#4122](https://github.com/informalsystems/hermes/issues/4122)) \ No newline at end of file diff --git a/.changelog/v1.10.2/improvements/ibc-relayer/4071-split-packet-clear-scheduling.md b/.changelog/v1.10.2/improvements/ibc-relayer/4071-split-packet-clear-scheduling.md new file mode 100644 index 0000000000..8aeec76505 --- /dev/null +++ b/.changelog/v1.10.2/improvements/ibc-relayer/4071-split-packet-clear-scheduling.md @@ -0,0 +1,4 @@ +- Add a new configuration `clear_limit` to specify the maximum number + of packets cleared every time packet clearing is triggered. + Defaults to 50. + ([\#4071](https://github.com/informalsystems/hermes/issues/4071)) \ No newline at end of file diff --git a/.changelog/v1.10.2/improvements/ibc-relayer/4101-add-pagination.md b/.changelog/v1.10.2/improvements/ibc-relayer/4101-add-pagination.md new file mode 100644 index 0000000000..912fdd9733 --- /dev/null +++ b/.changelog/v1.10.2/improvements/ibc-relayer/4101-add-pagination.md @@ -0,0 +1,3 @@ +- Paginate results of `query_packet_commitments` and `query_packet_acknowledgements` + queries to speed up the scanning phase. + ([\#4101](https://github.com/informalsystems/hermes/issues/4101)) \ No newline at end of file diff --git a/.changelog/v1.10.2/improvements/ibc-relayer/4143-use-connection-params-in-validate-params.md b/.changelog/v1.10.2/improvements/ibc-relayer/4143-use-connection-params-in-validate-params.md new file mode 100644 index 0000000000..81073cdfb7 --- /dev/null +++ b/.changelog/v1.10.2/improvements/ibc-relayer/4143-use-connection-params-in-validate-params.md @@ -0,0 +1,4 @@ +- Use the `ibc.core.connection.v1.ConnectionParams` gRPC query to retrieve `maxExpectedTimePerBlock` + and check it against the configured `max_block_time` instead of using the `/genesis` endpoint. + This improves both startup times and reliability for most chains. + ([\#4143](https://github.com/informalsystems/hermes/issues/4143)) \ No newline at end of file diff --git a/.changelog/v1.10.2/summary.md b/.changelog/v1.10.2/summary.md new file mode 100644 index 0000000000..220dccc7e8 --- /dev/null +++ b/.changelog/v1.10.2/summary.md @@ -0,0 +1 @@ +This release brings significant performance improvements and introduces a new configuration options for better control over packet clearing. Enhancements include faster startup times through optimized queries and the introduction of a `clear_limit` setting for packet clearing. Additionally, bug fixes and updates to the integration test framework ensure greater stability and compatibility across various environments. \ No newline at end of file diff --git a/.changelog/v1.10.3/bug-fixes/ibc-chain-registry/4160-explicit-rootls-config.md b/.changelog/v1.10.3/bug-fixes/ibc-chain-registry/4160-explicit-rootls-config.md new file mode 100644 index 0000000000..8bccf778ae --- /dev/null +++ b/.changelog/v1.10.3/bug-fixes/ibc-chain-registry/4160-explicit-rootls-config.md @@ -0,0 +1,2 @@ +- Add explicit root TLS configuration to gRPC clients + ([\#4160](https://github.com/informalsystems/hermes/issues/4160)) \ No newline at end of file diff --git a/.changelog/v1.10.3/bug-fixes/ibc-relayer-cli/3951-exclude-sequences-with-clear-cli.md b/.changelog/v1.10.3/bug-fixes/ibc-relayer-cli/3951-exclude-sequences-with-clear-cli.md new file mode 100644 index 0000000000..aca6d720ec --- /dev/null +++ b/.changelog/v1.10.3/bug-fixes/ibc-relayer-cli/3951-exclude-sequences-with-clear-cli.md @@ -0,0 +1,3 @@ +- Correctly filter out sequences from the `excluded_sequences` configuration + when clearing packets with the `clear packet` CLI. + ([\#4158](https://github.com/informalsystems/hermes/issues/4158)) \ No newline at end of file diff --git a/.changelog/v1.10.3/bug-fixes/ibc-relayer/4160-explicit-rootls-config.md b/.changelog/v1.10.3/bug-fixes/ibc-relayer/4160-explicit-rootls-config.md new file mode 100644 index 0000000000..8bccf778ae --- /dev/null +++ b/.changelog/v1.10.3/bug-fixes/ibc-relayer/4160-explicit-rootls-config.md @@ -0,0 +1,2 @@ +- Add explicit root TLS configuration to gRPC clients + ([\#4160](https://github.com/informalsystems/hermes/issues/4160)) \ No newline at end of file diff --git a/.changelog/v1.10.3/features/ibc-integration-test/4151-add-ibc-go-v9.md b/.changelog/v1.10.3/features/ibc-integration-test/4151-add-ibc-go-v9.md new file mode 100644 index 0000000000..806a0e0372 --- /dev/null +++ b/.changelog/v1.10.3/features/ibc-integration-test/4151-add-ibc-go-v9.md @@ -0,0 +1,2 @@ +- Add ibc-go `v9` to the chains running the integration tests in the CI. + ([\#4151](https://github.com/informalsystems/hermes/issues/4151)) \ No newline at end of file diff --git a/.changelog/v1.10.3/improvements/ibc-integration-test/4123-update-celestia-to-v1-14-0.md b/.changelog/v1.10.3/improvements/ibc-integration-test/4123-update-celestia-to-v1-14-0.md new file mode 100644 index 0000000000..6de196f323 --- /dev/null +++ b/.changelog/v1.10.3/improvements/ibc-integration-test/4123-update-celestia-to-v1-14-0.md @@ -0,0 +1,2 @@ +- Update the version of Celestia running the integration tests in the CI from `v1.11.0` + to `v1.14.0` ([\#4123](https://github.com/informalsystems/hermes/issues/4123)) \ No newline at end of file diff --git a/.changelog/v1.10.3/improvements/ibc-integration-test/4168-update-neutron-v4-2-2.md b/.changelog/v1.10.3/improvements/ibc-integration-test/4168-update-neutron-v4-2-2.md new file mode 100644 index 0000000000..1ca212bf53 --- /dev/null +++ b/.changelog/v1.10.3/improvements/ibc-integration-test/4168-update-neutron-v4-2-2.md @@ -0,0 +1,2 @@ +- Update the version of Neutron running the integration tests in the CI from `v4.1.0` + to `v4.2.2` ([\#4168](https://github.com/informalsystems/hermes/issues/4168)) \ No newline at end of file diff --git a/.changelog/v1.10.3/improvements/ibc-integration-test/4169-update-wasmd-to-v0-53-0.md b/.changelog/v1.10.3/improvements/ibc-integration-test/4169-update-wasmd-to-v0-53-0.md new file mode 100644 index 0000000000..3caa36c8e6 --- /dev/null +++ b/.changelog/v1.10.3/improvements/ibc-integration-test/4169-update-wasmd-to-v0-53-0.md @@ -0,0 +1,2 @@ +- Update the version of `wasmd` running the integration tests in the CI from `v0.52.0` + to `v0.53.0` ([\#4169](https://github.com/informalsystems/hermes/issues/4169)) \ No newline at end of file diff --git a/.changelog/v1.10.3/improvements/ibc-integration-test/4171-update-juno-v24.md b/.changelog/v1.10.3/improvements/ibc-integration-test/4171-update-juno-v24.md new file mode 100644 index 0000000000..e5d46c87f5 --- /dev/null +++ b/.changelog/v1.10.3/improvements/ibc-integration-test/4171-update-juno-v24.md @@ -0,0 +1,2 @@ +- Update the version of Juno running the integration tests in the CI from `v23.0.0` + to `v24.0.0` ([\#4171](https://github.com/informalsystems/hermes/issues/4171)) \ No newline at end of file diff --git a/.changelog/v1.10.3/improvements/ibc-relayer/4102-abci-query-during-health-check.md b/.changelog/v1.10.3/improvements/ibc-relayer/4102-abci-query-during-health-check.md new file mode 100644 index 0000000000..6f2613b12d --- /dev/null +++ b/.changelog/v1.10.3/improvements/ibc-relayer/4102-abci-query-during-health-check.md @@ -0,0 +1,3 @@ +- Use `abci_query` instead of gRPC queries when retrieving staking params + and service config during health-check, and when retrieving version information. + ([\#4102](https://github.com/informalsystems/hermes/issues/4102)) \ No newline at end of file diff --git a/.changelog/v1.10.3/summary.md b/.changelog/v1.10.3/summary.md new file mode 100644 index 0000000000..c7343de8ea --- /dev/null +++ b/.changelog/v1.10.3/summary.md @@ -0,0 +1,5 @@ +*September 2nd, 2024* + +This release fixes an issue where Hermes could not connect to gRPC servers over TLS. Additionally, this release also fixes a bug in the `clear packet` CLI where the `excluded_sequences` configuration option was not always taken into account. + +Furthermore, Hermes now uses `abci_query` instead of gRPC for some queries, for instance for querying staking parameters and service configuration during health checks, and when retrieving version information. diff --git a/.changelog/v1.4.0/summary.md b/.changelog/v1.4.0/summary.md index ab025f4608..e4d1406036 100644 --- a/.changelog/v1.4.0/summary.md +++ b/.changelog/v1.4.0/summary.md @@ -1,16 +1,16 @@ *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. diff --git a/.changelog/v1.7.1/summary.md b/.changelog/v1.7.1/summary.md index 28905e6542..aedd51533f 100644 --- a/.changelog/v1.7.1/summary.md +++ b/.changelog/v1.7.1/summary.md @@ -3,7 +3,7 @@ at a different value for each chain, using the new per-chain `clear_interval` se 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 +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. diff --git a/.changelog/unreleased/breaking-changes/3688-msrv.md b/.changelog/v1.8.0/breaking-changes/3688-msrv.md similarity index 100% rename from .changelog/unreleased/breaking-changes/3688-msrv.md rename to .changelog/v1.8.0/breaking-changes/3688-msrv.md diff --git a/.changelog/unreleased/features/ibc-integration-test/3455-async-icq-test.md b/.changelog/v1.8.0/features/ibc-integration-test/3455-async-icq-test.md similarity index 100% rename from .changelog/unreleased/features/ibc-integration-test/3455-async-icq-test.md rename to .changelog/v1.8.0/features/ibc-integration-test/3455-async-icq-test.md diff --git a/.changelog/unreleased/features/ibc-integration-test/3778-ordered-channel-timeout.md b/.changelog/v1.8.0/features/ibc-integration-test/3778-ordered-channel-timeout.md similarity index 100% rename from .changelog/unreleased/features/ibc-integration-test/3778-ordered-channel-timeout.md rename to .changelog/v1.8.0/features/ibc-integration-test/3778-ordered-channel-timeout.md diff --git a/.changelog/unreleased/features/ibc-relayer-cli/3402-lc-refresh.md b/.changelog/v1.8.0/features/ibc-relayer-cli/3402-lc-refresh.md similarity index 100% rename from .changelog/unreleased/features/ibc-relayer-cli/3402-lc-refresh.md rename to .changelog/v1.8.0/features/ibc-relayer-cli/3402-lc-refresh.md diff --git a/.changelog/unreleased/features/ibc-relayer-cli/3672-clears-packet-seq.md b/.changelog/v1.8.0/features/ibc-relayer-cli/3672-clears-packet-seq.md similarity index 100% rename from .changelog/unreleased/features/ibc-relayer-cli/3672-clears-packet-seq.md rename to .changelog/v1.8.0/features/ibc-relayer-cli/3672-clears-packet-seq.md diff --git a/.changelog/unreleased/features/ibc-relayer-cli/3696-new-chain-upgrade-flag.md b/.changelog/v1.8.0/features/ibc-relayer-cli/3696-new-chain-upgrade-flag.md similarity index 100% rename from .changelog/unreleased/features/ibc-relayer-cli/3696-new-chain-upgrade-flag.md rename to .changelog/v1.8.0/features/ibc-relayer-cli/3696-new-chain-upgrade-flag.md diff --git a/.changelog/unreleased/features/ibc-relayer-cli/3743-query_packets_chunk_size.md b/.changelog/v1.8.0/features/ibc-relayer-cli/3743-query_packets_chunk_size.md similarity index 100% rename from .changelog/unreleased/features/ibc-relayer-cli/3743-query_packets_chunk_size.md rename to .changelog/v1.8.0/features/ibc-relayer-cli/3743-query_packets_chunk_size.md diff --git a/.changelog/unreleased/features/ibc-relayer/3696-new-upgrade-proposal.md b/.changelog/v1.8.0/features/ibc-relayer/3696-new-upgrade-proposal.md similarity index 100% rename from .changelog/unreleased/features/ibc-relayer/3696-new-upgrade-proposal.md rename to .changelog/v1.8.0/features/ibc-relayer/3696-new-upgrade-proposal.md diff --git a/.changelog/v1.8.0/features/ibc-relayer/3738-dynamic-gas-fees.md b/.changelog/v1.8.0/features/ibc-relayer/3738-dynamic-gas-fees.md new file mode 100644 index 0000000000..578056b876 --- /dev/null +++ b/.changelog/v1.8.0/features/ibc-relayer/3738-dynamic-gas-fees.md @@ -0,0 +1,12 @@ +- Add a new per-chain configuration table `dynamic_gas_price` which enables + querying the current gas price from the chain instead of the static `gas_price`, + when the chain has [EIP-1559][eip]-like dynamic gas price. + The new configuration setting can be configured per-chain as follows: + ```toml + dynamic_gas_price = { enabled = true, multiplier = 1.1, max = 0.6 } + ``` + At the moment, only chains which support the `osmosis.txfees.v1beta1.Query/GetEipBaseFee` + query can be used with dynamic gas price enabled. + ([\#3738](https://github.com/informalsystems/hermes/issues/3738)) + +[eip]: https://metamask.io/1559/ diff --git a/.changelog/unreleased/features/ibc-relayer/3766-max-memo-receiver-config.md b/.changelog/v1.8.0/features/ibc-relayer/3766-max-memo-receiver-config.md similarity index 100% rename from .changelog/unreleased/features/ibc-relayer/3766-max-memo-receiver-config.md rename to .changelog/v1.8.0/features/ibc-relayer/3766-max-memo-receiver-config.md diff --git a/.changelog/v1.8.0/features/ibc-telemetry/3738-dynamic-gas-fees-metrics.md b/.changelog/v1.8.0/features/ibc-telemetry/3738-dynamic-gas-fees-metrics.md new file mode 100644 index 0000000000..98a9555967 --- /dev/null +++ b/.changelog/v1.8.0/features/ibc-telemetry/3738-dynamic-gas-fees-metrics.md @@ -0,0 +1,8 @@ +- Add three metrics related to EIP gas price: + - `dynamic_gas_queried_fees` contains data on the queried values + before applying any filter + - `dynamic_gas_queried_success_fees` contains data on the queried + values if the query was successful and before applying any filter + - `dynamic_gas_paid_fees` contains data on the queried values after + applying the `max` filter + ([\#3738](https://github.com/informalsystems/hermes/issues/3738)) \ No newline at end of file diff --git a/.changelog/v1.8.0/features/ibc-telemetry/3794-memo-receiver-filter-metric.md b/.changelog/v1.8.0/features/ibc-telemetry/3794-memo-receiver-filter-metric.md new file mode 100644 index 0000000000..d62c3790a0 --- /dev/null +++ b/.changelog/v1.8.0/features/ibc-telemetry/3794-memo-receiver-filter-metric.md @@ -0,0 +1,3 @@ +- Add a new metric `filtered_packets` which counts the number of + packets filtered due to having a memo or receiver field too big + ([\#3794](https://github.com/informalsystems/hermes/issues/3794)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/ibc-relayer-cli/3745-compat-0.50.md b/.changelog/v1.8.0/improvements/ibc-relayer-cli/3745-compat-0.50.md similarity index 100% rename from .changelog/unreleased/improvements/ibc-relayer-cli/3745-compat-0.50.md rename to .changelog/v1.8.0/improvements/ibc-relayer-cli/3745-compat-0.50.md diff --git a/.changelog/v1.8.0/summary.md b/.changelog/v1.8.0/summary.md new file mode 100644 index 0000000000..7ea70c84de --- /dev/null +++ b/.changelog/v1.8.0/summary.md @@ -0,0 +1,19 @@ +*January 23rd, 2024* + +This v1.8.0 release introduces new features and improvements to Hermes. + +One key feature is that Hermes is now compatible with both the legacy `UpgradeProposal` and the newer `MsgIbcSoftwareUpgrade` message when upgrading a chain. +This allows Hermes to be compatible with ibc-go v8.0.0. The compatibility check that Hermes performs on startup has been updated to reflect this. + +Additional configuration settings have been added: + +- The new global settings `ics20_max_memo_size` and `ics20_max_receiver_size` allow users to specify a limit for the size of the memo and receiver fields for ICS20 packets. Any packet with either field having a size exceeding the configured values will not be relayed. +- The new per-chain setting `query_packets_chunk_size` allows users to specify how many packets are queried at once from the chain when clearing pending packets. This is useful to tweak when there are many large pending packets and the RPC endpoints times out or refuses to answer the pending packets query. +- The new per-chain setting `client_refresh_rate` can be use to specify how often the clients referencing this chain should be refreshed. The rate is expressed as a fraction of the trusting period. +- The new per-chain setting `dynamic_gas_price` can be enabled to have the relayer query for and use a dynamic gas price instead of using the static `gas_price` specified in the config. This should only be used for chains which have a [EIP-1559][eip-1559]-like fee market enabled and support the `osmosis.txfees.v1beta1.Query/GetEipBaseFee` gRPC query. + +Telemetry now features new metrics: +- Monitoring the ICS20 packets filtered due to the memo and/or receiver field size exceeding the configured limits. +- Monitoring the distribution of dynamic gas fees queried from the chain, if enabled. + +[eip-1559]: https://metamask.io/1559/ diff --git a/.changelog/v1.8.1/bug-fixes/ibc-relayer/3770-non-utf8-packet-data.md b/.changelog/v1.8.1/bug-fixes/ibc-relayer/3770-non-utf8-packet-data.md new file mode 100644 index 0000000000..eae49f1583 --- /dev/null +++ b/.changelog/v1.8.1/bug-fixes/ibc-relayer/3770-non-utf8-packet-data.md @@ -0,0 +1,6 @@ +- Allow relaying ICS-04 packets with non-UTF-8 payloads ([\#3770](https://github.com/informalsystems/hermes/issues/3770)) + Hermes does not assume anymore that an ICS-04 packet data is valid UTF-8, + by using the `packet_data_hex` attribute when assembling a packet from events, instead of the deprecated `packet_data` attribute. + Relying on the `packet_data` attribute enforces a UTF-8 encoded payload (eg. JSON), disallowing eg. Protobuf-encoded payloads. + The `packet_data` attribute [has been deprecated][0] in favor of `packet_data_hex` since IBC-Go v1.0.0. + [0]: https://github.com/cosmos/ibc-go/blob/fadf8f2b0ab184798d021d220d877e00c7634e26/CHANGELOG.md?plain=1#L1417 diff --git a/.changelog/v1.8.1/bug-fixes/ibc-relayer/3831-better-compat-check.md b/.changelog/v1.8.1/bug-fixes/ibc-relayer/3831-better-compat-check.md new file mode 100644 index 0000000000..b533e98fe6 --- /dev/null +++ b/.changelog/v1.8.1/bug-fixes/ibc-relayer/3831-better-compat-check.md @@ -0,0 +1,2 @@ +- Improve reliability of compatibility check and fix parsing of expected modules + versions ([\#3831](https://github.com/informalsystems/hermes/issues/3831)) \ No newline at end of file diff --git a/.changelog/v1.8.1/features/ibc-relayer/3754-filter-packet-clearing.md b/.changelog/v1.8.1/features/ibc-relayer/3754-filter-packet-clearing.md new file mode 100644 index 0000000000..bdf29e069e --- /dev/null +++ b/.changelog/v1.8.1/features/ibc-relayer/3754-filter-packet-clearing.md @@ -0,0 +1,5 @@ +- Add a per-chain configuration `excluded_sequences` allowing + users to specify a list of packet sequences which will not be + cleared. + This configuration has no impact on standard packet relaying. + ([\#3754](https://github.com/informalsystems/hermes/issues/3754)) \ No newline at end of file diff --git a/.changelog/v1.8.1/features/ibc-relayer/3811-relayer-memo-overwrite.md b/.changelog/v1.8.1/features/ibc-relayer/3811-relayer-memo-overwrite.md new file mode 100644 index 0000000000..6a3a649a9e --- /dev/null +++ b/.changelog/v1.8.1/features/ibc-relayer/3811-relayer-memo-overwrite.md @@ -0,0 +1,3 @@ +- Add a per-chain configuration `memo_overwrite` allowing users + to overwrite the relayer memo used for each transaction + ([\#3811](https://github.com/informalsystems/hermes/issues/3811)) \ No newline at end of file diff --git a/.changelog/v1.8.1/features/ibc-telemetry/3845-add-simulate-errors-metric.md b/.changelog/v1.8.1/features/ibc-telemetry/3845-add-simulate-errors-metric.md new file mode 100644 index 0000000000..7e83a36b32 --- /dev/null +++ b/.changelog/v1.8.1/features/ibc-telemetry/3845-add-simulate-errors-metric.md @@ -0,0 +1,11 @@ +- Added a new Prometheus metric `simulate_errors` for tracking when a transaction simulation fails, with the following labels: + * `recoverable` (can the execution continue if this happened?) + * `account` (account from which the tx was sent) + * `error_description` (description of the error) + ([\#3845](https://github.com/informalsystems/hermes/issues/3845)) + + ``` + # HELP simulate_errors_total Number of errors observed by Hermes when simulating a Tx + # TYPE simulate_errors_total counter + simulate_errors_total{account="osmo17ndx5qfku28ymxgmq6zq4a6d02dvpfjjul0hyh",error_description="Unknown error",recoverable="false",service_name="unknown_service",otel_scope_name="hermes",otel_scope_version=""} 4 + ``` diff --git a/.changelog/v1.8.1/improvements/3814-grpc-syncing.md b/.changelog/v1.8.1/improvements/3814-grpc-syncing.md new file mode 100644 index 0000000000..877555aa43 --- /dev/null +++ b/.changelog/v1.8.1/improvements/3814-grpc-syncing.md @@ -0,0 +1,3 @@ +- Add syncing check for gRPC node ([#3814]) + +[#3814]: https://github.com/informalsystems/ibc-rs/issues/3814 diff --git a/.changelog/v1.8.1/improvements/3814-status-use-client-latest-height.md b/.changelog/v1.8.1/improvements/3814-status-use-client-latest-height.md new file mode 100644 index 0000000000..bf06bc6f8d --- /dev/null +++ b/.changelog/v1.8.1/improvements/3814-status-use-client-latest-height.md @@ -0,0 +1,3 @@ +- Use the consensus state at client latest height in status CLI ([#3814]) + +[#3814]: https://github.com/informalsystems/ibc-rs/issues/3814 diff --git a/.changelog/v1.8.1/improvements/ibc-relayer/3530-out-of-gas-error-log.md b/.changelog/v1.8.1/improvements/ibc-relayer/3530-out-of-gas-error-log.md new file mode 100644 index 0000000000..f1742da3ed --- /dev/null +++ b/.changelog/v1.8.1/improvements/ibc-relayer/3530-out-of-gas-error-log.md @@ -0,0 +1,4 @@ +- Improve the log diagnostic when an out of gas error is thrown. + And a new entry related to gas error has been added to the Hermes + guide. + ([\#3530](https://github.com/informalsystems/hermes/issues/3530)) \ No newline at end of file diff --git a/.changelog/v1.8.1/improvements/ibc-relayer/3540-ordered-channels-resilience.md b/.changelog/v1.8.1/improvements/ibc-relayer/3540-ordered-channels-resilience.md new file mode 100644 index 0000000000..88899c96f5 --- /dev/null +++ b/.changelog/v1.8.1/improvements/ibc-relayer/3540-ordered-channels-resilience.md @@ -0,0 +1,6 @@ +- Improve resilience when relaying on ordered channels. + When relaying packets on an ordered channel, Hermes will now attempt + to detect whether the next message to send has the sequence number + expected on that channel. If there is a mismatch, then Hermes will trigger a packet + clear on the channel to unblock it before resuming operations on that channel. + ([\#3540](https://github.com/informalsystems/hermes/issues/3540)) diff --git a/.changelog/v1.8.1/improvements/ibc-relayer/3792-legacy-simulation.md b/.changelog/v1.8.1/improvements/ibc-relayer/3792-legacy-simulation.md new file mode 100644 index 0000000000..f09d5088c1 --- /dev/null +++ b/.changelog/v1.8.1/improvements/ibc-relayer/3792-legacy-simulation.md @@ -0,0 +1,2 @@ +- Recover from gas simulation failures on legacy chains. + ([\#3792](https://github.com/informalsystems/hermes/issues/3792)) diff --git a/.changelog/v1.8.1/summary.md b/.changelog/v1.8.1/summary.md new file mode 100644 index 0000000000..40908d602b --- /dev/null +++ b/.changelog/v1.8.1/summary.md @@ -0,0 +1,19 @@ +*March 6th, 2024* + +This release improves reliability when relaying, more enhanced configuration and improved monitoring. + +Reliability has been improved: +* It is now possible to relay ICS-04 packets with non-UTF-8 payloads +* Packet sequences are now verified for ordered channels before trying to relay + +Additional per-chain configurations have been added: +* `excluded_sequences` used to skip problematic packets when clearing +* `memo_overwrite` allowing users to overwrite the relayer memo when chains have a +strict limit for the size of the memo + +Monitoring issues improvements: +* A new metric `simulate_errors` which counts the number of failed simulated transactions +* Out of gas error diagnostic gives more information and a dedicated entry to the guide has been added +* Failed gas simulation will not be considered as unrecoverable for legacy chains +* The compatibility check during the health-check has been improved will assess more correctly the versions + for Ibc-Go and Cosmos SDK diff --git a/.changelog/v1.8.2/bug-fixes/ibc-relayer-cli/3889-clear-packet-cli-fix.md b/.changelog/v1.8.2/bug-fixes/ibc-relayer-cli/3889-clear-packet-cli-fix.md new file mode 100644 index 0000000000..6470abd610 --- /dev/null +++ b/.changelog/v1.8.2/bug-fixes/ibc-relayer-cli/3889-clear-packet-cli-fix.md @@ -0,0 +1,3 @@ +- Correctly use the counterparty channel and port IDs when clearing the packets + from the destination chain to the source chain in the `packet clear` command + ([\#3889](https://github.com/informalsystems/hermes/issues/3889)) \ No newline at end of file diff --git a/.changelog/v1.8.2/bug-fixes/ibc-relayer/3880-health-check-fix.md b/.changelog/v1.8.2/bug-fixes/ibc-relayer/3880-health-check-fix.md new file mode 100644 index 0000000000..e6106fa10a --- /dev/null +++ b/.changelog/v1.8.2/bug-fixes/ibc-relayer/3880-health-check-fix.md @@ -0,0 +1,2 @@ +- Fix parsing of IBC-Go version in health check and improve health check + reporting ([\#3880](https://github.com/informalsystems/hermes/issues/3880)) \ No newline at end of file diff --git a/.changelog/v1.8.2/features/ibc-integration-test/3887-test-with-injective.md b/.changelog/v1.8.2/features/ibc-integration-test/3887-test-with-injective.md new file mode 100644 index 0000000000..5a9981b4e5 --- /dev/null +++ b/.changelog/v1.8.2/features/ibc-integration-test/3887-test-with-injective.md @@ -0,0 +1,2 @@ +- Add Injective chain to the chains running the integration tests in the CI. + ([\#3887](https://github.com/informalsystems/hermes/issues/3887)) \ No newline at end of file diff --git a/.changelog/v1.8.2/improvements/ibc-relayer/3864-handshake-retry.md b/.changelog/v1.8.2/improvements/ibc-relayer/3864-handshake-retry.md new file mode 100644 index 0000000000..45f5e18c86 --- /dev/null +++ b/.changelog/v1.8.2/improvements/ibc-relayer/3864-handshake-retry.md @@ -0,0 +1,3 @@ +- Change connection and channel handshake retry strategy + to retry at most 10 times (5 times per block max) + ([\#3864](https://github.com/informalsystems/hermes/issues/3864)) \ No newline at end of file diff --git a/.changelog/v1.8.2/summary.md b/.changelog/v1.8.2/summary.md new file mode 100644 index 0000000000..fba1f2ac82 --- /dev/null +++ b/.changelog/v1.8.2/summary.md @@ -0,0 +1,6 @@ +*March 12th, 2024* + +This release fixes the two following bugs and improves the connection and channel handshake retry mechanism: + +* Fix erroneous warnings for incompatible version of IBC-Go during health checks, ensuring accurate compatibility reporting +* Fix a bug in the `clear packets` command which caused packet clearing to fail with an "counterparty channel not found" error diff --git a/.changelog/v1.8.3/bug-fixes/ibc-relayer-cli/3999-duplicate-vote-fix-query.md b/.changelog/v1.8.3/bug-fixes/ibc-relayer-cli/3999-duplicate-vote-fix-query.md new file mode 100644 index 0000000000..a248e67ca2 --- /dev/null +++ b/.changelog/v1.8.3/bug-fixes/ibc-relayer-cli/3999-duplicate-vote-fix-query.md @@ -0,0 +1,2 @@ +- Fix the trusted height consensus state query when submitting the double vote evidence + ([\#3999](https://github.com/informalsystems/hermes/issues/3999)) diff --git a/.changelog/v1.8.3/summary.md b/.changelog/v1.8.3/summary.md new file mode 100644 index 0000000000..0495f558c3 --- /dev/null +++ b/.changelog/v1.8.3/summary.md @@ -0,0 +1 @@ +This patch release fixes a bug that may happen prevent the relayer from submitting the evidence for a duplicate vote in some cases. diff --git a/.changelog/v1.9.0/breaking-changes/ibc-telemetry/3878-remove-telemetry-flag.md b/.changelog/v1.9.0/breaking-changes/ibc-telemetry/3878-remove-telemetry-flag.md new file mode 100644 index 0000000000..aac1189638 --- /dev/null +++ b/.changelog/v1.9.0/breaking-changes/ibc-telemetry/3878-remove-telemetry-flag.md @@ -0,0 +1,3 @@ +- Remove the `telemetry` and `rest-server` feature flags, ensuring Hermes is always built with telemetry and REST support. + Both servers can still be disabled in the configuration file, by setting `telemetry.enabled = false` and `rest.enabled = false`, respectively. + ([\#3878](https://github.com/informalsystems/hermes/pull/3878)) diff --git a/.changelog/v1.9.0/bug-fixes/ibc-relayer-cli/3893-fix-min-gas-price-healthcheck.md b/.changelog/v1.9.0/bug-fixes/ibc-relayer-cli/3893-fix-min-gas-price-healthcheck.md new file mode 100644 index 0000000000..abe83a3a1a --- /dev/null +++ b/.changelog/v1.9.0/bug-fixes/ibc-relayer-cli/3893-fix-min-gas-price-healthcheck.md @@ -0,0 +1,2 @@ +- Fixed `minimum-gas-prices` health-check messages and make it more verbose and legible + ([\#3893](https://github.com/informalsystems/hermes/issues/3893)) diff --git a/.changelog/v1.9.0/bug-fixes/ibc-relayer-cli/3910-fix-subscribe-bug.md b/.changelog/v1.9.0/bug-fixes/ibc-relayer-cli/3910-fix-subscribe-bug.md new file mode 100644 index 0000000000..065ca533fe --- /dev/null +++ b/.changelog/v1.9.0/bug-fixes/ibc-relayer-cli/3910-fix-subscribe-bug.md @@ -0,0 +1,2 @@ +- Set `compat_mode` for pull mode in `hermes listen` command + ([\#3910](https://github.com/informalsystems/hermes/issues/3910)) \ No newline at end of file diff --git a/.changelog/v1.9.0/bug-fixes/ibc-relayer-cli/3999-duplicate-vote-fix-query.md b/.changelog/v1.9.0/bug-fixes/ibc-relayer-cli/3999-duplicate-vote-fix-query.md new file mode 100644 index 0000000000..8ba593c9a6 --- /dev/null +++ b/.changelog/v1.9.0/bug-fixes/ibc-relayer-cli/3999-duplicate-vote-fix-query.md @@ -0,0 +1,2 @@ +- Fixed the trusted height consensus state query when submitting the double vote evidence + ([\#3999](https://github.com/informalsystems/hermes/issues/3999)) diff --git a/.changelog/v1.9.0/bug-fixes/ibc-relayer/3817-deserialize-block-results.md b/.changelog/v1.9.0/bug-fixes/ibc-relayer/3817-deserialize-block-results.md new file mode 100644 index 0000000000..611643818d --- /dev/null +++ b/.changelog/v1.9.0/bug-fixes/ibc-relayer/3817-deserialize-block-results.md @@ -0,0 +1,3 @@ +- Fix creation of channels and connection on chains + using an unsupported version of ibc-go, eg. Sei + ([\#3817](https://github.com/informalsystems/hermes/issues/3817)) \ No newline at end of file diff --git a/.changelog/v1.9.0/bug-fixes/ibc-relayer/3954-interchainquery-missed-events.md b/.changelog/v1.9.0/bug-fixes/ibc-relayer/3954-interchainquery-missed-events.md new file mode 100644 index 0000000000..9ac2212acb --- /dev/null +++ b/.changelog/v1.9.0/bug-fixes/ibc-relayer/3954-interchainquery-missed-events.md @@ -0,0 +1,2 @@ +- Fix a bug where Hermes would only ever extract the first emitted ICS 031 CrossChain Query event, which would cause it to miss the other CCQ events. + ([\#3954](https://github.com/informalsystems/hermes/issues/3954)) \ No newline at end of file diff --git a/.changelog/v1.9.0/features/ibc-relayer/2547-channel-upgrades.md b/.changelog/v1.9.0/features/ibc-relayer/2547-channel-upgrades.md new file mode 100644 index 0000000000..869b7096d4 --- /dev/null +++ b/.changelog/v1.9.0/features/ibc-relayer/2547-channel-upgrades.md @@ -0,0 +1,2 @@ + - Add support for upgrading channels, as per the [ICS 004 specification](https://github.com/cosmos/ibc/blob/main/spec/core/ics-004-channel-and-packet-semantics/UPGRADES.md) ([#3228](https://github.com/informalsystems/hermes/issues/2547)) + This feature allows chains to upgrade an existing channel to take advantage of new features without having to create a new channel, thus preserving all existing packet state processed on the channel. For example, a channel could now be upgraded to enable the [ICS 029 fee middleware](https://ibc.cosmos.network/main/middleware/ics29-fee/overview), allowing relayer operators on that channel to receive fees each time they relay an incentivized packet. diff --git a/.changelog/v1.9.0/features/ibc-relayer/3894-continue-event-sourcing.md b/.changelog/v1.9.0/features/ibc-relayer/3894-continue-event-sourcing.md new file mode 100644 index 0000000000..f71ef4007e --- /dev/null +++ b/.changelog/v1.9.0/features/ibc-relayer/3894-continue-event-sourcing.md @@ -0,0 +1,6 @@ +- Improve reliability of event source in `pull` mode by proceeding to next block even if Hermes cannot parse the current block. + Add new configuration option to `event_source` setting: `max_retries` defines how many times Hermes should attempt to pull a block over RPC. + ```toml + event_source = { mode = 'pull', interval = '1s', max_retries = 4 } + ``` + ([\#3894](https://github.com/informalsystems/hermes/issues/3894)) diff --git a/.changelog/v1.9.0/improvements/ibc-integration-test/3959-update-juno-to-v21.md b/.changelog/v1.9.0/improvements/ibc-integration-test/3959-update-juno-to-v21.md new file mode 100644 index 0000000000..17a9b17a68 --- /dev/null +++ b/.changelog/v1.9.0/improvements/ibc-integration-test/3959-update-juno-to-v21.md @@ -0,0 +1,2 @@ +- Update the version of Juno running the integration tests in the CI from `v17.1.1` + to `v21.0.0` ([\#3959](https://github.com/informalsystems/hermes/issues/3959)) \ No newline at end of file diff --git a/.changelog/v1.9.0/improvements/ibc-integration-test/3960-update-migaloo-to-v4.md b/.changelog/v1.9.0/improvements/ibc-integration-test/3960-update-migaloo-to-v4.md new file mode 100644 index 0000000000..447e299663 --- /dev/null +++ b/.changelog/v1.9.0/improvements/ibc-integration-test/3960-update-migaloo-to-v4.md @@ -0,0 +1,3 @@ +- Update the version of Migaloo Chain running the + integration tests in the CI from `v3.0.2` to `v4.1.3` + ([\#3960](https://github.com/informalsystems/hermes/issues/3960)) \ No newline at end of file diff --git a/.changelog/v1.9.0/improvements/ibc-integration-test/3961-update-wasmd-to-v0-50.md b/.changelog/v1.9.0/improvements/ibc-integration-test/3961-update-wasmd-to-v0-50.md new file mode 100644 index 0000000000..b1847636bd --- /dev/null +++ b/.changelog/v1.9.0/improvements/ibc-integration-test/3961-update-wasmd-to-v0-50.md @@ -0,0 +1,3 @@ +- Update the version of `wasmd` running the + integration tests in the CI from `v0.30.0` to `v0.50.0` + ([\#3961](https://github.com/informalsystems/hermes/issues/3961)) \ No newline at end of file diff --git a/.changelog/v1.9.0/improvements/ibc-integration-test/4009-update-ibc-go-v8-ci.md b/.changelog/v1.9.0/improvements/ibc-integration-test/4009-update-ibc-go-v8-ci.md new file mode 100644 index 0000000000..ce8c7ee27e --- /dev/null +++ b/.changelog/v1.9.0/improvements/ibc-integration-test/4009-update-ibc-go-v8-ci.md @@ -0,0 +1,3 @@ +- Update the version of ibc-go simapp running the + integration tests in the CI from `v8.2.0` to `v8.3.1` + ([\#4009](https://github.com/informalsystems/hermes/issues/4009)) \ No newline at end of file diff --git a/.changelog/v1.9.0/improvements/ibc-relayer-cli/3913-config-auto-pull.md b/.changelog/v1.9.0/improvements/ibc-relayer-cli/3913-config-auto-pull.md new file mode 100644 index 0000000000..c19c7f34d6 --- /dev/null +++ b/.changelog/v1.9.0/improvements/ibc-relayer-cli/3913-config-auto-pull.md @@ -0,0 +1,2 @@ +- Use RPC (pull) event source instead of WebSocket (push) when generating configuration with `hermes config auto` + ([\#3913](https://github.com/informalsystems/hermes/issues/3913)) diff --git a/.changelog/v1.9.0/improvements/ibc-relayer/3895-tendermint-rs-0.35.md b/.changelog/v1.9.0/improvements/ibc-relayer/3895-tendermint-rs-0.35.md new file mode 100644 index 0000000000..fd27d9961e --- /dev/null +++ b/.changelog/v1.9.0/improvements/ibc-relayer/3895-tendermint-rs-0.35.md @@ -0,0 +1,2 @@ +- Update to tendermint-rs v0.35.0 + ([\#3895](https://github.com/informalsystems/hermes/issues/3895)) \ No newline at end of file diff --git a/.changelog/v1.9.0/improvements/ibc-relayer/3921-packet-ack-hex.md b/.changelog/v1.9.0/improvements/ibc-relayer/3921-packet-ack-hex.md new file mode 100644 index 0000000000..cd0f2c0aed --- /dev/null +++ b/.changelog/v1.9.0/improvements/ibc-relayer/3921-packet-ack-hex.md @@ -0,0 +1,2 @@ +- Use `packet_ack_hex` event attribute instead of deprecated `packet_ack` attribute to decode `WriteAck` event + ([\#3921](https://github.com/informalsystems/hermes/issues/3921)) diff --git a/.changelog/v1.9.0/improvements/ibc-relayer/3966-tendermint-rs-0.36.md b/.changelog/v1.9.0/improvements/ibc-relayer/3966-tendermint-rs-0.36.md new file mode 100644 index 0000000000..9d2d3f865e --- /dev/null +++ b/.changelog/v1.9.0/improvements/ibc-relayer/3966-tendermint-rs-0.36.md @@ -0,0 +1,2 @@ +- Update to tendermint-rs v0.36.0 + ([\#3966](https://github.com/informalsystems/hermes/issues/3966)) \ No newline at end of file diff --git a/.changelog/v1.9.0/improvements/ibc-relayer/4000-update-dynamic-gas-fee.md b/.changelog/v1.9.0/improvements/ibc-relayer/4000-update-dynamic-gas-fee.md new file mode 100644 index 0000000000..4c7123523a --- /dev/null +++ b/.changelog/v1.9.0/improvements/ibc-relayer/4000-update-dynamic-gas-fee.md @@ -0,0 +1,2 @@ +- Add support for dynamic gas fee for chains using Skip's [`x/feemarket`](https://github.com/skip-mev/feemarket) module, while keeping compatibility with Osmosis' bespoke implementation + ([\#4000](https://github.com/informalsystems/hermes/issues/4000)) \ No newline at end of file diff --git a/.changelog/v1.9.0/summary.md b/.changelog/v1.9.0/summary.md new file mode 100644 index 0000000000..8da025760a --- /dev/null +++ b/.changelog/v1.9.0/summary.md @@ -0,0 +1,11 @@ +*May 30th, 2024* + +This v1.9.0 release introduces new features and improvements to Hermes. + +**Major Features**: + +1. Channel Upgrade Compatibility: Hermes now supports channel upgrade events introduced in ibc-go v8, ensuring smoother transitions and enhanced functionality. + +3. Dynamic Gas Fees Compatibility: Hermes is now compatible with Skip's feemarket for dynamic gas fees, in addition to Osmosis' implementation, providing more flexibility in gas fee management. + +Additionally, this release includes various bug fixes enhancing the stability and performance of Hermes. These fixes address issues with channel and connection creation on unsupported ibc-go versions, event extraction, health-check messages, and more. diff --git a/.github/ISSUE_TEMPLATE/release-template.md b/.github/ISSUE_TEMPLATE/release-template.md index 1a80ba309f..960b3364ab 100644 --- a/.github/ISSUE_TEMPLATE/release-template.md +++ b/.github/ISSUE_TEMPLATE/release-template.md @@ -20,3 +20,4 @@ v without deliberation - [ ] Create a new release in the changelog, using [`unclog`](https://github.com/informalsystems/unclog) - If doing a release candidate (`rc`) version, then skip the `unclog release` step - [ ] Reassign unfinished issues of previous milestone to the next milestone +- [ ] Notify the comms team about the pending new release by tagging [@isa-belch](https://github.com/isa-belch) as a reviewer here diff --git a/.github/codespell/codespell.ini b/.github/codespell/codespell.ini index 681ebbd0f1..2e8efedbbd 100644 --- a/.github/codespell/codespell.ini +++ b/.github/codespell/codespell.ini @@ -1,3 +1,3 @@ [codespell] -skip = *.js,*.ts,*.css,*.svg,*.html,*.json,./target,./tools/integration-test/data,./tools/check-guide/target,./ci/misbehaviour/data +skip = *.js,*.ts,*.css,*.svg,*.html,*.json,./target,./tools/integration-test/data,./tools/check-guide/target,./ci/misbehaviour/data,./.git ignore-words = .github/codespell/words.txt diff --git a/.github/workflows/audit.yaml b/.github/workflows/audit.yaml index ffafedc37c..e6ad8d0de2 100644 --- a/.github/workflows/audit.yaml +++ b/.github/workflows/audit.yaml @@ -10,7 +10,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Cache cargo bin - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.cargo/bin key: ${{ runner.os }}-cargo-audit-v0.11.2 diff --git a/.github/workflows/cargo-doc.yaml b/.github/workflows/cargo-doc.yaml index ebc03618b6..9682a8456f 100644 --- a/.github/workflows/cargo-doc.yaml +++ b/.github/workflows/cargo-doc.yaml @@ -26,11 +26,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 + - uses: actions-rust-lang/setup-rust-toolchain@v1 with: - toolchain: nightly-2023-07-13 - override: true - + toolchain: nightly-2024-04-21 - name: Build API documentation uses: actions-rs/cargo@v1 env: @@ -41,7 +39,7 @@ jobs: - name: Push API documentation to GitHub Pages if: github.ref == 'refs/heads/master' - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@v4 with: deploy_key: ${{ secrets.IBC_RS_DOC_PRIVATE_KEY }} external_repository: informalsystems/hermes-api-doc diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index 6ad483e50d..7b82ed249f 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -17,6 +17,7 @@ jobs: - uses: actions/checkout@v4 - uses: codespell-project/actions-codespell@v2 with: - skip: '*.js,*.ts,*.css,*.svg,*.html,*.json,./target,./tools/integration-test/data,./tools/check-guide/target,./ci/misbehaviour/data' + skip: '*.js,*.ts,*.css,*.svg,*.html,*.json,./target,./tools/integration-test/data,./tools/check-guide/target,./ci/misbehaviour/data,./.git' ignore_words_file: .github/codespell/words.txt + check_hidden: true diff --git a/.github/workflows/guide-templates.yaml b/.github/workflows/guide-templates.yaml index 1d558a86cc..9eefc0d3fc 100644 --- a/.github/workflows/guide-templates.yaml +++ b/.github/workflows/guide-templates.yaml @@ -28,10 +28,9 @@ jobs: timeout-minutes: 60 steps: - uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 + - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable - override: true - name: Check templates run: bash scripts/auto_gen_templates.sh --mode "check" - uses: actions-rs/cargo@v1 diff --git a/.github/workflows/guide.yml b/.github/workflows/guide.yml index 5f37b5665e..869c5a4f6f 100644 --- a/.github/workflows/guide.yml +++ b/.github/workflows/guide.yml @@ -33,7 +33,7 @@ jobs: # Only deploy guide when releasing a new version of Hermes - name: Deploy to GitHub Pages - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@v4 if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') with: github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/integration.yaml b/.github/workflows/integration.yaml index 78ef604845..59f90f2caf 100644 --- a/.github/workflows/integration.yaml +++ b/.github/workflows/integration.yaml @@ -45,31 +45,31 @@ jobs: fail-fast: false matrix: chain: - - package: gaia13 + - package: gaia18 command: gaiad account_prefix: cosmos native_token: stake - features: forward-packet,clean-workers - - package: gaia14 - command: gaiad - account_prefix: cosmos - native_token: stake - features: forward-packet,clean-workers + features: forward-packet,clean-workers,ica,ics29-fee - package: ibc-go-v6-simapp command: simd account_prefix: cosmos native_token: stake - features: ica,ics29-fee + features: ica,ics29-fee,authz - package: ibc-go-v7-simapp command: simd account_prefix: cosmos native_token: stake - features: ica,ics29-fee + features: ica,ics29-fee,authz - package: ibc-go-v8-simapp command: simd account_prefix: cosmos native_token: stake - features: ica,ics29-fee + features: ica,ics29-fee,new-register-interchain-account,channel-upgrade,authz + - package: ibc-go-v9-simapp + command: simd + account_prefix: cosmos + native_token: stake + features: ica,ics29-fee,new-register-interchain-account,channel-upgrade,authz,no-denom-trace - package: wasmd command: wasmd account_prefix: wasm @@ -79,39 +79,45 @@ jobs: command: osmosisd account_prefix: osmo native_token: stake - features: '' + features: dynamic-gas-fee,forward-packet,ica - package: juno command: junod account_prefix: juno native_token: stake - features: juno,forward-packet + features: juno,forward-packet,ica,ics29-fee - package: provenance command: provenanced account_prefix: pb native_token: nhash - features: fee-grant,async-icq + features: fee-grant,authz,async-icq - package: migaloo command: migalood account_prefix: migaloo native_token: stake - features: '' + features: ics29-fee,ica,forward-packet + # Disable Injective because wasmvm hasn't been correctly + # wired for Injective in Cosmos Nix + #- package: injective + # command: injectived + # account_prefix: inj + # native_token: stake + # features: forward-packet,fee-grant steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v25 - 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@v14 - with: - name: cosmos - - uses: actions-rs/toolchain@v1 + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@main + with: + extra-conf: | + substituters = https://cache.nixos.org + trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= + - name: Install Cachix + uses: cachix/cachix-action@v15 + with: + name: cosmos-nix + - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable - override: true - - uses: Swatinem/rust-cache@v2 - uses: actions-rs/cargo@v1 with: command: test @@ -137,20 +143,19 @@ jobs: timeout-minutes: 60 steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v25 - 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@v14 - with: - name: cosmos - - uses: actions-rs/toolchain@v1 + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@main + with: + extra-conf: | + substituters = https://cache.nixos.org + trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= + - name: Install Cachix + uses: cachix/cachix-action@v15 + with: + name: cosmos-nix + - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable - override: true - - uses: Swatinem/rust-cache@v2 - uses: actions-rs/cargo@v1 with: command: test @@ -167,84 +172,37 @@ jobs: cargo nextest run -p ibc-integration-test --no-fail-fast --failure-output final --test-threads=2 \ --features ordered test_ordered_channel - interchain-security-no-ica: - runs-on: ubuntu-20.04 - strategy: - fail-fast: false - matrix: - chain: - - 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@v25 - 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@v14 - 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: ${{ 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 interchain-security interchain_security:: - interchain-security-ica: runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: chain: - - package: .#gaia13 .#stride-consumer - command: gaiad,strided - account_prefix: cosmos,stride - - package: .#gaia14 .#stride-consumer + - package: .#gaia18 .#stride command: gaiad,strided account_prefix: cosmos,stride + - package: .#gaia18 .#neutron + command: gaiad,neutrond + account_prefix: cosmos,neutron steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v25 - 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@v14 - with: - name: cosmos - - uses: actions-rs/toolchain@v1 + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@main + with: + extra-conf: | + substituters = https://cache.nixos.org + trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= + - name: Install Cachix + uses: cachix/cachix-action@v15 + with: + name: cosmos-nix + - uses: actions-rust-lang/setup-rust-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 + args: -p ibc-integration-test --features interchain-security,ica --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: @@ -265,28 +223,24 @@ jobs: fail-fast: false matrix: chain: - - package: .#gaia13 .#stride-consumer-no-admin - command: gaiad,strided - account_prefix: cosmos,stride - - package: .#gaia14 .#stride-consumer-no-admin + - package: .#gaia18 .#stride-no-admin command: gaiad,strided account_prefix: cosmos,stride steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v25 - 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@v14 - with: - name: cosmos - - uses: actions-rs/toolchain@v1 + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@main + with: + extra-conf: | + substituters = https://cache.nixos.org + trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= + - name: Install Cachix + uses: cachix/cachix-action@v15 + with: + name: cosmos-nix + - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable - override: true - - uses: Swatinem/rust-cache@v2 - uses: actions-rs/cargo@v1 with: command: test @@ -310,30 +264,25 @@ jobs: fail-fast: false matrix: chain: - - package: .#celestia .#gaia13 - command: celestia-appd,gaiad - account_prefix: celestia,cosmos - native_token: utia,stake - - package: .#celestia .#gaia14 + - package: .#celestia .#gaia18 command: celestia-appd,gaiad account_prefix: celestia,cosmos native_token: utia,stake steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v25 - 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@v14 - with: - name: cosmos - - uses: actions-rs/toolchain@v1 + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@main + with: + extra-conf: | + substituters = https://cache.nixos.org + trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= + - name: Install Cachix + uses: cachix/cachix-action@v15 + with: + name: cosmos-nix + - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable - override: true - - uses: Swatinem/rust-cache@v2 - uses: actions-rs/cargo@v1 with: command: test @@ -344,7 +293,7 @@ jobs: RUST_LOG: info RUST_BACKTRACE: 1 NO_COLOR_LOG: 1 - COMPAT_MODES: 0.34 + COMPAT_MODES: 0.34,0.37 CHAIN_COMMAND_PATHS: ${{ matrix.chain.command }} ACCOUNT_PREFIXES: ${{ matrix.chain.account_prefix }} NATIVE_TOKENS: ${{ matrix.chain.native_token }} @@ -352,43 +301,3 @@ jobs: nix shell .#python ${{ matrix.chain.package }} -c \ cargo nextest run -p ibc-integration-test --no-fail-fast --failure-output final --test-threads=2 \ --features celestia - - model-based-test: - runs-on: ubuntu-20.04 - timeout-minutes: 60 - strategy: - matrix: - gaiad: - - gaia6 - steps: - - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v25 - 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@v14 - 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 mbt --no-fail-fast --no-run - # Disable running MBT tests until flakiness is addressed - # - env: - # RUST_LOG: debug - # RUST_BACKTRACE: 1 - # NO_COLOR_LOG: 1 - # run: | - # nix shell \ - # .#${{ matrix.gaiad }} \ - # .#apalache \ - # -c cargo \ - # test -p ibc-integration-test --features mbt --no-fail-fast -- \ - # --failure-output final --test-threads=2 --test-threads=1 mbt diff --git a/.github/workflows/markdown-link-check.yml b/.github/workflows/markdown-link-check.yml index 9dbaba343b..01c16456da 100644 --- a/.github/workflows/markdown-link-check.yml +++ b/.github/workflows/markdown-link-check.yml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v4 - name: Link Checker id: lychee - uses: lycheeverse/lychee-action@v1.9.1 + uses: lycheeverse/lychee-action@v1.10.0 with: args: --verbose --no-progress --max-concurrency 16 './**/*.md' token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/misbehaviour.yml b/.github/workflows/misbehaviour.yml index 629ce08faf..43dfc6635d 100644 --- a/.github/workflows/misbehaviour.yml +++ b/.github/workflows/misbehaviour.yml @@ -43,22 +43,23 @@ jobs: fail-fast: false matrix: chain: - - package: gaia14 + - package: gaia18 command: gaiad account_prefix: cosmos steps: - uses: actions/checkout@v4 - name: Install Nix - uses: cachix/install-nix-action@v25 - with: - extra_nix_config: | - experimental-features = nix-command flakes - - name: Use cachix cache - uses: cachix/cachix-action@v14 - with: - name: cosmos + uses: DeterminateSystems/nix-installer-action@main + with: + extra-conf: | + substituters = https://cache.nixos.org + trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= + - name: Install Cachix + uses: cachix/cachix-action@v15 + with: + name: cosmos-nix - name: Install sconfig - uses: jaxxstorm/action-install-gh-release@v1.10.0 + uses: jaxxstorm/action-install-gh-release@v1.12.0 with: repo: freshautomations/sconfig platform: linux @@ -67,7 +68,7 @@ jobs: rename-to: sconfig chmod: 0755 - name: Install stoml - uses: jaxxstorm/action-install-gh-release@v1.10.0 + uses: jaxxstorm/action-install-gh-release@v1.12.0 with: repo: freshautomations/stoml platform: linux @@ -76,12 +77,9 @@ jobs: rename-to: stoml chmod: 0755 - name: Install Rust - uses: actions-rs/toolchain@v1 + uses: actions-rust-lang/setup-rust-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: @@ -103,16 +101,17 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install Nix - uses: cachix/install-nix-action@v25 - with: - extra_nix_config: | - experimental-features = nix-command flakes - - name: Use cachix cache - uses: cachix/cachix-action@v14 - with: - name: cosmos + uses: DeterminateSystems/nix-installer-action@main + with: + extra-conf: | + substituters = https://cache.nixos.org + trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= + - name: Install Cachix + uses: cachix/cachix-action@v15 + with: + name: cosmos-nix - name: Install sconfig - uses: jaxxstorm/action-install-gh-release@v1.10.0 + uses: jaxxstorm/action-install-gh-release@v1.12.0 with: repo: freshautomations/sconfig platform: linux @@ -121,7 +120,7 @@ jobs: rename-to: sconfig chmod: 0755 - name: Install stoml - uses: jaxxstorm/action-install-gh-release@v1.10.0 + uses: jaxxstorm/action-install-gh-release@v1.12.0 with: repo: freshautomations/stoml platform: linux @@ -130,12 +129,9 @@ jobs: rename-to: stoml chmod: 0755 - name: Install Rust - uses: actions-rs/toolchain@v1 + uses: actions-rust-lang/setup-rust-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: @@ -157,16 +153,17 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install Nix - uses: cachix/install-nix-action@v25 - with: - extra_nix_config: | - experimental-features = nix-command flakes - - name: Use cachix cache - uses: cachix/cachix-action@v14 - with: - name: cosmos + uses: DeterminateSystems/nix-installer-action@main + with: + extra-conf: | + substituters = https://cache.nixos.org + trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= + - name: Install Cachix + uses: cachix/cachix-action@v15 + with: + name: cosmos-nix - name: Install sconfig - uses: jaxxstorm/action-install-gh-release@v1.10.0 + uses: jaxxstorm/action-install-gh-release@v1.12.0 with: repo: freshautomations/sconfig platform: linux @@ -175,7 +172,7 @@ jobs: rename-to: sconfig chmod: 0755 - name: Install stoml - uses: jaxxstorm/action-install-gh-release@v1.10.0 + uses: jaxxstorm/action-install-gh-release@v1.12.0 with: repo: freshautomations/stoml platform: linux @@ -184,12 +181,9 @@ jobs: rename-to: stoml chmod: 0755 - name: Install Rust - uses: actions-rs/toolchain@v1 + uses: actions-rust-lang/setup-rust-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: @@ -212,16 +206,17 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install Nix - uses: cachix/install-nix-action@v25 - with: - extra_nix_config: | - experimental-features = nix-command flakes - - name: Use cachix cache - uses: cachix/cachix-action@v14 - with: - name: cosmos + uses: DeterminateSystems/nix-installer-action@main + with: + extra-conf: | + substituters = https://cache.nixos.org + trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= + - name: Install Cachix + uses: cachix/cachix-action@v15 + with: + name: cosmos-nix - name: Install sconfig - uses: jaxxstorm/action-install-gh-release@v1.10.0 + uses: jaxxstorm/action-install-gh-release@v1.12.0 with: repo: freshautomations/sconfig platform: linux @@ -230,7 +225,7 @@ jobs: rename-to: sconfig chmod: 0755 - name: Install stoml - uses: jaxxstorm/action-install-gh-release@v1.10.0 + uses: jaxxstorm/action-install-gh-release@v1.12.0 with: repo: freshautomations/stoml platform: linux @@ -239,12 +234,9 @@ jobs: rename-to: stoml chmod: 0755 - name: Install Rust - uses: actions-rs/toolchain@v1 + uses: actions-rust-lang/setup-rust-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: diff --git a/.github/workflows/multi-chains.yaml b/.github/workflows/multi-chains.yaml index 63edbede02..43846c1347 100644 --- a/.github/workflows/multi-chains.yaml +++ b/.github/workflows/multi-chains.yaml @@ -58,10 +58,7 @@ jobs: fail-fast: false matrix: first-package: - - package: gaia13 - command: gaiad - account_prefix: cosmos - - package: gaia14 + - package: gaia18 command: gaiad account_prefix: cosmos - package: ibc-go-v7-simapp @@ -70,6 +67,9 @@ jobs: - package: ibc-go-v8-simapp command: simd account_prefix: cosmos + - package: ibc-go-v9-simapp + command: simd + account_prefix: cosmos second-package: - package: osmosis command: osmosisd @@ -80,23 +80,25 @@ jobs: - package: wasmd command: wasmd account_prefix: wasm + - package: injective + command: injectived + account_prefix: inj steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v25 - 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@v14 - with: - name: cosmos - - uses: actions-rs/toolchain@v1 + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@main + with: + extra-conf: | + substituters = https://cache.nixos.org + trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= + - name: Install Cachix + uses: cachix/cachix-action@v15 + with: + name: cosmos-nix + - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable - override: true - - uses: Swatinem/rust-cache@v2 - uses: actions-rs/cargo@v1 with: command: test diff --git a/.github/workflows/publish-dry-run.yml b/.github/workflows/publish-dry-run.yml new file mode 100644 index 0000000000..2f22b4d851 --- /dev/null +++ b/.github/workflows/publish-dry-run.yml @@ -0,0 +1,20 @@ +name: Publish (dry-run) + +on: + push: + branches: + - 'release/*' + +jobs: + publish_dry_run: + name: Publish (dry-run) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: stable + - uses: katyo/publish-crates@v2 + with: + dry-run: true + diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index cbcbc6f39a..42106466c5 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,21 +1,21 @@ -name: Publish (dry-run) +name: Publish on: push: - branches: - - 'release/*' + tags: + - v[0-9]+.* jobs: - publish: - name: Publish (dry-run) + publish_dry_run: + name: Publish to crates.io runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 + - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable - override: true - uses: katyo/publish-crates@v2 with: - dry-run: true + registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }} + diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 49acf5017c..bc19b03142 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -38,10 +38,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 + - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable - override: true - uses: actions-rs/cargo@v1 with: command: fmt @@ -51,12 +50,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 + - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable components: clippy - override: true - - uses: Swatinem/rust-cache@v2 - uses: actions-rs/clippy-check@v1 with: name: clippy-all-features @@ -67,12 +64,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 + - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable components: clippy - override: true - - uses: Swatinem/rust-cache@v2 - uses: actions-rs/clippy-check@v1 with: name: clippy-no-default-features @@ -84,11 +79,9 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 + - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable - override: true - - uses: Swatinem/rust-cache@v2 - name: Install cargo-nextest run: curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin - uses: actions-rs/cargo@v1 @@ -100,13 +93,27 @@ jobs: command: nextest args: run --all-features --no-fail-fast --workspace --exclude ibc-integration-test --no-capture + msrv: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: stable + - name: Install cargo-binstall + uses: taiki-e/install-action@cargo-binstall + - name: Install cargo-msrv + run: cargo binstall --no-confirm --force cargo-msrv@0.16.0-beta.20 + - name: Check MSRV + run: cargo msrv verify --output-format minimal --manifest-path crates/relayer-cli/Cargo.toml -- 'cargo check --all-features' + # test-coverage: # runs-on: ubuntu-latest # steps: # - uses: actions/checkout@v4 # with: # fetch-depth: 0 - # - uses: actions-rs/toolchain@v1 + # - uses: actions-rust-lang/setup-rust-toolchain@v1 # with: # toolchain: stable # override: true diff --git a/.gitignore b/.gitignore index edd589a061..f46e505cd9 100644 --- a/.gitignore +++ b/.gitignore @@ -21,7 +21,7 @@ data .mypy_cache/ __pycache__/ -# Ignore modelator aritfacts +# Ignore modelator artifacts .modelator mc.log @@ -30,3 +30,6 @@ mc.log # Ignore tooling Cargo.lock tools/check-guide/Cargo.lock + +# Ignore data generated from wasm contract +ibc_08-wasm_client_data \ No newline at end of file diff --git a/.rustfmt.toml b/.rustfmt.toml index 3f8091e26c..bf987aed95 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1,8 +1,8 @@ max_width = 100 reorder_imports = true -imports_layout = "Vertical" -imports_granularity = "Crate" -group_imports = "StdExternalCrate" +# imports_layout = "Vertical" +# imports_granularity = "Crate" +# group_imports = "StdExternalCrate" # nightly only diff --git a/CHANGELOG.md b/CHANGELOG.md index 08dad0afd3..f901697dd4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,486 @@ # CHANGELOG +## v1.10.3 + +*September 2nd, 2024* + +This release fixes an issue where Hermes could not connect to gRPC servers over TLS. Additionally, this release also fixes a bug in the `clear packet` CLI where the `excluded_sequences` configuration option was not always taken into account. + +Furthermore, Hermes now uses `abci_query` instead of gRPC for some queries, for instance for querying staking parameters and service configuration during health checks, and when retrieving version information. + +### BUG FIXES + +- [Chain Registry](chain-registry) + - Add explicit root TLS configuration to gRPC clients + ([\#4160](https://github.com/informalsystems/hermes/issues/4160)) +- [Relayer Library](relayer) + - Add explicit root TLS configuration to gRPC clients + ([\#4160](https://github.com/informalsystems/hermes/issues/4160)) +- [Relayer CLI](relayer-cli) + - Correctly filter out sequences from the `excluded_sequences` configuration + when clearing packets with the `clear packet` CLI. + ([\#4158](https://github.com/informalsystems/hermes/issues/4158)) + +### IMPROVEMENTS + +- [Relayer Library](relayer) + - Use `abci_query` instead of gRPC queries when retrieving staking params + and service config during health-check, and when retrieving version information. + ([\#4102](https://github.com/informalsystems/hermes/issues/4102)) +- [Integration Test Framework](tools/test-framework) + - Update the version of Celestia running the integration tests in the CI from `v1.11.0` + to `v1.14.0` ([\#4123](https://github.com/informalsystems/hermes/issues/4123)) + - Update the version of Neutron running the integration tests in the CI from `v4.1.0` + to `v4.2.2` ([\#4168](https://github.com/informalsystems/hermes/issues/4168)) + - Update the version of `wasmd` running the integration tests in the CI from `v0.52.0` + to `v0.53.0` ([\#4169](https://github.com/informalsystems/hermes/issues/4169)) + - Update the version of Juno running the integration tests in the CI from `v23.0.0` + to `v24.0.0` ([\#4171](https://github.com/informalsystems/hermes/issues/4171)) + +### FEATURES + +- [Integration Test Framework](tools/test-framework) + - Add ibc-go `v9` to the chains running the integration tests in the CI. + ([\#4151](https://github.com/informalsystems/hermes/issues/4151)) + +## v1.10.2 + +*August 14th, 2024* + +This release brings significant performance improvements and introduces a new configuration options for better control over packet clearing. Enhancements include faster startup times through optimized queries and the introduction of a `clear_limit` setting for packet clearing. Additionally, bug fixes and updates to the integration test framework ensure greater stability and compatibility across various environments. + +### BUG FIXES + +- [Relayer Library](relayer) + - Fix the `memo_overwrite` configuration to correctly apply the + overwrite if it is configured. + ([\#4104](https://github.com/informalsystems/hermes/issues/4104)) +- [Telemetry & Metrics](telemetry) + - Fix the `dynamic_gas_queried_success_fees` Prometheus metric name. + ([\#4104](https://github.com/informalsystems/hermes/issues/4104)) + + +### IMPROVEMENTS +- [Relayer Library](relayer) + - Add a new configuration `clear_limit` to specify the maximum number + of packets cleared every time packet clearing is triggered. + Defaults to 50. + ([\#4071](https://github.com/informalsystems/hermes/issues/4071)) + - Paginate results of `query_packet_commitments` and `query_packet_acknowledgements` + queries to speed up the scanning phase. + ([\#4101](https://github.com/informalsystems/hermes/issues/4101)) + - Use the `ibc.core.connection.v1.ConnectionParams` gRPC query to retrieve `maxExpectedTimePerBlock` + and check it against the configured `max_block_time` instead of using the `/genesis` endpoint. + This improves both startup times and reliability for most chains. + ([\#4143](https://github.com/informalsystems/hermes/issues/4143)) +- [Integration Test Framework](tools/test-framework) + - Update the version of Gaia running the integration tests in the CI from `v17.2.1` + to `v18.1.0` ([\#4114](https://github.com/informalsystems/hermes/issues/4114)) + - Update the version of Provenance running the integration tests in the CI from `v1.17.0` + to `v1.19.1` ([\#4115](https://github.com/informalsystems/hermes/issues/4115)) + - Update the version of Osmosis running the integration tests in the CI from `v25.0.0` + to `v25.2.0` ([\#4116](https://github.com/informalsystems/hermes/issues/4116)) + - Update the version of Juno running the integration tests in the CI from `v22.0.0` + to `v23.0.0` ([\#4117](https://github.com/informalsystems/hermes/issues/4117)) + - Update the version of Migaloo Chain running the integration tests in the CI from `v4.1.3` + to `v4.2.0` ([\#4118](https://github.com/informalsystems/hermes/issues/4118)) + - Update the version of `wasmd` running the integration tests in the CI from `v0.51.0` + to `v0.52.0` ([\#4120](https://github.com/informalsystems/hermes/issues/4120)) + - Update the version of Stride running the integration tests in the CI from `v21.0.0` + to `v23.0.1` ([\#4121](https://github.com/informalsystems/hermes/issues/4121)) + - Update the version of Neutron running the integration tests in the CI from `v3.0.5` + to `v4.1.0` ([\#4122](https://github.com/informalsystems/hermes/issues/4122)) + +## v1.10.1 + +*July 23th, 2024* + +In this release `tendermint-rs` has been updated to the latest version, addressing issues with the `/block_results` response. This ensures compatibility with CometBFT v0.38.10. + +And enhancements have been made to the logs regarding packet clearing, providing better insights and warnings for users. + + +### BREAKING CHANGES + +- Bump version of `ibc-proto` from `v0.46.0` to `v0.47.0` and + version of `tendermint-rs` from `v0.37.0` to `v0.38.1`. + ([\#4093](https://github.com/informalsystems/hermes/issues/4093)) + +### IMPROVEMENTS + +- [Integration Test Framework](tools/test-framework) + - Add the features `packet-forward` and `ica` to enable + Packet Forward Middleware and ICA when running tests with Osmosis + ([\#3195](https://github.com/informalsystems/hermes/issues/3195)) +- [Relayer Library](relayer) + - Improve logs when clearing packet. + * When Hermes doesn't pull packet data it will now warn the user + instead of logging `pulled packet data for 0 events out of X` + * When ICS20 packets are filtered due to having a receiver or memo + field too big, the log will be at `warn` level instead of `debug`. + ([\#4072](https://github.com/informalsystems/hermes/issues/4072)) + +## v1.10.0 + +*June 24th, 2024* + +This release enhances filter configurations and includes the following updates: + +1. `excluded_sequences` supports sequence ranges in addition to exact values, + e.g. `[1, 2, "5-10", 13]` is now valid. +2. `packet_filter` now ignores unintended whitespace. +3. A new `allow_ccq` per-chain configuration has been added to skip the relaying of + ICS31 Cross Chain Queries. + +Additionally, various improvements to testing and bug fixes have been implemented. + +### BUG FIXES + +- General + - Fix a bug where in some cases, Hermes would drop all events in a + batch that came after an event rejected by the filtering policy + ([\#4034](https://github.com/informalsystems/hermes/issues/4034)) +- [Relayer Library](relayer) + - Discard CrossChain queries intended for unconfigured chains. + ([\#4021](https://github.com/informalsystems/hermes/issues/4021)) + +### FEATURES + +- [Integration Test Framework](tools/test-framework) + - Add tests to ensure that Hermes correctly relays transfer messages + from a grantee address with granted authorisation using `authz` module. + ([\#4046](https://github.com/informalsystems/hermes/issues/4046)) +- [Relayer Library](relayer) + - Add a new per-chain configuration `allow_ccq` to enable or disable + relaying of ICS31 Cross Chain Query packets. + ([\#4040](https://github.com/informalsystems/hermes/issues/4040)) + +### IMPROVEMENTS + +- [Integration Test Framework](tools/test-framework) + - Update the version of Gaia running the integration tests in the CI from `v15.2.0` + to `v17.2.0` ([\#4023](https://github.com/informalsystems/hermes/issues/4023)) + - Update the version of Osmosis running the integration tests in the CI from `v24.0.1` + to `v25.0.0` ([\#4024](https://github.com/informalsystems/hermes/issues/4024)) + - Update the version of Juno running the integration tests in the CI from `v21.0.0` + to `v22.0.0` ([\#4025](https://github.com/informalsystems/hermes/issues/4025)) + - Update the version of Neutron running the integration tests in the CI from `v3.0.2` + to `v3.0.5` ([\#4026](https://github.com/informalsystems/hermes/issues/4026)) + - Update the version of Celestia app running the integration tests in the CI from `v1.4.0` + to `v1.11.0` ([\#4027](https://github.com/informalsystems/hermes/issues/4027)) + - Update the version of `wasmd` running the integration tests in the CI from `v0.50.0` + to `v0.51.0` ([\#4029](https://github.com/informalsystems/hermes/issues/4029)) + - Reduce run time for ICS29 tests by immediately verifying if either + the legacy fees, `recv_fee + ack_fee + timeout_fee` or current + fees, `max(recv_fee + ack_fee, timeout_fee)` have been escrowed. + ([\#4053](https://github.com/informalsystems/hermes/issues/4053)) + - Refactored the test-framework bootstrapping for n-ary chain tests + to utilize the specified topology. + * Currently, only linear, cyclic and fully connected topologies are supported. + ([\#4038](https://github.com/informalsystems/hermes/issues/4038)) +- [Relayer Library](relayer) + - Use custom User-Agent for Hermes queries + ([\#3979](https://github.com/informalsystems/hermes/issues/3979)) + - Updated the channel and port filter parsing to ignore whitespaces. + This will prevent unintended channel scanning due to accidental + whitespaces when exact matches are specified in the `packet_filter` + configuration. + ([\#4045](https://github.com/informalsystems/hermes/issues/4045)) + - Improve the `excluded_sequences` configuration so that it now accepts + ranges of sequence values in addition to exact values. + Accepted format: + * Exact sequence, e.g. [1, 2, 3] + * "-" separator, e.g. ["1-3"] + + These can be combined making the following configurations equivalent: + * `excluded_sequences = { 'channel-0' = [1, "3-5", 7, "9-12"] }` + * `excluded_sequences = { 'channel-0' = [1, 3, 4, 5, 7, 9, 10, 11, 12] }` + + ([\#4047](https://github.com/informalsystems/hermes/issues/4047)) + +## v1.9.0 + +*May 30th, 2024* + +This v1.9.0 release introduces new features and improvements to Hermes. + +**Major Features**: + +1. **Channel Upgrades:** Hermes now handles [channel upgrade](https://www.ibcprotocol.dev/blog/introducing-ibc-channel-upgradability) events introduced in ibc-go v8, helping chains opting-in to new functionality on existing channels. +2. **Dynamic Gas Fees Compatibility:** Hermes is now compatible with Skip's `x/feemarket` module for dynamic gas fees, in addition to Osmosis' implementation, providing more flexibility in gas fee management. + +Additionally, this release includes various bug fixes enhancing the stability and performance of Hermes. These fixes address issues with channel and connection creation on older ibc-go versions, event extraction, health-check messages, and more. + +### BREAKING CHANGES + +- [Telemetry & Metrics](telemetry) + - Remove the `telemetry` and `rest-server` feature flags, ensuring Hermes is always built with telemetry and REST support. + Both servers can still be disabled in the configuration file, by setting `telemetry.enabled = false` and `rest.enabled = false`, respectively. + ([\#3878](https://github.com/informalsystems/hermes/pull/3878)) + +### FEATURES + +- [Relayer Library](relayer) + - Add support for upgrading channels, as per the [ICS 004 specification](https://github.com/cosmos/ibc/blob/main/spec/core/ics-004-channel-and-packet-semantics/UPGRADES.md) ([#3228](https://github.com/informalsystems/hermes/issues/2547)) + This feature allows chains to upgrade an existing channel to take advantage of new features without having to create a new channel, thus preserving all existing packet state processed on the channel. For example, a channel could now be upgraded to enable the [ICS 029 fee middleware](https://ibc.cosmos.network/main/middleware/ics29-fee/overview), allowing relayer operators on that channel to receive fees each time they relay an incentivized packet. + - Improve reliability of event source in `pull` mode by proceeding to next block even if Hermes cannot parse the current block. + Add new configuration option to `event_source` setting: `max_retries` defines how many times Hermes should attempt to pull a block over RPC. + ```toml + event_source = { mode = 'pull', interval = '1s', max_retries = 4 } + ``` + ([\#3894](https://github.com/informalsystems/hermes/issues/3894)) + +### IMPROVEMENTS + +- [Integration Test Framework](tools/test-framework) + - Update the version of Juno running the integration tests in the CI from `v17.1.1` + to `v21.0.0` ([\#3959](https://github.com/informalsystems/hermes/issues/3959)) + - Update the version of Migaloo Chain running the + integration tests in the CI from `v3.0.2` to `v4.1.3` + ([\#3960](https://github.com/informalsystems/hermes/issues/3960)) + - Update the version of `wasmd` running the + integration tests in the CI from `v0.30.0` to `v0.50.0` + ([\#3961](https://github.com/informalsystems/hermes/issues/3961)) + - Update the version of ibc-go simapp running the + integration tests in the CI from `v8.2.0` to `v8.3.1` + ([\#4009](https://github.com/informalsystems/hermes/issues/4009)) +- [Relayer Library](relayer) + - Update to tendermint-rs v0.35.0 + ([\#3895](https://github.com/informalsystems/hermes/issues/3895)) + - Use `packet_ack_hex` event attribute instead of deprecated `packet_ack` attribute to decode `WriteAck` event + ([\#3921](https://github.com/informalsystems/hermes/issues/3921)) + - Update to tendermint-rs v0.36.0 + ([\#3966](https://github.com/informalsystems/hermes/issues/3966)) + - Add support for dynamic gas fee for chains using Skip's [`x/feemarket`](https://github.com/skip-mev/feemarket) module, while keeping compatibility with Osmosis' bespoke implementation + ([\#4000](https://github.com/informalsystems/hermes/issues/4000)) +- [Relayer CLI](relayer-cli) + - Use RPC (pull) event source instead of WebSocket (push) when generating configuration with `hermes config auto` + ([\#3913](https://github.com/informalsystems/hermes/issues/3913)) + +### BUG FIXES + +- [Relayer Library](relayer) + - Fix creation of channels and connection on chains + using an unsupported version of ibc-go, eg. Sei + ([\#3817](https://github.com/informalsystems/hermes/issues/3817)) + - Fix a bug where Hermes would only ever extract the first emitted ICS 031 CrossChain Query event, which would cause it to miss the other CCQ events. + ([\#3954](https://github.com/informalsystems/hermes/issues/3954)) +- [Relayer CLI](relayer-cli) + - Fixed `minimum-gas-prices` health-check messages and make it more verbose and legible + ([\#3893](https://github.com/informalsystems/hermes/issues/3893)) + - Set `compat_mode` for pull mode in `hermes listen` command + ([\#3910](https://github.com/informalsystems/hermes/issues/3910)) + - Fixed the trusted height consensus state query when submitting the double vote evidence + ([\#3999](https://github.com/informalsystems/hermes/issues/3999)) + +## v1.8.3 + +*May 28th, 2024* + +This patch release fixes a bug that may happen prevent the relayer from submitting the evidence for a duplicate vote in some cases. + +### BUG FIXES + +- [Relayer CLI](relayer-cli) + - Fix the trusted height consensus state query when submitting the double vote evidence + ([\#3999](https://github.com/informalsystems/hermes/issues/3999)) + +## v1.8.2 + +*March 12th, 2024* + +This release fixes the two following bugs and improves the connection and channel handshake retry mechanism: + +* Fix erroneous warnings for incompatible version of IBC-Go during health checks, ensuring accurate compatibility reporting +* Fix a bug in the `clear packets` command which caused packet clearing to fail with an "counterparty channel not found" error + +### BUG FIXES + +- [Relayer CLI](relayer-cli) + - Correctly use the counterparty channel and port IDs when clearing the packets + from the destination chain to the source chain in the `packet clear` command + ([\#3889](https://github.com/informalsystems/hermes/issues/3889)) +- [Relayer](relayer) + - Fix parsing of IBC-Go version in health check and improve health check + reporting ([\#3880](https://github.com/informalsystems/hermes/issues/3880)) + +### FEATURES + +- [Integration Test Framework](tools/test-framework) + - Add Injective chain to the chains running the integration tests in the CI. + ([\#3887](https://github.com/informalsystems/hermes/issues/3887)) + +### IMPROVEMENTS + +- [Relayer](relayer) + - Change connection and channel handshake retry strategy + to retry at most 10 times (5 times per block max) + ([\#3864](https://github.com/informalsystems/hermes/issues/3864)) + +## v1.8.1 + +*March 7th, 2024* + +This v1.8.1 release brings better reliability when relaying, more enhanced configuration and improved monitoring. + +Reliability has been improved: +* It is now possible to relay ICS-04 packets with non-UTF-8 payloads +* Packet sequences are now verified for ordered channels before trying to relay + +Additional per-chain configurations have been added: +* `excluded_sequences` used to skip problematic packets when clearing +* `memo_overwrite` allowing users to overwrite the relayer memo when chains have a strict limit for the size of the memo. + +Monitoring issues improvements: +* A new metric `simulate_errors` which counts the number of failed simulated transactions +* Out of gas error diagnostic gives more information and a dedicated entry to the guide has been added +* Failed gas simulation will not be considered as unrecoverable for legacy chains. +* The compatibility check during the health-check has been improved will assess more correctly the versions for Ibc-Go and Cosmos SDK + +Special thanks to our contributors for their valuable additions to this release: + +* Sergey (@freak12techno) for adding the `simulate_errors` metric ([#3845]) +* Martin Dyring-Andersen (@mdyring) for adding recovery from failed gas simulation for legacy chains ([#3792]) + +### BUG FIXES + +- Allow relaying ICS-04 packets with non-UTF-8 payloads ([\#3770](https://github.com/informalsystems/hermes/issues/3770)) + Hermes does not assume anymore that an ICS-04 packet data is valid UTF-8, + by using the `packet_data_hex` attribute when assembling a packet from events, instead of the deprecated `packet_data` attribute. + Relying on the `packet_data` attribute enforces a UTF-8 encoded payload (eg. JSON), disallowing eg. Protobuf-encoded payloads. + The `packet_data` attribute [has been deprecated][0] in favor of `packet_data_hex` since IBC-Go v1.0.0. +- Improve reliability of compatibility check and fix parsing of expected modules versions ([\#3831](https://github.com/informalsystems/hermes/issues/3831)) + +[0]: https://github.com/cosmos/ibc-go/blob/fadf8f2b0ab184798d021d220d877e00c7634e26/CHANGELOG.md?plain=1#L1417 + +### FEATURES + +- Add a per-chain configuration `excluded_sequences` allowing users to specify a list of packet sequences which will not be cleared. + This configuration has no impact on standard packet relaying. + ([\#3754](https://github.com/informalsystems/hermes/issues/3754)) +- Add a per-chain configuration `memo_overwrite` allowing users to overwrite the relayer memo used for each transaction + ([\#3811](https://github.com/informalsystems/hermes/issues/3811)) +- Added a new Prometheus metric `simulate_errors` for tracking when a transaction simulation fails, with the following labels: + ([\#3845](https://github.com/informalsystems/hermes/issues/3845)) + * `recoverable` (can the execution continue if this happened?) + * `account` (account from which the tx was sent) + * `error_description` (description of the error) + + ``` + # HELP simulate_errors_total Number of errors observed by Hermes when simulating a Tx + # TYPE simulate_errors_total counter + simulate_errors_total{account="osmo17ndx5qfku28ymxgmq6zq4a6d02dvpfjjul0hyh",error_description="Unknown error",recoverable="false",service_name="unknown_service",otel_scope_name="hermes",otel_scope_version=""} 4 + ``` + +### IMPROVEMENTS + +- Use the consensus state at client latest height in status CLI ([#3814](https://github.com/informalsystems/ibc-rs/issues/3814)) +- Add syncing check for gRPC node ([#3814](https://github.com/informalsystems/ibc-rs/issues/3814)) +- Improve the log diagnostic when an out of gas error is thrown. + And a new entry related to gas error has been added to the Hermes guide. + ([\#3530](https://github.com/informalsystems/hermes/issues/3530)) +- Improve resilience when relaying on ordered channels. + When relaying packets on an ordered channel, Hermes will now attempt + to detect whether the next message to send has the sequence number + expected on that channel. If there is a mismatch, then Hermes will trigger a packet + clear on the channel to unblock it before resuming operations on that channel. + ([\#3540](https://github.com/informalsystems/hermes/issues/3540)) +- Recover from gas simulation failures on legacy chains. + ([\#3792](https://github.com/informalsystems/hermes/issues/3792)) + +## v1.8.0 + +*January 23rd, 2024* + +This v1.8.0 release introduces new features and improvements to Hermes. + +One key feature is that Hermes is now compatible with both the legacy `UpgradeProposal` and the newer `MsgIbcSoftwareUpgrade` message when upgrading a chain. +This allows Hermes to be compatible with ibc-go v8.0.0. The compatibility check that Hermes performs on startup has been updated to reflect this. + +Additional configuration settings have been added: + +- The new global settings `ics20_max_memo_size` and `ics20_max_receiver_size` allow users to specify a limit for the size of the memo and receiver fields for ICS20 packets. Any packet with either field having a size exceeding the configured values will not be relayed. +- The new per-chain setting `query_packets_chunk_size` allows users to specify how many packets are queried at once from the chain when clearing pending packets. This is useful to tweak when there are many large pending packets and the RPC endpoints times out or refuses to answer the pending packets query. +- The new per-chain setting `client_refresh_rate` can be use to specify how often the clients referencing this chain should be refreshed. The rate is expressed as a fraction of the trusting period. +- The new per-chain setting `dynamic_gas_price` can be enabled to have the relayer query for and use a dynamic gas price instead of using the static `gas_price` specified in the config. This should only be used for chains which have a [EIP-1559][eip-1559]-like fee market enabled and support the `osmosis.txfees.v1beta1.Query/GetEipBaseFee` gRPC query. + +Telemetry now features new metrics: +- Monitoring the ICS20 packets filtered due to the memo and/or receiver field size exceeding the configured limits. +- Monitoring the distribution of dynamic gas fees queried from the chain, if enabled. + +[eip-1559]: https://metamask.io/1559/ + +### BREAKING CHANGES + +- Bump MSRV to 1.71 ([\#3688](https://github.com/informalsystems/hermes/issues/3688)) + +### FEATURES + +- Relayer + - 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)) + - Add a new per-chain configuration table `dynamic_gas_price` which enables + querying the current gas price from the chain instead of the static `gas_price`, + when the chain has [EIP-1559][eip]-like dynamic gas price. + The new configuration setting can be configured per-chain as follows: + ```toml + dynamic_gas_price = { enabled = true, multiplier = 1.1, max = 0.6 } + ``` + At the moment, only chains which support the `osmosis.txfees.v1beta1.Query/GetEipBaseFee` + query can be used with dynamic gas price enabled. + ([\#3738](https://github.com/informalsystems/hermes/issues/3738)) + + [eip]: https://metamask.io/1559/ + - Add two new packet configurations: + * `ics20_max_memo_size` which filters ICS20 packets with memo field bigger than the configured value + * `ics20_max_receiver_size` which filters ICS20 packets with receiver field bigger than the configured value + ([\#3766](https://github.com/informalsystems/hermes/issues/3766)) + - Add a `client_refresh_rate` setting to specify the rate at which to refresh clients referencing this chain, relative to its trusting period. + ([\#3402](https://github.com/informalsystems/hermes/issues/3402)) + - Add a `--packet-sequences` flag to the `clear packets`, `tx packet-recv`, and `tx packet-ack` commands. + When this flag is specified, these commands will only clear the packets with the specified sequence numbers + on the given chain. If not provided, all pending packets will be cleared on both chains, as before. + ([\#3672](https://github.com/informalsystems/hermes/issues/3672)) + + This flag takes either a single sequence number or a range of sequences numbers. + Each element of the comma-separated list must be either a single sequence number or + a range of sequence numbers. + + Examples: + - `10` will clear a single packet with sequence number `10` + - `1,2,3` will clear packets with sequence numbers `1, 2, 3` + - `1..5` will clear packets with sequence numbers `1, 2, 3, 4, 5` + - `..5` will clear packets with sequence numbers `1, 2, 3, 4, 5` + - `5..` will clear packets with sequence numbers greater than or equal to `5` + - `..5,10..20,25,30..` will clear packets with sequence numbers `1, 2, 3, 4, 5, 10, 11, ..., 20, 25, 30, 31, ...` + - `..5,10..20,25,30..` will clear packets with sequence numbers `1, 2, 3, 4, 5, 10, 11, ..., 20, 25, 30, 31, ...` + - 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)) + - Add a `query_packets_chunk_size` config option and a `--query-packets-chunk-size` flag to the `clear packets` CLI to configure how + many packets to query at once from the chain when clearing pending packets. Lower this setting if one or more of packets you are + trying to clear are huge and make the packet query time out or fail. + ([\#3743](https://github.com/informalsystems/hermes/issues/3743)) +- Telemetry & Metrics + - Add three metrics related to EIP gas price: + - `dynamic_gas_queried_fees` contains data on the queried values before applying any filter + - `dynamic_gas_queried_success_fees` contains data on the queried values if the query was successful and before applying any filter + - `dynamic_gas_paid_fees` contains data on the queried values after applying the `max` filter + ([\#3738](https://github.com/informalsystems/hermes/issues/3738)) + - Add a new metric `filtered_packets` which counts the number of packets filtered due to having a memo or receiver field too big + ([\#3794](https://github.com/informalsystems/hermes/issues/3794)) +- Integration Test Framework + - Add a test for asynchronous Interchain Query relaying + ([\#3455](https://github.com/informalsystems/hermes/issues/3455)) + - Add an ICA test to assert a channel correctly closes after a packet time-outs + ([\#3778](https://github.com/informalsystems/hermes/issues/3778)) + +### IMPROVEMENTS + +- Relayer CLI + - Update compatibility check to allow IBC-Go 4.1.1 to 8.x and SDK 0.45.x to 0.50.x. + ([\#3745](https://github.com/informalsystems/hermes/issues/3745)) + ## v1.7.4 *December 15th, 2023* diff --git a/Cargo.lock b/Cargo.lock index a7aa63c819..10e25dba9e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,7 +35,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a3473aa652e90865a06b723102aaa4a54a7d9f2092dbf4582497a61d0537d3f" dependencies = [ "ident_case", - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", "syn 1.0.109", "synstructure", @@ -71,7 +71,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cipher 0.4.4", "cpufeatures", ] @@ -82,7 +82,7 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "once_cell", "version_check", "zerocopy", @@ -169,9 +169,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" [[package]] name = "arc-swap" @@ -278,7 +278,7 @@ checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" dependencies = [ "num-bigint", "num-traits", - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", "syn 1.0.109", ] @@ -360,7 +360,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", "syn 1.0.109", ] @@ -390,9 +390,9 @@ dependencies = [ [[package]] name = "arrayref" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" @@ -409,7 +409,7 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "astria-core" version = "0.1.0" -source = "git+https://github.com/astriaorg/astria?tag=sequencer-v0.16.0#6251eaae61cb0f22b4c9f1f6cf6dcbf980a8c95f" +source = "git+https://github.com/astriaorg/astria?rev=070cfee5b87c82819f87dc62a48870c5c22bc108#070cfee5b87c82819f87dc62a48870c5c22bc108" dependencies = [ "astria-merkle", "base64 0.21.7", @@ -419,11 +419,11 @@ dependencies = [ "ed25519-consensus", "hex", "ibc-types", - "indexmap 2.5.0", + "indexmap 2.6.0", "pbjson-types", "penumbra-ibc", "penumbra-proto", - "prost 0.12.6", + "prost 0.13.3", "rand", "sha2 0.10.8", "tendermint", @@ -433,10 +433,19 @@ dependencies = [ "zeroize", ] +[[package]] +name = "astria-eyre" +version = "0.1.0" +source = "git+https://github.com/astriaorg/astria?rev=070cfee5b87c82819f87dc62a48870c5c22bc108#070cfee5b87c82819f87dc62a48870c5c22bc108" +dependencies = [ + "eyre", + "itoa", +] + [[package]] name = "astria-merkle" version = "0.1.0" -source = "git+https://github.com/astriaorg/astria?tag=sequencer-v0.16.0#6251eaae61cb0f22b4c9f1f6cf6dcbf980a8c95f" +source = "git+https://github.com/astriaorg/astria?rev=070cfee5b87c82819f87dc62a48870c5c22bc108#070cfee5b87c82819f87dc62a48870c5c22bc108" dependencies = [ "sha2 0.10.8", ] @@ -444,14 +453,16 @@ dependencies = [ [[package]] name = "astria-sequencer-client" version = "0.1.0" -source = "git+https://github.com/astriaorg/astria?tag=sequencer-v0.16.0#6251eaae61cb0f22b4c9f1f6cf6dcbf980a8c95f" +source = "git+https://github.com/astriaorg/astria?rev=070cfee5b87c82819f87dc62a48870c5c22bc108#070cfee5b87c82819f87dc62a48870c5c22bc108" dependencies = [ "astria-core", + "astria-eyre", "async-trait", "futures", "futures-util", "hex", - "prost 0.12.6", + "humantime", + "prost 0.13.3", "tendermint", "tendermint-proto", "tendermint-rpc", @@ -459,13 +470,14 @@ dependencies = [ "tokio", "tokio-stream", "tracing", + "tryhard", ] [[package]] name = "async-stream" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", @@ -474,42 +486,49 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] name = "async-trait" -version = "0.1.82" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] name = "async-tungstenite" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e9efbe14612da0a19fb983059a0b621e9cf6225d7018ecab4f9988215540dc" +checksum = "3609af4bbf701ddaf1f6bb4e6257dff4ff8932327d0e685d3f653724c258b1ac" dependencies = [ "futures-io", "futures-util", "log", "pin-project-lite", - "rustls-native-certs", + "rustls-native-certs 0.7.3", + "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.25.0", "tungstenite", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "atty" version = "0.2.14" @@ -523,9 +542,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axum" @@ -534,13 +553,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" dependencies = [ "async-trait", - "axum-core", + "axum-core 0.3.4", "bitflags 1.3.2", "bytes", "futures-util", - "http", - "http-body", - "hyper", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.30", "itoa", "matchit", "memchr", @@ -552,9 +571,36 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 0.1.2", "tokio", - "tower", + "tower 0.4.13", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" +dependencies = [ + "async-trait", + "axum-core 0.4.5", + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper 1.0.1", + "tower 0.5.1", "tower-layer", "tower-service", ] @@ -568,10 +614,30 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", "mime", + "pin-project-lite", "rustversion", + "sync_wrapper 1.0.1", "tower-layer", "tower-service", ] @@ -584,7 +650,7 @@ checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", - "cfg-if 1.0.0", + "cfg-if", "libc", "miniz_oxide", "object", @@ -597,12 +663,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64" version = "0.21.7" @@ -780,7 +840,7 @@ dependencies = [ "arrayref", "arrayvec 0.7.6", "cc", - "cfg-if 1.0.0", + "cfg-if", "constant_time_eq 0.3.1", ] @@ -804,47 +864,26 @@ dependencies = [ [[package]] name = "borsh" -version = "0.10.3" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" +checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" dependencies = [ "borsh-derive", - "hashbrown 0.13.2", + "cfg_aliases", ] [[package]] name = "borsh-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" -dependencies = [ - "borsh-derive-internal", - "borsh-schema-derive-internal", - "proc-macro-crate 0.1.5", - "proc-macro2 1.0.86", - "syn 1.0.109", -] - -[[package]] -name = "borsh-derive-internal" -version = "0.10.3" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" +checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b" dependencies = [ - "proc-macro2 1.0.86", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "borsh-schema-derive-internal" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" -dependencies = [ - "proc-macro2 1.0.86", + "once_cell", + "proc-macro-crate", + "proc-macro2 1.0.87", "quote", - "syn 1.0.109", + "syn 2.0.79", + "syn_derive", ] [[package]] @@ -887,9 +926,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" dependencies = [ "serde", ] @@ -902,18 +941,18 @@ checksum = "e6e9e01327e6c86e92ec72b1c798d4a94810f147209bbe3ffab6a86954937a6f" [[package]] name = "cc" -version = "1.1.16" +version = "1.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9d013ecb737093c0e86b151a7b837993cf9ec6c502946cfb44bedc392421e0b" +checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" dependencies = [ "shlex", ] [[package]] name = "celestia-tendermint" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95f93b5cbbd62b6cfde961889bf05d5fe19e70d8500c4465694306ed2695ac23" +checksum = "ce8c92a01145f79a0f3ac7c44a43a9b5ee58e8a4c716b56d98833a3848db1afd" dependencies = [ "bytes", "celestia-tendermint-proto", @@ -925,7 +964,7 @@ dependencies = [ "num-traits", "once_cell", "prost 0.12.6", - "prost-types", + "prost-types 0.12.6", "serde", "serde_bytes", "serde_json", @@ -940,16 +979,16 @@ dependencies = [ [[package]] name = "celestia-tendermint-proto" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8f7d49c1ececa30a4587c5fe8a4035b786b78a3253ed0f9636de591b3dc2b37" +checksum = "9a95746c5221a74d7b913a415fdbb9e7c90e1b4d818dbbff59bddc034cfce2ec" dependencies = [ "bytes", "flex-error", "num-derive", "num-traits", "prost 0.12.6", - "prost-types", + "prost-types 0.12.6", "serde", "serde_bytes", "subtle-encoding", @@ -958,15 +997,15 @@ dependencies = [ [[package]] name = "cfg-if" -version = "0.1.10" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "cfg-if" -version = "1.0.0" +name = "cfg_aliases" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chacha20" @@ -974,7 +1013,7 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c80e5460aa66fe3b91d40bcbdab953a597b60053e34d684ac6903f863b680a6" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cipher 0.3.0", "cpufeatures", "zeroize", @@ -1059,7 +1098,7 @@ checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" dependencies = [ "heck 0.4.1", "proc-macro-error", - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", "syn 1.0.109", ] @@ -1143,7 +1182,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1d1429e3bd78171c65aa010eabcdf8f863ba3254728dbfb0ad4b1545beac15c" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", "syn 1.0.109", ] @@ -1166,30 +1205,20 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] -[[package]] -name = "crossbeam-channel" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" -dependencies = [ - "crossbeam-utils 0.7.2", - "maybe-uninit", -] - [[package]] name = "crossbeam-channel" version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ - "crossbeam-utils 0.8.20", + "crossbeam-utils", ] [[package]] @@ -1199,7 +1228,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ "crossbeam-epoch", - "crossbeam-utils 0.8.20", + "crossbeam-utils", ] [[package]] @@ -1208,18 +1237,7 @@ version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "crossbeam-utils 0.8.20", -] - -[[package]] -name = "crossbeam-utils" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" -dependencies = [ - "autocfg", - "cfg-if 0.1.10", - "lazy_static", + "crossbeam-utils", ] [[package]] @@ -1262,7 +1280,7 @@ version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest 0.10.7", @@ -1278,9 +1296,9 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1314,10 +1332,10 @@ checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", "strsim 0.11.1", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1328,7 +1346,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1337,7 +1355,7 @@ version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "hashbrown 0.14.5", "lock_api", "once_cell", @@ -1366,7 +1384,7 @@ dependencies = [ "ark-serialize", "ark-snark", "ark-std", - "cfg-if 1.0.0", + "cfg-if", "hashbrown 0.14.5", "hex", "num-bigint", @@ -1378,8 +1396,8 @@ dependencies = [ [[package]] name = "decaf377-fmd" -version = "0.80.2" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=87adc8d6b15f6081c1adf169daed4ca8873bd9f6#87adc8d6b15f6081c1adf169daed4ca8873bd9f6" +version = "0.80.6" +source = "git+https://github.com/noot/penumbra.git?rev=93fe7fd0771a958e3888c158d9d1fb94322724f1#93fe7fd0771a958e3888c158d9d1fb94322724f1" dependencies = [ "ark-ff", "ark-serialize", @@ -1392,8 +1410,8 @@ dependencies = [ [[package]] name = "decaf377-ka" -version = "0.80.2" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=87adc8d6b15f6081c1adf169daed4ca8873bd9f6#87adc8d6b15f6081c1adf169daed4ca8873bd9f6" +version = "0.80.6" +source = "git+https://github.com/noot/penumbra.git?rev=93fe7fd0771a958e3888c158d9d1fb94322724f1#93fe7fd0771a958e3888c158d9d1fb94322724f1" dependencies = [ "ark-ff", "decaf377", @@ -1454,7 +1472,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", "syn 1.0.109", ] @@ -1465,20 +1483,21 @@ version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] name = "dialoguer" -version = "0.10.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59c6f2989294b9a498d3ad5491a79c6deb604617378e1cdc4bfc1c1361fe2f87" +checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de" dependencies = [ "console", "shell-words", "tempfile", + "thiserror", "zeroize", ] @@ -1509,7 +1528,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "dirs-sys-next", ] @@ -1530,9 +1549,9 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1645,7 +1664,7 @@ version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -1655,19 +1674,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" dependencies = [ "log", -] - -[[package]] -name = "env_logger" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" -dependencies = [ - "humantime", - "is-terminal", - "log", "regex", - "termcolor", ] [[package]] @@ -1679,6 +1686,7 @@ dependencies = [ "anstream", "anstyle", "env_filter", + "humantime", "log", ] @@ -1777,7 +1785,6 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c606d892c9de11507fa0dcffc116434f94e105d0bbdc4e405b61519464c49d7b" dependencies = [ - "anyhow", "eyre", "paste", ] @@ -1814,9 +1821,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1829,9 +1836,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1839,15 +1846,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1856,38 +1863,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -1918,7 +1925,7 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "libc", "wasi", @@ -1957,7 +1964,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "729f9bd3449d77e7831a18abfb7ba2f99ee813dfd15b8c2167c9a54ba20aa99d" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", "syn 1.0.109", ] @@ -1973,8 +1980,27 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", - "indexmap 2.5.0", + "http 0.2.12", + "indexmap 2.6.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.1.0", + "indexmap 2.6.0", "slab", "tokio", "tokio-util", @@ -2018,6 +2044,12 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + [[package]] name = "hdpath" version = "0.6.3" @@ -2054,12 +2086,6 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" -[[package]] -name = "hermit-abi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" - [[package]] name = "hex" version = "0.4.3" @@ -2098,6 +2124,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http-body" version = "0.4.6" @@ -2105,15 +2142,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", "pin-project-lite", ] [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -2147,9 +2207,9 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", - "http", - "http-body", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa", @@ -2161,6 +2221,27 @@ dependencies = [ "want", ] +[[package]] +name = "hyper" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + [[package]] name = "hyper-rustls" version = "0.24.2" @@ -2168,30 +2249,50 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", - "http", - "hyper", - "rustls", + "http 0.2.12", + "hyper 0.14.30", + "rustls 0.21.12", "tokio", - "tokio-rustls", + "tokio-rustls 0.24.1", ] [[package]] name = "hyper-timeout" -version = "0.4.1" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" +dependencies = [ + "hyper 1.4.1", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "hyper", + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "hyper 1.4.1", "pin-project-lite", + "socket2", "tokio", - "tokio-io-timeout", + "tower-service", + "tracing", ] [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -2212,15 +2313,16 @@ dependencies = [ [[package]] name = "ibc-chain-registry" -version = "0.26.4" +version = "0.29.3" dependencies = [ "async-trait", "flex-error", "futures", - "http", + "http 1.1.0", "ibc-proto", + "ibc-relayer", "ibc-relayer-types", - "itertools 0.10.5", + "itertools 0.13.0", "reqwest", "serde", "serde_json", @@ -2231,17 +2333,16 @@ dependencies = [ [[package]] name = "ibc-integration-test" -version = "0.26.4" +version = "0.29.3" dependencies = [ "byte-unit", - "http", + "http 1.1.0", "ibc-relayer", "ibc-relayer-types", "ibc-test-framework", - "prost 0.12.6", + "prost 0.13.3", "serde", "serde_json", - "tempfile", "tendermint", "tendermint-rpc", "time", @@ -2251,16 +2352,16 @@ dependencies = [ [[package]] name = "ibc-proto" -version = "0.41.0" +version = "0.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4ee32b22d3b06f31529b956f4928e5c9a068d71e46cf6abfa19c31ca550553" +checksum = "c852d22b782d2d793f4a646f968de419be635e02bc8798d5d74a6e44eef27733" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "bytes", "flex-error", - "ics23 0.11.3", - "informalsystems-pbjson 0.7.0", - "prost 0.12.6", + "ics23", + "informalsystems-pbjson", + "prost 0.13.3", "serde", "subtle-encoding", "tendermint-proto", @@ -2269,7 +2370,7 @@ dependencies = [ [[package]] name = "ibc-relayer" -version = "0.26.4" +version = "0.29.3" dependencies = [ "anyhow", "astria-core", @@ -2280,27 +2381,27 @@ dependencies = [ "bs58", "byte-unit", "bytes", - "crossbeam-channel 0.5.13", + "crossbeam-channel", "digest 0.10.7", "dirs-next", "ed25519", "ed25519-consensus", "ed25519-dalek", "ed25519-dalek-bip32", - "env_logger 0.10.2", + "env_logger", "flex-error", "futures", "generic-array", "hdpath", "hex", - "http", + "http 1.1.0", "humantime", "humantime-serde", "ibc-proto", "ibc-relayer-types", "ibc-telemetry", "ibc-types", - "itertools 0.10.5", + "itertools 0.13.0", "jmt", "moka", "num-bigint", @@ -2309,8 +2410,9 @@ dependencies = [ "pbjson-types", "penumbra-ibc", "penumbra-proto", - "prost 0.12.6", + "prost 0.13.3", "regex", + "reqwest", "retry", "ripemd", "secp256k1", @@ -2345,28 +2447,28 @@ dependencies = [ [[package]] name = "ibc-relayer-cli" -version = "1.7.4" +version = "1.10.3" dependencies = [ "abscissa_core", "clap", "clap_complete", "color-eyre", "console", - "crossbeam-channel 0.5.13", + "crossbeam-channel", "dialoguer", "dirs-next", "eyre", "flex-error", "futures", "hdpath", - "http", + "http 1.1.0", "humantime", "ibc-chain-registry", "ibc-relayer", "ibc-relayer-rest", "ibc-relayer-types", "ibc-telemetry", - "itertools 0.10.5", + "itertools 0.13.0", "once_cell", "oneline-eyre", "regex", @@ -2386,10 +2488,10 @@ dependencies = [ [[package]] name = "ibc-relayer-rest" -version = "0.26.4" +version = "0.29.3" dependencies = [ - "axum", - "crossbeam-channel 0.5.13", + "axum 0.6.20", + "crossbeam-channel", "ibc-relayer", "ibc-relayer-types", "reqwest", @@ -2401,18 +2503,18 @@ dependencies = [ [[package]] name = "ibc-relayer-types" -version = "0.26.4" +version = "0.29.3" dependencies = [ "bytes", "derive_more", - "env_logger 0.10.2", + "env_logger", "flex-error", "ibc-proto", - "ics23 0.11.3", - "itertools 0.10.5", + "ics23", + "itertools 0.13.0", "num-rational", "primitive-types", - "prost 0.12.6", + "prost 0.13.3", "regex", "serde", "serde_derive", @@ -2432,9 +2534,9 @@ dependencies = [ [[package]] name = "ibc-telemetry" -version = "0.26.4" +version = "0.29.3" dependencies = [ - "axum", + "axum 0.6.20", "dashmap", "ibc-relayer-types", "moka", @@ -2451,22 +2553,22 @@ dependencies = [ [[package]] name = "ibc-test-framework" -version = "0.26.4" +version = "0.29.3" dependencies = [ "color-eyre", - "crossbeam-channel 0.5.13", + "crossbeam-channel", "eyre", "flex-error", "hdpath", "hex", - "http", + "http 1.1.0", "ibc-proto", "ibc-relayer", "ibc-relayer-cli", "ibc-relayer-types", - "itertools 0.10.5", + "itertools 0.13.0", "once_cell", - "prost 0.12.6", + "prost 0.13.3", "rand", "semver", "serde", @@ -2484,9 +2586,8 @@ dependencies = [ [[package]] name = "ibc-types" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f45534bc1118d30f6537040bdf822f17245dcb5467a14094070f7365d49428df" +version = "0.14.1" +source = "git+https://github.com/noot/ibc-types.git?rev=b1c17a074980216a8f8d620937c77357b1797bac#b1c17a074980216a8f8d620937c77357b1797bac" dependencies = [ "ibc-types-core-channel", "ibc-types-core-client", @@ -2502,9 +2603,8 @@ dependencies = [ [[package]] name = "ibc-types-core-channel" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dcce2afa6b83fc6f6bd0d626d3f31aaf62a9e9087fcef24e0f705148915cb56" +version = "0.14.1" +source = "git+https://github.com/noot/ibc-types.git?rev=b1c17a074980216a8f8d620937c77357b1797bac#b1c17a074980216a8f8d620937c77357b1797bac" dependencies = [ "anyhow", "bytes", @@ -2517,10 +2617,10 @@ dependencies = [ "ibc-types-domain-type", "ibc-types-identifier", "ibc-types-timestamp", - "ics23 0.11.3", + "ics23", "num-traits", "proc-macro2 0.1.10", - "prost 0.12.6", + "prost 0.13.3", "safe-regex", "serde", "serde_json", @@ -2534,9 +2634,8 @@ dependencies = [ [[package]] name = "ibc-types-core-client" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99ea8df52f9218da5f8e7daed1b22ca6b01b64711950b1c72a493f2d11660b9f" +version = "0.14.1" +source = "git+https://github.com/noot/ibc-types.git?rev=b1c17a074980216a8f8d620937c77357b1797bac#b1c17a074980216a8f8d620937c77357b1797bac" dependencies = [ "anyhow", "bytes", @@ -2546,9 +2645,9 @@ dependencies = [ "ibc-types-domain-type", "ibc-types-identifier", "ibc-types-timestamp", - "ics23 0.11.3", + "ics23", "num-traits", - "prost 0.12.6", + "prost 0.13.3", "serde", "serde_json", "sha2 0.10.8", @@ -2560,9 +2659,8 @@ dependencies = [ [[package]] name = "ibc-types-core-commitment" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b3583a2b7bd4d7f0b75177b619e9b0e0c317ece069170a348675913ad9a8125" +version = "0.14.1" +source = "git+https://github.com/noot/ibc-types.git?rev=b1c17a074980216a8f8d620937c77357b1797bac#b1c17a074980216a8f8d620937c77357b1797bac" dependencies = [ "anyhow", "bytes", @@ -2575,10 +2673,10 @@ dependencies = [ "ibc-types-domain-type", "ibc-types-identifier", "ibc-types-timestamp", - "ics23 0.11.3", + "ics23", "num-traits", "primitive-types", - "prost 0.12.6", + "prost 0.13.3", "safe-regex", "serde", "serde_json", @@ -2594,9 +2692,8 @@ dependencies = [ [[package]] name = "ibc-types-core-connection" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a989af1209864891c95645585fb2048720087968ae419288949965aa65fc4b5" +version = "0.14.1" +source = "git+https://github.com/noot/ibc-types.git?rev=b1c17a074980216a8f8d620937c77357b1797bac#b1c17a074980216a8f8d620937c77357b1797bac" dependencies = [ "anyhow", "bytes", @@ -2608,9 +2705,9 @@ dependencies = [ "ibc-types-domain-type", "ibc-types-identifier", "ibc-types-timestamp", - "ics23 0.11.3", + "ics23", "num-traits", - "prost 0.12.6", + "prost 0.13.3", "safe-regex", "serde", "serde_json", @@ -2623,20 +2720,18 @@ dependencies = [ [[package]] name = "ibc-types-domain-type" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabf22b6da00e7d41dd50e8f3009fc112be5f8c9cdc131d3e37ed264844f5131" +version = "0.14.1" +source = "git+https://github.com/noot/ibc-types.git?rev=b1c17a074980216a8f8d620937c77357b1797bac#b1c17a074980216a8f8d620937c77357b1797bac" dependencies = [ "anyhow", "bytes", - "prost 0.12.6", + "prost 0.13.3", ] [[package]] name = "ibc-types-identifier" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd1070c50d4f031474472d404a77847a32233396cd8397b1145cfd555f88573d" +version = "0.14.1" +source = "git+https://github.com/noot/ibc-types.git?rev=b1c17a074980216a8f8d620937c77357b1797bac#b1c17a074980216a8f8d620937c77357b1797bac" dependencies = [ "displaydoc", "serde", @@ -2644,9 +2739,8 @@ dependencies = [ [[package]] name = "ibc-types-lightclients-tendermint" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50390dbcbcb4d6f34a9ab4a1823196813c6171a9a7c28f0c6f498162c3d3aa0b" +version = "0.14.1" +source = "git+https://github.com/noot/ibc-types.git?rev=b1c17a074980216a8f8d620937c77357b1797bac#b1c17a074980216a8f8d620937c77357b1797bac" dependencies = [ "anyhow", "bytes", @@ -2661,10 +2755,10 @@ dependencies = [ "ibc-types-domain-type", "ibc-types-identifier", "ibc-types-timestamp", - "ics23 0.11.3", + "ics23", "num-traits", "primitive-types", - "prost 0.12.6", + "prost 0.13.3", "safe-regex", "serde", "serde_json", @@ -2680,9 +2774,8 @@ dependencies = [ [[package]] name = "ibc-types-path" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3088ab0bd2a33ccd4fb522497a65a23a540be699f63342ff3c22268708a08271" +version = "0.14.1" +source = "git+https://github.com/noot/ibc-types.git?rev=b1c17a074980216a8f8d620937c77357b1797bac#b1c17a074980216a8f8d620937c77357b1797bac" dependencies = [ "bytes", "derive_more", @@ -2691,7 +2784,7 @@ dependencies = [ "ibc-types-core-client", "ibc-types-core-connection", "num-traits", - "prost 0.12.6", + "prost 0.13.3", "serde", "serde_json", "subtle-encoding", @@ -2702,14 +2795,13 @@ dependencies = [ [[package]] name = "ibc-types-timestamp" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a108c721a477aaf2f3fd8c392577d6c71f03b5c54c8cd09d58365ab7aa16182b" +version = "0.14.1" +source = "git+https://github.com/noot/ibc-types.git?rev=b1c17a074980216a8f8d620937c77357b1797bac#b1c17a074980216a8f8d620937c77357b1797bac" dependencies = [ "bytes", "displaydoc", "num-traits", - "prost 0.12.6", + "prost 0.13.3", "serde", "serde_json", "subtle-encoding", @@ -2720,9 +2812,8 @@ dependencies = [ [[package]] name = "ibc-types-transfer" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f7198d1f63d8428a96a60b2534dbf2bba5594d36745db6166538ef9d89c3fef" +version = "0.14.1" +source = "git+https://github.com/noot/ibc-types.git?rev=b1c17a074980216a8f8d620937c77357b1797bac#b1c17a074980216a8f8d620937c77357b1797bac" dependencies = [ "displaydoc", "serde", @@ -2734,7 +2825,7 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1fcc7f316b2c079dde77564a1360639c1a956a23fa96122732e416cb10717bb" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "num-traits", "rand", "static_assertions", @@ -2742,34 +2833,17 @@ dependencies = [ [[package]] name = "ics23" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "442d4bab37956e76f739c864f246c825d87c0bb7f9afa65660c57833c91bf6d4" -dependencies = [ - "anyhow", - "bytes", - "hex", - "informalsystems-pbjson 0.6.0", - "prost 0.11.9", - "ripemd", - "serde", - "sha2 0.10.8", - "sha3", -] - -[[package]] -name = "ics23" -version = "0.11.3" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18798160736c1e368938ba6967dbcb3c7afb3256b442a5506ba5222eebb68a5a" +checksum = "73b17f1a5bd7d12ad30a21445cfa5f52fd7651cb3243ba866f9916b1ec112f12" dependencies = [ "anyhow", "blake2", "blake3", "bytes", "hex", - "informalsystems-pbjson 0.7.0", - "prost 0.12.6", + "informalsystems-pbjson", + "prost 0.13.3", "ripemd", "serde", "sha2 0.10.8", @@ -2831,7 +2905,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", "syn 1.0.109", ] @@ -2855,22 +2929,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.5", - "serde", -] - -[[package]] -name = "informalsystems-pbjson" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4eecd90f87bea412eac91c6ef94f6b1e390128290898cbe14f2b926787ae1fb" -dependencies = [ - "base64 0.13.1", + "hashbrown 0.15.0", "serde", ] @@ -2895,20 +2959,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.9.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" - -[[package]] -name = "is-terminal" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" -dependencies = [ - "hermit-abi 0.4.0", - "libc", - "windows-sys 0.52.0", -] +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "is_terminal_polyfill" @@ -2927,18 +2980,18 @@ dependencies = [ [[package]] name = "itertools" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] [[package]] name = "itertools" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] @@ -2951,15 +3004,15 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jmt" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1a302f0defd323b833c9848c20ab40c3156128f50d7bf8eebeed2ef58167258" +version = "0.10.0" +source = "git+https://github.com/noot/jmt.git?rev=9a41b264c9db8afb07c337274691e3127411ac47#9a41b264c9db8afb07c337274691e3127411ac47" dependencies = [ "anyhow", "borsh", + "digest 0.10.7", "hashbrown 0.13.2", "hex", - "ics23 0.10.2", + "ics23", "itertools 0.10.5", "mirai-annotations", "num-derive", @@ -2981,11 +3034,11 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "ecdsa", "elliptic-curve", "sha2 0.10.8", @@ -3008,9 +3061,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libredox" @@ -3059,12 +3112,6 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" - [[package]] name = "memchr" version = "2.7.4" @@ -3120,9 +3167,9 @@ version = "0.12.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32cf62eb4dd975d2dde76432fb1075c49e3ee2331cf36f1f8fd4b66550d32b6f" dependencies = [ - "crossbeam-channel 0.5.13", + "crossbeam-channel", "crossbeam-epoch", - "crossbeam-utils 0.8.20", + "crossbeam-utils", "once_cell", "parking_lot", "quanta", @@ -3173,7 +3220,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", "syn 1.0.109", ] @@ -3219,9 +3266,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "oneline-eyre" @@ -3288,7 +3335,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b3a2a91fdbfdd4d212c0dcc2ab540de2c2bcbbd90be17de7a7daf8822d010c1" dependencies = [ "async-trait", - "crossbeam-channel 0.5.13", + "crossbeam-channel", "dashmap", "fnv", "futures-channel", @@ -3339,8 +3386,8 @@ version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 3.2.0", - "proc-macro2 1.0.86", + "proc-macro-crate", + "proc-macro2 1.0.87", "quote", "syn 1.0.109", ] @@ -3361,7 +3408,7 @@ version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "redox_syscall", "smallvec", @@ -3376,9 +3423,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pbjson" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1030c719b0ec2a2d25a5df729d6cff1acf3cc230bf766f4f97833591f7577b90" +checksum = "c7e6349fa080353f4a597daffd05cb81572a9c031a6d4fff7e504947496fcc68" dependencies = [ "base64 0.21.7", "serde", @@ -3386,27 +3433,27 @@ dependencies = [ [[package]] name = "pbjson-build" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2580e33f2292d34be285c5bc3dba5259542b083cfad6037b6d70345f24dcb735" +checksum = "6eea3058763d6e656105d1403cb04e0a41b7bbac6362d413e7c33be0c32279c9" dependencies = [ - "heck 0.4.1", - "itertools 0.11.0", - "prost 0.12.6", - "prost-types", + "heck 0.5.0", + "itertools 0.13.0", + "prost 0.13.3", + "prost-types 0.13.3", ] [[package]] name = "pbjson-types" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18f596653ba4ac51bdecbb4ef6773bc7f56042dc13927910de1684ad3d32aa12" +checksum = "e54e5e7bfb1652f95bc361d76f3c780d8e526b134b85417e774166ee941f0887" dependencies = [ "bytes", "chrono", "pbjson", "pbjson-build", - "prost 0.12.6", + "prost 0.13.3", "prost-build", "serde", ] @@ -3447,7 +3494,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdad6a1d9cf116a059582ce415d5f5566aabcd4008646779dab7fdc2a9a9d426" dependencies = [ "peg-runtime", - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", ] @@ -3459,8 +3506,8 @@ checksum = "e3aeb8f54c078314c2065ee649a7241f46b9d8e418e1a9581ba0546657d7aa3a" [[package]] name = "penumbra-asset" -version = "0.80.2" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=87adc8d6b15f6081c1adf169daed4ca8873bd9f6#87adc8d6b15f6081c1adf169daed4ca8873bd9f6" +version = "0.80.6" +source = "git+https://github.com/noot/penumbra.git?rev=93fe7fd0771a958e3888c158d9d1fb94322724f1#93fe7fd0771a958e3888c158d9d1fb94322724f1" dependencies = [ "anyhow", "ark-ff", @@ -3497,8 +3544,8 @@ dependencies = [ [[package]] name = "penumbra-ibc" -version = "0.80.2" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=87adc8d6b15f6081c1adf169daed4ca8873bd9f6#87adc8d6b15f6081c1adf169daed4ca8873bd9f6" +version = "0.80.6" +source = "git+https://github.com/noot/penumbra.git?rev=93fe7fd0771a958e3888c158d9d1fb94322724f1#93fe7fd0771a958e3888c158d9d1fb94322724f1" dependencies = [ "anyhow", "ark-ff", @@ -3509,7 +3556,7 @@ dependencies = [ "hex", "ibc-proto", "ibc-types", - "ics23 0.11.3", + "ics23", "metrics", "num-traits", "once_cell", @@ -3519,21 +3566,21 @@ dependencies = [ "penumbra-proto", "penumbra-sct", "penumbra-txhash", - "prost 0.12.6", + "prost 0.13.3", "serde", "serde_json", "sha2 0.10.8", "tendermint", "tendermint-light-client-verifier", "time", - "tower", + "tower 0.4.13", "tracing", ] [[package]] name = "penumbra-keys" -version = "0.80.2" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=87adc8d6b15f6081c1adf169daed4ca8873bd9f6#87adc8d6b15f6081c1adf169daed4ca8873bd9f6" +version = "0.80.6" +source = "git+https://github.com/noot/penumbra.git?rev=93fe7fd0771a958e3888c158d9d1fb94322724f1#93fe7fd0771a958e3888c158d9d1fb94322724f1" dependencies = [ "aes", "anyhow", @@ -3576,8 +3623,8 @@ dependencies = [ [[package]] name = "penumbra-num" -version = "0.80.2" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=87adc8d6b15f6081c1adf169daed4ca8873bd9f6#87adc8d6b15f6081c1adf169daed4ca8873bd9f6" +version = "0.80.6" +source = "git+https://github.com/noot/penumbra.git?rev=93fe7fd0771a958e3888c158d9d1fb94322724f1#93fe7fd0771a958e3888c158d9d1fb94322724f1" dependencies = [ "anyhow", "ark-ff", @@ -3612,8 +3659,8 @@ dependencies = [ [[package]] name = "penumbra-proto" -version = "0.80.2" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=87adc8d6b15f6081c1adf169daed4ca8873bd9f6#87adc8d6b15f6081c1adf169daed4ca8873bd9f6" +version = "0.80.6" +source = "git+https://github.com/noot/penumbra.git?rev=93fe7fd0771a958e3888c158d9d1fb94322724f1#93fe7fd0771a958e3888c158d9d1fb94322724f1" dependencies = [ "anyhow", "async-trait", @@ -3625,11 +3672,11 @@ dependencies = [ "hex", "ibc-proto", "ibc-types", - "ics23 0.11.3", + "ics23", "pbjson", "pbjson-types", "pin-project", - "prost 0.12.6", + "prost 0.13.3", "serde", "serde_json", "subtle-encoding", @@ -3639,8 +3686,8 @@ dependencies = [ [[package]] name = "penumbra-sct" -version = "0.80.2" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=87adc8d6b15f6081c1adf169daed4ca8873bd9f6#87adc8d6b15f6081c1adf169daed4ca8873bd9f6" +version = "0.80.6" +source = "git+https://github.com/noot/penumbra.git?rev=93fe7fd0771a958e3888c158d9d1fb94322724f1#93fe7fd0771a958e3888c158d9d1fb94322724f1" dependencies = [ "anyhow", "ark-ff", @@ -3672,8 +3719,8 @@ dependencies = [ [[package]] name = "penumbra-tct" -version = "0.80.2" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=87adc8d6b15f6081c1adf169daed4ca8873bd9f6#87adc8d6b15f6081c1adf169daed4ca8873bd9f6" +version = "0.80.6" +source = "git+https://github.com/noot/penumbra.git?rev=93fe7fd0771a958e3888c158d9d1fb94322724f1#93fe7fd0771a958e3888c158d9d1fb94322724f1" dependencies = [ "ark-ed-on-bls12-377", "ark-ff", @@ -3700,8 +3747,8 @@ dependencies = [ [[package]] name = "penumbra-txhash" -version = "0.80.2" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=87adc8d6b15f6081c1adf169daed4ca8873bd9f6#87adc8d6b15f6081c1adf169daed4ca8873bd9f6" +version = "0.80.6" +source = "git+https://github.com/noot/penumbra.git?rev=93fe7fd0771a958e3888c158d9d1fb94322724f1#93fe7fd0771a958e3888c158d9d1fb94322724f1" dependencies = [ "anyhow", "blake2b_simd 1.0.2", @@ -3725,27 +3772,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.5.0", + "indexmap 2.6.0", ] [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -3783,9 +3830,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.7.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" [[package]] name = "poseidon-parameters" @@ -3850,8 +3897,8 @@ version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" dependencies = [ - "proc-macro2 1.0.86", - "syn 2.0.77", + "proc-macro2 1.0.87", + "syn 2.0.79", ] [[package]] @@ -3866,15 +3913,6 @@ dependencies = [ "uint", ] -[[package]] -name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml 0.5.11", -] - [[package]] name = "proc-macro-crate" version = "3.2.0" @@ -3891,7 +3929,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", "syn 1.0.109", "version_check", @@ -3903,7 +3941,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", "version_check", ] @@ -3919,9 +3957,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" dependencies = [ "unicode-ident", ] @@ -3932,7 +3970,7 @@ version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "fnv", "lazy_static", "memchr", @@ -3943,69 +3981,69 @@ dependencies = [ [[package]] name = "prost" -version = "0.11.9" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", - "prost-derive 0.11.9", + "prost-derive 0.12.6", ] [[package]] name = "prost" -version = "0.12.6" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" +checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" dependencies = [ "bytes", - "prost-derive 0.12.6", + "prost-derive 0.13.3", ] [[package]] name = "prost-build" -version = "0.12.6" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" +checksum = "0c1318b19085f08681016926435853bbf7858f9c082d0999b80550ff5d9abe15" dependencies = [ "bytes", "heck 0.5.0", - "itertools 0.12.1", + "itertools 0.13.0", "log", "multimap", "once_cell", "petgraph", "prettyplease", - "prost 0.12.6", - "prost-types", + "prost 0.13.3", + "prost-types 0.13.3", "regex", - "syn 2.0.77", + "syn 2.0.79", "tempfile", ] [[package]] name = "prost-derive" -version = "0.11.9" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.10.5", - "proc-macro2 1.0.86", + "itertools 0.12.1", + "proc-macro2 1.0.87", "quote", - "syn 1.0.109", + "syn 2.0.79", ] [[package]] name = "prost-derive" -version = "0.12.6" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" dependencies = [ "anyhow", - "itertools 0.12.1", - "proc-macro2 1.0.86", + "itertools 0.13.0", + "proc-macro2 1.0.87", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -4017,6 +4055,15 @@ dependencies = [ "prost 0.12.6", ] +[[package]] +name = "prost-types" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670" +dependencies = [ + "prost 0.13.3", +] + [[package]] name = "protobuf" version = "2.28.0" @@ -4029,7 +4076,7 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5" dependencies = [ - "crossbeam-utils 0.8.20", + "crossbeam-utils", "libc", "once_cell", "raw-cpuid", @@ -4044,7 +4091,7 @@ version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", ] [[package]] @@ -4094,9 +4141,9 @@ dependencies = [ [[package]] name = "raw-cpuid" -version = "11.1.0" +version = "11.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb9ee317cfe3fbd54b36a511efc1edd42e216903c9cd575e686dd68a2ba90d8d" +checksum = "1ab240315c661615f2ee9f0f2cd32d5a7343a84d5ebcccb99d46e6637565e7b0" dependencies = [ "bitflags 2.6.0", ] @@ -4118,14 +4165,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", - "crossbeam-utils 0.8.20", + "crossbeam-utils", ] [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ "bitflags 2.6.0", ] @@ -4143,14 +4190,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -4164,13 +4211,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", ] [[package]] @@ -4181,9 +4228,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" @@ -4196,10 +4243,10 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2", - "http", - "http-body", - "hyper", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.30", "hyper-rustls", "ipnet", "js-sys", @@ -4208,22 +4255,21 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls", - "rustls-native-certs", - "rustls-pemfile", + "rustls 0.21.12", + "rustls-native-certs 0.6.3", + "rustls-pemfile 1.0.4", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 0.1.2", "system-configuration", "tokio", - "tokio-rustls", + "tokio-rustls 0.24.1", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots", "winreg", ] @@ -4250,7 +4296,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", - "cfg-if 1.0.0", + "cfg-if", "getrandom", "libc", "spin", @@ -4296,9 +4342,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.36" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f55e80d50763938498dd5ebb18647174e0c76dc38c5505294bb224624f30f36" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ "bitflags 2.6.0", "errno", @@ -4315,10 +4361,39 @@ checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring", - "rustls-webpki", + "rustls-webpki 0.101.7", "sct", ] +[[package]] +name = "rustls" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" +dependencies = [ + "log", + "ring", + "rustls-pki-types", + "rustls-webpki 0.102.8", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls" +version = "0.23.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki 0.102.8", + "subtle", + "zeroize", +] + [[package]] name = "rustls-native-certs" version = "0.6.3" @@ -4326,7 +4401,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ "openssl-probe", - "rustls-pemfile", + "rustls-pemfile 1.0.4", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-native-certs" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +dependencies = [ + "openssl-probe", + "rustls-pemfile 2.2.0", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcaf18a4f2be7326cd874a5fa579fae794320a0f388d365dca7e480e55f83f8a" +dependencies = [ + "openssl-probe", + "rustls-pemfile 2.2.0", + "rustls-pki-types", "schannel", "security-framework", ] @@ -4340,6 +4441,21 @@ dependencies = [ "base64 0.21.7", ] +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + [[package]] name = "rustls-webpki" version = "0.101.7" @@ -4350,6 +4466,17 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.17" @@ -4418,13 +4545,22 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scc" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836f1e0f4963ef5288b539b643b35e043e76a32d0f4e47e67febf69576527f50" +dependencies = [ + "sdd", +] + [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4443,6 +4579,12 @@ dependencies = [ "untrusted", ] +[[package]] +name = "sdd" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a7b59a5d9b0099720b417b6325d91a52cbf5b3dcb5041d864be53eefa58abc" + [[package]] name = "sec1" version = "0.7.3" @@ -4503,9 +4645,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", @@ -4522,9 +4664,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] @@ -4550,13 +4692,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -4587,16 +4729,16 @@ version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -4615,15 +4757,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.9.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" +checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.5.0", + "indexmap 2.6.0", "serde", "serde_derive", "serde_json", @@ -4633,14 +4775,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.9.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" +checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" dependencies = [ "darling", - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -4649,7 +4791,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.5.0", + "indexmap 2.6.0", "itoa", "ryu", "serde", @@ -4658,27 +4800,27 @@ dependencies = [ [[package]] name = "serial_test" -version = "2.0.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e56dd856803e253c8f298af3f4d7eb0ae5e23a737252cd90bb4f3b435033b2d" +checksum = "4b4b487fe2acf240a021cf57c6b2b4903b1e78ca0ecd862a71b71d2a51fed77d" dependencies = [ - "dashmap", "futures", - "lazy_static", "log", + "once_cell", "parking_lot", + "scc", "serial_test_derive", ] [[package]] name = "serial_test_derive" -version = "2.0.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" +checksum = "82fe9db325bcef1fbcde82e078a5cc4efdf787e96b3b9cf45b50b529f2083d67" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -4687,7 +4829,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.10.7", ] @@ -4699,7 +4841,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ "block-buffer 0.9.0", - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.9.0", "opaque-debug", @@ -4711,7 +4853,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.10.7", ] @@ -4867,10 +5009,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" dependencies = [ "heck 0.4.1", - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", "rustversion", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -4900,38 +5042,56 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.77" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", "unicode-ident", ] +[[package]] +name = "syn_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" +dependencies = [ + "proc-macro-error", + "proc-macro2 1.0.87", + "quote", + "syn 2.0.79", +] + [[package]] name = "sync_wrapper" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + [[package]] name = "synstructure" version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", "syn 1.0.109", - "unicode-xid 0.2.5", + "unicode-xid 0.2.6", ] [[package]] @@ -4969,11 +5129,11 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.12.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "fastrand", "once_cell", "rustix", @@ -4982,9 +5142,9 @@ dependencies = [ [[package]] name = "tendermint" -version = "0.34.1" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15ab8f0a25d0d2ad49ac615da054d6a76aa6603ff95f7d18bafdd34450a1a04b" +checksum = "505d9d6ffeb83b1de47c307c6e0d2dff56c6256989299010ad03cd80a8491e97" dependencies = [ "bytes", "digest 0.10.7", @@ -4995,8 +5155,8 @@ dependencies = [ "k256", "num-traits", "once_cell", - "prost 0.12.6", - "prost-types", + "prost 0.13.3", + "prost-types 0.13.3", "ripemd", "serde", "serde_bytes", @@ -5013,26 +5173,26 @@ dependencies = [ [[package]] name = "tendermint-config" -version = "0.34.1" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1a02da769166e2052cd537b1a97c78017632c2d9e19266367b27e73910434fc" +checksum = "9de111ea653b2adaef627ac2452b463c77aa615c256eaaddf279ec5a1cf9775f" dependencies = [ "flex-error", "serde", "serde_json", "tendermint", - "toml 0.5.11", + "toml 0.8.19", "url", ] [[package]] name = "tendermint-light-client" -version = "0.34.1" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc60a09541be13b8f8be305c260eb6144e48e01299302f71956c6e5284f2e4d6" +checksum = "d91e5abb448c65e8abdfe0e17a3a189e005a71b4169b89f36aaa2053ff239577" dependencies = [ "contracts", - "crossbeam-channel 0.4.4", + "crossbeam-channel", "derive_more", "flex-error", "futures", @@ -5052,11 +5212,11 @@ dependencies = [ [[package]] name = "tendermint-light-client-detector" -version = "0.34.1" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6af616fb578fec00cb6466d57718ad962de8482e77a7b647f4c8acf3538913e4" +checksum = "eb1ac1607eb7a3393313558b339c36eebeba15aa7f2d101d1d47299e65825152" dependencies = [ - "crossbeam-channel 0.4.4", + "crossbeam-channel", "derive_more", "flex-error", "futures", @@ -5075,9 +5235,9 @@ dependencies = [ [[package]] name = "tendermint-light-client-verifier" -version = "0.34.1" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b8090d0eef9ad57b1b913b5e358e26145c86017e87338136509b94383a4af25" +checksum = "7a2674adbf0dc51aa0c8eaf8462c7d6692ec79502713e50ed5432a442002be90" dependencies = [ "derive_more", "flex-error", @@ -5088,16 +5248,14 @@ dependencies = [ [[package]] name = "tendermint-proto" -version = "0.34.1" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b797dd3d2beaaee91d2f065e7bdf239dc8d80bba4a183a288bc1279dd5a69a1e" +checksum = "8ed14abe3b0502a3afe21ca74ca5cdd6c7e8d326d982c26f98a394445eb31d6e" dependencies = [ "bytes", "flex-error", - "num-derive", - "num-traits", - "prost 0.12.6", - "prost-types", + "prost 0.13.3", + "prost-types 0.13.3", "serde", "serde_bytes", "subtle-encoding", @@ -5106,9 +5264,9 @@ dependencies = [ [[package]] name = "tendermint-rpc" -version = "0.34.1" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71afae8bb5f6b14ed48d4e1316a643b6c2c3cbad114f510be77b4ed20b7b3e42" +checksum = "02f96a2b8a0d3d0b59e4024b1a6bdc1589efc6af4709d08a480a20cc4ba90f63" dependencies = [ "async-trait", "async-tungstenite", @@ -5140,9 +5298,9 @@ dependencies = [ [[package]] name = "tendermint-testgen" -version = "0.34.1" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae652e9e8b23f27f6a4fbeb29ead22ff4c2256b8d32df226b73258ba2a4ce11e" +checksum = "ae007e2918414ae96e4835426aace7538d23b8ddf96d71e23d241f58f386e877" dependencies = [ "ed25519-consensus", "gumdrop", @@ -5169,7 +5327,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dffced63c2b5c7be278154d76b479f9f9920ed34e7574201407f0b14e2bbb93" dependencies = [ - "env_logger 0.11.5", + "env_logger", "test-log-macros", "tracing-subscriber 0.3.18", ] @@ -5180,9 +5338,9 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5999e24eaa32083191ba4e425deb75cdf25efefabe5aaccb7446dd0d4122a3f5" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -5193,22 +5351,22 @@ checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -5217,7 +5375,7 @@ version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "once_cell", ] @@ -5313,25 +5471,15 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "tokio-io-timeout" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" -dependencies = [ - "pin-project-lite", - "tokio", -] - [[package]] name = "tokio-macros" version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -5340,7 +5488,29 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls", + "rustls 0.21.12", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +dependencies = [ + "rustls 0.22.4", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls 0.23.14", + "rustls-pki-types", "tokio", ] @@ -5400,11 +5570,11 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.20" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.5.0", + "indexmap 2.6.0", "serde", "serde_spanned", "toml_datetime", @@ -5413,30 +5583,32 @@ dependencies = [ [[package]] name = "tonic" -version = "0.10.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d560933a0de61cf715926b9cac824d4c883c2c43142f787595e48280c40a1d0e" +checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" dependencies = [ "async-stream", "async-trait", - "axum", - "base64 0.21.7", + "axum 0.7.7", + "base64 0.22.1", "bytes", - "h2", - "http", - "http-body", - "hyper", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.4.1", "hyper-timeout", + "hyper-util", "percent-encoding", "pin-project", - "prost 0.12.6", - "rustls", - "rustls-native-certs", - "rustls-pemfile", + "prost 0.13.3", + "rustls-native-certs 0.8.0", + "rustls-pemfile 2.2.0", + "socket2", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.0", "tokio-stream", - "tower", + "tower 0.4.13", "tower-layer", "tower-service", "tracing", @@ -5462,6 +5634,20 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 0.1.2", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" version = "0.3.3" @@ -5492,9 +5678,9 @@ version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -5591,20 +5777,32 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "tryhard" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9f0a709784e86923586cff0d872dba54cd2d2e116b3bc57587d15737cfce9d" +dependencies = [ + "futures", + "pin-project-lite", + "tokio", +] + [[package]] name = "tungstenite" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" dependencies = [ "byteorder", "bytes", "data-encoding", - "http", + "http 1.1.0", "httparse", "log", "rand", - "rustls", + "rustls 0.22.4", + "rustls-pki-types", "sha1", "thiserror", "url", @@ -5631,30 +5829,30 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-xid" @@ -5664,9 +5862,9 @@ checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] name = "unicode-xid" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "universal-hash" @@ -5786,7 +5984,7 @@ version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "once_cell", "wasm-bindgen-macro", ] @@ -5800,9 +5998,9 @@ dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", - "syn 2.0.77", + "syn 2.0.79", "wasm-bindgen-shared", ] @@ -5812,7 +6010,7 @@ version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "wasm-bindgen", "web-sys", @@ -5834,9 +6032,9 @@ version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", - "syn 2.0.77", + "syn 2.0.79", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5857,12 +6055,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki-roots" -version = "0.25.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" - [[package]] name = "winapi" version = "0.3.9" @@ -6053,9 +6245,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] @@ -6066,7 +6258,7 @@ version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "windows-sys 0.48.0", ] @@ -6095,9 +6287,9 @@ version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -6115,7 +6307,7 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2 1.0.87", "quote", - "syn 2.0.77", + "syn 2.0.79", ] diff --git a/Cargo.toml b/Cargo.toml index c651008bfc..16d9531df7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,104 @@ exclude = [ "tools/query-events", ] +[workspace.dependencies] +# Hermes dependencies +ibc-relayer-cli = { version = "1.10.3", path = "crates/relayer-cli" } +ibc-relayer = { version = "0.29.3", path = "crates/relayer" } +ibc-relayer-rest = { version = "0.29.3", path = "crates/relayer-rest" } +ibc-relayer-types = { version = "0.29.3", path = "crates/relayer-types" } +ibc-chain-registry = { version = "0.29.3", path = "crates/chain-registry" } +ibc-telemetry = { version = "0.29.3", path = "crates/telemetry" } +ibc-test-framework = { version = "0.29.3", path = "tools/test-framework" } +ibc-integration-test = { version = "0.29.3", path = "tools/integration-test" } + +# Tendermint dependencies +tendermint = { version = "0.38.1", default-features = false } +tendermint-light-client = { version = "0.38.1", default-features = false } +tendermint-light-client-detector = { version = "0.38.1", default-features = false } +tendermint-light-client-verifier = { version = "0.38.1", default-features = false } +tendermint-proto = { version = "0.38.1" } +tendermint-rpc = { version = "0.38.1" } +tendermint-testgen = { version = "0.38.1" } + +# Other dependencies +abscissa_core = "=0.6.0" +anyhow = "1.0" +async-stream = "0.3.5" +async-trait = "0.1.81" +axum = "0.6.18" +bech32 = "0.9.1" +bitcoin = "0.31.2" +bs58 = "0.5.1" +byte-unit = { version = "4.0.19", default-features = false } +bytes = "1.7.1" +clap = "3.2" +clap_complete = "3.2" +color-eyre = "0.6" +console = "0.15.5" +crossbeam-channel = "0.5.12" +dashmap = "5.4.0" +derive_more = { version = "0.99.18", default-features = false } +dialoguer = "0.11.0" +digest = "0.10.6" +dirs-next = "2.0.0" +ed25519 = "2.2.2" +ed25519-dalek = "2.0.0" +ed25519-dalek-bip32 = "0.3.0" +env_logger = "0.11.5" +eyre = "0.6.12" +flex-error = { version = "0.4.4", default-features = false } +futures = "0.3.27" +generic-array = "0.14.7" +hdpath = "0.6.3" +hex = "0.4.3" +http = "1.0.0" +humantime = "2.1.0" +humantime-serde = "1.1.1" +ibc-proto = "0.47.0" +ics23 = "0.12.0" +itertools = "0.13.0" +moka = "0.12.8" +num-bigint = "0.4" +num-rational = "0.4.1" +once_cell = "1.19.0" +oneline-eyre = "0.1" +opentelemetry = "0.19.0" +opentelemetry-prometheus = "0.12.0" +primitive-types = { version = "0.12.1", default-features = false } +prometheus = "0.13.4" +prost = "0.13" +rand = "0.8.5" +regex = "1.10.6" +reqwest = { version = "0.11.27", default-features = false } +retry = { version = "2.0.0", default-features = false } +ripemd = "0.1.3" +secp256k1 = "0.28.2" +semver = "1.0.21" +serde = "1.0.209" +serde_derive = "1.0.104" +serde_json = "1.0.127" +serde_yaml = "0.9.34" +serial_test = "3.1.1" +sha2 = "0.10.6" +signal-hook = "0.3.17" +signature = "2.1.0" +strum = "0.25" +subtle-encoding = "0.5.1" +test-log = "0.2.14" +thiserror = "1.0.63" +time = "0.3" +tiny-bip39 = "1.0.0" +tiny-keccak = { version = "2.0.2", default-features = false } +tokio = "1.39.2" +tokio-stream = "0.1.14" +toml = "0.8.19" +tonic = "0.12" +tracing = { version = "0.1.36", default-features = false } +tracing-subscriber = "0.3.14" +uint = "0.9" +uuid = "1.10.0" + [profile.release] overflow-checks = true @@ -29,3 +127,9 @@ overflow-checks = true # tendermint-light-client-verifier = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "main" } # tendermint-light-client-detector = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "main" } # tendermint-testgen = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "main" } +ibc-types = { git = "https://github.com/noot/ibc-types.git", rev = "b1c17a074980216a8f8d620937c77357b1797bac" } +jmt = { git = "https://github.com/noot/jmt.git", rev = "9a41b264c9db8afb07c337274691e3127411ac47" } + +[patch.'https://github.com/penumbra-zone/penumbra.git'] +penumbra-ibc = { git = "https://github.com/noot/penumbra.git", rev = "93fe7fd0771a958e3888c158d9d1fb94322724f1" } +penumbra-proto = { git = "https://github.com/noot/penumbra.git", rev = "93fe7fd0771a958e3888c158d9d1fb94322724f1" } diff --git a/README.md b/README.md index b816b659e0..7dccced969 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,14 @@ # Hermes IBC relayer +![hermes-banner](https://github.com/informalsystems/hermes/assets/1757002/0878ab2a-1c6f-4137-a089-66352f948407) + [![Cosmos ecosystem][cosmos-shield]][cosmos-link] [![Build Status][build-image]][build-link] [![Integration tests][test-image]][test-link] [![Apache 2.0 Licensed][license-image]][license-link] ![Rust Stable][rustc-image] -![Rust 1.71+][rustc-version] +![Rust 1.76+][rustc-version] Rust implementation of an Inter-Blockchain Communication (IBC) relayer. @@ -46,7 +48,7 @@ The repository also includes [TLA+ specifications](docs/spec). ## Requirements -The crates in this project require Rust `1.71.0`. +The crates in this project require Rust `1.76.0`. ## Hermes Guide @@ -116,12 +118,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 -[test-image]: https://github.com/informalsystems/hermes/workflows/Integration/badge.svg +[test-image]: https://github.com/informalsystems/hermes/actions/workflows/integration.yaml/badge.svg?branch=master [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.71+-blue.svg +[rustc-version]: https://img.shields.io/badge/rustc-1.76+-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/config.toml b/ci/misbehaviour/config.toml index 92845f89ed..41b18706fd 100644 --- a/ci/misbehaviour/config.toml +++ b/ci/misbehaviour/config.toml @@ -211,6 +211,19 @@ gas_price = { price = 0.001, denom = 'stake' } # Minimum value: 1.0 gas_multiplier = 1.3 +# Query the current gas price from the chain instead of using the static `gas_price` from the config. +# Useful for chains which have [EIP-1559][eip]-like dynamic gas price. +# +# At the moment, only chains which support the `osmosis.txfees.v1beta1.Query/GetEipBaseFee` +# query or have enabled Skip's `x/feemarket` module https://github.com/skip-mev/feemarket +# can be used with dynamic gas price enabled. +# +# See this page in the Hermes guide for more information: +# https://hermes.informal.systems/documentation/configuration/dynamic-gas-fees.html +# +# Default: { enabled = false, multiplier = 1.1, max = 0.6 } +dynamic_gas_price = { enabled = true, multiplier = 1.3, max = 5.0 } + # Specify how many IBC messages at most to include in a single transaction. # Default: 30 max_msg_num = 30 @@ -314,6 +327,7 @@ default_gas = 100000 max_gas = 400000 gas_price = { price = 0.001, denom = 'stake' } gas_multiplier = 1.3 +dynamic_gas_price = { enabled = true, multiplier = 1.3, max = 5.0 } max_msg_num = 30 max_tx_size = 2097152 clock_drift = '5s' diff --git a/ci/misbehaviour/config_fork.toml b/ci/misbehaviour/config_fork.toml index 060dda1566..d637f8db48 100644 --- a/ci/misbehaviour/config_fork.toml +++ b/ci/misbehaviour/config_fork.toml @@ -208,7 +208,20 @@ gas_price = { price = 0.001, denom = 'stake' } # # Default: 1.1, ie. the gas is increased by 10% # Minimum value: 1.0 -gas_multiplier = 1.1 +gas_multiplier = 1.3 + +# Query the current gas price from the chain instead of using the static `gas_price` from the config. +# Useful for chains which have [EIP-1559][eip]-like dynamic gas price. +# +# At the moment, only chains which support the `osmosis.txfees.v1beta1.Query/GetEipBaseFee` +# query or have enabled Skip's `x/feemarket` module https://github.com/skip-mev/feemarket +# can be used with dynamic gas price enabled. +# +# See this page in the Hermes guide for more information: +# https://hermes.informal.systems/documentation/configuration/dynamic-gas-fees.html +# +# Default: { enabled = false, multiplier = 1.1, max = 0.6 } +dynamic_gas_price = { enabled = true, multiplier = 1.3, max = 5.0 } # Specify how many IBC messages at most to include in a single transaction. # Default: 30 @@ -312,7 +325,8 @@ store_prefix = 'ibc' default_gas = 100000 max_gas = 400000 gas_price = { price = 0.001, denom = 'stake' } -gas_multiplier = 1.1 +gas_multiplier = 1.3 +dynamic_gas_price = { enabled = true, multiplier = 1.3, max = 5.0 } max_msg_num = 30 max_tx_size = 2097152 clock_drift = '5s' diff --git a/ci/misbehaviour/create_fork.sh b/ci/misbehaviour/create_fork.sh index 66092298d0..c21eefa7f0 100755 --- a/ci/misbehaviour/create_fork.sh +++ b/ci/misbehaviour/create_fork.sh @@ -50,7 +50,7 @@ sconfig data/ibc-1-f/config/config.toml "rpc.laddr=tcp://0.0.0.0:26457" sconfig data/ibc-1-f/config/config.toml "p2p.laddr=tcp://0.0.0.0:26456" info "Starting ibc-1..." -gaiad --home ./data/ibc-1 start --pruning=nothing --grpc.address=0.0.0.0:9091 --log_level error > data/ibc-1.log 2>&1 & +gaiad --home ./data/ibc-1 start --pruning=nothing --rpc.laddr="tcp://0.0.0.0:26557" --grpc.address=0.0.0.0:9091 --log_level error > data/ibc-1.log 2>&1 & info "Starting ibc-1 fork..." -gaiad --home ./data/ibc-1-f start --pruning=nothing --grpc.address=0.0.0.0:9092 --log_level error > data/ibc-1-f.log 2>&1 & +gaiad --home ./data/ibc-1-f start --pruning=nothing --rpc.laddr="tcp://0.0.0.0:26457" --grpc.address=0.0.0.0:9092 --log_level error > data/ibc-1-f.log 2>&1 & diff --git a/clippy.toml b/clippy.toml index 8f7dac5dc3..7372c60ff2 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1 +1 @@ -msrv = "1.71.0" +msrv = "1.76.0" diff --git a/config.toml b/config.toml index 9ff0aa5ed3..aeb2eff924 100644 --- a/config.toml +++ b/config.toml @@ -59,6 +59,10 @@ clear_interval = 100 # Whether or not to clear packets on start. [Default: true] clear_on_start = true +# Set the maximum number of packets to clear each time packet clearing is triggered. +# [Default: 50] +#clear_limit = 50 + # Toggle the transaction confirmation mechanism. # The tx confirmation mechanism periodically queries the `/tx_search` RPC # endpoint to check that previously-submitted transactions @@ -154,7 +158,8 @@ port = 5555 # Specify the chain ID. Required id = 'ibc-0' -# Specify the chain type, currently only `"CosmosSdk"` is supported. +# Specify the chain type, currently only `CosmosSdk` is supported. +# Default: CosmosSdk type = "CosmosSdk" # Whether or not this is a CCV consumer chain. Default: false @@ -188,11 +193,12 @@ grpc_addr = 'http://127.0.0.1:9090' # b) Pull: for polling for IBC events via the `/block_results` RPC endpoint. # -# `{ mode = 'pull', interval = '1s' }` +# `{ mode = 'pull', interval = '1s', max_retries = 4 }` # # where # # - `interval` is the interval at which to poll for blocks. Default: 1s +# - `max_retries` is the maximum number of retries to collect events for each block. Default: 4 # # 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 @@ -302,6 +308,19 @@ gas_price = { price = 0.025, denom = 'stake' } # Minimum value: 1.0 gas_multiplier = 1.1 +# Query the current gas price from the chain instead of using the static `gas_price` from the config. +# Useful for chains which have [EIP-1559][eip]-like dynamic gas price. +# +# At the moment, only chains which support the `osmosis.txfees.v1beta1.Query/GetEipBaseFee` +# query or have enabled Skip's `x/feemarket` module https://github.com/skip-mev/feemarket +# can be used with dynamic gas price enabled. +# +# See this page in the Hermes guide for more information: +# https://hermes.informal.systems/documentation/configuration/dynamic-gas-fees.html +# +# Default: { enabled = false, multiplier = 1.1, max = 0.6 } +dynamic_gas_price = { enabled = false, multiplier = 1.1, max = 0.6 } + # Specify how many IBC messages at most to include in a single transaction. # Default: 30 max_msg_num = 30 @@ -356,6 +375,13 @@ trust_threshold = '2/3' # operational debugging information, e.g., relayer build version. memo_prefix = '' +# If this is set to a string, it will overwrite the memo used by Hermes for each transaction +# it submits to this chain. +# Default: not set. +# This is used for chains which have a very small character limit for the memo, +# and the additional information appended by Hermes would overflow that limit. +# memo_overwrite = '' + # This section specifies the filters for policy based relaying. # # Default: no policy / filters, allow all packets on all channels. @@ -420,9 +446,27 @@ memo_prefix = '' # This will override the global clear interval for this chain only, allowing different intervals for each chain. # clear_interval = 50 +# Specify packet sequences which should not be cleared, per channel. +# +# For each channel, specify a list of sequences which should not be cleared. Acceptable value +# include range of sequences with separator "-", eg. +# +# [chains.excluded_sequences] +# channel-0 = [1, 2, "3-7", 9, 11], +# channel-1 = [4, 5, 6], +# +# Default: No filter +# excluded_sequences = {} + +# Enable or disable relaying of ICS31 Cross Chain Query packets. +# If this configuration is set to false, Hermes will skip ICS31 +# Cross Chain Query packets. +# +# Default: true +# allow_ccq = true + [[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/crates/chain-registry/Cargo.toml b/crates/chain-registry/Cargo.toml index e42ff30d54..967fbdc54e 100644 --- a/crates/chain-registry/Cargo.toml +++ b/crates/chain-registry/Cargo.toml @@ -1,28 +1,29 @@ [package] name = "ibc-chain-registry" -version = "0.26.4" +version = "0.29.3" edition = "2021" license = "Apache-2.0" keywords = ["cosmos", "ibc", "relayer", "chain", "registry"] repository = "https://github.com/informalsystems/hermes" authors = ["Informal Systems "] -rust-version = "1.71" +rust-version = "1.76.0" description = """ Service to fetch data from the chain-registry """ [dependencies] -ibc-relayer-types = { version = "0.26.4", path = "../relayer-types" } -ibc-proto = { version = "0.41.0", features = ["serde"] } -tendermint-rpc = { version = "0.34.0", features = ["http-client", "websocket-client"] } +ibc-relayer = { workspace = true } +ibc-relayer-types = { workspace = true } +ibc-proto = { workspace = true, features = ["serde"] } +tendermint-rpc = { workspace = true, features = ["http-client", "websocket-client"] } -async-trait = "0.1.72" -flex-error = { version = "0.4.4", default-features = false } -futures = { version = "0.3", features = ["executor"] } -http = "0.2" -itertools = "0.10.5" -reqwest = { version = "0.11.13", features = ["rustls-tls", "json"], default-features = false } -serde = "1.0.195" -serde_json = "1" -tokio = "1.17.0" -tracing = "0.1.36" +async-trait = { workspace = true } +flex-error = { workspace = true } +futures = { workspace = true, features = ["executor"] } +http = { workspace = true } +itertools = { workspace = true } +reqwest = { workspace = true, features = ["rustls-tls-native-roots", "json"] } +serde = { workspace = true } +serde_json = { workspace = true } +tokio = { workspace = true } +tracing = { workspace = true } diff --git a/crates/chain-registry/src/asset_list.rs b/crates/chain-registry/src/asset_list.rs index da8df1fcbe..fc7b3115da 100644 --- a/crates/chain-registry/src/asset_list.rs +++ b/crates/chain-registry/src/asset_list.rs @@ -3,10 +3,7 @@ use std::path::PathBuf; -use serde::{ - Deserialize, - Serialize, -}; +use serde::{Deserialize, Serialize}; use crate::fetchable::Fetchable; @@ -48,6 +45,8 @@ pub struct LogoURIs { } impl Fetchable for AssetList { + const DESC: &'static str = "asset list"; + fn path(resource: &str) -> PathBuf { [resource, "assetlist.json"].iter().collect() } @@ -56,10 +55,7 @@ impl Fetchable for AssetList { #[cfg(test)] mod tests { use super::*; - use crate::{ - constants::ALL_CHAINS, - error::RegistryError, - }; + use crate::{constants::ALL_CHAINS, error::RegistryError}; #[tokio::test] #[ignore] diff --git a/crates/chain-registry/src/chain.rs b/crates/chain-registry/src/chain.rs index 5649d597a5..c806461b64 100644 --- a/crates/chain-registry/src/chain.rs +++ b/crates/chain-registry/src/chain.rs @@ -3,10 +3,7 @@ use std::path::PathBuf; use ibc_relayer_types::core::ics24_host::identifier::ChainId; -use serde::{ - Deserialize, - Serialize, -}; +use serde::{Deserialize, Serialize}; use crate::fetchable::Fetchable; @@ -157,6 +154,8 @@ pub struct Grpc { } impl Fetchable for ChainData { + const DESC: &'static str = "chain data"; + fn path(resource: &str) -> PathBuf { [resource, "chain.json"].iter().collect() } @@ -166,10 +165,7 @@ impl Fetchable for ChainData { #[cfg(test)] mod tests { use super::*; - use crate::{ - constants::ALL_CHAINS, - error::RegistryError, - }; + use crate::{constants::ALL_CHAINS, error::RegistryError}; #[tokio::test] #[ignore] diff --git a/crates/chain-registry/src/error.rs b/crates/chain-registry/src/error.rs index 13e7fdf1f2..01ccf6af39 100644 --- a/crates/chain-registry/src/error.rs +++ b/crates/chain-registry/src/error.rs @@ -1,18 +1,9 @@ use std::path::PathBuf; -use flex_error::{ - define_error, - TraceError, -}; -use http; +use flex_error::{define_error, TraceError}; use itertools::Itertools; -use reqwest; -use serde_json; -use tendermint_rpc; -use tokio::{ - task::JoinError, - time::error::Elapsed, -}; +use tokio::task::JoinError; +use tokio::time::error::Elapsed; define_error! { RegistryError { @@ -83,7 +74,7 @@ define_error! { .iter() .join(", "); - format!("Error finding a healthy endpoint after {} retries. Endpoints: {endpoints}", e.retries) + format!("Did not find a healthy endpoint after {} retries. Endpoints: {endpoints}", e.retries) }, UriParseError diff --git a/crates/chain-registry/src/fetchable.rs b/crates/chain-registry/src/fetchable.rs index e97098c07b..8310a550d0 100644 --- a/crates/chain-registry/src/fetchable.rs +++ b/crates/chain-registry/src/fetchable.rs @@ -6,12 +6,7 @@ use http::uri::Builder; use serde::de::DeserializeOwned; use crate::{ - constants::{ - DEFAULT_REF, - HOST, - PROTOCOL, - REGISTRY_PATH, - }, + constants::{DEFAULT_REF, HOST, PROTOCOL, REGISTRY_PATH}, error::RegistryError, }; @@ -22,6 +17,8 @@ pub trait Fetchable where Self: DeserializeOwned, { + const DESC: &'static str; + /// The path of the fetchable resource. fn path(resource: &str) -> PathBuf; diff --git a/crates/chain-registry/src/formatter.rs b/crates/chain-registry/src/formatter.rs index 90e0a8212c..fe520fac0e 100644 --- a/crates/chain-registry/src/formatter.rs +++ b/crates/chain-registry/src/formatter.rs @@ -2,12 +2,12 @@ //! Contains struct to build a `tendermint_rpc::Url` representing a //! WebSocket URL from a RPC URL and to parse or build a valid `http::Uri` //! from an (in)complete GRPC URL. + use std::str::FromStr; -use http::{ - uri::Scheme, - Uri, -}; +use http::uri::Scheme; +use http::Uri; + use tendermint_rpc::Url; use crate::error::RegistryError; @@ -99,13 +99,10 @@ impl UriFormatter for SimpleGrpcFormatter { #[cfg(test)] mod tests { - use std::{ - cmp::PartialEq, - fmt::Debug, - }; - use super::*; + use std::fmt::Debug; + struct FormatterTest { input: &'static str, // expected is None if the formatter should return an error @@ -186,11 +183,7 @@ mod tests { #[tokio::test] #[ignore] async fn all_chain_registry_grpc_address() -> Result<(), RegistryError> { - use crate::{ - chain::ChainData, - constants::ALL_CHAINS, - fetchable::Fetchable, - }; + use crate::{chain::ChainData, constants::ALL_CHAINS, fetchable::Fetchable}; let mut handles = Vec::with_capacity(ALL_CHAINS.len()); @@ -211,11 +204,7 @@ mod tests { #[tokio::test] #[ignore] async fn all_chain_registry_rpc_address() -> Result<(), RegistryError> { - use crate::{ - chain::ChainData, - constants::ALL_CHAINS, - fetchable::Fetchable, - }; + use crate::{chain::ChainData, constants::ALL_CHAINS, fetchable::Fetchable}; let mut handles = Vec::with_capacity(ALL_CHAINS.len()); diff --git a/crates/chain-registry/src/paths.rs b/crates/chain-registry/src/paths.rs index 5cbff7b73e..b41b9e1d43 100644 --- a/crates/chain-registry/src/paths.rs +++ b/crates/chain-registry/src/paths.rs @@ -1,15 +1,7 @@ use std::path::PathBuf; -use ibc_relayer_types::core::ics24_host::identifier::{ - ChannelId, - ClientId, - ConnectionId, - PortId, -}; -use serde::{ - Deserialize, - Serialize, -}; +use ibc_relayer_types::core::ics24_host::identifier::{ChannelId, ClientId, ConnectionId, PortId}; +use serde::{Deserialize, Serialize}; /// Models for serializing and deserializing IBC path JSON data found in the `_IBC/` directory of the registry repository use crate::fetchable::Fetchable; @@ -67,6 +59,8 @@ pub enum Tag { } impl Fetchable for IBCPath { + const DESC: &'static str = "IBC path"; + fn path(resource: &str) -> PathBuf { ["_IBC", resource].iter().collect() } @@ -76,10 +70,7 @@ impl Fetchable for IBCPath { #[cfg(test)] mod tests { use super::*; - use crate::{ - constants::ALL_PATHS, - error::RegistryError, - }; + use crate::{constants::ALL_PATHS, error::RegistryError}; #[tokio::test] #[ignore] @@ -109,10 +100,7 @@ mod tests { use std::str::FromStr; use ibc_relayer_types::core::ics24_host::identifier::{ - ChannelId, - ClientId, - ConnectionId, - PortId, + ChannelId, ClientId, ConnectionId, PortId, }; let path = r#"{ diff --git a/crates/chain-registry/src/querier.rs b/crates/chain-registry/src/querier.rs index 4864fac5ac..9129392fbe 100644 --- a/crates/chain-registry/src/querier.rs +++ b/crates/chain-registry/src/querier.rs @@ -2,40 +2,21 @@ //! Contains struct to perform a health check on a gRPC/WebSocket endpoint and //! to retrieve the `max_block_size` from a RPC endpoint. -use std::{ - fmt::Debug, - str::FromStr, -}; +use std::{fmt::Debug, str::FromStr}; use async_trait::async_trait; -use futures::{ - stream::FuturesUnordered, - StreamExt, -}; +use futures::{stream::FuturesUnordered, StreamExt}; use http::Uri; +use tendermint_rpc::HttpClient; +use tendermint_rpc::HttpClientUrl; +use tracing::{debug, info}; + use ibc_proto::cosmos::bank::v1beta1::query_client::QueryClient; -use tendermint_rpc::{ - Client, - SubscriptionClient, - Url, - WebSocketClient, -}; -use tokio::time::{ - timeout, - Duration, -}; -use tracing::{ - debug, - info, -}; - -use crate::{ - error::RegistryError, - formatter::{ - SimpleWebSocketFormatter, - UriFormatter, - }, -}; +use ibc_relayer::util::create_grpc_client; +use ibc_relayer::HERMES_VERSION; +use tendermint_rpc::{Client, Url}; + +use crate::error::RegistryError; /// `QueryTypes` represents the basic types required to query a node pub trait QueryTypes { @@ -92,8 +73,8 @@ pub trait QueryContext: QueryTypes { // ----------------- RPC ------------------ -/// `SimpleHermesRpcQuerier` retrieves `HermesConfigData` by querying a list of RPC endpoints through their WebSocket API -/// and returns the result of the first endpoint to answer. +/// `SimpleHermesRpcQuerier` retrieves `HermesConfigData` by querying a list of RPC endpoints +/// through their RPC API and returns the result of the first endpoint to answer. pub struct SimpleHermesRpcQuerier; /// Data which must be retrieved from RPC endpoints for Hermes @@ -101,7 +82,6 @@ pub struct SimpleHermesRpcQuerier; pub struct HermesConfigData { pub rpc_address: Url, pub max_block_size: u64, - pub websocket: Url, // max_block_time should also be retrieved from the RPC // however it looks like it is not in the genesis file anymore } @@ -120,46 +100,32 @@ impl QueryContext for SimpleHermesRpcQuerier { RegistryError::no_healthy_rpc(chain_name) } - /// Convert the RPC url to a WebSocket url, query the endpoint, return the data from the RPC. - async fn query(rpc: Self::QueryInput) -> Result { - let websocket_addr = SimpleWebSocketFormatter::parse_or_build_address(rpc.as_str())?; - - info!("Querying WebSocket server at {websocket_addr}"); + /// Query the endpoint, return the data from the RPC. + async fn query(rpc_url: Self::QueryInput) -> Result { + info!("Querying RPC server at {rpc_url}"); - let (client, driver) = timeout( - Duration::from_secs(5), - WebSocketClient::new(websocket_addr.clone()), - ) - .await - .map_err(|e| RegistryError::websocket_time_out_error(websocket_addr.to_string(), e))? - .map_err(|e| RegistryError::websocket_connect_error(websocket_addr.to_string(), e))?; + let url = HttpClientUrl::from_str(&rpc_url) + .map_err(|e| RegistryError::tendermint_url_parse_error(rpc_url.clone(), e))?; - let driver_handle = tokio::spawn(driver.run()); + let client = HttpClient::builder(url) + .user_agent(format!("hermes/{}", HERMES_VERSION)) + .build() + .map_err(|e| RegistryError::rpc_connect_error(rpc_url.clone(), e))?; let latest_consensus_params = match client.latest_consensus_params().await { Ok(response) => response.consensus_params.block.max_bytes, Err(e) => { return Err(RegistryError::rpc_consensus_params_error( - websocket_addr.to_string(), + rpc_url.to_string(), e, )) } }; - client.close().map_err(|e| { - RegistryError::websocket_conn_close_error(websocket_addr.to_string(), e) - })?; - - driver_handle - .await - .map_err(|e| RegistryError::join_error("chain_data_join".to_string(), e))? - .map_err(|e| RegistryError::websocket_driver_error(websocket_addr.to_string(), e))?; - Ok(HermesConfigData { - rpc_address: Url::from_str(&rpc) - .map_err(|e| RegistryError::tendermint_url_parse_error(rpc, e))?, + rpc_address: Url::from_str(&rpc_url) + .map_err(|e| RegistryError::tendermint_url_parse_error(rpc_url, e))?, max_block_size: latest_consensus_params, - websocket: websocket_addr, }) } } @@ -193,7 +159,7 @@ impl QueryContext for GrpcHealthCheckQuerier { info!("Querying gRPC server at {tendermint_url}"); - QueryClient::connect(uri) + create_grpc_client(uri, QueryClient::new) .await .map_err(|_| RegistryError::unable_to_connect_with_grpc())?; diff --git a/crates/relayer-cli/Cargo.toml b/crates/relayer-cli/Cargo.toml index 87e8aaeba7..c2f947ad0b 100644 --- a/crates/relayer-cli/Cargo.toml +++ b/crates/relayer-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ibc-relayer-cli" -version = "1.7.4" +version = "1.10.3" 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.71" +rust-version = "1.76.0" description = """ Hermes is an IBC Relayer written in Rust """ @@ -17,61 +17,44 @@ default-run = "hermes" [[bin]] name = "hermes" -[features] -default = ["telemetry", "rest-server", "std", "eyre_tracer"] -std = ["flex-error/std"] -eyre_tracer = ["flex-error/eyre_tracer"] -telemetry = ["ibc-relayer/telemetry", "ibc-telemetry"] -rest-server = ["ibc-relayer-rest"] - [dependencies] -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" -color-eyre = "0.6" -console = "0.15.5" -crossbeam-channel = "0.5.11" -dialoguer = "0.10.3" -dirs-next = "2.0.0" -eyre = "0.6.8" -flex-error = { version = "0.4.4", default-features = false, features = ["std", "eyre_tracer"] } -futures = "0.3" -hdpath = "0.6.3" -http = "0.2" -humantime = "2.1" -itertools = "0.10.5" -oneline-eyre = "0.1" -regex = "1.9.5" -serde = { version = "1.0", features = ["serde_derive"] } -serde_json = "1" -signal-hook = "0.3.17" -subtle-encoding = "0.5" -tokio = { version = "1.0", features = ["full"] } -tracing = "0.1.36" -tracing-subscriber = { version = "0.3.14", features = ["fmt", "env-filter", "json"]} -time = "0.3" -[dependencies.tendermint] -version = "0.34.0" -features = ["secp256k1"] - -[dependencies.tendermint-rpc] -version = "0.34.0" -features = ["http-client", "websocket-client"] - -[dependencies.tendermint-light-client-verifier] -version = "0.34.0" - -[dependencies.abscissa_core] -version = "=0.6.0" -features = ["options"] +ibc-relayer-types = { workspace = true } +ibc-relayer = { workspace = true } +ibc-telemetry = { workspace = true } +ibc-relayer-rest = { workspace = true } +ibc-chain-registry = { workspace = true } + +abscissa_core = { workspace = true, features = ["options"] } +clap = { workspace = true, features = ["cargo"] } +clap_complete = { workspace = true } +color-eyre = { workspace = true } +console = { workspace = true } +crossbeam-channel = { workspace = true } +dialoguer = { workspace = true } +dirs-next = { workspace = true } +eyre = { workspace = true } +flex-error = { workspace = true, features = ["std", "eyre_tracer"] } +futures = { workspace = true } +hdpath = { workspace = true } +http = { workspace = true } +humantime = { workspace = true } +itertools = { workspace = true } +oneline-eyre = { workspace = true } +regex = { workspace = true } +serde = { workspace = true, features = ["serde_derive"] } +serde_json = { workspace = true } +signal-hook = { workspace = true } +subtle-encoding = { workspace = true } +tendermint-light-client-verifier = { workspace = true } +tendermint-rpc = { workspace = true, features = ["http-client", "websocket-client"] } +tendermint = { workspace = true, features = ["secp256k1"] } +time = { workspace = true } +tokio = { workspace = true, features = ["full"] } +tracing = { workspace = true } +tracing-subscriber = { workspace = true, features = ["fmt", "env-filter", "json"] } [dev-dependencies] -abscissa_core = { version = "=0.6.0", features = ["testing"] } -once_cell = "1.19" -regex = "1.9" -serial_test = "2.0.0" +abscissa_core = { workspace = true, features = ["testing"] } +once_cell = { workspace = true } +regex = { workspace = true } +serial_test = { workspace = true } diff --git a/crates/relayer-cli/build.rs b/crates/relayer-cli/build.rs index 8f94e3f597..5983d57a8e 100644 --- a/crates/relayer-cli/build.rs +++ b/crates/relayer-cli/build.rs @@ -38,10 +38,7 @@ mod git { use core::marker::PhantomData; use std::{ ffi::OsStr, - process::{ - Command, - Output, - }, + process::{Command, Output}, }; // A wrapper over a git shell command that is only constructable if git is available & the diff --git a/crates/relayer-cli/src/application.rs b/crates/relayer-cli/src/application.rs index ddbe9466b4..48bfcc3a81 100644 --- a/crates/relayer-cli/src/application.rs +++ b/crates/relayer-cli/src/application.rs @@ -1,49 +1,24 @@ //! Definition of the application, based on the Abscissa framework -use std::{ - path::PathBuf, - thread, -}; +use std::{path::PathBuf, thread}; use abscissa_core::{ - application::{ - self, - AppCell, - }, + application::{self, AppCell}, component::Component, - config::{ - self, - CfgCell, - }, - terminal::{ - component::Terminal, - ColorChoice, - }, - Application, - Configurable, - FrameworkError, - FrameworkErrorKind, - StandardPaths, + config::{self, CfgCell}, + terminal::{component::Terminal, ColorChoice}, + Application, Configurable, FrameworkError, FrameworkErrorKind, StandardPaths, }; use ibc_relayer::{ - config::{ - Config, - TracingServerConfig, - }, + config::{Config, TracingServerConfig}, util::debug_section::DebugSection, }; use crate::{ commands::CliCmd, - components::{ - JsonTracing, - PrettyTracing, - }, + components::{JsonTracing, PrettyTracing}, entry::EntryPoint, - tracing_handle::{ - spawn_reload_handler, - ReloadHandle, - }, + tracing_handle::{spawn_reload_handler, ReloadHandle}, }; /// Application state @@ -190,7 +165,7 @@ impl Application for CliApp { let terminal = Terminal::new(self.term_colors(command)); let config_path = command.config_path(); - self.config_path = config_path.clone(); + self.config_path.clone_from(&config_path); let config = config_path .map(|path| self.load_config(&path)) diff --git a/crates/relayer-cli/src/bin/hermes/main.rs b/crates/relayer-cli/src/bin/hermes/main.rs index 45860088f5..567bd4dd09 100644 --- a/crates/relayer-cli/src/bin/hermes/main.rs +++ b/crates/relayer-cli/src/bin/hermes/main.rs @@ -1,12 +1,9 @@ //! Main entry point for Cli -#![deny(warnings, missing_docs, trivial_casts, unused_qualifications)] +#![deny(warnings, missing_docs, trivial_casts)] #![forbid(unsafe_code)] -use ibc_relayer_cli::{ - application::APPLICATION, - components::enable_ansi, -}; +use ibc_relayer_cli::{application::APPLICATION, components::enable_ansi}; fn main() -> eyre::Result<()> { install_error_reporter()?; diff --git a/crates/relayer-cli/src/chain_registry.rs b/crates/relayer-cli/src/chain_registry.rs index 94e09d8d8a..c43f0fc1c1 100644 --- a/crates/relayer-cli/src/chain_registry.rs +++ b/crates/relayer-cli/src/chain_registry.rs @@ -1,53 +1,30 @@ //! Contains functions to generate a relayer config for a given chain -use std::{ - collections::HashMap, - fmt::Display, - marker::Send, -}; +use std::collections::BTreeMap; +use std::collections::HashMap; +use std::fmt::Display; use futures::future::join_all; use http::Uri; -use ibc_chain_registry::{ - asset_list::AssetList, - chain::ChainData, - error::RegistryError, - fetchable::Fetchable, - formatter::{ - SimpleGrpcFormatter, - UriFormatter, - }, - paths::IBCPath, - querier::*, -}; -use ibc_relayer::{ - chain::cosmos::config::CosmosSdkConfig, - config::{ - default, - filter::{ - FilterPattern, - PacketFilter, - }, - gas_multiplier::GasMultiplier, - types::{ - MaxMsgNum, - MaxTxSize, - Memo, - TrustThreshold, - }, - AddressType, - ChainConfig, - EventSourceMode, - GasPrice, - }, - keyring::Store, -}; use tendermint_rpc::Url; -use tokio::task::{ - JoinError, - JoinHandle, -}; -use tracing::trace; +use tokio::task::{JoinError, JoinHandle}; +use tracing::{error, trace}; + +use ibc_chain_registry::asset_list::AssetList; +use ibc_chain_registry::chain::ChainData; +use ibc_chain_registry::error::RegistryError; +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::dynamic_gas::DynamicGasPrice; +use ibc_relayer::config::filter::{FilterPattern, PacketFilter}; +use ibc_relayer::config::gas_multiplier::GasMultiplier; +use ibc_relayer::config::types::{MaxMsgNum, MaxTxSize, Memo, TrustThreshold}; +use ibc_relayer::config::{default, AddressType, ChainConfig, EventSourceMode, GasPrice}; +use ibc_relayer::keyring::Store; +use ibc_relayer::util::excluded_sequences::ExcludedSequences; const MAX_HEALTHY_QUERY_RETRIES: u8 = 5; @@ -133,24 +110,26 @@ where ) .await?; - let websocket_address = - rpc_data.websocket.clone().try_into().map_err(|e| { - RegistryError::websocket_url_parse_error(rpc_data.websocket.to_string(), e) - })?; - let avg_gas_price = if let Some(fee_token) = chain_data.fees.fee_tokens.first() { fee_token.average_gas_price } else { 0.1 }; + // Use EIP-1559 dynamic gas price for Osmosis + let dynamic_gas_price = if chain_data.chain_id.as_str() == "osmosis-1" { + DynamicGasPrice::unsafe_new(true, 1.1, 0.6) + } else { + DynamicGasPrice::disabled() + }; + Ok(ChainConfig::CosmosSdk(CosmosSdkConfig { id: chain_data.chain_id, rpc_addr: rpc_data.rpc_address, grpc_addr: grpc_address, - event_source: EventSourceMode::Push { - url: websocket_address, - batch_delay: default::batch_delay(), + event_source: EventSourceMode::Pull { + interval: default::poll_interval(), + max_retries: default::max_retries(), }, rpc_timeout: default::rpc_timeout(), trusted_node: default::trusted_node(), @@ -164,6 +143,7 @@ where max_gas: Some(400000), gas_adjustment: None, gas_multiplier: Some(GasMultiplier::new(1.1).unwrap()), + dynamic_gas_price, fee_granter: None, max_msg_num: MaxMsgNum::default(), max_tx_size: MaxTxSize::default(), @@ -175,6 +155,7 @@ where client_refresh_rate: default::client_refresh_rate(), ccv_consumer_chain: false, memo_prefix: Memo::default(), + memo_overwrite: None, proof_specs: Default::default(), trust_threshold: TrustThreshold::default(), gas_price: GasPrice { @@ -187,6 +168,8 @@ where extension_options: Vec::new(), compat_mode: None, clear_interval: None, + excluded_sequences: ExcludedSequences::new(BTreeMap::new()), + allow_ccq: true, })) } @@ -205,6 +188,7 @@ where for i in 0..retries { let query_response = QuerierType::query_healthy(chain_name.to_string(), endpoints.clone()).await; + match query_response { Ok(r) => { return Ok(r); @@ -214,13 +198,13 @@ where } } } - Err(RegistryError::unhealthy_endpoints( - endpoints - .iter() - .map(|endpoint| endpoint.to_string()) - .collect(), - retries, - )) + + let endpoints = endpoints + .iter() + .map(|endpoint| endpoint.to_string()) + .collect(); + + Err(RegistryError::unhealthy_endpoints(endpoints, retries)) } /// Fetches the specified resources from the Cosmos chain registry, using the specified commit hash @@ -228,15 +212,21 @@ where /// Returns a vector of handles that need to be awaited in order to access the fetched data, or the /// error that occurred while fetching. async fn get_handles( - resources: &[String], + chain_ids: &[String], commit: &Option, -) -> Vec>> { - let handles = resources +) -> Vec<(String, JoinHandle>)> { + let handles = chain_ids .iter() - .map(|resource| { - let resource = resource.to_string(); + .map(|chain_id| { let commit = commit.clone(); - tokio::spawn(async move { T::fetch(resource, commit).await }) + let handle = { + let chain_id = chain_id.to_string(); + tokio::spawn(async move { + tracing::info!("{chain_id}: Fetching {}...", T::DESC); + T::fetch(chain_id, commit).await + }) + }; + (chain_id.to_string(), handle) }) .collect(); handles @@ -245,14 +235,18 @@ async fn get_handles( /// Given a vector of handles, awaits them and returns a vector of results. Any errors /// that occurred are mapped to a `RegistryError`. async fn get_data_from_handles( - handles: Vec>>, + handles: Vec<(String, JoinHandle>)>, error_task: &str, -) -> Result>, RegistryError> { - join_all(handles) +) -> Result)>, RegistryError> { + let (names, tasks): (Vec<_>, Vec<_>) = handles.into_iter().unzip(); + + let results = join_all(tasks) .await .into_iter() .collect::, JoinError>>() - .map_err(|e| RegistryError::join_error(error_task.to_string(), e)) + .map_err(|e| RegistryError::join_error(error_task.to_string(), e))?; + + Ok(names.into_iter().zip(results).collect()) } /// Fetches a list of ChainConfigs specified by the given slice of chain names. These @@ -275,17 +269,17 @@ async fn get_data_from_handles( pub async fn get_configs( chains: &[String], commit: Option, -) -> Result>, RegistryError> { - let n = chains.len(); - - if n == 0 { - return Ok(Vec::new()); +) -> Result>, RegistryError> { + if chains.is_empty() { + return Ok(HashMap::new()); } // Spawn tasks to fetch data from the chain-registry let chain_data_handle = get_handles::(chains, &commit).await; let asset_lists_handle = get_handles::(chains, &commit).await; + let n = chains.len(); + let mut path_handles = Vec::with_capacity(n * (n - 1) / 2); for i in 0..n { @@ -305,43 +299,65 @@ pub async fn get_configs( let asset_list_results = get_data_from_handles::(asset_lists_handle, "asset_handle_join").await?; - let chain_data_array: Vec = chain_data_results + let chain_data_array: Vec<(String, ChainData)> = chain_data_results .into_iter() - .filter_map(|chain_data| chain_data.ok()) + .filter_map(|(name, data)| match data { + Ok(data) => Some((name, data)), + Err(e) => { + error!("Error while fetching chain data for chain {name}: {e}"); + None + } + }) .collect(); - let asset_lists: Vec = asset_list_results + + let asset_lists: Vec<(String, AssetList)> = asset_list_results .into_iter() - .filter_map(|asset_list| asset_list.ok()) + .filter_map(|(name, assets)| match assets { + Ok(assets) => Some((name, assets)), + Err(e) => { + error!("Error while fetching asset list for chain {name}: {e}"); + None + } + }) .collect(); let path_data: Result, JoinError> = join_all(path_handles).await.into_iter().collect(); - let path_data: Vec = path_data + let path_data: Vec<_> = path_data .map_err(|e| RegistryError::join_error("path_handle_join".to_string(), e))? .into_iter() - .filter_map(|path| path.ok()) + .filter_map(|path| match path { + Ok(path) => Some(path), + Err(e) => { + error!("Error while fetching path data: {e}"); + None + } + }) .collect(); let mut packet_filters = construct_packet_filters(path_data); // Construct ChainConfig - let config_handles: Vec>> = chain_data_array + let config_handles: Vec<_> = chain_data_array .into_iter() .zip(asset_lists.into_iter()) - .zip(chains.iter()) - .map(|((chain_data, assets), chain_name)| { - let packet_filter = packet_filters.remove(chain_name); - tokio::spawn(async move { - hermes_config::< - GrpcHealthCheckQuerier, - SimpleHermesRpcQuerier, - SimpleGrpcFormatter, - >(chain_data, assets, packet_filter) - .await - }) + .map(|((chain_name, chain_data), (_, assets))| { + let packet_filter = packet_filters.remove(&chain_name); + let handle = tokio::spawn(hermes_config::< + GrpcHealthCheckQuerier, + SimpleHermesRpcQuerier, + SimpleGrpcFormatter, + >(chain_data, assets, packet_filter)); + + (chain_name, handle) }) .collect(); - get_data_from_handles::(config_handles, "config_handle_join").await + let result = get_data_from_handles::(config_handles, "config_handle_join") + .await? + .into_iter() + .collect(); + + Ok(result) } /// Concurrent RPC and GRPC queries are likely to fail. @@ -353,10 +369,7 @@ mod tests { use std::str::FromStr; use ibc_relayer::config::filter::ChannelPolicy; - use ibc_relayer_types::core::ics24_host::identifier::{ - ChannelId, - PortId, - }; + use ibc_relayer_types::core::ics24_host::identifier::{ChannelId, PortId}; use serial_test::serial; use super::*; @@ -370,7 +383,7 @@ mod tests { async fn should_have_no_filter(test_chains: &[String]) -> Result<(), RegistryError> { let configs = get_configs(test_chains, Some(TEST_COMMIT.to_owned())).await?; - for config in configs { + for (_name, config) in configs { match config { Ok(config) => { assert_eq!( @@ -378,10 +391,7 @@ mod tests { ChannelPolicy::AllowAll ); } - Err(e) => panic!( - "Encountered an unexpected error in chain registry test: {}", - e - ), + Err(e) => panic!("Encountered an unexpected error in chain registry test: {e}"), } } @@ -400,7 +410,7 @@ mod tests { let configs = get_configs(test_chains, Some(TEST_COMMIT.to_owned())).await?; - for config in configs { + for (_name, config) in configs { match config { Ok(config) => match &config.packet_filter().channel_policy { ChannelPolicy::Allow(channel_filter) => { diff --git a/crates/relayer-cli/src/cli_utils.rs b/crates/relayer-cli/src/cli_utils.rs index 6b3722ce3d..5441bb1594 100644 --- a/crates/relayer-cli/src/cli_utils.rs +++ b/crates/relayer-cli/src/cli_utils.rs @@ -5,30 +5,17 @@ use alloc::sync::Arc; use eyre::eyre; use ibc_relayer::{ chain::{ - counterparty::{ - channel_connection_client, - ChannelConnectionClient, - }, - handle::{ - BaseChainHandle, - ChainHandle, - }, + counterparty::{channel_connection_client, ChannelConnectionClient}, + handle::{BaseChainHandle, ChainHandle}, requests::{ - IncludeProof, - QueryChannelRequest, - QueryClientStateRequest, - QueryConnectionRequest, + IncludeProof, QueryChannelRequest, QueryClientStateRequest, QueryConnectionRequest, QueryHeight, }, }, config::Config, spawn, }; -use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, -}; +use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; use tokio::runtime::Runtime as TokioRuntime; use tracing::debug; diff --git a/crates/relayer-cli/src/commands.rs b/crates/relayer-cli/src/commands.rs index 92cc7939f5..bfdd3055d3 100644 --- a/crates/relayer-cli/src/commands.rs +++ b/crates/relayer-cli/src/commands.rs @@ -22,40 +22,16 @@ use core::time::Duration; use std::path::PathBuf; use abscissa_core::{ - clap::Parser, - config::Override, - Command, - Configurable, - FrameworkError, - Runnable, -}; -use ibc_relayer::config::{ - ChainConfig, - Config, -}; -use tracing::{ - error, - info, + clap::Parser, config::Override, Command, Configurable, FrameworkError, Runnable, }; +use ibc_relayer::config::{ChainConfig, Config}; +use tracing::{error, info}; use self::{ - clear::ClearCmds, - completions::CompletionsCmd, - config::ConfigCmd, - create::CreateCmds, - 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, + clear::ClearCmds, completions::CompletionsCmd, config::ConfigCmd, create::CreateCmds, + 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 crate::DEFAULT_CONFIG_PATH; @@ -124,7 +100,7 @@ pub enum CliCmd { /// The `version` subcommand, retained for backward compatibility. Version(VersionCmd), - /// Performs a health check of all chains in the the config + /// Performs a health check of all chains in the config HealthCheck(HealthCheckCmd), /// Generate auto-complete scripts for different shells. @@ -175,7 +151,11 @@ impl Configurable for CliCmd { for ccfg in config.chains.iter_mut() { #[allow(irrefutable_let_patterns)] if let ChainConfig::CosmosSdk(ref mut cosmos_ccfg) = ccfg { - cosmos_ccfg.memo_prefix.apply_suffix(&suffix); + if let Some(memo) = &cosmos_ccfg.memo_overwrite { + cosmos_ccfg.memo_prefix = memo.clone(); + } else { + cosmos_ccfg.memo_prefix.apply_suffix(&suffix); + } } } diff --git a/crates/relayer-cli/src/commands/clear.rs b/crates/relayer-cli/src/commands/clear.rs index 83ca60c562..14868011a2 100644 --- a/crates/relayer-cli/src/commands/clear.rs +++ b/crates/relayer-cli/src/commands/clear.rs @@ -1,42 +1,23 @@ +use eyre::eyre; use std::ops::RangeInclusive; -use abscissa_core::{ - clap::Parser, - config::Override, - Command, - FrameworkErrorKind, - Runnable, -}; -use ibc_relayer::{ - chain::handle::{ - BaseChainHandle, - ChainHandle, - }, - config::Config, - link::{ - error::LinkError, - Link, - LinkParameters, - }, - util::seq_range::parse_seq_range, -}; -use ibc_relayer_types::{ - core::{ - ics04_channel::packet::Sequence, - ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }, - }, - events::IbcEvent, -}; - -use crate::{ - application::app_config, - cli_utils::spawn_chain_counterparty, - conclude::Output, -}; +use abscissa_core::clap::Parser; +use abscissa_core::config::Override; +use abscissa_core::{Command, FrameworkErrorKind, Runnable}; + +use ibc_relayer::chain::handle::{BaseChainHandle, ChainHandle}; +use ibc_relayer::chain::requests::{IncludeProof, QueryChannelRequest, QueryHeight}; +use ibc_relayer::config::Config; +use ibc_relayer::link::error::LinkError; +use ibc_relayer::link::{Link, LinkParameters}; +use ibc_relayer::util::seq_range::parse_seq_range; +use ibc_relayer_types::core::ics04_channel::packet::Sequence; +use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; +use ibc_relayer_types::events::IbcEvent; + +use crate::application::app_config; +use crate::cli_utils::spawn_chain_counterparty; +use crate::conclude::Output; /// `clear` subcommands #[derive(Command, Debug, Parser, Runnable)] @@ -167,27 +148,84 @@ impl Runnable for ClearPacketsCmd { } } - let mut ev_list = vec![]; + let (channel, _) = match chains.src.query_channel( + QueryChannelRequest { + port_id: self.port_id.clone(), + channel_id: self.channel_id.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) { + Ok(channel) => channel, + Err(e) => Output::error(e).exit(), + }; + + let exclude_src_sequences = config + .find_chain(&chains.src.id()) + .map(|chain_config| chain_config.excluded_sequences(&self.channel_id).to_vec()) + .unwrap_or_default(); + + let exclude_dst_sequences = + if let Some(counterparty_channel_id) = channel.counterparty().channel_id() { + config + .find_chain(&chains.dst.id()) + .map(|chain_config| { + chain_config + .excluded_sequences(counterparty_channel_id) + .to_vec() + }) + .unwrap_or_default() + } else { + Vec::new() + }; // Construct links in both directions. - let opts = LinkParameters { + let fwd_opts = LinkParameters { src_port_id: self.port_id.clone(), src_channel_id: self.channel_id.clone(), max_memo_size: config.mode.packets.ics20_max_memo_size, max_receiver_size: config.mode.packets.ics20_max_receiver_size, + exclude_src_sequences, }; - let fwd_link = match Link::new_from_opts(chains.src.clone(), chains.dst, opts, false, false) - { + let counterparty_channel_id = match channel.counterparty().channel_id() { + Some(channel_id) => channel_id.clone(), + None => Output::error(eyre!( + "Channel `{}` and port `{}` does not have a counterparty channel id", + self.channel_id, + self.port_id + )) + .exit(), + }; + + // Construct links in both directions. + let reverse_opts = LinkParameters { + src_port_id: channel.counterparty().port_id().clone(), + src_channel_id: counterparty_channel_id, + max_memo_size: config.mode.packets.ics20_max_memo_size, + max_receiver_size: config.mode.packets.ics20_max_receiver_size, + exclude_src_sequences: exclude_dst_sequences, + }; + + let fwd_link = match Link::new_from_opts( + chains.src.clone(), + chains.dst.clone(), + fwd_opts, + false, + false, + ) { Ok(link) => link, Err(e) => Output::error(e).exit(), }; - let rev_link = match fwd_link.reverse(false, false) { + let rev_link = match Link::new_from_opts(chains.dst, chains.src, reverse_opts, false, false) + { Ok(link) => link, Err(e) => Output::error(e).exit(), }; + let mut ev_list = vec![]; + // Schedule RecvPacket messages for pending packets in both directions or, // if packet sequences are provided, only on the specified chain. // This may produce pending acks which will be processed in the next phase. @@ -227,17 +265,13 @@ where #[cfg(test)] mod tests { + use super::ClearPacketsCmd; + use std::str::FromStr; use abscissa_core::clap::Parser; - use ibc_relayer_types::core::{ - ics04_channel::packet::Sequence, - ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }, - }; + use ibc_relayer_types::core::ics04_channel::packet::Sequence; + use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; #[test] fn test_clear_packets_required_only() { diff --git a/crates/relayer-cli/src/commands/completions.rs b/crates/relayer-cli/src/commands/completions.rs index ff2b2942c7..4e1b30cd62 100644 --- a/crates/relayer-cli/src/commands/completions.rs +++ b/crates/relayer-cli/src/commands/completions.rs @@ -1,9 +1,6 @@ use std::io; -use abscissa_core::{ - clap::Parser, - Runnable, -}; +use abscissa_core::{clap::Parser, Runnable}; use clap::IntoApp; use clap_complete::Shell; diff --git a/crates/relayer-cli/src/commands/config.rs b/crates/relayer-cli/src/commands/config.rs index 4e6bf10a1a..737b4e877b 100644 --- a/crates/relayer-cli/src/commands/config.rs +++ b/crates/relayer-cli/src/commands/config.rs @@ -1,10 +1,6 @@ //! `config` subcommand -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; +use abscissa_core::{clap::Parser, Command, Runnable}; mod auto; mod validate; diff --git a/crates/relayer-cli/src/commands/config/auto.rs b/crates/relayer-cli/src/commands/config/auto.rs index ff729a14d3..2e837c801e 100644 --- a/crates/relayer-cli/src/commands/config/auto.rs +++ b/crates/relayer-cli/src/commands/config/auto.rs @@ -1,27 +1,15 @@ -use std::{ - collections::HashSet, - path::PathBuf, -}; - -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use ibc_relayer::config::{ - store, - ChainConfig, - Config, -}; -use tracing::{ - info, - warn, -}; - -use crate::{ - chain_registry::get_configs, - conclude::Output, -}; +use crate::chain_registry::get_configs; +use abscissa_core::clap::Parser; +use abscissa_core::{Command, Runnable}; +use itertools::Itertools; + +use crate::conclude::Output; + +use ibc_relayer::config::{store, ChainConfig, Config}; + +use std::collections::HashSet; +use std::path::PathBuf; +use tracing::{error, info, warn}; fn find_key(chain_config: &ChainConfig) -> Option { let keys = chain_config.list_keys().ok()?; @@ -38,7 +26,7 @@ fn find_key(chain_config: &ChainConfig) -> Option { /// If a is specified then it will be used without verifying that it exists. #[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] #[clap( - override_usage = "hermes config auto [OPTIONS] --output --chains " + override_usage = "hermes config auto [OPTIONS] --output --chain --chain " )] pub struct AutoCmd { #[clap( @@ -52,11 +40,14 @@ pub struct AutoCmd { #[clap( long = "chains", + alias = "chain", required = true, multiple = true, value_name = "CHAIN_NAME:OPTIONAL_KEY_NAME", help_heading = "REQUIRED", - help = "Names of the chains to include in the config. Every chain must be in the chain registry." + help = "Names of the chains to include in the configuration, together with an optional key name. \ + Either repeat this argument for every chain or pass a space-separated list of chains. \ + Every chain must be found in the chain registry." )] chain_names: Vec, @@ -90,18 +81,17 @@ impl Runnable for AutoCmd { // Extract keys and sort chains by name let names_and_keys = extract_chains_and_keys(&self.chain_names); - let sorted_names = names_and_keys + + let chain_names = names_and_keys .iter() - .map(|n| &n.0) + .map(|(n, _)| n) .cloned() .collect::>(); - let sorted_names_set: HashSet = HashSet::from_iter(sorted_names.iter().cloned()); - let commit = self.commit.clone(); // Fetch chain configs from the chain registry - let config_results = runtime.block_on(get_configs(&sorted_names, commit)); + let config_results = runtime.block_on(get_configs(&chain_names, commit)); if let Err(e) = config_results { let config = Config::default(); @@ -122,22 +112,32 @@ impl Runnable for AutoCmd { } }; - let mut chain_configs: Vec = config_results + let mut chain_configs: Vec<(String, ChainConfig)> = config_results .unwrap() .into_iter() - .filter_map(|r| r.ok()) + .filter_map(|(name, config)| match config { + Ok(config) => Some((name, config)), + Err(e) => { + error!("Failed to generate chain config for chain '{name}': {e}"); + None + } + }) .collect(); // Determine which chains were not fetched - 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(); + let fetched_chains_set: HashSet<_> = + HashSet::from_iter(chain_configs.iter().map(|(name, _)| name).cloned()); + let expected_chains_set: HashSet<_> = HashSet::from_iter(chain_names.iter().cloned()); + + let missing_chains_set: HashSet<_> = expected_chains_set + .difference(&fetched_chains_set) + .collect(); let configs_and_keys = chain_configs .iter_mut() - .zip(names_and_keys.iter().map(|n| &n.1).cloned()); + .zip(names_and_keys.iter().map(|(_, keys)| keys).cloned()); - for (chain_config, key_option) in configs_and_keys { + for ((_name, 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); @@ -157,28 +157,27 @@ impl Runnable for AutoCmd { } let config = Config { - chains: chain_configs, + chains: chain_configs.into_iter().map(|(_, c)| c).collect(), ..Config::default() }; match store(&config, &self.path) { + Ok(_) if missing_chains_set.is_empty() => { + Output::success_msg(format!( + "Config file written successfully at '{}'", + self.path.display() + )) + .exit() + }, Ok(_) => { - if missing_chains_set.is_empty() { - Output::success_msg(format!( - "Config file written successfully at '{}'", - self.path.display() - )) - .exit() - } else { - Output::success_msg(format!( - "Config file written successfully at '{}'. - However, configurations for the following chains were not able to be generated: {:?}", - self.path.display(), - missing_chains_set, - )) - .exit() - } - } + Output::success_msg(format!( + "Config file written successfully at '{}'. \ + However, configurations for the following chains were not able to be generated: {}", + self.path.display(), + missing_chains_set.iter().join(", "), + )) + .exit() + }, Err(e) => Output::error(format!( "An error occurred while attempting to write the config file: {}", e diff --git a/crates/relayer-cli/src/commands/config/validate.rs b/crates/relayer-cli/src/commands/config/validate.rs index 3970e33c63..ffbeaf5103 100644 --- a/crates/relayer-cli/src/commands/config/validate.rs +++ b/crates/relayer-cli/src/commands/config/validate.rs @@ -1,16 +1,8 @@ use std::fs; -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; +use abscissa_core::clap::Parser; -use crate::{ - conclude::Output, - config, - prelude::*, -}; +use crate::{conclude::Output, config, prelude::*}; /// In order to validate the configuration file the command will check that the file exists, /// that it is readable and not empty. It will then check the validity of the fields inside diff --git a/crates/relayer-cli/src/commands/create.rs b/crates/relayer-cli/src/commands/create.rs index 91a7dd6ca5..d1b0433f53 100644 --- a/crates/relayer-cli/src/commands/create.rs +++ b/crates/relayer-cli/src/commands/create.rs @@ -1,15 +1,8 @@ //! `create` subcommand -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; +use abscissa_core::{clap::Parser, Command, Runnable}; use crate::commands::{ - create::{ - channel::CreateChannelCommand, - connection::CreateConnectionCommand, - }, + create::{channel::CreateChannelCommand, connection::CreateConnectionCommand}, tx::client::TxCreateClientCmd, }; diff --git a/crates/relayer-cli/src/commands/create/channel.rs b/crates/relayer-cli/src/commands/create/channel.rs index 01b26dd79e..30e306dbee 100644 --- a/crates/relayer-cli/src/commands/create/channel.rs +++ b/crates/relayer-cli/src/commands/create/channel.rs @@ -1,49 +1,24 @@ -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; +use abscissa_core::clap::Parser; + use console::style; use dialoguer::Confirm; -use ibc_relayer::{ - chain::{ - handle::ChainHandle, - requests::{ - IncludeProof, - QueryClientStateRequest, - QueryConnectionRequest, - QueryHeight, - }, - }, - channel::Channel, - config::default::connection_delay, - connection::Connection, - foreign_client::ForeignClient, -}; -use ibc_relayer_types::core::{ - ics03_connection::connection::IdentifiedConnectionEnd, - ics04_channel::{ - channel::Ordering, - version::Version, - }, - ics24_host::identifier::{ - ChainId, - ConnectionId, - PortId, - }, -}; -use crate::{ - cli_utils::{ - spawn_chain_runtime, - ChainHandlePair, - }, - conclude::{ - exit_with_unrecoverable_error, - Output, - }, - prelude::*, +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::chain::requests::{ + IncludeProof, QueryClientStateRequest, QueryConnectionRequest, QueryHeight, }; +use ibc_relayer::channel::Channel; +use ibc_relayer::config::default::connection_delay; +use ibc_relayer::connection::Connection; +use ibc_relayer::foreign_client::ForeignClient; +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; +use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ConnectionId, PortId}; + +use crate::cli_utils::{spawn_chain_runtime, ChainHandlePair}; +use crate::conclude::{exit_with_unrecoverable_error, Output}; +use crate::prelude::*; 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 reuse a pre-existing connection."; @@ -297,15 +272,8 @@ mod tests { use abscissa_core::clap::Parser; use ibc_relayer_types::core::{ - ics04_channel::{ - channel::Ordering, - version::Version, - }, - ics24_host::identifier::{ - ChainId, - ConnectionId, - PortId, - }, + ics04_channel::{channel::Ordering, version::Version}, + ics24_host::identifier::{ChainId, ConnectionId, PortId}, }; use super::CreateChannelCommand; diff --git a/crates/relayer-cli/src/commands/create/connection.rs b/crates/relayer-cli/src/commands/create/connection.rs index 6e32016786..5e5a072a7d 100644 --- a/crates/relayer-cli/src/commands/create/connection.rs +++ b/crates/relayer-cli/src/commands/create/connection.rs @@ -1,36 +1,16 @@ use core::time::Duration; -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use ibc_relayer::{ - chain::{ - handle::ChainHandle, - requests::{ - IncludeProof, - QueryClientStateRequest, - QueryHeight, - }, - }, - connection::Connection, - foreign_client::ForeignClient, -}; -use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ClientId, -}; +use abscissa_core::clap::Parser; + +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::ics24_host::identifier::{ChainId, ClientId}; use crate::{ - cli_utils::{ - spawn_chain_runtime, - ChainHandlePair, - }, - conclude::{ - exit_with_unrecoverable_error, - Output, - }, + cli_utils::{spawn_chain_runtime, ChainHandlePair}, + conclude::{exit_with_unrecoverable_error, Output}, prelude::*, }; @@ -200,10 +180,7 @@ mod tests { use std::str::FromStr; use abscissa_core::clap::Parser; - use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ClientId, - }; + use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ClientId}; use super::CreateConnectionCommand; diff --git a/crates/relayer-cli/src/commands/evidence.rs b/crates/relayer-cli/src/commands/evidence.rs index 5848e121fe..3c4fb15877 100644 --- a/crates/relayer-cli/src/commands/evidence.rs +++ b/crates/relayer-cli/src/commands/evidence.rs @@ -1,81 +1,37 @@ -use std::{ - collections::HashMap, - ops::{ - ControlFlow, - Deref, - }, - sync::Arc, - thread::sleep, - time::Duration, -}; - -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use ibc_relayer::{ - chain::{ - cosmos::CosmosSdkChain, - endpoint::ChainEndpoint, - handle::{ - BaseChainHandle, - ChainHandle, - }, - requests::{ - IncludeProof, - PageRequest, - QueryHeight, - }, - tracking::TrackedMsgs, - }, - config::{ - ChainConfig, - Config, - }, - foreign_client::ForeignClient, - spawn::spawn_chain_runtime_with_modified_config, -}; -use ibc_relayer_types::{ - applications::ics28_ccv::msgs::{ - ccv_double_voting::MsgSubmitIcsConsumerDoubleVoting, - ccv_misbehaviour::MsgSubmitIcsConsumerMisbehaviour, - }, - clients::ics07_tendermint::{ - header::Header as TendermintHeader, - misbehaviour::Misbehaviour as TendermintMisbehaviour, - }, - core::{ - ics02_client::{ - height::Height, - msgs::misbehaviour::MsgSubmitMisbehaviour, - }, - ics24_host::identifier::{ - ChainId, - ClientId, - }, - }, - events::IbcEvent, - tx_msg::Msg, -}; -use tendermint::{ - block::Height as TendermintHeight, - evidence::{ - DuplicateVoteEvidence, - LightClientAttackEvidence, - }, - validator, -}; -use tendermint_rpc::{ - Client, - Paging, -}; +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 ibc_relayer::config::{ChainConfig, Config}; use tokio::runtime::Runtime as TokioRuntime; -use crate::{ - conclude::Output, - prelude::*, -}; +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 { @@ -373,11 +329,12 @@ fn submit_duplicate_vote_evidence( // 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 { + let consensus_state_heights = counterparty_chain_handle.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 @@ -740,10 +697,7 @@ fn fetch_all_counterparty_clients( config: &Config, chain: &CosmosSdkChain, ) -> eyre::Result> { - use ibc_relayer::chain::requests::{ - QueryClientStateRequest, - QueryConnectionsRequest, - }; + use ibc_relayer::chain::requests::{QueryClientStateRequest, QueryConnectionsRequest}; let connections = chain.query_connections(QueryConnectionsRequest { pagination: Some(PageRequest::all()), diff --git a/crates/relayer-cli/src/commands/fee.rs b/crates/relayer-cli/src/commands/fee.rs index c7feb66dd2..bc713c621b 100644 --- a/crates/relayer-cli/src/commands/fee.rs +++ b/crates/relayer-cli/src/commands/fee.rs @@ -1,16 +1,10 @@ //! `fee` subcommand -use abscissa_core::{ - clap::Parser, - config::Override, - Command, - Runnable, -}; +use abscissa_core::{clap::Parser, config::Override, Command, Runnable}; use ibc_relayer::config::Config; use self::{ - register_counterparty_payee::RegisterCounterpartyPayeeCmd, - register_payee::RegisterPayeeCmd, + register_counterparty_payee::RegisterCounterpartyPayeeCmd, register_payee::RegisterPayeeCmd, transfer::FeeTransferCmd, }; 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 536183397c..864f8a5f3d 100644 --- a/crates/relayer-cli/src/commands/fee/register_counterparty_payee.rs +++ b/crates/relayer-cli/src/commands/fee/register_counterparty_payee.rs @@ -1,31 +1,17 @@ use core::str::FromStr; -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use ibc_relayer::chain::{ - handle::ChainHandle, - tracking::TrackedMsgs, -}; +use abscissa_core::{clap::Parser, Command, Runnable}; +use ibc_relayer::chain::{handle::ChainHandle, tracking::TrackedMsgs}; use ibc_relayer_types::{ applications::ics29_fee::msgs::register_payee::build_register_counterparty_payee_message, - core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }, + core::ics24_host::identifier::{ChainId, ChannelId, PortId}, signer::Signer, }; use crate::{ application::app_config, cli_utils::spawn_chain_runtime, - conclude::{ - exit_with_unrecoverable_error, - Output, - }, + conclude::{exit_with_unrecoverable_error, Output}, error::Error, }; @@ -124,11 +110,7 @@ mod tests { use std::str::FromStr; use abscissa_core::clap::Parser; - use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }; + use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; use super::RegisterCounterpartyPayeeCmd; diff --git a/crates/relayer-cli/src/commands/fee/register_payee.rs b/crates/relayer-cli/src/commands/fee/register_payee.rs index d486f0e417..a8aa42df58 100644 --- a/crates/relayer-cli/src/commands/fee/register_payee.rs +++ b/crates/relayer-cli/src/commands/fee/register_payee.rs @@ -1,31 +1,17 @@ use core::str::FromStr; -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use ibc_relayer::chain::{ - handle::ChainHandle, - tracking::TrackedMsgs, -}; +use abscissa_core::{clap::Parser, Command, Runnable}; +use ibc_relayer::chain::{handle::ChainHandle, tracking::TrackedMsgs}; use ibc_relayer_types::{ applications::ics29_fee::msgs::register_payee::build_register_payee_message, - core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }, + core::ics24_host::identifier::{ChainId, ChannelId, PortId}, signer::Signer, }; use crate::{ application::app_config, cli_utils::spawn_chain_runtime, - conclude::{ - exit_with_unrecoverable_error, - Output, - }, + conclude::{exit_with_unrecoverable_error, Output}, error::Error, }; @@ -115,11 +101,7 @@ mod tests { use std::str::FromStr; use abscissa_core::clap::Parser; - use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }; + use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; use super::RegisterPayeeCmd; diff --git a/crates/relayer-cli/src/commands/fee/transfer.rs b/crates/relayer-cli/src/commands/fee/transfer.rs index 07a81edb17..ea5d0523a7 100644 --- a/crates/relayer-cli/src/commands/fee/transfer.rs +++ b/crates/relayer-cli/src/commands/fee/transfer.rs @@ -1,47 +1,23 @@ use core::time::Duration; -use abscissa_core::{ - clap::Parser, - config::Override, - Command, - FrameworkError, - FrameworkErrorKind, - Runnable, -}; +use abscissa_core::{clap::Parser, config::Override, FrameworkError, FrameworkErrorKind}; use eyre::eyre; use ibc_relayer::{ chain::handle::ChainHandle, config::Config, - transfer::{ - build_transfer_messages, - send_messages, - TransferOptions, - }, + transfer::{build_transfer_messages, send_messages, TransferOptions}, }; use ibc_relayer_types::{ applications::{ ics29_fee::msgs::pay_packet::build_pay_packet_message, - transfer::{ - Amount, - Coin, - }, - }, - core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, + transfer::{Amount, Coin}, }, + core::ics24_host::identifier::{ChainId, ChannelId, PortId}, }; use crate::{ - cli_utils::{ - check_can_send_on_channel, - ChainHandlePair, - }, - conclude::{ - exit_with_unrecoverable_error, - Output, - }, + cli_utils::{check_can_send_on_channel, ChainHandlePair}, + conclude::{exit_with_unrecoverable_error, Output}, prelude::*, }; @@ -331,11 +307,7 @@ mod tests { use abscissa_core::clap::Parser; use ibc_relayer_types::{ applications::transfer::Amount, - core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }, + core::ics24_host::identifier::{ChainId, ChannelId, PortId}, }; use super::FeeTransferCmd; diff --git a/crates/relayer-cli/src/commands/health.rs b/crates/relayer-cli/src/commands/health.rs index bf8c537302..6ecdd588dd 100644 --- a/crates/relayer-cli/src/commands/health.rs +++ b/crates/relayer-cli/src/commands/health.rs @@ -1,21 +1,11 @@ -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use ibc_relayer::chain::{ - endpoint::HealthCheck::*, - handle::ChainHandle, -}; - -use crate::{ - cli_utils::spawn_chain_runtime, - conclude::{ - exit_with_unrecoverable_error, - Output, - }, - prelude::*, -}; +use abscissa_core::clap::Parser; + +use ibc_relayer::chain::endpoint::HealthCheck::*; +use ibc_relayer::chain::handle::ChainHandle; + +use crate::cli_utils::spawn_chain_runtime; +use crate::conclude::{exit_with_unrecoverable_error, Output}; +use crate::prelude::*; #[derive(Clone, Command, Debug, Parser)] pub struct HealthCheckCmd {} diff --git a/crates/relayer-cli/src/commands/keys.rs b/crates/relayer-cli/src/commands/keys.rs index 3afb56da13..4d1c3f0986 100644 --- a/crates/relayer-cli/src/commands/keys.rs +++ b/crates/relayer-cli/src/commands/keys.rs @@ -1,9 +1,5 @@ //! `keys` subcommand -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; +use abscissa_core::{clap::Parser, Command, Runnable}; mod add; mod balance; diff --git a/crates/relayer-cli/src/commands/keys/add.rs b/crates/relayer-cli/src/commands/keys/add.rs index 2288ba49b8..a28ac5c941 100644 --- a/crates/relayer-cli/src/commands/keys/add.rs +++ b/crates/relayer-cli/src/commands/keys/add.rs @@ -1,41 +1,23 @@ use core::str::FromStr; use std::{ fs, - path::{ - Path, - PathBuf, - }, + path::{Path, PathBuf}, }; -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; +use abscissa_core::{clap::Parser, Command, Runnable}; use eyre::eyre; use hdpath::StandardHDPath; use ibc_relayer::{ - config::{ - ChainConfig, - Config, - }, + config::{ChainConfig, Config}, keyring::{ - AnySigningKeyPair, - Ed25519KeyPair, - KeyRing, - Secp256k1KeyPair, - SigningKeyPair, - SigningKeyPairSized, - Store, + AnySigningKeyPair, Ed25519KeyPair, KeyRing, Secp256k1KeyPair, SigningKeyPair, + SigningKeyPairSized, Store, }, }; use ibc_relayer_types::core::ics24_host::identifier::ChainId; use tracing::warn; -use crate::{ - application::app_config, - conclude::Output, -}; +use crate::{application::app_config, conclude::Output}; /// The data structure that represents the arguments when invoking the `keys add` CLI command. /// diff --git a/crates/relayer-cli/src/commands/keys/balance.rs b/crates/relayer-cli/src/commands/keys/balance.rs index 95ead20f2b..9a08d79d87 100644 --- a/crates/relayer-cli/src/commands/keys/balance.rs +++ b/crates/relayer-cli/src/commands/keys/balance.rs @@ -1,24 +1,13 @@ use std::fmt::Write; -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use ibc_relayer::{ - chain::handle::ChainHandle, - config::ChainConfig, -}; +use abscissa_core::{clap::Parser, Command, Runnable}; +use ibc_relayer::{chain::handle::ChainHandle, config::ChainConfig}; use ibc_relayer_types::core::ics24_host::identifier::ChainId; use crate::{ application::app_config, cli_utils::spawn_chain_runtime, - conclude::{ - exit_with_unrecoverable_error, - json, - Output, - }, + conclude::{exit_with_unrecoverable_error, json, Output}, }; /// The data structure that represents the arguments when invoking the `keys balance` CLI command. diff --git a/crates/relayer-cli/src/commands/keys/delete.rs b/crates/relayer-cli/src/commands/keys/delete.rs index 2370165eb0..be99da43ce 100644 --- a/crates/relayer-cli/src/commands/keys/delete.rs +++ b/crates/relayer-cli/src/commands/keys/delete.rs @@ -1,25 +1,12 @@ -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; +use abscissa_core::{clap::Parser, Command, Runnable}; use eyre::eyre; use ibc_relayer::{ - config::{ - ChainConfig, - Config, - }, - keyring::{ - KeyRing, - Store, - }, + config::{ChainConfig, Config}, + keyring::{KeyRing, Store}, }; use ibc_relayer_types::core::ics24_host::identifier::ChainId; -use crate::{ - application::app_config, - conclude::Output, -}; +use crate::{application::app_config, conclude::Output}; #[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] #[clap( diff --git a/crates/relayer-cli/src/commands/keys/list.rs b/crates/relayer-cli/src/commands/keys/list.rs index 2205cbb420..ac6c202755 100644 --- a/crates/relayer-cli/src/commands/keys/list.rs +++ b/crates/relayer-cli/src/commands/keys/list.rs @@ -1,23 +1,13 @@ use alloc::collections::btree_map::BTreeMap as HashMap; use core::fmt::Write; -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use ibc_relayer::config::{ - ChainConfig, - Config, -}; +use abscissa_core::{clap::Parser, Command, Runnable}; +use ibc_relayer::config::{ChainConfig, Config}; use ibc_relayer_types::core::ics24_host::identifier::ChainId; use crate::{ application::app_config, - conclude::{ - json, - Output, - }, + conclude::{json, Output}, }; #[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] diff --git a/crates/relayer-cli/src/commands/listen.rs b/crates/relayer-cli/src/commands/listen.rs index 092877a041..a262192d48 100644 --- a/crates/relayer-cli/src/commands/listen.rs +++ b/crates/relayer-cli/src/commands/listen.rs @@ -1,45 +1,26 @@ use alloc::sync::Arc; use core::{ - fmt::{ - Display, - Error as FmtError, - Formatter, - }, + fmt::{Display, Error as FmtError, Formatter}, str::FromStr, }; use std::thread; -use abscissa_core::{ - application::fatal_error, - clap::Parser, - Runnable, -}; +use abscissa_core::application::fatal_error; +use abscissa_core::clap::Parser; use eyre::eyre; use ibc_relayer::{ chain::handle::Subscription, - config::{ - ChainConfig, - EventSourceMode, - }, + config::{ChainConfig, EventSourceMode}, + error::Error, event::source::EventSource, util::compat_mode::compat_mode_from_version, + HERMES_VERSION, }; -use ibc_relayer_types::{ - core::ics24_host::identifier::ChainId, - events::IbcEvent, -}; +use ibc_relayer_types::{core::ics24_host::identifier::ChainId, events::IbcEvent}; use itertools::Itertools; -use tendermint_rpc::{ - client::CompatMode, - Client, - HttpClient, -}; +use tendermint_rpc::{client::CompatMode, Client, HttpClient}; use tokio::runtime::Runtime as TokioRuntime; -use tracing::{ - error, - info, - instrument, -}; +use tracing::{error, info, instrument}; use crate::prelude::*; @@ -176,12 +157,24 @@ fn subscribe( *batch_delay, rt, ), - EventSourceMode::Pull { interval } => EventSource::rpc( - chain_config.id().clone(), - HttpClient::new(config.rpc_addr.clone())?, - *interval, - rt, - ), + EventSourceMode::Pull { + interval, + max_retries, + } => { + let mut rpc_client = HttpClient::builder(config.rpc_addr.clone().try_into()?) + .user_agent(format!("hermes/{}", HERMES_VERSION)) + .build() + .map_err(|e| Error::rpc(config.rpc_addr.clone(), e))?; + rpc_client.set_compat_mode(compat_mode); + + EventSource::rpc( + chain_config.id().clone(), + rpc_client, + *interval, + *max_retries, + rt, + ) + } }?; thread::spawn(move || event_source.run()); @@ -201,7 +194,10 @@ fn detect_compatibility_mode( ChainConfig::CosmosSdk(config) => config.rpc_addr.clone(), ChainConfig::Astria(config) => config.rpc_addr.clone(), }; - let client = HttpClient::new(rpc_addr)?; + let client = HttpClient::builder(rpc_addr.try_into()?) + .user_agent(format!("hermes/{}", HERMES_VERSION)) + .build()?; + let status = rt.block_on(client.status())?; let compat_mode = match config { ChainConfig::CosmosSdk(config) => { @@ -221,10 +217,7 @@ mod tests { use abscissa_core::clap::Parser; use ibc_relayer_types::core::ics24_host::identifier::ChainId; - use super::{ - EventFilter, - ListenCmd, - }; + use super::{EventFilter, ListenCmd}; #[test] fn test_listen_required_only() { diff --git a/crates/relayer-cli/src/commands/logs.rs b/crates/relayer-cli/src/commands/logs.rs index 7aaeb53c4d..46f5e8f1ec 100644 --- a/crates/relayer-cli/src/commands/logs.rs +++ b/crates/relayer-cli/src/commands/logs.rs @@ -1,8 +1,4 @@ -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; +use abscissa_core::{clap::Parser, Command, Runnable}; pub mod log_level; pub mod raw; diff --git a/crates/relayer-cli/src/commands/logs/log_level.rs b/crates/relayer-cli/src/commands/logs/log_level.rs index 46ffb05f05..58b115488a 100644 --- a/crates/relayer-cli/src/commands/logs/log_level.rs +++ b/crates/relayer-cli/src/commands/logs/log_level.rs @@ -1,17 +1,7 @@ -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use tracing::{ - info, - Level, -}; +use abscissa_core::{clap::Parser, Command, Runnable}; +use tracing::{info, Level}; -use crate::{ - prelude::app_config, - tracing_handle::send_command, -}; +use crate::{prelude::app_config, tracing_handle::send_command}; #[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] pub struct SetLogLevelCmd { diff --git a/crates/relayer-cli/src/commands/logs/raw.rs b/crates/relayer-cli/src/commands/logs/raw.rs index 3ab062cb18..82316d0e4e 100644 --- a/crates/relayer-cli/src/commands/logs/raw.rs +++ b/crates/relayer-cli/src/commands/logs/raw.rs @@ -1,17 +1,7 @@ -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use tracing::{ - error, - info, -}; - -use crate::{ - prelude::app_config, - tracing_handle::send_command, -}; +use abscissa_core::{clap::Parser, Command, Runnable}; +use tracing::{error, info}; + +use crate::{prelude::app_config, tracing_handle::send_command}; // TODO `hermes set-raw-filter` #[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] diff --git a/crates/relayer-cli/src/commands/logs/reset.rs b/crates/relayer-cli/src/commands/logs/reset.rs index 29b7e8cb00..d76742b645 100644 --- a/crates/relayer-cli/src/commands/logs/reset.rs +++ b/crates/relayer-cli/src/commands/logs/reset.rs @@ -1,14 +1,7 @@ -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; - -use crate::{ - components::default_directive, - prelude::*, - tracing_handle::send_command, -}; +use abscissa_core::clap::Parser; +use abscissa_core::Command; + +use crate::{components::default_directive, prelude::*, tracing_handle::send_command}; #[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] pub struct ResetCmd {} diff --git a/crates/relayer-cli/src/commands/misbehaviour.rs b/crates/relayer-cli/src/commands/misbehaviour.rs index 9d091e35dc..e6e40e0cda 100644 --- a/crates/relayer-cli/src/commands/misbehaviour.rs +++ b/crates/relayer-cli/src/commands/misbehaviour.rs @@ -1,49 +1,20 @@ +use abscissa_core::clap::Parser; +use abscissa_core::Command; +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::chain::requests::{IncludeProof, QueryClientStateRequest, QueryHeight}; +use ibc_relayer::config::Config; +use ibc_relayer::foreign_client::{ForeignClient, MisbehaviourResults}; +use ibc_relayer::util::pretty::PrettySlice; +use ibc_relayer_types::core::ics02_client::events::UpdateClient; +use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ClientId}; +use ibc_relayer_types::events::IbcEvent; use std::ops::Deref; -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; +use crate::cli_utils::{spawn_chain_runtime, spawn_chain_runtime_generic}; +use crate::conclude::Output; +use crate::prelude::*; use eyre::eyre; -use ibc_relayer::{ - chain::{ - handle::ChainHandle, - requests::{ - IncludeProof, - QueryClientStateRequest, - QueryHeight, - }, - }, - config::Config, - foreign_client::{ - ForeignClient, - MisbehaviourResults, - }, - util::pretty::PrettySlice, -}; -use ibc_relayer_types::{ - core::{ - ics02_client::{ - client_state::ClientState, - events::UpdateClient, - }, - ics24_host::identifier::{ - ChainId, - ClientId, - }, - }, - events::IbcEvent, -}; - -use crate::{ - cli_utils::{ - spawn_chain_runtime, - spawn_chain_runtime_generic, - }, - conclude::Output, - prelude::*, -}; +use ibc_relayer_types::core::ics02_client::client_state::ClientState; #[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] pub struct MisbehaviourCmd { @@ -187,10 +158,7 @@ mod tests { use std::str::FromStr; use abscissa_core::clap::Parser; - use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ClientId, - }; + use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ClientId}; use super::MisbehaviourCmd; diff --git a/crates/relayer-cli/src/commands/query.rs b/crates/relayer-cli/src/commands/query.rs index cac9bf1fb5..3dd73168a2 100644 --- a/crates/relayer-cli/src/commands/query.rs +++ b/crates/relayer-cli/src/commands/query.rs @@ -1,16 +1,10 @@ //! `query` subcommand -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; +use abscissa_core::{clap::Parser, Command, Runnable}; use crate::commands::query::{ - channel_client::QueryChannelClientCmd, - channel_ends::QueryChannelEndsCmd, - channels::QueryChannelsCmd, - packet::QueryPacketCmds, + channel_client::QueryChannelClientCmd, channel_ends::QueryChannelEndsCmd, + channels::QueryChannelsCmd, packet::QueryPacketCmds, }; mod channel; diff --git a/crates/relayer-cli/src/commands/query/channel.rs b/crates/relayer-cli/src/commands/query/channel.rs index cfb02ee79b..87f2012d29 100644 --- a/crates/relayer-cli/src/commands/query/channel.rs +++ b/crates/relayer-cli/src/commands/query/channel.rs @@ -1,36 +1,15 @@ -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use ibc_relayer::chain::{ - handle::ChainHandle, - requests::{ - IncludeProof, - QueryChannelRequest, - QueryHeight, - }, -}; -use ibc_relayer_types::{ - core::{ - ics04_channel::channel::State, - ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }, - }, - Height, -}; - -use crate::{ - cli_utils::spawn_chain_runtime, - conclude::{ - exit_with_unrecoverable_error, - Output, - }, - prelude::*, -}; +use abscissa_core::clap::Parser; +use ibc_relayer::chain::handle::ChainHandle; + +use ibc_relayer::chain::requests::{IncludeProof, QueryChannelRequest, QueryHeight}; +use ibc_relayer_types::core::ics24_host::identifier::ChainId; +use ibc_relayer_types::core::ics24_host::identifier::{ChannelId, PortId}; + +use crate::cli_utils::spawn_chain_runtime; +use crate::conclude::{exit_with_unrecoverable_error, Output}; +use crate::prelude::*; +use ibc_relayer_types::core::ics04_channel::channel::State; +use ibc_relayer_types::Height; #[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] pub struct QueryChannelEndCmd { @@ -112,11 +91,7 @@ mod tests { use std::str::FromStr; use abscissa_core::clap::Parser; - use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }; + use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; use super::QueryChannelEndCmd; diff --git a/crates/relayer-cli/src/commands/query/channel_client.rs b/crates/relayer-cli/src/commands/query/channel_client.rs index 1fcdc4380b..e8a2ae0cca 100644 --- a/crates/relayer-cli/src/commands/query/channel_client.rs +++ b/crates/relayer-cli/src/commands/query/channel_client.rs @@ -1,25 +1,11 @@ -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use ibc_relayer::chain::{ - handle::ChainHandle, - requests::QueryChannelClientStateRequest, -}; -use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, -}; +use abscissa_core::{clap::Parser, Command, Runnable}; +use ibc_relayer::chain::{handle::ChainHandle, requests::QueryChannelClientStateRequest}; +use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; use crate::{ application::app_config, cli_utils::spawn_chain_runtime, - conclude::{ - exit_with_unrecoverable_error, - Output, - }, + conclude::{exit_with_unrecoverable_error, Output}, }; /// The data structure that represents the arguments when invoking the `query channel client` CLI command. @@ -80,11 +66,7 @@ mod tests { use std::str::FromStr; use abscissa_core::clap::Parser; - use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }; + use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; use super::QueryChannelClientCmd; diff --git a/crates/relayer-cli/src/commands/query/channel_ends.rs b/crates/relayer-cli/src/commands/query/channel_ends.rs index 72a7d85d96..6ea357facf 100644 --- a/crates/relayer-cli/src/commands/query/channel_ends.rs +++ b/crates/relayer-cli/src/commands/query/channel_ends.rs @@ -1,55 +1,21 @@ -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; +use abscissa_core::clap::Parser; +use serde::{Deserialize, Serialize}; + use eyre::eyre; -use ibc_relayer::{ - chain::{ - handle::{ - BaseChainHandle, - ChainHandle, - }, - requests::{ - IncludeProof, - QueryChannelRequest, - QueryClientStateRequest, - QueryConnectionRequest, - QueryHeight, - }, - }, - client_state::AnyClientState, - registry::Registry, -}; -use ibc_relayer_types::{ - core::{ - ics03_connection::connection::ConnectionEnd, - ics04_channel::channel::{ - ChannelEnd, - State, - }, - ics24_host::identifier::{ - ChainId, - ChannelId, - ClientId, - ConnectionId, - PortId, - }, - }, - Height, -}; -use serde::{ - Deserialize, - Serialize, +use ibc_relayer::chain::handle::{BaseChainHandle, ChainHandle}; +use ibc_relayer::chain::requests::{ + IncludeProof, QueryChannelRequest, QueryClientStateRequest, QueryConnectionRequest, QueryHeight, }; +use ibc_relayer::client_state::AnyClientState; +use ibc_relayer::registry::Registry; +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; +use ibc_relayer_types::core::ics24_host::identifier::{ChannelId, ClientId, ConnectionId, PortId}; +use ibc_relayer_types::Height; -use crate::{ - conclude::{ - exit_with_unrecoverable_error, - Output, - }, - prelude::*, -}; +use crate::conclude::{exit_with_unrecoverable_error, Output}; +use crate::prelude::*; #[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] pub struct QueryChannelEndsCmd { @@ -290,11 +256,7 @@ mod tests { use std::str::FromStr; use abscissa_core::clap::Parser; - use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }; + use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; use super::QueryChannelEndsCmd; diff --git a/crates/relayer-cli/src/commands/query/channels.rs b/crates/relayer-cli/src/commands/query/channels.rs index 9524928699..3091537784 100644 --- a/crates/relayer-cli/src/commands/query/channels.rs +++ b/crates/relayer-cli/src/commands/query/channels.rs @@ -1,52 +1,23 @@ -use core::fmt::{ - Debug, - Error, - Formatter, -}; +use core::fmt::{Debug, Error, Formatter}; + +use abscissa_core::clap::Parser; +use serde::Serialize; -use abscissa_core::{ - clap::Parser, - Runnable, -}; use eyre::eyre; -use ibc_relayer::{ - chain::{ - handle::{ - BaseChainHandle, - ChainHandle, - }, - requests::{ - IncludeProof, - PageRequest, - QueryChannelRequest, - QueryChannelsRequest, - QueryClientStateRequest, - QueryConnectionRequest, - QueryHeight, - }, - }, - registry::Registry, +use ibc_relayer::chain::handle::{BaseChainHandle, ChainHandle}; +use ibc_relayer::chain::requests::{ + IncludeProof, PageRequest, QueryChannelRequest, QueryChannelsRequest, QueryClientStateRequest, + QueryConnectionRequest, QueryHeight, }; -use ibc_relayer_types::core::{ - ics04_channel::channel::{ - ChannelEnd, - State, - }, - ics24_host::identifier::{ - ChainId, - ChannelId, - ConnectionId, - PortChannelId, - PortId, - }, +use ibc_relayer::registry::Registry; +use ibc_relayer_types::core::ics04_channel::channel::{ChannelEnd, State}; +use ibc_relayer_types::core::ics24_host::identifier::{ + ChainId, ChannelId, ConnectionId, PortChannelId, PortId, }; -use serde::Serialize; -use crate::{ - commands::query::channel_ends::ChannelEnds, - conclude::Output, - prelude::*, -}; +use crate::commands::query::channel_ends::ChannelEnds; +use crate::conclude::Output; +use crate::prelude::*; #[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] pub struct QueryChannelsCmd { diff --git a/crates/relayer-cli/src/commands/query/client.rs b/crates/relayer-cli/src/commands/query/client.rs index 53316ab0e8..ad5ffd0fd9 100644 --- a/crates/relayer-cli/src/commands/query/client.rs +++ b/crates/relayer-cli/src/commands/query/client.rs @@ -1,43 +1,22 @@ -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use color_eyre::eyre::eyre; -use ibc_relayer::chain::{ - handle::ChainHandle, - requests::{ - IncludeProof, - PageRequest, - QueryClientConnectionsRequest, - QueryClientEventRequest, - QueryClientStateRequest, - QueryConsensusStateHeightsRequest, - QueryConsensusStateRequest, - QueryHeight, - QueryTxRequest, - }, -}; -use ibc_relayer_types::{ - core::{ - ics02_client::client_state::ClientState, - ics24_host::identifier::{ - ChainId, - ClientId, - }, - }, - events::WithBlockDataType, - Height, +use abscissa_core::clap::Parser; +use abscissa_core::{Command, Runnable}; + +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::chain::requests::{ + IncludeProof, PageRequest, QueryClientConnectionsRequest, QueryClientEventRequest, + QueryClientStateRequest, QueryConsensusStateHeightsRequest, QueryConsensusStateRequest, + QueryHeight, QueryTxRequest, }; -use crate::{ - application::app_config, - cli_utils::spawn_chain_runtime, - conclude::{ - exit_with_unrecoverable_error, - Output, - }, -}; +use ibc_relayer_types::core::ics02_client::client_state::ClientState; +use ibc_relayer_types::core::ics24_host::identifier::ChainId; +use ibc_relayer_types::core::ics24_host::identifier::ClientId; +use ibc_relayer_types::events::WithBlockDataType; +use ibc_relayer_types::Height; + +use crate::application::app_config; +use crate::cli_utils::spawn_chain_runtime; +use crate::conclude::{exit_with_unrecoverable_error, Output}; /// Query client state command #[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] @@ -338,24 +317,10 @@ fn client_status( return Ok(Status::Frozen); } - let consensus_state_heights = - chain.query_consensus_state_heights(QueryConsensusStateHeightsRequest { - client_id: client_id.clone(), - pagination: Some(PageRequest::all()), - })?; - - let latest_consensus_height = consensus_state_heights.last().copied().ok_or_else(|| { - eyre!( - "no consensus state found for client '{}' on chain '{}'", - client_id, - chain.id() - ) - })?; - let (latest_consensus_state, _) = chain.query_consensus_state( QueryConsensusStateRequest { client_id: client_id.clone(), - consensus_height: latest_consensus_height, + consensus_height: client_state.latest_height(), query_height: QueryHeight::Latest, }, IncludeProof::No, @@ -430,17 +395,11 @@ mod tests { use std::str::FromStr; use abscissa_core::clap::Parser; - use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ClientId, - }; + use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ClientId}; use super::{ - QueryClientConnectionsCmd, - QueryClientConsensusCmd, - QueryClientHeaderCmd, - QueryClientStateCmd, - QueryClientStatusCmd, + QueryClientConnectionsCmd, QueryClientConsensusCmd, QueryClientHeaderCmd, + QueryClientStateCmd, QueryClientStatusCmd, }; #[test] diff --git a/crates/relayer-cli/src/commands/query/clients.rs b/crates/relayer-cli/src/commands/query/clients.rs index e19476a3c2..94cdff3e49 100644 --- a/crates/relayer-cli/src/commands/query/clients.rs +++ b/crates/relayer-cli/src/commands/query/clients.rs @@ -1,30 +1,14 @@ -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use ibc_relayer::chain::{ - handle::ChainHandle, - requests::{ - PageRequest, - QueryClientStatesRequest, - }, -}; -use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ClientId, -}; +use abscissa_core::clap::Parser; +use ibc_relayer::chain::handle::ChainHandle; use serde::Serialize; -use crate::{ - cli_utils::spawn_chain_runtime, - conclude::{ - exit_with_unrecoverable_error, - Output, - }, - error::Error, - prelude::*, -}; +use ibc_relayer::chain::requests::{PageRequest, QueryClientStatesRequest}; +use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ClientId}; + +use crate::cli_utils::spawn_chain_runtime; +use crate::conclude::{exit_with_unrecoverable_error, Output}; +use crate::error::Error; +use crate::prelude::*; /// Query clients command #[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] diff --git a/crates/relayer-cli/src/commands/query/connection.rs b/crates/relayer-cli/src/commands/query/connection.rs index 2e9b52f882..4dff3f9e85 100644 --- a/crates/relayer-cli/src/commands/query/connection.rs +++ b/crates/relayer-cli/src/commands/query/connection.rs @@ -1,39 +1,20 @@ -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use ibc_relayer::chain::{ - handle::ChainHandle, - requests::{ - IncludeProof, - PageRequest, - QueryConnectionChannelsRequest, - QueryConnectionRequest, - QueryHeight, - }, -}; -use ibc_relayer_types::{ - core::{ - ics03_connection::connection::State, - ics24_host::identifier::{ - ChainId, - ConnectionId, - PortChannelId, - }, - }, - Height, +use abscissa_core::clap::Parser; +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::chain::requests::{ + IncludeProof, PageRequest, QueryConnectionChannelsRequest, QueryConnectionRequest, QueryHeight, }; -use crate::{ - cli_utils::spawn_chain_runtime, - conclude::{ - exit_with_unrecoverable_error, - Output, - }, - error::Error, - prelude::*, +use ibc_relayer_types::core::{ + ics03_connection::connection::State, + ics24_host::identifier::ConnectionId, + ics24_host::identifier::{ChainId, PortChannelId}, }; +use ibc_relayer_types::Height; + +use crate::cli_utils::spawn_chain_runtime; +use crate::conclude::{exit_with_unrecoverable_error, Output}; +use crate::error::Error; +use crate::prelude::*; #[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] pub struct QueryConnectionEndCmd { @@ -161,15 +142,9 @@ mod tests { use std::str::FromStr; use abscissa_core::clap::Parser; - use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ConnectionId, - }; + use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ConnectionId}; - use super::{ - QueryConnectionChannelsCmd, - QueryConnectionEndCmd, - }; + use super::{QueryConnectionChannelsCmd, QueryConnectionEndCmd}; #[test] fn test_query_connection_channels() { diff --git a/crates/relayer-cli/src/commands/query/connections.rs b/crates/relayer-cli/src/commands/query/connections.rs index 08dd19c5ac..f583156ae5 100644 --- a/crates/relayer-cli/src/commands/query/connections.rs +++ b/crates/relayer-cli/src/commands/query/connections.rs @@ -1,28 +1,14 @@ -use abscissa_core::{ - clap::Parser, - Runnable, -}; -use ibc_relayer::chain::{ - handle::ChainHandle, - requests::{ - IncludeProof, - PageRequest, - QueryClientStateRequest, - QueryConnectionsRequest, - QueryHeight, - }, -}; -use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ConnectionId, +use abscissa_core::clap::Parser; + +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::chain::requests::{ + IncludeProof, PageRequest, QueryClientStateRequest, QueryConnectionsRequest, QueryHeight, }; +use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ConnectionId}; use crate::{ cli_utils::spawn_chain_runtime, - conclude::{ - exit_with_unrecoverable_error, - Output, - }, + conclude::{exit_with_unrecoverable_error, Output}, prelude::*, }; diff --git a/crates/relayer-cli/src/commands/query/packet.rs b/crates/relayer-cli/src/commands/query/packet.rs index f80cda2a2b..0920605ce3 100644 --- a/crates/relayer-cli/src/commands/query/packet.rs +++ b/crates/relayer-cli/src/commands/query/packet.rs @@ -1,8 +1,4 @@ -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; +use abscissa_core::{clap::Parser, Command, Runnable}; mod ack; mod acks; diff --git a/crates/relayer-cli/src/commands/query/packet/ack.rs b/crates/relayer-cli/src/commands/query/packet/ack.rs index ee2e09d812..5efe178ca8 100644 --- a/crates/relayer-cli/src/commands/query/packet/ack.rs +++ b/crates/relayer-cli/src/commands/query/packet/ack.rs @@ -1,41 +1,16 @@ -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use ibc_relayer::chain::{ - handle::ChainHandle, - requests::{ - IncludeProof, - QueryHeight, - QueryPacketAcknowledgementRequest, - }, -}; -use ibc_relayer_types::{ - core::{ - ics04_channel::packet::Sequence, - ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }, - }, - Height, -}; -use subtle_encoding::{ - Encoding, - Hex, -}; +use abscissa_core::clap::Parser; +use ibc_relayer::chain::requests::{IncludeProof, QueryHeight, QueryPacketAcknowledgementRequest}; +use subtle_encoding::{Encoding, Hex}; + +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer_types::core::ics04_channel::packet::Sequence; +use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; +use ibc_relayer_types::Height; -use crate::{ - cli_utils::spawn_chain_runtime, - conclude::{ - exit_with_unrecoverable_error, - Output, - }, - error::Error, - prelude::*, -}; +use crate::cli_utils::spawn_chain_runtime; +use crate::conclude::{exit_with_unrecoverable_error, Output}; +use crate::error::Error; +use crate::prelude::*; #[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] pub struct QueryPacketAcknowledgmentCmd { @@ -131,11 +106,7 @@ mod tests { use abscissa_core::clap::Parser; use ibc_relayer_types::core::{ ics04_channel::packet::Sequence, - ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }, + ics24_host::identifier::{ChainId, ChannelId, PortId}, }; use super::QueryPacketAcknowledgmentCmd; diff --git a/crates/relayer-cli/src/commands/query/packet/acks.rs b/crates/relayer-cli/src/commands/query/packet/acks.rs index 46a1cf9cd4..8815770d83 100644 --- a/crates/relayer-cli/src/commands/query/packet/acks.rs +++ b/crates/relayer-cli/src/commands/query/packet/acks.rs @@ -1,25 +1,11 @@ -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use ibc_relayer::chain::{ - counterparty::acknowledgements_on_chain, - handle::BaseChainHandle, -}; -use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, -}; +use abscissa_core::clap::Parser; + +use ibc_relayer::chain::counterparty::acknowledgements_on_chain; +use ibc_relayer::chain::handle::BaseChainHandle; +use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; use super::util::PacketSeqs; -use crate::{ - cli_utils::spawn_chain_counterparty, - conclude::Output, - error::Error, - prelude::*, -}; +use crate::{cli_utils::spawn_chain_counterparty, conclude::Output, error::Error, prelude::*}; #[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] pub struct QueryPacketAcknowledgementsCmd { @@ -93,11 +79,7 @@ mod tests { use std::str::FromStr; use abscissa_core::clap::Parser; - use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }; + use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; use super::QueryPacketAcknowledgementsCmd; diff --git a/crates/relayer-cli/src/commands/query/packet/commitment.rs b/crates/relayer-cli/src/commands/query/packet/commitment.rs index cc4069fe60..d3f7c0f40b 100644 --- a/crates/relayer-cli/src/commands/query/packet/commitment.rs +++ b/crates/relayer-cli/src/commands/query/packet/commitment.rs @@ -1,48 +1,16 @@ -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use ibc_relayer::chain::{ - handle::ChainHandle, - requests::{ - IncludeProof, - QueryHeight, - QueryPacketCommitmentRequest, - }, -}; -use ibc_relayer_types::{ - core::{ - ics04_channel::packet::Sequence, - ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }, - }, - Height, -}; -use serde::Serialize; -use subtle_encoding::{ - Encoding, - Hex, -}; +use abscissa_core::clap::Parser; +use subtle_encoding::{Encoding, Hex}; -use crate::{ - cli_utils::spawn_chain_runtime, - conclude::{ - exit_with_unrecoverable_error, - Output, - }, - error::Error, - prelude::*, -}; +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::chain::requests::{IncludeProof, QueryHeight, QueryPacketCommitmentRequest}; +use ibc_relayer_types::core::ics04_channel::packet::Sequence; +use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; +use ibc_relayer_types::Height; -#[derive(Serialize, Debug)] -struct PacketSeqs { - height: Height, - seqs: Vec, -} +use crate::cli_utils::spawn_chain_runtime; +use crate::conclude::{exit_with_unrecoverable_error, Output}; +use crate::error::Error; +use crate::prelude::*; #[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] pub struct QueryPacketCommitmentCmd { @@ -141,11 +109,7 @@ mod tests { use abscissa_core::clap::Parser; use ibc_relayer_types::core::{ ics04_channel::packet::Sequence, - ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }, + ics24_host::identifier::{ChainId, ChannelId, PortId}, }; use super::QueryPacketCommitmentCmd; diff --git a/crates/relayer-cli/src/commands/query/packet/commitments.rs b/crates/relayer-cli/src/commands/query/packet/commitments.rs index 94e9941b6b..55b8e41b76 100644 --- a/crates/relayer-cli/src/commands/query/packet/commitments.rs +++ b/crates/relayer-cli/src/commands/query/packet/commitments.rs @@ -1,22 +1,11 @@ -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; +use abscissa_core::clap::Parser; + use ibc_relayer::chain::counterparty::commitments_on_chain; -use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, -}; +use ibc_relayer::chain::requests::Paginate; +use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; use super::util::PacketSeqs; -use crate::{ - cli_utils::spawn_chain_runtime, - conclude::Output, - error::Error, - prelude::*, -}; +use crate::{cli_utils::spawn_chain_runtime, conclude::Output, error::Error, prelude::*}; #[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] pub struct QueryPacketCommitmentsCmd { @@ -55,7 +44,7 @@ impl QueryPacketCommitmentsCmd { let chain = spawn_chain_runtime(&config, &self.chain_id)?; - commitments_on_chain(&chain, &self.port_id, &self.channel_id) + commitments_on_chain(&chain, &self.port_id, &self.channel_id, Paginate::All) .map_err(Error::supervisor) .map(|(seqs_vec, height)| PacketSeqs { height, @@ -82,11 +71,7 @@ mod tests { use std::str::FromStr; use abscissa_core::clap::Parser; - use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }; + use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; use super::QueryPacketCommitmentsCmd; diff --git a/crates/relayer-cli/src/commands/query/packet/pending.rs b/crates/relayer-cli/src/commands/query/packet/pending.rs index c10898cd45..3974d7935d 100644 --- a/crates/relayer-cli/src/commands/query/packet/pending.rs +++ b/crates/relayer-cli/src/commands/query/packet/pending.rs @@ -1,35 +1,21 @@ use core::fmt; -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use ibc_relayer::chain::{ - counterparty::{ - channel_on_destination, - pending_packet_summary, - PendingPackets, - }, - handle::{ - BaseChainHandle, - ChainHandle, - }, -}; -use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, -}; +use abscissa_core::clap::Parser; use serde::Serialize; -use super::util::CollatedPendingPackets; -use crate::{ - cli_utils::spawn_chain_counterparty, - conclude::Output, - error::Error, - prelude::*, +use ibc_relayer::chain::counterparty::{ + channel_on_destination, pending_packet_summary, PendingPackets, }; +use ibc_relayer::chain::handle::{BaseChainHandle, ChainHandle}; +use ibc_relayer::chain::requests::Paginate; +use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; + +use crate::cli_utils::spawn_chain_counterparty; +use crate::conclude::Output; +use crate::error::Error; +use crate::prelude::*; + +use super::util::CollatedPendingPackets; /// A structure to display pending packet commitment sequence IDs /// at both ends of a channel. @@ -145,8 +131,13 @@ impl QueryPendingPacketsCmd { self.chain_id, chan_conn_cli.channel ); - let src_summary = pending_packet_summary(&chains.src, &chains.dst, &chan_conn_cli.channel) - .map_err(Error::supervisor)?; + let src_summary = pending_packet_summary( + &chains.src, + &chains.dst, + &chan_conn_cli.channel, + Paginate::All, + ) + .map_err(Error::supervisor)?; let counterparty_channel = channel_on_destination( &chan_conn_cli.channel, @@ -156,8 +147,13 @@ impl QueryPendingPacketsCmd { .map_err(Error::supervisor)? .ok_or_else(|| Error::missing_counterparty_channel_id(chan_conn_cli.channel))?; - let dst_summary = pending_packet_summary(&chains.dst, &chains.src, &counterparty_channel) - .map_err(Error::supervisor)?; + let dst_summary = pending_packet_summary( + &chains.dst, + &chains.src, + &counterparty_channel, + Paginate::All, + ) + .map_err(Error::supervisor)?; Ok(Summary { src_chain: chains.src.id(), @@ -185,11 +181,7 @@ mod tests { use std::str::FromStr; use abscissa_core::clap::Parser; - use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }; + use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; use super::QueryPendingPacketsCmd; diff --git a/crates/relayer-cli/src/commands/query/packet/pending_acks.rs b/crates/relayer-cli/src/commands/query/packet/pending_acks.rs index e20de7f482..e0463794c9 100644 --- a/crates/relayer-cli/src/commands/query/packet/pending_acks.rs +++ b/crates/relayer-cli/src/commands/query/packet/pending_acks.rs @@ -1,31 +1,17 @@ -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use ibc_relayer::{ - chain::{ - counterparty::unreceived_acknowledgements, - handle::BaseChainHandle, - }, - path::PathIdentifiers, - util::collate::CollatedIterExt, -}; -use ibc_relayer_types::core::{ - ics04_channel::packet::Sequence, - ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }, -}; - -use crate::{ - cli_utils::spawn_chain_counterparty, - conclude::Output, - error::Error, - prelude::*, -}; +use abscissa_core::clap::Parser; + +use ibc_relayer::chain::counterparty::unreceived_acknowledgements; +use ibc_relayer::chain::handle::BaseChainHandle; +use ibc_relayer::chain::requests::Paginate; +use ibc_relayer::path::PathIdentifiers; +use ibc_relayer::util::collate::CollatedIterExt; +use ibc_relayer_types::core::ics04_channel::packet::Sequence; +use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; + +use crate::cli_utils::spawn_chain_counterparty; +use crate::conclude::Output; +use crate::error::Error; +use crate::prelude::*; /// This command does the following: /// 1. queries the chain to get its counterparty, channel and port identifiers (needed in 2) @@ -83,8 +69,9 @@ impl QueryPendingAcksCmd { let path_identifiers = PathIdentifiers::from_channel_end(channel.clone()) .ok_or_else(|| Error::missing_counterparty_channel_id(channel))?; - let acks = unreceived_acknowledgements(&chains.src, &chains.dst, &path_identifiers) - .map_err(Error::supervisor)?; + let acks = + unreceived_acknowledgements(&chains.src, &chains.dst, &path_identifiers, Paginate::All) + .map_err(Error::supervisor)?; Ok(acks.map_or(vec![], |(sns, _)| sns)) } @@ -107,11 +94,7 @@ mod tests { use std::str::FromStr; use abscissa_core::clap::Parser; - use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }; + use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; use super::QueryPendingAcksCmd; diff --git a/crates/relayer-cli/src/commands/query/packet/pending_sends.rs b/crates/relayer-cli/src/commands/query/packet/pending_sends.rs index 9cbc305286..6f4fe5bf9e 100644 --- a/crates/relayer-cli/src/commands/query/packet/pending_sends.rs +++ b/crates/relayer-cli/src/commands/query/packet/pending_sends.rs @@ -1,31 +1,17 @@ -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use ibc_relayer::{ - chain::{ - counterparty::unreceived_packets, - handle::BaseChainHandle, - }, - path::PathIdentifiers, - util::collate::CollatedIterExt, -}; -use ibc_relayer_types::core::{ - ics04_channel::packet::Sequence, - ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }, -}; - -use crate::{ - cli_utils::spawn_chain_counterparty, - conclude::Output, - error::Error, - prelude::*, -}; +use abscissa_core::clap::Parser; + +use ibc_relayer::chain::counterparty::unreceived_packets; +use ibc_relayer::chain::handle::BaseChainHandle; +use ibc_relayer::chain::requests::Paginate; +use ibc_relayer::path::PathIdentifiers; +use ibc_relayer::util::collate::CollatedIterExt; +use ibc_relayer_types::core::ics04_channel::packet::Sequence; +use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; + +use crate::cli_utils::spawn_chain_counterparty; +use crate::conclude::Output; +use crate::error::Error; +use crate::prelude::*; /// This command does the following: /// 1. queries the chain to get its counterparty chain, channel and port identifiers (needed in 2) @@ -83,7 +69,7 @@ impl QueryPendingSendsCmd { let path_identifiers = PathIdentifiers::from_channel_end(channel.clone()) .ok_or_else(|| Error::missing_counterparty_channel_id(channel))?; - unreceived_packets(&chains.src, &chains.dst, &path_identifiers) + unreceived_packets(&chains.src, &chains.dst, &path_identifiers, Paginate::All) .map_err(Error::supervisor) .map(|(seq, _)| seq) } @@ -106,11 +92,7 @@ mod tests { use std::str::FromStr; use abscissa_core::clap::Parser; - use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }; + use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; use super::QueryPendingSendsCmd; diff --git a/crates/relayer-cli/src/commands/query/packet/util.rs b/crates/relayer-cli/src/commands/query/packet/util.rs index e02ff177f3..b7068cf344 100644 --- a/crates/relayer-cli/src/commands/query/packet/util.rs +++ b/crates/relayer-cli/src/commands/query/packet/util.rs @@ -1,14 +1,8 @@ use core::fmt; pub use ibc_relayer::chain::counterparty::PendingPackets; -use ibc_relayer::util::collate::{ - Collated, - CollatedIterExt, -}; -use ibc_relayer_types::{ - core::ics04_channel::packet::Sequence, - Height, -}; +use ibc_relayer::util::collate::{Collated, CollatedIterExt}; +use ibc_relayer_types::{core::ics04_channel::packet::Sequence, Height}; use serde::Serialize; #[derive(Serialize)] diff --git a/crates/relayer-cli/src/commands/query/transfer.rs b/crates/relayer-cli/src/commands/query/transfer.rs index c08b89f935..d1ec140a61 100644 --- a/crates/relayer-cli/src/commands/query/transfer.rs +++ b/crates/relayer-cli/src/commands/query/transfer.rs @@ -1,10 +1,6 @@ //! `query transfer` subcommand -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; +use abscissa_core::{clap::Parser, Command, Runnable}; mod denom_trace; diff --git a/crates/relayer-cli/src/commands/query/transfer/denom_trace.rs b/crates/relayer-cli/src/commands/query/transfer/denom_trace.rs index 9df325dec9..a0dea6d37c 100644 --- a/crates/relayer-cli/src/commands/query/transfer/denom_trace.rs +++ b/crates/relayer-cli/src/commands/query/transfer/denom_trace.rs @@ -1,19 +1,11 @@ -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; +use abscissa_core::{clap::Parser, Command, Runnable}; use ibc_relayer::chain::handle::ChainHandle; use ibc_relayer_types::core::ics24_host::identifier::ChainId; use crate::{ application::app_config, cli_utils::spawn_chain_runtime, - conclude::{ - exit_with_unrecoverable_error, - json, - Output, - }, + conclude::{exit_with_unrecoverable_error, json, Output}, }; /// The data structure that represents the arguments when invoking the `query transfer denom-trace` CLI command. @@ -22,7 +14,7 @@ use crate::{ /// /// `query transfer denom-trace --chain --hash ` /// -/// If successful the the base denomination and the path will be displayed. +/// If successful the base denomination and the path will be displayed. #[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] pub struct DenomTraceCmd { #[clap( diff --git a/crates/relayer-cli/src/commands/query/tx.rs b/crates/relayer-cli/src/commands/query/tx.rs index 311a996119..4d06b38256 100644 --- a/crates/relayer-cli/src/commands/query/tx.rs +++ b/crates/relayer-cli/src/commands/query/tx.rs @@ -1,10 +1,6 @@ //! `query tx` subcommand -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; +use abscissa_core::{clap::Parser, Command, Runnable}; mod events; diff --git a/crates/relayer-cli/src/commands/query/tx/events.rs b/crates/relayer-cli/src/commands/query/tx/events.rs index d4bcd51287..cd77ab0d04 100644 --- a/crates/relayer-cli/src/commands/query/tx/events.rs +++ b/crates/relayer-cli/src/commands/query/tx/events.rs @@ -1,26 +1,16 @@ use core::str::FromStr; -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; +use abscissa_core::{clap::Parser, Command, Runnable}; use ibc_relayer::chain::{ handle::ChainHandle, - requests::{ - QueryTxHash, - QueryTxRequest, - }, + requests::{QueryTxHash, QueryTxRequest}, }; use ibc_relayer_types::core::ics24_host::identifier::ChainId; use tendermint::Hash; use crate::{ cli_utils::spawn_chain_runtime, - conclude::{ - exit_with_unrecoverable_error, - Output, - }, + conclude::{exit_with_unrecoverable_error, Output}, error::Error, prelude::app_config, }; diff --git a/crates/relayer-cli/src/commands/start.rs b/crates/relayer-cli/src/commands/start.rs index a0a17cea19..94cc6ba07f 100644 --- a/crates/relayer-cli/src/commands/start.rs +++ b/crates/relayer-cli/src/commands/start.rs @@ -1,36 +1,18 @@ -use std::{ - error::Error, - io, -}; +use std::{error::Error, io}; -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; +use abscissa_core::clap::Parser; use crossbeam_channel::Sender; use ibc_relayer::{ - chain::handle::{ - CachingChainHandle, - ChainHandle, - }, + chain::handle::{CachingChainHandle, ChainHandle}, config::Config, registry::SharedRegistry, rest, - supervisor::{ - cmd::SupervisorCmd, - spawn_supervisor, - SupervisorHandle, - SupervisorOptions, - }, + supervisor::{cmd::SupervisorCmd, spawn_supervisor, SupervisorHandle, SupervisorOptions}, util::debug_section::DebugSection, }; use crate::{ - conclude::{ - json, - Output, - }, + conclude::{json, Output}, prelude::*, }; @@ -48,10 +30,7 @@ impl Runnable for StartCmd { let app = app_reader(); if app.debug_enabled(DebugSection::ProfilingJson) { - use std::{ - env, - path::Path, - }; + use std::{env, path::Path}; use ibc_relayer::util::profiling::open_or_create_profile_file; @@ -105,10 +84,7 @@ impl Runnable for StartCmd { /// - [DEPRECATED] SIGHUP: Trigger a reload of the configuration. /// - SIGUSR1: Ask the supervisor to dump its state and print it to the console. fn register_signals(tx_cmd: Sender) -> Result<(), io::Error> { - use signal_hook::{ - consts::signal::*, - iterator::Signals, - }; + use signal_hook::{consts::signal::*, iterator::Signals}; let sigs = vec![ SIGHUP, // Reload of configuration (disabled) @@ -154,7 +130,6 @@ fn register_signals(tx_cmd: Sender) -> Result<(), io::Error> { Ok(()) } -#[cfg(feature = "rest-server")] fn spawn_rest_server(config: &Config) -> Option { use ibc_relayer::util::spawn_blocking; @@ -192,23 +167,6 @@ fn spawn_rest_server(config: &Config) -> Option { Some(rx) } -#[cfg(not(feature = "rest-server"))] -fn spawn_rest_server(config: &Config) -> Option { - let rest = config.rest.clone(); - - if rest.enabled { - warn!( - "REST server enabled in the config but Hermes was built without REST support, \ - build Hermes with --features=rest-server to enable REST support." - ); - - None - } else { - None - } -} - -#[cfg(feature = "telemetry")] fn spawn_telemetry_server(config: &Config) { use ibc_relayer::util::spawn_blocking; @@ -243,16 +201,6 @@ fn spawn_telemetry_server(config: &Config) { }); } -#[cfg(not(feature = "telemetry"))] -fn spawn_telemetry_server(config: &Config) { - if config.telemetry.enabled { - warn!( - "telemetry enabled in the config but Hermes was built without telemetry support, \ - build Hermes with --features=telemetry to enable telemetry support." - ); - } -} - fn make_supervisor( config: Config, options: SupervisorOptions, diff --git a/crates/relayer-cli/src/commands/tx.rs b/crates/relayer-cli/src/commands/tx.rs index 8bca5448bd..cff8e440e5 100644 --- a/crates/relayer-cli/src/commands/tx.rs +++ b/crates/relayer-cli/src/commands/tx.rs @@ -1,10 +1,5 @@ //! `tx` subcommand -use abscissa_core::{ - clap::Parser, - config::Override, - Command, - Runnable, -}; +use abscissa_core::{clap::Parser, config::Override, Command, Runnable}; use ibc_relayer::config::Config; mod channel; @@ -48,6 +43,24 @@ pub enum TxCmd { /// Confirm the closing of a channel (ChannelCloseConfirm) ChanCloseConfirm(channel::TxChanCloseConfirmCmd), + /// Relay the channel upgrade attempt (ChannelUpgradeTry) + ChanUpgradeTry(channel::TxChanUpgradeTryCmd), + + /// Relay the channel upgrade attempt (ChannelUpgradeAck) + ChanUpgradeAck(channel::TxChanUpgradeAckCmd), + + /// Relay the channel upgrade attempt (ChannelUpgradeConfirm) + ChanUpgradeConfirm(channel::TxChanUpgradeConfirmCmd), + + /// Relay the channel upgrade attempt (ChannelUpgradeOpen) + ChanUpgradeOpen(channel::TxChanUpgradeOpenCmd), + + /// Relay the channel upgrade cancellation (ChannelUpgradeCancel) + ChanUpgradeCancel(channel::TxChanUpgradeCancelCmd), + + /// Relay the channel upgrade timeout (ChannelUpgradeTimeout) + ChanUpgradeTimeout(channel::TxChanUpgradeTimeoutCmd), + /// Send a fungible token transfer test transaction (ICS20 MsgTransfer) FtTransfer(transfer::TxIcs20MsgTransferCmd), diff --git a/crates/relayer-cli/src/commands/tx/channel.rs b/crates/relayer-cli/src/commands/tx/channel.rs index 73813b95ef..7db47011e7 100644 --- a/crates/relayer-cli/src/commands/tx/channel.rs +++ b/crates/relayer-cli/src/commands/tx/channel.rs @@ -1,46 +1,36 @@ #![allow(clippy::redundant_closure_call)] -use abscissa_core::{ - clap::Parser, - Command, - Runnable, +use abscissa_core::clap::Parser; +use abscissa_core::Command; + +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::chain::requests::{IncludeProof, QueryConnectionRequest, QueryHeight}; +use ibc_relayer::channel::{Channel, ChannelSide}; +use ibc_relayer_types::core::ics03_connection::connection::ConnectionEnd; +use ibc_relayer_types::core::ics04_channel::channel::Ordering; +use ibc_relayer_types::core::ics24_host::identifier::{ + ChainId, ChannelId, ClientId, ConnectionId, PortId, }; -use ibc_relayer::{ - chain::{ - handle::ChainHandle, - requests::{ - IncludeProof, - QueryConnectionRequest, - QueryHeight, - }, - }, - channel::{ - Channel, - ChannelSide, - }, -}; -use ibc_relayer_types::{ - core::{ - ics03_connection::connection::ConnectionEnd, - ics04_channel::channel::Ordering, - ics24_host::identifier::{ - ChainId, - ChannelId, - ClientId, - ConnectionId, - PortId, - }, - }, - events::IbcEvent, -}; - -use crate::{ - cli_utils::ChainHandlePair, - conclude::Output, - error::Error, - prelude::*, -}; - +use ibc_relayer_types::events::IbcEvent; + +use crate::cli_utils::ChainHandlePair; +use crate::conclude::Output; +use crate::error::Error; +use crate::prelude::*; + +/// Macro that generates the `Runnable::run` implementation for a +/// `tx channel` subcommand. +/// +/// The macro takes the following arguments: +/// - `$dbg_string`: a string literal that will be used to identify the subcommand +/// in debug logs +/// - `$func`: the method that will be called to build and send the `Channel` message +/// - `$self`: the type that `Runnable` is being implemented for +/// - `$chan`: a closure that specifies how to build the `Channel` object +/// +/// The macro spawns a `ChainHandlePair`, fetches the destination connection, +/// creates a `Channel` object via the closure, and then calls the `$func` method +/// with the `Channel` object. macro_rules! tx_chan_cmd { ($dbg_string:literal, $func:ident, $self:expr, $chan:expr) => { let config = app_config(); @@ -136,56 +126,33 @@ pub struct TxChanOpenInitCmd { impl Runnable for TxChanOpenInitCmd { fn run(&self) { - let config = app_config(); - - let chains = match ChainHandlePair::spawn(&config, &self.src_chain_id, &self.dst_chain_id) { - Ok(chains) => chains, - Err(e) => Output::error(e).exit(), - }; - - // Retrieve the connection - let dst_connection = match chains.dst.query_connection( - QueryConnectionRequest { - connection_id: self.dst_conn_id.clone(), - height: QueryHeight::Latest, - }, - IncludeProof::No, - ) { - Ok((connection, _)) => connection, - Err(e) => Output::error(e).exit(), - }; - - let channel = Channel { - connection_delay: Default::default(), - ordering: self.order, - a_side: ChannelSide::new( - chains.src, - ClientId::default(), - ConnectionId::default(), - self.src_port_id.clone(), - None, - None, - ), - b_side: ChannelSide::new( - chains.dst, - dst_connection.client_id().clone(), - self.dst_conn_id.clone(), - self.dst_port_id.clone(), - None, - None, - ), - }; - - info!("message ChanOpenInit: {}", channel); - - let res: Result = channel - .build_chan_open_init_and_send() - .map_err(Error::channel); - - match res { - Ok(receipt) => Output::success(receipt).exit(), - Err(e) => Output::error(e).exit(), - } + tx_chan_cmd!( + "ChanOpenInit", + build_chan_open_init_and_send, + self, + |chains: ChainHandlePair, dst_connection: ConnectionEnd| { + Channel { + connection_delay: Default::default(), + ordering: self.order, + a_side: ChannelSide::new( + chains.src, + ClientId::default(), + ConnectionId::default(), + self.src_port_id.clone(), + None, + None, + ), + b_side: ChannelSide::new( + chains.dst, + dst_connection.client_id().clone(), + self.dst_conn_id.clone(), + self.dst_port_id.clone(), + None, + None, + ), + } + } + ); } } @@ -692,28 +659,803 @@ impl Runnable for TxChanCloseConfirmCmd { } } -#[cfg(test)] -mod tests { - use std::str::FromStr; +/// Relay the channel upgrade attempt (ChannelUpgradeTry) +/// +/// Build and send a `ChannelUpgradeTry` message in response to +/// a `ChannelUpgradeInit` message, signaling the chain's intent to +/// cooperate with the source chain on upgrading the specified channel +/// and initiating the upgrade handshake. +#[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] +pub struct TxChanUpgradeTryCmd { + #[clap( + long = "dst-chain", + required = true, + value_name = "DST_CHAIN_ID", + help_heading = "REQUIRED", + help = "Identifier of the destination chain" + )] + dst_chain_id: ChainId, + + #[clap( + long = "src-chain", + required = true, + value_name = "SRC_CHAIN_ID", + help_heading = "REQUIRED", + help = "Identifier of the source chain" + )] + src_chain_id: ChainId, + + #[clap( + long = "dst-connection", + visible_alias = "dst-conn", + required = true, + value_name = "DST_CONNECTION_ID", + help_heading = "REQUIRED", + help = "Identifier of the destination connection" + )] + dst_conn_id: ConnectionId, + + #[clap( + long = "dst-port", + required = true, + value_name = "DST_PORT_ID", + help_heading = "REQUIRED", + help = "Identifier of the destination port" + )] + dst_port_id: PortId, + + #[clap( + long = "src-port", + required = true, + value_name = "SRC_PORT_ID", + help_heading = "REQUIRED", + help = "Identifier of the source port" + )] + src_port_id: PortId, + + #[clap( + long = "src-channel", + visible_alias = "src-chan", + required = true, + value_name = "SRC_CHANNEL_ID", + help_heading = "REQUIRED", + help = "Identifier of the source channel (required)" + )] + src_chan_id: ChannelId, + + #[clap( + long = "dst-channel", + visible_alias = "dst-chan", + required = true, + help_heading = "REQUIRED", + value_name = "DST_CHANNEL_ID", + help = "Identifier of the destination channel (optional)" + )] + dst_chan_id: Option, +} + +impl Runnable for TxChanUpgradeTryCmd { + fn run(&self) { + let config = app_config(); + + let chains = match ChainHandlePair::spawn(&config, &self.src_chain_id, &self.dst_chain_id) { + Ok(chains) => chains, + Err(e) => Output::error(format!("{}", e)).exit(), + }; + + // Retrieve the connection + let dst_connection = match chains.dst.query_connection( + QueryConnectionRequest { + connection_id: self.dst_conn_id.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) { + Ok((connection, _)) => connection, + Err(e) => Output::error(format!("{}", e)).exit(), + }; + + // Fetch the Channel that will facilitate the communication between the channel ends + // being upgraded. This channel is assumed to already exist on the destination chain. + let channel = Channel { + connection_delay: Default::default(), + ordering: Ordering::default(), + a_side: ChannelSide::new( + chains.src, + ClientId::default(), + ConnectionId::default(), + self.src_port_id.clone(), + Some(self.src_chan_id.clone()), + None, + ), + b_side: ChannelSide::new( + chains.dst, + dst_connection.client_id().clone(), + self.dst_conn_id.clone(), + self.dst_port_id.clone(), + self.dst_chan_id.clone(), + None, + ), + }; + + info!("message ChanUpgradeTry: {}", channel); + + let res: Result = channel + .build_chan_upgrade_try_and_send() + .map_err(Error::channel); + + match res { + Ok(receipt) => Output::success(receipt).exit(), + Err(e) => Output::error(e).exit(), + } + } +} + +/// Relay the channel upgrade attempt (ChannelUpgradeAck) +/// +/// Build and send a `ChannelUpgradeAck` message in response to +/// a `ChannelUpgradeTry` message in order to continue the channel +/// upgrade handshake. +#[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] +pub struct TxChanUpgradeAckCmd { + #[clap( + long = "dst-chain", + required = true, + value_name = "DST_CHAIN_ID", + help_heading = "REQUIRED", + help = "Identifier of the destination chain" + )] + dst_chain_id: ChainId, + + #[clap( + long = "src-chain", + required = true, + value_name = "SRC_CHAIN_ID", + help_heading = "REQUIRED", + help = "Identifier of the source chain" + )] + src_chain_id: ChainId, + + #[clap( + long = "dst-connection", + visible_alias = "dst-conn", + required = true, + value_name = "DST_CONNECTION_ID", + help_heading = "REQUIRED", + help = "Identifier of the destination connection" + )] + dst_conn_id: ConnectionId, + + #[clap( + long = "dst-port", + required = true, + value_name = "DST_PORT_ID", + help_heading = "REQUIRED", + help = "Identifier of the destination port" + )] + dst_port_id: PortId, + + #[clap( + long = "src-port", + required = true, + value_name = "SRC_PORT_ID", + help_heading = "REQUIRED", + help = "Identifier of the source port" + )] + src_port_id: PortId, + + #[clap( + long = "src-channel", + visible_alias = "src-chan", + required = true, + value_name = "SRC_CHANNEL_ID", + help_heading = "REQUIRED", + help = "Identifier of the source channel (required)" + )] + src_chan_id: ChannelId, + + #[clap( + long = "dst-channel", + visible_alias = "dst-chan", + required = true, + help_heading = "REQUIRED", + value_name = "DST_CHANNEL_ID", + help = "Identifier of the destination channel (optional)" + )] + dst_chan_id: Option, +} + +impl Runnable for TxChanUpgradeAckCmd { + fn run(&self) { + let config = app_config(); + + let chains = match ChainHandlePair::spawn(&config, &self.src_chain_id, &self.dst_chain_id) { + Ok(chains) => chains, + Err(e) => Output::error(format!("{}", e)).exit(), + }; + + // Retrieve the connection + let dst_connection = match chains.dst.query_connection( + QueryConnectionRequest { + connection_id: self.dst_conn_id.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) { + Ok((connection, _)) => connection, + Err(e) => Output::error(format!("{}", e)).exit(), + }; + + // Fetch the Channel that will facilitate the communication between the channel ends + // being upgraded. This channel is assumed to already exist on the destination chain. + let channel = Channel { + connection_delay: Default::default(), + ordering: Ordering::default(), + a_side: ChannelSide::new( + chains.src, + ClientId::default(), + ConnectionId::default(), + self.src_port_id.clone(), + Some(self.src_chan_id.clone()), + None, + ), + b_side: ChannelSide::new( + chains.dst, + dst_connection.client_id().clone(), + self.dst_conn_id.clone(), + self.dst_port_id.clone(), + self.dst_chan_id.clone(), + None, + ), + }; + + info!("message ChanUpgradeAck: {}", channel); + + let res: Result = channel + .build_chan_upgrade_ack_and_send() + .map_err(Error::channel); + + match res { + Ok(receipt) => Output::success(receipt).exit(), + Err(e) => Output::error(e).exit(), + } + } +} + +/// Relay the channel upgrade attempt (ChannelUpgradeConfirm) +/// +/// Build and send a `ChannelUpgradeConfirm` message in response to +/// a `ChannelUpgradeAck` message in order to continue the channel +/// upgrade handshake. +#[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] +pub struct TxChanUpgradeConfirmCmd { + #[clap( + long = "dst-chain", + required = true, + value_name = "DST_CHAIN_ID", + help_heading = "REQUIRED", + help = "Identifier of the destination chain" + )] + dst_chain_id: ChainId, + + #[clap( + long = "src-chain", + required = true, + value_name = "SRC_CHAIN_ID", + help_heading = "REQUIRED", + help = "Identifier of the source chain" + )] + src_chain_id: ChainId, + + #[clap( + long = "dst-connection", + visible_alias = "dst-conn", + required = true, + value_name = "DST_CONNECTION_ID", + help_heading = "REQUIRED", + help = "Identifier of the destination connection" + )] + dst_conn_id: ConnectionId, + + #[clap( + long = "dst-port", + required = true, + value_name = "DST_PORT_ID", + help_heading = "REQUIRED", + help = "Identifier of the destination port" + )] + dst_port_id: PortId, + + #[clap( + long = "src-port", + required = true, + value_name = "SRC_PORT_ID", + help_heading = "REQUIRED", + help = "Identifier of the source port" + )] + src_port_id: PortId, + + #[clap( + long = "src-channel", + visible_alias = "src-chan", + required = true, + value_name = "SRC_CHANNEL_ID", + help_heading = "REQUIRED", + help = "Identifier of the source channel (required)" + )] + src_chan_id: ChannelId, + + #[clap( + long = "dst-channel", + visible_alias = "dst-chan", + required = true, + help_heading = "REQUIRED", + value_name = "DST_CHANNEL_ID", + help = "Identifier of the destination channel (optional)" + )] + dst_chan_id: Option, +} + +impl Runnable for TxChanUpgradeConfirmCmd { + fn run(&self) { + let config = app_config(); + + let chains = match ChainHandlePair::spawn(&config, &self.src_chain_id, &self.dst_chain_id) { + Ok(chains) => chains, + Err(e) => Output::error(format!("{}", e)).exit(), + }; + + // Retrieve the connection + let dst_connection = match chains.dst.query_connection( + QueryConnectionRequest { + connection_id: self.dst_conn_id.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) { + Ok((connection, _)) => connection, + Err(e) => Output::error(format!("{}", e)).exit(), + }; + + // Fetch the Channel that will facilitate the communication between the channel ends + // being upgraded. This channel is assumed to already exist on the destination chain. + let channel = Channel { + connection_delay: Default::default(), + ordering: Ordering::default(), + a_side: ChannelSide::new( + chains.src, + ClientId::default(), + ConnectionId::default(), + self.src_port_id.clone(), + Some(self.src_chan_id.clone()), + None, + ), + b_side: ChannelSide::new( + chains.dst, + dst_connection.client_id().clone(), + self.dst_conn_id.clone(), + self.dst_port_id.clone(), + self.dst_chan_id.clone(), + None, + ), + }; + + info!("message ChanUpgradeConfirm: {}", channel); + + let res: Result = channel + .build_chan_upgrade_confirm_and_send() + .map_err(Error::channel); + + match res { + Ok(receipt) => Output::success(receipt).exit(), + Err(e) => Output::error(e).exit(), + } + } +} + +/// Relay the channel upgrade attempt (ChannelUpgradeOpen) +/// +/// Build and send a `ChannelUpgradeOpen` message to finalize +/// the channel upgrade handshake. +#[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] +pub struct TxChanUpgradeOpenCmd { + #[clap( + long = "dst-chain", + required = true, + value_name = "DST_CHAIN_ID", + help_heading = "REQUIRED", + help = "Identifier of the destination chain" + )] + dst_chain_id: ChainId, + + #[clap( + long = "src-chain", + required = true, + value_name = "SRC_CHAIN_ID", + help_heading = "REQUIRED", + help = "Identifier of the source chain" + )] + src_chain_id: ChainId, + + #[clap( + long = "dst-connection", + visible_alias = "dst-conn", + required = true, + value_name = "DST_CONNECTION_ID", + help_heading = "REQUIRED", + help = "Identifier of the destination connection" + )] + dst_conn_id: ConnectionId, + + #[clap( + long = "dst-port", + required = true, + value_name = "DST_PORT_ID", + help_heading = "REQUIRED", + help = "Identifier of the destination port" + )] + dst_port_id: PortId, + + #[clap( + long = "src-port", + required = true, + value_name = "SRC_PORT_ID", + help_heading = "REQUIRED", + help = "Identifier of the source port" + )] + src_port_id: PortId, + + #[clap( + long = "src-channel", + visible_alias = "src-chan", + required = true, + value_name = "SRC_CHANNEL_ID", + help_heading = "REQUIRED", + help = "Identifier of the source channel (required)" + )] + src_chan_id: ChannelId, + + #[clap( + long = "dst-channel", + visible_alias = "dst-chan", + required = true, + help_heading = "REQUIRED", + value_name = "DST_CHANNEL_ID", + help = "Identifier of the destination channel (optional)" + )] + dst_chan_id: Option, +} + +impl Runnable for TxChanUpgradeOpenCmd { + fn run(&self) { + let config = app_config(); + + let chains = match ChainHandlePair::spawn(&config, &self.src_chain_id, &self.dst_chain_id) { + Ok(chains) => chains, + Err(e) => Output::error(format!("{}", e)).exit(), + }; + + // Retrieve the connection + let dst_connection = match chains.dst.query_connection( + QueryConnectionRequest { + connection_id: self.dst_conn_id.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) { + Ok((connection, _)) => connection, + Err(e) => Output::error(format!("{}", e)).exit(), + }; + + // Fetch the Channel that will facilitate the communication between the channel ends + // being upgraded. This channel is assumed to already exist on the destination chain. + let channel = Channel { + connection_delay: Default::default(), + ordering: Ordering::default(), + a_side: ChannelSide::new( + chains.src, + ClientId::default(), + ConnectionId::default(), + self.src_port_id.clone(), + Some(self.src_chan_id.clone()), + None, + ), + b_side: ChannelSide::new( + chains.dst, + dst_connection.client_id().clone(), + self.dst_conn_id.clone(), + self.dst_port_id.clone(), + self.dst_chan_id.clone(), + None, + ), + }; + + info!("message ChanUpgradeOpen: {}", channel); + + let res: Result = channel + .build_chan_upgrade_open_and_send() + .map_err(Error::channel); + + match res { + Ok(receipt) => Output::success(receipt).exit(), + Err(e) => Output::error(e).exit(), + } + } +} + +/// Relay channel upgrade cancel when counterparty has aborted the upgrade (ChannelUpgradeCancel) +/// +/// Build and send a `ChannelUpgradeCancel` message to cancel +/// the channel upgrade handshake given that the counterparty has aborted. +#[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] +pub struct TxChanUpgradeCancelCmd { + #[clap( + long = "dst-chain", + required = true, + value_name = "DST_CHAIN_ID", + help_heading = "REQUIRED", + help = "Identifier of the destination chain" + )] + dst_chain_id: ChainId, + + #[clap( + long = "src-chain", + required = true, + value_name = "SRC_CHAIN_ID", + help_heading = "REQUIRED", + help = "Identifier of the source chain" + )] + src_chain_id: ChainId, + + #[clap( + long = "dst-connection", + visible_alias = "dst-conn", + required = true, + value_name = "DST_CONNECTION_ID", + help_heading = "REQUIRED", + help = "Identifier of the destination connection" + )] + dst_conn_id: ConnectionId, + + #[clap( + long = "dst-port", + required = true, + value_name = "DST_PORT_ID", + help_heading = "REQUIRED", + help = "Identifier of the destination port" + )] + dst_port_id: PortId, + + #[clap( + long = "src-port", + required = true, + value_name = "SRC_PORT_ID", + help_heading = "REQUIRED", + help = "Identifier of the source port" + )] + src_port_id: PortId, + + #[clap( + long = "src-channel", + visible_alias = "src-chan", + required = true, + value_name = "SRC_CHANNEL_ID", + help_heading = "REQUIRED", + help = "Identifier of the source channel (required)" + )] + src_chan_id: ChannelId, + + #[clap( + long = "dst-channel", + visible_alias = "dst-chan", + required = true, + help_heading = "REQUIRED", + value_name = "DST_CHANNEL_ID", + help = "Identifier of the destination channel (optional)" + )] + dst_chan_id: Option, +} + +impl Runnable for TxChanUpgradeCancelCmd { + fn run(&self) { + let config = app_config(); + + let chains = match ChainHandlePair::spawn(&config, &self.src_chain_id, &self.dst_chain_id) { + Ok(chains) => chains, + Err(e) => Output::error(format!("{}", e)).exit(), + }; + + // Retrieve the connection + let dst_connection = match chains.dst.query_connection( + QueryConnectionRequest { + connection_id: self.dst_conn_id.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) { + Ok((connection, _)) => connection, + Err(e) => Output::error(format!("{}", e)).exit(), + }; + + // Fetch the Channel that will facilitate the communication between the channel ends + // being upgraded. This channel is assumed to already exist on the destination chain. + let channel = Channel { + connection_delay: Default::default(), + ordering: Ordering::default(), + a_side: ChannelSide::new( + chains.src, + ClientId::default(), + ConnectionId::default(), + self.src_port_id.clone(), + Some(self.src_chan_id.clone()), + None, + ), + b_side: ChannelSide::new( + chains.dst, + dst_connection.client_id().clone(), + self.dst_conn_id.clone(), + self.dst_port_id.clone(), + self.dst_chan_id.clone(), + None, + ), + }; + + info!("message ChanUpgradeCancel: {}", channel); + + let res: Result = channel + .build_chan_upgrade_cancel_and_send() + .map_err(Error::channel); + + match res { + Ok(receipt) => Output::success(receipt).exit(), + Err(e) => Output::error(e).exit(), + } + } +} + +/// Relay channel upgrade timeout when counterparty has not flushed packets before upgrade timeout (ChannelUpgradeTimeout) +/// +/// Build and send a `ChannelUpgradeTimeout` message to timeout +/// the channel upgrade handshake given that the counterparty has not flushed packets before upgrade timeout. +#[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] +pub struct TxChanUpgradeTimeoutCmd { + #[clap( + long = "dst-chain", + required = true, + value_name = "DST_CHAIN_ID", + help_heading = "REQUIRED", + help = "Identifier of the destination chain" + )] + dst_chain_id: ChainId, + + #[clap( + long = "src-chain", + required = true, + value_name = "SRC_CHAIN_ID", + help_heading = "REQUIRED", + help = "Identifier of the source chain" + )] + src_chain_id: ChainId, + + #[clap( + long = "dst-connection", + visible_alias = "dst-conn", + required = true, + value_name = "DST_CONNECTION_ID", + help_heading = "REQUIRED", + help = "Identifier of the destination connection" + )] + dst_conn_id: ConnectionId, + + #[clap( + long = "dst-port", + required = true, + value_name = "DST_PORT_ID", + help_heading = "REQUIRED", + help = "Identifier of the destination port" + )] + dst_port_id: PortId, + + #[clap( + long = "src-port", + required = true, + value_name = "SRC_PORT_ID", + help_heading = "REQUIRED", + help = "Identifier of the source port" + )] + src_port_id: PortId, + + #[clap( + long = "src-channel", + visible_alias = "src-chan", + required = true, + value_name = "SRC_CHANNEL_ID", + help_heading = "REQUIRED", + help = "Identifier of the source channel (required)" + )] + src_chan_id: ChannelId, + + #[clap( + long = "dst-channel", + visible_alias = "dst-chan", + required = true, + help_heading = "REQUIRED", + value_name = "DST_CHANNEL_ID", + help = "Identifier of the destination channel (optional)" + )] + dst_chan_id: Option, +} + +impl Runnable for TxChanUpgradeTimeoutCmd { + fn run(&self) { + let config = app_config(); + + let chains = match ChainHandlePair::spawn(&config, &self.src_chain_id, &self.dst_chain_id) { + Ok(chains) => chains, + Err(e) => Output::error(format!("{}", e)).exit(), + }; + + // Retrieve the connection + let dst_connection = match chains.dst.query_connection( + QueryConnectionRequest { + connection_id: self.dst_conn_id.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) { + Ok((connection, _)) => connection, + Err(e) => Output::error(format!("{}", e)).exit(), + }; + + // Fetch the Channel that will facilitate the communication between the channel ends + // being upgraded. This channel is assumed to already exist on the destination chain. + let channel = Channel { + connection_delay: Default::default(), + ordering: Ordering::default(), + a_side: ChannelSide::new( + chains.src, + ClientId::default(), + ConnectionId::default(), + self.src_port_id.clone(), + Some(self.src_chan_id.clone()), + None, + ), + b_side: ChannelSide::new( + chains.dst, + dst_connection.client_id().clone(), + self.dst_conn_id.clone(), + self.dst_port_id.clone(), + self.dst_chan_id.clone(), + None, + ), + }; + + info!("message ChanUpgradeTimeout: {}", channel); + + let res: Result = channel + .build_chan_upgrade_timeout_and_send() + .map_err(Error::channel); + + match res { + Ok(receipt) => Output::success(receipt).exit(), + Err(e) => Output::error(e).exit(), + } + } +} + +#[cfg(test)] +mod tests { + use abscissa_core::clap::Parser; + use std::str::FromStr; - use abscissa_core::clap::Parser; use ibc_relayer_types::core::{ ics04_channel::channel::Ordering, - ics24_host::identifier::{ - ChainId, - ChannelId, - ConnectionId, - PortId, - }, + ics24_host::identifier::{ChainId, ChannelId, ConnectionId, PortId}, }; - use super::{ - TxChanCloseConfirmCmd, - TxChanCloseInitCmd, - TxChanOpenAckCmd, - TxChanOpenConfirmCmd, - TxChanOpenInitCmd, - TxChanOpenTryCmd, + use crate::commands::tx::channel::{ + TxChanCloseConfirmCmd, TxChanCloseInitCmd, TxChanOpenAckCmd, TxChanOpenConfirmCmd, + TxChanOpenInitCmd, TxChanOpenTryCmd, }; #[test] diff --git a/crates/relayer-cli/src/commands/tx/client.rs b/crates/relayer-cli/src/commands/tx/client.rs index 5f129e2733..f96871b11a 100644 --- a/crates/relayer-cli/src/commands/tx/client.rs +++ b/crates/relayer-cli/src/commands/tx/client.rs @@ -1,45 +1,24 @@ use core::{ - fmt::{ - Display, - Error as FmtError, - Formatter, - }, + fmt::{Display, Error as FmtError, Formatter}, time::Duration, }; use std::thread; -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; +use abscissa_core::{clap::Parser, Command, Runnable}; use ibc_relayer::{ chain::{ handle::ChainHandle, requests::{ - IncludeProof, - PageRequest, - QueryClientStateRequest, - QueryClientStatesRequest, + IncludeProof, PageRequest, QueryClientStateRequest, QueryClientStatesRequest, QueryHeight, }, }, - config::{ - ChainConfig, - Config, - GenesisRestart, - }, + config::{ChainConfig, Config, GenesisRestart}, event::IbcEventWithHeight, - foreign_client::{ - CreateOptions, - ForeignClient, - }, + foreign_client::{CreateOptions, ForeignClient}, }; use ibc_relayer_types::{ - core::ics24_host::identifier::{ - ChainId, - ClientId, - }, + core::ics24_host::identifier::{ChainId, ClientId}, events::IbcEvent, Height, }; @@ -50,15 +29,8 @@ use tracing::debug; use crate::{ application::app_config, - cli_utils::{ - spawn_chain_runtime, - spawn_chain_runtime_generic, - ChainHandlePair, - }, - conclude::{ - exit_with_unrecoverable_error, - Output, - }, + cli_utils::{spawn_chain_runtime, spawn_chain_runtime_generic, ChainHandlePair}, + conclude::{exit_with_unrecoverable_error, Output}, error::Error, }; @@ -644,17 +616,11 @@ mod tests { use abscissa_core::clap::Parser; use humantime::Duration; - use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ClientId, - }; + use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ClientId}; use tendermint_light_client_verifier::types::TrustThreshold; use super::{ - parse_trust_threshold, - TxCreateClientCmd, - TxUpdateClientCmd, - TxUpgradeClientCmd, + parse_trust_threshold, TxCreateClientCmd, TxUpdateClientCmd, TxUpgradeClientCmd, TxUpgradeClientsCmd, }; diff --git a/crates/relayer-cli/src/commands/tx/connection.rs b/crates/relayer-cli/src/commands/tx/connection.rs index a264e22185..8480037fef 100644 --- a/crates/relayer-cli/src/commands/tx/connection.rs +++ b/crates/relayer-cli/src/commands/tx/connection.rs @@ -1,30 +1,15 @@ #![allow(clippy::redundant_closure_call)] -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use ibc_relayer::connection::{ - Connection, - ConnectionSide, -}; +use abscissa_core::clap::Parser; + +use ibc_relayer::connection::{Connection, ConnectionSide}; use ibc_relayer_types::{ - core::ics24_host::identifier::{ - ChainId, - ClientId, - ConnectionId, - }, + core::ics24_host::identifier::{ChainId, ClientId, ConnectionId}, events::IbcEvent, timestamp::ZERO_DURATION, }; -use crate::{ - cli_utils::ChainHandlePair, - conclude::Output, - error::Error, - prelude::*, -}; +use crate::{cli_utils::ChainHandlePair, conclude::Output, error::Error, prelude::*}; macro_rules! conn_open_cmd { ($dbg_string:literal, $func:ident, $self:expr, $conn:expr) => { @@ -361,18 +346,9 @@ mod tests { use std::str::FromStr; use abscissa_core::clap::Parser; - use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ClientId, - ConnectionId, - }; + use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ClientId, ConnectionId}; - use super::{ - TxConnAckCmd, - TxConnConfirmCmd, - TxConnInitCmd, - TxConnTryCmd, - }; + use super::{TxConnAckCmd, TxConnConfirmCmd, TxConnInitCmd, TxConnTryCmd}; #[test] fn test_conn_init() { diff --git a/crates/relayer-cli/src/commands/tx/packet.rs b/crates/relayer-cli/src/commands/tx/packet.rs index 302a609e1d..f2b437cfad 100644 --- a/crates/relayer-cli/src/commands/tx/packet.rs +++ b/crates/relayer-cli/src/commands/tx/packet.rs @@ -1,37 +1,18 @@ +use abscissa_core::clap::Parser; +use ibc_relayer_types::core::ics02_client::height::Height; use std::ops::RangeInclusive; -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use ibc_relayer::{ - chain::handle::ChainHandle, - link::{ - Link, - LinkParameters, - }, - util::seq_range::parse_seq_range, -}; -use ibc_relayer_types::{ - core::{ - ics02_client::height::Height, - ics04_channel::packet::Sequence, - ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }, - }, - events::IbcEvent, -}; - -use crate::{ - cli_utils::ChainHandlePair, - conclude::Output, - error::Error, - prelude::*, -}; +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::link::{Link, LinkParameters}; +use ibc_relayer::util::seq_range::parse_seq_range; +use ibc_relayer_types::core::ics04_channel::packet::Sequence; +use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; +use ibc_relayer_types::events::IbcEvent; + +use crate::cli_utils::ChainHandlePair; +use crate::conclude::Output; +use crate::error::Error; +use crate::prelude::*; #[derive(Clone, Command, Debug, Parser, PartialEq, Eq)] pub struct TxPacketRecvCmd { @@ -106,7 +87,11 @@ impl Runnable for TxPacketRecvCmd { src_channel_id: self.src_channel_id.clone(), max_memo_size: config.mode.packets.ics20_max_memo_size, max_receiver_size: config.mode.packets.ics20_max_receiver_size, + + // Packets are only excluded when clearing + exclude_src_sequences: vec![], }; + let link = match Link::new_from_opts(chains.src, chains.dst, opts, false, false) { Ok(link) => link, Err(e) => Output::error(e).exit(), @@ -203,7 +188,11 @@ impl Runnable for TxPacketAckCmd { src_channel_id: self.src_channel_id.clone(), max_memo_size: config.mode.packets.ics20_max_memo_size, max_receiver_size: config.mode.packets.ics20_max_receiver_size, + + // Packets are only excluded when clearing + exclude_src_sequences: vec![], }; + let link = match Link::new_from_opts(chains.src, chains.dst, opts, false, false) { Ok(link) => link, Err(e) => Output::error(e).exit(), @@ -232,16 +221,9 @@ mod tests { use std::str::FromStr; use abscissa_core::clap::Parser; - use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }; - - use super::{ - TxPacketAckCmd, - TxPacketRecvCmd, - }; + use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ChannelId, PortId}; + + use super::{TxPacketAckCmd, TxPacketRecvCmd}; #[test] fn test_packet_recv_required_only() { diff --git a/crates/relayer-cli/src/commands/tx/transfer.rs b/crates/relayer-cli/src/commands/tx/transfer.rs index 60d56a1f12..364f32f354 100644 --- a/crates/relayer-cli/src/commands/tx/transfer.rs +++ b/crates/relayer-cli/src/commands/tx/transfer.rs @@ -1,40 +1,22 @@ use core::time::Duration; -use abscissa_core::{ - clap::Parser, - config::Override, - Command, - FrameworkErrorKind, - Runnable, -}; +use abscissa_core::clap::Parser; +use abscissa_core::{config::Override, FrameworkErrorKind}; use eyre::eyre; use ibc_relayer::{ chain::handle::ChainHandle, config::Config, event::IbcEventWithHeight, - transfer::{ - build_and_send_transfer_messages, - TransferOptions, - }, + transfer::{build_and_send_transfer_messages, TransferOptions}, }; use ibc_relayer_types::{ applications::transfer::Amount, - core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }, + core::ics24_host::identifier::{ChainId, ChannelId, PortId}, }; use crate::{ - cli_utils::{ - check_can_send_on_channel, - ChainHandlePair, - }, - conclude::{ - exit_with_unrecoverable_error, - Output, - }, + cli_utils::{check_can_send_on_channel, ChainHandlePair}, + conclude::{exit_with_unrecoverable_error, Output}, error::Error, prelude::*, }; @@ -235,11 +217,7 @@ mod tests { use abscissa_core::clap::Parser; use ibc_relayer_types::{ applications::transfer::Amount, - core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }, + core::ics24_host::identifier::{ChainId, ChannelId, PortId}, }; use super::TxIcs20MsgTransferCmd; diff --git a/crates/relayer-cli/src/commands/tx/upgrade.rs b/crates/relayer-cli/src/commands/tx/upgrade.rs index 4249f98715..8b8f7ca135 100644 --- a/crates/relayer-cli/src/commands/tx/upgrade.rs +++ b/crates/relayer-cli/src/commands/tx/upgrade.rs @@ -1,26 +1,14 @@ use core::time::Duration; -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; -use ibc_relayer::upgrade_chain::{ - build_and_send_ibc_upgrade_proposal, - requires_legacy_upgrade_proposal, - UpgradePlanOptions, -}; -use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ClientId, -}; +use abscissa_core::clap::Parser; + +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}; use crate::{ cli_utils::spawn_chain_runtime, - conclude::{ - exit_with_unrecoverable_error, - Output, - }, + conclude::{exit_with_unrecoverable_error, Output}, error::Error, prelude::*, }; @@ -169,10 +157,7 @@ mod tests { use std::str::FromStr; use abscissa_core::clap::Parser; - use ibc_relayer_types::core::ics24_host::identifier::{ - ChainId, - ClientId, - }; + use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ClientId}; use super::TxIbcUpgradeChainCmd; diff --git a/crates/relayer-cli/src/commands/update.rs b/crates/relayer-cli/src/commands/update.rs index 8d3e7cf80a..29967578ed 100644 --- a/crates/relayer-cli/src/commands/update.rs +++ b/crates/relayer-cli/src/commands/update.rs @@ -1,10 +1,6 @@ //! `update` subcommand -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; +use abscissa_core::{clap::Parser, Command, Runnable}; use crate::commands::tx::client::TxUpdateClientCmd; diff --git a/crates/relayer-cli/src/commands/upgrade.rs b/crates/relayer-cli/src/commands/upgrade.rs index 66c75bdf95..e0fa869d53 100644 --- a/crates/relayer-cli/src/commands/upgrade.rs +++ b/crates/relayer-cli/src/commands/upgrade.rs @@ -1,15 +1,8 @@ //! `upgrade` subcommand -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; +use abscissa_core::{clap::Parser, Command, Runnable}; -use crate::commands::tx::client::{ - TxUpgradeClientCmd, - TxUpgradeClientsCmd, -}; +use crate::commands::tx::client::{TxUpgradeClientCmd, TxUpgradeClientsCmd}; #[derive(Command, Debug, Parser, Runnable)] pub enum UpgradeCmds { diff --git a/crates/relayer-cli/src/commands/version.rs b/crates/relayer-cli/src/commands/version.rs index d3d209e92f..270b2b0a26 100644 --- a/crates/relayer-cli/src/commands/version.rs +++ b/crates/relayer-cli/src/commands/version.rs @@ -1,10 +1,6 @@ //! `version` subcommand -use abscissa_core::{ - clap::Parser, - Command, - Runnable, -}; +use abscissa_core::{clap::Parser, Command, Runnable}; use super::CliCmd; diff --git a/crates/relayer-cli/src/components.rs b/crates/relayer-cli/src/components.rs index 205609be8c..91c76b216e 100644 --- a/crates/relayer-cli/src/components.rs +++ b/crates/relayer-cli/src/components.rs @@ -1,23 +1,11 @@ //! Various components for internal use by the Abscissa subsystem. -use abscissa_core::{ - Component, - FrameworkError, - FrameworkErrorKind, -}; +use abscissa_core::{Component, FrameworkError, FrameworkErrorKind}; use ibc_relayer::{ - config::{ - Error, - GlobalConfig, - LogLevel, - }, + config::{Error, GlobalConfig, LogLevel}, util::debug_section::DebugSection, }; -use tracing_subscriber::{ - filter::EnvFilter, - util::SubscriberInitExt, - FmtSubscriber, -}; +use tracing_subscriber::{filter::EnvFilter, util::SubscriberInitExt, FmtSubscriber}; use crate::tracing_handle::ReloadHandle; diff --git a/crates/relayer-cli/src/conclude.rs b/crates/relayer-cli/src/conclude.rs index 4ea674a1a8..8af08afa55 100644 --- a/crates/relayer-cli/src/conclude.rs +++ b/crates/relayer-cli/src/conclude.rs @@ -17,9 +17,9 @@ //! ``` //! //! - Exit from a query/tx with an error of type `anomaly`: -//! In the case where the error is a complex type such as anomaly (including backtraces), it is -//! better to simplify the output and only write out the chain of error sources, which we can -//! achieve with `format!("{}", e)`. The complete solution is as follows: +//! In the case where the error is a complex type such as anomaly (including backtraces), it is +//! better to simplify the output and only write out the chain of error sources, which we can +//! achieve with `format!("{}", e)`. The complete solution is as follows: //! //! ```ignore //! let e: Error = Kind::Query.into(); diff --git a/crates/relayer-cli/src/entry.rs b/crates/relayer-cli/src/entry.rs index 55e825c3f9..a550bdb6d7 100644 --- a/crates/relayer-cli/src/entry.rs +++ b/crates/relayer-cli/src/entry.rs @@ -1,27 +1,10 @@ -#![allow(unused_qualifications)] // Fix for warning in `ValueEnum` generated code - //! Definition of the entrypoint for the Hermes CLI. -use std::{ - path::PathBuf, - process, -}; +use std::{path::PathBuf, process}; -use abscissa_core::{ - clap::Parser, - Command, - Configurable, - FrameworkError, - Runnable, -}; -use clap::{ - IntoApp, - ValueEnum, -}; -use ibc_relayer::{ - config::Config, - util::debug_section::DebugSection, -}; +use abscissa_core::{clap::Parser, Command, Configurable, FrameworkError, Runnable}; +use clap::{IntoApp, ValueEnum}; +use ibc_relayer::{config::Config, util::debug_section::DebugSection}; use crate::commands::CliCmd; diff --git a/crates/relayer-cli/src/error.rs b/crates/relayer-cli/src/error.rs index e891e05942..b989ccbb7b 100644 --- a/crates/relayer-cli/src/error.rs +++ b/crates/relayer-cli/src/error.rs @@ -2,28 +2,16 @@ use std::io::Error as IoError; -use flex_error::{ - define_error, - DisplayError, -}; +use flex_error::{define_error, DisplayError}; use ibc_relayer::{ - channel::ChannelError, - connection::ConnectionError, - error::Error as RelayerError, - foreign_client::ForeignClientError, - keyring::errors::Error as KeyRingError, - link::error::LinkError, - spawn::SpawnError, - supervisor::Error as SupervisorError, - transfer::TransferError, - upgrade_chain::UpgradeChainError, + channel::ChannelError, connection::ConnectionError, error::Error as RelayerError, + foreign_client::ForeignClientError, keyring::errors::Error as KeyRingError, + link::error::LinkError, spawn::SpawnError, supervisor::Error as SupervisorError, + transfer::TransferError, upgrade_chain::UpgradeChainError, }; use ibc_relayer_types::{ applications::ics29_fee::error::Error as FeeError, - core::{ - ics04_channel::channel::IdentifiedChannelEnd, - ics24_host::identifier::ChainId, - }, + core::{ics04_channel::channel::IdentifiedChannelEnd, ics24_host::identifier::ChainId}, signer::SignerError, }; use tendermint::Error as TendermintError; diff --git a/crates/relayer-cli/src/lib.rs b/crates/relayer-cli/src/lib.rs index ff28651be7..0b817798ff 100644 --- a/crates/relayer-cli/src/lib.rs +++ b/crates/relayer-cli/src/lib.rs @@ -13,13 +13,8 @@ // Tip: Deny warnings with `RUSTFLAGS="-D warnings"` environment variable in CI #![forbid(unsafe_code)] -#![deny( - rust_2018_idioms, - trivial_casts, - unused_lifetimes, - unused_qualifications -)] -#![allow(deprecated)] +#![deny(rust_2018_idioms, trivial_casts, unused_lifetimes)] +#![allow(deprecated, unknown_lints, non_local_definitions)] extern crate alloc; diff --git a/crates/relayer-cli/src/prelude.rs b/crates/relayer-cli/src/prelude.rs index 7c2a22d333..8108fee094 100644 --- a/crates/relayer-cli/src/prelude.rs +++ b/crates/relayer-cli/src/prelude.rs @@ -6,9 +6,7 @@ /// Abscissa core prelude pub use abscissa_core::prelude::*; +pub use abscissa_core::Command; /// Application state accessors -pub use crate::application::{ - app_config, - app_reader, -}; +pub use crate::application::{app_config, app_reader}; diff --git a/crates/relayer-cli/src/tracing_handle.rs b/crates/relayer-cli/src/tracing_handle.rs index d77205f271..6f7ca2c8e5 100644 --- a/crates/relayer-cli/src/tracing_handle.rs +++ b/crates/relayer-cli/src/tracing_handle.rs @@ -2,21 +2,10 @@ use std::io; use ibc_relayer::config::TracingServerConfig; use tokio::{ - io::{ - AsyncBufReadExt, - AsyncReadExt, - AsyncWriteExt, - BufReader, - }, - net::{ - TcpListener, - TcpStream, - }, -}; -use tracing_subscriber::{ - filter, - reload::Handle, + io::{AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader}, + net::{TcpListener, TcpStream}, }; +use tracing_subscriber::{filter, reload::Handle}; pub type ReloadHandle = Handle; diff --git a/crates/relayer-cli/tests/acceptance.rs b/crates/relayer-cli/tests/acceptance.rs index c50c4b0866..6b568ee1ef 100644 --- a/crates/relayer-cli/tests/acceptance.rs +++ b/crates/relayer-cli/tests/acceptance.rs @@ -10,13 +10,7 @@ // Tip: Deny warnings with `RUSTFLAGS="-D warnings"` environment variable in CI #![forbid(unsafe_code)] -#![warn( - missing_docs, - rust_2018_idioms, - trivial_casts, - unused_lifetimes, - unused_qualifications -)] +#![warn(missing_docs, rust_2018_idioms, trivial_casts, unused_lifetimes)] use abscissa_core::testing::prelude::*; use once_cell::sync::Lazy; @@ -30,7 +24,6 @@ use once_cell::sync::Lazy; pub static RUNNER: Lazy = Lazy::new(CmdRunner::default); /// Use `Config::default()` value if no config or args -#[cfg(not(tarpaulin))] #[test] fn start_no_args() { let mut runner = RUNNER.clone(); @@ -46,7 +39,6 @@ fn start_no_args() { cmd.wait().unwrap().expect_success(); } -#[cfg(not(tarpaulin))] #[test] fn example_configuration_is_valid() { let mut runner = RUNNER.clone(); diff --git a/crates/relayer-rest/Cargo.toml b/crates/relayer-rest/Cargo.toml index a5e7066646..7b406f4443 100644 --- a/crates/relayer-rest/Cargo.toml +++ b/crates/relayer-rest/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ibc-relayer-rest" -version = "0.26.4" +version = "0.29.3" authors = ["Informal Systems "] edition = "2021" license = "Apache-2.0" @@ -8,21 +8,21 @@ readme = "README.md" keywords = ["ibc", "rest", "api", "cosmos", "tendermint"] homepage = "https://hermes.informal.systems/" repository = "https://github.com/informalsystems/hermes" -rust-version = "1.71" +rust-version = "1.76.0" description = """ Rust implementation of a RESTful API server for Hermes """ [dependencies] -ibc-relayer-types = { version = "0.26.4", path = "../relayer-types" } -ibc-relayer = { version = "0.26.4", path = "../relayer" } +ibc-relayer-types = { workspace = true } +ibc-relayer = { workspace = true } -crossbeam-channel = "0.5" -serde = "1.0" -tracing = "0.1" -axum = "0.6" -tokio = "1.26" +axum = { workspace = true } +crossbeam-channel = { workspace = true } +serde = { workspace = true } +tokio = { workspace = true } +tracing = { workspace = true } [dev-dependencies] -reqwest = { version = "0.11.16", features = ["json"], default-features = false } -toml = "0.8.8" +reqwest = { workspace = true, features = ["json"] } +toml = { workspace = true } diff --git a/crates/relayer-rest/README.md b/crates/relayer-rest/README.md index ee66cb6870..db2dd9ca9f 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.71+][rustc-version] +![Rust 1.76.0+][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.71+-blue.svg +[rustc-version]: https://img.shields.io/badge/rustc-1.76.0+-blue.svg diff --git a/crates/relayer-rest/src/handle.rs b/crates/relayer-rest/src/handle.rs index 4e70afa0e9..0f9f9f1f74 100644 --- a/crates/relayer-rest/src/handle.rs +++ b/crates/relayer-rest/src/handle.rs @@ -4,12 +4,7 @@ use crossbeam_channel as channel; use ibc_relayer::{ config::ChainConfig, rest::{ - request::{ - reply_channel, - ReplySender, - Request, - VersionInfo, - }, + request::{reply_channel, ReplySender, Request, VersionInfo}, RestApiError, }, supervisor::dump_state::SupervisorState, diff --git a/crates/relayer-rest/src/server.rs b/crates/relayer-rest/src/server.rs index c21f5b321c..53b1bfbbaa 100644 --- a/crates/relayer-rest/src/server.rs +++ b/crates/relayer-rest/src/server.rs @@ -1,44 +1,22 @@ use std::{ error::Error, - net::{ - SocketAddr, - ToSocketAddrs, - }, + net::{SocketAddr, ToSocketAddrs}, }; use axum::{ - extract::{ - Path, - Query, - }, + extract::{Path, Query}, response::IntoResponse, - routing::{ - get, - post, - }, - Extension, - Json, - Router, - Server, + routing::{get, post}, + Extension, Json, Router, Server, }; use crossbeam_channel as channel; -use ibc_relayer::rest::{ - request::Request, - RestApiError, -}; +use ibc_relayer::rest::{request::Request, RestApiError}; use ibc_relayer_types::core::ics24_host::identifier::ChainId; -use serde::{ - Deserialize, - Serialize, -}; +use serde::{Deserialize, Serialize}; use tokio::task::JoinHandle; use crate::handle::{ - all_chain_ids, - assemble_version_info, - chain_config, - supervisor_state, - trigger_clear_packets, + all_chain_ids, assemble_version_info, chain_config, supervisor_state, trigger_clear_packets, }; pub type BoxError = Box; diff --git a/crates/relayer-rest/tests/mock.rs b/crates/relayer-rest/tests/mock.rs index 38ef39e7fe..ed5640ddd7 100644 --- a/crates/relayer-rest/tests/mock.rs +++ b/crates/relayer-rest/tests/mock.rs @@ -1,24 +1,13 @@ -use std::{ - fmt::Debug, - str::FromStr, - time::Duration, -}; +use std::{fmt::Debug, str::FromStr, time::Duration}; use ibc_relayer::{ config::ChainConfig, - rest::request::{ - Request, - VersionInfo, - }, + rest::request::{Request, VersionInfo}, supervisor::dump_state::SupervisorState, }; use ibc_relayer_rest::spawn; use ibc_relayer_types::core::ics24_host::identifier::ChainId; -use serde::{ - de::DeserializeOwned, - Deserialize, - Serialize, -}; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; enum TestResult { Success, @@ -50,7 +39,7 @@ where Err(e) => panic!("got an error: {e}"), }); - tokio::time::sleep(Duration::from_millis(500)).await; + tokio::time::sleep(Duration::from_millis(200)).await; let response = reqwest::get(&format!("http://127.0.0.1:{port}{path}")) .await @@ -73,7 +62,7 @@ async fn version() { let rest_api_version = VersionInfo { name: "ibc-relayer-rest".to_string(), - version: "0.26.4".to_string(), + version: "0.29.3".to_string(), }; let result: JsonResult<_, ()> = JsonResult::Success(vec![version.clone(), rest_api_version]); diff --git a/crates/relayer-types/Cargo.toml b/crates/relayer-types/Cargo.toml index 27bdcba4c1..b9ae3c2f9b 100644 --- a/crates/relayer-types/Cargo.toml +++ b/crates/relayer-types/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "ibc-relayer-types" -version = "0.26.4" +version = "0.29.3" 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.71" +rust-version = "1.76.0" description = """ Implementation of the Inter-Blockchain Communication Protocol (IBC). This crate comprises the main data structures and on-chain logic. @@ -18,48 +18,34 @@ all-features = true [features] clock = [] -# This feature grants access to development-time mocking libraries, such as `MockContext` or `MockHeader`. -# Depends on the `testgen` suite for generating Tendermint light blocks. -mocks = ["tendermint-testgen", "clock"] [dependencies] -# Proto definitions for all IBC-related interfaces, e.g., connections or channels. -ibc-proto = { version = "0.41.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" } -prost = { version = "0.12" } -bytes = { version = "1.4.0" } -subtle-encoding = { version = "0.5" } -flex-error = { version = "0.4.4" } -derive_more = { version = "0.99.17", default-features = false, features = ["from", "into", "display"] } -uint = { version = "0.9" } -itertools = { version = "0.10.3" } -primitive-types = { version = "0.12.1", default-features = false, features = ["serde_no_std"] } -num-rational = "0.4.1" -regex = "1" - -[dependencies.tendermint] -version = "0.34.0" -features = ["clock"] - -[dependencies.tendermint-proto] -version = "0.34.0" - -[dependencies.tendermint-light-client-verifier] -version = "0.34.0" -features = ["rust-crypto"] - -[dependencies.tendermint-testgen] -version = "0.34.0" -optional = true +bytes = { workspace = true } +derive_more = { workspace = true, features = ["from", "into", "display"] } +flex-error = { workspace = true } +ibc-proto = { workspace = true, features = ["serde"] } +ics23 = { workspace = true, features = ["std", "host-functions"] } +itertools = { workspace = true } +num-rational = { workspace = true } +primitive-types = { workspace = true, features = ["serde_no_std"] } +prost = { workspace = true } +regex = { workspace = true } +serde = { workspace = true } +serde_derive = { workspace = true } +serde_json = { workspace = true } +subtle-encoding = { workspace = true } +tendermint-light-client-verifier = { workspace = true, features = ["rust-crypto"] } +tendermint-proto = { workspace = true } +tendermint-testgen = { workspace = true, optional = true } +tendermint = { workspace = true, features = ["clock"] } +time = { workspace = true } +uint = { workspace = true } +tracing = { workspace = true } [dev-dependencies] -env_logger = "0.10.0" -tracing = { version = "0.1.36", default-features = false } -tracing-subscriber = { version = "0.3.14", features = ["fmt", "env-filter", "json"] } -test-log = { version = "0.2.14", features = ["trace"] } -tendermint-rpc = { version = "0.34.0", features = ["http-client", "websocket-client"] } -tendermint-testgen = { version = "0.34.0" } # Needed for generating (synthetic) light blocks. +env_logger = { workspace = true } +tendermint-rpc = { workspace = true, features = ["http-client", "websocket-client"] } +tendermint-testgen = { workspace = true } # Needed for generating (synthetic) light blocks. +test-log = { workspace = true, features = ["trace"] } +tracing = { workspace = true } +tracing-subscriber = { workspace = true, features = ["fmt", "env-filter", "json"] } 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 af7cee9daf..4c08c6b617 100644 --- a/crates/relayer-types/src/applications/ics27_ica/cosmos_tx.rs +++ b/crates/relayer-types/src/applications/ics27_ica/cosmos_tx.rs @@ -1,17 +1,11 @@ use ibc_proto::{ - google::protobuf::Any, - ibc::applications::interchain_accounts::v1::CosmosTx as RawCosmosTx, + google::protobuf::Any, ibc::applications::interchain_accounts::v1::CosmosTx as RawCosmosTx, Protobuf, }; -use serde_derive::{ - Deserialize, - Serialize, -}; +use serde_derive::{Deserialize, Serialize}; use crate::{ - applications::ics27_ica::error::Error, - core::ics24_host::error::ValidationError, - tx_msg::Msg, + applications::ics27_ica::error::Error, core::ics24_host::error::ValidationError, tx_msg::Msg, }; pub const TYPE_URL: &str = "/ibc.applications.interchain_accounts.v1.CosmosTx"; diff --git a/crates/relayer-types/src/applications/ics27_ica/error.rs b/crates/relayer-types/src/applications/ics27_ica/error.rs index f652b99bb2..263f090fe1 100644 --- a/crates/relayer-types/src/applications/ics27_ica/error.rs +++ b/crates/relayer-types/src/applications/ics27_ica/error.rs @@ -1,20 +1,27 @@ -use flex_error::define_error; +use crate::core::ics04_channel::error as channel_error; +use crate::core::ics24_host::error::ValidationError; +use crate::signer::SignerError; -use crate::{ - core::ics24_host::error::ValidationError, - signer::SignerError, -}; +use flex_error::define_error; define_error! { #[derive(Debug, PartialEq, Eq)] Error { + Ics04Channel + [ channel_error::Error ] + | _ | { "ICS 04 channel error" }, + Owner [ SignerError ] - | _ | { "failed to parse owner" }, + | _ | { "failed to parse owner" }, InvalidConnectionIdentifier [ ValidationError ] - | _ | { "connection identifier error" }, + | _ | { "connection identifier error" }, + + InvalidOrdering + { ordering: i32 } + | e | { format_args!("invalid ordering: {}", e.ordering) }, InvalidPacketData | _ | { "packet data is None" }, diff --git a/crates/relayer-types/src/applications/ics27_ica/mod.rs b/crates/relayer-types/src/applications/ics27_ica/mod.rs index c42612c711..74c81280b4 100644 --- a/crates/relayer-types/src/applications/ics27_ica/mod.rs +++ b/crates/relayer-types/src/applications/ics27_ica/mod.rs @@ -2,3 +2,6 @@ pub mod cosmos_tx; pub mod error; pub mod msgs; pub mod packet_data; + +/// ICS27 application current version. +pub const VERSION: &str = "ics27-1"; 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 1301de19cd..e39ee2f99c 100644 --- a/crates/relayer-types/src/applications/ics27_ica/msgs/register.rs +++ b/crates/relayer-types/src/applications/ics27_ica/msgs/register.rs @@ -2,23 +2,15 @@ use ibc_proto::{ ibc::applications::interchain_accounts::controller::v1::MsgRegisterInterchainAccount as RawMsgRegisterInterchainAccount, Protobuf, }; -use serde::{ - Deserialize, - Serialize, -}; +use serde::{Deserialize, Serialize}; -use crate::{ - applications::ics27_ica::error::Error, - core::{ - ics04_channel::version::Version, - ics24_host::{ - error::ValidationError, - identifier::ConnectionId, - }, - }, - signer::Signer, - tx_msg::Msg, -}; +use crate::applications::ics27_ica::error::Error; +use crate::core::ics04_channel::channel::Ordering; +use crate::core::ics04_channel::version::Version; +use crate::core::ics24_host::error::ValidationError; +use crate::core::ics24_host::identifier::ConnectionId; +use crate::signer::Signer; +use crate::tx_msg::Msg; pub const TYPE_URL: &str = "/ibc.applications.interchain_accounts.controller.v1.MsgRegisterInterchainAccount"; @@ -28,6 +20,7 @@ pub struct MsgRegisterInterchainAccount { pub owner: Signer, pub connection_id: ConnectionId, pub version: Version, + pub ordering: Ordering, } impl Msg for MsgRegisterInterchainAccount { @@ -56,6 +49,8 @@ impl TryFrom for MsgRegisterInterchainAccount { .parse() .map_err(Error::invalid_connection_identifier)?, version: value.version.into(), + ordering: Ordering::from_i32(value.ordering) + .map_err(|_| Error::invalid_ordering(value.ordering))?, }) } } @@ -66,6 +61,65 @@ impl From for RawMsgRegisterInterchainAccount { owner: value.owner.to_string(), connection_id: value.connection_id.to_string(), version: value.version.to_string(), + ordering: value.ordering as i32, + } + } +} + +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, prost::Message)] +pub struct LegacyRawMsgRegisterInterchainAccount { + #[prost(string, tag = "1")] + pub owner: String, + #[prost(string, tag = "2")] + pub connection_id: String, + #[prost(string, tag = "3")] + pub version: String, +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct LegacyMsgRegisterInterchainAccount { + pub owner: Signer, + pub connection_id: ConnectionId, + pub version: Version, +} + +impl Msg for LegacyMsgRegisterInterchainAccount { + type ValidationError = ValidationError; + type Raw = LegacyRawMsgRegisterInterchainAccount; + + fn route(&self) -> String { + crate::keys::ROUTER_KEY.to_string() + } + + fn type_url(&self) -> String { + TYPE_URL.to_string() + } +} + +impl Protobuf for LegacyMsgRegisterInterchainAccount {} + +impl TryFrom for LegacyMsgRegisterInterchainAccount { + type Error = Error; + + fn try_from(value: LegacyRawMsgRegisterInterchainAccount) -> Result { + Ok(LegacyMsgRegisterInterchainAccount { + owner: value.owner.parse().map_err(Error::owner)?, + connection_id: value + .connection_id + .parse() + .map_err(Error::invalid_connection_identifier)?, + version: value.version.into(), + }) + } +} + +impl From for LegacyRawMsgRegisterInterchainAccount { + fn from(value: LegacyMsgRegisterInterchainAccount) -> Self { + LegacyRawMsgRegisterInterchainAccount { + owner: value.owner.to_string(), + connection_id: value.connection_id.to_string(), + version: value.version.to_string(), } } } 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 7fb8e2e218..939ab6072a 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,21 +1,11 @@ use ibc_proto::{ - ibc::applications::interchain_accounts::controller::v1::MsgSendTx as RawMsgSendTx, - Protobuf, -}; -use serde_derive::{ - Deserialize, - Serialize, + ibc::applications::interchain_accounts::controller::v1::MsgSendTx as RawMsgSendTx, Protobuf, }; +use serde_derive::{Deserialize, Serialize}; use crate::{ - applications::ics27_ica::{ - error::Error, - packet_data::InterchainAccountPacketData, - }, - core::ics24_host::{ - error::ValidationError, - identifier::ConnectionId, - }, + applications::ics27_ica::{error::Error, packet_data::InterchainAccountPacketData}, + core::ics24_host::{error::ValidationError, identifier::ConnectionId}, signer::Signer, timestamp::Timestamp, tx_msg::Msg, diff --git a/crates/relayer-types/src/applications/ics27_ica/packet_data.rs b/crates/relayer-types/src/applications/ics27_ica/packet_data.rs index a7fa7c585f..fc5e9b260d 100644 --- a/crates/relayer-types/src/applications/ics27_ica/packet_data.rs +++ b/crates/relayer-types/src/applications/ics27_ica/packet_data.rs @@ -2,10 +2,7 @@ use ibc_proto::ibc::{ applications::interchain_accounts::v1::InterchainAccountPacketData as RawInterchainAccountPacketData, apps::interchain_accounts::v1::Type, }; -use serde_derive::{ - Deserialize, - Serialize, -}; +use serde_derive::{Deserialize, Serialize}; use crate::applications::ics27_ica::error::Error; 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 index 405ffe9755..2f058cc01b 100644 --- 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 @@ -7,11 +7,7 @@ use ibc_proto::{ use tendermint::evidence::DuplicateVoteEvidence; use super::error::Error; -use crate::{ - clients::ics07_tendermint::header::Header, - signer::Signer, - tx_msg::Msg, -}; +use crate::{clients::ics07_tendermint::header::Header, signer::Signer, tx_msg::Msg}; pub const ICS_DOUBLE_VOTING_TYPE_URL: &str = "/interchain_security.ccv.provider.v1.MsgSubmitConsumerDoubleVoting"; 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 index 0ce25b9147..a46bfc26ce 100644 --- a/crates/relayer-types/src/applications/ics28_ccv/msgs/ccv_misbehaviour.rs +++ b/crates/relayer-types/src/applications/ics28_ccv/msgs/ccv_misbehaviour.rs @@ -4,17 +4,10 @@ use ibc_proto::{ interchain_security::ccv::provider::v1::MsgSubmitConsumerMisbehaviour as RawIcsMisbehaviour, Protobuf, }; -use serde::{ - Deserialize, - Serialize, -}; +use serde::{Deserialize, Serialize}; use super::error::Error; -use crate::{ - clients::ics07_tendermint::misbehaviour::Misbehaviour, - signer::Signer, - tx_msg::Msg, -}; +use crate::{clients::ics07_tendermint::misbehaviour::Misbehaviour, signer::Signer, tx_msg::Msg}; pub const ICS_MISBEHAVIOR_TYPE_URL: &str = "/interchain_security.ccv.provider.v1.MsgSubmitConsumerMisbehaviour"; diff --git a/crates/relayer-types/src/applications/ics29_fee/error.rs b/crates/relayer-types/src/applications/ics29_fee/error.rs index 27265db13f..8bbcce0c60 100644 --- a/crates/relayer-types/src/applications/ics29_fee/error.rs +++ b/crates/relayer-types/src/applications/ics29_fee/error.rs @@ -1,15 +1,9 @@ -use flex_error::{ - define_error, - TraceError, -}; +use flex_error::{define_error, TraceError}; use prost::EncodeError; use crate::{ applications::transfer::error::Error as TransferError, - core::{ - ics04_channel::error::Error as ChannelError, - ics24_host::error::ValidationError, - }, + core::{ics04_channel::error::Error as ChannelError, ics24_host::error::ValidationError}, signer::SignerError, }; @@ -44,6 +38,10 @@ define_error! { EventAttributeNotFound { key: String } - | e | { format_args!("IBC event attribute not found for key: {}", e.key) }, + | e | { format_args!("IBC event attribute not found for key `{}`", e.key) }, + + EventAttributeInvalidUtf8 + { key: String } + | e | { format_args!("IBC event attribute value for key `{}` is not a valid UTF-8 string", e.key) }, } } diff --git a/crates/relayer-types/src/applications/ics29_fee/events.rs b/crates/relayer-types/src/applications/ics29_fee/events.rs index 87a2f78a78..ba3e2fd4ea 100644 --- a/crates/relayer-types/src/applications/ics29_fee/events.rs +++ b/crates/relayer-types/src/applications/ics29_fee/events.rs @@ -1,13 +1,7 @@ -use std::{ - fmt::Display, - str::FromStr, -}; +use std::{fmt::Display, str::FromStr}; use itertools::Itertools; -use serde_derive::{ - Deserialize, - Serialize, -}; +use serde_derive::{Deserialize, Serialize}; use tendermint::abci; use super::error::Error; @@ -15,10 +9,7 @@ use crate::{ applications::transfer::coin::RawCoin, core::{ ics04_channel::packet::Sequence, - ics24_host::identifier::{ - ChannelId, - PortId, - }, + ics24_host::identifier::{ChannelId, PortId}, }, events::IbcEventType, signer::Signer, @@ -38,12 +29,17 @@ fn find_value<'a>(key: &str, entries: &'a [abci::EventAttribute]) -> Result<&'a entries .iter() .find_map(|entry| { - if entry.key == key { - Some(entry.value.as_str()) + if entry.key_bytes() == key.as_bytes() { + Some( + entry + .value_str() + .map_err(|_| Error::event_attribute_invalid_utf8(key.to_owned())), + ) } else { None } }) + .transpose()? .ok_or_else(|| Error::event_attribute_not_found(key.to_owned())) } diff --git a/crates/relayer-types/src/applications/ics29_fee/msgs/pay_packet.rs b/crates/relayer-types/src/applications/ics29_fee/msgs/pay_packet.rs index b4ac413cf4..8fcda126a0 100644 --- a/crates/relayer-types/src/applications/ics29_fee/msgs/pay_packet.rs +++ b/crates/relayer-types/src/applications/ics29_fee/msgs/pay_packet.rs @@ -1,20 +1,11 @@ use ibc_proto::{ google::protobuf::Any, - ibc::applications::fee::v1::{ - Fee as ProtoFee, - MsgPayPacketFee, - }, + ibc::applications::fee::v1::{Fee as ProtoFee, MsgPayPacketFee}, }; use crate::{ - applications::{ - ics29_fee::error::Error, - transfer::coin::RawCoin, - }, - core::ics24_host::identifier::{ - ChannelId, - PortId, - }, + applications::{ics29_fee::error::Error, transfer::coin::RawCoin}, + core::ics24_host::identifier::{ChannelId, PortId}, signer::Signer, tx_msg::encode_message, }; diff --git a/crates/relayer-types/src/applications/ics29_fee/msgs/pay_packet_async.rs b/crates/relayer-types/src/applications/ics29_fee/msgs/pay_packet_async.rs index 14090636f7..4382321734 100644 --- a/crates/relayer-types/src/applications/ics29_fee/msgs/pay_packet_async.rs +++ b/crates/relayer-types/src/applications/ics29_fee/msgs/pay_packet_async.rs @@ -2,25 +2,17 @@ use ibc_proto::{ google::protobuf::Any, ibc::{ applications::fee::v1::{ - Fee as ProtoFee, - MsgPayPacketFeeAsync, - PacketFee as ProtoPacketFee, + Fee as ProtoFee, MsgPayPacketFeeAsync, PacketFee as ProtoPacketFee, }, core::channel::v1::PacketId as ProtoPacketId, }, }; use crate::{ - applications::{ - ics29_fee::error::Error, - transfer::coin::RawCoin, - }, + applications::{ics29_fee::error::Error, transfer::coin::RawCoin}, core::{ ics04_channel::packet::Sequence, - ics24_host::identifier::{ - ChannelId, - PortId, - }, + ics24_host::identifier::{ChannelId, PortId}, }, signer::Signer, tx_msg::encode_message, diff --git a/crates/relayer-types/src/applications/ics29_fee/msgs/register_payee.rs b/crates/relayer-types/src/applications/ics29_fee/msgs/register_payee.rs index c6464f9db7..2c70d036b9 100644 --- a/crates/relayer-types/src/applications/ics29_fee/msgs/register_payee.rs +++ b/crates/relayer-types/src/applications/ics29_fee/msgs/register_payee.rs @@ -1,17 +1,11 @@ use ibc_proto::{ google::protobuf::Any, - ibc::applications::fee::v1::{ - MsgRegisterCounterpartyPayee, - MsgRegisterPayee, - }, + ibc::applications::fee::v1::{MsgRegisterCounterpartyPayee, MsgRegisterPayee}, }; use crate::{ applications::ics29_fee::error::Error, - core::ics24_host::identifier::{ - ChannelId, - PortId, - }, + core::ics24_host::identifier::{ChannelId, PortId}, signer::Signer, tx_msg::encode_message, }; diff --git a/crates/relayer-types/src/applications/ics29_fee/packet_fee.rs b/crates/relayer-types/src/applications/ics29_fee/packet_fee.rs index 411d13a94f..d27ede7931 100644 --- a/crates/relayer-types/src/applications/ics29_fee/packet_fee.rs +++ b/crates/relayer-types/src/applications/ics29_fee/packet_fee.rs @@ -3,18 +3,14 @@ use std::str::FromStr; use ibc_proto::{ cosmos::base::v1beta1::Coin as ProtoCoin, ibc::applications::fee::v1::{ - Fee as ProtoFee, - IdentifiedPacketFees as ProtoIdentifiedPacketFees, + Fee as ProtoFee, IdentifiedPacketFees as ProtoIdentifiedPacketFees, PacketFee as ProtoPacketFee, }, }; use super::error::Error; use crate::{ - applications::transfer::{ - amount::Amount, - coin::RawCoin, - }, + applications::transfer::{amount::Amount, coin::RawCoin}, core::ics04_channel::packet_id::PacketId, signer::Signer, }; diff --git a/crates/relayer-types/src/applications/ics31_icq/events.rs b/crates/relayer-types/src/applications/ics31_icq/events.rs index b02b9fb272..23f78a962c 100644 --- a/crates/relayer-types/src/applications/ics31_icq/events.rs +++ b/crates/relayer-types/src/applications/ics31_icq/events.rs @@ -1,27 +1,15 @@ -use std::{ - collections::BTreeMap, - str::FromStr, -}; +use std::str::FromStr; -use serde::{ - Deserialize, - Serialize, -}; -use tendermint::{ - abci, - block::Height, -}; +use serde::{Deserialize, Serialize}; +use tendermint::{abci, block::Height}; use super::error::Error; use crate::{ - core::ics24_host::identifier::{ - ChainId, - ConnectionId, - }, + core::ics24_host::identifier::{ChainId, ConnectionId}, events::IbcEvent, }; -const EVENT_TYPE_PREFIX: &str = "query_request"; +pub const EVENT_TYPE_PREFIX: &str = "query_request"; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] pub struct CrossChainQueryPacket { @@ -35,25 +23,32 @@ pub struct CrossChainQueryPacket { pub request: String, } +impl From for IbcEvent { + fn from(packet: CrossChainQueryPacket) -> Self { + IbcEvent::CrossChainQueryPacket(packet) + } +} + fn find_value<'a>(key: &str, entries: &'a [abci::EventAttribute]) -> Result<&'a str, Error> { entries .iter() .find_map(|entry| { - if entry.key == key { - Some(entry.value.as_str()) + if entry.key_bytes() == key.as_bytes() { + Some(entry.value_str().map_err(|_| { + Error::event(format!( + "attribute value for key {key} is not a valid UTF-8 string" + )) + })) } else { None } }) + .transpose()? .ok_or_else(|| Error::event(format!("attribute not found for key: {key}"))) } fn new_attr(key: &str, value: &str) -> abci::EventAttribute { - abci::EventAttribute { - key: String::from(key), - value: String::from(value), - index: true, - } + abci::EventAttribute::from((key, value, true)) } impl From for abci::Event { @@ -105,66 +100,3 @@ impl<'a> TryFrom<&'a [abci::EventAttribute]> for CrossChainQueryPacket { }) } } - -fn fetch_first_element_from_events( - block_events: &BTreeMap>, - key: &str, -) -> Result { - let res = block_events - .get(key) - .ok_or_else(|| Error::event(format!("attribute not found for key: {key}")))? - .first() - .ok_or_else(|| { - Error::event(format!( - "element at position 0, of attribute with key `{key}`, not found" - )) - })?; - - Ok(res.clone()) -} - -impl CrossChainQueryPacket { - pub fn extract_query_event( - block_events: &BTreeMap>, - ) -> Result { - let chain_id_str = fetch_first_element_from_events( - block_events, - &format!("{}.{}", EVENT_TYPE_PREFIX, "chain_id"), - )?; - let connection_id_str = fetch_first_element_from_events( - block_events, - &format!("{}.{}", EVENT_TYPE_PREFIX, "connection_id"), - )?; - let query_type = fetch_first_element_from_events( - block_events, - &format!("{}.{}", EVENT_TYPE_PREFIX, "type"), - )?; - let height_str = fetch_first_element_from_events( - block_events, - &format!("{}.{}", EVENT_TYPE_PREFIX, "height"), - )?; - - Ok(IbcEvent::CrossChainQueryPacket(CrossChainQueryPacket { - module: fetch_first_element_from_events( - block_events, - &format!("{}.{}", EVENT_TYPE_PREFIX, "module"), - )?, - action: fetch_first_element_from_events( - block_events, - &format!("{}.{}", EVENT_TYPE_PREFIX, "action"), - )?, - query_id: fetch_first_element_from_events( - block_events, - &format!("{}.{}", EVENT_TYPE_PREFIX, "query_id"), - )?, - chain_id: ChainId::from_string(&chain_id_str), - connection_id: ConnectionId::from_str(&connection_id_str)?, - query_type, - height: Height::from_str(&height_str)?, - request: fetch_first_element_from_events( - block_events, - &format!("{}.{}", EVENT_TYPE_PREFIX, "request"), - )?, - })) - } -} diff --git a/crates/relayer-types/src/applications/ics31_icq/response.rs b/crates/relayer-types/src/applications/ics31_icq/response.rs index f81ad76e1f..6abdaeb18a 100644 --- a/crates/relayer-types/src/applications/ics31_icq/response.rs +++ b/crates/relayer-types/src/applications/ics31_icq/response.rs @@ -1,18 +1,9 @@ -use ibc_proto::{ - google::protobuf::Any, - stride::interchainquery::v1::MsgSubmitQueryResponse, -}; +use ibc_proto::{google::protobuf::Any, stride::interchainquery::v1::MsgSubmitQueryResponse}; use prost::Message; use tendermint::merkle::proof::ProofOps as TendermintProofOps; -use tendermint_proto::crypto::{ - ProofOp, - ProofOps, -}; +use tendermint_proto::crypto::{ProofOp, ProofOps}; -use crate::{ - applications::ics31_icq::error::Error, - signer::Signer, -}; +use crate::{applications::ics31_icq::error::Error, signer::Signer}; pub const TYPE_URL: &str = "/stride.interchainquery.v1.MsgSubmitQueryResponse"; diff --git a/crates/relayer-types/src/applications/transfer/acknowledgement.rs b/crates/relayer-types/src/applications/transfer/acknowledgement.rs index 047b0404a4..2277baebd6 100644 --- a/crates/relayer-types/src/applications/transfer/acknowledgement.rs +++ b/crates/relayer-types/src/applications/transfer/acknowledgement.rs @@ -1,13 +1,6 @@ -use std::fmt::{ - Display, - Error as FmtError, - Formatter, -}; - -use serde::{ - Deserialize, - Serialize, -}; +use std::fmt::{Display, Error as FmtError, Formatter}; + +use serde::{Deserialize, Serialize}; use super::error::Error; diff --git a/crates/relayer-types/src/applications/transfer/amount.rs b/crates/relayer-types/src/applications/transfer/amount.rs index cf0fd48a08..ce9446c511 100644 --- a/crates/relayer-types/src/applications/transfer/amount.rs +++ b/crates/relayer-types/src/applications/transfer/amount.rs @@ -1,18 +1,7 @@ -use std::{ - iter::Sum, - ops::Add, - str::FromStr, -}; +use std::{iter::Sum, ops::Add, str::FromStr}; -use derive_more::{ - Display, - From, - Into, -}; -use serde::{ - Deserialize, - Serialize, -}; +use derive_more::{Display, From, Into}; +use serde::{Deserialize, Serialize}; use super::error::Error; use crate::bigint::U256; diff --git a/crates/relayer-types/src/applications/transfer/coin.rs b/crates/relayer-types/src/applications/transfer/coin.rs index 207f4a3bff..90ef36df93 100644 --- a/crates/relayer-types/src/applications/transfer/coin.rs +++ b/crates/relayer-types/src/applications/transfer/coin.rs @@ -1,25 +1,15 @@ use std::{ - fmt::{ - Display, - Error as FmtError, - Formatter, - }, + fmt::{Display, Error as FmtError, Formatter}, str::FromStr, }; use ibc_proto::cosmos::base::v1beta1::Coin as ProtoCoin; use regex::Regex; -use serde::{ - Deserialize, - Serialize, -}; +use serde::{Deserialize, Serialize}; use super::{ amount::Amount, - denom::{ - BaseDenom, - PrefixedDenom, - }, + denom::{BaseDenom, PrefixedDenom}, error::Error, }; use crate::serializers::serde_string; diff --git a/crates/relayer-types/src/applications/transfer/denom.rs b/crates/relayer-types/src/applications/transfer/denom.rs index 4ceb009d4b..d74701c048 100644 --- a/crates/relayer-types/src/applications/transfer/denom.rs +++ b/crates/relayer-types/src/applications/transfer/denom.rs @@ -1,28 +1,15 @@ use std::{ - fmt::{ - Display, - Error as FmtError, - Formatter, - }, + fmt::{Display, Error as FmtError, Formatter}, str::FromStr, }; -use derive_more::{ - Display, - From, -}; +use derive_more::{Display, From}; use ibc_proto::ibc::applications::transfer::v1::DenomTrace as RawDenomTrace; -use serde::{ - Deserialize, - Serialize, -}; +use serde::{Deserialize, Serialize}; use super::error::Error; use crate::{ - core::ics24_host::identifier::{ - ChannelId, - PortId, - }, + core::ics24_host::identifier::{ChannelId, PortId}, serializers::serde_string, }; diff --git a/crates/relayer-types/src/applications/transfer/error.rs b/crates/relayer-types/src/applications/transfer/error.rs index f7c6c7d8f0..4e9fc8577e 100644 --- a/crates/relayer-types/src/applications/transfer/error.rs +++ b/crates/relayer-types/src/applications/transfer/error.rs @@ -1,31 +1,16 @@ -use std::{ - convert::Infallible, - str::Utf8Error, - string::FromUtf8Error, -}; +use std::{convert::Infallible, str::Utf8Error, string::FromUtf8Error}; -use flex_error::{ - define_error, - DisplayOnly, - TraceError, -}; +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, - error as channel_error, - version::Version, - }, + ics04_channel::{channel::Ordering, error as channel_error, version::Version}, ics24_host::{ error::ValidationError, - identifier::{ - ChannelId, - PortId, - }, + identifier::{ChannelId, PortId}, }, }, signer::SignerError, diff --git a/crates/relayer-types/src/applications/transfer/events.rs b/crates/relayer-types/src/applications/transfer/events.rs index 297283c746..51a83a44b7 100644 --- a/crates/relayer-types/src/applications/transfer/events.rs +++ b/crates/relayer-types/src/applications/transfer/events.rs @@ -1,9 +1,6 @@ use crate::{ applications::transfer::{ - acknowledgement::Acknowledgement, - Amount, - PrefixedDenom, - MODULE_ID_STR, + acknowledgement::Acknowledgement, Amount, PrefixedDenom, MODULE_ID_STR, }, events::ModuleEvent, signer::Signer, diff --git a/crates/relayer-types/src/applications/transfer/msgs/send.rs b/crates/relayer-types/src/applications/transfer/msgs/send.rs index 1a1a07f15a..599e228aa1 100644 --- a/crates/relayer-types/src/applications/transfer/msgs/send.rs +++ b/crates/relayer-types/src/applications/transfer/msgs/send.rs @@ -1,22 +1,10 @@ -use std::{ - fmt::Display, - str::FromStr, -}; +use std::{fmt::Display, str::FromStr}; -use ibc_proto::{ - cosmos::bank::v1beta1::MsgSend as RawMsgSend, - Protobuf, -}; -use serde_derive::{ - Deserialize, - Serialize, -}; +use ibc_proto::{cosmos::bank::v1beta1::MsgSend as RawMsgSend, Protobuf}; +use serde_derive::{Deserialize, Serialize}; use crate::{ - applications::transfer::{ - error::Error, - Coin, - }, + applications::transfer::{error::Error, Coin}, core::ics24_host::error::ValidationError, tx_msg::Msg, }; diff --git a/crates/relayer-types/src/applications/transfer/msgs/transfer.rs b/crates/relayer-types/src/applications/transfer/msgs/transfer.rs index 27b71b1bcd..63ee23ad08 100644 --- a/crates/relayer-types/src/applications/transfer/msgs/transfer.rs +++ b/crates/relayer-types/src/applications/transfer/msgs/transfer.rs @@ -1,20 +1,15 @@ //! This is the definition of a transfer messages that an application submits to a chain. use ibc_proto::{ - cosmos::base::v1beta1::Coin, - google::protobuf::Any, - ibc::applications::transfer::v1::MsgTransfer as RawMsgTransfer, - Protobuf, + cosmos::base::v1beta1::Coin, google::protobuf::Any, + ibc::applications::transfer::v1::MsgTransfer as RawMsgTransfer, Protobuf, }; use crate::{ applications::transfer::error::Error, core::{ ics04_channel::timeout::TimeoutHeight, - ics24_host::identifier::{ - ChannelId, - PortId, - }, + ics24_host::identifier::{ChannelId, PortId}, }, signer::Signer, timestamp::Timestamp, @@ -138,32 +133,18 @@ impl From for Any { #[cfg(test)] pub mod test_util { - use core::{ - ops::Add, - time::Duration, - }; + use core::{ops::Add, time::Duration}; use super::MsgTransfer; use crate::{ - applications::transfer::{ - packet::PacketData, - BaseCoin, - Coin, - PrefixedCoin, - }, + applications::transfer::{packet::PacketData, BaseCoin, Coin, PrefixedCoin}, bigint::U256, core::{ ics04_channel::{ - packet::{ - Packet, - Sequence, - }, + packet::{Packet, Sequence}, timeout::TimeoutHeight, }, - ics24_host::identifier::{ - ChannelId, - PortId, - }, + ics24_host::identifier::{ChannelId, PortId}, }, signer::Signer, test_utils::get_dummy_bech32_account, diff --git a/crates/relayer-types/src/applications/transfer/packet.rs b/crates/relayer-types/src/applications/transfer/packet.rs index d11157d993..a7ba9c8bde 100644 --- a/crates/relayer-types/src/applications/transfer/packet.rs +++ b/crates/relayer-types/src/applications/transfer/packet.rs @@ -1,24 +1,9 @@ -use std::{ - convert::TryFrom, - str::FromStr, - string::{ - String, - ToString, - }, -}; +use std::str::FromStr; use ibc_proto::ibc::applications::transfer::v2::FungibleTokenPacketData as RawPacketData; -use serde::{ - Deserialize, - Serialize, -}; +use serde::{Deserialize, Serialize}; -use super::{ - error::Error, - Amount, - PrefixedCoin, - PrefixedDenom, -}; +use super::{error::Error, Amount, PrefixedCoin, PrefixedDenom}; use crate::signer::Signer; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] 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 bf544dd6b8..3a8fe6dd93 100644 --- a/crates/relayer-types/src/clients/ics07_tendermint/client_state.rs +++ b/crates/relayer-types/src/clients/ics07_tendermint/client_state.rs @@ -1,10 +1,4 @@ -use std::{ - convert::{ - TryFrom, - TryInto, - }, - time::Duration, -}; +use std::time::Duration; use ibc_proto::{ google::protobuf::Any, @@ -15,33 +9,21 @@ use ibc_proto::{ Protobuf, }; use prost::Message; -use serde::{ - Deserialize, - Serialize, -}; +use serde::{Deserialize, Serialize}; use tendermint_light_client_verifier::options::Options; -use crate::{ - clients::ics07_tendermint::{ - error::Error, - header::Header as TmHeader, - }, - core::{ - ics02_client::{ - client_state::ClientState as Ics2ClientState, - client_type::ClientType, - error::Error as Ics02Error, - trust_threshold::TrustThreshold, - }, - ics23_commitment::specs::ProofSpecs, - ics24_host::identifier::ChainId, - }, - timestamp::{ - Timestamp, - ZERO_DURATION, - }, - Height, +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, UpgradableClientState, }; +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; +use crate::core::ics23_commitment::specs::ProofSpecs; +use crate::core::ics24_host::identifier::ChainId; +use crate::timestamp::{Timestamp, ZERO_DURATION}; +use crate::Height; pub const TENDERMINT_CLIENT_STATE_TYPE_URL: &str = "/ibc.lightclients.tendermint.v1.ClientState"; @@ -214,8 +196,6 @@ pub struct UpgradeOptions { } impl Ics2ClientState for ClientState { - type UpgradeOptions = UpgradeOptions; - fn chain_id(&self) -> ChainId { self.chain_id.clone() } @@ -232,6 +212,14 @@ impl Ics2ClientState for ClientState { self.frozen_height } + fn expired(&self, elapsed: Duration) -> bool { + elapsed > self.trusting_period + } +} + +impl UpgradableClientState for ClientState { + type UpgradeOptions = UpgradeOptions; + fn upgrade( &mut self, upgrade_height: Height, @@ -251,10 +239,6 @@ impl Ics2ClientState for ClientState { self.unbonding_period = upgrade_options.unbonding_period; self.chain_id = chain_id; } - - fn expired(&self, elapsed: Duration) -> bool { - elapsed > self.trusting_period - } } impl Protobuf for ClientState {} @@ -388,20 +372,13 @@ mod tests { use test_log::test; use crate::{ - clients::ics07_tendermint::client_state::{ - AllowUpdate, - ClientState, - }, + clients::ics07_tendermint::client_state::{AllowUpdate, ClientState}, core::{ - ics02_client::trust_threshold::TrustThreshold, - ics23_commitment::specs::ProofSpecs, + ics02_client::trust_threshold::TrustThreshold, ics23_commitment::specs::ProofSpecs, ics24_host::identifier::ChainId, }, test::test_serialization_roundtrip, - timestamp::{ - Timestamp, - ZERO_DURATION, - }, + timestamp::{Timestamp, ZERO_DURATION}, Height, }; @@ -692,43 +669,3 @@ mod tests { } } } - -#[cfg(any(test, feature = "mocks"))] -pub mod test_util { - use core::time::Duration; - - use tendermint::block::Header; - - use crate::{ - clients::ics07_tendermint::client_state::{ - AllowUpdate, - ClientState, - }, - core::{ - ics02_client::height::Height, - ics24_host::identifier::ChainId, - }, - }; - - pub fn get_dummy_tendermint_client_state(tm_header: Header) -> ClientState { - ClientState::new( - ChainId::from(tm_header.chain_id.clone()), - Default::default(), - Duration::from_secs(64000), - Duration::from_secs(128000), - Duration::from_millis(3000), - Height::new( - ChainId::chain_version(tm_header.chain_id.as_str()), - u64::from(tm_header.height), - ) - .unwrap(), - Default::default(), - vec!["".to_string()], - AllowUpdate { - after_expiry: false, - after_misbehaviour: false, - }, - ) - .unwrap() - } -} 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 34fce2a9d4..67087c5910 100644 --- a/crates/relayer-types/src/clients/ics07_tendermint/consensus_state.rs +++ b/crates/relayer-types/src/clients/ics07_tendermint/consensus_state.rs @@ -1,29 +1,15 @@ use ibc_proto::{ - google::protobuf::Any, - ibc::lightclients::tendermint::v1::ConsensusState as RawConsensusState, + google::protobuf::Any, ibc::lightclients::tendermint::v1::ConsensusState as RawConsensusState, Protobuf, }; -use serde::{ - Deserialize, - Serialize, -}; -use tendermint::{ - hash::Algorithm, - time::Time, - Hash, -}; +use serde::{Deserialize, Serialize}; +use tendermint::{hash::Algorithm, time::Time, Hash}; use tendermint_proto::google::protobuf as tpb; use crate::{ - clients::ics07_tendermint::{ - error::Error, - header::Header, - }, + clients::ics07_tendermint::{error::Error, header::Header}, core::{ - ics02_client::{ - client_type::ClientType, - error::Error as Ics02Error, - }, + ics02_client::{client_type::ClientType, error::Error as Ics02Error}, ics23_commitment::commitment::CommitmentRoot, }, timestamp::Timestamp, diff --git a/crates/relayer-types/src/clients/ics07_tendermint/error.rs b/crates/relayer-types/src/clients/ics07_tendermint/error.rs index 7a5ebb69c6..6cfb85a1bc 100644 --- a/crates/relayer-types/src/clients/ics07_tendermint/error.rs +++ b/crates/relayer-types/src/clients/ics07_tendermint/error.rs @@ -1,26 +1,13 @@ -use flex_error::{ - define_error, - TraceError, -}; -use tendermint::{ - account::Id, - hash::Hash, - Error as TendermintError, -}; +use flex_error::{define_error, TraceError}; +use tendermint::{account::Id, hash::Hash, Error as TendermintError}; use tendermint_light_client_verifier::errors::VerificationErrorDetail as LightClientErrorDetail; use crate::{ core::{ ics02_client::error::Error as Ics02Error, - ics24_host::{ - error::ValidationError, - identifier::ClientId, - }, - }, - timestamp::{ - Timestamp, - TimestampOverflowError, + ics24_host::{error::ValidationError, identifier::ClientId}, }, + timestamp::{Timestamp, TimestampOverflowError}, Height, }; diff --git a/crates/relayer-types/src/clients/ics07_tendermint/header.rs b/crates/relayer-types/src/clients/ics07_tendermint/header.rs index fc3693fba9..247e0c5143 100644 --- a/crates/relayer-types/src/clients/ics07_tendermint/header.rs +++ b/crates/relayer-types/src/clients/ics07_tendermint/header.rs @@ -1,39 +1,21 @@ -use std::fmt::{ - Display, - Error as FmtError, - Formatter, -}; +use std::fmt::{Display, Error as FmtError, Formatter}; use bytes::Buf; use ibc_proto::{ - google::protobuf::Any, - ibc::lightclients::tendermint::v1::Header as RawHeader, - Protobuf, + google::protobuf::Any, ibc::lightclients::tendermint::v1::Header as RawHeader, Protobuf, }; use prost::Message; -use serde_derive::{ - Deserialize, - Serialize, -}; -use tendermint::{ - block::signed_header::SignedHeader, - validator::Set as ValidatorSet, -}; +use serde_derive::{Deserialize, Serialize}; +use tendermint::{block::signed_header::SignedHeader, validator::Set as ValidatorSet}; use crate::{ clients::ics07_tendermint::error::Error, core::{ - ics02_client::{ - client_type::ClientType, - error::Error as Ics02Error, - }, + ics02_client::{client_type::ClientType, error::Error as Ics02Error}, ics24_host::identifier::ChainId, }, timestamp::Timestamp, - utils::pretty::{ - PrettySignedHeader, - PrettyValidatorSet, - }, + utils::pretty::{PrettySignedHeader, PrettyValidatorSet}, Height, }; @@ -166,74 +148,3 @@ impl From
for RawHeader { } } } - -#[cfg(any(test, feature = "mocks"))] -pub mod test_util { - - use subtle_encoding::hex; - use tendermint::{ - block::signed_header::SignedHeader, - validator::{ - Info as ValidatorInfo, - Set as ValidatorSet, - }, - PublicKey, - }; - - use crate::{ - clients::ics07_tendermint::header::Header, - Height, - }; - - pub fn get_dummy_tendermint_header() -> tendermint::block::Header { - serde_json::from_str::(include_str!( - "../../../tests/support/signed_header.json" - )) - .unwrap() - .header - } - - // TODO: This should be replaced with a ::default() or ::produce(). - // The implementation of this function comprises duplicate code (code borrowed from - // `tendermint-rs` for assembling a Header). - // See https://github.com/informalsystems/tendermint-rs/issues/381. - // - // The normal flow is: - // - get the (trusted) signed header and the `trusted_validator_set` at a `trusted_height` - // - get the `signed_header` and the `validator_set` at latest height - // - build the ics07 Header - // For testing purposes this function does: - // - get the `signed_header` from a .json file - // - create the `validator_set` with a single validator that is also the proposer - // - assume a `trusted_height` of 1 and no change in the validator set since height 1, - // i.e. `trusted_validator_set` = `validator_set` - pub fn get_dummy_ics07_header() -> Header { - // Build a SignedHeader from a JSON file. - let shdr = serde_json::from_str::(include_str!( - "../../../tests/support/signed_header.json" - )) - .unwrap(); - - // Build a set of validators. - // Below are test values inspired form `test_validator_set()` in tendermint-rs. - let v1: ValidatorInfo = ValidatorInfo::new( - PublicKey::from_raw_ed25519( - &hex::decode_upper( - "F349539C7E5EF7C49549B09C4BFC2335318AB0FE51FBFAA2433B4F13E816F4A7", - ) - .unwrap(), - ) - .unwrap(), - 281_815_u64.try_into().unwrap(), - ); - - let vs = ValidatorSet::new(vec![v1.clone()], Some(v1)); - - Header { - signed_header: shdr, - validator_set: vs.clone(), - trusted_height: Height::new(0, 1).unwrap(), - trusted_validator_set: vs, - } - } -} diff --git a/crates/relayer-types/src/clients/ics07_tendermint/misbehaviour.rs b/crates/relayer-types/src/clients/ics07_tendermint/misbehaviour.rs index eaedc9be28..d01f3f33cc 100644 --- a/crates/relayer-types/src/clients/ics07_tendermint/misbehaviour.rs +++ b/crates/relayer-types/src/clients/ics07_tendermint/misbehaviour.rs @@ -1,17 +1,8 @@ -use ibc_proto::{ - ibc::lightclients::tendermint::v1::Misbehaviour as RawMisbehaviour, - Protobuf, -}; -use serde::{ - Deserialize, - Serialize, -}; +use ibc_proto::{ibc::lightclients::tendermint::v1::Misbehaviour as RawMisbehaviour, Protobuf}; +use serde::{Deserialize, Serialize}; use crate::{ - clients::ics07_tendermint::{ - error::Error, - header::Header, - }, + clients::ics07_tendermint::{error::Error, header::Header}, core::ics24_host::identifier::ClientId, tx_msg::Msg, Height, 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 15a9af6b61..94e7719d7f 100644 --- a/crates/relayer-types/src/core/ics02_client/client_state.rs +++ b/crates/relayer-types/src/core/ics02_client/client_state.rs @@ -1,24 +1,12 @@ use core::fmt::Debug; -use std::{ - marker::{ - Send, - Sync, - }, - time::Duration, -}; +use std::time::Duration; use crate::{ - core::{ - ics02_client::client_type::ClientType, - ics24_host::identifier::ChainId, - }, + core::{ics02_client::client_type::ClientType, ics24_host::identifier::ChainId}, Height, }; -pub trait ClientState: Clone + Debug + Send + Sync // Any: From, -{ - type UpgradeOptions; - +pub trait ClientState: Clone + Debug + Send + Sync { /// 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; @@ -40,6 +28,10 @@ pub trait ClientState: Clone + Debug + Send + Sync // Any: From, /// Check if the state is expired when `elapsed` time has passed since the latest consensus /// state timestamp fn expired(&self, elapsed: Duration) -> bool; +} + +pub trait UpgradableClientState: ClientState { + type UpgradeOptions; /// Helper function to verify the upgrade client procedure. /// Resets all fields except the blockchain-specific ones, diff --git a/crates/relayer-types/src/core/ics02_client/client_type.rs b/crates/relayer-types/src/core/ics02_client/client_type.rs index 7419b1efa4..536dca1f8c 100644 --- a/crates/relayer-types/src/core/ics02_client/client_type.rs +++ b/crates/relayer-types/src/core/ics02_client/client_type.rs @@ -1,13 +1,6 @@ -use std::fmt::{ - Display, - Error as FmtError, - Formatter, -}; +use std::fmt::{Display, Error as FmtError, Formatter}; -use serde_derive::{ - Deserialize, - Serialize, -}; +use serde_derive::{Deserialize, Serialize}; use super::error::Error; @@ -15,24 +8,15 @@ use super::error::Error; #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] pub enum ClientType { Tendermint = 1, - - #[cfg(any(test, feature = "mocks"))] - Mock = 9999, } impl ClientType { const TENDERMINT_STR: &'static str = "07-tendermint"; - #[cfg_attr(not(test), allow(dead_code))] - const MOCK_STR: &'static str = "9999-mock"; - /// Yields the identifier of this client type as a string pub fn as_str(&self) -> &'static str { match self { Self::Tendermint => Self::TENDERMINT_STR, - - #[cfg(any(test, feature = "mocks"))] - Self::Mock => Self::MOCK_STR, } } } @@ -50,9 +34,6 @@ impl core::str::FromStr for ClientType { match s { Self::TENDERMINT_STR => Ok(Self::Tendermint), - #[cfg(any(test, feature = "mocks"))] - Self::MOCK_STR => Ok(Self::Mock), - _ => Err(Error::unknown_client_type(s.to_string())), } } @@ -65,10 +46,7 @@ mod tests { use test_log::test; use super::ClientType; - use crate::core::ics02_client::error::{ - Error, - ErrorDetail, - }; + use crate::core::ics02_client::error::{Error, ErrorDetail}; #[test] fn parse_tendermint_client_type() { @@ -80,16 +58,6 @@ mod tests { } } - #[test] - fn parse_mock_client_type() { - let client_type = ClientType::from_str("9999-mock"); - - match client_type { - Ok(ClientType::Mock) => (), - _ => panic!("parse failed"), - } - } - #[test] fn parse_unknown_client_type() { let client_type_str = "some-random-client-type"; @@ -105,14 +73,6 @@ mod tests { } } - #[test] - fn parse_mock_as_string_result() { - let client_type = ClientType::Mock; - let type_string = client_type.as_str(); - let client_type_from_str = ClientType::from_str(type_string).unwrap(); - assert_eq!(client_type_from_str, client_type); - } - #[test] fn parse_tendermint_as_string_result() { let client_type = ClientType::Tendermint; 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 7d6ef73467..877df6c1a3 100644 --- a/crates/relayer-types/src/core/ics02_client/consensus_state.rs +++ b/crates/relayer-types/src/core/ics02_client/consensus_state.rs @@ -1,16 +1,7 @@ -use core::{ - fmt::Debug, - marker::{ - Send, - Sync, - }, -}; +use core::fmt::Debug; use crate::{ - core::{ - ics02_client::client_type::ClientType, - ics23_commitment::commitment::CommitmentRoot, - }, + core::{ics02_client::client_type::ClientType, ics23_commitment::commitment::CommitmentRoot}, timestamp::Timestamp, }; diff --git a/crates/relayer-types/src/core/ics02_client/error.rs b/crates/relayer-types/src/core/ics02_client/error.rs index 16c76f80c1..7924f3df63 100644 --- a/crates/relayer-types/src/core/ics02_client/error.rs +++ b/crates/relayer-types/src/core/ics02_client/error.rs @@ -1,20 +1,11 @@ -use flex_error::{ - define_error, - TraceError, -}; +use flex_error::{define_error, TraceError}; use tendermint_proto::Error as TendermintProtoError; use crate::{ core::{ - ics02_client::{ - client_type::ClientType, - height::HeightError, - }, + ics02_client::{client_type::ClientType, height::HeightError}, ics23_commitment::error::Error as Ics23Error, - ics24_host::{ - error::ValidationError, - identifier::ClientId, - }, + ics24_host::{error::ValidationError, identifier::ClientId}, }, signer::SignerError, timestamp::Timestamp, @@ -291,5 +282,12 @@ define_error! { ClientSpecific { description: String } | e | { format_args!("client specific error: {0}", e.description) }, + + MalformedEventAttributeKey + | _ | { format_args!("event attribute key is not valid UTF-8") }, + + MalformedEventAttributeValue + { key: String } + | e | { format_args!("event attribute value for key {} is not valid UTF-8", e.key) }, } } diff --git a/crates/relayer-types/src/core/ics02_client/events.rs b/crates/relayer-types/src/core/ics02_client/events.rs index 1ede4ad438..6605b2534a 100644 --- a/crates/relayer-types/src/core/ics02_client/events.rs +++ b/crates/relayer-types/src/core/ics02_client/events.rs @@ -1,31 +1,18 @@ //! Types for the IBC events emitted from Tendermint Websocket by the client module. -use std::fmt::{ - Display, - Error as FmtError, - Formatter, -}; +use std::fmt::{Display, Error as FmtError, Formatter}; -use serde_derive::{ - Deserialize, - Serialize, -}; +use serde_derive::{Deserialize, Serialize}; use tendermint::abci; use tendermint_proto::Protobuf; use super::header::AnyHeader; use crate::{ core::{ - ics02_client::{ - client_type::ClientType, - height::Height, - }, + ics02_client::{client_type::ClientType, height::Height}, ics24_host::identifier::ClientId, }, - events::{ - IbcEvent, - IbcEventType, - }, + events::{IbcEvent, IbcEventType}, }; /// The content of the `key` field for the attribute containing the client identifier. diff --git a/crates/relayer-types/src/core/ics02_client/header.rs b/crates/relayer-types/src/core/ics02_client/header.rs index 55b4599c12..9692a5f8f4 100644 --- a/crates/relayer-types/src/core/ics02_client/header.rs +++ b/crates/relayer-types/src/core/ics02_client/header.rs @@ -1,24 +1,13 @@ use core::fmt::Debug; -use ibc_proto::{ - google::protobuf::Any, - Protobuf, -}; -use serde::{ - Deserialize, - Serialize, -}; +use ibc_proto::{google::protobuf::Any, Protobuf}; +use serde::{Deserialize, Serialize}; use crate::{ clients::ics07_tendermint::header::{ - decode_header as tm_decode_header, - Header as TendermintHeader, - TENDERMINT_HEADER_TYPE_URL, - }, - core::ics02_client::{ - client_type::ClientType, - error::Error, + decode_header as tm_decode_header, Header as TendermintHeader, TENDERMINT_HEADER_TYPE_URL, }, + core::ics02_client::{client_type::ClientType, error::Error}, timestamp::Timestamp, Height, }; diff --git a/crates/relayer-types/src/core/ics02_client/height.rs b/crates/relayer-types/src/core/ics02_client/height.rs index 064419f70b..6fb3de355b 100644 --- a/crates/relayer-types/src/core/ics02_client/height.rs +++ b/crates/relayer-types/src/core/ics02_client/height.rs @@ -1,26 +1,10 @@ -use std::{ - cmp::Ordering, - num::ParseIntError, - str::FromStr, -}; - -use flex_error::{ - define_error, - TraceError, -}; -use ibc_proto::{ - ibc::core::client::v1::Height as RawHeight, - Protobuf, -}; -use serde_derive::{ - Deserialize, - Serialize, -}; - -use crate::core::{ - ics02_client::error::Error, - ics24_host::identifier::ChainId, -}; +use std::{cmp::Ordering, num::ParseIntError, str::FromStr}; + +use flex_error::{define_error, TraceError}; +use ibc_proto::{ibc::core::client::v1::Height as RawHeight, Protobuf}; +use serde_derive::{Deserialize, Serialize}; + +use crate::core::{ics02_client::error::Error, ics24_host::identifier::ChainId}; #[derive(Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Height { diff --git a/crates/relayer-types/src/core/ics02_client/misbehaviour.rs b/crates/relayer-types/src/core/ics02_client/misbehaviour.rs index b700eba87e..ca1d30711a 100644 --- a/crates/relayer-types/src/core/ics02_client/misbehaviour.rs +++ b/crates/relayer-types/src/core/ics02_client/misbehaviour.rs @@ -1,9 +1,6 @@ use core::fmt::Debug; -use crate::{ - core::ics24_host::identifier::ClientId, - Height, -}; +use crate::{core::ics24_host::identifier::ClientId, Height}; pub trait Misbehaviour: Clone + Debug + Send + Sync { /// The type of client (eg. Tendermint) diff --git a/crates/relayer-types/src/core/ics02_client/msgs.rs b/crates/relayer-types/src/core/ics02_client/msgs.rs index cb9aaaaabd..fc13f07445 100644 --- a/crates/relayer-types/src/core/ics02_client/msgs.rs +++ b/crates/relayer-types/src/core/ics02_client/msgs.rs @@ -5,10 +5,8 @@ //! . use crate::core::ics02_client::msgs::{ - create_client::MsgCreateClient, - misbehaviour::MsgSubmitMisbehaviour, - update_client::MsgUpdateClient, - upgrade_client::MsgUpgradeClient, + create_client::MsgCreateClient, misbehaviour::MsgSubmitMisbehaviour, + update_client::MsgUpdateClient, upgrade_client::MsgUpgradeClient, }; pub mod create_client; 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 1c3e4b8b21..83dd2b54ac 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 @@ -1,16 +1,10 @@ //! Definition of domain type message `MsgCreateClient`. use ibc_proto::{ - google::protobuf::Any, - ibc::core::client::v1::MsgCreateClient as RawMsgCreateClient, - Protobuf, + google::protobuf::Any, ibc::core::client::v1::MsgCreateClient as RawMsgCreateClient, Protobuf, }; -use crate::{ - core::ics02_client::error::Error, - signer::Signer, - tx_msg::Msg, -}; +use crate::{core::ics02_client::error::Error, signer::Signer, tx_msg::Msg}; pub const TYPE_URL: &str = "/ibc.core.client.v1.MsgCreateClient"; @@ -76,41 +70,3 @@ impl From for RawMsgCreateClient { } } } - -#[cfg(test)] -mod tests { - - use ibc_proto::ibc::core::client::v1::MsgCreateClient as RawMsgCreateClient; - use test_log::test; - - use crate::{ - clients::ics07_tendermint::{ - client_state::test_util::get_dummy_tendermint_client_state, - consensus_state::ConsensusState as TmConsensusState, - header::test_util::get_dummy_tendermint_header, - }, - core::ics02_client::msgs::create_client::MsgCreateClient, - test_utils::get_dummy_account_id, - }; - - #[test] - fn msg_create_client_serialization() { - let signer = get_dummy_account_id(); - - let tm_header = get_dummy_tendermint_header(); - let tm_client_state = get_dummy_tendermint_client_state(tm_header.clone()).into(); - - let msg = MsgCreateClient::new( - tm_client_state, - TmConsensusState::from(tm_header).into(), - signer, - ) - .unwrap(); - - let raw = RawMsgCreateClient::from(msg.clone()); - let msg_back = MsgCreateClient::try_from(raw.clone()).unwrap(); - let raw_back = RawMsgCreateClient::from(msg_back.clone()); - assert_eq!(msg, msg_back); - assert_eq!(raw, raw_back); - } -} 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 2ac292af2d..bd09549019 100644 --- a/crates/relayer-types/src/core/ics02_client/msgs/misbehaviour.rs +++ b/crates/relayer-types/src/core/ics02_client/msgs/misbehaviour.rs @@ -1,14 +1,10 @@ use ibc_proto::{ google::protobuf::Any as ProtoAny, - ibc::core::client::v1::MsgSubmitMisbehaviour as RawMsgSubmitMisbehaviour, - Protobuf, + ibc::core::client::v1::MsgSubmitMisbehaviour as RawMsgSubmitMisbehaviour, Protobuf, }; use crate::{ - core::{ - ics02_client::error::Error, - ics24_host::identifier::ClientId, - }, + core::{ics02_client::error::Error, ics24_host::identifier::ClientId}, signer::Signer, tx_msg::Msg, }; 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 b1d260726c..d190767475 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 @@ -1,18 +1,13 @@ //! Definition of domain type message `MsgUpdateAnyClient`. use ibc_proto::{ - google::protobuf::Any, - ibc::core::client::v1::MsgUpdateClient as RawMsgUpdateClient, - Protobuf, + google::protobuf::Any, ibc::core::client::v1::MsgUpdateClient as RawMsgUpdateClient, Protobuf, }; use crate::{ core::{ ics02_client::error::Error, - ics24_host::{ - error::ValidationError, - identifier::ClientId, - }, + ics24_host::{error::ValidationError, identifier::ClientId}, }, signer::Signer, tx_msg::Msg, @@ -77,34 +72,3 @@ impl From for RawMsgUpdateClient { } } } - -#[cfg(test)] -mod tests { - - use ibc_proto::ibc::core::client::v1::MsgUpdateClient as RawMsgUpdateClient; - use test_log::test; - - use crate::{ - clients::ics07_tendermint::header::test_util::get_dummy_ics07_header, - core::{ - ics02_client::msgs::MsgUpdateClient, - ics24_host::identifier::ClientId, - }, - test_utils::get_dummy_account_id, - }; - - #[test] - fn msg_update_client_serialization() { - let client_id: ClientId = "tendermint".parse().unwrap(); - let signer = get_dummy_account_id(); - - let header = get_dummy_ics07_header(); - - let msg = MsgUpdateClient::new(client_id, header.into(), signer); - let raw = RawMsgUpdateClient::from(msg.clone()); - let msg_back = MsgUpdateClient::try_from(raw.clone()).unwrap(); - let raw_back = RawMsgUpdateClient::from(msg_back.clone()); - assert_eq!(msg, msg_back); - assert_eq!(raw, raw_back); - } -} 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 3882ace9e5..5c2f2ca5af 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 @@ -14,10 +14,7 @@ use ibc_proto::{ use crate::{ core::{ ics02_client::error::Error, - ics23_commitment::{ - commitment::CommitmentProofBytes, - error::Error as Ics23Error, - }, + ics23_commitment::{commitment::CommitmentProofBytes, error::Error as Ics23Error}, ics24_host::identifier::ClientId, }, signer::Signer, @@ -122,95 +119,3 @@ impl TryFrom for MsgUpgradeClient { }) } } - -#[cfg(test)] -pub mod test_util { - use ibc_proto::ibc::core::client::v1::MsgUpgradeClient as RawMsgUpgradeClient; - - use super::MsgUpgradeClient; - use crate::{ - core::{ - ics02_client::height::Height, - ics24_host::identifier::ClientId, - }, - mock::{ - client_state::MockClientState, - consensus_state::MockConsensusState, - header::MockHeader, - }, - test_utils::{ - get_dummy_bech32_account, - get_dummy_proof, - }, - }; - - /// Extends the implementation with additional helper methods. - impl MsgUpgradeClient { - /// Setter for `client_id`. Amenable to chaining, since it consumes the input message. - pub fn with_client_id(self, client_id: ClientId) -> Self { - MsgUpgradeClient { client_id, ..self } - } - } - - /// Returns a dummy `RawMsgUpgradeClient`, for testing only! - pub fn get_dummy_raw_msg_upgrade_client(height: Height) -> RawMsgUpgradeClient { - RawMsgUpgradeClient { - client_id: "tendermint".parse().unwrap(), - client_state: Some(MockClientState::new(MockHeader::new(height)).into()), - consensus_state: Some(MockConsensusState::new(MockHeader::new(height)).into()), - proof_upgrade_client: get_dummy_proof(), - proof_upgrade_consensus_state: get_dummy_proof(), - signer: get_dummy_bech32_account(), - } - } -} - -#[cfg(test)] -mod tests { - - use ibc_proto::ibc::core::client::v1::MsgUpgradeClient as RawMsgUpgradeClient; - - use crate::{ - core::{ - ics02_client::{ - height::Height, - msgs::upgrade_client::MsgUpgradeClient, - }, - ics23_commitment::commitment::test_util::get_dummy_merkle_proof, - ics24_host::identifier::ClientId, - }, - mock::{ - client_state::MockClientState, - consensus_state::MockConsensusState, - header::MockHeader, - }, - test_utils::get_dummy_account_id, - }; - - #[test] - fn msg_upgrade_client_serialization() { - let client_id: ClientId = "tendermint".parse().unwrap(); - let signer = get_dummy_account_id(); - - let height = Height::new(1, 1).unwrap(); - - let client_state = MockClientState::new(MockHeader::new(height)); - let consensus_state = MockConsensusState::new(MockHeader::new(height)); - - let proof = get_dummy_merkle_proof(); - - let msg = MsgUpgradeClient::new( - client_id, - client_state.into(), - consensus_state.into(), - proof.clone(), - proof, - signer, - ); - let raw: RawMsgUpgradeClient = RawMsgUpgradeClient::from(msg.clone()); - let msg_back = MsgUpgradeClient::try_from(raw.clone()).unwrap(); - let raw_back: RawMsgUpgradeClient = RawMsgUpgradeClient::from(msg_back.clone()); - assert_eq!(msg, msg_back); - assert_eq!(raw, raw_back); - } -} 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 ceabf7cc3e..47bea26482 100644 --- a/crates/relayer-types/src/core/ics02_client/trust_threshold.rs +++ b/crates/relayer-types/src/core/ics02_client/trust_threshold.rs @@ -2,25 +2,12 @@ //! represented as a fraction with valid values in the //! range `[0, 1)`. -use std::{ - convert::TryFrom, - fmt::{ - Display, - Error as FmtError, - Formatter, - }, - str::FromStr, -}; - -use ibc_proto::{ - ibc::lightclients::tendermint::v1::Fraction, - Protobuf, -}; +use std::fmt::{Display, Error as FmtError, Formatter}; +use std::str::FromStr; + +use ibc_proto::{ibc::lightclients::tendermint::v1::Fraction, Protobuf}; use num_rational::Ratio; -use serde::{ - Deserialize, - Serialize, -}; +use serde::{Deserialize, Serialize}; use tendermint::trust_threshold::TrustThresholdFraction; use crate::core::ics02_client::error::Error; @@ -173,10 +160,7 @@ impl<'de> Deserialize<'de> for TrustThreshold { { use std::fmt; - use serde::de::{ - self, - Visitor, - }; + use serde::de::{self, Visitor}; // This is a Visitor that forwards string types to T's `FromStr` impl and // forwards map types to T's `Deserialize` impl. The `PhantomData` is to @@ -229,10 +213,7 @@ where { use std::fmt; - use serde::de::{ - self, - Visitor, - }; + use serde::de::{self, Visitor}; struct StringOrInt; diff --git a/crates/relayer-types/src/core/ics03_connection/connection.rs b/crates/relayer-types/src/core/ics03_connection/connection.rs index d7d687d8b1..ee43003bae 100644 --- a/crates/relayer-types/src/core/ics03_connection/connection.rs +++ b/crates/relayer-types/src/core/ics03_connection/connection.rs @@ -1,41 +1,24 @@ -use std::{ - fmt::{ - Display, - Error as FmtError, - Formatter, - }, - str::FromStr, - time::Duration, - u64, -}; +use std::fmt::{Display, Error as FmtError, Formatter}; +use std::str::FromStr; +use std::time::Duration; use ibc_proto::{ ibc::core::connection::v1::{ - ConnectionEnd as RawConnectionEnd, - Counterparty as RawCounterparty, + ConnectionEnd as RawConnectionEnd, Counterparty as RawCounterparty, IdentifiedConnection as RawIdentifiedConnection, }, Protobuf, }; -use serde::{ - Deserialize, - Serialize, -}; +use serde::{Deserialize, Serialize}; use crate::{ core::{ ics02_client::error::Error as ClientError, - ics03_connection::{ - error::Error, - version::Version, - }, + ics03_connection::{error::Error, version::Version}, ics23_commitment::commitment::CommitmentPrefix, ics24_host::{ error::ValidationError, - identifier::{ - ClientId, - ConnectionId, - }, + identifier::{ClientId, ConnectionId}, }, }, timestamp::ZERO_DURATION, @@ -408,6 +391,6 @@ impl TryFrom for State { impl From for i32 { fn from(value: State) -> Self { - value.into() + value as i32 } } diff --git a/crates/relayer-types/src/core/ics03_connection/error.rs b/crates/relayer-types/src/core/ics03_connection/error.rs index c2106a7179..3b5b8bcfca 100644 --- a/crates/relayer-types/src/core/ics03_connection/error.rs +++ b/crates/relayer-types/src/core/ics03_connection/error.rs @@ -6,10 +6,7 @@ use crate::{ ics03_connection::version::Version, ics24_host::{ error::ValidationError, - identifier::{ - ClientId, - ConnectionId, - }, + identifier::{ClientId, ConnectionId}, }, }, proofs::ProofError, @@ -166,5 +163,12 @@ define_error! { ImplementationSpecific | _ | { "implementation specific error" }, + + MalformedEventAttributeKey + | _ | { format_args!("event attribute key is not valid UTF-8") }, + + MalformedEventAttributeValue + { key: String } + | e | { format_args!("event attribute value for key {} is not valid UTF-8", e.key) }, } } diff --git a/crates/relayer-types/src/core/ics03_connection/events.rs b/crates/relayer-types/src/core/ics03_connection/events.rs index 5f814bad70..06d5e21910 100644 --- a/crates/relayer-types/src/core/ics03_connection/events.rs +++ b/crates/relayer-types/src/core/ics03_connection/events.rs @@ -1,26 +1,13 @@ //! Types for the IBC events emitted from Tendermint Websocket by the connection module. -use std::fmt::{ - Display, - Error as FmtError, - Formatter, -}; +use std::fmt::{Display, Error as FmtError, Formatter}; -use serde_derive::{ - Deserialize, - Serialize, -}; +use serde_derive::{Deserialize, Serialize}; use tendermint::abci; use crate::{ - core::ics24_host::identifier::{ - ClientId, - ConnectionId, - }, - events::{ - IbcEvent, - IbcEventType, - }, + core::ics24_host::identifier::{ClientId, ConnectionId}, + events::{IbcEvent, IbcEventType}, }; /// The content of the `key` field for the attribute containing the connection identifier. diff --git a/crates/relayer-types/src/core/ics03_connection/msgs.rs b/crates/relayer-types/src/core/ics03_connection/msgs.rs index 84bb733584..c811278091 100644 --- a/crates/relayer-types/src/core/ics03_connection/msgs.rs +++ b/crates/relayer-types/src/core/ics03_connection/msgs.rs @@ -13,10 +13,8 @@ //! `signer` which is specific to Cosmos-SDK. use crate::core::ics03_connection::msgs::{ - conn_open_ack::MsgConnectionOpenAck, - conn_open_confirm::MsgConnectionOpenConfirm, - conn_open_init::MsgConnectionOpenInit, - conn_open_try::MsgConnectionOpenTry, + conn_open_ack::MsgConnectionOpenAck, conn_open_confirm::MsgConnectionOpenConfirm, + conn_open_init::MsgConnectionOpenInit, conn_open_try::MsgConnectionOpenTry, }; pub mod conn_open_ack; @@ -37,14 +35,10 @@ pub enum ConnectionMsg { pub mod test_util { use ibc_proto::ibc::core::{ - commitment::v1::MerklePrefix, - connection::v1::Counterparty as RawCounterparty, + commitment::v1::MerklePrefix, connection::v1::Counterparty as RawCounterparty, }; - use crate::core::ics24_host::identifier::{ - ClientId, - ConnectionId, - }; + use crate::core::ics24_host::identifier::{ClientId, ConnectionId}; pub fn get_dummy_raw_counterparty() -> RawCounterparty { RawCounterparty { 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 fec58fe4c4..2d602a7375 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,22 +1,15 @@ use ibc_proto::{ google::protobuf::Any, - ibc::core::connection::v1::MsgConnectionOpenAck as RawMsgConnectionOpenAck, - Protobuf, + ibc::core::connection::v1::MsgConnectionOpenAck as RawMsgConnectionOpenAck, Protobuf, }; use crate::{ core::{ - ics03_connection::{ - error::Error, - version::Version, - }, + ics03_connection::{error::Error, version::Version}, ics23_commitment::commitment::CommitmentProofBytes, ics24_host::identifier::ConnectionId, }, - proofs::{ - ConsensusProof, - Proofs, - }, + proofs::{ConsensusProof, Proofs}, signer::Signer, tx_msg::Msg, Height, @@ -146,19 +139,12 @@ impl From for RawMsgConnectionOpenAck { pub mod test_util { use ibc_proto::ibc::core::{ - client::v1::Height, - connection::v1::MsgConnectionOpenAck as RawMsgConnectionOpenAck, + client::v1::Height, connection::v1::MsgConnectionOpenAck as RawMsgConnectionOpenAck, }; use crate::{ - core::{ - ics03_connection::version::Version, - ics24_host::identifier::ConnectionId, - }, - test_utils::{ - get_dummy_bech32_account, - get_dummy_proof, - }, + core::{ics03_connection::version::Version, ics24_host::identifier::ConnectionId}, + test_utils::{get_dummy_bech32_account, get_dummy_proof}, }; pub fn get_dummy_raw_msg_conn_open_ack( @@ -191,14 +177,12 @@ pub mod test_util { mod tests { use ibc_proto::ibc::core::{ - client::v1::Height, - connection::v1::MsgConnectionOpenAck as RawMsgConnectionOpenAck, + client::v1::Height, connection::v1::MsgConnectionOpenAck as RawMsgConnectionOpenAck, }; use test_log::test; use crate::core::ics03_connection::msgs::conn_open_ack::{ - test_util::get_dummy_raw_msg_conn_open_ack, - MsgConnectionOpenAck, + test_util::get_dummy_raw_msg_conn_open_ack, MsgConnectionOpenAck, }; #[test] 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 d12e00b69b..f6f98b2d18 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,13 +1,9 @@ use ibc_proto::{ - ibc::core::connection::v1::MsgConnectionOpenConfirm as RawMsgConnectionOpenConfirm, - Protobuf, + ibc::core::connection::v1::MsgConnectionOpenConfirm as RawMsgConnectionOpenConfirm, Protobuf, }; use crate::{ - core::{ - ics03_connection::error::Error, - ics24_host::identifier::ConnectionId, - }, + core::{ics03_connection::error::Error, ics24_host::identifier::ConnectionId}, proofs::Proofs, signer::Signer, tx_msg::Msg, @@ -83,14 +79,10 @@ impl From for RawMsgConnectionOpenConfirm { pub mod test_util { use ibc_proto::ibc::core::{ - client::v1::Height, - connection::v1::MsgConnectionOpenConfirm as RawMsgConnectionOpenConfirm, + client::v1::Height, connection::v1::MsgConnectionOpenConfirm as RawMsgConnectionOpenConfirm, }; - use crate::test_utils::{ - get_dummy_bech32_account, - get_dummy_proof, - }; + use crate::test_utils::{get_dummy_bech32_account, get_dummy_proof}; pub fn get_dummy_raw_msg_conn_open_confirm() -> RawMsgConnectionOpenConfirm { RawMsgConnectionOpenConfirm { @@ -109,14 +101,12 @@ pub mod test_util { mod tests { use ibc_proto::ibc::core::{ - client::v1::Height, - connection::v1::MsgConnectionOpenConfirm as RawMsgConnectionOpenConfirm, + client::v1::Height, connection::v1::MsgConnectionOpenConfirm as RawMsgConnectionOpenConfirm, }; use test_log::test; use crate::core::ics03_connection::msgs::conn_open_confirm::{ - test_util::get_dummy_raw_msg_conn_open_confirm, - MsgConnectionOpenConfirm, + test_util::get_dummy_raw_msg_conn_open_confirm, MsgConnectionOpenConfirm, }; #[test] 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 4716327a94..6e069f4c0e 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,17 +1,12 @@ use std::time::Duration; use ibc_proto::{ - ibc::core::connection::v1::MsgConnectionOpenInit as RawMsgConnectionOpenInit, - Protobuf, + ibc::core::connection::v1::MsgConnectionOpenInit as RawMsgConnectionOpenInit, Protobuf, }; use crate::{ core::{ - ics03_connection::{ - connection::Counterparty, - error::Error, - version::Version, - }, + ics03_connection::{connection::Counterparty, error::Error, version::Version}, ics24_host::identifier::ClientId, }, signer::Signer, @@ -85,8 +80,7 @@ pub mod test_util { core::{ ics03_connection::{ msgs::{ - conn_open_init::MsgConnectionOpenInit, - test_util::get_dummy_raw_counterparty, + conn_open_init::MsgConnectionOpenInit, test_util::get_dummy_raw_counterparty, }, version::Version, }, @@ -120,8 +114,7 @@ pub mod test_util { mod tests { use ibc_proto::ibc::core::connection::v1::{ - Counterparty as RawCounterparty, - MsgConnectionOpenInit as RawMsgConnectionOpenInit, + Counterparty as RawCounterparty, MsgConnectionOpenInit as RawMsgConnectionOpenInit, }; use test_log::test; 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 21f57fe530..58063aee72 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 @@ -1,35 +1,17 @@ -use std::{ - convert::{ - TryFrom, - TryInto, - }, - str::FromStr, - time::Duration, -}; +use std::{str::FromStr, time::Duration}; use ibc_proto::{ google::protobuf::Any, - ibc::core::connection::v1::MsgConnectionOpenTry as RawMsgConnectionOpenTry, - Protobuf, + ibc::core::connection::v1::MsgConnectionOpenTry as RawMsgConnectionOpenTry, Protobuf, }; use crate::{ core::{ - ics03_connection::{ - connection::Counterparty, - error::Error, - version::Version, - }, + ics03_connection::{connection::Counterparty, error::Error, version::Version}, ics23_commitment::commitment::CommitmentProofBytes, - ics24_host::identifier::{ - ClientId, - ConnectionId, - }, - }, - proofs::{ - ConsensusProof, - Proofs, + ics24_host::identifier::{ClientId, ConnectionId}, }, + proofs::{ConsensusProof, Proofs}, signer::Signer, tx_msg::Msg, Height, @@ -188,28 +170,20 @@ impl From for RawMsgConnectionOpenTry { pub mod test_util { use ibc_proto::ibc::core::{ - client::v1::Height, - connection::v1::MsgConnectionOpenTry as RawMsgConnectionOpenTry, + client::v1::Height, connection::v1::MsgConnectionOpenTry as RawMsgConnectionOpenTry, }; use crate::{ core::{ ics03_connection::{ msgs::{ - conn_open_try::MsgConnectionOpenTry, - test_util::get_dummy_raw_counterparty, + conn_open_try::MsgConnectionOpenTry, test_util::get_dummy_raw_counterparty, }, version::get_compatible_versions, }, - ics24_host::identifier::{ - ClientId, - ConnectionId, - }, - }, - test_utils::{ - get_dummy_bech32_account, - get_dummy_proof, + ics24_host::identifier::{ClientId, ConnectionId}, }, + test_utils::{get_dummy_bech32_account, get_dummy_proof}, }; /// Testing-specific helper methods. @@ -273,17 +247,13 @@ mod tests { use ibc_proto::ibc::core::{ client::v1::Height, connection::v1::{ - Counterparty as RawCounterparty, - MsgConnectionOpenTry as RawMsgConnectionOpenTry, + Counterparty as RawCounterparty, MsgConnectionOpenTry as RawMsgConnectionOpenTry, }, }; use test_log::test; use crate::core::ics03_connection::msgs::{ - conn_open_try::{ - test_util::get_dummy_raw_msg_conn_open_try, - MsgConnectionOpenTry, - }, + conn_open_try::{test_util::get_dummy_raw_msg_conn_open_try, MsgConnectionOpenTry}, test_util::get_dummy_raw_counterparty, }; diff --git a/crates/relayer-types/src/core/ics03_connection/version.rs b/crates/relayer-types/src/core/ics03_connection/version.rs index d6f33bb8ce..c1bed7e360 100644 --- a/crates/relayer-types/src/core/ics03_connection/version.rs +++ b/crates/relayer-types/src/core/ics03_connection/version.rs @@ -1,19 +1,10 @@ use std::fmt::Display; -use ibc_proto::{ - ibc::core::connection::v1::Version as RawVersion, - Protobuf, -}; -use serde::{ - Deserialize, - Serialize, -}; +use ibc_proto::{ibc::core::connection::v1::Version as RawVersion, Protobuf}; +use serde::{Deserialize, Serialize}; use crate::{ - core::{ - ics03_connection::error::Error, - ics04_channel::channel::Ordering, - }, + core::{ics03_connection::error::Error, ics04_channel::channel::Ordering}, utils::pretty::PrettySlice, }; @@ -124,11 +115,7 @@ mod tests { use crate::core::ics03_connection::{ error::Error, - version::{ - get_compatible_versions, - pick_version, - Version, - }, + version::{get_compatible_versions, pick_version, Version}, }; fn good_versions() -> Vec { diff --git a/crates/relayer-types/src/core/ics04_channel/channel.rs b/crates/relayer-types/src/core/ics04_channel/channel.rs index 60998e4351..88d95fa85f 100644 --- a/crates/relayer-types/src/core/ics04_channel/channel.rs +++ b/crates/relayer-types/src/core/ics04_channel/channel.rs @@ -1,40 +1,20 @@ -use std::{ - fmt::{ - Display, - Error as FmtError, - Formatter, - }, - str::FromStr, -}; +use crate::utils::pretty::PrettySlice; -use ibc_proto::{ - ibc::core::channel::v1::{ - Channel as RawChannel, - Counterparty as RawCounterparty, - IdentifiedChannel as RawIdentifiedChannel, - }, - Protobuf, -}; -use serde::{ - Deserialize, - Serialize, -}; +use std::fmt::{Display, Error as FmtError, Formatter}; +use std::str::FromStr; + +use ibc_proto::Protobuf; +use serde::{Deserialize, Serialize}; -use crate::{ - core::{ - ics04_channel::{ - error::Error, - version::Version, - }, - ics24_host::identifier::{ - ChannelId, - ConnectionId, - PortId, - }, - }, - utils::pretty::PrettySlice, +use ibc_proto::ibc::core::channel::v1::{ + Channel as RawChannel, Counterparty as RawCounterparty, + IdentifiedChannel as RawIdentifiedChannel, }; +use crate::core::ics04_channel::packet::Sequence; +use crate::core::ics04_channel::{error::Error, version::Version}; +use crate::core::ics24_host::identifier::{ChannelId, ConnectionId, PortId}; + #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct IdentifiedChannelEnd { pub port_id: PortId, @@ -64,6 +44,7 @@ impl TryFrom for IdentifiedChannelEnd { counterparty: value.counterparty, connection_hops: value.connection_hops, version: value.version, + upgrade_sequence: value.upgrade_sequence, }; Ok(IdentifiedChannelEnd { @@ -77,7 +58,7 @@ impl TryFrom for IdentifiedChannelEnd { impl From for RawIdentifiedChannel { fn from(value: IdentifiedChannelEnd) -> Self { RawIdentifiedChannel { - state: value.channel_end.state as i32, + state: value.channel_end.state.as_i32(), ordering: value.channel_end.ordering as i32, counterparty: Some(value.channel_end.counterparty().clone().into()), connection_hops: value @@ -89,6 +70,7 @@ impl From for RawIdentifiedChannel { version: value.channel_end.version.to_string(), port_id: value.port_id.to_string(), channel_id: value.channel_id.to_string(), + upgrade_sequence: value.channel_end.upgrade_sequence.into(), } } } @@ -100,14 +82,15 @@ pub struct ChannelEnd { pub remote: Counterparty, pub connection_hops: Vec, pub version: Version, + pub upgrade_sequence: Sequence, } impl Display for ChannelEnd { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { write!( f, - "ChannelEnd {{ state: {}, ordering: {}, remote: {}, connection_hops: {}, version: {} }}", - self.state, self.ordering, self.remote, PrettySlice(&self.connection_hops), self.version + "ChannelEnd {{ state: {}, ordering: {}, remote: {}, connection_hops: {}, version: {}, upgrade_sequence: {} }}", + self.state, self.ordering, self.remote, PrettySlice(&self.connection_hops), self.version, self.upgrade_sequence ) } } @@ -120,6 +103,7 @@ impl Default for ChannelEnd { remote: Counterparty::default(), connection_hops: Vec::new(), version: Version::default(), + upgrade_sequence: Sequence::from(0), // The value of 0 indicates the channel has never been upgraded } } } @@ -160,6 +144,7 @@ impl TryFrom for ChannelEnd { remote, connection_hops, version, + value.upgrade_sequence.into(), )) } } @@ -167,7 +152,7 @@ impl TryFrom for ChannelEnd { impl From for RawChannel { fn from(value: ChannelEnd) -> Self { RawChannel { - state: value.state as i32, + state: value.state.as_i32(), ordering: value.ordering as i32, counterparty: Some(value.counterparty().clone().into()), connection_hops: value @@ -176,6 +161,7 @@ impl From for RawChannel { .map(|v| v.as_str().to_string()) .collect(), version: value.version.to_string(), + upgrade_sequence: value.upgrade_sequence.into(), } } } @@ -188,6 +174,7 @@ impl ChannelEnd { remote: Counterparty, connection_hops: Vec, version: Version, + upgrade_sequence: Sequence, ) -> Self { Self { state, @@ -195,6 +182,7 @@ impl ChannelEnd { remote, connection_hops, version, + upgrade_sequence, } } @@ -211,9 +199,11 @@ impl ChannelEnd { self.remote.channel_id = Some(c); } - /// Returns `true` if this `ChannelEnd` is in state [`State::Open`]. + /// Returns `true` if this `ChannelEnd` is in state [`State::Open`] + /// [`State::Open(UpgradeState::Upgrading)`] is only used in the channel upgrade + /// handshake so this method matches with [`State::Open(UpgradeState::NotUpgrading)`]. pub fn is_open(&self) -> bool { - self.state_matches(&State::Open) + self.state_matches(&State::Open(UpgradeState::NotUpgrading)) } pub fn state(&self) -> &State { @@ -248,25 +238,35 @@ impl ChannelEnd { /// Helper function to compare the state of this end with another state. pub fn state_matches(&self, other: &State) -> bool { - self.state.eq(other) + self.state() == other } /// Helper function to compare the order of this end with another order. pub fn order_matches(&self, other: &Ordering) -> bool { - self.ordering.eq(other) + self.ordering() == other } - #[allow(clippy::ptr_arg)] pub fn connection_hops_matches(&self, other: &Vec) -> bool { - self.connection_hops.eq(other) + self.connection_hops() == other } pub fn counterparty_matches(&self, other: &Counterparty) -> bool { - self.counterparty().eq(other) + self.counterparty() == other } pub fn version_matches(&self, other: &Version) -> bool { - self.version().eq(other) + self.version() == other + } + + /// Returns whether or not the channel with this state is + /// being upgraded. + pub fn is_upgrading(&self) -> bool { + use State::*; + + matches!( + self.state, + Open(UpgradeState::Upgrading) | Flushing | FlushComplete + ) } } @@ -392,13 +392,61 @@ impl FromStr for Ordering { } } +/// This enum is used to differentiate if a channel is being upgraded when +/// a `UpgradeInitChannel` or a `UpgradeOpenChannel` is received. +/// See `handshake_step` method in `crates/relayer/src/channel.rs`. #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub enum UpgradeState { + Upgrading, + NotUpgrading, +} + +/// The possible state variants that a channel can exhibit. +/// +/// These are encoded with integer discriminants so that there is +/// an easy way to compare channel states against one another. More +/// explicitly, this is an attempt to capture the lifecycle of a +/// channel, beginning from the `Uninitialized` state, through the +/// `Open` state, before finally being `Closed`. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize)] pub enum State { - Uninitialized = 0, - Init = 1, - TryOpen = 2, - Open = 3, - Closed = 4, + /// Default state + Uninitialized, + /// A channel has just started the opening handshake. + Init, + /// A channel has acknowledged the handshake step on the counterparty chain. + TryOpen, + /// A channel has completed the handshake step. Open channels are ready to + /// send and receive packets. + /// During some steps of channel upgrades, the state is still in Open. The + /// `UpgradeState` is used to differentiate these states during the upgrade + /// handshake. + /// + Open(UpgradeState), + /// A channel has been closed and can no longer be used to send or receive + /// packets. + Closed, + /// A channel has just accepted the upgrade handshake attempt and is flushing in-flight packets. + Flushing, + /// A channel has just completed flushing any in-flight packets. + FlushComplete, +} + +impl Serialize for State { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + match self { + Self::Uninitialized => serializer.serialize_str("Uninitialized"), + Self::Init => serializer.serialize_str("Init"), + Self::TryOpen => serializer.serialize_str("TryOpen"), + Self::Open(_) => serializer.serialize_str("Open"), + Self::Closed => serializer.serialize_str("Closed"), + Self::Flushing => serializer.serialize_str("Flushing"), + Self::FlushComplete => serializer.serialize_str("FlushComplete"), + } + } } impl State { @@ -408,8 +456,10 @@ impl State { Self::Uninitialized => "UNINITIALIZED", Self::Init => "INIT", Self::TryOpen => "TRYOPEN", - Self::Open => "OPEN", + Self::Open(_) => "OPEN", Self::Closed => "CLOSED", + Self::Flushing => "FLUSHING", + Self::FlushComplete => "FLUSHCOMPLETE", } } @@ -419,15 +469,30 @@ impl State { 0 => Ok(Self::Uninitialized), 1 => Ok(Self::Init), 2 => Ok(Self::TryOpen), - 3 => Ok(Self::Open), + 3 => Ok(Self::Open(UpgradeState::NotUpgrading)), 4 => Ok(Self::Closed), + 5 => Ok(Self::Flushing), + 6 => Ok(Self::FlushComplete), _ => Err(Error::unknown_state(s)), } } + // Parses the State out from a i32. + pub fn as_i32(&self) -> i32 { + match self { + State::Uninitialized => 0, + State::Init => 1, + State::TryOpen => 2, + State::Open(_) => 3, + State::Closed => 4, + State::Flushing => 5, + State::FlushComplete => 6, + } + } + /// Returns whether or not this channel state is `Open`. pub fn is_open(self) -> bool { - self == State::Open + self == State::Open(UpgradeState::NotUpgrading) } /// Returns whether or not this channel state is `Closed`. @@ -437,6 +502,7 @@ impl State { /// Returns whether or not the channel with this state /// has progressed less or the same than the argument. + /// This only takes into account the open channel handshake. /// /// # Example /// ```rust,ignore @@ -445,7 +511,16 @@ impl State { /// assert!(!State::Closed.less_or_equal_progress(State::Open)); /// ``` pub fn less_or_equal_progress(self, other: Self) -> bool { - self as u32 <= other as u32 + use State::*; + + match self { + Uninitialized => true, + + Init => !matches!(other, Uninitialized), + TryOpen => !matches!(other, Uninitialized | Init), + Open(UpgradeState::NotUpgrading) => !matches!(other, Uninitialized | Init | TryOpen), + _ => false, + } } } @@ -459,15 +534,10 @@ impl Display for State { #[cfg(test)] pub mod test_util { use ibc_proto::ibc::core::channel::v1::{ - Channel as RawChannel, - Counterparty as RawCounterparty, + Channel as RawChannel, Counterparty as RawCounterparty, }; - use crate::core::ics24_host::identifier::{ - ChannelId, - ConnectionId, - PortId, - }; + use crate::core::ics24_host::identifier::{ChannelId, ConnectionId, PortId}; /// Returns a dummy `RawCounterparty`, for testing only! /// Can be optionally parametrized with a specific channel identifier. @@ -486,6 +556,7 @@ pub mod test_util { counterparty: Some(get_dummy_raw_counterparty()), connection_hops: vec![ConnectionId::default().to_string()], version: "ics20".to_string(), // The version is not validated. + upgrade_sequence: 0, // The value of 0 indicates the channel has never been upgraded } } } @@ -498,10 +569,7 @@ mod tests { use ibc_proto::ibc::core::channel::v1::Channel as RawChannel; use test_log::test; - use crate::core::ics04_channel::channel::{ - test_util::get_dummy_raw_channel_end, - ChannelEnd, - }; + use crate::core::ics04_channel::channel::{test_util::get_dummy_raw_channel_end, ChannelEnd}; #[test] fn channel_end_try_from_raw() { @@ -628,4 +696,119 @@ mod tests { } } } + + #[test] + fn less_or_equal_progress_uninitialized() { + use crate::core::ics04_channel::channel::State; + use crate::core::ics04_channel::channel::UpgradeState; + + let higher_or_equal_states = vec![ + State::Uninitialized, + State::Init, + State::TryOpen, + State::Open(UpgradeState::NotUpgrading), + State::Open(UpgradeState::Upgrading), + State::Closed, + State::Flushing, + State::FlushComplete, + ]; + for state in higher_or_equal_states { + assert!(State::Uninitialized.less_or_equal_progress(state)) + } + } + + #[test] + fn less_or_equal_progress_init() { + use crate::core::ics04_channel::channel::State; + use crate::core::ics04_channel::channel::UpgradeState; + + let lower_states = vec![State::Uninitialized]; + let higher_or_equal_states = vec![ + State::Init, + State::TryOpen, + State::Open(UpgradeState::NotUpgrading), + State::Open(UpgradeState::Upgrading), + State::Closed, + State::Flushing, + State::FlushComplete, + ]; + for state in lower_states { + assert!(!State::Init.less_or_equal_progress(state)); + } + for state in higher_or_equal_states { + assert!(State::Init.less_or_equal_progress(state)) + } + } + + #[test] + fn less_or_equal_progress_tryopen() { + use crate::core::ics04_channel::channel::State; + use crate::core::ics04_channel::channel::UpgradeState; + + let lower_states = vec![State::Uninitialized, State::Init]; + let higher_or_equal_states = vec![ + State::TryOpen, + State::Open(UpgradeState::NotUpgrading), + State::Open(UpgradeState::Upgrading), + State::Closed, + State::Flushing, + State::FlushComplete, + ]; + for state in lower_states { + assert!(!State::TryOpen.less_or_equal_progress(state)); + } + for state in higher_or_equal_states { + assert!(State::TryOpen.less_or_equal_progress(state)) + } + } + + #[test] + fn less_or_equal_progress_open_not_upgrading() { + use crate::core::ics04_channel::channel::State; + use crate::core::ics04_channel::channel::UpgradeState; + + let lower_states = vec![State::Uninitialized, State::Init, State::TryOpen]; + let higher_or_equal_states = vec![ + State::Open(UpgradeState::NotUpgrading), + State::Open(UpgradeState::Upgrading), + State::Closed, + State::Flushing, + State::FlushComplete, + ]; + for state in lower_states { + assert!(!State::Open(UpgradeState::NotUpgrading).less_or_equal_progress(state)); + } + for state in higher_or_equal_states { + assert!(State::Open(UpgradeState::NotUpgrading).less_or_equal_progress(state)) + } + } + + #[test] + fn less_or_equal_progress_upgrading_states() { + use crate::core::ics04_channel::channel::State; + use crate::core::ics04_channel::channel::UpgradeState; + + let states = [ + State::Uninitialized, + State::Init, + State::TryOpen, + State::Open(UpgradeState::NotUpgrading), + State::Open(UpgradeState::Upgrading), + State::Closed, + State::Flushing, + State::FlushComplete, + ]; + + let upgrading_states = vec![ + State::Open(UpgradeState::Upgrading), + State::Closed, + State::Flushing, + State::FlushComplete, + ]; + for upgrade_state in upgrading_states { + for state in states.iter() { + assert!(!upgrade_state.less_or_equal_progress(*state)); + } + } + } } diff --git a/crates/relayer-types/src/core/ics04_channel/commitment.rs b/crates/relayer-types/src/core/ics04_channel/commitment.rs index 3ab3787d25..f3e3815240 100644 --- a/crates/relayer-types/src/core/ics04_channel/commitment.rs +++ b/crates/relayer-types/src/core/ics04_channel/commitment.rs @@ -1,7 +1,4 @@ -use serde_derive::{ - Deserialize, - Serialize, -}; +use serde_derive::{Deserialize, Serialize}; /// Packet commitment #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] diff --git a/crates/relayer-types/src/core/ics04_channel/error.rs b/crates/relayer-types/src/core/ics04_channel/error.rs index 3f80270d03..2555f88a7b 100644 --- a/crates/relayer-types/src/core/ics04_channel/error.rs +++ b/crates/relayer-types/src/core/ics04_channel/error.rs @@ -1,13 +1,8 @@ -use flex_error::{ - define_error, - TraceError, -}; +use flex_error::{define_error, TraceError}; +use itertools::Itertools; use tendermint_proto::Error as TendermintError; -use super::{ - packet::Sequence, - timeout::TimeoutHeight, -}; +use super::{packet::Sequence, timeout::TimeoutHeight}; use crate::{ core::{ ics02_client::error as client_error, @@ -15,12 +10,7 @@ use crate::{ ics04_channel::channel::State, ics24_host::{ error::ValidationError, - identifier::{ - ChannelId, - ClientId, - ConnectionId, - PortId, - }, + identifier::{ChannelId, ClientId, ConnectionId, PortId}, }, }, proofs::ProofError, @@ -40,6 +30,14 @@ define_error! { { state: i32 } | e | { format_args!("channel state unknown: {}", e.state) }, + UnknownFlushStatus + { state: i32 } + | e | { format_args!("flush status unknown: {}", e.state) }, + + UnknownFlushStatusType + { type_id: String } + | e | { format_args!("flush status unknown: {}", e.type_id) }, + Identifier [ ValidationError ] | _ | { "identifier error" }, @@ -68,6 +66,11 @@ define_error! { [ TraceError ] | _ | { "invalid version" }, + InvalidFlushStatus + { flush_status: i32 } + | e | { format_args!("invalid flush_status value: {}", e.flush_status) }, + + Signer [ SignerError ] | _ | { "invalid signer address" }, @@ -96,6 +99,10 @@ define_error! { InvalidTimeoutHeight | _ | { "invalid timeout height for the packet" }, + InvalidTimeoutTimestamp + [ crate::timestamp::ParseTimestampError ] + | _ | { "invalid timeout timestamp" }, + InvalidPacket | _ | { "invalid packet" }, @@ -109,11 +116,32 @@ define_error! { | _ | { "missing counterparty" }, NoCommonVersion - | _ | { "no commong version" }, + | _ | { "no common version" }, MissingChannel | _ | { "missing channel end" }, + MissingUpgradeTimeout + | _ | { "missing upgrade timeout, either a height or a timestamp must be set" }, + + MissingUpgrade + | _ | { "missing upgrade" }, + + MissingUpgradeFields + | _ | { "missing upgrade fields" }, + + MissingUpgradeErrorReceipt + | _ | { "missing upgrade error receipt" }, + + MissingProposedUpgradeChannel + | _ | { "missing proposed upgrade channel" }, + + MissingProofHeight + | _ | { "missing proof height" }, + + InvalidProofHeight + | _ | { "invalid proof height" }, + InvalidVersionLengthConnection | _ | { "single version must be negotiated on connection before opening channel" }, @@ -206,6 +234,22 @@ define_error! { e.given_sequence, e.next_sequence) }, + InvalidPacketData + { + data: String, + } + | e | { + format_args!("Invalid packet data, not a valid hex-encoded string: {}", e.data) + }, + + InvalidPacketAck + { + ack: String, + } + | e | { + format_args!("Invalid packet ack, not a valid hex-encoded string: {}", e.ack) + }, + LowPacketHeight { chain_height: Height, @@ -358,7 +402,25 @@ define_error! { AbciConversionFailed { abci_event: String } - | e | { format_args!("Failed to convert abci event to IbcEvent: {}", e.abci_event)} + | e | { format_args!("Failed to convert abci event to IbcEvent: {}", e.abci_event)}, + + ParseConnectionHopsVector + { failures: Vec<(String, ValidationError)> } + | e | { + let failures = e.failures + .iter() + .map(|(s, e)| format!("\"{}\": {}", s, e)) + .join(", "); + + format!("error parsing a vector of ConnectionId: {}", failures) + }, + + MalformedEventAttributeKey + | _ | { format_args!("event attribute key is not valid UTF-8") }, + + MalformedEventAttributeValue + { key: String } + | e | { format_args!("event attribute value for key {} is not valid UTF-8", e.key) }, } } diff --git a/crates/relayer-types/src/core/ics04_channel/events.rs b/crates/relayer-types/src/core/ics04_channel/events.rs index 2a4be81fd6..85e2493fe5 100644 --- a/crates/relayer-types/src/core/ics04_channel/events.rs +++ b/crates/relayer-types/src/core/ics04_channel/events.rs @@ -1,39 +1,19 @@ //! Types for the IBC events emitted from Tendermint Websocket by the channels module. -use std::{ - fmt::{ - Display, - Error as FmtError, - Formatter, - }, - str, -}; - -use serde_derive::{ - Deserialize, - Serialize, -}; +use std::fmt::{Display, Error as FmtError, Formatter}; +use std::str; + +use serde_derive::{Deserialize, Serialize}; use tendermint::abci; -use crate::{ - core::{ - ics04_channel::{ - error::Error, - packet::Packet, - }, - ics24_host::identifier::{ - ChannelId, - ConnectionId, - PortId, - }, - }, - events::{ - Error as EventError, - IbcEvent, - IbcEventType, - }, - utils::pretty::PrettySlice, -}; +use crate::core::ics02_client::height::Height; +use crate::core::ics04_channel::error::Error; +use crate::core::ics04_channel::packet::Packet; +use crate::core::ics04_channel::packet::Sequence; +use crate::core::ics24_host::identifier::{ChannelId, ConnectionId, PortId}; +use crate::events::{Error as EventError, IbcEvent, IbcEventType}; +use crate::timestamp::Timestamp; +use crate::utils::pretty::PrettySlice; /// Channel event attribute keys pub const CONNECTION_ID_ATTRIBUTE_KEY: &str = "connection_id"; @@ -44,14 +24,20 @@ pub const COUNTERPARTY_PORT_ID_ATTRIBUTE_KEY: &str = "counterparty_port_id"; /// Packet event attribute keys pub const PKT_SEQ_ATTRIBUTE_KEY: &str = "packet_sequence"; -pub const PKT_DATA_ATTRIBUTE_KEY: &str = "packet_data"; +pub const PKT_DATA_ATTRIBUTE_KEY: &str = "packet_data_hex"; pub const PKT_SRC_PORT_ATTRIBUTE_KEY: &str = "packet_src_port"; pub const PKT_SRC_CHANNEL_ATTRIBUTE_KEY: &str = "packet_src_channel"; pub const PKT_DST_PORT_ATTRIBUTE_KEY: &str = "packet_dst_port"; pub const PKT_DST_CHANNEL_ATTRIBUTE_KEY: &str = "packet_dst_channel"; pub const PKT_TIMEOUT_HEIGHT_ATTRIBUTE_KEY: &str = "packet_timeout_height"; pub const PKT_TIMEOUT_TIMESTAMP_ATTRIBUTE_KEY: &str = "packet_timeout_timestamp"; -pub const PKT_ACK_ATTRIBUTE_KEY: &str = "packet_ack"; +pub const PKT_ACK_ATTRIBUTE_KEY: &str = "packet_ack_hex"; + +/// Channel upgrade attribute keys +pub const UPGRADE_SEQUENCE: &str = "upgrade_sequence"; +pub const UPGRADE_TIMEOUT_HEIGHT: &str = "timeout_height"; +pub const UPGRADE_TIMEOUT_TIMESTAMP: &str = "timeout_timestamp"; +pub const UPGRADE_ERROR_RECEIPT: &str = "error_receipt"; #[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)] pub struct Attributes { @@ -108,10 +94,71 @@ impl From for Vec { } } +/// The attributes emitted by upon receiving a channel upgrade init message. +#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)] +pub struct UpgradeAttributes { + pub port_id: PortId, + pub channel_id: ChannelId, + pub counterparty_port_id: PortId, + pub counterparty_channel_id: Option, + pub upgrade_sequence: Sequence, + pub upgrade_timeout_height: Option, + pub upgrade_timeout_timestamp: Option, + pub error_receipt: Option, +} + +impl UpgradeAttributes { + pub fn port_id(&self) -> &PortId { + &self.port_id + } + pub fn channel_id(&self) -> &ChannelId { + &self.channel_id + } +} + +impl Display for UpgradeAttributes { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + if let Some(counterparty_channel_id) = &self.counterparty_channel_id { + write!(f, "UpgradeAttributes {{ port_id: {}, channel_id: {}, counterparty_port_id: {}, counterparty_channel_id: {counterparty_channel_id}, upgrade_connection_hops: [", self.port_id, self.channel_id, self.counterparty_port_id)?; + } else { + write!(f, "UpgradeAttributes {{ port_id: {}, channel_id: {}, counterparty_port_id: {}, counterparty_channel_id: None, upgrade_connection_hops: [", self.port_id, self.channel_id, self.counterparty_port_id)?; + } + write!(f, "], upgrade_sequence: {} }}", self.upgrade_sequence) + } +} pub trait EventType { fn event_type() -> IbcEventType; } +/// Convert channel upgrade attributes to Tendermint ABCI tags +impl From for Vec { + fn from(a: UpgradeAttributes) -> Self { + let mut attributes: Vec = vec![]; + + let port_id: abci::EventAttribute = (PORT_ID_ATTRIBUTE_KEY, a.port_id.as_str()).into(); + attributes.push(port_id); + + let channel_id: abci::EventAttribute = + (CHANNEL_ID_ATTRIBUTE_KEY, a.channel_id.as_str()).into(); + attributes.push(channel_id); + + let counterparty_port_id = ( + COUNTERPARTY_PORT_ID_ATTRIBUTE_KEY, + a.counterparty_port_id.as_str(), + ) + .into(); + + attributes.push(counterparty_port_id); + let channel_id = (COUNTERPARTY_CHANNEL_ID_ATTRIBUTE_KEY, a.channel_id.as_str()).into(); + attributes.push(channel_id); + + let upgrade_sequence = (UPGRADE_SEQUENCE, a.upgrade_sequence.to_string().as_str()).into(); + attributes.push(upgrade_sequence); + + attributes + } +} + #[derive(Clone, Debug, PartialEq, Eq, Serialize)] pub struct OpenInit { pub port_id: PortId, @@ -454,6 +501,663 @@ impl EventType for CloseConfirm { } } +#[derive(Clone, Debug, PartialEq, Eq, Serialize)] +pub struct UpgradeInit { + pub port_id: PortId, + pub channel_id: ChannelId, + pub counterparty_port_id: PortId, + pub counterparty_channel_id: Option, + pub upgrade_sequence: Sequence, +} + +impl Display for UpgradeInit { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + if let Some(counterparty_channel_id) = &self.counterparty_channel_id { + write!(f, "UpgradeAttributes {{ port_id: {}, channel_id: {}, counterparty_port_id: {}, counterparty_channel_id: {counterparty_channel_id}, upgrade_connection_hops: [", self.port_id, self.channel_id, self.counterparty_port_id)?; + } else { + write!(f, "UpgradeAttributes {{ port_id: {}, channel_id: {}, counterparty_port_id: {}, counterparty_channel_id: None, upgrade_connection_hops: [", self.port_id, self.channel_id, self.counterparty_port_id)?; + } + write!(f, "], upgrade_sequence: {} }}", self.upgrade_sequence) + } +} + +impl From for UpgradeAttributes { + fn from(ev: UpgradeInit) -> Self { + Self { + port_id: ev.port_id, + channel_id: ev.channel_id, + counterparty_port_id: ev.counterparty_port_id, + counterparty_channel_id: ev.counterparty_channel_id, + upgrade_sequence: ev.upgrade_sequence, + upgrade_timeout_height: None, + upgrade_timeout_timestamp: None, + error_receipt: None, + } + } +} + +impl UpgradeInit { + pub fn channel_id(&self) -> &ChannelId { + &self.channel_id + } + + pub fn port_id(&self) -> &PortId { + &self.port_id + } + + pub fn counterparty_port_id(&self) -> &PortId { + &self.counterparty_port_id + } + + pub fn counterparty_channel_id(&self) -> Option<&ChannelId> { + self.counterparty_channel_id.as_ref() + } +} + +impl TryFrom for UpgradeInit { + type Error = EventError; + + fn try_from(attrs: UpgradeAttributes) -> Result { + Ok(Self { + port_id: attrs.port_id, + channel_id: attrs.channel_id, + counterparty_port_id: attrs.counterparty_port_id, + counterparty_channel_id: attrs.counterparty_channel_id, + upgrade_sequence: attrs.upgrade_sequence, + }) + } +} + +impl From for IbcEvent { + fn from(v: UpgradeInit) -> Self { + IbcEvent::UpgradeInitChannel(v) + } +} + +impl EventType for UpgradeInit { + fn event_type() -> IbcEventType { + IbcEventType::UpgradeInitChannel + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize)] +pub struct UpgradeTry { + pub port_id: PortId, + pub channel_id: ChannelId, + pub counterparty_port_id: PortId, + pub counterparty_channel_id: Option, + pub upgrade_sequence: Sequence, +} + +impl Display for UpgradeTry { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + if let Some(counterparty_channel_id) = &self.counterparty_channel_id { + write!(f, "UpgradeAttributes {{ port_id: {}, channel_id: {}, counterparty_port_id: {}, counterparty_channel_id: {counterparty_channel_id}, upgrade_connection_hops: [", self.port_id, self.channel_id, self.counterparty_port_id)?; + } else { + write!(f, "UpgradeAttributes {{ port_id: {}, channel_id: {}, counterparty_port_id: {}, counterparty_channel_id: None, upgrade_connection_hops: [", self.port_id, self.channel_id, self.counterparty_port_id)?; + } + write!(f, "], upgrade_sequence: {} }}", self.upgrade_sequence) + } +} + +impl From for UpgradeAttributes { + fn from(ev: UpgradeTry) -> Self { + Self { + port_id: ev.port_id, + channel_id: ev.channel_id, + counterparty_port_id: ev.counterparty_port_id, + counterparty_channel_id: ev.counterparty_channel_id, + upgrade_sequence: ev.upgrade_sequence, + upgrade_timeout_height: None, + upgrade_timeout_timestamp: None, + error_receipt: None, + } + } +} + +impl UpgradeTry { + pub fn channel_id(&self) -> &ChannelId { + &self.channel_id + } + + pub fn port_id(&self) -> &PortId { + &self.port_id + } + + pub fn counterparty_port_id(&self) -> &PortId { + &self.counterparty_port_id + } + + pub fn counterparty_channel_id(&self) -> Option<&ChannelId> { + self.counterparty_channel_id.as_ref() + } +} + +impl TryFrom for UpgradeTry { + type Error = EventError; + + fn try_from(attrs: UpgradeAttributes) -> Result { + Ok(Self { + port_id: attrs.port_id, + channel_id: attrs.channel_id, + counterparty_port_id: attrs.counterparty_port_id, + counterparty_channel_id: attrs.counterparty_channel_id, + upgrade_sequence: attrs.upgrade_sequence, + }) + } +} + +impl From for IbcEvent { + fn from(v: UpgradeTry) -> Self { + IbcEvent::UpgradeTryChannel(v) + } +} + +impl EventType for UpgradeTry { + fn event_type() -> IbcEventType { + IbcEventType::UpgradeTryChannel + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize)] +pub struct UpgradeAck { + pub port_id: PortId, + pub channel_id: ChannelId, + pub counterparty_port_id: PortId, + pub counterparty_channel_id: Option, + pub upgrade_sequence: Sequence, +} + +impl Display for UpgradeAck { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + if let Some(counterparty_channel_id) = &self.counterparty_channel_id { + write!(f, "UpgradeAttributes {{ port_id: {}, channel_id: {}, counterparty_port_id: {}, counterparty_channel_id: {counterparty_channel_id}, upgrade_connection_hops: [", self.port_id, self.channel_id, self.counterparty_port_id)?; + } else { + write!(f, "UpgradeAttributes {{ port_id: {}, channel_id: {}, counterparty_port_id: {}, counterparty_channel_id: None, upgrade_connection_hops: [", self.port_id, self.channel_id, self.counterparty_port_id)?; + } + write!(f, "], upgrade_sequence: {} }}", self.upgrade_sequence) + } +} + +impl From for UpgradeAttributes { + fn from(ev: UpgradeAck) -> Self { + Self { + port_id: ev.port_id, + channel_id: ev.channel_id, + counterparty_port_id: ev.counterparty_port_id, + counterparty_channel_id: ev.counterparty_channel_id, + upgrade_sequence: ev.upgrade_sequence, + upgrade_timeout_height: None, + upgrade_timeout_timestamp: None, + error_receipt: None, + } + } +} + +impl UpgradeAck { + pub fn channel_id(&self) -> &ChannelId { + &self.channel_id + } + + pub fn port_id(&self) -> &PortId { + &self.port_id + } + + pub fn counterparty_port_id(&self) -> &PortId { + &self.counterparty_port_id + } + + pub fn counterparty_channel_id(&self) -> Option<&ChannelId> { + self.counterparty_channel_id.as_ref() + } +} + +impl TryFrom for UpgradeAck { + type Error = EventError; + + fn try_from(attrs: UpgradeAttributes) -> Result { + Ok(Self { + port_id: attrs.port_id, + channel_id: attrs.channel_id, + counterparty_port_id: attrs.counterparty_port_id, + counterparty_channel_id: attrs.counterparty_channel_id, + upgrade_sequence: attrs.upgrade_sequence, + }) + } +} + +impl From for IbcEvent { + fn from(v: UpgradeAck) -> Self { + IbcEvent::UpgradeAckChannel(v) + } +} + +impl EventType for UpgradeAck { + fn event_type() -> IbcEventType { + IbcEventType::UpgradeAckChannel + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize)] +pub struct UpgradeConfirm { + pub port_id: PortId, + pub channel_id: ChannelId, + pub counterparty_port_id: PortId, + pub counterparty_channel_id: Option, + pub upgrade_sequence: Sequence, +} + +impl Display for UpgradeConfirm { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + if let Some(counterparty_channel_id) = &self.counterparty_channel_id { + write!(f, "UpgradeAttributes {{ port_id: {}, channel_id: {}, counterparty_port_id: {}, counterparty_channel_id: {counterparty_channel_id}, upgrade_connection_hops: [", self.port_id, self.channel_id, self.counterparty_port_id)?; + } else { + write!(f, "UpgradeAttributes {{ port_id: {}, channel_id: {}, counterparty_port_id: {}, counterparty_channel_id: None, upgrade_connection_hops: [", self.port_id, self.channel_id, self.counterparty_port_id)?; + } + write!(f, "], upgrade_sequence: {} }}", self.upgrade_sequence) + } +} + +impl From for UpgradeAttributes { + fn from(ev: UpgradeConfirm) -> Self { + Self { + port_id: ev.port_id, + channel_id: ev.channel_id, + counterparty_port_id: ev.counterparty_port_id, + counterparty_channel_id: ev.counterparty_channel_id, + upgrade_sequence: ev.upgrade_sequence, + upgrade_timeout_height: None, + upgrade_timeout_timestamp: None, + error_receipt: None, + } + } +} + +impl UpgradeConfirm { + pub fn channel_id(&self) -> &ChannelId { + &self.channel_id + } + + pub fn port_id(&self) -> &PortId { + &self.port_id + } + + pub fn counterparty_port_id(&self) -> &PortId { + &self.counterparty_port_id + } + + pub fn counterparty_channel_id(&self) -> Option<&ChannelId> { + self.counterparty_channel_id.as_ref() + } +} + +impl TryFrom for UpgradeConfirm { + type Error = EventError; + + fn try_from(attrs: UpgradeAttributes) -> Result { + Ok(Self { + port_id: attrs.port_id, + channel_id: attrs.channel_id, + counterparty_port_id: attrs.counterparty_port_id, + counterparty_channel_id: attrs.counterparty_channel_id, + upgrade_sequence: attrs.upgrade_sequence, + }) + } +} + +impl From for IbcEvent { + fn from(v: UpgradeConfirm) -> Self { + IbcEvent::UpgradeConfirmChannel(v) + } +} + +impl EventType for UpgradeConfirm { + fn event_type() -> IbcEventType { + IbcEventType::UpgradeConfirmChannel + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize)] +pub struct UpgradeOpen { + pub port_id: PortId, + pub channel_id: ChannelId, + pub counterparty_port_id: PortId, + pub counterparty_channel_id: Option, + pub upgrade_sequence: Sequence, +} + +impl Display for UpgradeOpen { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + if let Some(counterparty_channel_id) = &self.counterparty_channel_id { + write!(f, "UpgradeAttributes {{ port_id: {}, channel_id: {}, counterparty_port_id: {}, counterparty_channel_id: {counterparty_channel_id}, upgrade_connection_hops: [", self.port_id, self.channel_id, self.counterparty_port_id)?; + } else { + write!(f, "UpgradeAttributes {{ port_id: {}, channel_id: {}, counterparty_port_id: {}, counterparty_channel_id: None, upgrade_connection_hops: [", self.port_id, self.channel_id, self.counterparty_port_id)?; + } + write!(f, "], upgrade_sequence: {} }}", self.upgrade_sequence) + } +} + +impl From for UpgradeAttributes { + fn from(ev: UpgradeOpen) -> Self { + Self { + port_id: ev.port_id, + channel_id: ev.channel_id, + counterparty_port_id: ev.counterparty_port_id, + counterparty_channel_id: ev.counterparty_channel_id, + upgrade_sequence: ev.upgrade_sequence, + upgrade_timeout_height: None, + upgrade_timeout_timestamp: None, + error_receipt: None, + } + } +} + +impl UpgradeOpen { + pub fn channel_id(&self) -> &ChannelId { + &self.channel_id + } + + pub fn port_id(&self) -> &PortId { + &self.port_id + } + + pub fn counterparty_port_id(&self) -> &PortId { + &self.counterparty_port_id + } + + pub fn counterparty_channel_id(&self) -> Option<&ChannelId> { + self.counterparty_channel_id.as_ref() + } +} + +impl TryFrom for UpgradeOpen { + type Error = EventError; + + fn try_from(attrs: UpgradeAttributes) -> Result { + Ok(Self { + port_id: attrs.port_id, + channel_id: attrs.channel_id, + counterparty_port_id: attrs.counterparty_port_id, + counterparty_channel_id: attrs.counterparty_channel_id, + upgrade_sequence: attrs.upgrade_sequence, + }) + } +} + +impl From for IbcEvent { + fn from(v: UpgradeOpen) -> Self { + IbcEvent::UpgradeOpenChannel(v) + } +} + +impl EventType for UpgradeOpen { + fn event_type() -> IbcEventType { + IbcEventType::UpgradeOpenChannel + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize)] +pub struct UpgradeCancel { + pub port_id: PortId, + pub channel_id: ChannelId, + pub counterparty_port_id: PortId, + pub counterparty_channel_id: Option, + pub upgrade_sequence: Sequence, +} + +impl Display for UpgradeCancel { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + if let Some(counterparty_channel_id) = &self.counterparty_channel_id { + write!(f, "UpgradeAttributes {{ port_id: {}, channel_id: {}, counterparty_port_id: {}, counterparty_channel_id: {counterparty_channel_id}, upgrade_connection_hops: [", self.port_id, self.channel_id, self.counterparty_port_id)?; + } else { + write!(f, "UpgradeAttributes {{ port_id: {}, channel_id: {}, counterparty_port_id: {}, counterparty_channel_id: None, upgrade_connection_hops: [", self.port_id, self.channel_id, self.counterparty_port_id)?; + } + write!(f, "], upgrade_sequence: {} }}", self.upgrade_sequence) + } +} + +impl From for UpgradeAttributes { + fn from(ev: UpgradeCancel) -> Self { + Self { + port_id: ev.port_id, + channel_id: ev.channel_id, + counterparty_port_id: ev.counterparty_port_id, + counterparty_channel_id: ev.counterparty_channel_id, + upgrade_sequence: ev.upgrade_sequence, + upgrade_timeout_height: None, + upgrade_timeout_timestamp: None, + error_receipt: None, + } + } +} + +impl UpgradeCancel { + pub fn channel_id(&self) -> &ChannelId { + &self.channel_id + } + + pub fn port_id(&self) -> &PortId { + &self.port_id + } + + pub fn counterparty_port_id(&self) -> &PortId { + &self.counterparty_port_id + } + + pub fn counterparty_channel_id(&self) -> Option<&ChannelId> { + self.counterparty_channel_id.as_ref() + } +} + +impl TryFrom for UpgradeCancel { + type Error = EventError; + + fn try_from(attrs: UpgradeAttributes) -> Result { + Ok(Self { + port_id: attrs.port_id, + channel_id: attrs.channel_id, + counterparty_port_id: attrs.counterparty_port_id, + counterparty_channel_id: attrs.counterparty_channel_id, + upgrade_sequence: attrs.upgrade_sequence, + }) + } +} + +impl From for IbcEvent { + fn from(v: UpgradeCancel) -> Self { + IbcEvent::UpgradeCancelChannel(v) + } +} + +impl EventType for UpgradeCancel { + fn event_type() -> IbcEventType { + IbcEventType::UpgradeCancelChannel + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize)] +pub struct UpgradeTimeout { + pub port_id: PortId, + pub channel_id: ChannelId, + pub counterparty_port_id: PortId, + pub counterparty_channel_id: Option, + pub upgrade_sequence: Sequence, + pub upgrade_timeout_height: Option, + pub upgrade_timeout_timestamp: Option, +} + +impl Display for UpgradeTimeout { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + if let Some(counterparty_channel_id) = &self.counterparty_channel_id { + write!(f, "UpgradeAttributes {{ port_id: {}, channel_id: {}, counterparty_port_id: {}, counterparty_channel_id: {counterparty_channel_id}, upgrade_connection_hops: [", self.port_id, self.channel_id, self.counterparty_port_id)?; + } else { + write!(f, "UpgradeAttributes {{ port_id: {}, channel_id: {}, counterparty_port_id: {}, counterparty_channel_id: None, upgrade_connection_hops: [", self.port_id, self.channel_id, self.counterparty_port_id)?; + } + + write!(f, "], upgrade_sequence: {}", self.upgrade_sequence)?; + + match (self.upgrade_timeout_height, self.upgrade_timeout_timestamp) { + (Some(height), Some(timestamp)) => write!( + f, + " timeout_height: {}, timeout_timestamp: {} }}", + height, timestamp + ), + (Some(height), None) => write!(f, " timeout_height: {} }}", height), + (None, Some(timestamp)) => write!(f, " timeout_timestamp: {} }}", timestamp), + (None, None) => write!(f, " }}"), + } + } +} + +impl From for UpgradeAttributes { + fn from(ev: UpgradeTimeout) -> Self { + Self { + port_id: ev.port_id, + channel_id: ev.channel_id, + counterparty_port_id: ev.counterparty_port_id, + counterparty_channel_id: ev.counterparty_channel_id, + upgrade_sequence: ev.upgrade_sequence, + upgrade_timeout_height: ev.upgrade_timeout_height, + upgrade_timeout_timestamp: ev.upgrade_timeout_timestamp, + error_receipt: None, + } + } +} + +impl UpgradeTimeout { + pub fn channel_id(&self) -> &ChannelId { + &self.channel_id + } + + pub fn port_id(&self) -> &PortId { + &self.port_id + } + + pub fn counterparty_port_id(&self) -> &PortId { + &self.counterparty_port_id + } + + pub fn counterparty_channel_id(&self) -> Option<&ChannelId> { + self.counterparty_channel_id.as_ref() + } +} + +impl TryFrom for UpgradeTimeout { + type Error = EventError; + + fn try_from(attrs: UpgradeAttributes) -> Result { + Ok(Self { + port_id: attrs.port_id, + channel_id: attrs.channel_id, + counterparty_port_id: attrs.counterparty_port_id, + counterparty_channel_id: attrs.counterparty_channel_id, + upgrade_sequence: attrs.upgrade_sequence, + upgrade_timeout_height: attrs.upgrade_timeout_height, + upgrade_timeout_timestamp: attrs.upgrade_timeout_timestamp, + }) + } +} + +impl From for IbcEvent { + fn from(v: UpgradeTimeout) -> Self { + IbcEvent::UpgradeTimeoutChannel(v) + } +} + +impl EventType for UpgradeTimeout { + fn event_type() -> IbcEventType { + IbcEventType::UpgradeTimeoutChannel + } +} +// + +#[derive(Clone, Debug, PartialEq, Eq, Serialize)] +pub struct UpgradeError { + pub port_id: PortId, + pub channel_id: ChannelId, + pub counterparty_port_id: PortId, + pub counterparty_channel_id: Option, + pub upgrade_sequence: Sequence, + pub error_receipt: String, +} + +impl Display for UpgradeError { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + if let Some(counterparty_channel_id) = &self.counterparty_channel_id { + write!(f, "UpgradeAttributes {{ port_id: {}, channel_id: {}, counterparty_port_id: {}, counterparty_channel_id: {counterparty_channel_id}, upgrade_connection_hops: [", self.port_id, self.channel_id, self.counterparty_port_id)?; + } else { + write!(f, "UpgradeAttributes {{ port_id: {}, channel_id: {}, counterparty_port_id: {}, counterparty_channel_id: None, upgrade_connection_hops: [", self.port_id, self.channel_id, self.counterparty_port_id)?; + } + + write!( + f, + "], upgrade_sequence: {}, error_receipt: {} }}", + self.upgrade_sequence, self.error_receipt + ) + } +} + +impl From for UpgradeAttributes { + fn from(ev: UpgradeError) -> Self { + Self { + port_id: ev.port_id, + channel_id: ev.channel_id, + counterparty_port_id: ev.counterparty_port_id, + counterparty_channel_id: ev.counterparty_channel_id, + upgrade_sequence: ev.upgrade_sequence, + upgrade_timeout_height: None, + upgrade_timeout_timestamp: None, + error_receipt: Some(ev.error_receipt), + } + } +} + +impl UpgradeError { + pub fn channel_id(&self) -> &ChannelId { + &self.channel_id + } + + pub fn port_id(&self) -> &PortId { + &self.port_id + } + + pub fn counterparty_port_id(&self) -> &PortId { + &self.counterparty_port_id + } + + pub fn counterparty_channel_id(&self) -> Option<&ChannelId> { + self.counterparty_channel_id.as_ref() + } +} + +impl TryFrom for UpgradeError { + type Error = EventError; + + fn try_from(attrs: UpgradeAttributes) -> Result { + let error_receipt = attrs.error_receipt.unwrap_or_default(); + Ok(Self { + port_id: attrs.port_id, + channel_id: attrs.channel_id, + counterparty_port_id: attrs.counterparty_port_id, + counterparty_channel_id: attrs.counterparty_channel_id, + upgrade_sequence: attrs.upgrade_sequence, + error_receipt, + }) + } +} + +impl From for IbcEvent { + fn from(v: UpgradeError) -> Self { + IbcEvent::UpgradeErrorChannel(v) + } +} + +impl EventType for UpgradeError { + fn event_type() -> IbcEventType { + IbcEventType::UpgradeErrorChannel + } +} + macro_rules! impl_try_from_attribute_for_event { ($($event:ty),+) => { $(impl TryFrom for $event { diff --git a/crates/relayer-types/src/core/ics04_channel/mod.rs b/crates/relayer-types/src/core/ics04_channel/mod.rs index 21d1378da6..018a0608de 100644 --- a/crates/relayer-types/src/core/ics04_channel/mod.rs +++ b/crates/relayer-types/src/core/ics04_channel/mod.rs @@ -9,4 +9,6 @@ pub mod msgs; pub mod packet; pub mod packet_id; pub mod timeout; +pub mod upgrade; +pub mod upgrade_fields; pub mod version; diff --git a/crates/relayer-types/src/core/ics04_channel/msgs.rs b/crates/relayer-types/src/core/ics04_channel/msgs.rs index ac1c8329c1..b57d59021f 100644 --- a/crates/relayer-types/src/core/ics04_channel/msgs.rs +++ b/crates/relayer-types/src/core/ics04_channel/msgs.rs @@ -2,15 +2,10 @@ //! as packets. use crate::core::ics04_channel::msgs::{ - acknowledgement::MsgAcknowledgement, - chan_close_confirm::MsgChannelCloseConfirm, - chan_close_init::MsgChannelCloseInit, - chan_open_ack::MsgChannelOpenAck, - chan_open_confirm::MsgChannelOpenConfirm, - chan_open_init::MsgChannelOpenInit, - chan_open_try::MsgChannelOpenTry, - recv_packet::MsgRecvPacket, - timeout::MsgTimeout, + acknowledgement::MsgAcknowledgement, chan_close_confirm::MsgChannelCloseConfirm, + chan_close_init::MsgChannelCloseInit, chan_open_ack::MsgChannelOpenAck, + chan_open_confirm::MsgChannelOpenConfirm, chan_open_init::MsgChannelOpenInit, + chan_open_try::MsgChannelOpenTry, recv_packet::MsgRecvPacket, timeout::MsgTimeout, timeout_on_close::MsgTimeoutOnClose, }; @@ -24,6 +19,15 @@ pub mod chan_open_try; pub mod chan_close_confirm; pub mod chan_close_init; +// Upgrade handshake messages. +pub mod chan_upgrade_ack; +pub mod chan_upgrade_cancel; +pub mod chan_upgrade_confirm; +pub mod chan_upgrade_init; +pub mod chan_upgrade_open; +pub mod chan_upgrade_timeout; +pub mod chan_upgrade_try; + // Packet specific messages. pub mod acknowledgement; pub mod recv_packet; 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 5bf862b732..7d81455c33 100644 --- a/crates/relayer-types/src/core/ics04_channel/msgs/acknowledgement.rs +++ b/crates/relayer-types/src/core/ics04_channel/msgs/acknowledgement.rs @@ -1,17 +1,8 @@ -use derive_more::{ - From, - Into, -}; -use ibc_proto::{ - ibc::core::channel::v1::MsgAcknowledgement as RawMsgAcknowledgement, - Protobuf, -}; +use derive_more::{From, Into}; +use ibc_proto::{ibc::core::channel::v1::MsgAcknowledgement as RawMsgAcknowledgement, Protobuf}; use crate::{ - core::ics04_channel::{ - error::Error, - packet::Packet, - }, + core::ics04_channel::{error::Error, packet::Packet}, proofs::Proofs, signer::Signer, tx_msg::Msg, @@ -132,19 +123,13 @@ impl From for RawMsgAcknowledgement { #[cfg(test)] pub mod test_util { use ibc_proto::ibc::core::{ - channel::v1::{ - MsgAcknowledgement as RawMsgAcknowledgement, - Packet as RawPacket, - }, + channel::v1::{MsgAcknowledgement as RawMsgAcknowledgement, Packet as RawPacket}, client::v1::Height as RawHeight, }; use crate::{ core::ics04_channel::packet::test_utils::get_dummy_raw_packet, - test_utils::{ - get_dummy_bech32_account, - get_dummy_proof, - }, + test_utils::{get_dummy_bech32_account, get_dummy_proof}, }; /// Returns a dummy `RawMsgAcknowledgement`, for testing only! @@ -180,8 +165,7 @@ mod test { core::ics04_channel::{ error::Error, msgs::acknowledgement::{ - test_util::get_dummy_raw_msg_acknowledgement, - MsgAcknowledgement, + test_util::get_dummy_raw_msg_acknowledgement, MsgAcknowledgement, }, }, test_utils::get_dummy_bech32_account, 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 0ffc52eb1e..d0b3cd39d4 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,20 +1,13 @@ use ibc_proto::{ - ibc::core::channel::v1::MsgChannelCloseConfirm as RawMsgChannelCloseConfirm, - Protobuf, + ibc::core::channel::v1::MsgChannelCloseConfirm as RawMsgChannelCloseConfirm, Protobuf, }; -use crate::{ - core::{ - ics04_channel::error::Error, - ics24_host::identifier::{ - ChannelId, - PortId, - }, - }, - proofs::Proofs, - signer::Signer, - tx_msg::Msg, -}; +use crate::core::ics04_channel::error::Error; +use crate::core::ics04_channel::packet::Sequence; +use crate::core::ics24_host::identifier::{ChannelId, PortId}; +use crate::proofs::Proofs; +use crate::signer::Signer; +use crate::tx_msg::Msg; pub const TYPE_URL: &str = "/ibc.core.channel.v1.MsgChannelCloseConfirm"; @@ -28,6 +21,7 @@ pub struct MsgChannelCloseConfirm { pub channel_id: ChannelId, pub proofs: Proofs, pub signer: Signer, + pub counterparty_upgrade_sequence: Sequence, } impl MsgChannelCloseConfirm { @@ -37,6 +31,7 @@ impl MsgChannelCloseConfirm { channel_id, proofs, signer, + counterparty_upgrade_sequence: Sequence::from(0), } } } @@ -81,6 +76,7 @@ impl TryFrom for MsgChannelCloseConfirm { channel_id: raw_msg.channel_id.parse().map_err(Error::identifier)?, proofs, signer: raw_msg.signer.parse().map_err(Error::signer)?, + counterparty_upgrade_sequence: raw_msg.counterparty_upgrade_sequence.into(), }) } } @@ -93,6 +89,7 @@ impl From for RawMsgChannelCloseConfirm { proof_init: domain_msg.proofs.object_proof().clone().into(), proof_height: Some(domain_msg.proofs.height().into()), signer: domain_msg.signer.to_string(), + counterparty_upgrade_sequence: domain_msg.counterparty_upgrade_sequence.into(), } } } @@ -101,19 +98,12 @@ impl From for RawMsgChannelCloseConfirm { pub mod test_util { use ibc_proto::ibc::core::{ - channel::v1::MsgChannelCloseConfirm as RawMsgChannelCloseConfirm, - client::v1::Height, + channel::v1::MsgChannelCloseConfirm as RawMsgChannelCloseConfirm, client::v1::Height, }; use crate::{ - core::ics24_host::identifier::{ - ChannelId, - PortId, - }, - test_utils::{ - get_dummy_bech32_account, - get_dummy_proof, - }, + core::ics24_host::identifier::{ChannelId, PortId}, + test_utils::{get_dummy_bech32_account, get_dummy_proof}, }; /// Returns a dummy `RawMsgChannelCloseConfirm`, for testing only! @@ -127,6 +117,7 @@ pub mod test_util { revision_height: proof_height, }), signer: get_dummy_bech32_account(), + counterparty_upgrade_sequence: 0, } } } @@ -135,13 +126,11 @@ pub mod test_util { mod tests { use ibc_proto::ibc::core::{ - channel::v1::MsgChannelCloseConfirm as RawMsgChannelCloseConfirm, - client::v1::Height, + channel::v1::MsgChannelCloseConfirm as RawMsgChannelCloseConfirm, client::v1::Height, }; use crate::core::ics04_channel::msgs::chan_close_confirm::{ - test_util::get_dummy_raw_msg_chan_close_confirm, - MsgChannelCloseConfirm, + test_util::get_dummy_raw_msg_chan_close_confirm, MsgChannelCloseConfirm, }; #[test] 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 6c466af635..9832bc8cd7 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,15 +1,9 @@ -use ibc_proto::{ - ibc::core::channel::v1::MsgChannelCloseInit as RawMsgChannelCloseInit, - Protobuf, -}; +use ibc_proto::{ibc::core::channel::v1::MsgChannelCloseInit as RawMsgChannelCloseInit, Protobuf}; use crate::{ core::{ ics04_channel::error::Error, - ics24_host::identifier::{ - ChannelId, - PortId, - }, + ics24_host::identifier::{ChannelId, PortId}, }, signer::Signer, tx_msg::Msg, @@ -17,9 +11,7 @@ use crate::{ pub const TYPE_URL: &str = "/ibc.core.channel.v1.MsgChannelCloseInit"; -/// /// Message definition for the first step in the channel close handshake (`ChanCloseInit` datagram). -/// #[derive(Clone, Debug, PartialEq, Eq)] pub struct MsgChannelCloseInit { pub port_id: PortId, @@ -80,10 +72,7 @@ pub mod test_util { use ibc_proto::ibc::core::channel::v1::MsgChannelCloseInit as RawMsgChannelCloseInit; use crate::{ - core::ics24_host::identifier::{ - ChannelId, - PortId, - }, + core::ics24_host::identifier::{ChannelId, PortId}, test_utils::get_dummy_bech32_account, }; @@ -104,8 +93,7 @@ mod tests { use test_log::test; use crate::core::ics04_channel::msgs::chan_close_init::{ - test_util::get_dummy_raw_msg_chan_close_init, - MsgChannelCloseInit, + test_util::get_dummy_raw_msg_chan_close_init, MsgChannelCloseInit, }; #[test] 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 506202a8ee..e160657bd1 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 @@ -1,18 +1,9 @@ -use ibc_proto::{ - ibc::core::channel::v1::MsgChannelOpenAck as RawMsgChannelOpenAck, - Protobuf, -}; +use ibc_proto::{ibc::core::channel::v1::MsgChannelOpenAck as RawMsgChannelOpenAck, Protobuf}; use crate::{ core::{ - ics04_channel::{ - error::Error, - version::Version, - }, - ics24_host::identifier::{ - ChannelId, - PortId, - }, + ics04_channel::{error::Error, version::Version}, + ics24_host::identifier::{ChannelId, PortId}, }, proofs::Proofs, signer::Signer, @@ -118,19 +109,12 @@ impl From for RawMsgChannelOpenAck { pub mod test_util { use ibc_proto::ibc::core::{ - channel::v1::MsgChannelOpenAck as RawMsgChannelOpenAck, - client::v1::Height, + channel::v1::MsgChannelOpenAck as RawMsgChannelOpenAck, client::v1::Height, }; use crate::{ - core::ics24_host::identifier::{ - ChannelId, - PortId, - }, - test_utils::{ - get_dummy_bech32_account, - get_dummy_proof, - }, + core::ics24_host::identifier::{ChannelId, PortId}, + test_utils::{get_dummy_bech32_account, get_dummy_proof}, }; /// Returns a dummy `RawMsgChannelOpenAck`, for testing only! @@ -154,14 +138,12 @@ pub mod test_util { mod tests { use ibc_proto::ibc::core::{ - channel::v1::MsgChannelOpenAck as RawMsgChannelOpenAck, - client::v1::Height, + channel::v1::MsgChannelOpenAck as RawMsgChannelOpenAck, client::v1::Height, }; use test_log::test; use crate::core::ics04_channel::msgs::chan_open_ack::{ - test_util::get_dummy_raw_msg_chan_open_ack, - MsgChannelOpenAck, + test_util::get_dummy_raw_msg_chan_open_ack, MsgChannelOpenAck, }; #[test] 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 aa55544123..733a50808f 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 @@ -1,15 +1,11 @@ use ibc_proto::{ - ibc::core::channel::v1::MsgChannelOpenConfirm as RawMsgChannelOpenConfirm, - Protobuf, + ibc::core::channel::v1::MsgChannelOpenConfirm as RawMsgChannelOpenConfirm, Protobuf, }; use crate::{ core::{ ics04_channel::error::Error, - ics24_host::identifier::{ - ChannelId, - PortId, - }, + ics24_host::identifier::{ChannelId, PortId}, }, proofs::Proofs, signer::Signer, @@ -98,19 +94,12 @@ impl From for RawMsgChannelOpenConfirm { pub mod test_util { use ibc_proto::ibc::core::{ - channel::v1::MsgChannelOpenConfirm as RawMsgChannelOpenConfirm, - client::v1::Height, + channel::v1::MsgChannelOpenConfirm as RawMsgChannelOpenConfirm, client::v1::Height, }; use crate::{ - core::ics24_host::identifier::{ - ChannelId, - PortId, - }, - test_utils::{ - get_dummy_bech32_account, - get_dummy_proof, - }, + core::ics24_host::identifier::{ChannelId, PortId}, + test_utils::{get_dummy_bech32_account, get_dummy_proof}, }; /// Returns a dummy `RawMsgChannelOpenConfirm`, for testing only! @@ -132,14 +121,12 @@ pub mod test_util { mod tests { use ibc_proto::ibc::core::{ - channel::v1::MsgChannelOpenConfirm as RawMsgChannelOpenConfirm, - client::v1::Height, + channel::v1::MsgChannelOpenConfirm as RawMsgChannelOpenConfirm, client::v1::Height, }; use test_log::test; use crate::core::ics04_channel::msgs::chan_open_confirm::{ - test_util::get_dummy_raw_msg_chan_open_confirm, - MsgChannelOpenConfirm, + test_util::get_dummy_raw_msg_chan_open_confirm, MsgChannelOpenConfirm, }; #[test] 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 0cf1ffe4a3..8beb3299db 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 @@ -1,14 +1,8 @@ -use ibc_proto::{ - ibc::core::channel::v1::MsgChannelOpenInit as RawMsgChannelOpenInit, - Protobuf, -}; +use ibc_proto::{ibc::core::channel::v1::MsgChannelOpenInit as RawMsgChannelOpenInit, Protobuf}; use crate::{ core::{ - ics04_channel::{ - channel::ChannelEnd, - error::Error, - }, + ics04_channel::{channel::ChannelEnd, error::Error}, ics24_host::identifier::PortId, }, signer::Signer, @@ -17,9 +11,7 @@ use crate::{ pub const TYPE_URL: &str = "/ibc.core.channel.v1.MsgChannelOpenInit"; -/// /// Message definition for the first step in the channel open handshake (`ChanOpenInit` datagram). -/// #[derive(Clone, Debug, PartialEq, Eq)] pub struct MsgChannelOpenInit { pub port_id: PortId, @@ -106,8 +98,7 @@ mod tests { use test_log::test; use crate::core::ics04_channel::msgs::chan_open_init::{ - test_util::get_dummy_raw_msg_chan_open_init, - MsgChannelOpenInit, + test_util::get_dummy_raw_msg_chan_open_init, MsgChannelOpenInit, }; #[test] 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 3be9608b72..2a83658433 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 @@ -1,35 +1,20 @@ -use core::str::FromStr; +use crate::core::ics04_channel::channel::ChannelEnd; +use crate::core::ics04_channel::error::Error as ChannelError; +use crate::core::ics04_channel::version::Version; +use crate::core::ics24_host::identifier::{ChannelId, PortId}; -use ibc_proto::{ - ibc::core::channel::v1::MsgChannelOpenTry as RawMsgChannelOpenTry, - Protobuf, -}; +use crate::proofs::Proofs; +use crate::signer::Signer; +use crate::tx_msg::Msg; -use crate::{ - core::{ - ics04_channel::{ - channel::ChannelEnd, - error::Error as ChannelError, - version::Version, - }, - ics24_host::{ - error::ValidationError, - identifier::{ - ChannelId, - PortId, - }, - }, - }, - proofs::Proofs, - signer::Signer, - tx_msg::Msg, -}; +use ibc_proto::ibc::core::channel::v1::MsgChannelOpenTry as RawMsgChannelOpenTry; +use ibc_proto::Protobuf; + +use core::str::FromStr; pub const TYPE_URL: &str = "/ibc.core.channel.v1.MsgChannelOpenTry"; -/// /// Message definition for the second step in the channel open handshake (`ChanOpenTry` datagram). -/// #[derive(Clone, Debug, PartialEq, Eq)] pub struct MsgChannelOpenTry { pub port_id: PortId, @@ -71,13 +56,6 @@ impl Msg for MsgChannelOpenTry { fn type_url(&self) -> String { TYPE_URL.to_string() } - - fn validate_basic(&self) -> Result<(), ValidationError> { - match self.channel.counterparty().channel_id() { - None => Err(ValidationError::invalid_counterparty_channel_id()), - Some(_c) => Ok(()), - } - } } impl Protobuf for MsgChannelOpenTry {} @@ -109,21 +87,25 @@ impl TryFrom for MsgChannelOpenTry { .transpose() .map_err(ChannelError::identifier)?; + let channel: ChannelEnd = raw_msg + .channel + .ok_or_else(ChannelError::missing_channel)? + .try_into()?; + + assert!( + channel.counterparty().channel_id().is_some(), + "Expected counterparty channel to have a channel ID" + ); + let msg = MsgChannelOpenTry { port_id: raw_msg.port_id.parse().map_err(ChannelError::identifier)?, previous_channel_id, - channel: raw_msg - .channel - .ok_or_else(ChannelError::missing_channel)? - .try_into()?, + channel, counterparty_version: raw_msg.counterparty_version.into(), proofs, signer: raw_msg.signer.parse().map_err(ChannelError::signer)?, }; - msg.validate_basic() - .map_err(ChannelError::invalid_counterparty_channel_id)?; - Ok(msg) } } @@ -149,22 +131,15 @@ impl From for RawMsgChannelOpenTry { pub mod test_util { use ibc_proto::ibc::core::{ - channel::v1::MsgChannelOpenTry as RawMsgChannelOpenTry, - client::v1::Height, + channel::v1::MsgChannelOpenTry as RawMsgChannelOpenTry, client::v1::Height, }; use crate::{ core::{ ics04_channel::channel::test_util::get_dummy_raw_channel_end, - ics24_host::identifier::{ - ChannelId, - PortId, - }, - }, - test_utils::{ - get_dummy_bech32_account, - get_dummy_proof, + ics24_host::identifier::{ChannelId, PortId}, }, + test_utils::{get_dummy_bech32_account, get_dummy_proof}, }; /// Returns a dummy `RawMsgChannelOpenTry`, for testing only! @@ -188,14 +163,12 @@ pub mod test_util { #[cfg(test)] mod tests { use ibc_proto::ibc::core::{ - channel::v1::MsgChannelOpenTry as RawMsgChannelOpenTry, - client::v1::Height, + channel::v1::MsgChannelOpenTry as RawMsgChannelOpenTry, client::v1::Height, }; use test_log::test; use crate::core::ics04_channel::msgs::chan_open_try::{ - test_util::get_dummy_raw_msg_chan_open_try, - MsgChannelOpenTry, + test_util::get_dummy_raw_msg_chan_open_try, MsgChannelOpenTry, }; #[test] diff --git a/crates/relayer-types/src/core/ics04_channel/msgs/chan_upgrade_ack.rs b/crates/relayer-types/src/core/ics04_channel/msgs/chan_upgrade_ack.rs new file mode 100644 index 0000000000..3b92cb7db0 --- /dev/null +++ b/crates/relayer-types/src/core/ics04_channel/msgs/chan_upgrade_ack.rs @@ -0,0 +1,249 @@ +use ibc_proto::ibc::core::channel::v1::MsgChannelUpgradeAck as RawMsgChannelUpgradeAck; +use ibc_proto::Protobuf; + +use crate::core::ics04_channel::error::Error; +use crate::core::ics04_channel::upgrade::Upgrade; +use crate::core::ics23_commitment::commitment::CommitmentProofBytes; +use crate::core::ics24_host::identifier::{ChannelId, PortId}; +use crate::signer::Signer; +use crate::tx_msg::Msg; +use crate::Height; + +pub const TYPE_URL: &str = "/ibc.core.channel.v1.MsgChannelUpgradeAck"; + +/// Message definition for the third step of the channel upgrade +/// handshake (the `ChanUpgradeAck` datagram). +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct MsgChannelUpgradeAck { + pub port_id: PortId, + pub channel_id: ChannelId, + pub counterparty_upgrade: Upgrade, + /// The proof of the counterparty channel + pub proof_channel: CommitmentProofBytes, + /// The proof of the counterparty upgrade + pub proof_upgrade: CommitmentProofBytes, + /// The height at which the proofs were queried. + pub proof_height: Height, + pub signer: Signer, +} + +impl MsgChannelUpgradeAck { + #[allow(clippy::too_many_arguments)] + pub fn new( + port_id: PortId, + channel_id: ChannelId, + counterparty_upgrade: Upgrade, + proof_channel: CommitmentProofBytes, + proof_upgrade: CommitmentProofBytes, + proof_height: Height, + signer: Signer, + ) -> Self { + Self { + port_id, + channel_id, + counterparty_upgrade, + proof_channel, + proof_upgrade, + proof_height, + signer, + } + } +} + +impl Msg for MsgChannelUpgradeAck { + type ValidationError = Error; + type Raw = RawMsgChannelUpgradeAck; + + fn route(&self) -> String { + crate::keys::ROUTER_KEY.to_string() + } + + fn type_url(&self) -> String { + TYPE_URL.to_string() + } +} + +impl Protobuf for MsgChannelUpgradeAck {} + +impl TryFrom for MsgChannelUpgradeAck { + type Error = Error; + + fn try_from(raw_msg: RawMsgChannelUpgradeAck) -> Result { + let counterparty_upgrade = raw_msg + .counterparty_upgrade + .ok_or(Error::missing_upgrade())? + .try_into()?; + + let proof_height = raw_msg + .proof_height + .ok_or_else(Error::missing_proof_height)? + .try_into() + .map_err(|_| Error::invalid_proof_height())?; + + Ok(MsgChannelUpgradeAck { + port_id: raw_msg.port_id.parse().map_err(Error::identifier)?, + channel_id: raw_msg.channel_id.parse().map_err(Error::identifier)?, + counterparty_upgrade, + proof_channel: raw_msg + .proof_channel + .try_into() + .map_err(Error::invalid_proof)?, + proof_upgrade: raw_msg + .proof_upgrade + .try_into() + .map_err(Error::invalid_proof)?, + proof_height, + signer: raw_msg.signer.parse().map_err(Error::signer)?, + }) + } +} + +impl From for RawMsgChannelUpgradeAck { + fn from(domain_msg: MsgChannelUpgradeAck) -> Self { + RawMsgChannelUpgradeAck { + port_id: domain_msg.port_id.to_string(), + channel_id: domain_msg.channel_id.to_string(), + counterparty_upgrade: Some(domain_msg.counterparty_upgrade.into()), + proof_upgrade: domain_msg.proof_upgrade.into(), + proof_channel: domain_msg.proof_channel.into(), + proof_height: Some(domain_msg.proof_height.into()), + signer: domain_msg.signer.to_string(), + } + } +} + +#[cfg(test)] +pub mod test_util { + use ibc_proto::ibc::core::channel::v1::MsgChannelUpgradeAck as RawMsgChannelUpgradeAck; + use ibc_proto::ibc::core::client::v1::Height as RawHeight; + + use crate::core::ics04_channel::upgrade::test_util::get_dummy_upgrade; + use crate::core::ics24_host::identifier::{ChannelId, PortId}; + use crate::test_utils::{get_dummy_bech32_account, get_dummy_proof}; + + /// Returns a dummy `RawMsgChannelUpgradeAck`, for testing only! + pub fn get_dummy_raw_msg_chan_upgrade_ack() -> RawMsgChannelUpgradeAck { + RawMsgChannelUpgradeAck { + port_id: PortId::default().to_string(), + channel_id: ChannelId::default().to_string(), + counterparty_upgrade: Some(get_dummy_upgrade()), + proof_upgrade: get_dummy_proof(), + proof_channel: get_dummy_proof(), + proof_height: Some(RawHeight { + revision_number: 1, + revision_height: 1, + }), + signer: get_dummy_bech32_account(), + } + } +} + +#[cfg(test)] +mod tests { + use test_log::test; + + use ibc_proto::ibc::core::channel::v1::MsgChannelUpgradeAck as RawMsgChannelUpgradeAck; + + use crate::core::ics04_channel::msgs::chan_upgrade_ack::test_util::get_dummy_raw_msg_chan_upgrade_ack; + use crate::core::ics04_channel::msgs::chan_upgrade_ack::MsgChannelUpgradeAck; + + #[test] + fn parse_channel_upgrade_try_msg() { + struct Test { + name: String, + raw: RawMsgChannelUpgradeAck, + want_pass: bool, + } + + let default_raw_msg = get_dummy_raw_msg_chan_upgrade_ack(); + + let tests: Vec = vec![ + Test { + name: "Good parameters".to_string(), + raw: default_raw_msg.clone(), + want_pass: true, + }, + Test { + name: "Correct port ID".to_string(), + raw: RawMsgChannelUpgradeAck { + port_id: "p36".to_string(), + ..default_raw_msg.clone() + }, + want_pass: true, + }, + Test { + name: "Port too short".to_string(), + raw: RawMsgChannelUpgradeAck { + port_id: "p".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Port too long".to_string(), + raw: RawMsgChannelUpgradeAck { + port_id: "abcdefsdfasdfasdfasdfasdfasdfadsfasdgafsgadfasdfasdfasdfsdfasdfaghijklmnopqrstuabcdefsdfasdfasdfasdfasdfasdfadsfasdgafsgadfasdfasdfasdfsdfasdfaghijklmnopqrstu".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Correct channel ID".to_string(), + raw: RawMsgChannelUpgradeAck { + channel_id: "channel-2".to_string(), + ..default_raw_msg.clone() + }, + want_pass: true, + }, + Test { + name: "Channel name too short".to_string(), + raw: RawMsgChannelUpgradeAck { + channel_id: "c".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Channel name too long".to_string(), + raw: RawMsgChannelUpgradeAck { + channel_id: "channel-128391283791827398127398791283912837918273981273987912839".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Empty proof channel".to_string(), + raw: RawMsgChannelUpgradeAck { + proof_channel: vec![], + ..default_raw_msg + }, + want_pass: false, + }, + ] + .into_iter() + .collect(); + + for test in tests { + let res = MsgChannelUpgradeAck::try_from(test.raw.clone()); + + assert_eq!( + test.want_pass, + res.is_ok(), + "MsgChannelUpgradeAck::try_from failed for test {}, \nraw msg {:?} with err {:?}", + test.name, + test.raw, + res.err() + ); + } + } + + #[test] + fn to_and_from() { + let raw = get_dummy_raw_msg_chan_upgrade_ack(); + let msg = MsgChannelUpgradeAck::try_from(raw.clone()).unwrap(); + let raw_back = RawMsgChannelUpgradeAck::from(msg.clone()); + let msg_back = MsgChannelUpgradeAck::try_from(raw_back.clone()).unwrap(); + assert_eq!(raw, raw_back); + assert_eq!(msg, msg_back); + } +} diff --git a/crates/relayer-types/src/core/ics04_channel/msgs/chan_upgrade_cancel.rs b/crates/relayer-types/src/core/ics04_channel/msgs/chan_upgrade_cancel.rs new file mode 100644 index 0000000000..f2e33039b1 --- /dev/null +++ b/crates/relayer-types/src/core/ics04_channel/msgs/chan_upgrade_cancel.rs @@ -0,0 +1,241 @@ +use ibc_proto::ibc::core::channel::v1::MsgChannelUpgradeCancel as RawMsgChannelUpgradeCancel; +use ibc_proto::Protobuf; + +use crate::core::ics04_channel::error::Error; +use crate::core::ics04_channel::upgrade::ErrorReceipt; +use crate::core::ics23_commitment::commitment::CommitmentProofBytes; +use crate::core::ics24_host::identifier::{ChannelId, PortId}; +use crate::signer::Signer; +use crate::tx_msg::Msg; +use crate::Height; + +pub const TYPE_URL: &str = "/ibc.core.channel.v1.MsgChannelUpgradeCancel"; + +/// Message definition the `ChanUpgradeCancel` datagram. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct MsgChannelUpgradeCancel { + pub port_id: PortId, + pub channel_id: ChannelId, + pub error_receipt: ErrorReceipt, + /// The proof of the counterparty error receipt + pub proof_error_receipt: CommitmentProofBytes, + /// The height at which the proofs were queried. + pub proof_height: Height, + pub signer: Signer, +} + +impl MsgChannelUpgradeCancel { + #[allow(clippy::too_many_arguments)] + pub fn new( + port_id: PortId, + channel_id: ChannelId, + error_receipt: ErrorReceipt, + proof_error_receipt: CommitmentProofBytes, + proof_height: Height, + signer: Signer, + ) -> Self { + Self { + port_id, + channel_id, + error_receipt, + proof_error_receipt, + proof_height, + signer, + } + } +} + +impl Msg for MsgChannelUpgradeCancel { + type ValidationError = Error; + type Raw = RawMsgChannelUpgradeCancel; + + fn route(&self) -> String { + crate::keys::ROUTER_KEY.to_string() + } + + fn type_url(&self) -> String { + TYPE_URL.to_string() + } +} + +impl Protobuf for MsgChannelUpgradeCancel {} + +impl TryFrom for MsgChannelUpgradeCancel { + type Error = Error; + + fn try_from(raw_msg: RawMsgChannelUpgradeCancel) -> Result { + let raw_error_receipt = raw_msg + .error_receipt + .ok_or(Error::missing_upgrade_error_receipt())?; + let error_receipt = ErrorReceipt::try_from(raw_error_receipt)?; + + let proof_height = raw_msg + .proof_height + .ok_or_else(Error::missing_proof_height)? + .try_into() + .map_err(|_| Error::invalid_proof_height())?; + + Ok(MsgChannelUpgradeCancel { + port_id: raw_msg.port_id.parse().map_err(Error::identifier)?, + channel_id: raw_msg.channel_id.parse().map_err(Error::identifier)?, + error_receipt, + proof_error_receipt: raw_msg + .proof_error_receipt + .try_into() + .map_err(Error::invalid_proof)?, + proof_height, + signer: raw_msg.signer.parse().map_err(Error::signer)?, + }) + } +} + +impl From for RawMsgChannelUpgradeCancel { + fn from(domain_msg: MsgChannelUpgradeCancel) -> Self { + RawMsgChannelUpgradeCancel { + port_id: domain_msg.port_id.to_string(), + channel_id: domain_msg.channel_id.to_string(), + error_receipt: Some(domain_msg.error_receipt.into()), + proof_error_receipt: domain_msg.proof_error_receipt.into(), + proof_height: Some(domain_msg.proof_height.into()), + signer: domain_msg.signer.to_string(), + } + } +} + +#[cfg(test)] +pub mod test_util { + use ibc_proto::ibc::core::channel::v1::ErrorReceipt as RawErrorReceipt; + use ibc_proto::ibc::core::channel::v1::MsgChannelUpgradeCancel as RawMsgChannelUpgradeCancel; + use ibc_proto::ibc::core::client::v1::Height as RawHeight; + + use crate::core::ics24_host::identifier::{ChannelId, PortId}; + use crate::test_utils::{get_dummy_bech32_account, get_dummy_proof}; + + /// Returns a dummy `RawMsgChannelUpgradeCnacel`, for testing only! + pub fn get_dummy_raw_msg_chan_upgrade_cancel() -> RawMsgChannelUpgradeCancel { + RawMsgChannelUpgradeCancel { + port_id: PortId::default().to_string(), + channel_id: ChannelId::default().to_string(), + error_receipt: Some(RawErrorReceipt { + sequence: 1, + message: "error message".to_string(), + }), + proof_error_receipt: get_dummy_proof(), + proof_height: Some(RawHeight { + revision_number: 1, + revision_height: 1, + }), + signer: get_dummy_bech32_account(), + } + } +} + +#[cfg(test)] +mod tests { + use test_log::test; + + use ibc_proto::ibc::core::channel::v1::MsgChannelUpgradeCancel as RawMsgChannelUpgradeCancel; + + use crate::core::ics04_channel::msgs::chan_upgrade_cancel::test_util::get_dummy_raw_msg_chan_upgrade_cancel; + use crate::core::ics04_channel::msgs::chan_upgrade_cancel::MsgChannelUpgradeCancel; + + #[test] + fn parse_channel_upgrade_try_msg() { + struct Test { + name: String, + raw: RawMsgChannelUpgradeCancel, + want_pass: bool, + } + + let default_raw_msg = get_dummy_raw_msg_chan_upgrade_cancel(); + + let tests: Vec = vec![ + Test { + name: "Good parameters".to_string(), + raw: default_raw_msg.clone(), + want_pass: true, + }, + Test { + name: "Correct port ID".to_string(), + raw: RawMsgChannelUpgradeCancel { + port_id: "p36".to_string(), + ..default_raw_msg.clone() + }, + want_pass: true, + }, + Test { + name: "Port too short".to_string(), + raw: RawMsgChannelUpgradeCancel { + port_id: "p".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Port too long".to_string(), + raw: RawMsgChannelUpgradeCancel { + port_id: "abcdefsdfasdfasdfasdfasdfasdfadsfasdgafsgadfasdfasdfasdfsdfasdfaghijklmnopqrstuabcdefsdfasdfasdfasdfasdfasdfadsfasdgafsgadfasdfasdfasdfsdfasdfaghijklmnopqrstu".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Correct channel ID".to_string(), + raw: RawMsgChannelUpgradeCancel { + channel_id: "channel-2".to_string(), + ..default_raw_msg.clone() + }, + want_pass: true, + }, + Test { + name: "Channel name too short".to_string(), + raw: RawMsgChannelUpgradeCancel { + channel_id: "c".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Channel name too long".to_string(), + raw: RawMsgChannelUpgradeCancel { + channel_id: "channel-128391283791827398127398791283912837918273981273987912839".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Empty proof channel".to_string(), + raw: RawMsgChannelUpgradeCancel { + proof_error_receipt: vec![], + ..default_raw_msg + }, + want_pass: false, + }, + ] + .into_iter() + .collect(); + + for test in tests { + let res = MsgChannelUpgradeCancel::try_from(test.raw.clone()); + + assert_eq!( + test.want_pass, + res.is_ok(), + "RawMsgChannelUpgradeCancel::try_from failed for test {}, \nraw msg {:?} with err {:?}", + test.name, + test.raw, + res.err() + ); + } + } + + #[test] + fn to_and_from() { + let raw = get_dummy_raw_msg_chan_upgrade_cancel(); + let msg = MsgChannelUpgradeCancel::try_from(raw.clone()).unwrap(); + let raw_back = RawMsgChannelUpgradeCancel::from(msg.clone()); + let msg_back = MsgChannelUpgradeCancel::try_from(raw_back.clone()).unwrap(); + assert_eq!(raw, raw_back); + assert_eq!(msg, msg_back); + } +} diff --git a/crates/relayer-types/src/core/ics04_channel/msgs/chan_upgrade_confirm.rs b/crates/relayer-types/src/core/ics04_channel/msgs/chan_upgrade_confirm.rs new file mode 100644 index 0000000000..d2a2c96b22 --- /dev/null +++ b/crates/relayer-types/src/core/ics04_channel/msgs/chan_upgrade_confirm.rs @@ -0,0 +1,256 @@ +use ibc_proto::ibc::core::channel::v1::MsgChannelUpgradeConfirm as RawMsgChannelUpgradeConfirm; +use ibc_proto::Protobuf; + +use crate::core::ics04_channel::channel::State; +use crate::core::ics04_channel::error::Error; +use crate::core::ics04_channel::upgrade::Upgrade; +use crate::core::ics23_commitment::commitment::CommitmentProofBytes; +use crate::core::ics24_host::identifier::{ChannelId, PortId}; +use crate::signer::Signer; +use crate::tx_msg::Msg; +use crate::Height; + +pub const TYPE_URL: &str = "/ibc.core.channel.v1.MsgChannelUpgradeConfirm"; + +/// Message definition for the third step of the channel upgrade +/// handshake (the `ChanUpgradeConfirm` datagram). +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct MsgChannelUpgradeConfirm { + pub port_id: PortId, + pub channel_id: ChannelId, + pub counterparty_channel_state: State, + pub counterparty_upgrade: Upgrade, + /// The proof of the counterparty channel + pub proof_channel: CommitmentProofBytes, + /// The proof of the counterparty upgrade + pub proof_upgrade: CommitmentProofBytes, + /// The height at which the proofs were queried. + pub proof_height: Height, + pub signer: Signer, +} + +impl MsgChannelUpgradeConfirm { + #[allow(clippy::too_many_arguments)] + pub fn new( + port_id: PortId, + channel_id: ChannelId, + counterparty_channel_state: State, + counterparty_upgrade: Upgrade, + proof_channel: CommitmentProofBytes, + proof_upgrade: CommitmentProofBytes, + proof_height: Height, + signer: Signer, + ) -> Self { + Self { + port_id, + channel_id, + counterparty_channel_state, + counterparty_upgrade, + proof_channel, + proof_upgrade, + proof_height, + signer, + } + } +} + +impl Msg for MsgChannelUpgradeConfirm { + type ValidationError = Error; + type Raw = RawMsgChannelUpgradeConfirm; + + fn route(&self) -> String { + crate::keys::ROUTER_KEY.to_string() + } + + fn type_url(&self) -> String { + TYPE_URL.to_string() + } +} + +impl Protobuf for MsgChannelUpgradeConfirm {} + +impl TryFrom for MsgChannelUpgradeConfirm { + type Error = Error; + + fn try_from(raw_msg: RawMsgChannelUpgradeConfirm) -> Result { + let counterparty_upgrade = raw_msg + .counterparty_upgrade + .ok_or(Error::missing_upgrade())? + .try_into()?; + + let proof_height = raw_msg + .proof_height + .ok_or_else(Error::missing_proof_height)? + .try_into() + .map_err(|_| Error::invalid_proof_height())?; + + Ok(MsgChannelUpgradeConfirm { + port_id: raw_msg.port_id.parse().map_err(Error::identifier)?, + channel_id: raw_msg.channel_id.parse().map_err(Error::identifier)?, + counterparty_channel_state: State::from_i32(raw_msg.counterparty_channel_state)?, + counterparty_upgrade, + proof_channel: raw_msg + .proof_channel + .try_into() + .map_err(Error::invalid_proof)?, + proof_upgrade: raw_msg + .proof_upgrade + .try_into() + .map_err(Error::invalid_proof)?, + proof_height, + signer: raw_msg.signer.parse().map_err(Error::signer)?, + }) + } +} + +impl From for RawMsgChannelUpgradeConfirm { + fn from(domain_msg: MsgChannelUpgradeConfirm) -> Self { + RawMsgChannelUpgradeConfirm { + port_id: domain_msg.port_id.to_string(), + channel_id: domain_msg.channel_id.to_string(), + counterparty_channel_state: domain_msg.counterparty_channel_state.as_i32(), + counterparty_upgrade: Some(domain_msg.counterparty_upgrade.into()), + proof_upgrade: domain_msg.proof_upgrade.into(), + proof_channel: domain_msg.proof_channel.into(), + proof_height: Some(domain_msg.proof_height.into()), + signer: domain_msg.signer.to_string(), + } + } +} + +#[cfg(test)] +pub mod test_util { + use ibc_proto::ibc::core::channel::v1::MsgChannelUpgradeConfirm as RawMsgChannelUpgradeConfirm; + use ibc_proto::ibc::core::client::v1::Height as RawHeight; + + use crate::core::ics04_channel::upgrade::test_util::get_dummy_upgrade; + use crate::core::ics24_host::identifier::{ChannelId, PortId}; + use crate::test_utils::{get_dummy_bech32_account, get_dummy_proof}; + + /// Returns a dummy `RawMsgChannelUpgradeConfirm`, for testing only! + pub fn get_dummy_raw_msg_chan_upgrade_confirm() -> RawMsgChannelUpgradeConfirm { + RawMsgChannelUpgradeConfirm { + port_id: PortId::default().to_string(), + channel_id: ChannelId::default().to_string(), + counterparty_channel_state: 6, // FlushComplete + counterparty_upgrade: Some(get_dummy_upgrade()), + proof_upgrade: get_dummy_proof(), + proof_channel: get_dummy_proof(), + proof_height: Some(RawHeight { + revision_number: 1, + revision_height: 1, + }), + signer: get_dummy_bech32_account(), + } + } +} + +#[cfg(test)] +mod tests { + use test_log::test; + + use ibc_proto::ibc::core::channel::v1::MsgChannelUpgradeConfirm as RawMsgChannelUpgradeConfirm; + + use crate::core::ics04_channel::msgs::chan_upgrade_confirm::test_util::get_dummy_raw_msg_chan_upgrade_confirm; + use crate::core::ics04_channel::msgs::chan_upgrade_confirm::MsgChannelUpgradeConfirm; + + #[test] + fn parse_channel_upgrade_try_msg() { + struct Test { + name: String, + raw: RawMsgChannelUpgradeConfirm, + want_pass: bool, + } + + let default_raw_msg = get_dummy_raw_msg_chan_upgrade_confirm(); + + let tests: Vec = vec![ + Test { + name: "Good parameters".to_string(), + raw: default_raw_msg.clone(), + want_pass: true, + }, + Test { + name: "Correct port ID".to_string(), + raw: RawMsgChannelUpgradeConfirm { + port_id: "p36".to_string(), + ..default_raw_msg.clone() + }, + want_pass: true, + }, + Test { + name: "Port too short".to_string(), + raw: RawMsgChannelUpgradeConfirm { + port_id: "p".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Port too long".to_string(), + raw: RawMsgChannelUpgradeConfirm { + port_id: "abcdefsdfasdfasdfasdfasdfasdfadsfasdgafsgadfasdfasdfasdfsdfasdfaghijklmnopqrstuabcdefsdfasdfasdfasdfasdfasdfadsfasdgafsgadfasdfasdfasdfsdfasdfaghijklmnopqrstu".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Correct channel ID".to_string(), + raw: RawMsgChannelUpgradeConfirm { + channel_id: "channel-2".to_string(), + ..default_raw_msg.clone() + }, + want_pass: true, + }, + Test { + name: "Channel name too short".to_string(), + raw: RawMsgChannelUpgradeConfirm { + channel_id: "c".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Channel name too long".to_string(), + raw: RawMsgChannelUpgradeConfirm { + channel_id: "channel-128391283791827398127398791283912837918273981273987912839".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Empty proof channel".to_string(), + raw: RawMsgChannelUpgradeConfirm { + proof_channel: vec![], + ..default_raw_msg + }, + want_pass: false, + }, + ] + .into_iter() + .collect(); + + for test in tests { + let res = MsgChannelUpgradeConfirm::try_from(test.raw.clone()); + + assert_eq!( + test.want_pass, + res.is_ok(), + "MsgChannelUpgradeConfirm::try_from failed for test {}, \nraw msg {:?} with err {:?}", + test.name, + test.raw, + res.err() + ); + } + } + + #[test] + fn to_and_from() { + let raw = get_dummy_raw_msg_chan_upgrade_confirm(); + let msg = MsgChannelUpgradeConfirm::try_from(raw.clone()).unwrap(); + let raw_back = RawMsgChannelUpgradeConfirm::from(msg.clone()); + let msg_back = MsgChannelUpgradeConfirm::try_from(raw_back.clone()).unwrap(); + assert_eq!(raw, raw_back); + assert_eq!(msg, msg_back); + } +} diff --git a/crates/relayer-types/src/core/ics04_channel/msgs/chan_upgrade_init.rs b/crates/relayer-types/src/core/ics04_channel/msgs/chan_upgrade_init.rs new file mode 100644 index 0000000000..df696905d5 --- /dev/null +++ b/crates/relayer-types/src/core/ics04_channel/msgs/chan_upgrade_init.rs @@ -0,0 +1,200 @@ +use crate::core::ics04_channel::upgrade_fields::UpgradeFields; + +use ibc_proto::ibc::core::channel::v1::MsgChannelUpgradeInit as RawMsgChannelUpgradeInit; +use ibc_proto::Protobuf; + +use crate::core::ics04_channel::error::Error; +use crate::core::ics24_host::identifier::{ChannelId, PortId}; +use crate::signer::Signer; +use crate::tx_msg::Msg; + +pub const TYPE_URL: &str = "/ibc.core.channel.v1.MsgChannelUpgradeInit"; + +/// Message definition for the first step in the channel +/// upgrade handshake (`ChanUpgradeInit` datagram). +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct MsgChannelUpgradeInit { + pub port_id: PortId, + pub channel_id: ChannelId, + pub fields: UpgradeFields, + pub signer: Signer, +} + +impl MsgChannelUpgradeInit { + pub fn new( + port_id: PortId, + channel_id: ChannelId, + fields: UpgradeFields, + signer: Signer, + ) -> Self { + Self { + port_id, + channel_id, + fields, + signer, + } + } +} + +impl Msg for MsgChannelUpgradeInit { + type ValidationError = Error; + type Raw = RawMsgChannelUpgradeInit; + + fn route(&self) -> String { + crate::keys::ROUTER_KEY.to_string() + } + + fn type_url(&self) -> String { + TYPE_URL.to_string() + } +} + +impl Protobuf for MsgChannelUpgradeInit {} + +impl TryFrom for MsgChannelUpgradeInit { + type Error = Error; + + fn try_from(raw_msg: RawMsgChannelUpgradeInit) -> Result { + let raw_fields = raw_msg.fields.ok_or(Error::missing_upgrade_fields())?; + let fields = UpgradeFields::try_from(raw_fields)?; + + Ok(MsgChannelUpgradeInit { + port_id: raw_msg.port_id.parse().map_err(Error::identifier)?, + channel_id: raw_msg.channel_id.parse().map_err(Error::identifier)?, + signer: raw_msg.signer.parse().map_err(Error::signer)?, + fields, + }) + } +} + +impl From for RawMsgChannelUpgradeInit { + fn from(domain_msg: MsgChannelUpgradeInit) -> Self { + Self { + port_id: domain_msg.port_id.to_string(), + channel_id: domain_msg.channel_id.to_string(), + signer: domain_msg.signer.to_string(), + fields: Some(domain_msg.fields.into()), + } + } +} + +#[cfg(test)] +pub mod test_util { + use ibc_proto::ibc::core::channel::v1::MsgChannelUpgradeInit as RawMsgChannelUpgradeInit; + + use crate::core::ics04_channel::upgrade_fields::test_util::get_dummy_upgrade_fields; + use crate::core::ics24_host::identifier::{ChannelId, PortId}; + use crate::test_utils::get_dummy_bech32_account; + + /// Returns a dummy `RawMsgChannelUpgadeInit`, for testing only! + pub fn get_dummy_raw_msg_chan_upgrade_init() -> RawMsgChannelUpgradeInit { + RawMsgChannelUpgradeInit { + port_id: PortId::default().to_string(), + channel_id: ChannelId::default().to_string(), + signer: get_dummy_bech32_account(), + fields: Some(get_dummy_upgrade_fields()), + } + } +} + +#[cfg(test)] +mod tests { + use test_log::test; + + use ibc_proto::ibc::core::channel::v1::MsgChannelUpgradeInit as RawMsgChannelUpgradeInit; + + use crate::core::ics04_channel::msgs::chan_upgrade_init::test_util::get_dummy_raw_msg_chan_upgrade_init; + use crate::core::ics04_channel::msgs::chan_upgrade_init::MsgChannelUpgradeInit; + + #[test] + fn parse_channel_upgrade_init_msg() { + struct Test { + name: String, + raw: RawMsgChannelUpgradeInit, + want_pass: bool, + } + + let default_raw_msg = get_dummy_raw_msg_chan_upgrade_init(); + + let tests: Vec = vec![ + Test { + name: "Good parameters".to_string(), + raw: default_raw_msg.clone(), + want_pass: true, + }, + Test { + name: "Correct port ID".to_string(), + raw: RawMsgChannelUpgradeInit { + port_id: "p36".to_string(), + ..default_raw_msg.clone() + }, + want_pass: true, + }, + Test { + name: "Port too short".to_string(), + raw: RawMsgChannelUpgradeInit { + port_id: "p".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Port too long".to_string(), + raw: RawMsgChannelUpgradeInit { + port_id: "abcdefsdfasdfasdfasdfasdfasdfadsfasdgafsgadfasdfasdfasdfsdfasdfaghijklmnopqrstuabcdefsdfasdfasdfasdfasdfasdfadsfasdgafsgadfasdfasdfasdfsdfasdfaghijklmnopqrstu".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Correct channel ID".to_string(), + raw: RawMsgChannelUpgradeInit { + channel_id: "channel-2".to_string(), + ..default_raw_msg.clone() + }, + want_pass: true, + }, + Test { + name: "Channel name too short".to_string(), + raw: RawMsgChannelUpgradeInit { + channel_id: "c".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Channel name too long".to_string(), + raw: RawMsgChannelUpgradeInit { + channel_id: "channel-128391283791827398127398791283912837918273981273987912839".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + ] + .into_iter() + .collect(); + + for test in tests { + let res = MsgChannelUpgradeInit::try_from(test.raw.clone()); + + assert_eq!( + test.want_pass, + res.is_ok(), + "MsgChannelUpgradeInit::try_from failed for test {}, \nraw msg {:?} with err {:?}", + test.name, + test.raw, + res.err() + ); + } + } + + #[test] + fn to_and_from() { + let raw = get_dummy_raw_msg_chan_upgrade_init(); + let msg = MsgChannelUpgradeInit::try_from(raw.clone()).unwrap(); + let raw_back = RawMsgChannelUpgradeInit::from(msg.clone()); + let msg_back = MsgChannelUpgradeInit::try_from(raw_back.clone()).unwrap(); + assert_eq!(raw, raw_back); + assert_eq!(msg, msg_back); + } +} diff --git a/crates/relayer-types/src/core/ics04_channel/msgs/chan_upgrade_open.rs b/crates/relayer-types/src/core/ics04_channel/msgs/chan_upgrade_open.rs new file mode 100644 index 0000000000..36bac21367 --- /dev/null +++ b/crates/relayer-types/src/core/ics04_channel/msgs/chan_upgrade_open.rs @@ -0,0 +1,240 @@ +use ibc_proto::ibc::core::channel::v1::MsgChannelUpgradeOpen as RawMsgChannelUpgradeOpen; +use ibc_proto::Protobuf; + +use crate::core::ics04_channel::channel::State; +use crate::core::ics04_channel::error::Error; +use crate::core::ics04_channel::packet::Sequence; +use crate::core::ics23_commitment::commitment::CommitmentProofBytes; +use crate::core::ics24_host::identifier::{ChannelId, PortId}; +use crate::signer::Signer; +use crate::tx_msg::Msg; +use crate::Height; + +pub const TYPE_URL: &str = "/ibc.core.channel.v1.MsgChannelUpgradeOpen"; + +/// Message definition for the last step of the channel upgrade +/// handshake (the `ChanUpgradeOpen` datagram). +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct MsgChannelUpgradeOpen { + pub port_id: PortId, + pub channel_id: ChannelId, + pub counterparty_channel_state: State, + pub counterparty_upgrade_sequence: Sequence, + /// The proof of the counterparty channel + pub proof_channel: CommitmentProofBytes, + /// The height at which the proofs were queried. + pub proof_height: Height, + pub signer: Signer, +} + +impl MsgChannelUpgradeOpen { + #[allow(clippy::too_many_arguments)] + pub fn new( + port_id: PortId, + channel_id: ChannelId, + counterparty_channel_state: State, + counterparty_upgrade_sequence: Sequence, + proof_channel: CommitmentProofBytes, + proof_height: Height, + signer: Signer, + ) -> Self { + Self { + port_id, + channel_id, + counterparty_channel_state, + counterparty_upgrade_sequence, + proof_channel, + proof_height, + signer, + } + } +} + +impl Msg for MsgChannelUpgradeOpen { + type ValidationError = Error; + type Raw = RawMsgChannelUpgradeOpen; + + fn route(&self) -> String { + crate::keys::ROUTER_KEY.to_string() + } + + fn type_url(&self) -> String { + TYPE_URL.to_string() + } +} + +impl Protobuf for MsgChannelUpgradeOpen {} + +impl TryFrom for MsgChannelUpgradeOpen { + type Error = Error; + + fn try_from(raw_msg: RawMsgChannelUpgradeOpen) -> Result { + let proof_height = raw_msg + .proof_height + .ok_or_else(Error::missing_proof_height)? + .try_into() + .map_err(|_| Error::invalid_proof_height())?; + + Ok(MsgChannelUpgradeOpen { + port_id: raw_msg.port_id.parse().map_err(Error::identifier)?, + channel_id: raw_msg.channel_id.parse().map_err(Error::identifier)?, + counterparty_channel_state: State::from_i32(raw_msg.counterparty_channel_state)?, + counterparty_upgrade_sequence: raw_msg.counterparty_upgrade_sequence.into(), + proof_channel: raw_msg + .proof_channel + .try_into() + .map_err(Error::invalid_proof)?, + proof_height, + signer: raw_msg.signer.parse().map_err(Error::signer)?, + }) + } +} + +impl From for RawMsgChannelUpgradeOpen { + fn from(domain_msg: MsgChannelUpgradeOpen) -> Self { + RawMsgChannelUpgradeOpen { + port_id: domain_msg.port_id.to_string(), + channel_id: domain_msg.channel_id.to_string(), + counterparty_channel_state: domain_msg.counterparty_channel_state.as_i32(), + counterparty_upgrade_sequence: domain_msg.counterparty_upgrade_sequence.into(), + proof_channel: domain_msg.proof_channel.into(), + proof_height: Some(domain_msg.proof_height.into()), + signer: domain_msg.signer.to_string(), + } + } +} + +#[cfg(test)] +pub mod test_util { + use ibc_proto::ibc::core::channel::v1::MsgChannelUpgradeOpen as RawMsgChannelUpgradeOpen; + use ibc_proto::ibc::core::client::v1::Height as RawHeight; + + use crate::core::ics24_host::identifier::{ChannelId, PortId}; + use crate::test_utils::{get_dummy_bech32_account, get_dummy_proof}; + + /// Returns a dummy `RawMsgChannelUpgradeOpen`, for testing only! + pub fn get_dummy_raw_msg_chan_upgrade_open() -> RawMsgChannelUpgradeOpen { + RawMsgChannelUpgradeOpen { + port_id: PortId::default().to_string(), + channel_id: ChannelId::default().to_string(), + counterparty_channel_state: 6, // FlushComplete + counterparty_upgrade_sequence: 1, + proof_channel: get_dummy_proof(), + proof_height: Some(RawHeight { + revision_number: 1, + revision_height: 1, + }), + signer: get_dummy_bech32_account(), + } + } +} + +#[cfg(test)] +mod tests { + use test_log::test; + + use ibc_proto::ibc::core::channel::v1::MsgChannelUpgradeOpen as RawMsgChannelUpgradeOpen; + + use crate::core::ics04_channel::msgs::chan_upgrade_open::test_util::get_dummy_raw_msg_chan_upgrade_open; + use crate::core::ics04_channel::msgs::chan_upgrade_open::MsgChannelUpgradeOpen; + + #[test] + fn parse_channel_upgrade_try_msg() { + struct Test { + name: String, + raw: RawMsgChannelUpgradeOpen, + want_pass: bool, + } + + let default_raw_msg = get_dummy_raw_msg_chan_upgrade_open(); + + let tests: Vec = vec![ + Test { + name: "Good parameters".to_string(), + raw: default_raw_msg.clone(), + want_pass: true, + }, + Test { + name: "Correct port ID".to_string(), + raw: RawMsgChannelUpgradeOpen { + port_id: "p36".to_string(), + ..default_raw_msg.clone() + }, + want_pass: true, + }, + Test { + name: "Port too short".to_string(), + raw: RawMsgChannelUpgradeOpen { + port_id: "p".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Port too long".to_string(), + raw: RawMsgChannelUpgradeOpen { + port_id: "abcdefsdfasdfasdfasdfasdfasdfadsfasdgafsgadfasdfasdfasdfsdfasdfaghijklmnopqrstuabcdefsdfasdfasdfasdfasdfasdfadsfasdgafsgadfasdfasdfasdfsdfasdfaghijklmnopqrstu".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Correct channel ID".to_string(), + raw: RawMsgChannelUpgradeOpen { + channel_id: "channel-2".to_string(), + ..default_raw_msg.clone() + }, + want_pass: true, + }, + Test { + name: "Channel name too short".to_string(), + raw: RawMsgChannelUpgradeOpen { + channel_id: "c".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Channel name too long".to_string(), + raw: RawMsgChannelUpgradeOpen { + channel_id: "channel-128391283791827398127398791283912837918273981273987912839".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Empty proof channel".to_string(), + raw: RawMsgChannelUpgradeOpen { + proof_channel: vec![], + ..default_raw_msg + }, + want_pass: false, + }, + ] + .into_iter() + .collect(); + + for test in tests { + let res = MsgChannelUpgradeOpen::try_from(test.raw.clone()); + + assert_eq!( + test.want_pass, + res.is_ok(), + "MsgChannelUpgradeOpen::try_from failed for test {}, \nraw msg {:?} with err {:?}", + test.name, + test.raw, + res.err() + ); + } + } + + #[test] + fn to_and_from() { + let raw = get_dummy_raw_msg_chan_upgrade_open(); + let msg = MsgChannelUpgradeOpen::try_from(raw.clone()).unwrap(); + let raw_back = RawMsgChannelUpgradeOpen::from(msg.clone()); + let msg_back = MsgChannelUpgradeOpen::try_from(raw_back.clone()).unwrap(); + assert_eq!(raw, raw_back); + assert_eq!(msg, msg_back); + } +} diff --git a/crates/relayer-types/src/core/ics04_channel/msgs/chan_upgrade_timeout.rs b/crates/relayer-types/src/core/ics04_channel/msgs/chan_upgrade_timeout.rs new file mode 100644 index 0000000000..e6bbe74fd9 --- /dev/null +++ b/crates/relayer-types/src/core/ics04_channel/msgs/chan_upgrade_timeout.rs @@ -0,0 +1,258 @@ +use ibc_proto::ibc::core::channel::v1::MsgChannelUpgradeTimeout as RawMsgChannelUpgradeTimeout; +use ibc_proto::Protobuf; + +use crate::core::ics04_channel::channel::ChannelEnd; +use crate::core::ics04_channel::error::Error; +use crate::core::ics23_commitment::commitment::CommitmentProofBytes; +use crate::core::ics24_host::identifier::{ChannelId, PortId}; +use crate::signer::Signer; +use crate::tx_msg::Msg; +use crate::Height; + +pub const TYPE_URL: &str = "/ibc.core.channel.v1.MsgChannelUpgradeTimeout"; + +/// Message definition the `ChanUpgradeTimeout` datagram. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct MsgChannelUpgradeTimeout { + pub port_id: PortId, + pub channel_id: ChannelId, + pub counterparty_channel: ChannelEnd, + /// The proof of the counterparty channel + pub proof_channel: CommitmentProofBytes, + /// The height at which the proofs were queried. + pub proof_height: Height, + pub signer: Signer, +} + +impl MsgChannelUpgradeTimeout { + #[allow(clippy::too_many_arguments)] + pub fn new( + port_id: PortId, + channel_id: ChannelId, + counterparty_channel: ChannelEnd, + proof_channel: CommitmentProofBytes, + proof_height: Height, + signer: Signer, + ) -> Self { + Self { + port_id, + channel_id, + counterparty_channel, + proof_channel, + proof_height, + signer, + } + } +} + +impl Msg for MsgChannelUpgradeTimeout { + type ValidationError = Error; + type Raw = RawMsgChannelUpgradeTimeout; + + fn route(&self) -> String { + crate::keys::ROUTER_KEY.to_string() + } + + fn type_url(&self) -> String { + TYPE_URL.to_string() + } +} + +impl Protobuf for MsgChannelUpgradeTimeout {} + +impl TryFrom for MsgChannelUpgradeTimeout { + type Error = Error; + + fn try_from(raw_msg: RawMsgChannelUpgradeTimeout) -> Result { + let raw_counterparty_channel = raw_msg + .counterparty_channel + .ok_or(Error::missing_channel())?; + let counterparty_channel = ChannelEnd::try_from(raw_counterparty_channel)?; + + let proof_height = raw_msg + .proof_height + .ok_or_else(Error::missing_proof_height)? + .try_into() + .map_err(|_| Error::invalid_proof_height())?; + + Ok(MsgChannelUpgradeTimeout { + port_id: raw_msg.port_id.parse().map_err(Error::identifier)?, + channel_id: raw_msg.channel_id.parse().map_err(Error::identifier)?, + counterparty_channel, + proof_channel: raw_msg + .proof_channel + .try_into() + .map_err(Error::invalid_proof)?, + proof_height, + signer: raw_msg.signer.parse().map_err(Error::signer)?, + }) + } +} + +impl From for RawMsgChannelUpgradeTimeout { + fn from(domain_msg: MsgChannelUpgradeTimeout) -> Self { + RawMsgChannelUpgradeTimeout { + port_id: domain_msg.port_id.to_string(), + channel_id: domain_msg.channel_id.to_string(), + counterparty_channel: Some(domain_msg.counterparty_channel.into()), + proof_channel: domain_msg.proof_channel.into(), + proof_height: Some(domain_msg.proof_height.into()), + signer: domain_msg.signer.to_string(), + } + } +} + +#[cfg(test)] +pub mod test_util { + use crate::core::ics04_channel::channel::test_util::get_dummy_raw_channel_end; + use ibc_proto::ibc::core::channel::v1::MsgChannelUpgradeTimeout as RawMsgChannelUpgradeTimeout; + use ibc_proto::ibc::core::client::v1::Height as RawHeight; + + use crate::core::ics24_host::identifier::{ChannelId, PortId}; + use crate::test_utils::{get_dummy_bech32_account, get_dummy_proof}; + + /// Returns a dummy `RawMsgChannelUpgradeCnacel`, for testing only! + pub fn get_dummy_raw_msg_chan_upgrade_timeout() -> RawMsgChannelUpgradeTimeout { + RawMsgChannelUpgradeTimeout { + port_id: PortId::default().to_string(), + channel_id: ChannelId::default().to_string(), + counterparty_channel: Some(get_dummy_raw_channel_end()), + proof_channel: get_dummy_proof(), + proof_height: Some(RawHeight { + revision_number: 1, + revision_height: 1, + }), + signer: get_dummy_bech32_account(), + } + } +} + +#[cfg(test)] +mod tests { + use test_log::test; + + use ibc_proto::ibc::core::channel::v1::MsgChannelUpgradeTimeout as RawMsgChannelUpgradeTimeout; + use ibc_proto::ibc::core::client::v1::Height; + + use crate::core::ics04_channel::msgs::chan_upgrade_timeout::test_util::get_dummy_raw_msg_chan_upgrade_timeout; + use crate::core::ics04_channel::msgs::chan_upgrade_timeout::MsgChannelUpgradeTimeout; + + #[test] + fn parse_channel_upgrade_try_msg() { + struct Test { + name: String, + raw: RawMsgChannelUpgradeTimeout, + want_pass: bool, + } + + let default_raw_msg = get_dummy_raw_msg_chan_upgrade_timeout(); + + let tests: Vec = vec![ + Test { + name: "Good parameters".to_string(), + raw: default_raw_msg.clone(), + want_pass: true, + }, + Test { + name: "Correct port ID".to_string(), + raw: RawMsgChannelUpgradeTimeout { + port_id: "p36".to_string(), + ..default_raw_msg.clone() + }, + want_pass: true, + }, + Test { + name: "Port too short".to_string(), + raw: RawMsgChannelUpgradeTimeout { + port_id: "p".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Port too long".to_string(), + raw: RawMsgChannelUpgradeTimeout { + port_id: "abcdefsdfasdfasdfasdfasdfasdfadsfasdgafsgadfasdfasdfasdfsdfasdfaghijklmnopqrstuabcdefsdfasdfasdfasdfasdfasdfadsfasdgafsgadfasdfasdfasdfsdfasdfaghijklmnopqrstu".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Correct channel ID".to_string(), + raw: RawMsgChannelUpgradeTimeout { + channel_id: "channel-2".to_string(), + ..default_raw_msg.clone() + }, + want_pass: true, + }, + Test { + name: "Channel name too short".to_string(), + raw: RawMsgChannelUpgradeTimeout { + channel_id: "c".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Channel name too long".to_string(), + raw: RawMsgChannelUpgradeTimeout { + channel_id: "channel-128391283791827398127398791283912837918273981273987912839".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Empty proof channel".to_string(), + raw: RawMsgChannelUpgradeTimeout { + proof_channel: vec![], + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Bad proof height, height = 0".to_string(), + raw: RawMsgChannelUpgradeTimeout { + proof_height: Some(Height { + revision_number: 0, + revision_height: 0, + }), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Missing proof height".to_string(), + raw: RawMsgChannelUpgradeTimeout { + proof_height: None, + ..default_raw_msg.clone() + }, + want_pass: false, + }, + ] + .into_iter() + .collect(); + + for test in tests { + let res = MsgChannelUpgradeTimeout::try_from(test.raw.clone()); + + assert_eq!( + test.want_pass, + res.is_ok(), + "RawMsgChannelUpgradeTimeout::try_from failed for test {}, \nraw msg {:?} with err {:?}", + test.name, + test.raw, + res.err() + ); + } + } + + #[test] + fn to_and_from() { + let raw = get_dummy_raw_msg_chan_upgrade_timeout(); + let msg = MsgChannelUpgradeTimeout::try_from(raw.clone()).unwrap(); + let raw_back = RawMsgChannelUpgradeTimeout::from(msg.clone()); + let msg_back = MsgChannelUpgradeTimeout::try_from(raw_back.clone()).unwrap(); + assert_eq!(raw, raw_back); + assert_eq!(msg, msg_back); + } +} diff --git a/crates/relayer-types/src/core/ics04_channel/msgs/chan_upgrade_try.rs b/crates/relayer-types/src/core/ics04_channel/msgs/chan_upgrade_try.rs new file mode 100644 index 0000000000..fa4c2333f9 --- /dev/null +++ b/crates/relayer-types/src/core/ics04_channel/msgs/chan_upgrade_try.rs @@ -0,0 +1,276 @@ +use crate::core::ics04_channel::packet::Sequence; +use crate::core::ics04_channel::upgrade_fields::UpgradeFields; +use crate::Height; + +use ibc_proto::Protobuf; + +use ibc_proto::ibc::core::channel::v1::MsgChannelUpgradeTry as RawMsgChannelUpgradeTry; + +use crate::core::ics04_channel::error::Error; +use crate::core::ics23_commitment::commitment::CommitmentProofBytes; +use crate::core::ics24_host::identifier::{ChannelId, ConnectionId, PortId}; +use crate::signer::Signer; +use crate::tx_msg::Msg; + +pub const TYPE_URL: &str = "/ibc.core.channel.v1.MsgChannelUpgradeTry"; + +/// Message definition for the second step of the channel upgrade +/// handshake (the `ChanUpgradeTry` datagram). +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct MsgChannelUpgradeTry { + pub port_id: PortId, + pub channel_id: ChannelId, + pub proposed_upgrade_connection_hops: Vec, + pub counterparty_upgrade_fields: UpgradeFields, + pub counterparty_upgrade_sequence: Sequence, + /// The proof of the counterparty channel + pub proof_channel: CommitmentProofBytes, + /// The proof of the counterparty upgrade + pub proof_upgrade: CommitmentProofBytes, + /// The height at which the proofs were queried. + pub proof_height: Height, + pub signer: Signer, +} + +impl MsgChannelUpgradeTry { + #[allow(clippy::too_many_arguments)] + pub fn new( + port_id: PortId, + channel_id: ChannelId, + proposed_upgrade_connection_hops: Vec, + counterparty_upgrade_fields: UpgradeFields, + counterparty_upgrade_sequence: Sequence, + proof_channel: CommitmentProofBytes, + proof_upgrade: CommitmentProofBytes, + proof_height: Height, + signer: Signer, + ) -> Self { + Self { + port_id, + channel_id, + proposed_upgrade_connection_hops, + counterparty_upgrade_fields, + counterparty_upgrade_sequence, + proof_channel, + proof_upgrade, + proof_height, + signer, + } + } +} + +impl Msg for MsgChannelUpgradeTry { + type ValidationError = Error; + type Raw = RawMsgChannelUpgradeTry; + + fn route(&self) -> String { + crate::keys::ROUTER_KEY.to_string() + } + + fn type_url(&self) -> String { + TYPE_URL.to_string() + } +} + +impl Protobuf for MsgChannelUpgradeTry {} + +impl TryFrom for MsgChannelUpgradeTry { + type Error = Error; + + fn try_from(raw_msg: RawMsgChannelUpgradeTry) -> Result { + let proposed_upgrade_connection_hops: Result, Error> = raw_msg + .proposed_upgrade_connection_hops + .iter() + .map(|hop| hop.parse().map_err(Error::identifier)) + .collect(); + let counterparty_upgrade_fields = raw_msg + .counterparty_upgrade_fields + .ok_or(Error::missing_upgrade_fields())? + .try_into()?; + let counterparty_upgrade_sequence = raw_msg.counterparty_upgrade_sequence.into(); + + let proof_height = raw_msg + .proof_height + .ok_or_else(Error::missing_proof_height)? + .try_into() + .map_err(|_| Error::invalid_proof_height())?; + + Ok(MsgChannelUpgradeTry { + port_id: raw_msg.port_id.parse().map_err(Error::identifier)?, + channel_id: raw_msg.channel_id.parse().map_err(Error::identifier)?, + proposed_upgrade_connection_hops: proposed_upgrade_connection_hops?, + counterparty_upgrade_fields, + counterparty_upgrade_sequence, + proof_channel: raw_msg + .proof_channel + .try_into() + .map_err(Error::invalid_proof)?, + proof_upgrade: raw_msg + .proof_upgrade + .try_into() + .map_err(Error::invalid_proof)?, + proof_height, + signer: raw_msg.signer.parse().map_err(Error::signer)?, + }) + } +} + +impl From for RawMsgChannelUpgradeTry { + fn from(domain_msg: MsgChannelUpgradeTry) -> Self { + let proposed_upgrade_connection_hops = domain_msg + .proposed_upgrade_connection_hops + .into_iter() + .map(|hop| hop.to_string()) + .collect(); + + RawMsgChannelUpgradeTry { + port_id: domain_msg.port_id.to_string(), + channel_id: domain_msg.channel_id.to_string(), + proposed_upgrade_connection_hops, + counterparty_upgrade_fields: Some(domain_msg.counterparty_upgrade_fields.into()), + counterparty_upgrade_sequence: domain_msg.counterparty_upgrade_sequence.into(), + proof_upgrade: domain_msg.proof_upgrade.into(), + proof_channel: domain_msg.proof_channel.into(), + proof_height: Some(domain_msg.proof_height.into()), + signer: domain_msg.signer.to_string(), + } + } +} + +#[cfg(test)] +pub mod test_util { + use ibc_proto::ibc::core::channel::v1::MsgChannelUpgradeTry as RawMsgChannelUpgradeTry; + use ibc_proto::ibc::core::client::v1::Height as RawHeight; + + use crate::core::ics04_channel::upgrade_fields::test_util::get_dummy_upgrade_fields; + use crate::core::ics24_host::identifier::{ChannelId, PortId}; + use crate::test_utils::{get_dummy_bech32_account, get_dummy_proof}; + + /// Returns a dummy `RawMsgChannelUpgradeTry`, for testing only! + pub fn get_dummy_raw_msg_chan_upgrade_try() -> RawMsgChannelUpgradeTry { + RawMsgChannelUpgradeTry { + port_id: PortId::default().to_string(), + channel_id: ChannelId::default().to_string(), + proposed_upgrade_connection_hops: vec![], + counterparty_upgrade_fields: Some(get_dummy_upgrade_fields()), + counterparty_upgrade_sequence: 1, + proof_upgrade: get_dummy_proof(), + proof_channel: get_dummy_proof(), + proof_height: Some(RawHeight { + revision_number: 1, + revision_height: 1, + }), + signer: get_dummy_bech32_account(), + } + } +} + +#[cfg(test)] +mod tests { + use test_log::test; + + use ibc_proto::ibc::core::channel::v1::MsgChannelUpgradeTry as RawMsgChannelUpgradeTry; + + use crate::core::ics04_channel::msgs::chan_upgrade_try::test_util::get_dummy_raw_msg_chan_upgrade_try; + use crate::core::ics04_channel::msgs::chan_upgrade_try::MsgChannelUpgradeTry; + + #[test] + fn parse_channel_upgrade_try_msg() { + struct Test { + name: String, + raw: RawMsgChannelUpgradeTry, + want_pass: bool, + } + + let default_raw_msg = get_dummy_raw_msg_chan_upgrade_try(); + + let tests: Vec = vec![ + Test { + name: "Good parameters".to_string(), + raw: default_raw_msg.clone(), + want_pass: true, + }, + Test { + name: "Correct port ID".to_string(), + raw: RawMsgChannelUpgradeTry { + port_id: "p36".to_string(), + ..default_raw_msg.clone() + }, + want_pass: true, + }, + Test { + name: "Port too short".to_string(), + raw: RawMsgChannelUpgradeTry { + port_id: "p".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Port too long".to_string(), + raw: RawMsgChannelUpgradeTry { + port_id: "abcdefsdfasdfasdfasdfasdfasdfadsfasdgafsgadfasdfasdfasdfsdfasdfaghijklmnopqrstuabcdefsdfasdfasdfasdfasdfasdfadsfasdgafsgadfasdfasdfasdfsdfasdfaghijklmnopqrstu".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Correct channel ID".to_string(), + raw: RawMsgChannelUpgradeTry { + channel_id: "channel-2".to_string(), + ..default_raw_msg.clone() + }, + want_pass: true, + }, + Test { + name: "Channel name too short".to_string(), + raw: RawMsgChannelUpgradeTry { + channel_id: "c".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Channel name too long".to_string(), + raw: RawMsgChannelUpgradeTry { + channel_id: "channel-128391283791827398127398791283912837918273981273987912839".to_string(), + ..default_raw_msg.clone() + }, + want_pass: false, + }, + Test { + name: "Empty proof channel".to_string(), + raw: RawMsgChannelUpgradeTry { + proof_channel: vec![], + ..default_raw_msg + }, + want_pass: false, + }, + ] + .into_iter() + .collect(); + + for test in tests { + let res = MsgChannelUpgradeTry::try_from(test.raw.clone()); + + assert_eq!( + test.want_pass, + res.is_ok(), + "MsgChannelUpgradeTry::try_from failed for test {}, \nraw msg {:?} with err {:?}", + test.name, + test.raw, + res.err() + ); + } + } + + #[test] + fn to_and_from() { + let raw = get_dummy_raw_msg_chan_upgrade_try(); + let msg = MsgChannelUpgradeTry::try_from(raw.clone()).unwrap(); + let raw_back = RawMsgChannelUpgradeTry::from(msg.clone()); + let msg_back = MsgChannelUpgradeTry::try_from(raw_back.clone()).unwrap(); + assert_eq!(raw, raw_back); + assert_eq!(msg, msg_back); + } +} 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 84a8f6a0d6..e3b595cf76 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,13 +1,7 @@ -use ibc_proto::{ - ibc::core::channel::v1::MsgRecvPacket as RawMsgRecvPacket, - Protobuf, -}; +use ibc_proto::{ibc::core::channel::v1::MsgRecvPacket as RawMsgRecvPacket, Protobuf}; use crate::{ - core::ics04_channel::{ - error::Error, - packet::Packet, - }, + core::ics04_channel::{error::Error, packet::Packet}, proofs::Proofs, signer::Signer, tx_msg::Msg, @@ -94,22 +88,15 @@ impl From for RawMsgRecvPacket { #[cfg(test)] pub mod test_util { - use core::{ - ops::Add, - time::Duration, - }; + use core::{ops::Add, time::Duration}; use ibc_proto::ibc::core::{ - channel::v1::MsgRecvPacket as RawMsgRecvPacket, - client::v1::Height as RawHeight, + channel::v1::MsgRecvPacket as RawMsgRecvPacket, client::v1::Height as RawHeight, }; use crate::{ core::ics04_channel::packet::test_utils::get_dummy_raw_packet, - test_utils::{ - get_dummy_bech32_account, - get_dummy_proof, - }, + test_utils::{get_dummy_bech32_account, get_dummy_proof}, timestamp::Timestamp, }; @@ -141,10 +128,7 @@ mod test { use crate::{ core::ics04_channel::{ error::Error, - msgs::recv_packet::{ - test_util::get_dummy_raw_msg_recv_packet, - MsgRecvPacket, - }, + msgs::recv_packet::{test_util::get_dummy_raw_msg_recv_packet, MsgRecvPacket}, }, test_utils::get_dummy_bech32_account, }; 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 5233f6d2cf..56348b1f23 100644 --- a/crates/relayer-types/src/core/ics04_channel/msgs/timeout.rs +++ b/crates/relayer-types/src/core/ics04_channel/msgs/timeout.rs @@ -1,15 +1,9 @@ -use ibc_proto::{ - ibc::core::channel::v1::MsgTimeout as RawMsgTimeout, - Protobuf, -}; +use ibc_proto::{ibc::core::channel::v1::MsgTimeout as RawMsgTimeout, Protobuf}; use crate::{ core::ics04_channel::{ error::Error, - packet::{ - Packet, - Sequence, - }, + packet::{Packet, Sequence}, }, proofs::Proofs, signer::Signer, @@ -109,16 +103,12 @@ impl From for RawMsgTimeout { #[cfg(test)] pub mod test_util { use ibc_proto::ibc::core::{ - channel::v1::MsgTimeout as RawMsgTimeout, - client::v1::Height as RawHeight, + channel::v1::MsgTimeout as RawMsgTimeout, client::v1::Height as RawHeight, }; use crate::{ core::ics04_channel::packet::test_utils::get_dummy_raw_packet, - test_utils::{ - get_dummy_bech32_account, - get_dummy_proof, - }, + test_utils::{get_dummy_bech32_account, get_dummy_proof}, }; /// Returns a dummy `RawMsgTimeout`, for testing only! @@ -150,10 +140,7 @@ mod test { use crate::{ core::ics04_channel::{ error::Error, - msgs::timeout::{ - test_util::get_dummy_raw_msg_timeout, - MsgTimeout, - }, + msgs::timeout::{test_util::get_dummy_raw_msg_timeout, MsgTimeout}, }, test_utils::get_dummy_bech32_account, }; 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 6f74287fe4..bec964f98a 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,15 +1,9 @@ -use ibc_proto::{ - ibc::core::channel::v1::MsgTimeoutOnClose as RawMsgTimeoutOnClose, - Protobuf, -}; +use ibc_proto::{ibc::core::channel::v1::MsgTimeoutOnClose as RawMsgTimeoutOnClose, Protobuf}; use crate::{ core::ics04_channel::{ error::Error, - packet::{ - Packet, - Sequence, - }, + packet::{Packet, Sequence}, }, proofs::Proofs, signer::Signer, @@ -27,6 +21,7 @@ pub struct MsgTimeoutOnClose { pub next_sequence_recv: Sequence, pub proofs: Proofs, pub signer: Signer, + pub counterparty_upgrade_sequence: Sequence, } impl MsgTimeoutOnClose { @@ -35,12 +30,14 @@ impl MsgTimeoutOnClose { next_sequence_recv: Sequence, proofs: Proofs, signer: Signer, + counterparty_upgrade_sequence: Sequence, ) -> MsgTimeoutOnClose { Self { packet, next_sequence_recv, proofs, signer, + counterparty_upgrade_sequence, } } } @@ -95,6 +92,7 @@ impl TryFrom for MsgTimeoutOnClose { next_sequence_recv: Sequence::from(raw_msg.next_sequence_recv), signer: raw_msg.signer.parse().map_err(Error::signer)?, proofs, + counterparty_upgrade_sequence: raw_msg.counterparty_upgrade_sequence.into(), }) } } @@ -111,6 +109,7 @@ impl From for RawMsgTimeoutOnClose { proof_height: Some(domain_msg.proofs.height().into()), next_sequence_recv: domain_msg.next_sequence_recv.into(), signer: domain_msg.signer.to_string(), + counterparty_upgrade_sequence: domain_msg.counterparty_upgrade_sequence.into(), } } } @@ -122,8 +121,7 @@ mod tests { use test_log::test; use crate::core::ics04_channel::msgs::timeout_on_close::{ - test_util::get_dummy_raw_msg_timeout_on_close, - MsgTimeoutOnClose, + test_util::get_dummy_raw_msg_timeout_on_close, MsgTimeoutOnClose, }; #[test] @@ -207,16 +205,12 @@ mod tests { #[cfg(test)] pub mod test_util { use ibc_proto::ibc::core::{ - channel::v1::MsgTimeoutOnClose as RawMsgTimeoutOnClose, - client::v1::Height as RawHeight, + channel::v1::MsgTimeoutOnClose as RawMsgTimeoutOnClose, client::v1::Height as RawHeight, }; use crate::{ core::ics04_channel::packet::test_utils::get_dummy_raw_packet, - test_utils::{ - get_dummy_bech32_account, - get_dummy_proof, - }, + test_utils::{get_dummy_bech32_account, get_dummy_proof}, }; /// Returns a dummy `RawMsgTimeoutOnClose`, for testing only! @@ -235,6 +229,7 @@ pub mod test_util { }), next_sequence_recv: 1, signer: get_dummy_bech32_account(), + counterparty_upgrade_sequence: 0, } } } diff --git a/crates/relayer-types/src/core/ics04_channel/packet.rs b/crates/relayer-types/src/core/ics04_channel/packet.rs index 413f2ade2d..bb3fad0869 100644 --- a/crates/relayer-types/src/core/ics04_channel/packet.rs +++ b/crates/relayer-types/src/core/ics04_channel/packet.rs @@ -1,24 +1,15 @@ use std::str::FromStr; use ibc_proto::ibc::core::channel::v1::Packet as RawPacket; -use serde_derive::{ - Deserialize, - Serialize, -}; +use serde_derive::{Deserialize, Serialize}; use super::timeout::TimeoutHeight; use crate::{ core::{ ics04_channel::error::Error, - ics24_host::identifier::{ - ChannelId, - PortId, - }, - }, - timestamp::{ - Expiry::Expired, - Timestamp, + ics24_host::identifier::{ChannelId, PortId}, }, + timestamp::{Expiry::Expired, Timestamp}, Height, }; @@ -285,15 +276,9 @@ impl From for RawPacket { #[cfg(test)] pub mod test_utils { - use ibc_proto::ibc::core::{ - channel::v1::Packet as RawPacket, - client::v1::Height as RawHeight, - }; + use ibc_proto::ibc::core::{channel::v1::Packet as RawPacket, client::v1::Height as RawHeight}; - use crate::core::ics24_host::identifier::{ - ChannelId, - PortId, - }; + use crate::core::ics24_host::identifier::{ChannelId, PortId}; /// Returns a dummy `RawPacket`, for testing only! pub fn get_dummy_raw_packet(timeout_height: u64, timeout_timestamp: u64) -> RawPacket { @@ -316,16 +301,10 @@ pub mod test_utils { #[cfg(test)] mod tests { - use ibc_proto::ibc::core::{ - channel::v1::Packet as RawPacket, - client::v1::Height as RawHeight, - }; + use ibc_proto::ibc::core::{channel::v1::Packet as RawPacket, client::v1::Height as RawHeight}; use test_log::test; - use crate::core::ics04_channel::packet::{ - test_utils::get_dummy_raw_packet, - Packet, - }; + use crate::core::ics04_channel::packet::{test_utils::get_dummy_raw_packet, Packet}; #[test] fn packet_try_from_raw() { diff --git a/crates/relayer-types/src/core/ics04_channel/packet_id.rs b/crates/relayer-types/src/core/ics04_channel/packet_id.rs index 6abb853e64..b046472c1c 100644 --- a/crates/relayer-types/src/core/ics04_channel/packet_id.rs +++ b/crates/relayer-types/src/core/ics04_channel/packet_id.rs @@ -1,19 +1,9 @@ -use std::{ - convert::TryFrom, - str::FromStr, -}; - use ibc_proto::ibc::core::channel::v1::PacketId as ProtoPacketId; +use std::str::FromStr; use crate::core::{ - ics04_channel::{ - error::Error, - packet::Sequence, - }, - ics24_host::identifier::{ - ChannelId, - PortId, - }, + ics04_channel::{error::Error, packet::Sequence}, + ics24_host::identifier::{ChannelId, PortId}, }; #[derive(Debug, Clone)] diff --git a/crates/relayer-types/src/core/ics04_channel/timeout.rs b/crates/relayer-types/src/core/ics04_channel/timeout.rs index d2ed737b02..cee5f40601 100644 --- a/crates/relayer-types/src/core/ics04_channel/timeout.rs +++ b/crates/relayer-types/src/core/ics04_channel/timeout.rs @@ -1,19 +1,16 @@ -use std::fmt::{ - Display, - Error as FmtError, - Formatter, -}; +use core::fmt::{Display, Error as FmtError, Formatter}; +use std::str::FromStr; +use flex_error::{define_error, TraceError}; +use serde::{Deserialize, Serialize}; + +use ibc_proto::ibc::core::channel::v1::Timeout as RawTimeout; use ibc_proto::ibc::core::client::v1::Height as RawHeight; -use serde::{ - Deserialize, - Serialize, -}; +use ibc_proto::Protobuf; -use crate::core::ics02_client::{ - error::Error as ICS2Error, - height::Height, -}; +use crate::core::ics02_client::{error::Error as ICS2Error, height::Height}; +use crate::core::ics04_channel::error::Error as ChannelError; +use crate::timestamp::{ParseTimestampError, Timestamp}; /// Indicates a consensus height on the destination chain after which the packet /// will no longer be processed, and will instead count as having timed-out. @@ -189,3 +186,146 @@ impl<'de> Deserialize<'de> for TimeoutHeight { }) } } + +/// A composite of timeout height and timeout timestamp types, useful for when +/// performing a channel upgrade handshake, as there are cases when only timeout +/// height is set, only timeout timestamp is set, or both are set. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub enum Timeout { + /// Timeout height indicates the height at which the counterparty + /// must no longer proceed with the upgrade handshake. + /// The chains will then preserve their original channel and the upgrade handshake is aborted + Height(Height), + + /// Timeout timestamp indicates the time on the counterparty at which + /// the counterparty must no longer proceed with the upgrade handshake. + /// The chains will then preserve their original channel and the upgrade handshake is aborted. + Timestamp(Timestamp), + + /// Both timeouts are set. + Both(Height, Timestamp), +} + +impl Display for Timeout { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + match self { + Self::Height(height) => write!(f, "{height}"), + Self::Timestamp(timestamp) => write!(f, "{timestamp}"), + Self::Both(height, timestamp) => write!(f, "{height}, {timestamp}"), + } + } +} + +impl Timeout { + pub fn new(height: Option, timestamp: Option) -> Result { + match (height, timestamp) { + (Some(height), None) => Ok(Timeout::Height(height)), + (None, Some(timestamp)) => Ok(Timeout::Timestamp(timestamp)), + (Some(height), Some(timestamp)) => Ok(Timeout::Both(height, timestamp)), + (None, None) => Err(ChannelError::missing_upgrade_timeout()), + } + } + + pub fn into_tuple(self) -> (Option, Option) { + match self { + Timeout::Height(height) => (Some(height), None), + Timeout::Timestamp(timestamp) => (None, Some(timestamp)), + Timeout::Both(height, timestamp) => (Some(height), Some(timestamp)), + } + } +} + +define_error! { + #[derive(Debug, PartialEq, Eq)] + TimeoutError { + InvalidTimestamp + { timestamp: String } + [ TraceError ] + |e| { format_args!("cannot convert into a `Timestamp` type from string {0}", e.timestamp) }, + + InvalidTimeout + { timeout: String } + |e| { format_args!("invalid timeout {0}", e.timeout) }, + } +} + +impl FromStr for Timeout { + type Err = TimeoutError; + + fn from_str(value: &str) -> Result { + let split: Vec<&str> = value.split(' ').collect(); + + if split.len() != 2 { + return Err(TimeoutError::invalid_timeout(value.to_owned())); + } + + // only timeout timestamp are supported at the moment + split[1] + .parse::() + .map(Timeout::Timestamp) + .map_err(|e| TimeoutError::invalid_timestamp(value.to_owned(), e)) + } +} + +impl Protobuf for Timeout {} + +impl TryFrom for Timeout { + type Error = ChannelError; + + fn try_from(value: RawTimeout) -> Result { + let raw_timeout_height = value.height.map(Height::try_from).transpose(); + + let raw_timeout_timestamp = Timestamp::from_nanoseconds(value.timestamp) + .map_err(|_| Self::Error::invalid_timeout_timestamp) + .ok() + .filter(|ts| ts.nanoseconds() > 0); + + let (timeout_height, timeout_timestamp) = match (raw_timeout_height, raw_timeout_timestamp) + { + (Ok(timeout_height), Some(timeout_timestamp)) => { + (timeout_height, Some(timeout_timestamp)) + } + (Ok(timeout_height), None) => (timeout_height, None), + (Err(_), Some(timeout_timestamp)) => (None, Some(timeout_timestamp)), + (Err(e), None) => { + return Err(e).map_err(|_| Self::Error::invalid_timeout_height()); + } + }; + + Self::new(timeout_height, timeout_timestamp) + } +} + +impl From for RawTimeout { + fn from(value: Timeout) -> Self { + match value { + Timeout::Height(height) => Self { + height: Some(RawHeight::from(height)), + timestamp: 0, + }, + Timeout::Timestamp(timestamp) => Self { + height: None, + timestamp: timestamp.nanoseconds(), + }, + Timeout::Both(height, timestamp) => Self { + height: Some(RawHeight::from(height)), + timestamp: timestamp.nanoseconds(), + }, + } + } +} + +#[cfg(test)] +pub mod test_util { + use ibc_proto::ibc::core::channel::v1::Timeout as RawTimeout; + use ibc_proto::ibc::core::client::v1::Height as RawHeight; + + use crate::core::ics02_client::height::Height; + + pub fn get_dummy_upgrade_timeout() -> RawTimeout { + RawTimeout { + height: Some(RawHeight::from(Height::new(1, 50).unwrap())), + timestamp: 0, + } + } +} diff --git a/crates/relayer-types/src/core/ics04_channel/upgrade.rs b/crates/relayer-types/src/core/ics04_channel/upgrade.rs new file mode 100644 index 0000000000..6eb5b9bea2 --- /dev/null +++ b/crates/relayer-types/src/core/ics04_channel/upgrade.rs @@ -0,0 +1,96 @@ +use ibc_proto::ibc::core::channel::v1::ErrorReceipt as RawErrorReceipt; +use ibc_proto::ibc::core::channel::v1::Upgrade as RawUpgrade; +use ibc_proto::Protobuf; + +use crate::core::ics04_channel::error::Error as ChannelError; +use crate::core::ics04_channel::packet::Sequence; +use crate::core::ics04_channel::timeout::Timeout; +use crate::core::ics04_channel::upgrade_fields::UpgradeFields; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Upgrade { + pub fields: UpgradeFields, + // timeout can be zero, see `TryFrom` implementation + pub timeout: Option, + pub next_sequence_send: Sequence, +} + +impl Protobuf for Upgrade {} + +impl TryFrom for Upgrade { + type Error = ChannelError; + + fn try_from(value: RawUpgrade) -> Result { + let fields = value + .fields + .ok_or(ChannelError::missing_upgrade_fields())? + .try_into()?; + let timeout = value + .timeout + .filter(|tm| Timeout::try_from(*tm).is_ok()) + .map(|tm| Timeout::try_from(tm).unwrap()); + let next_sequence_send = value.next_sequence_send.into(); + + Ok(Self { + fields, + timeout, + next_sequence_send, + }) + } +} + +impl From for RawUpgrade { + fn from(value: Upgrade) -> Self { + let timeout = value.timeout.map(|tm| tm.into()); + Self { + fields: Some(value.fields.into()), + timeout, + next_sequence_send: value.next_sequence_send.into(), + } + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct ErrorReceipt { + pub sequence: Sequence, + pub message: String, +} + +impl Protobuf for ErrorReceipt {} + +impl TryFrom for ErrorReceipt { + type Error = ChannelError; + + fn try_from(value: RawErrorReceipt) -> Result { + Ok(Self { + sequence: value.sequence.into(), + message: value.message, + }) + } +} + +impl From for RawErrorReceipt { + fn from(value: ErrorReceipt) -> Self { + Self { + sequence: value.sequence.into(), + message: value.message, + } + } +} + +#[cfg(test)] +pub mod test_util { + use crate::core::ics04_channel::{ + timeout::test_util::get_dummy_upgrade_timeout, + upgrade_fields::test_util::get_dummy_upgrade_fields, + }; + use ibc_proto::ibc::core::channel::v1::Upgrade as RawUpgrade; + + pub fn get_dummy_upgrade() -> RawUpgrade { + RawUpgrade { + fields: Some(get_dummy_upgrade_fields()), + timeout: Some(get_dummy_upgrade_timeout()), + next_sequence_send: 1, + } + } +} diff --git a/crates/relayer-types/src/core/ics04_channel/upgrade_fields.rs b/crates/relayer-types/src/core/ics04_channel/upgrade_fields.rs new file mode 100644 index 0000000000..9d90ed41c1 --- /dev/null +++ b/crates/relayer-types/src/core/ics04_channel/upgrade_fields.rs @@ -0,0 +1,88 @@ +use core::str::FromStr; + +use ibc_proto::ibc::core::channel::v1::UpgradeFields as RawUpgradeFields; +use ibc_proto::Protobuf; +use itertools::Itertools; + +use crate::core::ics04_channel::channel::Ordering; +use crate::core::ics04_channel::error::Error as ChannelError; +use crate::core::ics04_channel::version::Version; +use crate::core::ics24_host::identifier::ConnectionId; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct UpgradeFields { + ordering: Ordering, + connection_hops: Vec, + version: Version, +} + +impl UpgradeFields { + pub fn new(ordering: Ordering, connection_hops: Vec, version: Version) -> Self { + Self { + ordering, + connection_hops, + version, + } + } +} + +impl Protobuf for UpgradeFields {} + +impl TryFrom for UpgradeFields { + type Error = ChannelError; + + fn try_from(value: RawUpgradeFields) -> Result { + use itertools::Either; + + let ordering = Ordering::from_i32(value.ordering)?; + + let (connection_hops, failures): (Vec<_>, Vec<_>) = value + .connection_hops + .iter() + .partition_map(|id| match ConnectionId::from_str(id) { + Ok(connection_id) => Either::Left(connection_id), + Err(e) => Either::Right((id.clone(), e)), + }); + + if !failures.is_empty() { + return Err(Self::Error::parse_connection_hops_vector(failures)); + } + + let version = Version::from(value.version); + + Ok(Self::new(ordering, connection_hops, version)) + } +} + +impl From for RawUpgradeFields { + fn from(value: UpgradeFields) -> Self { + let raw_connection_hops = value + .connection_hops + .iter() + .map(|id| id.to_string()) + .collect(); + Self { + ordering: value.ordering as i32, + connection_hops: raw_connection_hops, + version: value.version.to_string(), + } + } +} + +#[cfg(test)] +pub mod test_util { + use std::string::ToString; + use std::vec; + + use ibc_proto::ibc::core::channel::v1::UpgradeFields as RawUpgradeFields; + + use crate::core::ics04_channel::version::Version; + + pub fn get_dummy_upgrade_fields() -> RawUpgradeFields { + RawUpgradeFields { + ordering: 1, + connection_hops: vec![], + version: Version::ics20_with_fee().to_string(), + } + } +} diff --git a/crates/relayer-types/src/core/ics04_channel/version.rs b/crates/relayer-types/src/core/ics04_channel/version.rs index 0b60ecf3b1..daa5dd3759 100644 --- a/crates/relayer-types/src/core/ics04_channel/version.rs +++ b/crates/relayer-types/src/core/ics04_channel/version.rs @@ -4,18 +4,11 @@ use std::{ convert::Infallible, - fmt::{ - Display, - Error as FmtError, - Formatter, - }, + fmt::{Display, Error as FmtError, Formatter}, str::FromStr, }; -use serde_derive::{ - Deserialize, - Serialize, -}; +use serde_derive::{Deserialize, Serialize}; use serde_json as json; use crate::applications::transfer; @@ -25,7 +18,7 @@ use crate::applications::transfer; /// This field is opaque to the core IBC protocol. /// No explicit validation is necessary, and the /// spec (v1) currently allows empty strings. -#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] +#[derive(Clone, Debug, Eq, Deserialize, Serialize)] pub struct Version(pub String); impl Version { @@ -46,6 +39,15 @@ impl Version { Self::new(val.to_string()) } + pub fn app_version_with_fee(app_version: &str) -> Self { + let val = json::json!({ + "fee_version": "ics29-1", + "app_version": app_version, + }); + + Self::new(val.to_string()) + } + pub fn empty() -> Self { Self::new("".to_string()) } @@ -64,6 +66,28 @@ impl Version { } } +impl PartialEq for Version { + fn eq(&self, other: &Self) -> bool { + if self.0 != other.0 { + // If the Version strings don't match, check that this isn't due to the json + // fields being in a different order + let parsed_version = match serde_json::from_str::(&self.0) { + Ok(value) => value, + Err(_) => return false, + }; + let parsed_other = match serde_json::from_str::(&other.to_string()) { + Ok(value) => value, + Err(_) => return false, + }; + + if parsed_version != parsed_other { + return false; + } + } + true + } +} + impl From for Version { fn from(s: String) -> Self { Self::new(s) diff --git a/crates/relayer-types/src/core/ics23_commitment/commitment.rs b/crates/relayer-types/src/core/ics23_commitment/commitment.rs index dbc6e6c1e6..be9f1c3304 100644 --- a/crates/relayer-types/src/core/ics23_commitment/commitment.rs +++ b/crates/relayer-types/src/core/ics23_commitment/commitment.rs @@ -1,26 +1,10 @@ -use std::{ - convert::TryFrom, - fmt, -}; +use serde::{Deserialize, Serialize}; +use std::fmt; +use subtle_encoding::{Encoding, Hex}; +use super::{error::Error, merkle::MerkleProof}; +use crate::{proofs::ProofError, tx_msg::encode_message}; use ibc_proto::ibc::core::commitment::v1::MerkleProof as RawMerkleProof; -use serde::{ - Deserialize, - Serialize, -}; -use subtle_encoding::{ - Encoding, - Hex, -}; - -use super::{ - error::Error, - merkle::MerkleProof, -}; -use crate::{ - proofs::ProofError, - tx_msg::encode_message, -}; #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(transparent)] @@ -186,8 +170,7 @@ impl Serialize for CommitmentPrefix { pub mod test_util { use ibc_proto::{ - ibc::core::commitment::v1::MerkleProof as RawMerkleProof, - ics23::CommitmentProof, + ibc::core::commitment::v1::MerkleProof as RawMerkleProof, ics23::CommitmentProof, }; /// Returns a dummy `RawMerkleProof`, for testing only! diff --git a/crates/relayer-types/src/core/ics23_commitment/error.rs b/crates/relayer-types/src/core/ics23_commitment/error.rs index f4a22487f5..260c9557b4 100644 --- a/crates/relayer-types/src/core/ics23_commitment/error.rs +++ b/crates/relayer-types/src/core/ics23_commitment/error.rs @@ -1,7 +1,4 @@ -use flex_error::{ - define_error, - TraceError, -}; +use flex_error::{define_error, TraceError}; use prost::DecodeError; define_error! { diff --git a/crates/relayer-types/src/core/ics23_commitment/merkle.rs b/crates/relayer-types/src/core/ics23_commitment/merkle.rs index 881ab121d8..0b34fa29a4 100644 --- a/crates/relayer-types/src/core/ics23_commitment/merkle.rs +++ b/crates/relayer-types/src/core/ics23_commitment/merkle.rs @@ -1,23 +1,12 @@ -use ibc_proto::ibc::core::commitment::v1::{ - MerklePath, - MerkleProof as RawMerkleProof, - MerkleRoot, -}; +use ibc_proto::ibc::core::commitment::v1::{MerklePath, MerkleProof as RawMerkleProof, MerkleRoot}; use ics23::{ - calculate_existence_root, - commitment_proof::Proof, - verify_membership, - verify_non_membership, - CommitmentProof, - NonExistenceProof, + calculate_existence_root, commitment_proof::Proof, verify_membership, verify_non_membership, + CommitmentProof, NonExistenceProof, }; use tendermint::merkle::proof::ProofOps as TendermintProof; use crate::core::ics23_commitment::{ - commitment::{ - CommitmentPrefix, - CommitmentRoot, - }, + commitment::{CommitmentPrefix, CommitmentRoot}, error::Error, specs::ProofSpecs, }; @@ -111,7 +100,7 @@ impl MerkleProof { ) { return Err(Error::verification_failure()); } - value = subroot.clone(); + value.clone_from(&subroot); } _ => return Err(Error::invalid_merkle_proof()), } diff --git a/crates/relayer-types/src/core/ics23_commitment/mock.rs b/crates/relayer-types/src/core/ics23_commitment/mock.rs deleted file mode 100644 index 8b13789179..0000000000 --- a/crates/relayer-types/src/core/ics23_commitment/mock.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/relayer-types/src/core/ics23_commitment/mod.rs b/crates/relayer-types/src/core/ics23_commitment/mod.rs index e3806ad771..ecffa81d63 100644 --- a/crates/relayer-types/src/core/ics23_commitment/mod.rs +++ b/crates/relayer-types/src/core/ics23_commitment/mod.rs @@ -4,5 +4,4 @@ pub mod commitment; pub mod error; pub mod merkle; -pub mod mock; pub mod specs; diff --git a/crates/relayer-types/src/core/ics23_commitment/specs.rs b/crates/relayer-types/src/core/ics23_commitment/specs.rs index 9c7f942922..75486c955e 100644 --- a/crates/relayer-types/src/core/ics23_commitment/specs.rs +++ b/crates/relayer-types/src/core/ics23_commitment/specs.rs @@ -1,8 +1,5 @@ use ics23::ProofSpec; -use serde::{ - Deserialize, - Serialize, -}; +use serde::{Deserialize, Serialize}; /// An array of proof specifications. /// diff --git a/crates/relayer-types/src/core/ics24_host/error.rs b/crates/relayer-types/src/core/ics24_host/error.rs index 11e6983fe6..331d578a69 100644 --- a/crates/relayer-types/src/core/ics24_host/error.rs +++ b/crates/relayer-types/src/core/ics24_host/error.rs @@ -15,11 +15,20 @@ define_error! { min: usize, max: usize, } - | e | { format_args!("identifier {0} has invalid length {1} must be between {2}-{3} characters", e.id, e.length, e.min, e.max) }, + | e | { + format_args!( + "identifier {0} has invalid length {1} must be between {2}-{3} characters", + e.id, e.length, e.min, e.max + ) + }, InvalidCharacter { id: String } - | e | { format_args!("identifier {0} must only contain alphanumeric characters or `.`, `_`, `+`, `-`, `#`, - `[`, `]`, `<`, `>`", e.id) }, + | e | { + format_args!( + "identifier {0} must only contain alphanumeric characters or `.`, `_`, `+`, `-`, `#`, - `[`, `]`, `<`, `>`", e.id + ) + }, Empty | _ | { "identifier cannot be empty" }, @@ -29,6 +38,14 @@ define_error! { | e | { format_args!("chain identifiers are expected to be in epoch format {0}", e.id) }, InvalidCounterpartyChannelId - |_| { "Invalid channel id in counterparty" } + |_| { "invalid channel id in counterparty" } } } + +impl PartialEq for ValidationError { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} + +impl Eq for ValidationError {} diff --git a/crates/relayer-types/src/core/ics24_host/identifier.rs b/crates/relayer-types/src/core/ics24_host/identifier.rs index 66ccae442c..1c11bfd80f 100644 --- a/crates/relayer-types/src/core/ics24_host/identifier.rs +++ b/crates/relayer-types/src/core/ics24_host/identifier.rs @@ -1,28 +1,12 @@ -use std::{ - convert::{ - From, - Infallible, - }, - fmt::{ - Debug, - Display, - Error as FmtError, - Formatter, - }, - str::FromStr, -}; +use std::convert::Infallible; +use std::fmt::{Debug, Display, Error as FmtError, Formatter}; +use std::str::FromStr; use regex::Regex; -use serde::{ - Deserialize, - Serialize, -}; +use serde::{Deserialize, Serialize}; use super::validate::*; -use crate::core::{ - ics02_client::client_type::ClientType, - ics24_host::error::ValidationError, -}; +use crate::core::{ics02_client::client_type::ClientType, ics24_host::error::ValidationError}; /// This type is subject to future changes. /// @@ -192,9 +176,6 @@ impl ClientId { pub fn prefix(client_type: ClientType) -> &'static str { match client_type { ClientType::Tendermint => ClientType::Tendermint.as_str(), - - #[cfg(any(test, feature = "mocks"))] - ClientType::Mock => ClientType::Mock.as_str(), } } diff --git a/crates/relayer-types/src/core/ics24_host/mod.rs b/crates/relayer-types/src/core/ics24_host/mod.rs index 40eb80d8ab..23be43fb73 100644 --- a/crates/relayer-types/src/core/ics24_host/mod.rs +++ b/crates/relayer-types/src/core/ics24_host/mod.rs @@ -1,12 +1,7 @@ //! ICS 24: Host defines the minimal set of interfaces that a //! state machine hosting an IBC-enabled chain must implement. -pub use path::{ - ClientUpgradePath, - Path, - IBC_QUERY_PATH, - SDK_UPGRADE_QUERY_PATH, -}; +pub use path::{ClientUpgradePath, Path, IBC_QUERY_PATH, SDK_UPGRADE_QUERY_PATH}; pub mod error; pub mod identifier; diff --git a/crates/relayer-types/src/core/ics24_host/path.rs b/crates/relayer-types/src/core/ics24_host/path.rs index 3fde102b1b..66b3105524 100644 --- a/crates/relayer-types/src/core/ics24_host/path.rs +++ b/crates/relayer-types/src/core/ics24_host/path.rs @@ -4,20 +4,12 @@ /// use std::str::FromStr; -use derive_more::{ - Display, - From, -}; +use derive_more::{Display, From}; use flex_error::define_error; use crate::core::{ ics04_channel::packet::Sequence, - ics24_host::identifier::{ - ChannelId, - ClientId, - ConnectionId, - PortId, - }, + ics24_host::identifier::{ChannelId, ClientId, ConnectionId, PortId}, }; /// ABCI Query path for the IBC sub-store @@ -52,6 +44,22 @@ pub enum Path { Acks(AcksPath), Receipts(ReceiptsPath), Upgrade(ClientUpgradePath), + ChannelUpgrade(ChannelUpgradePath), + ChannelUpgradeError(ChannelUpgradeErrorPath), +} + +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)] +#[display(fmt = "channelUpgrades/upgradeError/ports/{port_id}/channels/{channel_id}")] +pub struct ChannelUpgradeErrorPath { + pub port_id: PortId, + pub channel_id: ChannelId, +} + +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)] +#[display(fmt = "channelUpgrades/upgrades/ports/{port_id}/channels/{channel_id}")] +pub struct ChannelUpgradePath { + pub port_id: PortId, + pub channel_id: ChannelId, } #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)] @@ -588,8 +596,6 @@ fn parse_upgrades(components: &[&str]) -> Option { #[cfg(test)] mod tests { - use core::str::FromStr; - use super::*; #[test] diff --git a/crates/relayer-types/src/core/ics24_host/validate.rs b/crates/relayer-types/src/core/ics24_host/validate.rs index bbe6187f87..8c8fc446ae 100644 --- a/crates/relayer-types/src/core/ics24_host/validate.rs +++ b/crates/relayer-types/src/core/ics24_host/validate.rs @@ -78,11 +78,8 @@ mod tests { use test_log::test; use crate::core::ics24_host::validate::{ - validate_channel_identifier, - validate_client_identifier, - validate_connection_identifier, - validate_identifier, - validate_port_identifier, + validate_channel_identifier, validate_client_identifier, validate_connection_identifier, + validate_identifier, validate_port_identifier, }; #[test] diff --git a/crates/relayer-types/src/core/ics26_routing/error.rs b/crates/relayer-types/src/core/ics26_routing/error.rs index b0112be80c..12020f405c 100644 --- a/crates/relayer-types/src/core/ics26_routing/error.rs +++ b/crates/relayer-types/src/core/ics26_routing/error.rs @@ -1,15 +1,8 @@ -use flex_error::{ - define_error, - TraceError, -}; +use flex_error::{define_error, TraceError}; use crate::{ applications::transfer, - core::{ - ics02_client, - ics03_connection, - ics04_channel, - }, + core::{ics02_client, ics03_connection, ics04_channel}, }; define_error! { diff --git a/crates/relayer-types/src/core/ics26_routing/msgs.rs b/crates/relayer-types/src/core/ics26_routing/msgs.rs index c95b0dc813..71d7536c4a 100644 --- a/crates/relayer-types/src/core/ics26_routing/msgs.rs +++ b/crates/relayer-types/src/core/ics26_routing/msgs.rs @@ -1,34 +1,13 @@ -use ibc_proto::{ - google::protobuf::Any, - Protobuf, -}; +use ibc_proto::{google::protobuf::Any, Protobuf}; use crate::core::{ - ics02_client::msgs::{ - create_client, - update_client, - upgrade_client, - ClientMsg, - }, + ics02_client::msgs::{create_client, update_client, upgrade_client, ClientMsg}, ics03_connection::msgs::{ - conn_open_ack, - conn_open_confirm, - conn_open_init, - conn_open_try, - ConnectionMsg, + conn_open_ack, conn_open_confirm, conn_open_init, conn_open_try, ConnectionMsg, }, ics04_channel::msgs::{ - acknowledgement, - chan_close_confirm, - chan_close_init, - chan_open_ack, - chan_open_confirm, - chan_open_init, - chan_open_try, - recv_packet, - timeout, - timeout_on_close, - ChannelMsg, + acknowledgement, chan_close_confirm, chan_close_init, chan_open_ack, chan_open_confirm, + chan_open_init, chan_open_try, recv_packet, timeout, timeout_on_close, ChannelMsg, PacketMsg, }, ics26_routing::error::Error, diff --git a/crates/relayer-types/src/events.rs b/crates/relayer-types/src/events.rs index 8bf42e8b65..7ceb45d5c2 100644 --- a/crates/relayer-types/src/events.rs +++ b/crates/relayer-types/src/events.rs @@ -1,60 +1,28 @@ -use std::{ - borrow::Cow, - convert::TryFrom, - fmt::{ - Display, - Error as FmtError, - Formatter, - }, - str::FromStr, -}; - -use flex_error::{ - define_error, - TraceError, -}; -use serde_derive::{ - Deserialize, - Serialize, -}; +use std::borrow::Cow; +use std::fmt::{Display, Error as FmtError, Formatter}; +use std::str::FromStr; + +use flex_error::{define_error, TraceError}; +use serde_derive::{Deserialize, Serialize}; use tendermint::abci; -use crate::{ - applications::{ - ics29_fee::{ - error::Error as FeeError, - events::{ - DistributeFeePacket, - IncentivizedPacket, - }, - }, - ics31_icq::{ - error::Error as QueryPacketError, - events::CrossChainQueryPacket, - }, - }, - core::{ - ics02_client::{ - error as client_error, - events as ClientEvents, - events::NewBlock, - }, - ics03_connection::{ - error as connection_error, - events as ConnectionEvents, - events::Attributes as ConnectionAttributes, - }, - ics04_channel::{ - error as channel_error, - events as ChannelEvents, - events::Attributes as ChannelAttributes, - packet::Packet, - }, - ics24_host::error::ValidationError, - }, - timestamp::ParseTimestampError, - utils::pretty::PrettySlice, -}; +use crate::applications::ics29_fee::error::Error as FeeError; +use crate::applications::ics29_fee::events::{DistributeFeePacket, IncentivizedPacket}; +use crate::applications::ics31_icq::error::Error as QueryPacketError; +use crate::applications::ics31_icq::events::CrossChainQueryPacket; +use crate::core::ics02_client::error as client_error; +use crate::core::ics02_client::events as ClientEvents; +use crate::core::ics02_client::events::NewBlock; +use crate::core::ics03_connection::error as connection_error; +use crate::core::ics03_connection::events as ConnectionEvents; +use crate::core::ics03_connection::events::Attributes as ConnectionAttributes; +use crate::core::ics04_channel::error as channel_error; +use crate::core::ics04_channel::events::Attributes as ChannelAttributes; +use crate::core::ics04_channel::events::{self as ChannelEvents, UpgradeAttributes}; +use crate::core::ics04_channel::packet::Packet; +use crate::core::ics24_host::error::ValidationError; +use crate::timestamp::ParseTimestampError; +use crate::utils::pretty::PrettySlice; define_error! { Error { @@ -97,9 +65,13 @@ define_error! { [ TraceError ] | _ | { "error decoding protobuf" }, - SubtleEncoding - [ TraceError ] - | _ | { "error decoding hex" }, + InvalidPacketData + { data: String } + | e | { format_args!("error decoding hex-encoded packet data: {}", e.data) }, + + InvalidPacketAck + { ack: String } + | e | { format_args!("error decoding hex-encoded packet ack: {}", e.ack) }, MissingActionString | _ | { "missing action string" }, @@ -160,6 +132,15 @@ const CHANNEL_OPEN_ACK_EVENT: &str = "channel_open_ack"; const CHANNEL_OPEN_CONFIRM_EVENT: &str = "channel_open_confirm"; const CHANNEL_CLOSE_INIT_EVENT: &str = "channel_close_init"; const CHANNEL_CLOSE_CONFIRM_EVENT: &str = "channel_close_confirm"; +/// Channel upgrade event types +const CHANNEL_UPGRADE_INIT_EVENT: &str = "channel_upgrade_init"; +const CHANNEL_UPGRADE_TRY_EVENT: &str = "channel_upgrade_try"; +const CHANNEL_UPGRADE_ACK_EVENT: &str = "channel_upgrade_ack"; +const CHANNEL_UPGRADE_CONFIRM_EVENT: &str = "channel_upgrade_confirm"; +const CHANNEL_UPGRADE_OPEN_EVENT: &str = "channel_upgrade_open"; +const CHANNEL_UPGRADE_CANCEL_EVENT: &str = "channel_upgrade_cancelled"; +const CHANNEL_UPGRADE_TIMEOUT_EVENT: &str = "channel_upgrade_timeout"; +const CHANNEL_UPGRADE_ERROR_EVENT: &str = "channel_upgrade_error"; /// Packet event types const SEND_PACKET_EVENT: &str = "send_packet"; const RECEIVE_PACKET_EVENT: &str = "receive_packet"; @@ -191,6 +172,14 @@ pub enum IbcEventType { OpenConfirmChannel, CloseInitChannel, CloseConfirmChannel, + UpgradeInitChannel, + UpgradeTryChannel, + UpgradeAckChannel, + UpgradeConfirmChannel, + UpgradeOpenChannel, + UpgradeCancelChannel, + UpgradeTimeoutChannel, + UpgradeErrorChannel, SendPacket, ReceivePacket, WriteAck, @@ -223,6 +212,14 @@ impl IbcEventType { IbcEventType::OpenConfirmChannel => CHANNEL_OPEN_CONFIRM_EVENT, IbcEventType::CloseInitChannel => CHANNEL_CLOSE_INIT_EVENT, IbcEventType::CloseConfirmChannel => CHANNEL_CLOSE_CONFIRM_EVENT, + IbcEventType::UpgradeInitChannel => CHANNEL_UPGRADE_INIT_EVENT, + IbcEventType::UpgradeTryChannel => CHANNEL_UPGRADE_TRY_EVENT, + IbcEventType::UpgradeAckChannel => CHANNEL_UPGRADE_ACK_EVENT, + IbcEventType::UpgradeConfirmChannel => CHANNEL_UPGRADE_CONFIRM_EVENT, + IbcEventType::UpgradeOpenChannel => CHANNEL_UPGRADE_OPEN_EVENT, + IbcEventType::UpgradeCancelChannel => CHANNEL_UPGRADE_CANCEL_EVENT, + IbcEventType::UpgradeTimeoutChannel => CHANNEL_UPGRADE_TIMEOUT_EVENT, + IbcEventType::UpgradeErrorChannel => CHANNEL_UPGRADE_ERROR_EVENT, IbcEventType::SendPacket => SEND_PACKET_EVENT, IbcEventType::ReceivePacket => RECEIVE_PACKET_EVENT, IbcEventType::WriteAck => WRITE_ACK_EVENT, @@ -259,6 +256,14 @@ impl FromStr for IbcEventType { CHANNEL_OPEN_CONFIRM_EVENT => Ok(IbcEventType::OpenConfirmChannel), CHANNEL_CLOSE_INIT_EVENT => Ok(IbcEventType::CloseInitChannel), CHANNEL_CLOSE_CONFIRM_EVENT => Ok(IbcEventType::CloseConfirmChannel), + CHANNEL_UPGRADE_INIT_EVENT => Ok(IbcEventType::UpgradeInitChannel), + CHANNEL_UPGRADE_TRY_EVENT => Ok(IbcEventType::UpgradeTryChannel), + CHANNEL_UPGRADE_ACK_EVENT => Ok(IbcEventType::UpgradeAckChannel), + CHANNEL_UPGRADE_CONFIRM_EVENT => Ok(IbcEventType::UpgradeConfirmChannel), + CHANNEL_UPGRADE_OPEN_EVENT => Ok(IbcEventType::UpgradeOpenChannel), + CHANNEL_UPGRADE_CANCEL_EVENT => Ok(IbcEventType::UpgradeCancelChannel), + CHANNEL_UPGRADE_TIMEOUT_EVENT => Ok(IbcEventType::UpgradeTimeoutChannel), + CHANNEL_UPGRADE_ERROR_EVENT => Ok(IbcEventType::UpgradeErrorChannel), SEND_PACKET_EVENT => Ok(IbcEventType::SendPacket), RECEIVE_PACKET_EVENT => Ok(IbcEventType::ReceivePacket), WRITE_ACK_EVENT => Ok(IbcEventType::WriteAck), @@ -297,6 +302,14 @@ pub enum IbcEvent { OpenConfirmChannel(ChannelEvents::OpenConfirm), CloseInitChannel(ChannelEvents::CloseInit), CloseConfirmChannel(ChannelEvents::CloseConfirm), + UpgradeInitChannel(ChannelEvents::UpgradeInit), + UpgradeTryChannel(ChannelEvents::UpgradeTry), + UpgradeAckChannel(ChannelEvents::UpgradeAck), + UpgradeConfirmChannel(ChannelEvents::UpgradeConfirm), + UpgradeOpenChannel(ChannelEvents::UpgradeOpen), + UpgradeCancelChannel(ChannelEvents::UpgradeCancel), + UpgradeTimeoutChannel(ChannelEvents::UpgradeTimeout), + UpgradeErrorChannel(ChannelEvents::UpgradeError), SendPacket(ChannelEvents::SendPacket), ReceivePacket(ChannelEvents::ReceivePacket), @@ -336,6 +349,14 @@ impl Display for IbcEvent { IbcEvent::OpenConfirmChannel(ev) => write!(f, "OpenConfirmChannel({ev})"), IbcEvent::CloseInitChannel(ev) => write!(f, "CloseInitChannel({ev})"), IbcEvent::CloseConfirmChannel(ev) => write!(f, "CloseConfirmChannel({ev})"), + IbcEvent::UpgradeInitChannel(ev) => write!(f, "UpgradeInitChannel({ev})"), + IbcEvent::UpgradeTryChannel(ev) => write!(f, "UpgradeTryChannel({ev})"), + IbcEvent::UpgradeAckChannel(ev) => write!(f, "UpgradeAckChannel({ev})"), + IbcEvent::UpgradeConfirmChannel(ev) => write!(f, "UpgradeConfirmChannel({ev})"), + IbcEvent::UpgradeOpenChannel(ev) => write!(f, "UpgradeOpenChannel({ev})"), + IbcEvent::UpgradeCancelChannel(ev) => write!(f, "UpgradeCancelChannel({ev})"), + IbcEvent::UpgradeTimeoutChannel(ev) => write!(f, "UpgradeTimeoutChannel({ev})"), + IbcEvent::UpgradeErrorChannel(ev) => write!(f, "UpgradeErrorChannel({ev})"), IbcEvent::SendPacket(ev) => write!(f, "SendPacket({ev})"), IbcEvent::ReceivePacket(ev) => write!(f, "ReceivePacket({ev})"), @@ -381,6 +402,14 @@ impl IbcEvent { IbcEvent::OpenConfirmChannel(_) => IbcEventType::OpenConfirmChannel, IbcEvent::CloseInitChannel(_) => IbcEventType::CloseInitChannel, IbcEvent::CloseConfirmChannel(_) => IbcEventType::CloseConfirmChannel, + IbcEvent::UpgradeInitChannel(_) => IbcEventType::UpgradeInitChannel, + IbcEvent::UpgradeTryChannel(_) => IbcEventType::UpgradeTryChannel, + IbcEvent::UpgradeAckChannel(_) => IbcEventType::UpgradeAckChannel, + IbcEvent::UpgradeConfirmChannel(_) => IbcEventType::UpgradeConfirmChannel, + IbcEvent::UpgradeOpenChannel(_) => IbcEventType::UpgradeOpenChannel, + IbcEvent::UpgradeCancelChannel(_) => IbcEventType::UpgradeCancelChannel, + IbcEvent::UpgradeTimeoutChannel(_) => IbcEventType::UpgradeTimeoutChannel, + IbcEvent::UpgradeErrorChannel(_) => IbcEventType::UpgradeErrorChannel, IbcEvent::SendPacket(_) => IbcEventType::SendPacket, IbcEvent::ReceivePacket(_) => IbcEventType::ReceivePacket, IbcEvent::WriteAcknowledgement(_) => IbcEventType::WriteAck, @@ -405,6 +434,20 @@ impl IbcEvent { } } + pub fn channel_upgrade_attributes(self) -> Option { + match self { + IbcEvent::UpgradeInitChannel(ev) => Some(ev.into()), + IbcEvent::UpgradeTryChannel(ev) => Some(ev.into()), + IbcEvent::UpgradeAckChannel(ev) => Some(ev.into()), + IbcEvent::UpgradeConfirmChannel(ev) => Some(ev.into()), + IbcEvent::UpgradeOpenChannel(ev) => Some(ev.into()), + IbcEvent::UpgradeCancelChannel(ev) => Some(ev.into()), + IbcEvent::UpgradeTimeoutChannel(ev) => Some(ev.into()), + IbcEvent::UpgradeErrorChannel(ev) => Some(ev.into()), + _ => None, + } + } + pub fn connection_attributes(&self) -> Option<&ConnectionAttributes> { match self { IbcEvent::OpenInitConnection(ev) => Some(ev.attributes()), diff --git a/crates/relayer-types/src/lib.rs b/crates/relayer-types/src/lib.rs index 43eb7c1ba4..eee880d3cb 100644 --- a/crates/relayer-types/src/lib.rs +++ b/crates/relayer-types/src/lib.rs @@ -4,11 +4,9 @@ #![allow(clippy::large_enum_variant)] #![deny( - // warnings, trivial_casts, trivial_numeric_casts, unused_import_braces, - unused_qualifications, rust_2018_idioms )] #![forbid(unsafe_code)] @@ -65,8 +63,5 @@ pub type Height = core::ics02_client::height::Height; #[cfg(test)] mod test; -#[cfg(any(test, feature = "mocks"))] +#[cfg(test)] pub mod test_utils; - -#[cfg(any(test, feature = "mocks"))] -pub mod mock; // Context mock, the underlying host chain, and client types: for testing all handlers. diff --git a/crates/relayer-types/src/mock/client_state.rs b/crates/relayer-types/src/mock/client_state.rs deleted file mode 100644 index 3d7c30c37a..0000000000 --- a/crates/relayer-types/src/mock/client_state.rs +++ /dev/null @@ -1,143 +0,0 @@ -use std::time::Duration; - -use ibc_proto::{ - google::protobuf::Any, - ibc::mock::ClientState as RawMockClientState, - Protobuf, -}; -use serde::{ - Deserialize, - Serialize, -}; - -use crate::{ - core::{ - ics02_client::{ - client_state::ClientState, - client_type::ClientType, - error::Error, - }, - ics24_host::identifier::ChainId, - }, - mock::{ - consensus_state::MockConsensusState, - header::MockHeader, - }, - Height, -}; - -pub const MOCK_CLIENT_STATE_TYPE_URL: &str = "/ibc.mock.ClientState"; - -/// 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)] -pub struct MockClientState { - pub header: MockHeader, - pub frozen_height: Option, -} - -impl MockClientState { - pub fn new(header: MockHeader) -> Self { - Self { - header, - frozen_height: None, - } - } - - pub fn latest_height(&self) -> Height { - self.header.height() - } -} - -impl Protobuf for MockClientState {} - -impl TryFrom for MockClientState { - type Error = Error; - - fn try_from(raw: RawMockClientState) -> Result { - Ok(Self::new(raw.header.unwrap().try_into()?)) - } -} - -impl From for RawMockClientState { - fn from(value: MockClientState) -> Self { - RawMockClientState { - header: Some(ibc_proto::ibc::mock::Header { - height: Some(value.header.height().into()), - timestamp: value.header.timestamp.nanoseconds(), - }), - } - } -} - -impl Protobuf for MockClientState {} - -impl TryFrom for MockClientState { - type Error = Error; - - fn try_from(raw: Any) -> Result { - use core::ops::Deref; - - use bytes::Buf; - use prost::Message; - - fn decode_client_state(buf: B) -> Result { - RawMockClientState::decode(buf) - .map_err(Error::decode)? - .try_into() - } - - match raw.type_url.as_str() { - MOCK_CLIENT_STATE_TYPE_URL => { - decode_client_state(raw.value.deref()).map_err(Into::into) - } - _ => Err(Error::unexpected_client_state_type( - MOCK_CLIENT_STATE_TYPE_URL.to_string(), - raw.type_url, - )), - } - } -} - -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), - } - } -} - -impl ClientState for MockClientState { - type UpgradeOptions = (); - - fn chain_id(&self) -> ChainId { - unimplemented!() - } - - fn client_type(&self) -> ClientType { - ClientType::Mock - } - - fn latest_height(&self) -> Height { - self.header.height() - } - - fn frozen_height(&self) -> Option { - self.frozen_height - } - - fn upgrade(&mut self, _upgrade_height: Height, _upgrade_options: (), _chain_id: ChainId) { - unimplemented!() - } - - fn expired(&self, _elapsed: Duration) -> bool { - false - } -} - -impl From for MockClientState { - fn from(cs: MockConsensusState) -> Self { - Self::new(cs.header) - } -} diff --git a/crates/relayer-types/src/mock/consensus_state.rs b/crates/relayer-types/src/mock/consensus_state.rs deleted file mode 100644 index 60558d00c4..0000000000 --- a/crates/relayer-types/src/mock/consensus_state.rs +++ /dev/null @@ -1,118 +0,0 @@ -use ibc_proto::{ - google::protobuf::Any, - ibc::mock::ConsensusState as RawMockConsensusState, - Protobuf, -}; -use serde::{ - Deserialize, - Serialize, -}; - -use crate::{ - core::{ - ics02_client::{ - client_type::ClientType, - consensus_state::ConsensusState, - error::Error, - }, - ics23_commitment::commitment::CommitmentRoot, - }, - mock::header::MockHeader, - timestamp::Timestamp, -}; - -pub const MOCK_CONSENSUS_STATE_TYPE_URL: &str = "/ibc.mock.ConsensusState"; - -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct MockConsensusState { - pub header: MockHeader, - pub root: CommitmentRoot, -} - -impl MockConsensusState { - pub fn new(header: MockHeader) -> Self { - MockConsensusState { - header, - root: CommitmentRoot::from(vec![0]), - } - } - - pub fn timestamp(&self) -> Timestamp { - self.header.timestamp - } -} - -impl Protobuf for MockConsensusState {} - -impl TryFrom for MockConsensusState { - type Error = Error; - - fn try_from(raw: RawMockConsensusState) -> Result { - let raw_header = raw.header.ok_or_else(Error::missing_raw_consensus_state)?; - - Ok(Self { - header: MockHeader::try_from(raw_header)?, - root: CommitmentRoot::from(vec![0]), - }) - } -} - -impl From for RawMockConsensusState { - fn from(value: MockConsensusState) -> Self { - RawMockConsensusState { - header: Some(ibc_proto::ibc::mock::Header { - height: Some(value.header.height().into()), - timestamp: value.header.timestamp.nanoseconds(), - }), - } - } -} - -impl Protobuf for MockConsensusState {} - -impl TryFrom for MockConsensusState { - type Error = Error; - - fn try_from(raw: Any) -> Result { - use core::ops::Deref; - - use bytes::Buf; - use prost::Message; - - fn decode_consensus_state(buf: B) -> Result { - RawMockConsensusState::decode(buf) - .map_err(Error::decode)? - .try_into() - } - - match raw.type_url.as_str() { - MOCK_CONSENSUS_STATE_TYPE_URL => { - decode_consensus_state(raw.value.deref()).map_err(Into::into) - } - _ => Err(Error::unknown_consensus_state_type(raw.type_url)), - } - } -} - -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), - } - } -} - -impl ConsensusState for MockConsensusState { - fn client_type(&self) -> ClientType { - ClientType::Mock - } - - fn root(&self) -> &CommitmentRoot { - &self.root - } - - fn timestamp(&self) -> Timestamp { - self.header.timestamp - } -} diff --git a/crates/relayer-types/src/mock/header.rs b/crates/relayer-types/src/mock/header.rs deleted file mode 100644 index b202c7ca44..0000000000 --- a/crates/relayer-types/src/mock/header.rs +++ /dev/null @@ -1,154 +0,0 @@ -use std::fmt::{ - Display, - Error as FmtError, - Formatter, -}; - -use ibc_proto::{ - google::protobuf::Any, - ibc::mock::Header as RawMockHeader, - Protobuf, -}; -use serde_derive::{ - Deserialize, - Serialize, -}; - -use crate::{ - core::ics02_client::{ - client_type::ClientType, - error::Error, - header::Header, - }, - timestamp::Timestamp, - Height, -}; - -pub const MOCK_HEADER_TYPE_URL: &str = "/ibc.mock.Header"; - -#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] -pub struct MockHeader { - pub height: Height, - pub timestamp: Timestamp, -} - -impl Default for MockHeader { - fn default() -> Self { - Self { - height: Height::new(0, 1).unwrap(), - timestamp: Default::default(), - } - } -} - -impl Display for MockHeader { - fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { - write!( - f, - "MockHeader {{ height: {}, timestamp: {} }}", - self.height, self.timestamp - ) - } -} - -impl Protobuf for MockHeader {} - -impl TryFrom for MockHeader { - type Error = Error; - - fn try_from(raw: RawMockHeader) -> Result { - Ok(MockHeader { - height: raw - .height - .and_then(|raw_height| raw_height.try_into().ok()) - .ok_or_else(Error::missing_raw_header)?, - - timestamp: Timestamp::from_nanoseconds(raw.timestamp) - .map_err(Error::invalid_packet_timestamp)?, - }) - } -} - -impl From for RawMockHeader { - fn from(value: MockHeader) -> Self { - RawMockHeader { - height: Some(value.height.into()), - timestamp: value.timestamp.nanoseconds(), - } - } -} - -impl MockHeader { - pub fn height(&self) -> Height { - self.height - } - - pub fn new(height: Height) -> Self { - Self { - height, - timestamp: Timestamp::now(), - } - } - - pub fn with_timestamp(self, timestamp: Timestamp) -> Self { - Self { timestamp, ..self } - } -} - -impl Header for MockHeader { - fn client_type(&self) -> ClientType { - ClientType::Mock - } - - fn height(&self) -> Height { - self.height - } - - fn timestamp(&self) -> Timestamp { - self.timestamp - } -} - -impl Protobuf for MockHeader {} - -impl TryFrom for MockHeader { - type Error = Error; - - fn try_from(raw: Any) -> Result { - match raw.type_url.as_str() { - MOCK_HEADER_TYPE_URL => Ok(Protobuf::::decode_vec(&raw.value) - .map_err(Error::invalid_raw_header)?), - _ => Err(Error::unknown_header_type(raw.type_url)), - } - } -} - -impl From for Any { - fn from(header: MockHeader) -> Self { - Any { - type_url: MOCK_HEADER_TYPE_URL.to_string(), - value: Protobuf::::encode_vec(header), - } - } -} - -#[cfg(test)] -mod tests { - use ibc_proto::Protobuf; - - use super::*; - - #[test] - fn encode_any() { - let header = MockHeader::new(Height::new(1, 10).unwrap()).with_timestamp(Timestamp::none()); - let bytes = >::encode_vec(header); - - assert_eq!( - &bytes, - &[ - 10, 16, 47, 105, 98, 99, 46, 109, 111, 99, 107, 46, 72, 101, 97, 100, 101, 114, 18, - 6, 10, 4, 8, 1, 16, 10 - ] - ); - } -} diff --git a/crates/relayer-types/src/mock/misbehaviour.rs b/crates/relayer-types/src/mock/misbehaviour.rs deleted file mode 100644 index bc33816f01..0000000000 --- a/crates/relayer-types/src/mock/misbehaviour.rs +++ /dev/null @@ -1,66 +0,0 @@ -use ibc_proto::{ - ibc::mock::Misbehaviour as RawMisbehaviour, - Protobuf, -}; -use serde::{ - Deserialize, - Serialize, -}; - -use crate::{ - core::{ - ics02_client::error::Error, - ics24_host::identifier::ClientId, - }, - mock::header::MockHeader, - Height, -}; - -pub const MOCK_MISBEHAVIOUR_TYPE_URL: &str = "/ibc.mock.Misbehavior"; - -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct Misbehaviour { - pub client_id: ClientId, - pub header1: MockHeader, - pub header2: MockHeader, -} - -impl crate::core::ics02_client::misbehaviour::Misbehaviour for Misbehaviour { - fn client_id(&self) -> &ClientId { - &self.client_id - } - - fn height(&self) -> Height { - self.header1.height() - } -} - -impl Protobuf for Misbehaviour {} - -impl TryFrom for Misbehaviour { - type Error = Error; - - fn try_from(raw: RawMisbehaviour) -> Result { - Ok(Self { - client_id: Default::default(), - header1: raw - .header1 - .ok_or_else(Error::missing_raw_misbehaviour)? - .try_into()?, - header2: raw - .header2 - .ok_or_else(Error::missing_raw_misbehaviour)? - .try_into()?, - }) - } -} - -impl From for RawMisbehaviour { - fn from(value: Misbehaviour) -> Self { - RawMisbehaviour { - client_id: value.client_id.to_string(), - header1: Some(value.header1.into()), - header2: Some(value.header2.into()), - } - } -} diff --git a/crates/relayer-types/src/mock/mod.rs b/crates/relayer-types/src/mock/mod.rs deleted file mode 100644 index 340dacdaef..0000000000 --- a/crates/relayer-types/src/mock/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -//! Implementation of mocks for context, host chain, and client. - -pub mod client_state; -pub mod consensus_state; -pub mod header; -pub mod misbehaviour; diff --git a/crates/relayer-types/src/proofs.rs b/crates/relayer-types/src/proofs.rs index 30477d63d2..97a8795771 100644 --- a/crates/relayer-types/src/proofs.rs +++ b/crates/relayer-types/src/proofs.rs @@ -1,14 +1,8 @@ -use flex_error::{ - define_error, - TraceError, -}; +use flex_error::{define_error, TraceError}; use prost::EncodeError; use serde::Serialize; -use crate::{ - core::ics23_commitment::commitment::CommitmentProofBytes, - Height, -}; +use crate::{core::ics23_commitment::commitment::CommitmentProofBytes, Height}; define_error! { #[derive(Debug, PartialEq, Eq)] diff --git a/crates/relayer-types/src/serializers.rs b/crates/relayer-types/src/serializers.rs index f28d8456b2..e1eaea366c 100644 --- a/crates/relayer-types/src/serializers.rs +++ b/crates/relayer-types/src/serializers.rs @@ -1,11 +1,5 @@ -use serde::ser::{ - Serialize, - Serializer, -}; -use subtle_encoding::{ - Encoding, - Hex, -}; +use serde::ser::{Serialize, Serializer}; +use subtle_encoding::{Encoding, Hex}; pub fn ser_hex_upper(data: T, serializer: S) -> Result where @@ -18,17 +12,9 @@ where pub mod serde_string { - use core::{ - fmt::Display, - str::FromStr, - }; + use core::{fmt::Display, str::FromStr}; - use serde::{ - de, - Deserialize, - Deserializer, - Serializer, - }; + use serde::{de, Deserialize, Deserializer, Serializer}; pub fn serialize(value: &T, serializer: S) -> Result where diff --git a/crates/relayer-types/src/signer.rs b/crates/relayer-types/src/signer.rs index b0b6203812..e016850c7d 100644 --- a/crates/relayer-types/src/signer.rs +++ b/crates/relayer-types/src/signer.rs @@ -2,10 +2,7 @@ use std::str::FromStr; use derive_more::Display; use flex_error::define_error; -use serde::{ - Deserialize, - Serialize, -}; +use serde::{Deserialize, Serialize}; define_error! { #[derive(Debug, PartialEq, Eq)] diff --git a/crates/relayer-types/src/test.rs b/crates/relayer-types/src/test.rs index f6ccd35d08..373a052929 100644 --- a/crates/relayer-types/src/test.rs +++ b/crates/relayer-types/src/test.rs @@ -1,9 +1,6 @@ use core::fmt::Debug; -use serde::{ - de::DeserializeOwned, - Serialize, -}; +use serde::{de::DeserializeOwned, Serialize}; /// Test that a struct `T` can be: /// diff --git a/crates/relayer-types/src/test_utils.rs b/crates/relayer-types/src/test_utils.rs index 733c479c5d..ea52217f22 100644 --- a/crates/relayer-types/src/test_utils.rs +++ b/crates/relayer-types/src/test_utils.rs @@ -1,9 +1,4 @@ -use tendermint::{ - block, - consensus, - evidence, - public_key::Algorithm, -}; +use tendermint::{block, consensus, evidence, public_key::Algorithm}; use crate::signer::Signer; diff --git a/crates/relayer-types/src/timestamp.rs b/crates/relayer-types/src/timestamp.rs index 767992abc4..a3f2950167 100644 --- a/crates/relayer-types/src/timestamp.rs +++ b/crates/relayer-types/src/timestamp.rs @@ -1,27 +1,14 @@ use std::{ - fmt::{ - Display, - Error as FmtError, - Formatter, - }, + fmt::{Display, Error as FmtError, Formatter}, hash::Hash, num::ParseIntError, - ops::{ - Add, - Sub, - }, + ops::{Add, Sub}, str::FromStr, time::Duration, }; -use flex_error::{ - define_error, - TraceError, -}; -use serde_derive::{ - Deserialize, - Serialize, -}; +use flex_error::{define_error, TraceError}; +use serde_derive::{Deserialize, Serialize}; use tendermint::Time; use time::OffsetDateTime; @@ -254,11 +241,7 @@ mod tests { use test_log::test; use time::OffsetDateTime; - use super::{ - Expiry, - Timestamp, - ZERO_DURATION, - }; + use super::{Expiry, Timestamp, ZERO_DURATION}; #[test] fn test_timestamp_comparisons() { diff --git a/crates/relayer-types/src/tx_msg.rs b/crates/relayer-types/src/tx_msg.rs index 9e152f13f7..2608fe57c8 100644 --- a/crates/relayer-types/src/tx_msg.rs +++ b/crates/relayer-types/src/tx_msg.rs @@ -1,8 +1,5 @@ use ibc_proto::google::protobuf::Any; -use prost::{ - EncodeError, - Message, -}; +use prost::{EncodeError, Message}; use crate::core::ics24_host::error::ValidationError; diff --git a/crates/relayer-types/src/utils/pretty.rs b/crates/relayer-types/src/utils/pretty.rs index 975bec308d..429b750f2f 100644 --- a/crates/relayer-types/src/utils/pretty.rs +++ b/crates/relayer-types/src/utils/pretty.rs @@ -1,17 +1,9 @@ use std::{ - fmt::{ - Debug, - Display, - Error as FmtError, - Formatter, - }, + fmt::{Debug, Display, Error as FmtError, Formatter}, time::Duration, }; -use tendermint::{ - block::signed_header::SignedHeader, - validator::Set as ValidatorSet, -}; +use tendermint::{block::signed_header::SignedHeader, validator::Set as ValidatorSet}; pub struct PrettyDuration<'a>(pub &'a Duration); @@ -89,10 +81,7 @@ impl<'a, T: Display> Display for PrettySlice<'a, T> { #[cfg(test)] mod tests { - use std::{ - string::String, - vec, - }; + use std::vec; use super::*; diff --git a/crates/relayer/Cargo.toml b/crates/relayer/Cargo.toml index 6b252fe9d4..0ac6285ac8 100644 --- a/crates/relayer/Cargo.toml +++ b/crates/relayer/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "ibc-relayer" -version = "0.26.4" +version = "0.29.3" 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.71" +rust-version = "1.76.0" description = """ Implementation of an IBC Relayer in Rust, as a library """ @@ -17,111 +17,83 @@ all-features = true [features] default = ["flex-error/std", "flex-error/eyre_tracer"] -telemetry = ["ibc-telemetry"] [dependencies] -ibc-proto = { version = "0.41.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"] } - -astria-core = { git = "https://github.com/astriaorg/astria", tag = "sequencer-v0.16.0" } -astria-sequencer-client = { git = "https://github.com/astriaorg/astria", tag = "sequencer-v0.16.0", features = [ "http" ] } +astria-core = { git = "https://github.com/astriaorg/astria", rev = "070cfee5b87c82819f87dc62a48870c5c22bc108" } +astria-sequencer-client = { git = "https://github.com/astriaorg/astria", rev = "070cfee5b87c82819f87dc62a48870c5c22bc108", features = [ "http" ] } ed25519-consensus = "2.1.0" -ibc-types = "0.12.0" -jmt = "0.6" -penumbra-ibc = { git = "https://github.com/penumbra-zone/penumbra.git", rev = "87adc8d6b15f6081c1adf169daed4ca8873bd9f6", default-features = false } -penumbra-proto = { git = "https://github.com/penumbra-zone/penumbra.git", rev = "87adc8d6b15f6081c1adf169daed4ca8873bd9f6" } -pbjson-types = "0.6" - -subtle-encoding = "0.5" -humantime-serde = "1.1.1" -serde = "1.0" -serde_derive = "1.0" -thiserror = "1.0.40" -toml = "0.8" -tracing = "0.1.36" -tokio = { version = "1.0", features = ["rt-multi-thread", "time", "sync"] } -serde_json = { version = "1" } -bytes = "1.4.0" -prost = { version = "0.12" } -tonic = { version = "0.10", features = ["tls", "tls-roots"] } -futures = "0.3" -crossbeam-channel = "0.5.11" -hex = "0.4" -bitcoin = { version = "0.31.1", features = ["serde"] } -tiny-bip39 = "1.0.0" -hdpath = "0.6.3" -sha2 = "0.10.6" -tiny-keccak = { version = "2.0.2", features = ["keccak"], default-features = false } -ripemd = "0.1.3" -bech32 = "0.9.1" -itertools = "0.10.5" -dirs-next = "2.0.0" -retry = { version = "2.0.0", default-features = false } -async-stream = "0.3.5" -http = "0.2.9" -flex-error = { version = "0.4.4", default-features = false } -signature = "2.1.0" -anyhow = "1.0" -semver = "1.0" -humantime = "2.1.0" -regex = "1" -moka = { version = "0.12.0", features = ["sync"] } -uuid = { version = "1.6.1", features = ["v4"] } -bs58 = "0.5.0" -digest = "0.10.6" -ed25519 = "2.2.2" -ed25519-dalek = { version = "2.0.0", features = ["serde"] } -ed25519-dalek-bip32 = "0.3.0" -generic-array = "0.14.7" -secp256k1 = { version = "0.28.1", features = ["rand-std"] } -strum = { version = "0.25", features = ["derive"] } -tokio-stream = "0.1.14" -once_cell = "1.19.0" -tracing-subscriber = { version = "0.3.14", features = ["fmt", "env-filter", "json"] } - -[dependencies.byte-unit] -version = "4.0.19" -default-features = false -features = ["serde"] - -[dependencies.num-bigint] -version = "0.4" -features = ["serde"] - -[dependencies.num-rational] -version = "0.4.1" -features = ["num-bigint", "serde"] - -[dependencies.tendermint] -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"] - -[dependencies.tendermint-light-client] -version = "0.34.0" -default-features = false -features = ["rpc-client", "secp256k1", "unstable"] - -[dependencies.tendermint-light-client-detector] -version = "0.34.0" -default-features = false - -[dependencies.tendermint-light-client-verifier] -version = "0.34.0" -default-features = false +ibc-types = "0.14" +jmt = "0.10" +penumbra-ibc = { git = "https://github.com/penumbra-zone/penumbra.git", tag = "v0.80.5", default-features = false } +penumbra-proto = { git = "https://github.com/penumbra-zone/penumbra.git", tag = "v0.80.5" } +pbjson-types = "0.7" + +ibc-proto = { workspace = true, features = ["serde"] } +ibc-telemetry = { workspace = true } +ibc-relayer-types = { workspace = true, features = ["clock"] } + +anyhow = { workspace = true } +async-stream = { workspace = true } +bech32 = { workspace = true } +bitcoin = { workspace = true, features = ["serde"] } +bs58 = { workspace = true } +byte-unit = { workspace = true, features = ["serde"] } +bytes = { workspace = true } +crossbeam-channel = { workspace = true } +digest = { workspace = true } +dirs-next = { workspace = true } +ed25519 = { workspace = true } +ed25519-dalek = { workspace = true, features = ["serde"] } +ed25519-dalek-bip32 = { workspace = true } +flex-error = { workspace = true } +futures = { workspace = true } +generic-array = { workspace = true } +hdpath = { workspace = true } +hex = { workspace = true } +http = { workspace = true } +humantime = { workspace = true } +humantime-serde = { workspace = true } +itertools = { workspace = true } +moka = { workspace = true, features = ["sync"] } +num-bigint = { workspace = true, features = ["serde"] } +num-rational = { workspace = true, features = ["num-bigint", "serde"] } +once_cell = { workspace = true } +prost = { workspace = true } +regex = { workspace = true } +reqwest = { workspace = true, features = ["rustls-tls-native-roots", "json"] } +retry = { workspace = true } +ripemd = { workspace = true } +secp256k1 = { workspace = true, features = ["rand-std"] } +semver = { workspace = true } +serde = { workspace = true } +serde_derive = { workspace = true } +serde_json = { workspace = true } +sha2 = { workspace = true } +signature = { workspace = true } +strum = { workspace = true, features = ["derive"] } +subtle-encoding = { workspace = true } +tendermint = { workspace = true, features = ["secp256k1"] } +tendermint-light-client = { workspace = true, features = ["rpc-client", "secp256k1", "unstable"] } +tendermint-light-client-detector = { workspace = true } +tendermint-light-client-verifier = { workspace = true } +tendermint-proto = { workspace = true } +tendermint-rpc = { workspace = true, features = ["http-client", "websocket-client"] } +thiserror = { workspace = true } +tiny-bip39 = { workspace = true } +tiny-keccak = { workspace = true, features = ["keccak"] } +tokio = { workspace = true, features = ["rt-multi-thread", "time", "sync"] } +tokio-stream = { workspace = true } +toml = { workspace = true } +tonic = { workspace = true, features = ["tls", "tls-roots"] } +tracing = { workspace = true } +tracing-subscriber = { workspace = true, features = ["fmt", "env-filter", "json"] } +uuid = { workspace = true, features = ["v4"] } [dev-dependencies] -ibc-relayer-types = { version = "0.26.4", path = "../relayer-types", features = ["mocks"] } -serial_test = "2.0.0" -env_logger = "0.10.0" -test-log = { version = "0.2.14", features = ["trace"] } +ibc-relayer-types = { workspace = true } +serial_test = { workspace = true } +env_logger = { workspace = true } +test-log = { workspace = true, features = ["trace"] } # Needed for generating (synthetic) light blocks. -tendermint-testgen = { version = "0.34.0" } +tendermint-testgen = { workspace = true } diff --git a/crates/relayer/src/account.rs b/crates/relayer/src/account.rs index 1e993fd8d1..8ee076ab6e 100644 --- a/crates/relayer/src/account.rs +++ b/crates/relayer/src/account.rs @@ -1,9 +1,6 @@ //! Data structures related to the accounts used by the relayer. -use serde::{ - Deserialize, - Serialize, -}; +use serde::{Deserialize, Serialize}; /// The balance for a specific denom #[derive(Clone, Debug, Serialize, Deserialize)] diff --git a/crates/relayer/src/cache.rs b/crates/relayer/src/cache.rs index b8021e197c..dacab151be 100644 --- a/crates/relayer/src/cache.rs +++ b/crates/relayer/src/cache.rs @@ -3,20 +3,13 @@ //! Utilizes the [`moka`](https://docs.rs/moka) crate, which provides full //! concurrency of retrievals and a high expected concurrency for updates. use core::fmt::Formatter; -use std::{ - fmt, - time::Duration, -}; +use std::{fmt, time::Duration}; use ibc_relayer_types::core::{ ics02_client::height::Height, ics03_connection::connection::ConnectionEnd, ics04_channel::channel::ChannelEnd, - ics24_host::identifier::{ - ClientId, - ConnectionId, - PortChannelId, - }, + ics24_host::identifier::{ClientId, ConnectionId, PortChannelId}, }; use moka::sync::Cache as MokaCache; @@ -106,6 +99,9 @@ impl Cache { where F: FnOnce() -> Result, { + // FIXME: If a channel being upgraded is queried using Latest + // Height, it might return the wrong Channel End information. + // Find an alternative to avoid this issue if let Some(chan) = self.channels.get(id) { // If cache hit, return it. Ok((chan, CacheStatus::Hit)) diff --git a/crates/relayer/src/chain/astria/endpoint.rs b/crates/relayer/src/chain/astria/endpoint.rs index e4bebbde63..842430766e 100644 --- a/crates/relayer/src/chain/astria/endpoint.rs +++ b/crates/relayer/src/chain/astria/endpoint.rs @@ -1,54 +1,32 @@ use alloc::sync::Arc; -use std::{ - str::FromStr as _, - time::Duration, -}; +use std::{str::FromStr as _, time::Duration}; +use ibc_proto::ibc::core::channel::v1::{QueryUpgradeErrorRequest, QueryUpgradeRequest}; use ibc_proto::ibc::{ - apps::fee::v1::{ - QueryIncentivizedPacketRequest, - QueryIncentivizedPacketResponse, - }, + apps::fee::v1::{QueryIncentivizedPacketRequest, QueryIncentivizedPacketResponse}, core::{ channel::v1::query_client::QueryClient as IbcChannelQueryClient, client::v1::query_client::QueryClient as IbcClientQueryClient, connection::v1::query_client::QueryClient as IbcConnectionQueryClient, }, }; +use ibc_relayer_types::core::ics02_client::height::Height; +use ibc_relayer_types::core::ics04_channel::upgrade::{ErrorReceipt, Upgrade}; use ibc_relayer_types::{ applications::ics31_icq::response::CrossChainQueryResponse, clients::ics07_tendermint::{ client_state::ClientState as TendermintClientState, - consensus_state::ConsensusState as TendermintConsensusState, - header::Header, + consensus_state::ConsensusState as TendermintConsensusState, header::Header, }, core::{ - ics02_client::{ - client_type::ClientType, - events::UpdateClient, - }, - ics03_connection::connection::{ - ConnectionEnd, - IdentifiedConnectionEnd, - }, + ics02_client::{client_type::ClientType, events::UpdateClient}, + ics03_connection::connection::{ConnectionEnd, IdentifiedConnectionEnd}, ics04_channel::{ - channel::{ - ChannelEnd, - IdentifiedChannelEnd, - }, + channel::{ChannelEnd, IdentifiedChannelEnd}, packet::Sequence, }, - ics23_commitment::{ - commitment::CommitmentPrefix, - merkle::MerkleProof, - }, - ics24_host::identifier::{ - ChainId, - ChannelId, - ClientId, - ConnectionId, - PortId, - }, + ics23_commitment::{commitment::CommitmentPrefix, merkle::MerkleProof}, + ics24_host::identifier::{ChainId, ChannelId, ClientId, ConnectionId, PortId}, }, signer::Signer, Height as ICSHeight, @@ -58,12 +36,8 @@ use tendermint::time::Time as TmTime; use tendermint_light_client::verifier::types::LightBlock; use tendermint_rpc::{ client::CompatMode, - endpoint::{ - broadcast::tx_sync::Response as TxResponse, - status, - }, - Client as _, - HttpClient, + endpoint::{broadcast::tx_sync::Response as TxResponse, status}, + Client as _, HttpClient, }; use tokio::runtime::Runtime as TokioRuntime; use tonic::IntoRequest; @@ -72,49 +46,28 @@ use tracing::warn; use crate::{ account::Balance, chain::{ - astria::utils::{ - decode_merkle_proof, - response_to_tx_sync_result, - }, + astria::utils::{decode_merkle_proof, response_to_tx_sync_result}, client::ClientSettings, - cosmos::{ - version::Specs, - wait::wait_for_block_commits, - }, - endpoint::{ - ChainEndpoint, - ChainStatus, - HealthCheck, - }, + cosmos::{version::Specs, wait::wait_for_block_commits}, + endpoint::{ChainEndpoint, ChainStatus, HealthCheck}, handle::Subscription, requests::*, tracking::TrackedMsgs, }, - client_state::{ - AnyClientState, - IdentifiedAnyClientState, - }, + client_state::{AnyClientState, IdentifiedAnyClientState}, config::ChainConfig, consensus_state::AnyConsensusState, denom::DenomTrace, error::Error, event::{ - source::{ - EventSource, - TxEventSourceCmd, - }, + source::{EventSource, TxEventSourceCmd}, IbcEventWithHeight, }, - keyring::{ - Ed25519KeyPair, - KeyRing, - }, - light_client::{ - tendermint::LightClient, - LightClient as _, - }, + keyring::{Ed25519KeyPair, KeyRing}, + light_client::{tendermint::LightClient, LightClient as _}, misbehaviour::MisbehaviourEvidence, }; +use astria_core::protocol::transaction::v1alpha1::UnsignedTransactionBuilder; const DEFAULT_RPC_TIMEOUT: Duration = Duration::from_secs(60); @@ -216,10 +169,14 @@ impl AstriaEndpoint { *batch_delay, self.rt.clone(), ), - Mode::Pull { interval } => EventSource::rpc( + Mode::Pull { + interval, + max_retries, + } => EventSource::rpc( self.id().clone(), self.sequencer_client.clone(), *interval, + *max_retries, self.rt.clone(), ), } @@ -231,18 +188,10 @@ impl AstriaEndpoint { async fn broadcast_messages(&mut self, tracked_msgs: TrackedMsgs) -> Result { use astria_core::{ - crypto::{ - SigningKey, - VerificationKey, - }, + crypto::{SigningKey, VerificationKey}, generated::protocol::transactions::v1alpha1::Ics20Withdrawal as RawIcs20Withdrawal, primitive::v1::Address, - protocol::transaction::v1alpha1::{ - action::Ics20Withdrawal, - Action, - TransactionParams, - UnsignedTransaction, - }, + protocol::transaction::v1alpha1::{action::Ics20Withdrawal, Action}, Protobuf as _, }; use astria_sequencer_client::SequencerClientExt as _; @@ -287,13 +236,12 @@ impl AstriaEndpoint { .await .map_err(|e| Error::other(Box::new(e)))?; - let unsigned_tx = UnsignedTransaction { - params: TransactionParams::builder() - .nonce(nonce.nonce) - .chain_id(self.id().to_string()) - .build(), - actions, - }; + let unsigned_tx = UnsignedTransactionBuilder::new() + .nonce(nonce.nonce) + .chain_id(self.id().to_string()) + .actions(actions) + .try_build() + .map_err(|e| Error::other(e.into()))?; let signed_tx = unsigned_tx.into_signed(&SigningKey::from(signing_key.to_bytes())); let tx_bytes = signed_tx.into_raw().encode_to_vec(); @@ -599,14 +547,8 @@ impl ChainEndpoint for AstriaEndpoint { _key_name: Option<&str>, denom: Option<&str>, ) -> Result { - use astria_core::{ - crypto::VerificationKey, - protocol::account::v1alpha1::AssetBalance, - }; - use astria_sequencer_client::{ - Address, - SequencerClientExt as _, - }; + use astria_core::{crypto::VerificationKey, protocol::account::v1alpha1::AssetBalance}; + use astria_sequencer_client::{Address, SequencerClientExt as _}; let signing_key: ed25519_consensus::SigningKey = (*self.get_key()?.signing_key().as_bytes()).into(); // TODO cache this @@ -680,10 +622,7 @@ impl ChainEndpoint for AstriaEndpoint { &self, request: QueryClientStatesRequest, ) -> Result, Error> { - use crate::{ - chain::cosmos::client_id_suffix, - util::pretty::PrettyIdentifiedClientState, - }; + use crate::{chain::cosmos::client_id_suffix, util::pretty::PrettyIdentifiedClientState}; let mut client = self.ibc_client_grpc_client.clone(); @@ -1379,10 +1318,7 @@ impl ChainEndpoint for AstriaEndpoint { mut request: QueryPacketEventDataRequest, ) -> Result, Error> { use crate::chain::cosmos::{ - query::tx::{ - query_packets_from_block, - query_packets_from_txs, - }, + query::tx::{query_packets_from_block, query_packets_from_txs}, sort_events_by_sequence, }; @@ -1538,4 +1474,22 @@ impl ChainEndpoint for AstriaEndpoint { fn query_consumer_chains(&self) -> Result, Error> { todo!() } + + fn query_upgrade( + &self, + request: QueryUpgradeRequest, + height: Height, + include_proof: IncludeProof, + ) -> Result<(Upgrade, Option), Error> { + todo!() + } + + fn query_upgrade_error( + &self, + request: QueryUpgradeErrorRequest, + height: Height, + include_proof: IncludeProof, + ) -> Result<(ErrorReceipt, Option), Error> { + todo!() + } } diff --git a/crates/relayer/src/chain/astria/utils.rs b/crates/relayer/src/chain/astria/utils.rs index c3696eee9e..abcb37d445 100644 --- a/crates/relayer/src/chain/astria/utils.rs +++ b/crates/relayer/src/chain/astria/utils.rs @@ -1,15 +1,11 @@ use ibc_relayer_types::core::{ - ics23_commitment::merkle::MerkleProof, - ics24_host::identifier::ChainId, + ics23_commitment::merkle::MerkleProof, ics24_host::identifier::ChainId, }; use ibc_types::DomainType as _; use tendermint_rpc::endpoint::broadcast::tx_sync::Response; use crate::{ - chain::cosmos::types::tx::{ - TxStatus, - TxSyncResult, - }, + chain::cosmos::types::tx::{TxStatus, TxSyncResult}, error::Error, event::IbcEventWithHeight, }; diff --git a/crates/relayer/src/chain/client.rs b/crates/relayer/src/chain/client.rs index 8b6df2ea71..18cb000139 100644 --- a/crates/relayer/src/chain/client.rs +++ b/crates/relayer/src/chain/client.rs @@ -1,10 +1,6 @@ //! Data structures and logic to set up IBC client's parameters. -use crate::{ - chain::cosmos, - config::ChainConfig, - foreign_client::CreateOptions, -}; +use crate::{chain::cosmos, config::ChainConfig, foreign_client::CreateOptions}; /// Client parameters for the `build_create_client` operation. /// diff --git a/crates/relayer/src/chain/cosmos.rs b/crates/relayer/src/chain/cosmos.rs index e89224f7b5..eec0b29bfe 100644 --- a/crates/relayer/src/chain/cosmos.rs +++ b/crates/relayer/src/chain/cosmos.rs @@ -1,233 +1,128 @@ use alloc::sync::Arc; -use core::{ - convert::{ - TryFrom, - TryInto, - }, - future::Future, - str::FromStr, - time::Duration, +use bytes::Buf; +use bytes::Bytes; +use core::{future::Future, str::FromStr, time::Duration}; +use futures::future::join_all; +use num_bigint::BigInt; +use prost::Message; +use std::cmp::Ordering; +use std::thread; +use tokio::runtime::Runtime as TokioRuntime; +use tonic::codegen::http::Uri; +use tonic::metadata::AsciiMetadataValue; +use tracing::{debug, error, instrument, trace, warn}; + +use ibc_proto::cosmos::base::node::v1beta1::ConfigResponse; +use ibc_proto::cosmos::staking::v1beta1::{Params as StakingParams, QueryParamsResponse}; +use ibc_proto::ibc::apps::fee::v1::{ + QueryIncentivizedPacketRequest, QueryIncentivizedPacketResponse, }; -use std::{ - cmp::Ordering, - thread, +use ibc_proto::ibc::core::channel::v1::{QueryUpgradeErrorRequest, QueryUpgradeRequest}; +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, }; - -use bytes::{ - Buf, - Bytes, +use ibc_relayer_types::clients::ics07_tendermint::consensus_state::ConsensusState as TmConsensusState; +use ibc_relayer_types::clients::ics07_tendermint::header::Header as TmHeader; +use ibc_relayer_types::core::ics02_client::client_type::ClientType; +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::ics03_connection::connection::{ + ConnectionEnd, IdentifiedConnectionEnd, }; -use futures::future::join_all; -use ibc_proto::{ - cosmos::{ - base::node::v1beta1::ConfigResponse, - staking::v1beta1::Params as StakingParams, - }, - ibc::apps::fee::v1::{ - QueryIncentivizedPacketRequest, - QueryIncentivizedPacketResponse, - }, - interchain_security::ccv::v1::ConsumerParams as CcvConsumerParams, - Protobuf, +use ibc_relayer_types::core::ics04_channel::channel::{ChannelEnd, IdentifiedChannelEnd}; +use ibc_relayer_types::core::ics04_channel::channel::{State, UpgradeState}; +use ibc_relayer_types::core::ics04_channel::packet::Sequence; +use ibc_relayer_types::core::ics23_commitment::commitment::CommitmentPrefix; +use ibc_relayer_types::core::ics23_commitment::merkle::MerkleProof; +use ibc_relayer_types::core::ics24_host::identifier::{ + ChainId, ChannelId, ClientId, ConnectionId, PortId, }; -use ibc_relayer_types::{ - applications::ics31_icq::response::CrossChainQueryResponse, - clients::ics07_tendermint::{ - client_state::{ - AllowUpdate, - ClientState as TmClientState, - }, - consensus_state::ConsensusState as TmConsensusState, - header::Header as TmHeader, - }, - core::{ - ics02_client::{ - client_type::ClientType, - error::Error as ClientError, - events::UpdateClient, - }, - ics03_connection::connection::{ - ConnectionEnd, - IdentifiedConnectionEnd, - }, - ics04_channel::{ - channel::{ - ChannelEnd, - IdentifiedChannelEnd, - }, - packet::Sequence, - }, - ics23_commitment::{ - commitment::CommitmentPrefix, - merkle::MerkleProof, - }, - ics24_host::{ - identifier::{ - ChainId, - ChannelId, - ClientId, - ConnectionId, - PortId, - }, - path::{ - AcksPath, - ChannelEndsPath, - ClientConsensusStatePath, - ClientStatePath, - CommitmentsPath, - ConnectionsPath, - ReceiptsPath, - SeqRecvsPath, - }, - ClientUpgradePath, - Path, - IBC_QUERY_PATH, - SDK_UPGRADE_QUERY_PATH, - }, - }, - signer::Signer, - Height as ICSHeight, +use ibc_relayer_types::core::ics24_host::path::{ + AcksPath, ChannelEndsPath, ChannelUpgradeErrorPath, ChannelUpgradePath, + ClientConsensusStatePath, ClientStatePath, CommitmentsPath, ConnectionsPath, ReceiptsPath, + SeqRecvsPath, }; -use num_bigint::BigInt; -use tendermint::{ - block::Height as TmHeight, - node::{ - self, - info::TxIndexStatus, - }, - time::Time as TmTime, +use ibc_relayer_types::core::ics24_host::{ + ClientUpgradePath, Path, IBC_QUERY_PATH, SDK_UPGRADE_QUERY_PATH, }; -use tendermint_light_client::verifier::types::LightBlock as TmLightBlock; -use tendermint_rpc::{ - client::CompatMode, - endpoint::{ - broadcast::tx_sync::Response, - status, - }, - Client, - HttpClient, - Order, +use ibc_relayer_types::core::{ + ics02_client::height::Height, ics04_channel::upgrade::ErrorReceipt, + ics04_channel::upgrade::Upgrade, }; -use tokio::runtime::Runtime as TokioRuntime; -use tonic::{ - codegen::http::Uri, - metadata::AsciiMetadataValue, +use ibc_relayer_types::signer::Signer; +use ibc_relayer_types::Height as ICSHeight; + +use tendermint::block::Height as TmHeight; +use tendermint::node::{self, info::TxIndexStatus}; +use tendermint::time::Time as TmTime; +use tendermint_light_client::verifier::types::LightBlock as TmLightBlock; +use tendermint_rpc::client::CompatMode; +use tendermint_rpc::endpoint::broadcast::tx_sync::Response; +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, }; -use tracing::{ - debug, - error, - info, - instrument, - trace, - warn, +use crate::chain::cosmos::encode::key_pair_to_signer; +use crate::chain::cosmos::fee::maybe_register_counterparty_payee; +use crate::chain::cosmos::gas::{calculate_fee, mul_ceil}; +use crate::chain::cosmos::query::account::get_or_fetch_account; +use crate::chain::cosmos::query::balance::{query_all_balances, query_balance}; +use crate::chain::cosmos::query::connection::query_connection_params; +use crate::chain::cosmos::query::consensus_state::query_consensus_state_heights; +use crate::chain::cosmos::query::custom::cross_chain_query_via_rpc; +use crate::chain::cosmos::query::denom_trace::query_denom_trace; +use crate::chain::cosmos::query::fee::query_incentivized_packet; +use crate::chain::cosmos::query::status::query_status; +use crate::chain::cosmos::query::tx::{ + filter_matching_event, query_packets_from_block, query_packets_from_txs, query_txs, }; - -use self::{ - types::app_state::GenesisAppState, - version::Specs, +use crate::chain::cosmos::query::{abci_query, fetch_version_specs, packet_query, QueryResponse}; +use crate::chain::cosmos::types::account::Account; +use crate::chain::cosmos::types::config::TxConfig; +use crate::chain::cosmos::types::gas::{ + default_gas_from_config, gas_multiplier_from_config, max_gas_from_config, }; -use crate::{ - account::Balance, - chain::{ - client::ClientSettings, - cosmos::{ - batch::{ - send_batched_messages_and_wait_check_tx, - send_batched_messages_and_wait_commit, - sequential_send_batched_messages_and_wait_commit, - }, - encode::key_pair_to_signer, - fee::maybe_register_counterparty_payee, - gas::{ - calculate_fee, - mul_ceil, - }, - query::{ - abci_query, - account::get_or_fetch_account, - balance::{ - query_all_balances, - query_balance, - }, - consensus_state::query_consensus_state_heights, - custom::cross_chain_query_via_rpc, - denom_trace::query_denom_trace, - fee::query_incentivized_packet, - fetch_version_specs, - packet_query, - status::query_status, - tx::{ - filter_matching_event, - query_packets_from_block, - query_packets_from_txs, - query_txs, - }, - QueryResponse, - }, - types::{ - account::Account, - config::TxConfig, - gas::{ - default_gas_from_config, - gas_multiplier_from_config, - max_gas_from_config, - }, - }, - }, - endpoint::{ - ChainEndpoint, - ChainStatus, - HealthCheck, - }, - handle::Subscription, - requests::*, - tracking::TrackedMsgs, - }, - client_state::{ - AnyClientState, - IdentifiedAnyClientState, - }, - config::{ - parse_gas_prices, - ChainConfig, - Error as ConfigError, - GasPrice, - }, - consensus_state::AnyConsensusState, - denom::DenomTrace, - error::Error, - event::{ - source::{ - EventSource, - TxEventSourceCmd, - }, - IbcEventWithHeight, - }, - keyring::{ - KeyRing, - Secp256k1KeyPair, - SigningKeyPair, - }, - light_client::{ - tendermint::LightClient as TmLightClient, - LightClient, - Verified, - }, - misbehaviour::MisbehaviourEvidence, - util::{ - compat_mode::compat_mode_from_version, - pretty::{ - PrettyIdentifiedChannel, - PrettyIdentifiedClientState, - PrettyIdentifiedConnection, - }, - }, +use crate::chain::endpoint::{ChainEndpoint, ChainStatus, HealthCheck}; +use crate::chain::handle::Subscription; +use crate::chain::requests::*; +use crate::chain::tracking::TrackedMsgs; +use crate::client_state::{AnyClientState, IdentifiedAnyClientState}; +use crate::config::Error as ConfigError; +use crate::config::{parse_gas_prices, ChainConfig, GasPrice}; +use crate::consensus_state::AnyConsensusState; +use crate::denom::DenomTrace; +use crate::error::Error; +use crate::event::source::{EventSource, TxEventSourceCmd}; +use crate::event::IbcEventWithHeight; +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::create_grpc_client; +use crate::util::pretty::PrettySlice; +use crate::util::pretty::{ + PrettyIdentifiedChannel, PrettyIdentifiedClientState, PrettyIdentifiedConnection, }; +use crate::HERMES_VERSION; + +use self::gas::dynamic_gas_price; +use self::types::gas::GasConfig; +use self::version::Specs; pub mod batch; pub mod client; pub mod compatibility; pub mod config; +pub mod eip_base_fee; pub mod encode; pub mod estimate; pub mod fee; @@ -255,6 +150,7 @@ 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: config::CosmosSdkConfig, tx_config: TxConfig, @@ -401,23 +297,30 @@ impl CosmosSdkChain { )); } - // Query /genesis RPC endpoint to retrieve the `max_expected_time_per_block` value - // to use as `max_block_time`. - // If it is not found, keep the configured `max_block_time`. - match self.block_on(self.rpc_client.genesis::()) { - Ok(genesis_reponse) => { - let old_max_block_time = self.config.max_block_time; - self.config.max_block_time = - Duration::from_nanos(genesis_reponse.app_state.max_expected_time_per_block()); - info!( - "Updated `max_block_time` using /genesis endpoint. Old value: `{}s`, new value: `{}s`", - old_max_block_time.as_secs(), - self.config.max_block_time.as_secs() + // Query Connection Params with gRPC endpoint to retrieve the `max_expected_time_per_block` value and verify the + // configured `max_block_time`. + // If it is not found, the verification for the configured `max_block_time` is skipped. + match self.block_on(query_connection_params(&self.grpc_addr)) { + Ok(params) => { + debug!( + "queried `max_expected_time_per_block`: `{}ns`", + params.max_expected_time_per_block ); + let new_max_block_time = Duration::from_nanos(params.max_expected_time_per_block); + + if new_max_block_time != self.config.max_block_time { + warn!( + "configured `max_block_time` value of `{}s` does not match queried value of `{}s`. \ + `max_block_time` will be updated with queried value", + self.config.max_block_time.as_secs(), + new_max_block_time.as_secs(), + ); + self.config.max_block_time = new_max_block_time; + } } Err(e) => { warn!( - "Will use fallback value for max_block_time: `{}s`. Error: {e}", + "configured value for max_block_time: `{}s` could not be verified. Error: {e}", self.config.max_block_time.as_secs() ); } @@ -444,10 +347,14 @@ impl CosmosSdkChain { *batch_delay, self.rt.clone(), ), - Mode::Pull { interval } => EventSource::rpc( + Mode::Pull { + interval, + max_retries, + } => EventSource::rpc( self.config.id.clone(), self.rpc_client.clone(), *interval, + *max_retries, self.rt.clone(), ), } @@ -468,13 +375,10 @@ impl CosmosSdkChain { ); crate::telemetry!(query, self.id(), "query_ccv_consumer_chain_params"); - let mut client = self - .block_on( - ibc_proto::interchain_security::ccv::consumer::v1::query_client::QueryClient::connect( - self.grpc_addr.clone() - ), - ) - .map_err(Error::grpc_transport)?; + let mut client = self.block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::interchain_security::ccv::consumer::v1::query_client::QueryClient::new, + ))?; client = client .max_decoding_message_size(self.config().max_grpc_decoding_size.get_bytes() as usize); @@ -505,26 +409,20 @@ impl CosmosSdkChain { ); crate::telemetry!(query, self.id(), "query_staking_params"); - let mut client = self - .block_on( - ibc_proto::cosmos::staking::v1beta1::query_client::QueryClient::connect( - self.grpc_addr.clone(), - ), - ) - .map_err(Error::grpc_transport)?; - - client = client - .max_decoding_message_size(self.config().max_grpc_decoding_size.get_bytes() as usize); - - let request = - tonic::Request::new(ibc_proto::cosmos::staking::v1beta1::QueryParamsRequest {}); - - let response = self - .block_on(client.params(request)) - .map_err(|e| Error::grpc_status(e, "query_staking_params".to_owned()))?; + let query_response = self.block_on(abci_query( + &self.rpc_client, + &self.config().rpc_addr, + "/cosmos.staking.v1beta1.Query/Params".to_owned(), + "".to_owned(), + QueryHeight::Latest.into(), + false, + ))?; + let params_response = + QueryParamsResponse::decode(query_response.value.as_ref()).map_err(|e| { + Error::protobuf_decode("cosmos.staking.v1beta1.Query/Params".to_owned(), e) + })?; - let params = response - .into_inner() + let params = params_response .params .ok_or_else(|| Error::grpc_response_param("no staking params".to_string()))?; @@ -548,49 +446,24 @@ impl CosmosSdkChain { ); crate::telemetry!(query, self.id(), "query_config_params"); - // Helper function to diagnose if the node config query is unimplemented - // by matching on the error details. - fn is_unimplemented_node_query(err_status: &tonic::Status) -> bool { - if err_status.code() != tonic::Code::Unimplemented { - return false; - } - - err_status - .message() - .contains("unknown service cosmos.base.node.v1beta1.Service") - } - - let mut client = self - .block_on( - ibc_proto::cosmos::base::node::v1beta1::service_client::ServiceClient::connect( - self.grpc_addr.clone(), - ), - ) - .map_err(Error::grpc_transport)?; - - client = client - .max_decoding_message_size(self.config().max_grpc_decoding_size.get_bytes() as usize); - - let request = tonic::Request::new(ibc_proto::cosmos::base::node::v1beta1::ConfigRequest {}); - - match self.block_on(client.config(request)) { - Ok(response) => { - let params = response.into_inner(); + let query_response = self.block_on(abci_query( + &self.rpc_client, + &self.config().rpc_addr, + "/cosmos.base.node.v1beta1.Service/Config".to_owned(), + "".to_owned(), + QueryHeight::Latest.into(), + false, + ))?; + let config_response = + ConfigResponse::decode(query_response.value.as_ref()).map_err(|e| { + Error::protobuf_decode("cosmos.base.node.v1beta1.Service/Config".to_owned(), e) + })?; - Ok(Some(params)) - } - Err(e) => { - if is_unimplemented_node_query(&e) { - Ok(None) - } else { - Err(Error::grpc_status(e, "query_config_params".to_owned())) - } - } - } + Ok(Some(config_response)) } /// The minimum gas price that this node accepts - pub fn min_gas_price(&self) -> Result, Error> { + pub fn min_gas_price(&self) -> Result>, Error> { crate::time!( "min_gas_price", { @@ -598,14 +471,23 @@ impl CosmosSdkChain { } ); - let min_gas_price: Vec = - self.query_config_params()?.map_or(vec![], |cfg_response| { - parse_gas_prices(cfg_response.minimum_gas_price) - }); + let min_gas_price: Option> = self + .query_config_params()? + .map(|cfg_response| parse_gas_prices(cfg_response.minimum_gas_price)); Ok(min_gas_price) } + pub fn dynamic_gas_price(&self) -> GasPrice { + let gas_config = GasConfig::from(self.config()); + + self.rt.block_on(dynamic_gas_price( + &gas_config, + &self.config.id, + &self.config.rpc_addr, + )) + } + /// The unbonding period of this chain pub fn unbonding_period(&self) -> Result { crate::time!( @@ -665,11 +547,6 @@ impl CosmosSdkChain { height_query: QueryHeight, prove: bool, ) -> Result { - crate::time!("query", - { - "src_chain": self.config().id.to_string(), - }); - let data = data.into(); if !data.is_provable() & prove { return Err(Error::private_store()); @@ -731,27 +608,51 @@ impl CosmosSdkChain { /// /// Returns an error if the node is still syncing and has not caught up, /// ie. if `sync_info.catching_up` is `true`. - fn chain_status(&self) -> Result { + fn chain_rpc_status(&self) -> Result { crate::time!( - "chain_status", + "chain_rpc_status", { "src_chain": self.config().id.to_string(), } ); - crate::telemetry!(query, self.id(), "status"); + crate::telemetry!(query, self.id(), "rpc_status"); let status = self .block_on(self.rpc_client.status()) .map_err(|e| Error::rpc(self.config.rpc_addr.clone(), e))?; if status.sync_info.catching_up { + Err(Error::chain_not_caught_up( + self.config.rpc_addr.to_string(), + self.config().id.clone(), + )) + } else { + Ok(status) + } + } + + /// Query the chain status of the RPC and gRPC nodes. + /// + /// Returns an error if any of the node is still syncing and has not caught up. + fn chain_status(&self) -> Result { + crate::time!( + "chain_status", + { + "src_chain": self.config().id.to_string(), + } + ); + crate::telemetry!(query, self.id(), "status"); + + let rpc_status = self.chain_rpc_status()?; + + if rpc_status.sync_info.catching_up { return Err(Error::chain_not_caught_up( self.config.rpc_addr.to_string(), self.config().id.clone(), )); } - Ok(status) + Ok(rpc_status) } /// Query the chain's latest height @@ -801,13 +702,19 @@ impl CosmosSdkChain { let account = get_or_fetch_account(&self.grpc_addr, &key_account, &mut self.account).await?; + let memo_prefix = if let Some(memo_overwrite) = &self.config.memo_overwrite { + memo_overwrite.clone() + } else { + self.config.memo_prefix.clone() + }; + if self.config.sequential_batch_tx { sequential_send_batched_messages_and_wait_commit( &self.rpc_client, &self.tx_config, &key_pair, account, - &self.config.memo_prefix, + &memo_prefix, proto_msgs, ) .await @@ -817,7 +724,7 @@ impl CosmosSdkChain { &self.tx_config, &key_pair, account, - &self.config.memo_prefix, + &memo_prefix, proto_msgs, ) .await @@ -852,12 +759,18 @@ impl CosmosSdkChain { let account = get_or_fetch_account(&self.grpc_addr, &key_account, &mut self.account).await?; + let memo_prefix = if let Some(memo_overwrite) = &self.config.memo_overwrite { + memo_overwrite.clone() + } else { + self.config.memo_prefix.clone() + }; + send_batched_messages_and_wait_check_tx( &self.rpc_client, &self.tx_config, &key_pair, account, - &self.config.memo_prefix, + &memo_prefix, proto_msgs, ) .await @@ -1000,7 +913,9 @@ impl ChainEndpoint for CosmosSdkChain { return Err(Error::config(ConfigError::wrong_type())); }; - let mut rpc_client = HttpClient::new(config.rpc_addr.clone()) + let mut rpc_client = HttpClient::builder(config.rpc_addr.clone().try_into().unwrap()) + .user_agent(format!("hermes/{}", HERMES_VERSION)) + .build() .map_err(|e| Error::rpc(config.rpc_addr.clone(), e))?; let node_info = rt.block_on(fetch_node_info(&rpc_client, &config))?; @@ -1095,17 +1010,17 @@ impl ChainEndpoint for CosmosSdkChain { /// further checks. fn health_check(&mut self) -> Result { if let Err(e) = do_health_check(self) { - warn!("Health checkup for chain '{}' failed", self.id()); - warn!(" Reason: {}", e.detail()); - warn!(" Some Hermes features may not work in this mode!"); + warn!("health check failed for chain '{}'", self.id()); + warn!("reason: {}", e.detail()); + warn!("some Hermes features may not work in this mode!"); return Ok(HealthCheck::Unhealthy(Box::new(e))); } if let Err(e) = self.validate_params() { - warn!("Hermes might be misconfigured for chain '{}'", self.id()); - warn!(" Reason: {}", e.detail()); - warn!(" Some Hermes features may not work in this mode!"); + warn!("found potential misconfiguration for chain '{}'", self.id()); + warn!("reason: {}", e.detail()); + warn!("some Hermes features may not work in this mode!"); return Ok(HealthCheck::Unhealthy(Box::new(e))); } @@ -1197,11 +1112,21 @@ impl ChainEndpoint for CosmosSdkChain { } fn version_specs(&self) -> Result { - let version_specs = self.block_on(fetch_version_specs(self.id(), &self.grpc_addr))?; + let version_specs = self.block_on(fetch_version_specs( + self.id(), + &self.rpc_client, + &self.config.rpc_addr, + ))?; Ok(version_specs) } fn query_balance(&self, key_name: Option<&str>, denom: Option<&str>) -> Result { + crate::time!( + "query_balance", + { + "src_chain": self.config().id.to_string(), + } + ); // If a key_name is given, extract the account hash. // Else retrieve the account from the configuration file. let key = match key_name { @@ -1217,6 +1142,12 @@ impl ChainEndpoint for CosmosSdkChain { } fn query_all_balances(&self, key_name: Option<&str>) -> Result, Error> { + crate::time!( + "query_all_balances", + { + "src_chain": self.config().id.to_string(), + } + ); // If a key_name is given, extract the account hash. // Else retrieve the account from the configuration file. let key = match key_name { @@ -1296,13 +1227,10 @@ impl ChainEndpoint for CosmosSdkChain { ); crate::telemetry!(query, self.id(), "query_clients"); - let mut client = self - .block_on( - ibc_proto::ibc::core::client::v1::query_client::QueryClient::connect( - self.grpc_addr.clone(), - ), - ) - .map_err(Error::grpc_transport)?; + let mut client = self.block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::ibc::core::client::v1::query_client::QueryClient::new, + ))?; client = client .max_decoding_message_size(self.config().max_grpc_decoding_size.get_bytes() as usize); @@ -1487,13 +1415,10 @@ impl ChainEndpoint for CosmosSdkChain { ); crate::telemetry!(query, self.id(), "query_client_connections"); - let mut client = self - .block_on( - ibc_proto::ibc::core::connection::v1::query_client::QueryClient::connect( - self.grpc_addr.clone(), - ), - ) - .map_err(Error::grpc_transport)?; + let mut client = self.block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::ibc::core::connection::v1::query_client::QueryClient::new, + ))?; client = client .max_decoding_message_size(self.config().max_grpc_decoding_size.get_bytes() as usize); @@ -1533,13 +1458,10 @@ impl ChainEndpoint for CosmosSdkChain { ); crate::telemetry!(query, self.id(), "query_connections"); - let mut client = self - .block_on( - ibc_proto::ibc::core::connection::v1::query_client::QueryClient::connect( - self.grpc_addr.clone(), - ), - ) - .map_err(Error::grpc_transport)?; + let mut client = self.block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::ibc::core::connection::v1::query_client::QueryClient::new, + ))?; client = client .max_decoding_message_size(self.config().max_grpc_decoding_size.get_bytes() as usize); @@ -1591,10 +1513,11 @@ impl ChainEndpoint for CosmosSdkChain { use ibc_proto::ibc::core::connection::v1 as connection; use tonic::IntoRequest; - let mut client = - connection::query_client::QueryClient::connect(chain.grpc_addr.clone()) - .await - .map_err(Error::grpc_transport)?; + let mut client = create_grpc_client( + chain.grpc_addr.clone(), + connection::query_client::QueryClient::new, + ) + .await?; client = client.max_decoding_message_size( chain.config().max_grpc_decoding_size.get_bytes() as usize, @@ -1672,13 +1595,10 @@ impl ChainEndpoint for CosmosSdkChain { ); crate::telemetry!(query, self.id(), "query_connection_channels"); - 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 mut client = self.block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::ibc::core::channel::v1::query_client::QueryClient::new, + ))?; client = client .max_decoding_message_size(self.config().max_grpc_decoding_size.get_bytes() as usize); @@ -1690,7 +1610,9 @@ impl ChainEndpoint for CosmosSdkChain { .map_err(|e| Error::grpc_status(e, "query_connection_channels".to_owned()))? .into_inner(); - let channels = response + let height = self.query_chain_latest_height()?; + + let channels: Vec = response .channels .into_iter() .filter_map(|ch| { @@ -1704,7 +1626,27 @@ impl ChainEndpoint for CosmosSdkChain { }) .ok() }) + .map(|mut channel| { + // If the channel is open, look for an upgrade in order to correctly set the + // state to Open(Upgrading) or Open(NotUpgrading) + if channel.channel_end.is_open() + && self + .query_upgrade( + QueryUpgradeRequest { + port_id: channel.port_id.to_string(), + channel_id: channel.channel_id.to_string(), + }, + height, + IncludeProof::No, + ) + .is_ok() + { + channel.channel_end.state = State::Open(UpgradeState::Upgrading); + } + channel + }) .collect(); + Ok(channels) } @@ -1722,13 +1664,10 @@ impl ChainEndpoint for CosmosSdkChain { ); crate::telemetry!(query, self.id(), "query_channels"); - 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 mut client = self.block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::ibc::core::channel::v1::query_client::QueryClient::new, + ))?; client = client .max_decoding_message_size(self.config().max_grpc_decoding_size.get_bytes() as usize); @@ -1740,6 +1679,8 @@ impl ChainEndpoint for CosmosSdkChain { .map_err(|e| Error::grpc_status(e, "query_channels".to_owned()))? .into_inner(); + let height = self.query_chain_latest_height()?; + let channels = response .channels .into_iter() @@ -1754,6 +1695,25 @@ impl ChainEndpoint for CosmosSdkChain { }) .ok() }) + .map(|mut channel| { + // If the channel is open, look for an upgrade in order to correctly set the + // state to Open(Upgrading) or Open(NotUpgrading) + if channel.channel_end.is_open() + && self + .query_upgrade( + QueryUpgradeRequest { + port_id: channel.port_id.to_string(), + channel_id: channel.channel_id.to_string(), + }, + height, + IncludeProof::No, + ) + .is_ok() + { + channel.channel_end.state = State::Open(UpgradeState::Upgrading); + } + channel + }) .collect(); Ok(channels) @@ -1773,12 +1733,34 @@ impl ChainEndpoint for CosmosSdkChain { crate::telemetry!(query, self.id(), "query_channel"); let res = self.query( - ChannelEndsPath(request.port_id, request.channel_id), + ChannelEndsPath(request.port_id.clone(), request.channel_id.clone()), request.height, matches!(include_proof, IncludeProof::Yes), )?; - let channel_end = ChannelEnd::decode_vec(&res.value).map_err(Error::decode)?; + let mut channel_end = ChannelEnd::decode_vec(&res.value).map_err(Error::decode)?; + + if channel_end.is_open() { + let height = match request.height { + QueryHeight::Latest => self.query_chain_latest_height()?, + QueryHeight::Specific(height) => height, + }; + // In order to determine if the channel is Open upgrading or not the Upgrade is queried. + // If an upgrade is ongoing then the query will succeed in finding an Upgrade. + if self + .query_upgrade( + QueryUpgradeRequest { + port_id: request.port_id.to_string(), + channel_id: request.channel_id.to_string(), + }, + height, + IncludeProof::No, + ) + .is_ok() + { + channel_end.state = State::Open(UpgradeState::Upgrading); + } + } match include_proof { IncludeProof::Yes => { @@ -1803,13 +1785,10 @@ impl ChainEndpoint for CosmosSdkChain { ); crate::telemetry!(query, self.id(), "query_channel_client_state"); - 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 mut client = self.block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::ibc::core::channel::v1::query_client::QueryClient::new, + ))?; client = client .max_decoding_message_size(self.config().max_grpc_decoding_size.get_bytes() as usize); @@ -1833,6 +1812,12 @@ impl ChainEndpoint for CosmosSdkChain { request: QueryPacketCommitmentRequest, include_proof: IncludeProof, ) -> Result<(Vec, Option), Error> { + crate::time!( + "query_packet_commitment", + { + "src_chain": self.config().id.to_string(), + } + ); let res = self.query( CommitmentsPath { port_id: request.port_id, @@ -1868,36 +1853,119 @@ impl ChainEndpoint for CosmosSdkChain { crate::telemetry!(query, self.id(), "query_packet_commitments"); 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)?; + .block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::ibc::core::channel::v1::query_client::QueryClient::new, + )) + .map(|client| { + client.max_decoding_message_size( + self.config().max_grpc_decoding_size.get_bytes() as usize + ) + })?; - client = client - .max_decoding_message_size(self.config().max_grpc_decoding_size.get_bytes() as usize); + if request.pagination.is_enabled() { + let mut results = Vec::new(); + let mut page_key = Vec::new(); - let request = tonic::Request::new(request.into()); + let pagination_information = request.pagination.get_values(); + let mut current_results = 0; - let response = self - .block_on(client.packet_commitments(request)) - .map_err(|e| Error::grpc_status(e, "query_packet_commitments".to_owned()))? - .into_inner(); + loop { + crate::time!( + "query_packet_commitments_loop_iteration", + { + "src_chain": self.config().id.to_string(), + } + ); + let mut raw_request = + ibc_proto::ibc::core::channel::v1::QueryPacketCommitmentsRequest::from( + request.clone(), + ); - let mut commitment_sequences: Vec = response - .commitments - .into_iter() - .map(|v| v.sequence.into()) - .collect(); - commitment_sequences.sort_unstable(); + if let Some(pagination) = raw_request.pagination.as_mut() { + pagination.key = page_key; + } + + let mut tonic_request = tonic::Request::new(raw_request); + // TODO: This should either be configurable or inferred from the pagination + tonic_request.set_timeout(Duration::from_secs(10)); + + let response = self.rt.block_on(async { + client + .packet_commitments(tonic_request) + .await + .map_err(|e| Error::grpc_status(e, "query_packet_commitments".to_owned())) + }); + + match response { + Ok(response) => { + let inner_response = response.into_inner().clone(); + let next_key = inner_response + .pagination + .as_ref() + .map(|p| p.next_key.clone()); + + results.push(Ok(inner_response)); + current_results += pagination_information.0; + + match next_key { + Some(next_key) if !next_key.is_empty() => { + page_key = next_key; + } + _ => break, + } + } + Err(e) => { + results.push(Err(e)); + break; + } + } + if current_results >= pagination_information.1 { + break; + } + } + + let responses = results.into_iter().collect::, _>>()?; + + let mut commitment_sequences = Vec::new(); + + for response in &responses { + commitment_sequences.extend( + response + .commitments + .iter() + .map(|commit| Sequence::from(commit.sequence)), + ); + } - let height = response - .height - .and_then(|raw_height| raw_height.try_into().ok()) - .ok_or_else(|| Error::grpc_response_param("height".to_string()))?; + let height = responses + .first() + .and_then(|res| res.height) + .and_then(|raw_height| raw_height.try_into().ok()) + .ok_or_else(|| Error::grpc_response_param("height".to_string()))?; - Ok((commitment_sequences, height)) + Ok((commitment_sequences, height)) + } else { + let request = tonic::Request::new(request.into()); + let response = self + .block_on(client.packet_commitments(request)) + .map_err(|e| Error::grpc_status(e, "query_packet_commitments".to_owned()))? + .into_inner(); + + let mut commitment_sequences: Vec = response + .commitments + .into_iter() + .map(|v| v.sequence.into()) + .collect(); + commitment_sequences.sort_unstable(); + + let height = response + .height + .and_then(|raw_height| raw_height.try_into().ok()) + .ok_or_else(|| Error::grpc_response_param("height".to_string()))?; + + Ok((commitment_sequences, height)) + } } fn query_packet_receipt( @@ -1905,6 +1973,12 @@ impl ChainEndpoint for CosmosSdkChain { request: QueryPacketReceiptRequest, include_proof: IncludeProof, ) -> Result<(Vec, Option), Error> { + crate::time!( + "query_packet_receipt", + { + "src_chain": self.config().id.to_string(), + } + ); let res = self.query( ReceiptsPath { port_id: request.port_id, @@ -1939,13 +2013,10 @@ impl ChainEndpoint for CosmosSdkChain { ); crate::telemetry!(query, self.id(), "query_unreceived_packets"); - 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 mut client = self.block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::ibc::core::channel::v1::query_client::QueryClient::new, + ))?; client = client .max_decoding_message_size(self.config().max_grpc_decoding_size.get_bytes() as usize); @@ -1970,6 +2041,12 @@ impl ChainEndpoint for CosmosSdkChain { request: QueryPacketAcknowledgementRequest, include_proof: IncludeProof, ) -> Result<(Vec, Option), Error> { + crate::time!( + "query_packet_acknowledgement", + { + "src_chain": self.config().id.to_string(), + } + ); let res = self.query( AcksPath { port_id: request.port_id, @@ -2009,35 +2086,108 @@ impl ChainEndpoint for CosmosSdkChain { } 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)?; + .block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::ibc::core::channel::v1::query_client::QueryClient::new, + )) + .map(|client| { + client.max_decoding_message_size( + self.config().max_grpc_decoding_size.get_bytes() as usize + ) + })?; - client = client - .max_decoding_message_size(self.config().max_grpc_decoding_size.get_bytes() as usize); + if request.pagination.is_enabled() { + let mut results = Vec::new(); + let mut page_key = Vec::new(); - let request = tonic::Request::new(request.into()); + loop { + let mut raw_request = + ibc_proto::ibc::core::channel::v1::QueryPacketAcknowledgementsRequest::from( + request.clone(), + ); - let response = self - .block_on(client.packet_acknowledgements(request)) - .map_err(|e| Error::grpc_status(e, "query_packet_acknowledgements".to_owned()))? - .into_inner(); + if let Some(pagination) = raw_request.pagination.as_mut() { + pagination.key = page_key; + } - let acks_sequences = response - .acknowledgements - .into_iter() - .map(|v| v.sequence.into()) - .collect(); + let mut tonic_request = tonic::Request::new(raw_request); + // TODO: This should either be configurable or inferred from the pagination + tonic_request.set_timeout(Duration::from_secs(10)); + + let response = self.rt.block_on(async { + client + .packet_acknowledgements(tonic_request) + .await + .map_err(|e| { + Error::grpc_status(e, "query_packet_acknowledgements".to_owned()) + }) + }); + + match response { + Ok(response) => { + let inner_response = response.into_inner().clone(); + let next_key = inner_response + .pagination + .as_ref() + .map(|p| p.next_key.clone()); + + results.push(Ok(inner_response)); + + match next_key { + Some(next_key) if !next_key.is_empty() => { + page_key = next_key; + } + _ => break, + } + } + Err(e) => { + results.push(Err(e)); + break; + } + } + } + + let responses = results.into_iter().collect::, _>>()?; + + let mut acks_sequences = Vec::new(); + + for response in &responses { + acks_sequences.extend( + response + .acknowledgements + .iter() + .map(|commit| Sequence::from(commit.sequence)), + ); + } - let height = response - .height - .and_then(|raw_height| raw_height.try_into().ok()) - .ok_or_else(|| Error::grpc_response_param("height".to_string()))?; + let height = responses + .first() + .and_then(|res| res.height) + .and_then(|raw_height| raw_height.try_into().ok()) + .ok_or_else(|| Error::grpc_response_param("height".to_string()))?; - Ok((acks_sequences, height)) + Ok((acks_sequences, height)) + } else { + let request = tonic::Request::new(request.into()); + let response = self + .block_on(client.packet_acknowledgements(request)) + .map_err(|e| Error::grpc_status(e, "query_packet_commitments".to_owned()))? + .into_inner(); + + let mut acks_sequences: Vec = response + .acknowledgements + .into_iter() + .map(|v| v.sequence.into()) + .collect(); + acks_sequences.sort_unstable(); + + let height = response + .height + .and_then(|raw_height| raw_height.try_into().ok()) + .ok_or_else(|| Error::grpc_response_param("height".to_string()))?; + + Ok((acks_sequences, height)) + } } /// Performs a `QueryUnreceivedAcksRequest` gRPC query to fetch the unreceived acknowledgements @@ -2054,13 +2204,10 @@ impl ChainEndpoint for CosmosSdkChain { ); crate::telemetry!(query, self.id(), "query_unreceived_acknowledgements"); - 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 mut client = self.block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::ibc::core::channel::v1::query_client::QueryClient::new, + ))?; client = client .max_decoding_message_size(self.config().max_grpc_decoding_size.get_bytes() as usize); @@ -2127,10 +2274,6 @@ impl ChainEndpoint for CosmosSdkChain { /// 1. Client Update request - returns a vector with at most one update client event /// 2. Transaction event request - returns all IBC events resulted from a Tx execution fn query_txs(&self, request: QueryTxRequest) -> Result, Error> { - crate::time!("query_txs", - { - "src_chain": self.config().id.to_string(), - }); crate::telemetry!(query, self.id(), "query_txs"); self.block_on(query_txs( @@ -2226,6 +2369,12 @@ impl ChainEndpoint for CosmosSdkChain { &self, request: QueryHostConsensusStateRequest, ) -> Result { + crate::time!( + "query_host_consensus_state", + { + "src_chain": self.config().id.to_string(), + } + ); let height = match request.height { QueryHeight::Latest => TmHeight::from(0u32), QueryHeight::Specific(ibc_height) => TmHeight::from(ibc_height), @@ -2256,6 +2405,12 @@ impl ChainEndpoint for CosmosSdkChain { height: ICSHeight, settings: ClientSettings, ) -> Result { + crate::time!( + "build_client_state", + { + "src_chain": self.config().id.to_string(), + } + ); let ClientSettings::Tendermint(settings) = settings; let unbonding_period = self.unbonding_period()?; let trusting_period = settings @@ -2331,12 +2486,18 @@ impl ChainEndpoint for CosmosSdkChain { let address = self.get_signer()?; let key_pair = self.key()?; + let memo_prefix = if let Some(memo_overwrite) = &self.config.memo_overwrite { + memo_overwrite.clone() + } else { + self.config.memo_prefix.clone() + }; + self.rt.block_on(maybe_register_counterparty_payee( &self.rpc_client, &self.tx_config, &key_pair, &mut self.account, - &self.config.memo_prefix, + &memo_prefix, channel_id, port_id, &address, @@ -2381,12 +2542,10 @@ impl ChainEndpoint for CosmosSdkChain { ); 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 mut client = self.block_on(create_grpc_client( + self.grpc_addr.clone(), + ibc_proto::interchain_security::ccv::provider::v1::query_client::QueryClient::new, + ))?; let request = tonic::Request::new( ibc_proto::interchain_security::ccv::provider::v1::QueryConsumerChainsRequest {}, @@ -2405,6 +2564,64 @@ impl ChainEndpoint for CosmosSdkChain { Ok(result) } + + fn query_upgrade( + &self, + request: QueryUpgradeRequest, + height: Height, + include_proof: IncludeProof, + ) -> Result<(Upgrade, Option), Error> { + let port_id = PortId::from_str(&request.port_id) + .map_err(|_| Error::invalid_port_string(request.port_id))?; + let channel_id = ChannelId::from_str(&request.channel_id) + .map_err(|_| Error::invalid_channel_string(request.channel_id))?; + let res = self.query( + ChannelUpgradePath { + port_id, + channel_id, + }, + QueryHeight::Specific(height), + true, + )?; + let upgrade = Upgrade::decode_vec(&res.value).map_err(Error::decode)?; + + match include_proof { + IncludeProof::Yes => { + let proof = res.proof.ok_or_else(Error::empty_response_proof)?; + Ok((upgrade, Some(proof))) + } + IncludeProof::No => Ok((upgrade, None)), + } + } + + fn query_upgrade_error( + &self, + request: QueryUpgradeErrorRequest, + height: Height, + include_proof: IncludeProof, + ) -> Result<(ErrorReceipt, Option), Error> { + let port_id = PortId::from_str(&request.port_id) + .map_err(|_| Error::invalid_port_string(request.port_id))?; + let channel_id = ChannelId::from_str(&request.channel_id) + .map_err(|_| Error::invalid_channel_string(request.channel_id))?; + let res = self.query( + ChannelUpgradeErrorPath { + port_id, + channel_id, + }, + QueryHeight::Specific(height), + true, + )?; + let error_receipt = ErrorReceipt::decode_vec(&res.value).map_err(Error::decode)?; + + match include_proof { + IncludeProof::Yes => { + let proof = res.proof.ok_or_else(Error::empty_response_proof)?; + Ok((error_receipt, Some(proof))) + } + IncludeProof::No => Ok((error_receipt, None)), + } + } } pub(crate) fn sort_events_by_sequence(events: &mut [IbcEventWithHeight]) { @@ -2461,6 +2678,17 @@ fn do_health_check(chain: &CosmosSdkChain) -> Result<(), Error> { let grpc_address = chain.grpc_addr.to_string(); let rpc_address = chain.config.rpc_addr.to_string(); + if !chain.config.excluded_sequences.map.is_empty() { + for (channel_id, seqs) in chain.config.excluded_sequences.map.iter() { + if !seqs.is_empty() { + warn!( + "chain '{chain_id}' will not clear packets on channel '{channel_id}' with sequences: {}. \ + Ignore this warning if this configuration is correct.", PrettySlice(seqs) + ); + } + } + } + chain.block_on(chain.rpc_client.health()).map_err(|e| { Error::health_check_json_rpc( chain_id.clone(), @@ -2486,44 +2714,54 @@ fn do_health_check(chain: &CosmosSdkChain) -> Result<(), Error> { } let relayer_gas_price = &chain.config.gas_price; - let node_min_gas_prices = chain.min_gas_price()?; - - if !node_min_gas_prices.is_empty() { - let mut found_matching_denom = false; - - for price in node_min_gas_prices { - match relayer_gas_price.partial_cmp(&price) { - Some(Ordering::Less) => return Err(Error::gas_price_too_low(chain_id.clone())), - Some(_) => { - found_matching_denom = true; - break; + let node_min_gas_prices_result = chain.min_gas_price()?; + + match node_min_gas_prices_result { + Some(node_min_gas_prices) if !node_min_gas_prices.is_empty() => { + let mut found_matching_denom = false; + + for price in node_min_gas_prices { + match relayer_gas_price.partial_cmp(&price) { + Some(Ordering::Less) => return Err(Error::gas_price_too_low(chain_id.clone())), + Some(_) => { + found_matching_denom = true; + break; + } + None => continue, } - None => continue, } - } - if !found_matching_denom { - warn!( - "Chain '{}' has no minimum gas price of denomination '{}' \ - that is strictly less than the `gas_price` specified for \ - that chain in the Hermes configuration. \ - This is usually a sign of misconfiguration, please check your chain and Hermes configurations", - chain_id, relayer_gas_price.denom - ); + if !found_matching_denom { + warn!( + "chain '{}' has no minimum gas price of denomination '{}' \ + that is strictly less than the `gas_price` specified for that chain in the Hermes configuration. \ + This is usually a sign of misconfiguration, please check your chain and Hermes configurations", + chain_id, relayer_gas_price.denom + ); + } } - } else { - warn!( - "Chain '{}' has no minimum gas price value configured for denomination '{}'. \ - This is usually a sign of misconfiguration, please check your chain and \ - relayer configurations", + + Some(_) => warn!( + "chain '{}' has no minimum gas price value configured for denomination '{}'. \ + This is usually a sign of misconfiguration, please check your chain and relayer configurations", chain_id, relayer_gas_price.denom - ); + ), + + None => warn!( + "chain '{}' does not implement the `cosmos.base.node.v1beta1.Service/Params` endpoint. \ + It is impossible to check whether the chain's minimum-gas-prices matches the ones specified in config", + chain_id, + ), } - let version_specs = chain.block_on(fetch_version_specs(&chain.config.id, &chain.grpc_addr))?; + let version_specs = chain.block_on(fetch_version_specs( + &chain.config.id, + &chain.rpc_client, + &chain.config.rpc_addr, + ))?; if let Err(diagnostic) = compatibility::run_diagnostic(&version_specs) { - return Err(Error::sdk_module_version( + return Err(Error::compat_check_failed( chain_id.clone(), grpc_address, diagnostic.to_string(), @@ -2539,27 +2777,8 @@ fn do_health_check(chain: &CosmosSdkChain) -> Result<(), Error> { #[cfg(test)] mod tests { - use ibc_relayer_types::{ - core::{ - ics02_client::client_type::ClientType, - ics24_host::identifier::ClientId, - }, - mock::{ - client_state::MockClientState, - header::MockHeader, - }, - Height, - }; - use super::calculate_fee; - use crate::{ - chain::cosmos::client_id_suffix, - client_state::{ - AnyClientState, - IdentifiedAnyClientState, - }, - config::GasPrice, - }; + use crate::config::GasPrice; #[test] fn mul_ceil() { @@ -2597,38 +2816,4 @@ mod tests { let fee = calculate_fee(gas_amount, &gas_price); assert_eq!(&fee.amount, "90000000000000000000000000"); } - - #[test] - fn sort_clients_id_suffix() { - let mut clients: Vec = vec![ - IdentifiedAnyClientState::new( - ClientId::new(ClientType::Tendermint, 4).unwrap(), - AnyClientState::Mock(MockClientState::new(MockHeader::new( - Height::new(0, 1).unwrap(), - ))), - ), - IdentifiedAnyClientState::new( - ClientId::new(ClientType::Tendermint, 1).unwrap(), - AnyClientState::Mock(MockClientState::new(MockHeader::new( - Height::new(0, 1).unwrap(), - ))), - ), - IdentifiedAnyClientState::new( - ClientId::new(ClientType::Tendermint, 7).unwrap(), - AnyClientState::Mock(MockClientState::new(MockHeader::new( - Height::new(0, 1).unwrap(), - ))), - ), - ]; - clients.sort_by_cached_key(|c| client_id_suffix(&c.client_id).unwrap_or(0)); - assert_eq!( - client_id_suffix(&clients.first().unwrap().client_id).unwrap(), - 1 - ); - assert_eq!(client_id_suffix(&clients[1].client_id).unwrap(), 4); - assert_eq!( - client_id_suffix(&clients.last().unwrap().client_id).unwrap(), - 7 - ); - } } diff --git a/crates/relayer/src/chain/cosmos/batch.rs b/crates/relayer/src/chain/cosmos/batch.rs index 0b2c89fca1..e4f0042029 100644 --- a/crates/relayer/src/chain/cosmos/batch.rs +++ b/crates/relayer/src/chain/cosmos/batch.rs @@ -1,16 +1,9 @@ use core::mem; use ibc_proto::google::protobuf::Any; -use ibc_relayer_types::{ - core::ics24_host::identifier::ChainId, - events::IbcEvent, - Height, -}; +use ibc_relayer_types::{core::ics24_host::identifier::ChainId, events::IbcEvent, Height}; use prost::Message; -use tendermint_rpc::{ - endpoint::broadcast::tx_sync::Response, - HttpClient, -}; +use tendermint_rpc::{endpoint::broadcast::tx_sync::Response, HttpClient}; use tracing::debug; use crate::{ @@ -21,10 +14,7 @@ use crate::{ types::{ account::Account, config::TxConfig, - tx::{ - TxStatus, - TxSyncResult, - }, + tx::{TxStatus, TxSyncResult}, }, wait::wait_for_block_commits, }, @@ -115,7 +105,7 @@ pub async fn send_batched_messages_and_wait_check_tx( return Ok(Vec::new()); } - let batches = batch_messages(config, key_pair, account, tx_memo, messages)?; + let batches = batch_messages(config, key_pair, account, tx_memo, messages).await?; let mut responses = Vec::new(); @@ -145,7 +135,7 @@ async fn send_messages_as_batches( let message_count = messages.len(); - let batches = batch_messages(config, key_pair, account, tx_memo, messages)?; + let batches = batch_messages(config, key_pair, account, tx_memo, messages).await?; debug!( "sending {} messages as {} batches to chain {} in parallel", @@ -186,7 +176,7 @@ async fn sequential_send_messages_as_batches( let message_count = messages.len(); - let batches = batch_messages(config, key_pair, account, tx_memo, messages)?; + let batches = batch_messages(config, key_pair, account, tx_memo, messages).await?; debug!( "sending {} messages as {} batches to chain {} in serial", @@ -251,7 +241,7 @@ fn response_to_tx_sync_result( } } -fn batch_messages( +async fn batch_messages( config: &TxConfig, key_pair: &Secp256k1KeyPair, account: &Account, @@ -266,7 +256,14 @@ fn batch_messages( // Estimate the overhead of the transaction envelope's encoding, // by taking the encoded length of an empty tx with the same auth info and signatures. // Use the maximum possible fee to get an upper bound for varint encoding. - let max_fee = gas_amount_to_fee(&config.gas_config, config.gas_config.max_gas); + let max_fee = gas_amount_to_fee( + &config.gas_config, + config.gas_config.max_gas, + &config.chain_id, + &config.rpc_address, + ) + .await; + let tx_metrics = encoded_tx_metrics(config, key_pair, account, tx_memo, &[], &max_fee)?; let tx_envelope_len = tx_metrics.envelope_len; let empty_body_len = tx_metrics.body_bytes_len; @@ -333,27 +330,13 @@ mod tests { encode::sign_and_encode_tx, gas::gas_amount_to_fee, types::{ - account::{ - Account, - AccountAddress, - AccountNumber, - AccountSequence, - }, + account::{Account, AccountAddress, AccountNumber, AccountSequence}, config::TxConfig, }, }, config, - config::types::{ - MaxMsgNum, - MaxTxSize, - Memo, - }, - keyring::{ - self, - KeyRing, - Secp256k1KeyPair, - SigningKeyPair, - }, + config::types::{MaxMsgNum, MaxTxSize, Memo}, + keyring::{self, KeyRing, Secp256k1KeyPair, SigningKeyPair}, }; const COSMOS_HD_PATH: &str = "m/44'/118'/0'/0/0"; @@ -397,10 +380,16 @@ mod tests { (tx_config, key_pair, account) } - #[test] - fn batch_does_not_exceed_max_tx_size() { + #[tokio::test] + async fn batch_does_not_exceed_max_tx_size() { let (config, key_pair, account) = test_fixture(); - let max_fee = gas_amount_to_fee(&config.gas_config, config.gas_config.max_gas); + let max_fee = gas_amount_to_fee( + &config.gas_config, + config.gas_config.max_gas, + &config.chain_id, + &config.rpc_address, + ) + .await; let mut messages = vec![Any { type_url: "/example.Baz".into(), value: vec![0; 2], @@ -437,6 +426,7 @@ mod tests { &memo, messages.clone(), ) + .await .unwrap(); assert_eq!(batches.len(), 2); @@ -453,8 +443,8 @@ mod tests { } } - #[test] - fn batch_error_on_oversized_message() { + #[tokio::test] + async fn batch_error_on_oversized_message() { const MAX_TX_SIZE: usize = 203; let (config, key_pair, account) = test_fixture(); @@ -475,25 +465,32 @@ mod tests { &memo, messages.clone(), ) + .await .unwrap(); assert_eq!(batches.len(), 1); assert_eq!(batches[0].len(), 1); - let max_fee = gas_amount_to_fee(&config.gas_config, config.gas_config.max_gas); + let max_fee = gas_amount_to_fee( + &config.gas_config, + config.gas_config.max_gas, + &config.chain_id, + &config.rpc_address, + ) + .await; let tx_bytes = sign_and_encode_tx(&config, &key_pair, &account, &memo, &batches[0], &max_fee).unwrap(); assert_eq!(tx_bytes.len(), MAX_TX_SIZE); limited_config.max_tx_size = MaxTxSize::new(MAX_TX_SIZE - 1).unwrap(); - let res = batch_messages(&limited_config, &key_pair, &account, &memo, messages); + let res = batch_messages(&limited_config, &key_pair, &account, &memo, messages).await; assert!(res.is_err()); } - #[test] - fn test_batches_are_structured_appropriately_per_max_msg_num() { + #[tokio::test] + async fn test_batches_are_structured_appropriately_per_max_msg_num() { let (config, key_pair, account) = test_fixture(); // Ensure that when MaxMsgNum is 1, the resulting batch @@ -532,6 +529,7 @@ mod tests { &Memo::new("").unwrap(), messages.clone(), ) + .await .unwrap(); assert_eq!(batches.len(), 5); @@ -550,14 +548,15 @@ mod tests { &Memo::new("").unwrap(), messages, ) + .await .unwrap(); assert_eq!(batches.len(), 1); assert_eq!(batches[0].len(), 5); } - #[test] - fn test_batches_are_structured_appropriately_per_max_tx_size() { + #[tokio::test] + async fn test_batches_are_structured_appropriately_per_max_tx_size() { const MAX_TX_SIZE: usize = 198; let (config, key_pair, account) = test_fixture(); @@ -598,11 +597,18 @@ mod tests { &memo, messages.clone(), ) + .await .unwrap(); assert_eq!(batches.len(), 5); - let max_fee = gas_amount_to_fee(&config.gas_config, config.gas_config.max_gas); + let max_fee = gas_amount_to_fee( + &config.gas_config, + config.gas_config.max_gas, + &config.chain_id, + &config.rpc_address, + ) + .await; for batch in batches { assert_eq!(batch.len(), 1); @@ -622,15 +628,16 @@ mod tests { &Memo::new("").unwrap(), messages, ) + .await .unwrap(); assert_eq!(batches.len(), 1); assert_eq!(batches[0].len(), 5); } - #[test] + #[tokio::test] #[should_panic(expected = "`max_msg_num` must be greater than or equal to 1, found 0")] - fn test_max_msg_num_of_zero_panics() { + async fn test_max_msg_num_of_zero_panics() { let (mut config, key_pair, account) = test_fixture(); config.max_msg_num = MaxMsgNum::new(0).unwrap(); let _batches = batch_messages( @@ -639,6 +646,7 @@ mod tests { &account, &Memo::new("").unwrap(), vec![], - ); + ) + .await; } } diff --git a/crates/relayer/src/chain/cosmos/client.rs b/crates/relayer/src/chain/cosmos/client.rs index dfae496fe0..4f9a35fcaf 100644 --- a/crates/relayer/src/chain/cosmos/client.rs +++ b/crates/relayer/src/chain/cosmos/client.rs @@ -6,8 +6,7 @@ use ibc_relayer_types::core::ics02_client::trust_threshold::TrustThreshold; use tracing::warn; use crate::{ - chain::cosmos::config::CosmosSdkConfig, - foreign_client::CreateOptions, + chain::cosmos::config::CosmosSdkConfig, foreign_client::CreateOptions, util::pretty::PrettyDuration, }; diff --git a/crates/relayer/src/chain/cosmos/compatibility.rs b/crates/relayer/src/chain/cosmos/compatibility.rs index 990fc0b60a..f997081d92 100644 --- a/crates/relayer/src/chain/cosmos/compatibility.rs +++ b/crates/relayer/src/chain/cosmos/compatibility.rs @@ -24,12 +24,18 @@ const IBC_GO_MODULE_VERSION_REQ: &str = ">=4.1.1, <9"; #[derive(Error, Debug)] pub enum Diagnostic { + #[error("SDK module version not found, required {requirements}")] + MissingSdkModuleVersion { requirements: String }, + + #[error("IBC-Go module version not found, required {requirements}")] + MissingIbcGoModuleVersion { requirements: String }, + #[error( "SDK module at version '{found}' does not meet compatibility requirements {requirements}" )] MismatchingSdkModuleVersion { requirements: String, found: String }, - #[error("Ibc-Go module at version '{found}' does not meet compatibility requirements {requirements}")] + #[error("IBC-Go module at version '{found}' does not meet compatibility requirements {requirements}")] MismatchingIbcGoModuleVersion { requirements: String, found: String }, } @@ -44,40 +50,44 @@ pub enum Diagnostic { /// Sdk module by name, as well as the constants /// [`SDK_MODULE_VERSION_REQ`] and [`IBC_GO_MODULE_VERSION_REQ`] /// for establishing compatibility requirements. -pub(crate) fn run_diagnostic(v: &version::Specs) -> Result<(), Diagnostic> { - debug!("running diagnostic on version info {}", v); +pub(crate) fn run_diagnostic(specs: &version::Specs) -> Result<(), Diagnostic> { + debug!("running diagnostic on version specs: {specs}"); - sdk_diagnostic(&v.cosmos_sdk)?; - ibc_go_diagnostic(v.ibc_go.as_ref())?; + sdk_diagnostic(specs.cosmos_sdk.as_ref())?; + ibc_go_diagnostic(specs.ibc_go.as_ref())?; Ok(()) } -fn sdk_diagnostic(version: &semver::Version) -> Result<(), Diagnostic> { +fn sdk_diagnostic(version: Option<&semver::Version>) -> Result<(), Diagnostic> { // Parse the SDK requirements into a semver let sdk_reqs = semver::VersionReq::parse(SDK_MODULE_VERSION_REQ) .expect("parsing the SDK module requirements into semver"); - // Finally, check the version requirements - match sdk_reqs.matches(version) { - true => Ok(()), - false => Err(Diagnostic::MismatchingSdkModuleVersion { + match version { + None => Err(Diagnostic::MissingSdkModuleVersion { requirements: SDK_MODULE_VERSION_REQ.to_string(), - found: version.to_string(), }), + + Some(version) => match sdk_reqs.matches(version) { + true => Ok(()), + false => Err(Diagnostic::MismatchingSdkModuleVersion { + requirements: SDK_MODULE_VERSION_REQ.to_string(), + found: version.to_string(), + }), + }, } } -fn ibc_go_diagnostic(version_info: Option<&semver::Version>) -> Result<(), Diagnostic> { +fn ibc_go_diagnostic(version: Option<&semver::Version>) -> Result<(), Diagnostic> { // Parse the IBC-go module requirements into a semver let ibc_reqs = semver::VersionReq::parse(IBC_GO_MODULE_VERSION_REQ) .expect("parsing the IBC-Go module requirements into semver"); - // Find the Ibc-Go module - match version_info { - // If binary lacks the ibc-go dependency it is _not_ an error, - // we support chains without the standalone ibc-go module. - None => Ok(()), + match version { + None => Err(Diagnostic::MissingIbcGoModuleVersion { + requirements: IBC_GO_MODULE_VERSION_REQ.to_string(), + }), Some(version) => match ibc_reqs.matches(version) { true => Ok(()), false => Err(Diagnostic::MismatchingIbcGoModuleVersion { diff --git a/crates/relayer/src/chain/cosmos/config.rs b/crates/relayer/src/chain/cosmos/config.rs index c64e8e0503..813a9e4412 100644 --- a/crates/relayer/src/chain/cosmos/config.rs +++ b/crates/relayer/src/chain/cosmos/config.rs @@ -3,38 +3,22 @@ use std::path::PathBuf; use byte_unit::Byte; use ibc_relayer_types::core::{ - ics23_commitment::specs::ProofSpecs, - ics24_host::identifier::ChainId, -}; -use serde_derive::{ - Deserialize, - Serialize, + ics23_commitment::specs::ProofSpecs, ics24_host::identifier::ChainId, }; +use serde_derive::{Deserialize, Serialize}; use tendermint_rpc::Url; -use crate::{ - chain::cosmos::config::error::Error as ConfigError, - config::{ - self, - compat_mode::CompatMode, - default, - gas_multiplier::GasMultiplier, - types::{ - MaxMsgNum, - MaxTxSize, - Memo, - TrustThreshold, - }, - AddressType, - EventSourceMode, - ExtensionOption, - GasPrice, - GenesisRestart, - PacketFilter, - RefreshRate, - }, - keyring::Store, +use crate::chain::cosmos::config::error::Error as ConfigError; +use crate::config::compat_mode::CompatMode; +use crate::config::dynamic_gas::DynamicGasPrice; +use crate::config::gas_multiplier::GasMultiplier; +use crate::config::types::{MaxMsgNum, MaxTxSize, Memo, TrustThreshold}; +use crate::config::{ + self, AddressType, EventSourceMode, ExtensionOption, GasPrice, GenesisRestart, PacketFilter, }; +use crate::config::{default, RefreshRate}; +use crate::keyring::Store; +use crate::util::excluded_sequences::ExcludedSequences; pub mod error; @@ -71,7 +55,7 @@ pub struct CosmosSdkConfig { 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 + // for when we need to upgrade a client across a genesis restart and // therefore need and archive node to fetch blocks from. pub genesis_restart: Option, @@ -123,6 +107,9 @@ pub struct CosmosSdkConfig { #[serde(default)] pub memo_prefix: Memo, + #[serde(default)] + pub memo_overwrite: Option, + // 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 @@ -151,12 +138,20 @@ pub struct CosmosSdkConfig { #[serde(default)] pub packet_filter: PacketFilter, + #[serde(default)] + pub dynamic_gas_price: DynamicGasPrice, + #[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, + #[serde(default)] + pub excluded_sequences: ExcludedSequences, + + #[serde(default = "default::allow_ccq")] + pub allow_ccq: bool, } impl CosmosSdkConfig { diff --git a/crates/relayer/src/chain/cosmos/config/error.rs b/crates/relayer/src/chain/cosmos/config/error.rs index 9500fce21b..545f845609 100644 --- a/crates/relayer/src/chain/cosmos/config/error.rs +++ b/crates/relayer/src/chain/cosmos/config/error.rs @@ -1,8 +1,8 @@ use flex_error::define_error; -use ibc_relayer_types::core::{ - ics02_client::trust_threshold::TrustThreshold, - ics24_host::identifier::ChainId, -}; +use flex_error::TraceError; + +use ibc_relayer_types::core::ics02_client::trust_threshold::TrustThreshold; +use ibc_relayer_types::core::ics24_host::identifier::ChainId; define_error! { Error { @@ -30,5 +30,41 @@ define_error! { e.chain_id, e.gas_adjustment, e.gas_multiplier ) }, + + ExpectedExcludedSequencesArray + |_| { "expected excluded_sequences to be an array of values" }, + + InvalidExcludedSequencesSeparator + { separator: String } + |e| { + format!("excluded_sequences range `{}` is invalid, only '..', '..=' and '-' are valid separators", e.separator) + }, + + MissingStartExcludedSequence + { entry: String } + |e| { + format!("missing the excluded sequence value before the separator in the entry `{}`", e.entry) + }, + + MissingEndExcludedSequence + { entry: String } + |e| { + format!("missing the excluded sequence value after the separator in the entry `{}`", e.entry) + }, + + ParsingStartExcludedSequenceFailed + { entry: String } + [ TraceError ] + |e| { + format!("Error parsing starting sequence as integer in entry `{}`", e.entry) + }, + + + ParsingEndExcludedSequenceFailed + { entry: String } + [ TraceError ] + |e| { + format!("Error parsing ending sequence as integer in entry `{}`", e.entry) + }, } } diff --git a/crates/relayer/src/chain/cosmos/eip_base_fee.rs b/crates/relayer/src/chain/cosmos/eip_base_fee.rs new file mode 100644 index 0000000000..5c91fc7ad6 --- /dev/null +++ b/crates/relayer/src/chain/cosmos/eip_base_fee.rs @@ -0,0 +1,191 @@ +use core::fmt; +use std::ops::Div; +use std::str::FromStr; + +use serde::Deserialize; +use subtle_encoding::base64; +use tendermint_rpc::Url; +use tracing::{debug, trace}; + +use ibc_proto::cosmos::base::v1beta1::{DecCoin, DecProto}; +use ibc_relayer_types::core::ics24_host::identifier::ChainId; + +use crate::error::Error; + +pub async fn query_eip_base_fee( + rpc_address: &Url, + gas_price_denom: &str, + chain_id: &ChainId, +) -> Result { + debug!("Querying Omosis EIP-1559 base fee from {rpc_address}"); + + let chain_name = chain_id.name(); + + let is_osmosis = chain_name.starts_with("osmosis") || chain_name.starts_with("osmo-test"); + + let url = if is_osmosis { + format!( + "{}abci_query?path=\"/osmosis.txfees.v1beta1.Query/GetEipBaseFee\"", + rpc_address + ) + } else { + format!( + "{}abci_query?path=\"/feemarket.feemarket.v1.Query/GasPrices\"&denom={}", + rpc_address, gas_price_denom + ) + }; + + let response = reqwest::get(&url).await.map_err(Error::http_request)?; + + if !response.status().is_success() { + return Err(Error::http_response(response.status())); + } + + #[derive(Deserialize)] + struct EipBaseFeeHTTPResult { + result: EipBaseFeeResult, + } + + #[derive(Deserialize)] + struct EipBaseFeeResult { + response: EipBaseFeeResponse, + } + + #[derive(Deserialize)] + struct EipBaseFeeResponse { + value: String, + } + + let result: EipBaseFeeHTTPResult = response.json().await.map_err(Error::http_response_body)?; + + let amount = if is_osmosis { + extract_dynamic_gas_price_osmosis(result.result.response.value)? + } else { + extract_dynamic_gas_price(result.result.response.value)? + }; + + trace!("EIP-1559 base fee: {amount}"); + + Ok(amount) +} + +/// This method extracts the gas base fee from Skip's feemarket +fn extract_dynamic_gas_price(encoded: String) -> Result { + let decoded = base64::decode(encoded).map_err(Error::base64_decode)?; + + let gas_price_response: GasPriceResponse = + prost::Message::decode(decoded.as_ref()).map_err(|e| { + Error::protobuf_decode("feemarket.feemarket.v1.GasPricesResponse".to_string(), e) + })?; + let dec_coin = gas_price_response.price.unwrap().clone(); + let base_fee_uint128 = Uint128::from_str(&dec_coin.amount).map_err(Error::parse_int)?; + + let dec = Decimal::new(base_fee_uint128); + f64::from_str(dec.to_string().as_str()).map_err(Error::parse_float) +} + +/// This method extracts the gas base fee from Osmosis EIP-1559 +fn extract_dynamic_gas_price_osmosis(encoded: String) -> Result { + let decoded = base64::decode(encoded).map_err(Error::base64_decode)?; + + let dec_proto: DecProto = prost::Message::decode(decoded.as_ref()) + .map_err(|e| Error::protobuf_decode("cosmos.base.v1beta1.DecProto".to_string(), e))?; + + let base_fee_uint128 = Uint128::from_str(&dec_proto.dec).map_err(Error::parse_int)?; + + let dec = Decimal::new(base_fee_uint128); + f64::from_str(dec.to_string().as_str()).map_err(Error::parse_float) +} + +/// GasPriceResponse is the response type for the Query/GasPrice RPC method. +/// Returns a gas price in specified denom. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GasPriceResponse { + #[prost(message, optional, tag = "1")] + pub price: ::core::option::Option, +} + +/// Extracted from `cosmwasm-std` +/// +/// +#[derive(Clone, Copy)] +struct Uint128(u128); + +impl Uint128 { + pub const fn new(value: u128) -> Self { + Self(value) + } + + pub fn is_zero(&self) -> bool { + self.0 == 0 + } + + pub fn checked_rem(&self, rhs: Self) -> Option { + self.0.checked_rem(rhs.0).map(Self) + } +} + +impl FromStr for Uint128 { + type Err = std::num::ParseIntError; + + fn from_str(s: &str) -> Result { + s.parse::().map(Self) + } +} + +impl Div for Uint128 { + type Output = Self; + + fn div(self, rhs: Self) -> Self::Output { + Self( + self.0 + .checked_div(rhs.0) + .expect("attempt to divide by zero"), + ) + } +} + +impl fmt::Display for Uint128 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +/// Extracted from `cosmwasm-std` +/// +/// +#[derive(Clone, Copy)] +struct Decimal(Uint128); + +impl Decimal { + const DECIMAL_FRACTIONAL: Uint128 = Uint128::new(1_000_000_000_000_000_000u128); // 1*10**18 + pub const DECIMAL_PLACES: u32 = 18; + + pub const fn new(value: Uint128) -> Self { + Self(value) + } +} + +impl fmt::Display for Decimal { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use core::fmt::Write; + + let whole = (self.0) / Self::DECIMAL_FRACTIONAL; + let fractional = (self.0).checked_rem(Self::DECIMAL_FRACTIONAL).unwrap(); + + if fractional.is_zero() { + write!(f, "{whole}") + } else { + let fractional_string = format!( + "{:0>padding$}", + fractional, + padding = Self::DECIMAL_PLACES as usize + ); + f.write_str(&whole.to_string())?; + f.write_char('.')?; + f.write_str(fractional_string.trim_end_matches('0'))?; + Ok(()) + } + } +} diff --git a/crates/relayer/src/chain/cosmos/encode.rs b/crates/relayer/src/chain/cosmos/encode.rs index 615a0e2121..5e26696717 100644 --- a/crates/relayer/src/chain/cosmos/encode.rs +++ b/crates/relayer/src/chain/cosmos/encode.rs @@ -1,30 +1,15 @@ use core::str::FromStr; -use bech32::{ - ToBase32, - Variant, -}; +use bech32::{ToBase32, Variant}; use ibc_proto::{ cosmos::tx::v1beta1::{ - mode_info::{ - Single, - Sum, - }, - AuthInfo, - Fee, - ModeInfo, - SignDoc, - SignerInfo, - TxBody, - TxRaw, + mode_info::{Single, Sum}, + AuthInfo, Fee, ModeInfo, SignDoc, SignerInfo, TxBody, TxRaw, }, google::protobuf::Any, }; use ibc_relayer_types::{ - core::{ - ics02_client::error::Error as ClientError, - ics24_host::identifier::ChainId, - }, + core::{ics02_client::error::Error as ClientError, ics24_host::identifier::ChainId}, signer::Signer, }; use prost::Message; @@ -32,23 +17,13 @@ use tendermint::account::Id as AccountId; use crate::{ chain::cosmos::types::{ - account::{ - Account, - AccountNumber, - AccountSequence, - }, + account::{Account, AccountNumber, AccountSequence}, config::TxConfig, tx::SignedTx, }, - config::{ - types::Memo, - AddressType, - }, + config::{types::Memo, AddressType}, error::Error, - keyring::{ - Secp256k1KeyPair, - SigningKeyPair, - }, + keyring::{Secp256k1KeyPair, SigningKeyPair}, }; pub fn sign_and_encode_tx( @@ -145,7 +120,7 @@ pub fn sign_tx( fn encode_key_bytes(key_pair: &Secp256k1KeyPair) -> Result, Error> { let mut pk_buf = Vec::new(); - prost::Message::encode(&key_pair.public_key.serialize().to_vec(), &mut pk_buf) + Message::encode(&key_pair.public_key.serialize().to_vec(), &mut pk_buf) .map_err(|e| Error::protobuf_encode("PublicKey".into(), e))?; Ok(pk_buf) @@ -167,7 +142,7 @@ fn encode_sign_doc( // A protobuf serialization of a SignDoc let mut signdoc_buf = Vec::new(); - prost::Message::encode(&sign_doc, &mut signdoc_buf).unwrap(); + Message::encode(&sign_doc, &mut signdoc_buf).unwrap(); let signed = key_pair.sign(&signdoc_buf).map_err(Error::key_base)?; @@ -203,7 +178,7 @@ fn encode_signer_info( fn encode_tx_raw(tx_raw: TxRaw) -> Result, Error> { let mut tx_bytes = Vec::new(); - prost::Message::encode(&tx_raw, &mut tx_bytes) + Message::encode(&tx_raw, &mut tx_bytes) .map_err(|e| Error::protobuf_encode("Transaction".to_string(), e))?; Ok(tx_bytes) @@ -231,7 +206,7 @@ fn auth_info_and_bytes(signer_info: SignerInfo, fee: Fee) -> Result<(AuthInfo, V // A protobuf serialization of a AuthInfo let mut auth_buf = Vec::new(); - prost::Message::encode(&auth_info, &mut auth_buf) + Message::encode(&auth_info, &mut auth_buf) .map_err(|e| Error::protobuf_encode(String::from("AuthInfo"), e))?; Ok((auth_info, auth_buf)) @@ -254,7 +229,7 @@ fn tx_body_and_bytes( // A protobuf serialization of a TxBody let mut body_buf = Vec::new(); - prost::Message::encode(&body, &mut body_buf) + Message::encode(&body, &mut body_buf) .map_err(|e| Error::protobuf_encode(String::from("TxBody"), e))?; Ok((body, body_buf)) diff --git a/crates/relayer/src/chain/cosmos/estimate.rs b/crates/relayer/src/chain/cosmos/estimate.rs index 4ce084bda1..c5d11f1a7f 100644 --- a/crates/relayer/src/chain/cosmos/estimate.rs +++ b/crates/relayer/src/chain/cosmos/estimate.rs @@ -1,36 +1,36 @@ use ibc_proto::{ - cosmos::tx::v1beta1::{ - Fee, - Tx, - }, + cosmos::tx::v1beta1::{Fee, Tx}, google::protobuf::Any, }; use ibc_relayer_types::core::ics24_host::identifier::ChainId; +use tendermint_rpc::Url; use tonic::codegen::http::Uri; -use tracing::{ - debug, - error, - span, - warn, - Level, -}; +use tracing::{debug, error, span, warn, Level}; + +use crate::chain::cosmos::encode::sign_tx; +use crate::chain::cosmos::gas::gas_amount_to_fee; +use crate::chain::cosmos::simulate::send_tx_simulate; +use crate::chain::cosmos::types::account::Account; +use crate::chain::cosmos::types::config::TxConfig; +use crate::chain::cosmos::types::gas::GasConfig; +use crate::config::types::Memo; +use crate::error::Error; +use crate::keyring::Secp256k1KeyPair; +use crate::telemetry; +use crate::util::pretty::PrettyFee; + +pub enum EstimatedGas { + Simulated(u64), + Default(u64), +} -use crate::{ - chain::cosmos::{ - encode::sign_tx, - gas::gas_amount_to_fee, - simulate::send_tx_simulate, - types::{ - account::Account, - config::TxConfig, - gas::GasConfig, - }, - }, - config::types::Memo, - error::Error, - keyring::Secp256k1KeyPair, - util::pretty::PrettyFee, -}; +impl EstimatedGas { + pub fn get_amount(&self) -> u64 { + match self { + Self::Simulated(amount) | Self::Default(amount) => *amount, + } + } +} pub async fn estimate_tx_fees( config: &TxConfig, @@ -38,7 +38,7 @@ pub async fn estimate_tx_fees( account: &Account, tx_memo: &Memo, messages: &[Any], -) -> Result { +) -> Result<(Fee, EstimatedGas), Error> { let gas_config = &config.gas_config; debug!( @@ -61,18 +61,27 @@ pub async fn estimate_tx_fees( signatures: signed_tx.signatures, }; - let estimated_fee = - estimate_fee_with_tx(gas_config, &config.grpc_address, &config.chain_id, tx).await?; + let estimated_fee_and_gas = estimate_fee_with_tx( + gas_config, + &config.grpc_address, + &config.rpc_address, + &config.chain_id, + tx, + account, + ) + .await?; - Ok(estimated_fee) + Ok(estimated_fee_and_gas) } async fn estimate_fee_with_tx( gas_config: &GasConfig, grpc_address: &Uri, + rpc_address: &Url, chain_id: &ChainId, tx: Tx, -) -> Result { + account: &Account, +) -> Result<(Fee, EstimatedGas), Error> { let estimated_gas = { crate::time!( "estimate_gas_with_tx", @@ -81,32 +90,35 @@ async fn estimate_fee_with_tx( } ); - estimate_gas_with_tx(gas_config, grpc_address, tx).await + estimate_gas_with_tx(gas_config, grpc_address, tx, account).await }?; - if estimated_gas > gas_config.max_gas { + let estimated_gas_amount = estimated_gas.get_amount(); + + if estimated_gas_amount > gas_config.max_gas { debug!( - id = %chain_id, estimated = ?estimated_gas, max = ?gas_config.max_gas, + id = %chain_id, estimated = ?estimated_gas_amount, max = ?gas_config.max_gas, "send_tx: estimated gas is higher than max gas" ); return Err(Error::tx_simulate_gas_estimate_exceeded( chain_id.clone(), - estimated_gas, + estimated_gas_amount, gas_config.max_gas, )); } - let adjusted_fee = gas_amount_to_fee(gas_config, estimated_gas); + let adjusted_fee = + gas_amount_to_fee(gas_config, estimated_gas_amount, chain_id, rpc_address).await; debug!( id = %chain_id, "send_tx: using {} gas, fee {}", - estimated_gas, + estimated_gas_amount, PrettyFee(&adjusted_fee) ); - Ok(adjusted_fee) + Ok((adjusted_fee, estimated_gas)) } /// Try to simulate the given tx in order to estimate how much gas will be needed to submit it. @@ -121,7 +133,8 @@ async fn estimate_gas_with_tx( gas_config: &GasConfig, grpc_address: &Uri, tx: Tx, -) -> Result { + _account: &Account, +) -> Result { let simulated_gas = send_tx_simulate(grpc_address, tx) .await .map(|sr| sr.gas_info); @@ -135,7 +148,7 @@ async fn estimate_gas_with_tx( gas_info.gas_used ); - Ok(gas_info.gas_used) + Ok(EstimatedGas::Simulated(gas_info.gas_used)) } Ok(None) => { @@ -144,7 +157,7 @@ async fn estimate_gas_with_tx( gas_config.default_gas ); - Ok(gas_config.default_gas) + Ok(EstimatedGas::Default(gas_config.default_gas)) } // If there is a chance that the tx will be accepted once actually submitted, we fall @@ -156,7 +169,14 @@ async fn estimate_gas_with_tx( e.detail() ); - Ok(gas_config.default_gas) + telemetry!( + simulate_errors, + &_account.address.to_string(), + true, + get_error_text(&e), + ); + + Ok(EstimatedGas::Default(gas_config.default_gas)) } Err(e) => { @@ -164,6 +184,14 @@ async fn estimate_gas_with_tx( "failed to simulate tx. propagating error to caller: {}", e.detail() ); + + telemetry!( + simulate_errors, + &_account.address.to_string(), + false, + get_error_text(&e), + ); + // Propagate the error, the retrying mechanism at caller may catch & retry. Err(e) } @@ -180,7 +208,17 @@ fn can_recover_from_simulation_failure(e: &Error) -> bool { detail.is_client_state_height_too_low() || detail.is_account_sequence_mismatch_that_can_be_ignored() || detail.is_out_of_order_packet_sequence_error() + || detail.is_empty_tx_error() } _ => false, } } + +fn get_error_text(e: &Error) -> String { + use crate::error::ErrorDetail::*; + + match e.detail() { + GrpcStatus(detail) => detail.status.code().to_string(), + detail => detail.to_string(), + } +} diff --git a/crates/relayer/src/chain/cosmos/fee.rs b/crates/relayer/src/chain/cosmos/fee.rs index 9f6e635b7b..d9ad1c72ac 100644 --- a/crates/relayer/src/chain/cosmos/fee.rs +++ b/crates/relayer/src/chain/cosmos/fee.rs @@ -1,32 +1,20 @@ use ibc_relayer_types::{ applications::ics29_fee::msgs::register_payee::build_register_counterparty_payee_message, - core::ics24_host::identifier::{ - ChannelId, - PortId, - }, + core::ics24_host::identifier::{ChannelId, PortId}, signer::Signer, }; use tendermint_rpc::HttpClient; use crate::{ chain::cosmos::{ - query::{ - account::get_or_fetch_account, - fee::query_counterparty_payee, - }, + query::{account::get_or_fetch_account, fee::query_counterparty_payee}, retry::send_tx_with_account_sequence_retry, - types::{ - account::Account, - config::TxConfig, - }, + types::{account::Account, config::TxConfig}, wait::wait_tx_succeed, }, config::types::Memo, error::Error, - keyring::{ - Secp256k1KeyPair, - SigningKeyPair, - }, + keyring::{Secp256k1KeyPair, SigningKeyPair}, }; // FIXME: monster function, refactor diff --git a/crates/relayer/src/chain/cosmos/gas.rs b/crates/relayer/src/chain/cosmos/gas.rs index 78341cd075..2106da3375 100644 --- a/crates/relayer/src/chain/cosmos/gas.rs +++ b/crates/relayer/src/chain/cosmos/gas.rs @@ -1,18 +1,24 @@ use core::cmp::min; - -use ibc_proto::cosmos::{ - base::v1beta1::Coin, - tx::v1beta1::Fee, -}; +use ibc_proto::cosmos::base::v1beta1::Coin; +use ibc_proto::cosmos::tx::v1beta1::Fee; +use ibc_relayer_types::core::ics24_host::identifier::ChainId; use num_bigint::BigInt; use num_rational::BigRational; +use tendermint_rpc::Url; +use tracing::warn; + +use crate::chain::cosmos::types::gas::GasConfig; +use crate::config::GasPrice; +use crate::telemetry; -use crate::{ - chain::cosmos::types::gas::GasConfig, - config::GasPrice, -}; +use super::eip_base_fee::query_eip_base_fee; -pub fn gas_amount_to_fee(config: &GasConfig, gas_amount: u64) -> Fee { +pub async fn gas_amount_to_fee( + config: &GasConfig, + gas_amount: u64, + chain_id: &ChainId, + rpc_address: &Url, +) -> Fee { let adjusted_gas_limit = adjust_estimated_gas(AdjustGas { gas_multiplier: config.gas_multiplier, max_gas: config.max_gas, @@ -20,7 +26,8 @@ pub fn gas_amount_to_fee(config: &GasConfig, gas_amount: u64) -> Fee { }); // The fee in coins based on gas amount - let amount = calculate_fee(adjusted_gas_limit, &config.gas_price); + let dynamic_gas_price = dynamic_gas_price(config, chain_id, rpc_address).await; + let amount = calculate_fee(adjusted_gas_limit, &dynamic_gas_price); Fee { amount: vec![amount], @@ -30,6 +37,59 @@ pub fn gas_amount_to_fee(config: &GasConfig, gas_amount: u64) -> Fee { } } +pub async fn dynamic_gas_price( + config: &GasConfig, + chain_id: &ChainId, + rpc_address: &Url, +) -> GasPrice { + if config.dynamic_gas_price.enabled { + let dynamic_gas_price = query_eip_base_fee(rpc_address, &config.gas_price.denom, chain_id) + .await + .map(|base_fee| base_fee * config.dynamic_gas_price.multiplier) + .map(|new_price| GasPrice { + price: new_price, + denom: config.gas_price.denom.clone(), + }); + + let dynamic_gas_price = match dynamic_gas_price { + Ok(dynamic_gas_price) => { + telemetry!( + dynamic_gas_queried_success_fees, + chain_id, + dynamic_gas_price.price + ); + + dynamic_gas_price + } + Err(e) => { + warn!("failed to query EIP base fee, will fallback to configured `gas_price`: {e}"); + config.gas_price.clone() + } + }; + + { + telemetry!(dynamic_gas_queried_fees, chain_id, dynamic_gas_price.price); + let _ = chain_id; + } + + if dynamic_gas_price.price > config.dynamic_gas_price.max { + warn!( + "queried EIP gas price is higher than configured max gas price, \ + will fallback to configured `max`. Queried: {}, maximum: {}", + dynamic_gas_price.price, config.dynamic_gas_price.max + ); + + return GasPrice::new(config.dynamic_gas_price.max, dynamic_gas_price.denom); + } + + telemetry!(dynamic_gas_paid_fees, chain_id, dynamic_gas_price.price); + + dynamic_gas_price + } else { + config.gas_price.clone() + } +} + pub fn calculate_fee(adjusted_gas_amount: u64, gas_price: &GasPrice) -> Coin { let fee_amount = mul_ceil(adjusted_gas_amount, gas_price.price); @@ -103,10 +163,7 @@ fn adjust_estimated_gas( #[cfg(test)] mod tests { - use super::{ - adjust_estimated_gas, - AdjustGas, - }; + use super::{adjust_estimated_gas, AdjustGas}; #[test] fn adjust_zero_gas() { diff --git a/crates/relayer/src/chain/cosmos/query.rs b/crates/relayer/src/chain/cosmos/query.rs index 48d3137a71..9a6061c713 100644 --- a/crates/relayer/src/chain/cosmos/query.rs +++ b/crates/relayer/src/chain/cosmos/query.rs @@ -1,38 +1,21 @@ -use http::uri::Uri; -use ibc_proto::cosmos::base::tendermint::v1beta1::{ - service_client::ServiceClient, - GetNodeInfoRequest, -}; -use ibc_relayer_types::core::{ - ics04_channel::packet::Sequence, - ics23_commitment::merkle::{ - convert_tm_to_ics_merkle_proof, - MerkleProof, - }, - ics24_host::identifier::ChainId, +use ibc_proto::cosmos::base::tendermint::v1beta1::GetNodeInfoResponse; +use ibc_relayer_types::core::ics04_channel::packet::Sequence; +use ibc_relayer_types::core::ics23_commitment::merkle::{ + convert_tm_to_ics_merkle_proof, MerkleProof, }; +use ibc_relayer_types::core::ics24_host::identifier::ChainId; +use prost::Message; use tendermint::block::Height; -use tendermint_rpc::{ - query::Query, - Client, - HttpClient, - Url, -}; +use tendermint_rpc::{query::Query, Client, HttpClient, Url}; -use crate::{ - chain::{ - cosmos::version::Specs, - requests::{ - QueryClientEventRequest, - QueryPacketEventDataRequest, - QueryTxHash, - }, - }, - error::Error, -}; +use crate::chain::cosmos::version::Specs; +use crate::chain::requests::QueryHeight; +use crate::chain::requests::{QueryClientEventRequest, QueryPacketEventDataRequest, QueryTxHash}; +use crate::error::Error; pub mod account; pub mod balance; +pub mod connection; pub mod consensus_state; pub mod custom; pub mod denom_trace; @@ -137,36 +120,32 @@ pub async fn abci_query( } /// Queries the chain to obtain the version information. -pub async fn fetch_version_specs(chain_id: &ChainId, grpc_address: &Uri) -> Result { - let grpc_addr_string = grpc_address.to_string(); - - // Construct a gRPC client - let mut client = ServiceClient::connect(grpc_address.clone()) - .await - .map_err(|e| { - Error::fetch_version_grpc_transport( - chain_id.clone(), - grpc_addr_string.clone(), - "tendermint::ServiceClient".to_string(), +pub async fn fetch_version_specs( + chain_id: &ChainId, + rpc_client: &HttpClient, + rpc_addr: &Url, +) -> Result { + let query_response = abci_query( + rpc_client, + rpc_addr, + "/cosmos.base.tendermint.v1beta1.Service/GetNodeInfo".to_owned(), + "".to_owned(), + QueryHeight::Latest.into(), + false, + ) + .await?; + let node_info_response = + GetNodeInfoResponse::decode(query_response.value.as_ref()).map_err(|e| { + Error::protobuf_decode( + "cosmos.base.tendermint.v1beta1.Service/GetNodeInfo".to_owned(), e, ) })?; - let request = tonic::Request::new(GetNodeInfoRequest {}); - - let response = client.get_node_info(request).await.map_err(|e| { - Error::fetch_version_grpc_status( - chain_id.clone(), - grpc_addr_string.clone(), - "tendermint::ServiceClient".to_string(), - e, - ) - })?; - - let version = response.into_inner().application_version.ok_or_else(|| { + let version = node_info_response.application_version.ok_or_else(|| { Error::fetch_version_invalid_version_response( chain_id.clone(), - grpc_addr_string.clone(), + rpc_addr.to_string(), "tendermint::GetNodeInfoRequest".to_string(), ) })?; @@ -174,5 +153,5 @@ pub async fn fetch_version_specs(chain_id: &ChainId, grpc_address: &Uri) -> Resu // Parse the raw version info into a domain-type `version::Specs` version .try_into() - .map_err(|e| Error::fetch_version_parsing(chain_id.clone(), grpc_addr_string.clone(), e)) + .map_err(|e| Error::fetch_version_parsing(chain_id.clone(), rpc_addr.to_string(), e)) } diff --git a/crates/relayer/src/chain/cosmos/query/account.rs b/crates/relayer/src/chain/cosmos/query/account.rs index 5a72a77bd6..9b8962d275 100644 --- a/crates/relayer/src/chain/cosmos/query/account.rs +++ b/crates/relayer/src/chain/cosmos/query/account.rs @@ -1,18 +1,14 @@ use http::uri::Uri; use ibc_proto::cosmos::auth::v1beta1::{ - query_client::QueryClient, - BaseAccount, - EthAccount, - QueryAccountRequest, + query_client::QueryClient, BaseAccount, EthAccount, QueryAccountRequest, }; use prost::Message; use tracing::info; -use crate::{ - chain::cosmos::types::account::Account, - config::default::max_grpc_decoding_size, - error::Error, -}; +use crate::chain::cosmos::types::account::Account; +use crate::config::default::max_grpc_decoding_size; +use crate::error::Error; +use crate::util::create_grpc_client; /// Get a `&mut Account` from an `&mut Option` if it is `Some(Account)`. /// Otherwise query for the account information, update the `Option` to `Some`, @@ -60,9 +56,7 @@ pub async fn query_account( grpc_address: &Uri, account_address: &str, ) -> Result { - let mut client = QueryClient::connect(grpc_address.clone()) - .await - .map_err(Error::grpc_transport)?; + let mut client = create_grpc_client(grpc_address.clone(), QueryClient::new).await?; client = client.max_decoding_message_size(max_grpc_decoding_size().get_bytes() as usize); diff --git a/crates/relayer/src/chain/cosmos/query/balance.rs b/crates/relayer/src/chain/cosmos/query/balance.rs index 265fde4350..5237d9123c 100644 --- a/crates/relayer/src/chain/cosmos/query/balance.rs +++ b/crates/relayer/src/chain/cosmos/query/balance.rs @@ -1,15 +1,12 @@ use http::uri::Uri; use ibc_proto::cosmos::bank::v1beta1::{ - query_client::QueryClient, - QueryAllBalancesRequest, - QueryBalanceRequest, + query_client::QueryClient, QueryAllBalancesRequest, QueryBalanceRequest, }; -use crate::{ - account::Balance, - config::default::max_grpc_decoding_size, - error::Error, -}; +use crate::account::Balance; +use crate::config::default::max_grpc_decoding_size; +use crate::error::Error; +use crate::util::create_grpc_client; /// Uses the GRPC client to retrieve the account balance for a specific denom pub async fn query_balance( @@ -17,9 +14,7 @@ pub async fn query_balance( account_address: &str, denom: &str, ) -> Result { - let mut client = QueryClient::connect(grpc_address.clone()) - .await - .map_err(Error::grpc_transport)?; + let mut client = create_grpc_client(grpc_address.clone(), QueryClient::new).await?; client = client.max_decoding_message_size(max_grpc_decoding_size().get_bytes() as usize); @@ -50,9 +45,7 @@ pub async fn query_all_balances( grpc_address: &Uri, account_address: &str, ) -> Result, Error> { - let mut client = QueryClient::connect(grpc_address.clone()) - .await - .map_err(Error::grpc_transport)?; + let mut client = create_grpc_client(grpc_address.clone(), QueryClient::new).await?; client = client.max_decoding_message_size(max_grpc_decoding_size().get_bytes() as usize); diff --git a/crates/relayer/src/chain/cosmos/query/connection.rs b/crates/relayer/src/chain/cosmos/query/connection.rs new file mode 100644 index 0000000000..2fbfe29650 --- /dev/null +++ b/crates/relayer/src/chain/cosmos/query/connection.rs @@ -0,0 +1,29 @@ +use http::uri::Uri; + +use ibc_proto::ibc::core::connection::v1::query_client::QueryClient; +use ibc_proto::ibc::core::connection::v1::Params; +use ibc_proto::ibc::core::connection::v1::QueryConnectionParamsRequest; + +use crate::config::default::max_grpc_decoding_size; +use crate::error::Error; +use crate::util::create_grpc_client; + +/// Uses the GRPC client to retrieve the connection params +pub async fn query_connection_params(grpc_address: &Uri) -> Result { + let mut client = create_grpc_client(grpc_address.clone(), QueryClient::new).await?; + + client = client.max_decoding_message_size(max_grpc_decoding_size().get_bytes() as usize); + + let request = tonic::Request::new(QueryConnectionParamsRequest {}); + + let response = client + .connection_params(request) + .await + .map(|r| r.into_inner()) + .map_err(|e| Error::grpc_status(e, "query_connection_params".to_owned()))?; + + // Querying connection params might not be found + let params = response.params.ok_or_else(Error::empty_connection_params)?; + + Ok(params) +} diff --git a/crates/relayer/src/chain/cosmos/query/consensus_state.rs b/crates/relayer/src/chain/cosmos/query/consensus_state.rs index b586b83229..220a3619a2 100644 --- a/crates/relayer/src/chain/cosmos/query/consensus_state.rs +++ b/crates/relayer/src/chain/cosmos/query/consensus_state.rs @@ -1,26 +1,13 @@ use http::Uri; -use ibc_relayer_types::{ - core::ics24_host::identifier::ChainId, - Height, -}; -use tracing::{ - debug, - warn, -}; - -use crate::{ - chain::requests::{ - QueryConsensusStateHeightsRequest, - QueryConsensusStatesRequest, - }, - config::default::max_grpc_decoding_size, - consensus_state::AnyConsensusStateWithHeight, - error::Error, - util::pretty::{ - PrettyConsensusStateWithHeight, - PrettyHeight, - }, -}; +use ibc_relayer_types::{core::ics24_host::identifier::ChainId, Height}; +use tracing::{debug, warn}; + +use crate::chain::requests::{QueryConsensusStateHeightsRequest, QueryConsensusStatesRequest}; +use crate::config::default::max_grpc_decoding_size; +use crate::consensus_state::AnyConsensusStateWithHeight; +use crate::error::Error; +use crate::util::create_grpc_client; +use crate::util::pretty::{PrettyConsensusStateWithHeight, PrettyHeight}; /// Performs a `QueryConsensusStateHeightsRequest` gRPC query to fetch all the consensus state /// heights associated with a given client. @@ -49,10 +36,11 @@ pub async fn query_consensus_state_heights( .contains("unknown method ConsensusStateHeights") } - let mut client = - ibc_proto::ibc::core::client::v1::query_client::QueryClient::connect(grpc_addr.clone()) - .await - .map_err(Error::grpc_transport)?; + let mut client = create_grpc_client( + grpc_addr.clone(), + ibc_proto::ibc::core::client::v1::query_client::QueryClient::new, + ) + .await?; client = client.max_decoding_message_size(max_grpc_decoding_size().get_bytes() as usize); @@ -85,7 +73,7 @@ pub async fn query_consensus_state_heights( .consensus_state_heights .into_iter() .filter_map(|h| { - Height::try_from(h.clone()) + Height::try_from(h) .map_err(|e| { warn!( "failed to parse consensus state height {}. Error: {}", @@ -118,10 +106,11 @@ pub async fn query_consensus_states( } ); - let mut client = - ibc_proto::ibc::core::client::v1::query_client::QueryClient::connect(grpc_addr.clone()) - .await - .map_err(Error::grpc_transport)?; + let mut client = create_grpc_client( + grpc_addr.clone(), + ibc_proto::ibc::core::client::v1::query_client::QueryClient::new, + ) + .await?; client = client.max_decoding_message_size(max_grpc_decoding_size().get_bytes() as usize); diff --git a/crates/relayer/src/chain/cosmos/query/custom.rs b/crates/relayer/src/chain/cosmos/query/custom.rs index 79557099c9..a31c64db47 100644 --- a/crates/relayer/src/chain/cosmos/query/custom.rs +++ b/crates/relayer/src/chain/cosmos/query/custom.rs @@ -1,23 +1,17 @@ -use hex; +use crate::chain::requests::CrossChainQueryRequest; +use crate::error::Error; + use ibc_relayer_types::applications::ics31_icq::{ - error::Error as CrossChainQueryError, - response::CrossChainQueryResponse, -}; -use tendermint_rpc::{ - Client, - HttpClient, + error::Error as CrossChainQueryError, response::CrossChainQueryResponse, }; -use crate::{ - chain::requests::CrossChainQueryRequest, - error::Error, -}; +use tendermint_rpc::{Client, HttpClient}; pub async fn cross_chain_query_via_rpc( client: &HttpClient, cross_chain_query_request: CrossChainQueryRequest, ) -> Result { - let hex_decoded_request = hex::decode(cross_chain_query_request.request) + let hex_decoded_request = hex::decode(cross_chain_query_request.request.to_lowercase()) .map_err(|_| Error::ics31(CrossChainQueryError::parse()))?; let response = client diff --git a/crates/relayer/src/chain/cosmos/query/denom_trace.rs b/crates/relayer/src/chain/cosmos/query/denom_trace.rs index 1b3e1f85b6..04c213c588 100644 --- a/crates/relayer/src/chain/cosmos/query/denom_trace.rs +++ b/crates/relayer/src/chain/cosmos/query/denom_trace.rs @@ -1,20 +1,16 @@ use http::uri::Uri; use ibc_proto::ibc::applications::transfer::v1::{ - query_client::QueryClient, - QueryDenomTraceRequest, + query_client::QueryClient, QueryDenomTraceRequest, }; -use crate::{ - config::default::max_grpc_decoding_size, - denom::DenomTrace, - error::Error, -}; +use crate::config::default::max_grpc_decoding_size; +use crate::denom::DenomTrace; +use crate::error::Error; +use crate::util::create_grpc_client; // Uses the GRPC client to retrieve the denom trace for a specific hash pub async fn query_denom_trace(grpc_address: &Uri, hash: &str) -> Result { - let mut client = QueryClient::connect(grpc_address.clone()) - .await - .map_err(Error::grpc_transport)?; + let mut client = create_grpc_client(grpc_address.clone(), QueryClient::new).await?; client = client.max_decoding_message_size(max_grpc_decoding_size().get_bytes() as usize); diff --git a/crates/relayer/src/chain/cosmos/query/fee.rs b/crates/relayer/src/chain/cosmos/query/fee.rs index 317f5ba518..bf48230cad 100644 --- a/crates/relayer/src/chain/cosmos/query/fee.rs +++ b/crates/relayer/src/chain/cosmos/query/fee.rs @@ -1,38 +1,28 @@ use http::uri::Uri; use ibc_proto::ibc::{ applications::fee::v1::{ - query_client::QueryClient, - QueryCounterpartyPayeeRequest, + query_client::QueryClient, QueryCounterpartyPayeeRequest, QueryIncentivizedPacketsForChannelRequest, }, - apps::fee::v1::{ - QueryIncentivizedPacketRequest, - QueryIncentivizedPacketResponse, - }, + apps::fee::v1::{QueryIncentivizedPacketRequest, QueryIncentivizedPacketResponse}, }; use ibc_relayer_types::{ applications::ics29_fee::packet_fee::IdentifiedPacketFees, - core::ics24_host::identifier::{ - ChannelId, - PortId, - }, + core::ics24_host::identifier::{ChannelId, PortId}, signer::Signer, }; use tonic::Code; -use crate::{ - config::default::max_grpc_decoding_size, - error::Error, -}; +use crate::config::default::max_grpc_decoding_size; +use crate::error::Error; +use crate::util::create_grpc_client; pub async fn query_counterparty_payee( grpc_address: &Uri, channel_id: &ChannelId, address: &Signer, ) -> Result, Error> { - let mut client = QueryClient::connect(grpc_address.clone()) - .await - .map_err(Error::grpc_transport)?; + let mut client = create_grpc_client(grpc_address.clone(), QueryClient::new).await?; client = client.max_decoding_message_size(max_grpc_decoding_size().get_bytes() as usize); @@ -64,9 +54,7 @@ pub async fn query_incentivized_packets( channel_id: &ChannelId, port_id: &PortId, ) -> Result, Error> { - let mut client = QueryClient::connect(grpc_address.clone()) - .await - .map_err(Error::grpc_transport)?; + let mut client = create_grpc_client(grpc_address.clone(), QueryClient::new).await?; client = client.max_decoding_message_size(max_grpc_decoding_size().get_bytes() as usize); @@ -98,9 +86,7 @@ pub async fn query_incentivized_packet( grpc_address: &Uri, request: QueryIncentivizedPacketRequest, ) -> Result { - let mut client = QueryClient::connect(grpc_address.clone()) - .await - .map_err(Error::grpc_transport)?; + let mut client = create_grpc_client(grpc_address.clone(), QueryClient::new).await?; client = client.max_decoding_message_size(max_grpc_decoding_size().get_bytes() as usize); diff --git a/crates/relayer/src/chain/cosmos/query/status.rs b/crates/relayer/src/chain/cosmos/query/status.rs index 532a170ef3..5da1a83bc1 100644 --- a/crates/relayer/src/chain/cosmos/query/status.rs +++ b/crates/relayer/src/chain/cosmos/query/status.rs @@ -1,17 +1,7 @@ -use ibc_relayer_types::{ - core::ics24_host::identifier::ChainId, - Height, -}; -use tendermint_rpc::{ - Client, - HttpClient, - Url, -}; +use ibc_relayer_types::{core::ics24_host::identifier::ChainId, Height}; +use tendermint_rpc::{Client, HttpClient, Url}; -use crate::{ - chain::endpoint::ChainStatus, - error::Error, -}; +use crate::{chain::endpoint::ChainStatus, error::Error}; /// Query the chain status via an RPC query. /// diff --git a/crates/relayer/src/chain/cosmos/query/tx.rs b/crates/relayer/src/chain/cosmos/query/tx.rs index 859f69f7f0..97d8f25c58 100644 --- a/crates/relayer/src/chain/cosmos/query/tx.rs +++ b/crates/relayer/src/chain/cosmos/query/tx.rs @@ -1,51 +1,29 @@ use ibc_relayer_types::{ core::{ ics02_client::height::Height, - ics04_channel::packet::{ - Packet, - Sequence, - }, + ics04_channel::packet::{Packet, Sequence}, ics24_host::identifier::ChainId, }, events::IbcEvent, Height as ICSHeight, }; -use tendermint::{ - abci::Event, - Hash as TxHash, -}; -use tendermint_rpc::{ - endpoint::tx::Response as TxResponse, - Client, - HttpClient, - Order, - Url, -}; +use tendermint::{abci::Event, Hash as TxHash}; +use tendermint_rpc::{endpoint::tx::Response as TxResponse, Client, HttpClient, Order, Url}; use tracing::warn; use crate::{ chain::{ cosmos::{ - query::{ - header_query, - packet_query, - tx_hash_query, - }, + query::{header_query, packet_query, tx_hash_query}, types::events, }, requests::{ - QueryClientEventRequest, - QueryHeight, - QueryPacketEventDataRequest, - QueryTxHash, + QueryClientEventRequest, QueryHeight, QueryPacketEventDataRequest, QueryTxHash, QueryTxRequest, }, }, error::Error, - event::{ - ibc_event_try_from_abci_event, - IbcEventWithHeight, - }, + event::{ibc_event_try_from_abci_event, IbcEventWithHeight}, }; /// This function queries transactions for events matching certain criteria. @@ -106,6 +84,12 @@ pub async fn query_txs( } QueryTxRequest::Transaction(tx) => { + crate::time!( + "query_txs: transaction hash", + { + "src_chain": chain_id, + } + ); let mut response = rpc_client .tx_search( tx_hash_query(&tx), diff --git a/crates/relayer/src/chain/cosmos/retry.rs b/crates/relayer/src/chain/cosmos/retry.rs index 7dfb3fac5b..a49f20c472 100644 --- a/crates/relayer/src/chain/cosmos/retry.rs +++ b/crates/relayer/src/chain/cosmos/retry.rs @@ -3,35 +3,20 @@ use std::thread; use ibc_proto::google::protobuf::Any; use tendermint::abci::Code; -use tendermint_rpc::{ - endpoint::broadcast::tx_sync::Response, - HttpClient, -}; -use tracing::{ - debug, - error, - instrument, - warn, -}; +use tendermint_rpc::{endpoint::broadcast::tx_sync::Response, HttpClient}; +use tracing::{debug, error, instrument, warn}; use crate::{ chain::cosmos::{ query::account::refresh_account, tx::estimate_fee_and_send_tx, - types::{ - account::Account, - config::TxConfig, - }, + types::{account::Account, config::TxConfig}, }, config::types::Memo, error::Error, - keyring::{ - Secp256k1KeyPair, - SigningKeyPair, - }, + keyring::{Secp256k1KeyPair, SigningKeyPair}, sdk_error::sdk_error_from_tx_sync_error_code, - telemetry, - time, + telemetry, time, }; // Delay in milliseconds before retrying in the case of account sequence mismatch. @@ -119,7 +104,7 @@ async fn do_send_tx_with_account_sequence_retry( // 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) => { + Ok((response, _)) if response.code == Code::from(INCORRECT_ACCOUNT_SEQUENCE_ERR) => { warn!( ?response, "failed to broadcast tx because of a mismatched account sequence number, \ @@ -141,7 +126,7 @@ async fn do_send_tx_with_account_sequence_retry( // Gas estimation succeeded and broadcast_tx_sync was either successful or has failed with // an unrecoverable error. - Ok(response) => { + Ok((response, estimated_gas)) => { debug!("gas estimation succeeded"); // Gas estimation and broadcast_tx_sync were successful. @@ -171,7 +156,7 @@ async fn do_send_tx_with_account_sequence_retry( // Log the error. error!( ?response, - diagnostic = ?sdk_error_from_tx_sync_error_code(code.into()), + diagnostic = ?sdk_error_from_tx_sync_error_code(code.into(), estimated_gas), "failed to broadcast tx with unrecoverable error" ); @@ -211,7 +196,10 @@ async fn refresh_account_and_retry_send_tx_with_account_sequence( // Retry after delay thread::sleep(Duration::from_millis(ACCOUNT_SEQUENCE_RETRY_DELAY)); - estimate_fee_and_send_tx(rpc_client, config, key_pair, account, tx_memo, messages).await + let (estimate_result, _) = + estimate_fee_and_send_tx(rpc_client, config, key_pair, account, tx_memo, messages).await?; + + Ok(estimate_result) } /// Determine whether the given error yielded by `tx_simulate` diff --git a/crates/relayer/src/chain/cosmos/simulate.rs b/crates/relayer/src/chain/cosmos/simulate.rs index ec6abbceb7..6481c7b80a 100644 --- a/crates/relayer/src/chain/cosmos/simulate.rs +++ b/crates/relayer/src/chain/cosmos/simulate.rs @@ -1,15 +1,11 @@ use ibc_proto::cosmos::tx::v1beta1::{ - service_client::ServiceClient, - SimulateRequest, - SimulateResponse, - Tx, + service_client::ServiceClient, SimulateRequest, SimulateResponse, Tx, }; use tonic::codegen::http::Uri; -use crate::{ - config::default::max_grpc_decoding_size, - error::Error, -}; +use crate::config::default::max_grpc_decoding_size; +use crate::error::Error; +use crate::util::create_grpc_client; pub async fn send_tx_simulate(grpc_address: &Uri, tx: Tx) -> Result { let mut tx_bytes = vec![]; @@ -21,9 +17,7 @@ pub async fn send_tx_simulate(grpc_address: &Uri, tx: Tx) -> Result Result { - let fee = estimate_tx_fees(config, key_pair, account, tx_memo, messages).await?; +) -> Result<(Response, EstimatedGas), Error> { + let (fee, estimated_gas) = + estimate_tx_fees(config, key_pair, account, tx_memo, messages).await?; - send_tx_with_fee( + let tx_result = send_tx_with_fee( rpc_client, config, key_pair, account, tx_memo, messages, &fee, ) - .await + .await?; + + Ok((tx_result, estimated_gas)) } async fn send_tx_with_fee( @@ -103,7 +91,7 @@ pub async fn simple_send_tx( .await? .into(); - let response = estimate_fee_and_send_tx( + let (response, _) = estimate_fee_and_send_tx( rpc_client, config, key_pair, diff --git a/crates/relayer/src/chain/cosmos/types/account.rs b/crates/relayer/src/chain/cosmos/types/account.rs index bdb6b1a997..be1d5209f6 100644 --- a/crates/relayer/src/chain/cosmos/types/account.rs +++ b/crates/relayer/src/chain/cosmos/types/account.rs @@ -1,8 +1,4 @@ -use core::fmt::{ - Display, - Error as FmtError, - Formatter, -}; +use core::fmt::{Display, Error as FmtError, Formatter}; use ibc_proto::cosmos::auth::v1beta1::BaseAccount; diff --git a/crates/relayer/src/chain/cosmos/types/app_state.rs b/crates/relayer/src/chain/cosmos/types/app_state.rs deleted file mode 100644 index e4feec3f7b..0000000000 --- a/crates/relayer/src/chain/cosmos/types/app_state.rs +++ /dev/null @@ -1,49 +0,0 @@ -//! Structure used to parse queried Genesis state using -//! /genesis RPC endpoint. - -use serde::Deserialize as SerdeDeserialize; -use serde_derive::{ - Deserialize, - Serialize, -}; - -#[derive(Debug, Deserialize, Serialize)] -pub struct GenesisAppState { - ibc: IbcConfig, -} - -impl GenesisAppState { - pub fn max_expected_time_per_block(&self) -> u64 { - self.ibc - .connection_genesis - .params - .max_expected_time_per_block - } -} - -#[derive(Debug, Deserialize, Serialize)] -struct IbcConfig { - connection_genesis: ConnectionGenesisConfig, -} - -#[derive(Debug, Deserialize, Serialize)] -struct ConnectionGenesisConfig { - params: ConnectionGenesisParams, -} - -#[derive(Debug, Deserialize, Serialize)] -struct ConnectionGenesisParams { - #[serde(deserialize_with = "deserialize_max_expected_per_block")] - max_expected_time_per_block: u64, -} - -fn deserialize_max_expected_per_block<'de, T, D>(de: D) -> Result -where - D: serde::Deserializer<'de>, - T: std::str::FromStr, - ::Err: std::fmt::Display, -{ - String::deserialize(de)? - .parse() - .map_err(serde::de::Error::custom) -} diff --git a/crates/relayer/src/chain/cosmos/types/config.rs b/crates/relayer/src/chain/cosmos/types/config.rs index de93bc5e57..8034a6a374 100644 --- a/crates/relayer/src/chain/cosmos/types/config.rs +++ b/crates/relayer/src/chain/cosmos/types/config.rs @@ -1,7 +1,4 @@ -use core::{ - str::FromStr, - time::Duration, -}; +use core::{str::FromStr, time::Duration}; use http::Uri; use ibc_proto::google::protobuf::Any; @@ -9,15 +6,9 @@ use ibc_relayer_types::core::ics24_host::identifier::ChainId; use tendermint_rpc::Url; use crate::{ - chain::cosmos::{ - config::CosmosSdkConfig, - types::gas::GasConfig, - }, + chain::cosmos::{config::CosmosSdkConfig, types::gas::GasConfig}, config::{ - types::{ - MaxMsgNum, - MaxTxSize, - }, + types::{MaxMsgNum, MaxTxSize}, AddressType, }, error::Error, diff --git a/crates/relayer/src/chain/cosmos/types/events/channel.rs b/crates/relayer/src/chain/cosmos/types/events/channel.rs index fcb7b970eb..7a1313ae00 100644 --- a/crates/relayer/src/chain/cosmos/types/events/channel.rs +++ b/crates/relayer/src/chain/cosmos/types/events/channel.rs @@ -1,42 +1,22 @@ use alloc::collections::btree_map::BTreeMap as HashMap; -use ibc_relayer_types::{ - core::{ - ics02_client::height::HeightErrorDetail, - ics04_channel::{ - error::Error, - events::{ - AcknowledgePacket, - Attributes, - CloseConfirm, - CloseInit, - EventType, - OpenAck, - OpenConfirm, - OpenInit, - OpenTry, - ReceivePacket, - SendPacket, - TimeoutOnClosePacket, - TimeoutPacket, - WriteAcknowledgement, - PKT_ACK_ATTRIBUTE_KEY, - PKT_DATA_ATTRIBUTE_KEY, - PKT_DST_CHANNEL_ATTRIBUTE_KEY, - PKT_DST_PORT_ATTRIBUTE_KEY, - PKT_SEQ_ATTRIBUTE_KEY, - PKT_SRC_CHANNEL_ATTRIBUTE_KEY, - PKT_SRC_PORT_ATTRIBUTE_KEY, - PKT_TIMEOUT_HEIGHT_ATTRIBUTE_KEY, - PKT_TIMEOUT_TIMESTAMP_ATTRIBUTE_KEY, - }, - packet::Packet, - timeout::TimeoutHeight, - }, - }, - events::Error as EventError, - Height, +use ibc_relayer_types::applications::ics31_icq::events::CrossChainQueryPacket; +use ibc_relayer_types::core::ics02_client::height::HeightErrorDetail; +use ibc_relayer_types::core::ics04_channel::error::Error; +use ibc_relayer_types::core::ics04_channel::events::{ + AcknowledgePacket, Attributes, CloseConfirm, CloseInit, EventType, OpenAck, OpenConfirm, + OpenInit, OpenTry, SendPacket, TimeoutPacket, UpgradeAttributes, UpgradeInit, + WriteAcknowledgement, PKT_ACK_ATTRIBUTE_KEY, PKT_DATA_ATTRIBUTE_KEY, + PKT_DST_CHANNEL_ATTRIBUTE_KEY, PKT_DST_PORT_ATTRIBUTE_KEY, PKT_SEQ_ATTRIBUTE_KEY, + PKT_SRC_CHANNEL_ATTRIBUTE_KEY, PKT_SRC_PORT_ATTRIBUTE_KEY, PKT_TIMEOUT_HEIGHT_ATTRIBUTE_KEY, + PKT_TIMEOUT_TIMESTAMP_ATTRIBUTE_KEY, }; +use ibc_relayer_types::core::ics04_channel::events::{ReceivePacket, TimeoutOnClosePacket}; +use ibc_relayer_types::core::ics04_channel::packet::Packet; +use ibc_relayer_types::core::ics04_channel::timeout::TimeoutHeight; +use ibc_relayer_types::core::ics24_host::identifier::ChainId; +use ibc_relayer_types::events::Error as EventError; +use ibc_relayer_types::Height; fn extract_attributes(object: &RawObject<'_>, namespace: &str) -> Result { Ok(Attributes { @@ -62,6 +42,46 @@ fn extract_attributes(object: &RawObject<'_>, namespace: &str) -> Result, + namespace: &str, +) -> Result { + Ok(UpgradeAttributes { + port_id: extract_attribute(object, &format!("{namespace}.port_id"))? + .parse() + .map_err(EventError::parse)?, + channel_id: extract_attribute(object, &format!("{namespace}.channel_id"))? + .parse() + .map_err(EventError::parse)?, + counterparty_port_id: extract_attribute( + object, + &format!("{namespace}.counterparty_port_id"), + )? + .parse() + .map_err(EventError::parse)?, + counterparty_channel_id: maybe_extract_attribute( + object, + &format!("{namespace}.counterparty_channel_id"), + ) + .and_then(|v| v.parse().ok()), + upgrade_sequence: extract_attribute(object, &format!("{namespace}.upgrade_sequence"))? + .parse() + .map_err(|_| EventError::missing_action_string())?, + upgrade_timeout_height: maybe_extract_attribute( + object, + &format!("{namespace}.timeout_height"), + ) + .and_then(|v| v.parse().ok()), + upgrade_timeout_timestamp: maybe_extract_attribute( + object, + &format!("{namespace}.timeout_timestamp"), + ) + .and_then(|v| v.parse().ok()), + error_receipt: maybe_extract_attribute(object, &format!("{namespace}.error_receipt")) + .and_then(|v| v.parse().ok()), + }) +} + macro_rules! impl_try_from_raw_obj_for_event { ($($event:ty),+) => { $(impl TryFrom> for $event { @@ -89,11 +109,7 @@ macro_rules! impl_try_from_raw_obj_for_packet { type Error = EventError; fn try_from(obj: RawObject<'_>) -> Result { - let data_str: String = extract_attribute(&obj, &format!("{}.{}", obj.action, PKT_DATA_ATTRIBUTE_KEY))?; - - let mut packet = Packet::try_from(obj)?; - packet.data = Vec::from(data_str.as_str().as_bytes()); - + let packet = Packet::try_from(obj)?; Ok(Self { packet }) } })+ @@ -112,18 +128,26 @@ impl TryFrom> for WriteAcknowledgement { type Error = EventError; fn try_from(obj: RawObject<'_>) -> Result { - let data_str: String = - extract_attribute(&obj, &format!("{}.{}", obj.action, PKT_DATA_ATTRIBUTE_KEY))?; - let ack = extract_attribute(&obj, &format!("{}.{}", obj.action, PKT_ACK_ATTRIBUTE_KEY))? - .into_bytes(); + let ack_str = + extract_attribute(&obj, &format!("{}.{}", obj.action, PKT_ACK_ATTRIBUTE_KEY))?; - let mut packet = Packet::try_from(obj)?; - packet.data = Vec::from(data_str.as_bytes()); + let ack = hex::decode(ack_str.to_lowercase()) + .map_err(|_| EventError::invalid_packet_ack(ack_str))?; + + let packet = Packet::try_from(obj)?; Ok(Self { packet, ack }) } } +impl TryFrom> for UpgradeInit { + type Error = EventError; + + fn try_from(obj: RawObject<'_>) -> Result { + extract_upgrade_attributes(&obj, Self::event_type().as_str())?.try_into() + } +} + /// Parse a string into a timeout height expected to be stored in /// `Packet.timeout_height`. We need to parse the timeout height differently /// because of a quirk introduced in ibc-go. See comment in @@ -140,7 +164,14 @@ pub fn parse_timeout_height(s: &str) -> Result { impl TryFrom> for Packet { type Error = EventError; + fn try_from(obj: RawObject<'_>) -> Result { + let data_str = + extract_attribute(&obj, &format!("{}.{}", obj.action, PKT_DATA_ATTRIBUTE_KEY))?; + + let data = hex::decode(data_str.to_lowercase()) + .map_err(|_| EventError::invalid_packet_data(data_str))?; + Ok(Packet { sequence: extract_attribute( &obj, @@ -148,31 +179,37 @@ impl TryFrom> for Packet { )? .parse() .map_err(EventError::channel)?, + source_port: extract_attribute( &obj, &format!("{}.{}", obj.action, PKT_SRC_PORT_ATTRIBUTE_KEY), )? .parse() .map_err(EventError::parse)?, + source_channel: extract_attribute( &obj, &format!("{}.{}", obj.action, PKT_SRC_CHANNEL_ATTRIBUTE_KEY), )? .parse() .map_err(EventError::parse)?, + destination_port: extract_attribute( &obj, &format!("{}.{}", obj.action, PKT_DST_PORT_ATTRIBUTE_KEY), )? .parse() .map_err(EventError::parse)?, + destination_channel: extract_attribute( &obj, &format!("{}.{}", obj.action, PKT_DST_CHANNEL_ATTRIBUTE_KEY), )? .parse() .map_err(EventError::parse)?, - data: vec![], + + data, + timeout_height: { let timeout_height_str = extract_attribute( &obj, @@ -190,6 +227,28 @@ impl TryFrom> for Packet { } } +impl TryFrom> for CrossChainQueryPacket { + type Error = EventError; + + fn try_from(obj: RawObject<'_>) -> Result { + Ok(Self { + module: extract_attribute(&obj, &format!("{}.module", obj.action))?, + action: extract_attribute(&obj, &format!("{}.action", obj.action))?, + query_id: extract_attribute(&obj, &format!("{}.query_id", obj.action))?, + chain_id: extract_attribute(&obj, &format!("{}.chain_id", obj.action)) + .map(|s| ChainId::from_string(&s))?, + connection_id: extract_attribute(&obj, &format!("{}.connection_id", obj.action))? + .parse() + .map_err(EventError::parse)?, + query_type: extract_attribute(&obj, &format!("{}.type", obj.action))?, + request: extract_attribute(&obj, &format!("{}.request", obj.action))?, + height: extract_attribute(&obj, &format!("{}.height", obj.action))? + .parse() + .map_err(|_| EventError::height())?, + }) + } +} + #[derive(Debug, Clone)] pub struct RawObject<'a> { pub height: Height, diff --git a/crates/relayer/src/chain/cosmos/types/events/client.rs b/crates/relayer/src/chain/cosmos/types/events/client.rs index f4e27264bc..fcb1415ef7 100644 --- a/crates/relayer/src/chain/cosmos/types/events/client.rs +++ b/crates/relayer/src/chain/cosmos/types/events/client.rs @@ -77,50 +77,3 @@ pub fn extract_header_from_tx(event: &AbciEvent) -> Result, Erro } Err(Error::missing_raw_header()) } - -#[cfg(test)] -mod tests { - use ibc_relayer_types::core::ics02_client::client_type::ClientType; - use ibc_relayer_types::mock::header::MockHeader; - use ibc_relayer_types::Height; - - use super::*; - - #[test] - fn client_event_to_abci_event() { - let height = Height::new(1, 1).unwrap(); - let attributes = Attributes { - height, - client_id: "test_client".parse().unwrap(), - client_type: ClientType::Tendermint, - consensus_height: height, - }; - let mut abci_events = vec![]; - let create_client = CreateClient::from(attributes.clone()); - abci_events.push(AbciEvent::from(create_client.clone())); - let client_misbehaviour = ClientMisbehaviour::from(attributes.clone()); - abci_events.push(AbciEvent::from(client_misbehaviour.clone())); - let upgrade_client = UpgradeClient::from(attributes.clone()); - abci_events.push(AbciEvent::from(upgrade_client.clone())); - let mut update_client = UpdateClient::from(attributes); - let header = AnyHeader::Mock(MockHeader::new(height)); - update_client.header = Some(header.into_box()); - abci_events.push(AbciEvent::from(update_client.clone())); - - for event in abci_events { - match try_from_tx(&event) { - Some(e) => match e { - IbcEvent::CreateClient(e) => assert_eq!(e.0, create_client.0), - IbcEvent::ClientMisbehaviour(e) => assert_eq!(e.0, client_misbehaviour.0), - IbcEvent::UpgradeClient(e) => assert_eq!(e.0, upgrade_client.0), - IbcEvent::UpdateClient(e) => { - assert_eq!(e.common, update_client.common); - assert_eq!(e.header, update_client.header); - } - _ => panic!("unexpected event type"), - }, - None => panic!("converted event was wrong"), - } - } - } -} diff --git a/crates/relayer/src/chain/cosmos/types/events/fee.rs b/crates/relayer/src/chain/cosmos/types/events/fee.rs index c0050e05b3..678ecda3f8 100644 --- a/crates/relayer/src/chain/cosmos/types/events/fee.rs +++ b/crates/relayer/src/chain/cosmos/types/events/fee.rs @@ -1,9 +1,6 @@ use ibc_relayer_types::{ applications::ics29_fee::events::IncentivizedPacket, - events::{ - IbcEvent, - IbcEventType, - }, + events::{IbcEvent, IbcEventType}, }; use tendermint::abci::Event as AbciEvent; diff --git a/crates/relayer/src/chain/cosmos/types/events/mod.rs b/crates/relayer/src/chain/cosmos/types/events/mod.rs index 40c247c3c1..e96cafdfca 100644 --- a/crates/relayer/src/chain/cosmos/types/events/mod.rs +++ b/crates/relayer/src/chain/cosmos/types/events/mod.rs @@ -1,10 +1,7 @@ use ibc_relayer_types::Height; use tendermint::abci; -use crate::event::{ - ibc_event_try_from_abci_event, - IbcEventWithHeight, -}; +use crate::event::{ibc_event_try_from_abci_event, IbcEventWithHeight}; pub mod channel; pub mod fee; diff --git a/crates/relayer/src/chain/cosmos/types/gas.rs b/crates/relayer/src/chain/cosmos/types/gas.rs index 0198760167..e472eb91af 100644 --- a/crates/relayer/src/chain/cosmos/types/gas.rs +++ b/crates/relayer/src/chain/cosmos/types/gas.rs @@ -1,12 +1,9 @@ use ibc_proto::cosmos::tx::v1beta1::Fee; -use crate::{ - chain::cosmos::{ - calculate_fee, - config::CosmosSdkConfig, - }, - config::GasPrice, -}; +use crate::chain::cosmos::calculate_fee; +use crate::chain::cosmos::config::CosmosSdkConfig; +use crate::config::dynamic_gas::DynamicGasPrice; +use crate::config::GasPrice; /// Default gas limit when submitting a transaction. const DEFAULT_MAX_GAS: u64 = 400_000; @@ -21,6 +18,7 @@ pub struct GasConfig { pub gas_price: GasPrice, pub max_fee: Fee, pub fee_granter: String, + pub dynamic_gas_price: DynamicGasPrice, } impl<'a> From<&'a CosmosSdkConfig> for GasConfig { @@ -32,6 +30,7 @@ impl<'a> From<&'a CosmosSdkConfig> for GasConfig { gas_price: config.gas_price.clone(), max_fee: max_fee_from_config(config), fee_granter: fee_granter_from_config(config), + dynamic_gas_price: config.dynamic_gas_price, } } } diff --git a/crates/relayer/src/chain/cosmos/types/mod.rs b/crates/relayer/src/chain/cosmos/types/mod.rs index 9951b58784..8877d47c36 100644 --- a/crates/relayer/src/chain/cosmos/types/mod.rs +++ b/crates/relayer/src/chain/cosmos/types/mod.rs @@ -1,5 +1,4 @@ pub mod account; -pub mod app_state; pub mod config; pub mod events; pub mod gas; diff --git a/crates/relayer/src/chain/cosmos/types/tx.rs b/crates/relayer/src/chain/cosmos/types/tx.rs index ab50109211..e51184baf0 100644 --- a/crates/relayer/src/chain/cosmos/types/tx.rs +++ b/crates/relayer/src/chain/cosmos/types/tx.rs @@ -1,7 +1,4 @@ -use ibc_proto::cosmos::tx::v1beta1::{ - AuthInfo, - TxBody, -}; +use ibc_proto::cosmos::tx::v1beta1::{AuthInfo, TxBody}; use tendermint_rpc::endpoint::broadcast::tx_sync::Response; use crate::event::IbcEventWithHeight; diff --git a/crates/relayer/src/chain/cosmos/version.rs b/crates/relayer/src/chain/cosmos/version.rs index ffd9b93fdd..5db1b56961 100644 --- a/crates/relayer/src/chain/cosmos/version.rs +++ b/crates/relayer/src/chain/cosmos/version.rs @@ -2,16 +2,13 @@ //! of Cosmos-SDK networks. The extracted version specification //! is captured in a domain-type semver format in [`Specs`]. -use core::fmt::{ - Display, - Error as FmtError, - Formatter, -}; +use core::fmt::{Display, Error as FmtError, Formatter}; use flex_error::define_error; -use ibc_proto::cosmos::base::tendermint::v1beta1::VersionInfo; use tracing::trace; +use ibc_proto::cosmos::base::tendermint::v1beta1::{Module, VersionInfo}; + /// Specifies the SDK, IBC-go, and Tendermint modules path, as expected /// to appear in the application version information of a /// Cosmos-SDK network. @@ -25,69 +22,63 @@ use tracing::trace; /// sum: "h1:yaD4PyOx0LnyfiWasC5egg1U76lT83GRxjJjupPo7Gk=", /// }, /// ``` -const SDK_MODULE_NAME: &str = "cosmos/cosmos-sdk"; -const IBC_GO_MODULE_NAME: &str = "cosmos/ibc-go"; -const TENDERMINT_MODULE_NAME: &str = "tendermint/tendermint"; -const COMET_MODULE_NAME: &str = "cometbft/cometbft"; +const SDK_MODULE_NAME: &str = "github.com/cosmos/cosmos-sdk"; +const IBC_GO_MODULE_PREFIX: &str = "github.com/cosmos/ibc-go/v"; +const TENDERMINT_MODULE_NAME: &str = "github.com/tendermint/tendermint"; +const COMET_MODULE_NAME: &str = "github.com/cometbft/cometbft"; -/// Captures the version(s) specification of different -/// modules of a network. -/// -/// Assumes that the network runs on Cosmos SDK. -/// Stores both the SDK version as well as -/// the IBC-go module version (if existing). -#[derive(Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum ConsensusVersion { + Tendermint(semver::Version), + Comet(semver::Version), +} + +/// Captures the version(s) specification of different modules of a network. +#[derive(Clone, Debug, PartialEq, Eq)] pub struct Specs { - pub cosmos_sdk: semver::Version, + pub cosmos_sdk: Option, pub ibc_go: Option, - pub tendermint: Option, - pub comet: Option, + pub consensus: Option, } impl Display for Specs { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { - let ibc_go = self - .ibc_go + let cosmos_sdk = self + .cosmos_sdk .as_ref() .map(|v| v.to_string()) .unwrap_or_else(|| "UNKNOWN".to_string()); - let tendermint = self - .tendermint + let ibc_go = self + .ibc_go .as_ref() .map(|v| v.to_string()) .unwrap_or_else(|| "UNKNOWN".to_string()); - let comet = self - .comet - .as_ref() - .map(|v| v.to_string()) - .unwrap_or_else(|| "UNKNOWN".to_string()); + let consensus = match self.consensus { + Some(ConsensusVersion::Tendermint(ref v)) => format!("Tendermint {v}"), + Some(ConsensusVersion::Comet(ref v)) => format!("CometBFT {v}"), + None => "Tendermint: UNKNOWN, CometBFT: UNKNOWN".to_string(), + }; write!( f, - "Cosmos SDK {}, IBC-Go {}, Tendermint {}, CometBFT {}", - self.cosmos_sdk, ibc_go, tendermint, comet + "Cosmos SDK {}, IBC-Go {}, {}", + cosmos_sdk, ibc_go, consensus ) } } define_error! { Error { - SdkModuleNotFound - { - address: String, - app: AppInfo, - } - |e| { format!("failed to find the SDK module dependency ('{}') for application {}", e.address, e.app) }, - ConsensusModuleNotFound { tendermint: String, comet: String, app: AppInfo, } - |e| { format!("failed to find the Tendermint ('{}') or CometBFT ('{}') dependency for application {}", e.tendermint, e.comet, e.app) }, + |e| { format!("failed to find the Tendermint ('{}') or CometBFT ('{}') dependency for application {}", + e.tendermint, e.comet, e.app) }, VersionParsingFailed { @@ -111,8 +102,14 @@ impl TryFrom for Specs { let tendermint_version = parse_tendermint_version(&raw_version)?; let comet_version = parse_comet_version(&raw_version)?; + let consensus_version = match (tendermint_version, comet_version) { + (_, Some(comet)) => Some(ConsensusVersion::Comet(comet)), + (Some(tendermint), _) => Some(ConsensusVersion::Tendermint(tendermint)), + _ => None, + }; + // Ensure that either Tendermint or CometBFT are being used. - if tendermint_version.is_none() && comet_version.is_none() { + if consensus_version.is_none() { return Err(Error::consensus_module_not_found( TENDERMINT_MODULE_NAME.to_string(), COMET_MODULE_NAME.to_string(), @@ -124,77 +121,50 @@ impl TryFrom for Specs { application = %raw_version.app_name, version = %raw_version.version, git_commit = %raw_version.git_commit, - sdk_version = %sdk_version, + sdk_version = ?sdk_version, ibc_go_status = ?ibc_go_version, - tendermint_version = ?tendermint_version, - comet_version = ?comet_version, + consensus_version = ?consensus_version, "parsed version specification" ); Ok(Self { cosmos_sdk: sdk_version, ibc_go: ibc_go_version, - tendermint: tendermint_version, - comet: comet_version, + consensus: consensus_version, }) } } -fn parse_sdk_version(version_info: &VersionInfo) -> Result { - let module = version_info - .build_deps - .iter() - .find(|&m| m.path.contains(SDK_MODULE_NAME)) - .ok_or_else(|| { - Error::sdk_module_not_found(SDK_MODULE_NAME.to_string(), AppInfo::from(version_info)) - })?; - - // The raw version number has a leading 'v', trim it out; - let plain_version = module.version.trim_start_matches('v'); - - // Parse the module version - let mut version = semver::Version::parse(plain_version).map_err(|e| { - Error::version_parsing_failed( - module.path.clone(), - module.version.clone(), - e.to_string(), - AppInfo::from(version_info), - ) - })?; - - // Remove the pre-release version to ensure we treat pre-releases of the SDK - // as their normal version, eg. 0.42.0-rc2 should satisfy >=0.41.3, <= 0.42.6. - version.pre = semver::Prerelease::EMPTY; - - Ok(version) +fn parse_sdk_version(version_info: &VersionInfo) -> Result, Error> { + parse_optional_version(version_info, |m| m.path == SDK_MODULE_NAME) } fn parse_ibc_go_version(version_info: &VersionInfo) -> Result, Error> { - parse_optional_version(version_info, IBC_GO_MODULE_NAME) + parse_optional_version(version_info, |m| m.path.starts_with(IBC_GO_MODULE_PREFIX)) } fn parse_tendermint_version(version_info: &VersionInfo) -> Result, Error> { - parse_optional_version(version_info, TENDERMINT_MODULE_NAME) + parse_optional_version(version_info, |m| m.path == TENDERMINT_MODULE_NAME) } fn parse_comet_version(version_info: &VersionInfo) -> Result, Error> { - parse_optional_version(version_info, COMET_MODULE_NAME) + parse_optional_version(version_info, |m| m.path == COMET_MODULE_NAME) } fn parse_optional_version( version_info: &VersionInfo, - module_name: &str, + predicate: impl Fn(&Module) -> bool, ) -> Result, Error> { - match version_info - .build_deps - .iter() - .find(|&m| m.path.contains(module_name)) - { + let module = version_info.build_deps.iter().find(|&m| predicate(m)); + + match module { None => Ok(None), + Some(module) => { let plain_version = module.version.trim_start_matches('v'); semver::Version::parse(plain_version) + // Discard the pre-release version, if any .map(|mut version| { version.pre = semver::Prerelease::EMPTY; Some(version) @@ -213,7 +183,7 @@ fn parse_optional_version( /// Helper struct to capture all the reported information of an /// IBC application, e.g., `gaiad`. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct AppInfo { app_name: String, version: String, @@ -235,3 +205,171 @@ impl From<&VersionInfo> for AppInfo { } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn cosmoshub() { + let version_info = VersionInfo { + name: "gaia".to_string(), + app_name: "gaiad".to_string(), + version: "v14.2.0".to_string(), + git_commit: "3aa6e5058b4cbb4729300b239abfabd9a5b5691f".to_string(), + build_tags: "netgo,ledger".to_string(), + go_version: "go version go1.20.3 linux/amd64".to_string(), + cosmos_sdk_version: "v0.45.16".to_string(), + build_deps: vec![ + Module { + path: "github.com/cometbft/cometbft-db".to_string(), + version: "v0.7.0".to_string(), + sum: "h1:uBjbrBx4QzU0zOEnU8KxoDl18dMNgDh+zZRUE0ucsbo=".to_string(), + }, + Module { + path: "github.com/confio/ics23/go".to_string(), + version: "v0.9.0".to_string(), + sum: "h1:cWs+wdbS2KRPZezoaaj+qBleXgUk5WOQFMP3CQFGTr4=".to_string(), + }, + Module { + path: "github.com/cosmos/cosmos-db".to_string(), + version: "v0.0.0-20221226095112-f3c38ecb5e32".to_string(), + sum: "h1:zlCp9n3uwQieELltZWHRmwPmPaZ8+XoL2Sj+A2YJlr8=".to_string(), + }, + Module { + path: "github.com/cosmos/cosmos-proto".to_string(), + version: "v1.0.0-beta.1".to_string(), + sum: "h1:iDL5qh++NoXxG8hSy93FdYJut4XfgbShIocllGaXx/0=".to_string(), + }, + Module { + path: "github.com/cosmos/cosmos-sdk".to_string(), + version: "v0.45.16".to_string(), + sum: "".to_string(), + }, + Module { + path: "github.com/cosmos/go-bip39".to_string(), + version: "v1.0.0".to_string(), + sum: "h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY=".to_string(), + }, + Module { + path: "github.com/cosmos/iavl".to_string(), + version: "v0.19.5".to_string(), + sum: "h1:rGA3hOrgNxgRM5wYcSCxgQBap7fW82WZgY78V9po/iY=".to_string(), + }, + Module { + path: "github.com/tendermint/tendermint".to_string(), + version: "v0.34.27".to_string(), + sum: "".to_string(), + }, + Module { + path: "github.com/cosmos/ibc-go/v4".to_string(), + version: "v4.4.2".to_string(), + sum: "h1:PG4Yy0/bw6Hvmha3RZbc53KYzaCwuB07Ot4GLyzcBvo=".to_string(), + }, + Module { + path: "github.com/cosmos/interchain-security/v2".to_string(), + version: "v2.0.0".to_string(), + sum: "".to_string(), + }, + ], + }; + + let app_info = AppInfo::from(&version_info); + + assert_eq!( + app_info, + AppInfo { + app_name: "gaiad".to_string(), + version: "v14.2.0".to_string(), + git_commit: "3aa6e5058b4cbb4729300b239abfabd9a5b5691f".to_string() + } + ); + + let specs = Specs::try_from(version_info).unwrap(); + + assert_eq!( + specs, + Specs { + cosmos_sdk: Some(semver::Version::parse("0.45.16").unwrap()), + ibc_go: Some(semver::Version::parse("4.4.2").unwrap()), + consensus: Some(ConsensusVersion::Tendermint( + semver::Version::parse("0.34.27").unwrap() + )) + } + ); + } + + #[test] + fn phoenix() { + let version_info = VersionInfo { + name: "terra".to_string(), + app_name: "terrad".to_string(), + version: "20210603".to_string(), + git_commit: "7cbb1f555b661a6ebec55231e563d2f94effc40e".to_string(), + build_tags: "netgo,ledger".to_string(), + go_version: "go version go1.20 linux/amd64".to_string(), + cosmos_sdk_version: "v0.47.5".to_string(), + build_deps: vec![ + Module { + path: "github.com/confio/ics23/go".to_string(), + version: "v0.9.0".to_string(), + sum: "h1:cWs+wdbS2KRPZezoaaj+qBleXgUk5WOQFMP3CQFGTr4=".to_string(), + }, + Module { + path: "github.com/cometbft/cometbft-db".to_string(), + version: "v0.8.0".to_string(), + sum: "h1:vUMDaH3ApkX8m0KZvOFFy9b5DZHBAjsnEuo9AKVZpjo=".to_string(), + }, + Module { + path: "github.com/cosmos/cosmos-proto".to_string(), + version: "v1.0.0-beta.3".to_string(), + sum: "h1:VitvZ1lPORTVxkmF2fAp3IiA61xVwArQYKXTdEcpW6o=".to_string(), + }, + Module { + path: "github.com/cosmos/cosmos-sdk".to_string(), + version: "v0.47.5".to_string(), + sum: "".to_string(), + }, + Module { + path: "github.com/cosmos/ibc-go/v7".to_string(), + version: "v7.3.0".to_string(), + sum: "".to_string(), + }, + Module { + path: "github.com/cosmos/ics23/go".to_string(), + version: "v0.10.0".to_string(), + sum: "h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM=".to_string(), + }, + Module { + path: "github.com/cometbft/cometbft".to_string(), + version: "v0.37.2".to_string(), + sum: "h1:XB0yyHGT0lwmJlFmM4+rsRnczPlHoAKFX6K8Zgc2/Jc=".to_string(), + }, + ], + }; + + let app_info = AppInfo::from(&version_info); + + assert_eq!( + app_info, + AppInfo { + app_name: "terrad".to_string(), + version: "20210603".to_string(), + git_commit: "7cbb1f555b661a6ebec55231e563d2f94effc40e".to_string() + } + ); + + let specs = Specs::try_from(version_info).unwrap(); + + assert_eq!( + specs, + Specs { + cosmos_sdk: Some(semver::Version::parse("0.47.5").unwrap()), + ibc_go: Some(semver::Version::parse("7.3.0").unwrap()), + consensus: Some(ConsensusVersion::Comet( + semver::Version::parse("0.37.2").unwrap() + )) + } + ); + } +} diff --git a/crates/relayer/src/chain/cosmos/wait.rs b/crates/relayer/src/chain/cosmos/wait.rs index 61266bf009..43e897a026 100644 --- a/crates/relayer/src/chain/cosmos/wait.rs +++ b/crates/relayer/src/chain/cosmos/wait.rs @@ -1,37 +1,19 @@ use core::time::Duration; -use std::{ - thread, - time::Instant, -}; +use std::{thread, time::Instant}; -use ibc_relayer_types::{ - core::ics24_host::identifier::ChainId, - events::IbcEvent, - Height, -}; +use ibc_relayer_types::{core::ics24_host::identifier::ChainId, events::IbcEvent, Height}; use itertools::Itertools; use tendermint::Hash as TxHash; -use tendermint_rpc::{ - endpoint::tx::Response as TxResponse, - HttpClient, - Url, -}; +use tendermint_rpc::{endpoint::tx::Response as TxResponse, HttpClient, Url}; use tokio::time::sleep; -use tracing::{ - debug, - debug_span, - trace, -}; +use tracing::{debug, debug_span, trace}; use crate::{ chain::cosmos::{ query::tx::query_tx_response, types::{ events::from_tx_response_event, - tx::{ - TxStatus, - TxSyncResult, - }, + tx::{TxStatus, TxSyncResult}, }, }, error::Error, diff --git a/crates/relayer/src/chain/counterparty.rs b/crates/relayer/src/chain/counterparty.rs index d13e16be0d..ffd4a42c9c 100644 --- a/crates/relayer/src/chain/counterparty.rs +++ b/crates/relayer/src/chain/counterparty.rs @@ -3,61 +3,36 @@ use std::collections::HashSet; use ibc_relayer_types::{ core::{ ics03_connection::connection::{ - ConnectionEnd, - IdentifiedConnectionEnd, - State as ConnectionState, + ConnectionEnd, IdentifiedConnectionEnd, State as ConnectionState, }, ics04_channel::{ - channel::{ - IdentifiedChannelEnd, - State, - }, + channel::{IdentifiedChannelEnd, State}, packet::Sequence, }, ics24_host::identifier::{ - ChainId, - ChannelId, - ClientId, - ConnectionId, - PortChannelId, - PortId, + ChainId, ChannelId, ClientId, ConnectionId, PortChannelId, PortId, }, }, Height, }; -use serde::{ - Deserialize, - Serialize, -}; -use tracing::{ - error, - trace, -}; +use serde::{Deserialize, Serialize}; +use tracing::{error, trace}; +use super::requests::{ + IncludeProof, PageRequest, Paginate, QueryChannelRequest, QueryClientConnectionsRequest, + QueryClientStateRequest, QueryConnectionRequest, QueryPacketAcknowledgementsRequest, + QueryUnreceivedAcksRequest, QueryUnreceivedPacketsRequest, +}; use super::{ handle::ChainHandle, - requests::{ - IncludeProof, - PageRequest, - QueryChannelRequest, - QueryClientConnectionsRequest, - QueryClientStateRequest, - QueryConnectionChannelsRequest, - QueryConnectionRequest, - QueryPacketAcknowledgementsRequest, - QueryPacketCommitmentsRequest, - QueryUnreceivedAcksRequest, - QueryUnreceivedPacketsRequest, - }, -}; -use crate::{ - chain::requests::QueryHeight, - channel::ChannelError, - client_state::IdentifiedAnyClientState, - path::PathIdentifiers, - supervisor::Error, - telemetry, + requests::{QueryConnectionChannelsRequest, QueryPacketCommitmentsRequest}, }; +use crate::chain::requests::QueryHeight; +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, @@ -192,7 +167,7 @@ pub fn channel_connection_client_no_checks( channel_id: channel_id.clone(), height: QueryHeight::Latest, }, - IncludeProof::No, + IncludeProof::Yes, ) .map_err(Error::relayer)?; @@ -320,7 +295,11 @@ pub fn channel_on_destination( channel_id: remote_channel_id.clone(), height: QueryHeight::Latest, }, - IncludeProof::No, + // IncludeProof::Yes forces a new query when the CachingChainHandle + // is used. + // TODO: Pass the BaseChainHandle instead of the CachingChainHandle + // to the channel worker to avoid querying for a Proof . + IncludeProof::Yes, ) .map(|(c, _)| IdentifiedChannelEnd { port_id: channel.channel_end.counterparty().port_id().clone(), @@ -402,13 +381,14 @@ pub fn commitments_on_chain( chain: &impl ChainHandle, port_id: &PortId, channel_id: &ChannelId, + paginate: Paginate, ) -> Result<(Vec, Height), Error> { // get the packet commitments on the counterparty/ source chain let (mut commit_sequences, response_height) = chain .query_packet_commitments(QueryPacketCommitmentsRequest { port_id: port_id.clone(), channel_id: channel_id.clone(), - pagination: Some(PageRequest::all()), + pagination: paginate, }) .map_err(Error::relayer)?; @@ -445,6 +425,7 @@ pub fn packet_acknowledgements( port_id: &PortId, channel_id: &ChannelId, commit_sequences: Vec, + pagination: Paginate, ) -> Result, Height)>, Error> { // If there aren't any sequences to query for, return early. // Otherwise we end up with the full list of acknowledgements on chain, @@ -460,7 +441,7 @@ pub fn packet_acknowledgements( .query_packet_acknowledgements(QueryPacketAcknowledgementsRequest { port_id: port_id.clone(), channel_id: channel_id.clone(), - pagination: Some(PageRequest::all()), + pagination, packet_commitment_sequences: commit_sequences, }) .map_err(Error::relayer)?; @@ -521,11 +502,13 @@ pub fn unreceived_packets( chain: &impl ChainHandle, counterparty_chain: &impl ChainHandle, path: &PathIdentifiers, + paginate: Paginate, ) -> Result<(Vec, Height), Error> { let (commit_sequences, h) = commitments_on_chain( counterparty_chain, &path.counterparty_port_id, &path.counterparty_channel_id, + paginate, )?; telemetry!( @@ -562,6 +545,7 @@ pub fn acknowledgements_on_chain( counterparty_chain, &counterparty.port_id, counterparty_channel_id, + Paginate::All, )?; let sequences_and_height = packet_acknowledgements( @@ -569,6 +553,7 @@ pub fn acknowledgements_on_chain( &channel.port_id, &channel.channel_id, commitments_on_counterparty, + Paginate::All, )?; Ok(sequences_and_height) @@ -607,14 +592,17 @@ pub fn unreceived_acknowledgements( chain: &impl ChainHandle, counterparty_chain: &impl ChainHandle, path: &PathIdentifiers, + pagination: Paginate, ) -> Result, Height)>, Error> { - let (commitments_on_src, _) = commitments_on_chain(chain, &path.port_id, &path.channel_id)?; + let (commitments_on_src, _) = + commitments_on_chain(chain, &path.port_id, &path.channel_id, pagination)?; let acks_and_height_on_counterparty = packet_acknowledgements( counterparty_chain, &path.counterparty_port_id, &path.counterparty_channel_id, commitments_on_src, + pagination, )?; if let Some((acks_on_counterparty, height)) = acks_and_height_on_counterparty { @@ -646,6 +634,7 @@ pub fn pending_packet_summary( chain: &impl ChainHandle, counterparty_chain: &impl ChainHandle, channel: &IdentifiedChannelEnd, + pagination: Paginate, ) -> Result { let counterparty = channel.channel_end.counterparty(); let counterparty_channel_id = counterparty @@ -654,7 +643,7 @@ pub fn pending_packet_summary( .ok_or_else(Error::missing_counterparty_channel_id)?; let (commitments_on_src, _) = - commitments_on_chain(chain, &channel.port_id, &channel.channel_id)?; + commitments_on_chain(chain, &channel.port_id, &channel.channel_id, pagination)?; let unreceived = unreceived_packets_sequences( counterparty_chain, @@ -668,6 +657,7 @@ pub fn pending_packet_summary( &counterparty.port_id, counterparty_channel_id, commitments_on_src, + Paginate::All, )?; let pending_acks = if let Some((acks_on_counterparty, _)) = acks_on_counterparty { diff --git a/crates/relayer/src/chain/endpoint.rs b/crates/relayer/src/chain/endpoint.rs index 7a2a83498a..fae5dbac6b 100644 --- a/crates/relayer/src/chain/endpoint.rs +++ b/crates/relayer/src/chain/endpoint.rs @@ -1,95 +1,53 @@ use alloc::sync::Arc; -use core::convert::TryFrom; + +use ibc_proto::ibc::core::channel::v1::{QueryUpgradeErrorRequest, QueryUpgradeRequest}; +use ibc_relayer_types::core::ics02_client::height::Height; +use tokio::runtime::Runtime as TokioRuntime; use ibc_proto::ibc::apps::fee::v1::{ - QueryIncentivizedPacketRequest, - QueryIncentivizedPacketResponse, + QueryIncentivizedPacketRequest, QueryIncentivizedPacketResponse, }; -use ibc_relayer_types::{ - applications::ics31_icq::response::CrossChainQueryResponse, - core::{ - ics02_client::{ - client_state::ClientState, - consensus_state::ConsensusState, - events::UpdateClient, - header::{ - AnyHeader, - Header, - }, - }, - ics03_connection::{ - connection::{ - ConnectionEnd, - IdentifiedConnectionEnd, - State, - }, - version::{ - get_compatible_versions, - Version, - }, - }, - ics04_channel::{ - channel::{ - ChannelEnd, - IdentifiedChannelEnd, - }, - packet::{ - PacketMsgType, - Sequence, - }, - }, - ics23_commitment::{ - commitment::{ - CommitmentPrefix, - CommitmentProofBytes, - }, - merkle::MerkleProof, - }, - ics24_host::identifier::{ - ChainId, - ChannelId, - ClientId, - ConnectionId, - PortId, - }, - }, - proofs::{ - ConsensusProof, - Proofs, - }, - signer::Signer, - timestamp::Timestamp, - Height as ICSHeight, +use ibc_relayer_types::applications::ics31_icq::response::CrossChainQueryResponse; +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::{AnyHeader, Header}; +use ibc_relayer_types::core::ics03_connection::connection::{ + ConnectionEnd, IdentifiedConnectionEnd, State, +}; +use ibc_relayer_types::core::ics03_connection::version::{get_compatible_versions, Version}; +use ibc_relayer_types::core::ics04_channel::channel::{ChannelEnd, IdentifiedChannelEnd}; +use ibc_relayer_types::core::ics04_channel::packet::{PacketMsgType, Sequence}; +use ibc_relayer_types::core::ics04_channel::upgrade::{ErrorReceipt, Upgrade}; +use ibc_relayer_types::core::ics23_commitment::commitment::{ + CommitmentPrefix, CommitmentProofBytes, +}; +use ibc_relayer_types::core::ics23_commitment::merkle::MerkleProof; +use ibc_relayer_types::core::ics24_host::identifier::{ + ChainId, ChannelId, ClientId, ConnectionId, PortId, }; +use ibc_relayer_types::proofs::{ConsensusProof, Proofs}; +use ibc_relayer_types::signer::Signer; +use ibc_relayer_types::timestamp::Timestamp; +use ibc_relayer_types::Height as ICSHeight; + use tendermint_rpc::endpoint::broadcast::tx_sync::Response as TxResponse; -use tokio::runtime::Runtime as TokioRuntime; -use crate::{ - account::Balance, - chain::{ - client::ClientSettings, - cosmos::version::Specs, - handle::Subscription, - requests::*, - tracking::TrackedMsgs, - }, - client_state::{ - AnyClientState, - IdentifiedAnyClientState, - }, - config::ChainConfig, - connection::ConnectionMsgType, - consensus_state::AnyConsensusState, - denom::DenomTrace, - error::Error, - event::IbcEventWithHeight, - keyring::{ - AnySigningKeyPair, - KeyRing, - SigningKeyPairSized, - }, - misbehaviour::MisbehaviourEvidence, -}; +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; +use crate::client_state::{AnyClientState, IdentifiedAnyClientState}; +use crate::config::ChainConfig; +use crate::connection::ConnectionMsgType; +use crate::consensus_state::AnyConsensusState; +use crate::denom::DenomTrace; +use crate::error::Error; +use crate::event::IbcEventWithHeight; +use crate::keyring::{AnySigningKeyPair, KeyRing, SigningKeyPairSized}; +use crate::misbehaviour::MisbehaviourEvidence; /// The result of a health check. #[derive(Debug)] @@ -731,4 +689,18 @@ pub trait ChainEndpoint: Sized { ) -> Result; fn query_consumer_chains(&self) -> Result, Error>; + + fn query_upgrade( + &self, + request: QueryUpgradeRequest, + height: Height, + include_proof: IncludeProof, + ) -> Result<(Upgrade, Option), Error>; + + fn query_upgrade_error( + &self, + request: QueryUpgradeErrorRequest, + height: Height, + include_proof: IncludeProof, + ) -> Result<(ErrorReceipt, Option), Error>; } diff --git a/crates/relayer/src/chain/handle.rs b/crates/relayer/src/chain/handle.rs index 5e4bf0946a..5a38acacbf 100644 --- a/crates/relayer/src/chain/handle.rs +++ b/crates/relayer/src/chain/handle.rs @@ -1,50 +1,26 @@ use alloc::sync::Arc; -use core::fmt::{ - self, - Debug, - Display, -}; +use core::fmt::{self, Debug, Display}; use crossbeam_channel as channel; use ibc_proto::ibc::apps::fee::v1::{ - QueryIncentivizedPacketRequest, - QueryIncentivizedPacketResponse, + QueryIncentivizedPacketRequest, QueryIncentivizedPacketResponse, }; +use ibc_proto::ibc::core::channel::v1::{QueryUpgradeErrorRequest, QueryUpgradeRequest}; use ibc_relayer_types::{ applications::ics31_icq::response::CrossChainQueryResponse, core::{ - ics02_client::{ - events::UpdateClient, - header::AnyHeader, - }, + ics02_client::{events::UpdateClient, header::AnyHeader}, ics03_connection::{ - connection::{ - ConnectionEnd, - IdentifiedConnectionEnd, - }, + connection::{ConnectionEnd, IdentifiedConnectionEnd}, version::Version, }, ics04_channel::{ - channel::{ - ChannelEnd, - IdentifiedChannelEnd, - }, - packet::{ - PacketMsgType, - Sequence, - }, - }, - ics23_commitment::{ - commitment::CommitmentPrefix, - merkle::MerkleProof, - }, - ics24_host::identifier::{ - ChainId, - ChannelId, - ClientId, - ConnectionId, - PortId, + channel::{ChannelEnd, IdentifiedChannelEnd}, + packet::{PacketMsgType, Sequence}, + upgrade::{ErrorReceipt, Upgrade}, }, + ics23_commitment::{commitment::CommitmentPrefix, merkle::MerkleProof}, + ics24_host::identifier::{ChainId, ChannelId, ClientId, ConnectionId, PortId}, }, proofs::Proofs, signer::Signer, @@ -55,29 +31,20 @@ use tracing::Span; use super::{ client::ClientSettings, cosmos::version::Specs, - endpoint::{ - ChainStatus, - HealthCheck, - }, + endpoint::{ChainStatus, HealthCheck}, requests::*, tracking::TrackedMsgs, }; use crate::{ account::Balance, - client_state::{ - AnyClientState, - IdentifiedAnyClientState, - }, + client_state::{AnyClientState, IdentifiedAnyClientState}, config::ChainConfig, connection::ConnectionMsgType, consensus_state::AnyConsensusState, denom::DenomTrace, error::Error, event::{ - source::{ - EventBatch, - Result as MonitorResult, - }, + source::{EventBatch, Result as MonitorResult}, IbcEventWithHeight, }, keyring::AnySigningKeyPair, @@ -404,6 +371,20 @@ pub enum ChainRequest { QueryConsumerChains { reply_to: ReplyTo>, }, + + QueryUpgrade { + request: QueryUpgradeRequest, + height: Height, + include_proof: IncludeProof, + reply_to: ReplyTo<(Upgrade, Option)>, + }, + + QueryUpgradeError { + request: QueryUpgradeErrorRequest, + height: Height, + include_proof: IncludeProof, + reply_to: ReplyTo<(ErrorReceipt, Option)>, + }, } pub trait ChainHandle: Clone + Display + Send + Sync + Debug + 'static { @@ -717,4 +698,18 @@ pub trait ChainHandle: Clone + Display + Send + Sync + Debug + 'static { ) -> Result; fn query_consumer_chains(&self) -> Result, Error>; + + fn query_upgrade( + &self, + request: QueryUpgradeRequest, + height: Height, + include_proof: IncludeProof, + ) -> Result<(Upgrade, Option), Error>; + + fn query_upgrade_error( + &self, + request: QueryUpgradeErrorRequest, + height: Height, + include_proof: IncludeProof, + ) -> Result<(ErrorReceipt, Option), Error>; } diff --git a/crates/relayer/src/chain/handle/base.rs b/crates/relayer/src/chain/handle/base.rs index ef9d171617..5312e8a23a 100644 --- a/crates/relayer/src/chain/handle/base.rs +++ b/crates/relayer/src/chain/handle/base.rs @@ -1,78 +1,39 @@ -use core::fmt::{ - Debug, - Display, - Error as FmtError, - Formatter, -}; +use core::fmt::{Debug, Display, Error as FmtError, Formatter}; use crossbeam_channel as channel; -use ibc_proto::ibc::apps::fee::v1::{ - QueryIncentivizedPacketRequest, - QueryIncentivizedPacketResponse, +use tracing::Span; + +use ibc_proto::ibc::{ + apps::fee::v1::{QueryIncentivizedPacketRequest, QueryIncentivizedPacketResponse}, + core::channel::v1::{QueryUpgradeErrorRequest, QueryUpgradeRequest}, }; use ibc_relayer_types::{ applications::ics31_icq::response::CrossChainQueryResponse, core::{ - ics02_client::{ - events::UpdateClient, - header::AnyHeader, - }, - ics03_connection::{ - connection::{ - ConnectionEnd, - IdentifiedConnectionEnd, - }, - version::Version, - }, + ics02_client::{events::UpdateClient, header::AnyHeader}, + ics03_connection::connection::{ConnectionEnd, IdentifiedConnectionEnd}, + ics03_connection::version::Version, + ics04_channel::channel::{ChannelEnd, IdentifiedChannelEnd}, ics04_channel::{ - channel::{ - ChannelEnd, - IdentifiedChannelEnd, - }, - packet::{ - PacketMsgType, - Sequence, - }, - }, - ics23_commitment::{ - commitment::CommitmentPrefix, - merkle::MerkleProof, - }, - ics24_host::identifier::{ - ChainId, - ChannelId, - ClientId, - ConnectionId, - PortId, + packet::{PacketMsgType, Sequence}, + upgrade::{ErrorReceipt, Upgrade}, }, + ics23_commitment::{commitment::CommitmentPrefix, merkle::MerkleProof}, + ics24_host::identifier::{ChainId, ChannelId, ClientId, ConnectionId, PortId}, }, proofs::Proofs, signer::Signer, Height, }; -use tracing::Span; -use super::{ - reply_channel, - ChainHandle, - ChainRequest, - HealthCheck, - ReplyTo, - Subscription, -}; +use super::{reply_channel, ChainHandle, ChainRequest, HealthCheck, ReplyTo, Subscription}; use crate::{ account::Balance, chain::{ - client::ClientSettings, - cosmos::version::Specs, - endpoint::ChainStatus, - requests::*, + client::ClientSettings, cosmos::version::Specs, endpoint::ChainStatus, requests::*, tracking::TrackedMsgs, }, - client_state::{ - AnyClientState, - IdentifiedAnyClientState, - }, + client_state::{AnyClientState, IdentifiedAnyClientState}, config::ChainConfig, connection::ConnectionMsgType, consensus_state::AnyConsensusState, @@ -561,4 +522,32 @@ impl ChainHandle for BaseChainHandle { fn query_consumer_chains(&self) -> Result, Error> { self.send(|reply_to| ChainRequest::QueryConsumerChains { reply_to }) } + + fn query_upgrade( + &self, + request: QueryUpgradeRequest, + height: Height, + include_proof: IncludeProof, + ) -> Result<(Upgrade, Option), Error> { + self.send(|reply_to| ChainRequest::QueryUpgrade { + request, + height, + include_proof, + reply_to, + }) + } + + fn query_upgrade_error( + &self, + request: QueryUpgradeErrorRequest, + height: Height, + include_proof: IncludeProof, + ) -> Result<(ErrorReceipt, Option), Error> { + self.send(|reply_to| ChainRequest::QueryUpgradeError { + request, + height, + include_proof, + reply_to, + }) + } } diff --git a/crates/relayer/src/chain/handle/cache.rs b/crates/relayer/src/chain/handle/cache.rs index e6002537bb..6a1731f903 100644 --- a/crates/relayer/src/chain/handle/cache.rs +++ b/crates/relayer/src/chain/handle/cache.rs @@ -1,92 +1,48 @@ -use core::fmt::{ - Display, - Error as FmtError, - Formatter, -}; - +use core::fmt::{Display, Error as FmtError, Formatter}; use crossbeam_channel as channel; -use ibc_proto::ibc::apps::fee::v1::{ - QueryIncentivizedPacketRequest, - QueryIncentivizedPacketResponse, -}; -use ibc_relayer_types::{ - applications::ics31_icq::response::CrossChainQueryResponse, - core::{ - ics02_client::{ - events::UpdateClient, - header::AnyHeader, - }, - ics03_connection::{ - connection::{ - ConnectionEnd, - IdentifiedConnectionEnd, - }, - version::Version, - }, - ics04_channel::{ - channel::{ - ChannelEnd, - IdentifiedChannelEnd, - }, - packet::{ - PacketMsgType, - Sequence, - }, - }, - ics23_commitment::{ - commitment::CommitmentPrefix, - merkle::MerkleProof, - }, - ics24_host::identifier::{ - ChainId, - ChannelId, - ClientId, - ConnectionId, - PortChannelId, - PortId, - }, - }, - proofs::Proofs, - signer::Signer, - Height, -}; +use ibc_relayer_types::core::ics02_client::header::AnyHeader; +use ibc_relayer_types::core::ics04_channel::upgrade::ErrorReceipt; use tracing::Span; -use crate::{ - account::Balance, - cache::{ - Cache, - CacheStatus, - }, - chain::{ - client::ClientSettings, - cosmos::version::Specs, - endpoint::{ - ChainStatus, - HealthCheck, - }, - handle::{ - ChainHandle, - ChainRequest, - Subscription, - }, - requests::*, - tracking::TrackedMsgs, - }, - client_state::{ - AnyClientState, - IdentifiedAnyClientState, - }, - config::ChainConfig, - connection::ConnectionMsgType, - consensus_state::AnyConsensusState, - denom::DenomTrace, - error::Error, - event::IbcEventWithHeight, - keyring::AnySigningKeyPair, - misbehaviour::MisbehaviourEvidence, - telemetry, +use ibc_proto::ibc::apps::fee::v1::QueryIncentivizedPacketRequest; +use ibc_proto::ibc::apps::fee::v1::QueryIncentivizedPacketResponse; +use ibc_proto::ibc::core::channel::v1::{QueryUpgradeErrorRequest, QueryUpgradeRequest}; +use ibc_relayer_types::applications::ics31_icq::response::CrossChainQueryResponse; +use ibc_relayer_types::core::ics02_client::events::UpdateClient; +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; +use ibc_relayer_types::core::ics04_channel::channel::ChannelEnd; +use ibc_relayer_types::core::ics04_channel::channel::IdentifiedChannelEnd; +use ibc_relayer_types::core::ics04_channel::packet::{PacketMsgType, Sequence}; +use ibc_relayer_types::core::ics04_channel::upgrade::Upgrade; +use ibc_relayer_types::core::ics23_commitment::commitment::CommitmentPrefix; +use ibc_relayer_types::core::ics23_commitment::merkle::MerkleProof; +use ibc_relayer_types::core::ics24_host::identifier::{ + ChainId, ChannelId, ClientId, ConnectionId, PortChannelId, PortId, }; +use ibc_relayer_types::proofs::Proofs; +use ibc_relayer_types::signer::Signer; +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::*; +use crate::chain::tracking::TrackedMsgs; +use crate::client_state::{AnyClientState, IdentifiedAnyClientState}; +use crate::config::ChainConfig; +use crate::connection::ConnectionMsgType; +use crate::consensus_state::AnyConsensusState; +use crate::denom::DenomTrace; +use crate::error::Error; +use crate::event::IbcEventWithHeight; +use crate::keyring::AnySigningKeyPair; +use crate::misbehaviour::MisbehaviourEvidence; +use crate::telemetry; /// A chain handle with support for caching. /// To be used for the passive relaying mode (i.e., `start` CLI). @@ -562,4 +518,23 @@ impl ChainHandle for CachingChainHandle { fn query_consumer_chains(&self) -> Result, Error> { self.inner.query_consumer_chains() } + + fn query_upgrade( + &self, + request: QueryUpgradeRequest, + height: Height, + include_proof: IncludeProof, + ) -> Result<(Upgrade, Option), Error> { + self.inner.query_upgrade(request, height, include_proof) + } + + fn query_upgrade_error( + &self, + request: QueryUpgradeErrorRequest, + height: Height, + include_proof: IncludeProof, + ) -> Result<(ErrorReceipt, Option), Error> { + self.inner + .query_upgrade_error(request, height, include_proof) + } } diff --git a/crates/relayer/src/chain/handle/counting.rs b/crates/relayer/src/chain/handle/counting.rs index 9b833eb4af..7cad47d64e 100644 --- a/crates/relayer/src/chain/handle/counting.rs +++ b/crates/relayer/src/chain/handle/counting.rs @@ -1,88 +1,48 @@ -use core::fmt::{ - Display, - Error as FmtError, - Formatter, -}; +use core::fmt::{Display, Error as FmtError, Formatter}; use std::{ collections::HashMap, - sync::{ - Arc, - RwLock, - RwLockReadGuard, - }, + sync::{Arc, RwLock, RwLockReadGuard}, }; use crossbeam_channel as channel; +use ibc_proto::ibc::core::channel::v1::{QueryUpgradeErrorRequest, QueryUpgradeRequest}; +use ibc_relayer_types::core::ics04_channel::upgrade::{ErrorReceipt, Upgrade}; +use tracing::{debug, Span}; + use ibc_proto::ibc::apps::fee::v1::{ - QueryIncentivizedPacketRequest, - QueryIncentivizedPacketResponse, + QueryIncentivizedPacketRequest, QueryIncentivizedPacketResponse, }; use ibc_relayer_types::{ applications::ics31_icq::response::CrossChainQueryResponse, core::{ - ics02_client::{ - events::UpdateClient, - header::AnyHeader, - }, + ics02_client::{events::UpdateClient, header::AnyHeader}, ics03_connection::{ - connection::{ - ConnectionEnd, - IdentifiedConnectionEnd, - }, + connection::{ConnectionEnd, IdentifiedConnectionEnd}, version::Version, }, ics04_channel::{ - channel::{ - ChannelEnd, - IdentifiedChannelEnd, - }, - packet::{ - PacketMsgType, - Sequence, - }, - }, - ics23_commitment::{ - commitment::CommitmentPrefix, - merkle::MerkleProof, - }, - ics24_host::identifier::{ - ChainId, - ChannelId, - ClientId, - ConnectionId, - PortId, + channel::{ChannelEnd, IdentifiedChannelEnd}, + packet::{PacketMsgType, Sequence}, }, + ics23_commitment::{commitment::CommitmentPrefix, merkle::MerkleProof}, + ics24_host::identifier::{ChainId, ChannelId, ClientId, ConnectionId, PortId}, }, proofs::Proofs, signer::Signer, Height, }; -use tracing::{ - debug, - Span, -}; use crate::{ account::Balance, chain::{ client::ClientSettings, cosmos::version::Specs, - endpoint::{ - ChainStatus, - HealthCheck, - }, - handle::{ - ChainHandle, - ChainRequest, - Subscription, - }, + endpoint::{ChainStatus, HealthCheck}, + handle::{ChainHandle, ChainRequest, Subscription}, requests::*, tracking::TrackedMsgs, }, - client_state::{ - AnyClientState, - IdentifiedAnyClientState, - }, + client_state::{AnyClientState, IdentifiedAnyClientState}, config::ChainConfig, connection::ConnectionMsgType, consensus_state::AnyConsensusState, @@ -559,4 +519,25 @@ impl ChainHandle for CountingChainHandle { self.inc_metric("query_consumer_chains"); self.inner.query_consumer_chains() } + + fn query_upgrade( + &self, + request: QueryUpgradeRequest, + height: Height, + include_proof: IncludeProof, + ) -> Result<(Upgrade, Option), Error> { + self.inc_metric("query_upgrade"); + self.inner.query_upgrade(request, height, include_proof) + } + + fn query_upgrade_error( + &self, + request: QueryUpgradeErrorRequest, + height: Height, + include_proof: IncludeProof, + ) -> Result<(ErrorReceipt, Option), Error> { + self.inc_metric("query_upgrade_error"); + self.inner + .query_upgrade_error(request, height, include_proof) + } } diff --git a/crates/relayer/src/chain/requests.rs b/crates/relayer/src/chain/requests.rs index 29a6d6f186..fcb1f985d8 100644 --- a/crates/relayer/src/chain/requests.rs +++ b/crates/relayer/src/chain/requests.rs @@ -1,7 +1,4 @@ -use core::fmt::{ - self, - Display, -}; +use core::fmt::{self, Display}; use ibc_proto::{ cosmos::base::query::v1beta1::PageRequest as RawPageRequest, @@ -30,25 +27,13 @@ use ibc_proto::{ use ibc_relayer_types::{ core::{ ics04_channel::packet::Sequence, - ics24_host::identifier::{ - ChainId, - ChannelId, - ClientId, - ConnectionId, - PortId, - }, + ics24_host::identifier::{ChainId, ChannelId, ClientId, ConnectionId, PortId}, }, events::WithBlockDataType, Height, }; -use serde::{ - Deserialize, - Serialize, -}; -use tendermint::{ - block::Height as TMBlockHeight, - Hash as TxHash, -}; +use serde::{Deserialize, Serialize}; +use tendermint::{block::Height as TMBlockHeight, Hash as TxHash}; use tonic::metadata::AsciiMetadataValue; use crate::error::Error; @@ -85,7 +70,7 @@ impl TryFrom for AsciiMetadataValue { } impl Display for QueryHeight { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { QueryHeight::Latest => write!(f, "latest height"), QueryHeight::Specific(height) => write!(f, "{height}"), @@ -112,7 +97,7 @@ pub struct PageRequest { /// key is a value returned in PageResponse.next_key to begin /// querying the next page most efficiently. Only one of offset or key /// should be set. - pub key: ::prost::alloc::vec::Vec, + pub key: Vec, /// offset is a numeric offset that can be used when key is unavailable. /// It is less efficient than using key. Only one of offset or key should /// be set. @@ -134,8 +119,12 @@ impl PageRequest { // Note: do not use u64::MAX as the limit, as it may have unintended consequences // See https://github.com/informalsystems/hermes/pull/2950#issuecomment-1373733744 + Self::per_page(u32::MAX as u64) + } + + pub fn per_page(limit: u64) -> Self { PageRequest { - limit: u32::MAX as u64, + limit, ..Default::default() } } @@ -153,6 +142,39 @@ impl From for RawPageRequest { } } +#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] +pub enum Paginate { + #[default] + All, + + PerPage { + per_page: u64, + total: u64, + }, +} + +impl Paginate { + pub fn is_enabled(&self) -> bool { + !matches!(self, Self::All) + } + + pub fn get_values(&self) -> (u64, u64) { + match self { + Paginate::PerPage { total, per_page } => (*per_page, *total), + _ => (0, 0), + } + } +} + +impl From for PageRequest { + fn from(value: Paginate) -> Self { + match value { + Paginate::All => PageRequest::all(), + Paginate::PerPage { per_page, .. } => PageRequest::per_page(per_page), + } + } +} + #[derive(Clone, Debug, Serialize, Deserialize)] pub struct QueryClientStateRequest { pub client_id: ClientId, @@ -322,7 +344,7 @@ pub struct QueryPacketCommitmentRequest { pub struct QueryPacketCommitmentsRequest { pub port_id: PortId, pub channel_id: ChannelId, - pub pagination: Option, + pub pagination: Paginate, } impl From for RawQueryPacketCommitmentsRequest { @@ -330,7 +352,7 @@ impl From for RawQueryPacketCommitmentsRequest { RawQueryPacketCommitmentsRequest { port_id: request.port_id.to_string(), channel_id: request.channel_id.to_string(), - pagination: request.pagination.map(|pagination| pagination.into()), + pagination: Some(PageRequest::from(request.pagination).into()), } } } @@ -378,7 +400,7 @@ pub struct QueryPacketAcknowledgementRequest { pub struct QueryPacketAcknowledgementsRequest { pub port_id: PortId, pub channel_id: ChannelId, - pub pagination: Option, + pub pagination: Paginate, pub packet_commitment_sequences: Vec, } @@ -387,7 +409,7 @@ impl From for RawQueryPacketAcknowledgements RawQueryPacketAcknowledgementsRequest { port_id: request.port_id.to_string(), channel_id: request.channel_id.to_string(), - pagination: request.pagination.map(|pagination| pagination.into()), + pagination: Some(PageRequest::from(request.pagination).into()), packet_commitment_sequences: request .packet_commitment_sequences .into_iter() diff --git a/crates/relayer/src/chain/runtime.rs b/crates/relayer/src/chain/runtime.rs index f59a2db3c4..ff54415ad0 100644 --- a/crates/relayer/src/chain/runtime.rs +++ b/crates/relayer/src/chain/runtime.rs @@ -2,80 +2,45 @@ use alloc::sync::Arc; use std::thread; use crossbeam_channel as channel; -use ibc_proto::ibc::apps::fee::v1::{ - QueryIncentivizedPacketRequest, - QueryIncentivizedPacketResponse, +use tokio::runtime::Runtime as TokioRuntime; +use tracing::{error, Span}; + +use ibc_proto::ibc::{ + apps::fee::v1::{QueryIncentivizedPacketRequest, QueryIncentivizedPacketResponse}, + core::channel::v1::{QueryUpgradeErrorRequest, QueryUpgradeRequest}, }; use ibc_relayer_types::{ applications::ics31_icq::response::CrossChainQueryResponse, core::{ - ics02_client::{ - events::UpdateClient, - header::AnyHeader, - }, + ics02_client::{events::UpdateClient, header::AnyHeader}, ics03_connection::{ - connection::{ - ConnectionEnd, - IdentifiedConnectionEnd, - }, + connection::{ConnectionEnd, IdentifiedConnectionEnd}, version::Version, }, ics04_channel::{ - channel::{ - ChannelEnd, - IdentifiedChannelEnd, - }, - packet::{ - PacketMsgType, - Sequence, - }, - }, - ics23_commitment::{ - commitment::CommitmentPrefix, - merkle::MerkleProof, - }, - ics24_host::identifier::{ - ChainId, - ChannelId, - ClientId, - ConnectionId, - PortId, + channel::{ChannelEnd, IdentifiedChannelEnd}, + packet::{PacketMsgType, Sequence}, + upgrade::{ErrorReceipt, Upgrade}, }, + ics23_commitment::{commitment::CommitmentPrefix, merkle::MerkleProof}, + ics24_host::identifier::{ChainId, ChannelId, ClientId, ConnectionId, PortId}, }, proofs::Proofs, signer::Signer, Height, }; -use tokio::runtime::Runtime as TokioRuntime; -use tracing::{ - error, - Span, -}; use super::{ client::ClientSettings, cosmos::version::Specs, - endpoint::{ - ChainEndpoint, - ChainStatus, - HealthCheck, - }, - handle::{ - ChainHandle, - ChainRequest, - ReplyTo, - Subscription, - }, + endpoint::{ChainEndpoint, ChainStatus, HealthCheck}, + handle::{ChainHandle, ChainRequest, ReplyTo, Subscription}, requests::*, tracking::TrackedMsgs, }; use crate::{ account::Balance, - chain::requests::QueryPacketEventDataRequest, - client_state::{ - AnyClientState, - IdentifiedAnyClientState, - }, + client_state::{AnyClientState, IdentifiedAnyClientState}, config::ChainConfig, connection::ConnectionMsgType, consensus_state::AnyConsensusState, @@ -388,6 +353,14 @@ where ChainRequest::QueryConsumerChains { reply_to } => { self.query_consumer_chains(reply_to)? }, + + ChainRequest::QueryUpgrade { request, height, include_proof, reply_to } => { + self.query_upgrade(request, height, include_proof, reply_to)? + }, + + ChainRequest::QueryUpgradeError { request, height, include_proof, reply_to } => { + self.query_upgrade_error(request, height, include_proof, reply_to)? + }, } }, } @@ -899,4 +872,32 @@ where Ok(()) } + + fn query_upgrade( + &self, + request: QueryUpgradeRequest, + height: Height, + include_proof: IncludeProof, + reply_to: ReplyTo<(Upgrade, Option)>, + ) -> Result<(), Error> { + let result = self.chain.query_upgrade(request, height, include_proof); + reply_to.send(result).map_err(Error::send)?; + + Ok(()) + } + + fn query_upgrade_error( + &self, + request: QueryUpgradeErrorRequest, + height: Height, + include_proof: IncludeProof, + reply_to: ReplyTo<(ErrorReceipt, Option)>, + ) -> Result<(), Error> { + let result = self + .chain + .query_upgrade_error(request, height, include_proof); + reply_to.send(result).map_err(Error::send)?; + + Ok(()) + } } diff --git a/crates/relayer/src/chain/tracking.rs b/crates/relayer/src/chain/tracking.rs index 526bf02d43..589ad305f2 100644 --- a/crates/relayer/src/chain/tracking.rs +++ b/crates/relayer/src/chain/tracking.rs @@ -1,8 +1,4 @@ -use core::fmt::{ - Display, - Error as FmtError, - Formatter, -}; +use core::fmt::{Display, Error as FmtError, Formatter}; use ibc_proto::google::protobuf::Any; use uuid::Uuid; @@ -19,7 +15,7 @@ pub enum TrackingId { /// the CLI or during packet clearing. Static(&'static str), /// Random identifier used to track latency of packet clearing. - ClearedUuid(Uuid), + PacketClearing(Uuid), } impl TrackingId { @@ -33,8 +29,13 @@ impl TrackingId { Self::Static(s) } - pub fn new_cleared_uuid() -> Self { - Self::ClearedUuid(Uuid::new_v4()) + pub fn new_packet_clearing() -> Self { + Self::PacketClearing(Uuid::new_v4()) + } + + /// Indicates whether a packet clearing process is currently in-progress. + pub fn is_clearing(&self) -> bool { + matches!(self, Self::PacketClearing(_)) } } @@ -47,7 +48,7 @@ impl Display for TrackingId { s.fmt(f) } TrackingId::Static(s) => s.fmt(f), - TrackingId::ClearedUuid(u) => { + TrackingId::PacketClearing(u) => { let mut uuid = "cleared/".to_owned(); let mut s = u.to_string(); s.truncate(8); diff --git a/crates/relayer/src/channel.rs b/crates/relayer/src/channel.rs index a901aabfb2..97d4335628 100644 --- a/crates/relayer/src/channel.rs +++ b/crates/relayer/src/channel.rs @@ -1,128 +1,88 @@ -use core::{ - fmt::{ - Display, - Error as FmtError, - Formatter, - }, - time::Duration, -}; +use core::fmt::{Display, Error as FmtError, Formatter}; +use core::time::Duration; -pub use error::ChannelError; use ibc_proto::google::protobuf::Any; -use ibc_relayer_types::{ - core::{ - ics04_channel::{ - channel::{ - ChannelEnd, - Counterparty, - IdentifiedChannelEnd, - Ordering, - State, - }, - msgs::{ - chan_close_confirm::MsgChannelCloseConfirm, - chan_close_init::MsgChannelCloseInit, - chan_open_ack::MsgChannelOpenAck, - chan_open_confirm::MsgChannelOpenConfirm, - chan_open_init::MsgChannelOpenInit, - chan_open_try::MsgChannelOpenTry, - }, - }, - ics24_host::identifier::{ - ChainId, - ChannelId, - ClientId, - ConnectionId, - PortId, - }, - }, - events::IbcEvent, - tx_msg::Msg, - Height, -}; use serde::Serialize; -use tracing::{ - debug, - error, - info, - warn, +use tracing::{debug, error, info, warn}; + +use ibc_proto::ibc::core::channel::v1::{QueryUpgradeErrorRequest, QueryUpgradeRequest}; +use ibc_relayer_types::core::ics04_channel::msgs::chan_upgrade_ack::MsgChannelUpgradeAck; +use ibc_relayer_types::core::ics04_channel::msgs::chan_upgrade_cancel::MsgChannelUpgradeCancel; +use ibc_relayer_types::core::ics04_channel::msgs::chan_upgrade_confirm::MsgChannelUpgradeConfirm; +use ibc_relayer_types::core::ics04_channel::msgs::chan_upgrade_open::MsgChannelUpgradeOpen; +use ibc_relayer_types::core::ics04_channel::msgs::chan_upgrade_timeout::MsgChannelUpgradeTimeout; +use ibc_relayer_types::core::ics04_channel::packet::Sequence; + +use ibc_relayer_types::core::ics04_channel::channel::{ + ChannelEnd, Counterparty, IdentifiedChannelEnd, Ordering, State, UpgradeState, }; - -use crate::{ - chain::{ - counterparty::{ - channel_connection_client, - channel_state_on_destination, - }, - handle::ChainHandle, - requests::{ - IncludeProof, - PageRequest, - QueryChannelRequest, - QueryConnectionChannelsRequest, - QueryConnectionRequest, - QueryHeight, - }, - tracking::TrackedMsgs, - }, - connection::Connection, - foreign_client::{ - ForeignClient, - HasExpiredOrFrozenError, - }, - object::Channel as WorkerChannelObject, - supervisor::error::Error as SupervisorError, - util::{ - pretty::{ - PrettyDuration, - PrettyOption, - }, - retry::{ - retry_with_index, - RetryResult, - }, - task::Next, - }, +use ibc_relayer_types::core::ics04_channel::msgs::chan_close_confirm::MsgChannelCloseConfirm; +use ibc_relayer_types::core::ics04_channel::msgs::chan_close_init::MsgChannelCloseInit; +use ibc_relayer_types::core::ics04_channel::msgs::chan_open_ack::MsgChannelOpenAck; +use ibc_relayer_types::core::ics04_channel::msgs::chan_open_confirm::MsgChannelOpenConfirm; +use ibc_relayer_types::core::ics04_channel::msgs::chan_open_init::MsgChannelOpenInit; +use ibc_relayer_types::core::ics04_channel::msgs::chan_open_try::MsgChannelOpenTry; +use ibc_relayer_types::core::ics04_channel::msgs::chan_upgrade_try::MsgChannelUpgradeTry; +use ibc_relayer_types::core::ics23_commitment::commitment::CommitmentProofBytes; +use ibc_relayer_types::core::ics24_host::identifier::{ + ChainId, ChannelId, ClientId, ConnectionId, PortId, }; +use ibc_relayer_types::events::IbcEvent; +use ibc_relayer_types::tx_msg::Msg; +use ibc_relayer_types::Height; + +use crate::chain::counterparty::{channel_connection_client, channel_state_on_destination}; +use crate::chain::handle::ChainHandle; +use crate::chain::requests::{ + IncludeProof, PageRequest, QueryChannelRequest, QueryConnectionChannelsRequest, + QueryConnectionRequest, QueryHeight, +}; +use crate::chain::tracking::TrackedMsgs; +use crate::connection::Connection; +use crate::foreign_client::{ForeignClient, HasExpiredOrFrozenError}; +use crate::object::Channel as WorkerChannelObject; +use crate::supervisor::error::Error as SupervisorError; +use crate::util::pretty::{PrettyDuration, PrettyOption}; +use crate::util::retry::retry_with_index; +use crate::util::retry::RetryResult; +use crate::util::task::Next; -pub mod error; pub mod version; use version::Version; +pub mod error; +pub use error::ChannelError; + pub mod channel_handshake_retry { //! Provides utility methods and constants to configure the retry behavior //! for the channel handshake algorithm. + use crate::channel::ChannelError; + use crate::util::retry::{clamp, ConstantGrowth}; use core::time::Duration; - use crate::{ - channel::ChannelError, - util::retry::{ - clamp_total, - ConstantGrowth, - }, - }; + use crate::util::retry::clamp_total; /// Approximate number of retries per block. - const PER_BLOCK_RETRIES: u32 = 10; + const PER_BLOCK_RETRIES: u32 = 5; /// Defines the increment in delay between subsequent retries. /// A value of `0` will make the retry delay constant. - const DELAY_INCREMENT: u64 = 0; + const DELAY_INCREMENT: Duration = Duration::from_secs(0); - /// Maximum retry delay expressed in number of blocks - const BLOCK_NUMBER_DELAY: u32 = 10; + /// Maximum number of retries + const MAX_RETRIES: u32 = 10; /// The default retry strategy. /// We retry with a constant backoff strategy. The strategy is parametrized by the /// maximum block time expressed as a `Duration`. - pub fn default_strategy(max_block_times: Duration) -> impl Iterator { - let retry_delay = max_block_times / PER_BLOCK_RETRIES; + pub fn default_strategy(max_block_time: Duration) -> impl Iterator { + let retry_delay = max_block_time / PER_BLOCK_RETRIES; - clamp_total( - ConstantGrowth::new(retry_delay, Duration::from_secs(DELAY_INCREMENT)), - retry_delay, - max_block_times * BLOCK_NUMBER_DELAY, + clamp( + ConstantGrowth::new(retry_delay, DELAY_INCREMENT), + retry_delay + DELAY_INCREMENT * MAX_RETRIES, + MAX_RETRIES as usize, ) } @@ -342,16 +302,20 @@ impl Channel { chain: ChainA, counterparty_chain: ChainB, channel: WorkerChannelObject, - height: Height, + height: QueryHeight, ) -> Result<(Channel, State), ChannelError> { let (a_channel, _) = chain .query_channel( QueryChannelRequest { port_id: channel.src_port_id.clone(), channel_id: channel.src_channel_id.clone(), - height: QueryHeight::Specific(height), + height, }, - IncludeProof::No, + // IncludeProof::Yes forces a new query when the CachingChainHandle + // is used. + // TODO: Pass the BaseChainHandle instead of the CachingChainHandle + // to the channel worker to avoid querying for a Proof . + IncludeProof::Yes, ) .map_err(ChannelError::relayer)?; @@ -499,7 +463,7 @@ impl Channel { channel_id: id.clone(), height: QueryHeight::Latest, }, - IncludeProof::No, + IncludeProof::Yes, ) .map(|(channel_end, _)| channel_end) .map_err(|e| ChannelError::chain_query(self.a_chain().id(), e)) @@ -663,7 +627,7 @@ impl Channel { ); match (a_state, b_state) { - // send the Init message to chain a (source) + // send the Init message to chain A (source) (State::Uninitialized, State::Uninitialized) => { let event = self .flipped() @@ -676,7 +640,7 @@ impl Channel { self.a_side.channel_id = Some(channel_id.clone()); } - // send the Try message to chain a (source) + // send the Try message to chain A (source) (State::Uninitialized, State::Init) | (State::Init, State::Init) => { let event = self.flipped().build_chan_open_try_and_send().map_err(|e| { error!("failed ChanOpenTry {}: {}", self.a_side, e); @@ -687,7 +651,7 @@ impl Channel { self.a_side.channel_id = Some(channel_id.clone()); } - // send the Try message to chain b (destination) + // send the Try message to chain B (destination) (State::Init, State::Uninitialized) => { let event = self.build_chan_open_try_and_send().map_err(|e| { error!("failed ChanOpenTry {}: {}", self.b_side, e); @@ -698,7 +662,7 @@ impl Channel { self.b_side.channel_id = Some(channel_id.clone()); } - // send the Ack message to chain a (source) + // send the Ack message to chain A (source) (State::Init, State::TryOpen) | (State::TryOpen, State::TryOpen) => { self.flipped().build_chan_open_ack_and_send().map_err(|e| { error!("failed ChanOpenAck {}: {}", self.a_side, e); @@ -706,7 +670,7 @@ impl Channel { })?; } - // send the Ack message to chain b (destination) + // send the Ack message to chain B (destination) (State::TryOpen, State::Init) => { self.build_chan_open_ack_and_send().map_err(|e| { error!("failed ChanOpenAck {}: {}", self.b_side, e); @@ -714,16 +678,16 @@ impl Channel { })?; } - // send the Confirm message to chain b (destination) - (State::Open, State::TryOpen) => { + // send the Confirm message to chain B (destination) + (State::Open(UpgradeState::NotUpgrading), State::TryOpen) => { self.build_chan_open_confirm_and_send().map_err(|e| { error!("failed ChanOpenConfirm {}: {}", self.b_side, e); e })?; } - // send the Confirm message to chain a (source) - (State::TryOpen, State::Open) => { + // send the Confirm message to chain A (source) + (State::TryOpen, State::Open(UpgradeState::NotUpgrading)) => { self.flipped() .build_chan_open_confirm_and_send() .map_err(|e| { @@ -732,7 +696,7 @@ impl Channel { })?; } - (State::Open, State::Open) => { + (State::Open(UpgradeState::NotUpgrading), State::Open(UpgradeState::NotUpgrading)) => { info!("channel handshake already finished for {}", self); return Ok(()); } @@ -809,17 +773,58 @@ impl Channel { (State::Init, State::Init) => Some(self.build_chan_open_try_and_send()?), (State::TryOpen, State::Init) => Some(self.build_chan_open_ack_and_send()?), (State::TryOpen, State::TryOpen) => Some(self.build_chan_open_ack_and_send()?), - (State::Open, State::TryOpen) => Some(self.build_chan_open_confirm_and_send()?), - (State::Open, State::Open) => return Ok((None, Next::Abort)), + (State::Open(UpgradeState::NotUpgrading), State::TryOpen) => { + Some(self.build_chan_open_confirm_and_send()?) + } + (State::Open(UpgradeState::NotUpgrading), State::Open(UpgradeState::NotUpgrading)) => { + return Ok((None, Next::Abort)) + } // If the counterparty state is already Open but current state is TryOpen, // return anyway as the final step is to be done by the counterparty worker. - (State::TryOpen, State::Open) => return Ok((None, Next::Abort)), + (State::TryOpen, State::Open(UpgradeState::NotUpgrading)) => { + return Ok((None, Next::Abort)) + } // Close handshake steps (State::Closed, State::Closed) => return Ok((None, Next::Abort)), (State::Closed, _) => Some(self.build_chan_close_confirm_and_send()?), + // Channel Upgrade handshake steps + (State::Open(UpgradeState::Upgrading), State::Open(UpgradeState::NotUpgrading)) => { + Some(self.build_chan_upgrade_try_and_send()?) + } + (State::Open(UpgradeState::Upgrading), State::Open(UpgradeState::Upgrading)) => { + Some(self.build_chan_upgrade_try_and_send()?) + } + (State::Open(UpgradeState::NotUpgrading), State::Open(UpgradeState::Upgrading)) => { + Some(self.build_chan_upgrade_try_and_send()?) + } + (State::Flushing, State::Open(UpgradeState::Upgrading)) => { + Some(self.build_chan_upgrade_ack_and_send()?) + } + (State::Flushing, State::Flushing) => Some(self.build_chan_upgrade_ack_and_send()?), + (State::FlushComplete, State::Flushing) => { + Some(self.build_chan_upgrade_confirm_and_send()?) + } + + (State::Flushing, State::Open(UpgradeState::NotUpgrading)) => { + Some(self.flipped().build_chan_upgrade_cancel_and_send()?) + } + (State::Open(UpgradeState::NotUpgrading), State::Flushing) => { + Some(self.build_chan_upgrade_cancel_and_send()?) + } + + (State::FlushComplete, State::FlushComplete) => { + Some(self.build_chan_upgrade_open_and_send()?) + } + (State::FlushComplete, State::Open(UpgradeState::NotUpgrading)) => self + .flipped() + .build_chan_upgrade_open_or_cancel_and_send()?, + (State::Open(UpgradeState::NotUpgrading), State::FlushComplete) => { + self.build_chan_upgrade_open_or_cancel_and_send()? + } + _ => None, }; @@ -828,7 +833,10 @@ impl Channel { match event { Some(IbcEvent::OpenConfirmChannel(_)) | Some(IbcEvent::OpenAckChannel(_)) - | Some(IbcEvent::CloseConfirmChannel(_)) => Ok((event, Next::Abort)), + | Some(IbcEvent::CloseConfirmChannel(_)) + | Some(IbcEvent::UpgradeConfirmChannel(_)) + | Some(IbcEvent::UpgradeOpenChannel(_)) + | Some(IbcEvent::UpgradeCancelChannel(_)) => Ok((event, Next::Abort)), _ => Ok((event, Next::Continue)), } } @@ -859,9 +867,14 @@ impl Channel { let state = match event { IbcEvent::OpenInitChannel(_) => State::Init, IbcEvent::OpenTryChannel(_) => State::TryOpen, - IbcEvent::OpenAckChannel(_) => State::Open, - IbcEvent::OpenConfirmChannel(_) => State::Open, + IbcEvent::OpenAckChannel(_) => State::Open(UpgradeState::NotUpgrading), + IbcEvent::OpenConfirmChannel(_) => State::Open(UpgradeState::NotUpgrading), IbcEvent::CloseInitChannel(_) => State::Closed, + IbcEvent::UpgradeInitChannel(_) => State::Open(UpgradeState::Upgrading), + IbcEvent::UpgradeTryChannel(_) => State::Flushing, + IbcEvent::UpgradeAckChannel(_) => State::FlushComplete, + IbcEvent::UpgradeConfirmChannel(_) => State::FlushComplete, + IbcEvent::UpgradeOpenChannel(_) => State::Open(UpgradeState::NotUpgrading), _ => State::Uninitialized, }; @@ -912,6 +925,7 @@ impl Channel { counterparty, vec![self.dst_connection_id().clone()], version, + Sequence::from(0), ); // Build the domain type message @@ -956,7 +970,7 @@ impl Channel { } /// Retrieves the channel from destination and compares it - /// against the expected channel. built from the message type [`ChannelMsgType`]. + /// against the expected channel. Built from the message type [`ChannelMsgType`]. /// /// If the expected and the destination channels are compatible, /// returns the expected channel @@ -981,7 +995,7 @@ impl Channel { let highest_state = match msg_type { ChannelMsgType::OpenAck => State::TryOpen, ChannelMsgType::OpenConfirm => State::TryOpen, - ChannelMsgType::CloseConfirm => State::Open, + ChannelMsgType::CloseConfirm => State::Open(UpgradeState::NotUpgrading), _ => State::Uninitialized, }; @@ -991,6 +1005,7 @@ impl Channel { counterparty, vec![self.dst_connection_id().clone()], Version::empty(), + Sequence::from(0), ); // Retrieve existing channel @@ -1082,6 +1097,7 @@ impl Channel { counterparty, vec![self.dst_connection_id().clone()], version, + Sequence::from(0), ); // Get signer @@ -1434,7 +1450,8 @@ impl Channel { self.validated_expected_channel(ChannelMsgType::CloseConfirm)?; // Channel must exist on source - self.src_chain() + let (src_channel_end, _) = self + .src_chain() .query_channel( QueryChannelRequest { port_id: self.src_port_id().clone(), @@ -1466,6 +1483,8 @@ impl Channel { .build_channel_proofs(self.src_port_id(), src_channel_id, query_height) .map_err(ChannelError::channel_proof)?; + let counterparty_upgrade_sequence = src_channel_end.upgrade_sequence; + // Build message(s) to update client on destination let mut msgs = self.build_update_client_on_dst(proofs.height())?; @@ -1481,6 +1500,7 @@ impl Channel { channel_id: dst_channel_id.clone(), proofs, signer, + counterparty_upgrade_sequence, }; msgs.push(new_msg.to_any()); @@ -1518,6 +1538,679 @@ impl Channel { } } + pub fn build_chan_upgrade_try(&self) -> Result, ChannelError> { + let src_channel_id = self + .src_channel_id() + .ok_or_else(ChannelError::missing_local_channel_id)?; + let src_port_id = self.src_port_id(); + let src_latest_height = self + .src_chain() + .query_latest_height() + .map_err(|e| ChannelError::chain_query(self.src_chain().id(), e))?; + + let dst_channel_id = self + .dst_channel_id() + .ok_or_else(ChannelError::missing_local_channel_id)?; + let dst_port_id = self.dst_port_id(); + + // Fetch the src channel end that will be upgraded by the upgrade handshake + // Querying for the Channel End now includes the upgrade sequence number + let (channel_end, _) = self + .src_chain() + .query_channel( + QueryChannelRequest { + port_id: src_port_id.clone(), + channel_id: src_channel_id.clone(), + height: QueryHeight::Specific(src_latest_height), + }, + IncludeProof::Yes, + ) + .map_err(|e| ChannelError::query(self.src_chain().id(), e))?; + + // Building the channel proof at the queried height + let src_proof = self + .src_chain() + .build_channel_proofs( + &src_port_id.clone(), + &src_channel_id.clone(), + src_latest_height, + ) + .map_err(ChannelError::channel_proof)?; + + let (dst_channel_end, _) = self + .dst_chain() + .query_channel( + QueryChannelRequest { + port_id: dst_port_id.clone(), + channel_id: dst_channel_id.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::Yes, + ) + .map_err(|e| ChannelError::query(self.src_chain().id(), e))?; + + let (upgrade, maybe_upgrade_proof) = self + .src_chain() + .query_upgrade( + QueryUpgradeRequest { + port_id: self.src_port_id().to_string(), + channel_id: src_channel_id.to_string(), + }, + src_latest_height, + IncludeProof::Yes, + ) + .map_err(|e| ChannelError::chain_query(self.src_chain().id(), e))?; + + let upgrade_proof = maybe_upgrade_proof.ok_or(ChannelError::missing_upgrade_proof())?; + + let proof_upgrade = + CommitmentProofBytes::try_from(upgrade_proof).map_err(ChannelError::malformed_proof)?; + + if !matches!(channel_end.state, State::Open(_)) { + return Err(ChannelError::invalid_channel_upgrade_state( + State::Open(UpgradeState::NotUpgrading).to_string(), + channel_end.state.to_string(), + )); + } + + let signer = self + .dst_chain() + .get_signer() + .map_err(|e| ChannelError::fetch_signer(self.dst_chain().id(), e))?; + + // Build the domain type message + let new_msg = MsgChannelUpgradeTry { + port_id: dst_port_id.clone(), + channel_id: dst_channel_id.clone(), + proposed_upgrade_connection_hops: dst_channel_end.connection_hops, + counterparty_upgrade_fields: upgrade.fields, + counterparty_upgrade_sequence: channel_end.upgrade_sequence, + proof_channel: src_proof.object_proof().clone(), + proof_upgrade, + proof_height: src_proof.height(), + signer, + }; + + let mut chain_a_msgs = self.build_update_client_on_dst(src_proof.height())?; + + chain_a_msgs.push(new_msg.to_any()); + + Ok(chain_a_msgs) + } + + pub fn build_chan_upgrade_try_and_send(&self) -> Result { + let dst_msgs = self.build_chan_upgrade_try()?; + + let tm = TrackedMsgs::new_static(dst_msgs, "ChannelUpgradeTry"); + + let events = self + .dst_chain() + .send_messages_and_wait_commit(tm) + .map_err(|e| ChannelError::submit(self.dst_chain().id(), e))?; + + // Find the relevant event for channel upgrade try + let result = events + .into_iter() + .find(|events_with_height| { + matches!(events_with_height.event, IbcEvent::UpgradeTryChannel(_)) + || matches!(events_with_height.event, IbcEvent::UpgradeErrorChannel(_)) + || matches!(events_with_height.event, IbcEvent::ChainError(_)) + }) + .ok_or_else(|| { + ChannelError::missing_event( + "no chan upgrade try or upgrade error event was in the response".to_string(), + ) + })?; + + match result.event { + IbcEvent::UpgradeTryChannel(_) => { + info!("👋 {} => {}", self.dst_chain().id(), result); + Ok(result.event) + } + IbcEvent::UpgradeErrorChannel(ref ev) => { + warn!( + "Channel Upgrade Try failed with error: {}", + ev.error_receipt + ); + Ok(result.event) + } + IbcEvent::ChainError(e) => Err(ChannelError::tx_response(e.clone())), + _ => Err(ChannelError::invalid_event(result.event)), + } + } + + pub fn build_chan_upgrade_ack(&self) -> Result, ChannelError> { + // Destination channel ID must exist + + let src_channel_id = self + .src_channel_id() + .ok_or_else(ChannelError::missing_counterparty_channel_id)?; + + let dst_channel_id = self + .dst_channel_id() + .ok_or_else(ChannelError::missing_counterparty_channel_id)?; + + let src_port_id = self.src_port_id(); + + let dst_port_id = self.dst_port_id(); + + let src_latest_height = self + .src_chain() + .query_latest_height() + .map_err(|e| ChannelError::chain_query(self.src_chain().id(), e))?; + + let (upgrade, maybe_upgrade_proof) = self + .src_chain() + .query_upgrade( + QueryUpgradeRequest { + port_id: self.src_port_id().to_string(), + channel_id: src_channel_id.to_string(), + }, + src_latest_height, + IncludeProof::Yes, + ) + .map_err(|e| ChannelError::chain_query(self.src_chain().id(), e))?; + + let upgrade_proof = maybe_upgrade_proof.ok_or(ChannelError::missing_upgrade_proof())?; + + let proof_upgrade = + CommitmentProofBytes::try_from(upgrade_proof).map_err(ChannelError::malformed_proof)?; + + // Building the channel proof at the queried height + let proof = self + .src_chain() + .build_channel_proofs( + &src_port_id.clone(), + &src_channel_id.clone(), + src_latest_height, + ) + .map_err(ChannelError::channel_proof)?; + + let signer = self + .dst_chain() + .get_signer() + .map_err(|e| ChannelError::fetch_signer(self.dst_chain().id(), e))?; + + // Build the domain type message + let new_msg = MsgChannelUpgradeAck { + port_id: dst_port_id.clone(), + channel_id: dst_channel_id.clone(), + counterparty_upgrade: upgrade, + proof_channel: proof.object_proof().clone(), + proof_upgrade, + proof_height: proof.height(), + signer, + }; + + let mut chain_a_msgs = self.build_update_client_on_dst(proof.height())?; + + chain_a_msgs.push(new_msg.to_any()); + + Ok(chain_a_msgs) + } + + pub fn build_chan_upgrade_ack_and_send(&self) -> Result { + let dst_msgs = self.build_chan_upgrade_ack()?; + + let tm = TrackedMsgs::new_static(dst_msgs, "ChannelUpgradeAck"); + + let events = self + .dst_chain() + .send_messages_and_wait_commit(tm) + .map_err(|e| ChannelError::submit(self.dst_chain().id(), e))?; + + // Find the relevant event for channel upgrade ack + let result = events + .into_iter() + .find(|events_with_height| { + matches!(events_with_height.event, IbcEvent::UpgradeAckChannel(_)) + || matches!(events_with_height.event, IbcEvent::UpgradeErrorChannel(_)) + || matches!(events_with_height.event, IbcEvent::ChainError(_)) + }) + .ok_or_else(|| { + ChannelError::missing_event( + "no chan upgrade ack or upgrade error event was in the response".to_string(), + ) + })?; + + match result.event { + IbcEvent::UpgradeAckChannel(_) => { + info!("👋 {} => {}", self.dst_chain().id(), result); + Ok(result.event) + } + IbcEvent::UpgradeErrorChannel(ref ev) => { + warn!( + "Channel Upgrade Ack failed with error: {}", + ev.error_receipt + ); + Ok(result.event) + } + IbcEvent::ChainError(e) => Err(ChannelError::tx_response(e.clone())), + _ => Err(ChannelError::invalid_event(result.event)), + } + } + + pub fn build_chan_upgrade_confirm(&self) -> Result, ChannelError> { + // Destination channel ID must exist + + let src_channel_id = self + .src_channel_id() + .ok_or_else(ChannelError::missing_counterparty_channel_id)?; + + let dst_channel_id = self + .dst_channel_id() + .ok_or_else(ChannelError::missing_counterparty_channel_id)?; + + let src_port_id = self.src_port_id(); + + let dst_port_id = self.dst_port_id(); + + let src_latest_height = self + .src_chain() + .query_latest_height() + .map_err(|e| ChannelError::chain_query(self.src_chain().id(), e))?; + + // Fetch the src channel end that will be upgraded by the upgrade handshake + // Querying for the Channel End now includes the upgrade sequence number + let (channel_end, _) = self + .src_chain() + .query_channel( + QueryChannelRequest { + port_id: src_port_id.clone(), + channel_id: src_channel_id.clone(), + height: QueryHeight::Specific(src_latest_height), + }, + IncludeProof::Yes, + ) + .map_err(|e| ChannelError::query(self.src_chain().id(), e))?; + + let (upgrade, maybe_upgrade_proof) = self + .src_chain() + .query_upgrade( + QueryUpgradeRequest { + port_id: self.src_port_id().to_string(), + channel_id: src_channel_id.to_string(), + }, + src_latest_height, + IncludeProof::Yes, + ) + .map_err(|e| ChannelError::chain_query(self.src_chain().id(), e))?; + + let upgrade_proof = maybe_upgrade_proof.ok_or(ChannelError::missing_upgrade_proof())?; + + let proof_upgrade = + CommitmentProofBytes::try_from(upgrade_proof).map_err(ChannelError::malformed_proof)?; + + // Building the channel proof at the queried height + let proof = self + .src_chain() + .build_channel_proofs( + &src_port_id.clone(), + &src_channel_id.clone(), + src_latest_height, + ) + .map_err(ChannelError::channel_proof)?; + + let signer = self + .dst_chain() + .get_signer() + .map_err(|e| ChannelError::fetch_signer(self.dst_chain().id(), e))?; + + // Build the domain type message + let new_msg = MsgChannelUpgradeConfirm { + port_id: dst_port_id.clone(), + channel_id: dst_channel_id.clone(), + counterparty_channel_state: channel_end.state, + counterparty_upgrade: upgrade, + proof_channel: proof.object_proof().clone(), + proof_upgrade, + proof_height: proof.height(), + signer, + }; + + let mut chain_a_msgs = self.build_update_client_on_dst(proof.height())?; + + chain_a_msgs.push(new_msg.to_any()); + + Ok(chain_a_msgs) + } + + pub fn build_chan_upgrade_confirm_and_send(&self) -> Result { + let dst_msgs = self.build_chan_upgrade_confirm()?; + + let tm = TrackedMsgs::new_static(dst_msgs, "ChannelUpgradeConfirm"); + + let events = self + .dst_chain() + .send_messages_and_wait_commit(tm) + .map_err(|e| ChannelError::submit(self.dst_chain().id(), e))?; + + // Find the relevant event for channel upgrade confirm + let result = events + .into_iter() + .find(|events_with_height| { + matches!(events_with_height.event, IbcEvent::UpgradeConfirmChannel(_)) + || matches!(events_with_height.event, IbcEvent::UpgradeErrorChannel(_)) + || matches!(events_with_height.event, IbcEvent::ChainError(_)) + }) + .ok_or_else(|| { + ChannelError::missing_event( + "no chan upgrade ack or upgrade error event was in the response".to_string(), + ) + })?; + + match result.event { + IbcEvent::UpgradeConfirmChannel(_) => { + info!("👋 {} => {}", self.dst_chain().id(), result); + Ok(result.event) + } + IbcEvent::UpgradeErrorChannel(ref ev) => { + warn!( + "Channel Upgrade Confirm failed with error: {}", + ev.error_receipt + ); + Ok(result.event) + } + IbcEvent::ChainError(e) => Err(ChannelError::tx_response(e.clone())), + _ => Err(ChannelError::invalid_event(result.event)), + } + } + + pub fn build_chan_upgrade_open(&self) -> Result, ChannelError> { + // Destination channel ID must exist + let src_channel_id = self + .src_channel_id() + .ok_or_else(ChannelError::missing_counterparty_channel_id)?; + + let dst_channel_id = self + .dst_channel_id() + .ok_or_else(ChannelError::missing_counterparty_channel_id)?; + + let src_port_id = self.src_port_id(); + + let dst_port_id = self.dst_port_id(); + + let src_latest_height = self + .src_chain() + .query_latest_height() + .map_err(|e| ChannelError::chain_query(self.src_chain().id(), e))?; + + let (src_channel_end, _) = self + .src_chain() + .query_channel( + QueryChannelRequest { + port_id: src_port_id.clone(), + channel_id: src_channel_id.clone(), + height: QueryHeight::Specific(src_latest_height), + }, + IncludeProof::Yes, + ) + .map_err(|e| ChannelError::query(self.src_chain().id(), e))?; + + let counterparty_upgrade_sequence = src_channel_end.upgrade_sequence; + + // Building the channel proof at the queried height + let proofs = self + .src_chain() + .build_channel_proofs( + &src_port_id.clone(), + &src_channel_id.clone(), + src_latest_height, + ) + .map_err(ChannelError::channel_proof)?; + + // Build message(s) to update client on destination + let mut msgs = self.build_update_client_on_dst(proofs.height())?; + + let signer = self + .dst_chain() + .get_signer() + .map_err(|e| ChannelError::fetch_signer(self.dst_chain().id(), e))?; + + // Build the domain type message + let new_msg = MsgChannelUpgradeOpen { + port_id: dst_port_id.clone(), + channel_id: dst_channel_id.clone(), + counterparty_channel_state: src_channel_end.state, + counterparty_upgrade_sequence, + proof_channel: proofs.object_proof().clone(), + proof_height: proofs.height(), + signer, + }; + + msgs.push(new_msg.to_any()); + Ok(msgs) + } + + pub fn build_chan_upgrade_open_and_send(&self) -> Result { + let dst_msgs = self.build_chan_upgrade_open()?; + + let tm = TrackedMsgs::new_static(dst_msgs, "ChannelUpgradeOpen"); + + let events = self + .dst_chain() + .send_messages_and_wait_commit(tm) + .map_err(|e| ChannelError::submit(self.dst_chain().id(), e))?; + + let result = events + .into_iter() + .find(|event_with_height| { + matches!(event_with_height.event, IbcEvent::UpgradeOpenChannel(_)) + || matches!(event_with_height.event, IbcEvent::ChainError(_)) + }) + .ok_or_else(|| { + ChannelError::missing_event( + "no channel upgrade open event was in the response".to_string(), + ) + })?; + + match &result.event { + IbcEvent::UpgradeOpenChannel(_) => { + info!("👋 {} => {}", self.dst_chain().id(), result); + Ok(result.event) + } + IbcEvent::ChainError(e) => Err(ChannelError::tx_response(e.clone())), + _ => Err(ChannelError::invalid_event(result.event)), + } + } + + pub fn build_chan_upgrade_cancel(&self) -> Result, ChannelError> { + // Destination channel ID must exist + let src_channel_id = self + .src_channel_id() + .ok_or_else(ChannelError::missing_counterparty_channel_id)?; + + let dst_channel_id = self + .dst_channel_id() + .ok_or_else(ChannelError::missing_counterparty_channel_id)?; + + let src_port_id = self.src_port_id(); + + let dst_port_id = self.dst_port_id(); + + let src_latest_height = self + .src_chain() + .query_latest_height() + .map_err(|e| ChannelError::chain_query(self.src_chain().id(), e))?; + + let (error_receipt, maybe_error_receipt_proof) = self + .src_chain() + .query_upgrade_error( + QueryUpgradeErrorRequest { + port_id: src_port_id.to_string(), + channel_id: src_channel_id.to_string(), + }, + src_latest_height, + IncludeProof::Yes, + ) + .map_err(|e| ChannelError::chain_query(self.src_chain().id(), e))?; + + let error_receipt_proof = + maybe_error_receipt_proof.ok_or(ChannelError::missing_upgrade_error_receipt_proof())?; + + let proof_error_receipt = CommitmentProofBytes::try_from(error_receipt_proof) + .map_err(ChannelError::malformed_proof)?; + + // Building the channel proof at the queried height + let proofs = self + .src_chain() + .build_channel_proofs( + &src_port_id.clone(), + &src_channel_id.clone(), + src_latest_height, + ) + .map_err(ChannelError::channel_proof)?; + + // Build message(s) to update client on destination + let mut msgs = self.build_update_client_on_dst(proofs.height())?; + + let signer = self + .dst_chain() + .get_signer() + .map_err(|e| ChannelError::fetch_signer(self.dst_chain().id(), e))?; + + // Build the domain type message + let new_msg = MsgChannelUpgradeCancel { + port_id: dst_port_id.clone(), + channel_id: dst_channel_id.clone(), + error_receipt, + proof_error_receipt, + proof_height: proofs.height(), + signer, + }; + + msgs.push(new_msg.to_any()); + Ok(msgs) + } + + pub fn build_chan_upgrade_cancel_and_send(&self) -> Result { + let dst_msgs = self.build_chan_upgrade_cancel()?; + + let tm = TrackedMsgs::new_static(dst_msgs, "ChannelUpgradeCancel"); + + let events = self + .dst_chain() + .send_messages_and_wait_commit(tm) + .map_err(|e| ChannelError::submit(self.dst_chain().id(), e))?; + + let result = events + .into_iter() + .find(|event_with_height| { + matches!(event_with_height.event, IbcEvent::UpgradeCancelChannel(_)) + || matches!(event_with_height.event, IbcEvent::ChainError(_)) + }) + .ok_or_else(|| { + ChannelError::missing_event( + "no channel upgrade cancel event was in the response".to_string(), + ) + })?; + + match &result.event { + IbcEvent::UpgradeCancelChannel(_) => { + info!("👋 {} => {}", self.dst_chain().id(), result); + Ok(result.event) + } + IbcEvent::ChainError(e) => Err(ChannelError::tx_response(e.clone())), + _ => Err(ChannelError::invalid_event(result.event)), + } + } + + pub fn build_chan_upgrade_timeout(&self) -> Result, ChannelError> { + // Destination channel ID must exist + let src_channel_id = self + .src_channel_id() + .ok_or_else(ChannelError::missing_counterparty_channel_id)?; + + let dst_channel_id = self + .dst_channel_id() + .ok_or_else(ChannelError::missing_counterparty_channel_id)?; + + let src_port_id = self.src_port_id(); + + let dst_port_id = self.dst_port_id(); + + let src_latest_height = self + .src_chain() + .query_latest_height() + .map_err(|e| ChannelError::chain_query(self.src_chain().id(), e))?; + + // Retrieve counterparty channel + let (counterparty_channel, _) = self + .src_chain() + .query_channel( + QueryChannelRequest { + port_id: src_port_id.clone(), + channel_id: src_channel_id.clone(), + height: QueryHeight::Specific(src_latest_height), + }, + IncludeProof::Yes, + ) + .map_err(|e| ChannelError::query(self.src_chain().id(), e))?; + + // Building the channel proof at the queried height + let proofs = self + .src_chain() + .build_channel_proofs( + &src_port_id.clone(), + &src_channel_id.clone(), + src_latest_height, + ) + .map_err(ChannelError::channel_proof)?; + + // Build message(s) to update client on destination + let mut msgs = self.build_update_client_on_dst(proofs.height())?; + + let signer = self + .dst_chain() + .get_signer() + .map_err(|e| ChannelError::fetch_signer(self.dst_chain().id(), e))?; + + // Build the domain type message + let new_msg = MsgChannelUpgradeTimeout { + port_id: dst_port_id.clone(), + channel_id: dst_channel_id.clone(), + counterparty_channel, + proof_channel: proofs.object_proof().clone(), + proof_height: proofs.height(), + signer, + }; + + msgs.push(new_msg.to_any()); + Ok(msgs) + } + + pub fn build_chan_upgrade_timeout_and_send(&self) -> Result { + let dst_msgs = self.build_chan_upgrade_timeout()?; + + let tm = TrackedMsgs::new_static(dst_msgs, "ChannelUpgradeTimeout"); + + let events = self + .dst_chain() + .send_messages_and_wait_commit(tm) + .map_err(|e| ChannelError::submit(self.dst_chain().id(), e))?; + + let result = events + .into_iter() + .find(|event_with_height| { + matches!(event_with_height.event, IbcEvent::UpgradeTimeoutChannel(_)) + || matches!(event_with_height.event, IbcEvent::ChainError(_)) + }) + .ok_or_else(|| { + ChannelError::missing_event( + "no channel upgrade timeout event was in the response".to_string(), + ) + })?; + + match &result.event { + IbcEvent::UpgradeTimeoutChannel(_) => { + info!("👋 {} => {}", self.dst_chain().id(), result); + Ok(result.event) + } + IbcEvent::ChainError(e) => Err(ChannelError::tx_response(e.clone())), + _ => Err(ChannelError::invalid_event(result.event)), + } + } + pub fn map_chain( self, mapper_a: impl Fn(ChainA) -> ChainC, @@ -1530,6 +2223,38 @@ impl Channel { connection_delay: self.connection_delay, } } + + pub fn build_chan_upgrade_open_or_cancel_and_send( + &self, + ) -> Result, ChannelError> { + // Check if error query_upgrade_error + let height = self.a_chain().query_latest_height().unwrap(); + let upgrade_error = self + .a_chain() + .query_upgrade_error( + QueryUpgradeErrorRequest { + port_id: self.a_side.port_id.clone().to_string(), + channel_id: self.a_side.channel_id.clone().unwrap().clone().to_string(), + }, + height, + IncludeProof::No, + ) + .map_err(|_| ChannelError::missing_upgrade_error_receipt_proof()); + + let channel_end = self.b_channel(self.b_channel_id())?; + + if let Ok((upgrade_error, _)) = upgrade_error { + if upgrade_error.sequence > 0.into() + && upgrade_error.sequence == channel_end.upgrade_sequence + { + Ok(Some(self.build_chan_upgrade_cancel_and_send()?)) + } else { + Ok(Some(self.build_chan_upgrade_open_and_send()?)) + } + } else { + Ok(Some(self.build_chan_upgrade_open_and_send()?)) + } + } } pub fn extract_channel_id(event: &IbcEvent) -> Result<&ChannelId, ChannelError> { @@ -1538,6 +2263,7 @@ pub fn extract_channel_id(event: &IbcEvent) -> Result<&ChannelId, ChannelError> IbcEvent::OpenTryChannel(ev) => ev.channel_id(), IbcEvent::OpenAckChannel(ev) => ev.channel_id(), IbcEvent::OpenConfirmChannel(ev) => ev.channel_id(), + IbcEvent::UpgradeInitChannel(ev) => Some(ev.channel_id()), _ => None, } .ok_or_else(|| ChannelError::missing_event("cannot extract channel_id from result".to_string())) @@ -1561,7 +2287,9 @@ fn check_destination_channel_state( existing_channel.connection_hops() == expected_channel.connection_hops(); // TODO: Refactor into a method - let good_state = *existing_channel.state() as u32 <= *expected_channel.state() as u32; + let good_state = existing_channel + .state() + .less_or_equal_progress(*expected_channel.state()); let good_channel_port_ids = existing_channel.counterparty().channel_id().is_none() || existing_channel.counterparty().channel_id() == expected_channel.counterparty().channel_id() diff --git a/crates/relayer/src/channel/error.rs b/crates/relayer/src/channel/error.rs index a2bbd2baab..e7ec2878a7 100644 --- a/crates/relayer/src/channel/error.rs +++ b/crates/relayer/src/channel/error.rs @@ -1,30 +1,18 @@ use core::time::Duration; -use flex_error::{ - define_error, - ErrorMessageTracer, -}; -use ibc_relayer_types::{ - core::{ - ics02_client::error::Error as ClientError, - ics04_channel::channel::State, - ics24_host::identifier::{ - ChainId, - ChannelId, - ClientId, - PortChannelId, - PortId, - }, - }, - events::IbcEvent, +use flex_error::{define_error, ErrorMessageTracer}; + +use ibc_relayer_types::core::ics02_client::error::Error as ClientError; +use ibc_relayer_types::core::ics04_channel::channel::{Ordering, State}; +use ibc_relayer_types::core::ics24_host::identifier::{ + ChainId, ChannelId, ClientId, PortChannelId, PortId, }; +use ibc_relayer_types::events::IbcEvent; +use ibc_relayer_types::proofs::ProofError; use crate::{ error::Error as RelayerError, - foreign_client::{ - ForeignClientError, - HasExpiredOrFrozenError, - }, + foreign_client::{ForeignClientError, HasExpiredOrFrozenError}, supervisor::Error as SupervisorError, }; @@ -49,6 +37,16 @@ define_error! { e.reason) }, + InvalidChannelUpgradeOrdering + |_| { "attempted to upgrade a channel to a more strict ordring, which is not allowed" }, + + InvalidChannelUpgradeState + { expected: String, actual: String } + |e| { format_args!("channel state should be {} but is {}", e.expected, e.actual) }, + + InvalidChannelUpgradeTimeout + |_| { "attempted to upgrade a channel without supplying at least one of timeout height or timeout timestamp" }, + MissingLocalChannelId |_| { "failed due to missing local channel id" }, @@ -68,10 +66,33 @@ define_error! { MissingChannelOnDestination |_| { "missing channel on destination chain" }, + MissingChannelProof + |_| { "missing channel proof" }, + + MissingUpgradeProof + |_| { "missing upgrade proof" }, + + MissingUpgradeErrorReceiptProof + |_| { "missing upgrade error receipt proof" }, + + MalformedProof + [ ProofError ] + |_| { "malformed proof" }, + ChannelProof [ RelayerError ] |_| { "failed to build channel proofs" }, + InvalidOrdering + { + channel_ordering: Ordering, + counterparty_ordering: Ordering, + } + | e | { + format_args!("channel ordering '{0}' does not match counterparty ordering '{1}'", + e.channel_ordering, e.counterparty_ordering) + }, + ClientOperation { client_id: ClientId, diff --git a/crates/relayer/src/channel/version.rs b/crates/relayer/src/channel/version.rs index 9866779c05..5f6ec78ea9 100644 --- a/crates/relayer/src/channel/version.rs +++ b/crates/relayer/src/channel/version.rs @@ -5,12 +5,9 @@ //! handshake. pub use ibc_relayer_types::core::ics04_channel::version::Version; -use ibc_relayer_types::{ - applications::transfer, - core::ics24_host::identifier::PortId, -}; +use ibc_relayer_types::{applications::transfer, core::ics24_host::identifier::PortId}; -/// Returns the default channel version, depending on the the given [`PortId`]. +/// Returns the default channel version, depending on the given [`PortId`]. pub fn default_by_port(port_id: &PortId) -> Option { if port_id.as_str() == transfer::PORT_ID_STR { // https://github.com/cosmos/ibc/tree/master/spec/app/ics-020-fungible-token-transfer#forwards-compatibility diff --git a/crates/relayer/src/client_state.rs b/crates/relayer/src/client_state.rs index 2178c3d006..85f5b83dc4 100644 --- a/crates/relayer/src/client_state.rs +++ b/crates/relayer/src/client_state.rs @@ -1,136 +1,74 @@ -use core::time::Duration; +use std::time::Duration; -#[cfg(test)] -use ibc_proto::ibc::mock::ClientState as RawMockClientState; -use ibc_proto::{ - google::protobuf::Any, - ibc::{ - core::client::v1::IdentifiedClientState, - lightclients::tendermint::v1::ClientState as RawTmClientState, - }, - Protobuf, -}; -#[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::{ - clients::ics07_tendermint::client_state::{ - ClientState as TmClientState, - UpgradeOptions as TmUpgradeOptions, - TENDERMINT_CLIENT_STATE_TYPE_URL, - }, - core::{ - ics02_client::{ - client_state::ClientState, - client_type::ClientType, - error::Error, - trust_threshold::TrustThreshold, - }, - ics24_host::{ - error::ValidationError, - identifier::{ - ChainId, - ClientId, - }, - }, - }, - Height, -}; -use serde::{ - Deserialize, - Serialize, -}; +use serde::{Deserialize, Serialize}; -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -#[serde(tag = "type")] -pub enum AnyUpgradeOptions { - Tendermint(TmUpgradeOptions), - - #[cfg(test)] - Mock(()), -} - -impl AnyUpgradeOptions { - fn into_tm_upgrade_options(self) -> Option { - match self { - AnyUpgradeOptions::Tendermint(tm) => Some(tm), - #[cfg(test)] - AnyUpgradeOptions::Mock(_) => None, - } - } -} +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, TENDERMINT_CLIENT_STATE_TYPE_URL, +}; +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; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "type")] pub enum AnyClientState { Tendermint(TmClientState), - - #[cfg(test)] - Mock(MockClientState), } 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(), - - #[cfg(test)] - Self::Mock(mock_state) => mock_state.latest_height(), } } pub fn frozen_height(&self) -> Option { match self { Self::Tendermint(tm_state) => tm_state.frozen_height(), - - #[cfg(test)] - Self::Mock(mock_state) => mock_state.frozen_height(), } } pub fn trust_threshold(&self) -> Option { match self { AnyClientState::Tendermint(state) => Some(state.trust_threshold), - - #[cfg(test)] - AnyClientState::Mock(_) => None, } } pub fn trusting_period(&self) -> Duration { match self { AnyClientState::Tendermint(state) => state.trusting_period, - - #[cfg(test)] - AnyClientState::Mock(_) => Duration::from_secs(14 * 24 * 60 * 60), // 2 weeks } } pub fn max_clock_drift(&self) -> Duration { match self { AnyClientState::Tendermint(state) => state.max_clock_drift, - - #[cfg(test)] - AnyClientState::Mock(_) => Duration::new(0, 0), } } pub fn client_type(&self) -> ClientType { match self { Self::Tendermint(state) => state.client_type(), + } + } - #[cfg(test)] - Self::Mock(state) => state.client_type(), + pub fn expired(&self, elapsed: Duration) -> bool { + match self { + Self::Tendermint(state) => state.expired(elapsed), } } } @@ -149,12 +87,6 @@ impl TryFrom for AnyClientState { .map_err(Error::decode_raw_client_state)?, )), - #[cfg(test)] - MOCK_CLIENT_STATE_TYPE_URL => Ok(AnyClientState::Mock( - Protobuf::::decode_vec(&raw.value) - .map_err(Error::decode_raw_client_state)?, - )), - _ => Err(Error::unknown_client_state_type(raw.type_url)), } } @@ -167,68 +99,29 @@ impl From for Any { type_url: TENDERMINT_CLIENT_STATE_TYPE_URL.to_string(), 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), - }, } } } impl ClientState for AnyClientState { - type UpgradeOptions = AnyUpgradeOptions; - 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(), - } + AnyClientState::chain_id(self) } fn client_type(&self) -> ClientType { - self.client_type() + AnyClientState::client_type(self) } fn latest_height(&self) -> Height { - self.latest_height() + AnyClientState::latest_height(self) } fn frozen_height(&self) -> Option { - self.frozen_height() - } - - fn upgrade( - &mut self, - upgrade_height: Height, - upgrade_options: AnyUpgradeOptions, - chain_id: ChainId, - ) { - match self { - 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, (), chain_id); - } - } + AnyClientState::frozen_height(self) } - fn expired(&self, elapsed_since_latest: Duration) -> bool { - match self { - AnyClientState::Tendermint(tm_state) => tm_state.expired(elapsed_since_latest), - - #[cfg(test)] - AnyClientState::Mock(mock_state) => mock_state.expired(elapsed_since_latest), - } + fn expired(&self, elapsed: Duration) -> bool { + AnyClientState::expired(self, elapsed) } } @@ -238,13 +131,6 @@ impl From for AnyClientState { } } -#[cfg(test)] -impl From for AnyClientState { - fn from(cs: MockClientState) -> Self { - Self::Mock(cs) - } -} - #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "type")] pub struct IdentifiedAnyClientState { @@ -287,25 +173,3 @@ impl From for IdentifiedClientState { } } } - -#[cfg(test)] -mod tests { - use ibc_proto::google::protobuf::Any; - use ibc_relayer_types::clients::ics07_tendermint::{ - client_state::test_util::get_dummy_tendermint_client_state, - header::test_util::get_dummy_tendermint_header, - }; - use test_log::test; - - use super::AnyClientState; - - #[test] - fn any_client_state_serialization() { - let tm_client_state: AnyClientState = - get_dummy_tendermint_client_state(get_dummy_tendermint_header()).into(); - - let raw: Any = tm_client_state.clone().into(); - let tm_client_state_back = AnyClientState::try_from(raw).unwrap(); - assert_eq!(tm_client_state, tm_client_state_back); - } -} diff --git a/crates/relayer/src/config.rs b/crates/relayer/src/config.rs index aee6a3ca64..02ce0ebb06 100644 --- a/crates/relayer/src/config.rs +++ b/crates/relayer/src/config.rs @@ -1,6 +1,7 @@ //! Relayer configuration pub mod compat_mode; +pub mod dynamic_gas; pub mod error; pub mod filter; pub mod gas_multiplier; @@ -9,66 +10,39 @@ pub mod refresh_rate; pub mod types; use alloc::collections::BTreeMap; -use core::{ - cmp::Ordering, - fmt::{ - Display, - Error as FmtError, - Formatter, - }, - str::FromStr, - time::Duration, -}; -use std::{ - fs, - fs::File, - io::Write, - ops::Range, - path::Path, -}; +use core::cmp::Ordering; +use core::fmt::{Display, Error as FmtError, Formatter}; +use core::str::FromStr; +use core::time::Duration; +use ibc_relayer_types::core::ics04_channel::packet::Sequence; +use std::borrow::Cow; +use std::{fs, fs::File, io::Write, ops::Range, path::Path}; use byte_unit::Byte; -pub use error::Error; -pub use filter::PacketFilter; -use ibc_proto::google::protobuf::Any; -use ibc_relayer_types::{ - core::{ - ics23_commitment::specs::ProofSpecs, - ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }, - }, - timestamp::ZERO_DURATION, -}; -pub use refresh_rate::RefreshRate; -use serde_derive::{ - Deserialize, - Serialize, -}; +use serde::{Deserialize, Serialize}; use tendermint::block::Height as BlockHeight; -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::cosmos::config::CosmosSdkConfig; +use crate::config::types::ics20_field_size_limit::Ics20FieldSizeLimit; +use crate::config::types::TrustThreshold; +use crate::error::Error as RelayerError; +use crate::extension_options::ExtensionOptionDynamicFeeTx; +use crate::keyring::{AnySigningKeyPair, KeyRing, Store}; + +use crate::keyring; pub use crate::config::Error as ConfigError; -use crate::{ - chain::cosmos::config::CosmosSdkConfig, - config::types::{ - ics20_field_size_limit::Ics20FieldSizeLimit, - TrustThreshold, - }, - error::Error as RelayerError, - extension_options::ExtensionOptionDynamicFeeTx, - keyring, - keyring::{ - AnySigningKeyPair, - KeyRing, - Store, - }, -}; +pub use error::Error; + +pub use filter::PacketFilter; +pub use refresh_rate::RefreshRate; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct GasPrice { @@ -202,7 +176,11 @@ pub mod default { } pub fn poll_interval() -> Duration { - Duration::from_secs(1) + Duration::from_millis(500) + } + + pub fn max_retries() -> u32 { + 4 } pub fn batch_delay() -> Duration { @@ -269,6 +247,14 @@ pub mod default { pub fn ics20_max_receiver_size() -> Ics20FieldSizeLimit { Ics20FieldSizeLimit::new(true, Byte::from_bytes(2048)) } + + pub fn allow_ccq() -> bool { + true + } + + pub fn clear_limit() -> usize { + 50 + } } #[derive(Clone, Debug, Default, Deserialize, Serialize)] @@ -444,6 +430,11 @@ pub struct Packets { pub ics20_max_memo_size: Ics20FieldSizeLimit, #[serde(default = "default::ics20_max_receiver_size")] pub ics20_max_receiver_size: Ics20FieldSizeLimit, + #[serde(default = "default::clear_limit")] + pub clear_limit: usize, + + #[serde(skip)] + pub force_disable_clear_on_start: bool, } impl Default for Packets { @@ -456,6 +447,8 @@ impl Default for Packets { auto_register_counterparty_payee: default::auto_register_counterparty_payee(), ics20_max_memo_size: default::ics20_max_memo_size(), ics20_max_receiver_size: default::ics20_max_receiver_size(), + clear_limit: default::clear_limit(), + force_disable_clear_on_start: false, } } } @@ -648,11 +641,21 @@ pub enum EventSourceMode { /// The polling interval #[serde(default = "default::poll_interval", with = "humantime_serde")] interval: Duration, + + /// The maximum retries to collect the block results + /// before giving up and moving to the next block + #[serde(default = "default::max_retries")] + max_retries: u32, }, } -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -#[serde(deny_unknown_fields)] +// NOTE: To work around a limitation of serde, which does not allow +// to specify a default variant if not tag is present, we use +// a custom Deserializer impl. +// +// IMPORTANT: Do not forget to update the `Deserializer` impl +// below when adding a new chain type. +#[derive(Clone, Debug, PartialEq, Serialize)] #[serde(tag = "type")] pub enum ChainConfig { CosmosSdk(CosmosSdkConfig), @@ -776,11 +779,72 @@ impl ChainConfig { Self::Astria(config) => config.query_packets_chunk_size = query_packets_chunk_size, } } + + pub fn excluded_sequences(&self, channel_id: &ChannelId) -> Cow<'_, [Sequence]> { + match self { + Self::CosmosSdk(config) => config + .excluded_sequences + .map + .get(channel_id) + .map(|seqs| Cow::Borrowed(seqs.as_slice())) + .unwrap_or_else(|| Cow::Owned(Vec::new())), + Self::Astria(config) => config + .excluded_sequences + .map + .get(channel_id) + .map(|seqs| Cow::Borrowed(seqs.as_slice())) + .unwrap_or_else(|| Cow::Owned(Vec::new())), + } + } + + pub fn allow_ccq(&self) -> bool { + match self { + Self::CosmosSdk(config) => config.allow_ccq, + Self::Astria(config) => config.allow_ccq, + } + } +} + +// /!\ Update me when adding a new chain type! +impl<'de> Deserialize<'de> for ChainConfig { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let mut value = serde_json::Value::deserialize(deserializer)?; + + // Remove the `type` key from the TOML value in order for deserialization to work, + // otherwise it would fail with: `unknown field `type`. + let type_value = value + .as_object_mut() + .ok_or_else(|| serde::de::Error::custom("invalid chain config, must be a table"))? + .remove("type") + .unwrap_or_else(|| serde_json::json!("CosmosSdk")); + + let type_str = type_value + .as_str() + .ok_or_else(|| serde::de::Error::custom("invalid chain type, must be a string"))?; + + match type_str { + "CosmosSdk" => CosmosSdkConfig::deserialize(value) + .map(Self::CosmosSdk) + .map_err(|e| serde::de::Error::custom(format!("invalid CosmosSdk config: {e}"))), + "Astria" => CosmosSdkConfig::deserialize(value) + .map(Self::Astria) + .map_err(|e| serde::de::Error::custom(format!("invalid Astria config: {e}"))), + // + // <-- Add new chain types here --> + // + chain_type => Err(serde::de::Error::custom(format!( + "unknown chain type: {chain_type}", + ))), + } + } } /// Attempt to load and parse the TOML config file as a `Config`. pub fn load(path: impl AsRef) -> Result { - let config_toml = std::fs::read_to_string(&path).map_err(Error::io)?; + let config_toml = fs::read_to_string(&path).map_err(Error::io)?; let config = toml::from_str::(&config_toml[..]).map_err(Error::decode)?; @@ -851,13 +915,7 @@ impl From for Error { mod tests { use core::str::FromStr; - use test_log::test; - - use super::{ - load, - parse_gas_prices, - store_writer, - }; + use super::{load, parse_gas_prices, store_writer, ChainConfig}; use crate::config::GasPrice; #[test] @@ -918,6 +976,23 @@ mod tests { assert!(load(path).is_err()); } + #[test] + fn parse_default_chain_type() { + let path = concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/config/fixtures/relayer_conf_example_default_chain_type.toml" + ); + + let config = load(path).expect("could not parse config"); + + match config.chains[0] { + super::ChainConfig::CosmosSdk(_) => { + // all good + } + super::ChainConfig::Astria(_) => panic!("expected CosmosSdk chain type"), + } + } + #[test] fn serialize_valid_config() { let path = concat!( @@ -931,6 +1006,41 @@ mod tests { store_writer(&config, &mut buffer).unwrap(); } + #[test] + fn serialize_valid_excluded_sequences_config() { + let path = concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/config/fixtures/relayer_conf_example.toml" + ); + + let config = load(path).expect("could not parse config"); + + let excluded_sequences1 = match config.chains.first().unwrap() { + ChainConfig::CosmosSdk(chain_config) => chain_config.excluded_sequences.clone(), + ChainConfig::Astria(chain_config) => chain_config.excluded_sequences.clone(), + }; + + let excluded_sequences2 = match config.chains.last().unwrap() { + ChainConfig::CosmosSdk(chain_config) => chain_config.excluded_sequences.clone(), + ChainConfig::Astria(chain_config) => chain_config.excluded_sequences.clone(), + }; + + assert_eq!(excluded_sequences1, excluded_sequences2); + + let mut buffer = Vec::new(); + store_writer(&config, &mut buffer).unwrap(); + } + + #[test] + fn serialize_invalid_excluded_sequences_config() { + let path = concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/config/fixtures/relayer_conf_example_invalid_excluded_sequences.toml" + ); + + assert!(load(path).is_err()); + } + #[test] fn gas_price_from_str() { let gp_original = GasPrice::new(10.0, "atom".to_owned()); diff --git a/crates/relayer/src/config/compat_mode.rs b/crates/relayer/src/config/compat_mode.rs index 4fdff7552e..e939cec28b 100644 --- a/crates/relayer/src/config/compat_mode.rs +++ b/crates/relayer/src/config/compat_mode.rs @@ -1,18 +1,9 @@ use core::{ - fmt::{ - Display, - Error as FmtError, - Formatter, - }, + fmt::{Display, Error as FmtError, Formatter}, str::FromStr, }; -use serde::{ - Deserialize, - Deserializer, - Serialize, - Serializer, -}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use tendermint_rpc::client::CompatMode as TmCompatMode; use crate::config::Error; diff --git a/crates/relayer/src/config/dynamic_gas.rs b/crates/relayer/src/config/dynamic_gas.rs new file mode 100644 index 0000000000..f18246f7eb --- /dev/null +++ b/crates/relayer/src/config/dynamic_gas.rs @@ -0,0 +1,142 @@ +use serde::de::Error as DeserializeError; +use serde::de::Unexpected; +use serde::Deserialize; +use serde::Deserializer; +use serde_derive::Serialize; + +flex_error::define_error! { + Error { + MultiplierTooSmall + { value: f64 } + |e| { + format_args!("`multiplier` in dynamic_gas configuration must be greater than or equal to {}, found {}", + DynamicGasPrice::MIN_MULTIPLIER, e.value) + }, + } +} + +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize)] +pub struct DynamicGasPrice { + pub enabled: bool, + pub multiplier: f64, + pub max: f64, +} + +impl DynamicGasPrice { + const DEFAULT_MULTIPLIER: f64 = 1.1; + const DEFAULT_MAX: f64 = 0.6; + const MIN_MULTIPLIER: f64 = 1.0; + + pub fn enabled(multiplier: f64, max: f64) -> Result { + Self::new(true, multiplier, max) + } + + pub fn disabled() -> Self { + Self { + enabled: false, + multiplier: Self::DEFAULT_MULTIPLIER, + max: Self::DEFAULT_MAX, + } + } + + pub fn new(enabled: bool, multiplier: f64, max: f64) -> Result { + if multiplier < Self::MIN_MULTIPLIER { + return Err(Error::multiplier_too_small(multiplier)); + } + + Ok(Self { + enabled, + multiplier, + max, + }) + } + + // Unsafe GasMultiplier used for test cases only. + pub fn unsafe_new(enabled: bool, multiplier: f64, max: f64) -> Self { + Self { + enabled, + multiplier, + max, + } + } +} + +impl Default for DynamicGasPrice { + fn default() -> Self { + Self::disabled() + } +} + +impl<'de> Deserialize<'de> for DynamicGasPrice { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + #[derive(Deserialize)] + struct DynGas { + enabled: bool, + multiplier: f64, + max: f64, + } + + let DynGas { + enabled, + multiplier, + max, + } = DynGas::deserialize(deserializer)?; + + DynamicGasPrice::new(enabled, multiplier, max).map_err(|e| match e.detail() { + ErrorDetail::MultiplierTooSmall(_) => D::Error::invalid_value( + Unexpected::Float(multiplier), + &format!( + "a floating-point value greater than {}", + Self::MIN_MULTIPLIER + ) + .as_str(), + ), + }) + } +} + +#[cfg(test)] +#[allow(dead_code)] // the field of the struct `DummyConfig` defined below is never accessed +mod tests { + use super::*; + + use serde::Deserialize; + use test_log::test; + + #[test] + fn parse_invalid_gas_multiplier() { + #[derive(Debug, Deserialize)] + struct DummyConfig { + dynamic_gas: DynamicGasPrice, + } + + let err = toml::from_str::( + "dynamic_gas = { enabled = true, multiplier = 0.9, max = 0.6 }", + ) + .unwrap_err() + .to_string(); + + println!("err: {err}"); + + assert!(err.contains("expected a floating-point value greater than")); + } + + #[test] + fn safe_gas_multiplier() { + let dynamic_gas = DynamicGasPrice::new(true, 0.6, 0.6); + assert!( + dynamic_gas.is_err(), + "Gas multiplier should be an error if value is lower than 1.0: {dynamic_gas:?}" + ); + } + + #[test] + fn unsafe_gas_multiplier() { + let dynamic_gas = DynamicGasPrice::unsafe_new(true, 0.6, 0.4); + assert_eq!(dynamic_gas.multiplier, 0.6); + assert_eq!(dynamic_gas.max, 0.4); + } +} diff --git a/crates/relayer/src/config/error.rs b/crates/relayer/src/config/error.rs index c93bce7ee7..1efd3a1fdb 100644 --- a/crates/relayer/src/config/error.rs +++ b/crates/relayer/src/config/error.rs @@ -1,7 +1,4 @@ -use flex_error::{ - define_error, - TraceError, -}; +use flex_error::{define_error, TraceError}; use ibc_relayer_types::core::ics24_host::identifier::ChainId; use tracing_subscriber::filter::ParseError; diff --git a/crates/relayer/src/config/filter.rs b/crates/relayer/src/config/filter.rs index fb6c74324e..a01a248e69 100644 --- a/crates/relayer/src/config/filter.rs +++ b/crates/relayer/src/config/filter.rs @@ -1,31 +1,16 @@ //! Custom `serde` deserializer for `FilterMatch` -use core::{ - fmt, - str::FromStr, -}; -use std::{ - collections::HashMap, - hash::Hash, -}; +use core::{fmt, str::FromStr}; +use std::{collections::HashMap, hash::Hash}; use ibc_relayer_types::{ applications::transfer::RawCoin, bigint::U256, - core::ics24_host::identifier::{ - ChannelId, - PortId, - }, + core::ics24_host::identifier::{ChannelId, PortId}, events::IbcEventType, }; use itertools::Itertools; -use serde::{ - de, - Deserialize, - Deserializer, - Serialize, - Serializer, -}; +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; /// Represents all the filtering policies for packets. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -387,7 +372,7 @@ impl<'de> Deserialize<'de> for ChannelFilterMatch { } pub(crate) mod port { - use ibc_relayer_types::core::ics24_host::identifier::PortId; + use super::*; use super::*; @@ -401,11 +386,13 @@ pub(crate) mod port { } fn visit_str(self, v: &str) -> Result { - if let Ok(port_id) = PortId::from_str(v) { - Ok(PortFilterMatch::Exact(port_id)) - } else { - let wildcard = v.parse().map_err(E::custom)?; + let trimmed_v = v.trim(); + if trimmed_v.contains('*') { + let wildcard = trimmed_v.parse().map_err(E::custom)?; Ok(PortFilterMatch::Wildcard(wildcard)) + } else { + let port_id = PortId::from_str(trimmed_v).map_err(E::custom)?; + Ok(PortFilterMatch::Exact(port_id)) } } @@ -416,7 +403,7 @@ pub(crate) mod port { } pub(crate) mod channel { - use ibc_relayer_types::core::ics24_host::identifier::ChannelId; + use super::*; use super::*; @@ -430,11 +417,13 @@ pub(crate) mod channel { } fn visit_str(self, v: &str) -> Result { - if let Ok(channel_id) = ChannelId::from_str(v) { - Ok(ChannelFilterMatch::Exact(channel_id)) - } else { - let wildcard = v.parse().map_err(E::custom)?; + let trimmed_v = v.trim(); + if trimmed_v.contains('*') { + let wildcard = trimmed_v.parse().map_err(E::custom)?; Ok(ChannelFilterMatch::Wildcard(wildcard)) + } else { + let channel_id = ChannelId::from_str(trimmed_v.trim()).map_err(E::custom)?; + Ok(ChannelFilterMatch::Exact(channel_id)) } } @@ -447,7 +436,6 @@ pub(crate) mod channel { #[cfg(test)] mod tests { use super::*; - use crate::config::filter::ChannelPolicy; #[test] fn deserialize_packet_filter_policy() { @@ -469,10 +457,7 @@ mod tests { fn serialize_packet_filter_policy() { use std::str::FromStr; - use ibc_relayer_types::core::ics24_host::identifier::{ - ChannelId, - PortId, - }; + use ibc_relayer_types::core::ics24_host::identifier::{ChannelId, PortId}; let filter_policy = ChannelFilters(vec![ ( @@ -625,4 +610,21 @@ mod tests { let wildcard = "ica*".parse::().unwrap(); assert_eq!(wildcard.to_string(), "ica*".to_string()); } + + #[test] + fn test_exact_matches() { + let allow_policy = r#" + policy = "allow" + list = [ + [ "transfer", "channel-88", ], # Standard exact match + [ "transfer", "channel-476 ", ], # Whitespace abstraction + ] + "#; + + let pf: ChannelPolicy = + toml::from_str(allow_policy).expect("could not parse filter policy"); + + let assert_allow = matches!(pf, ChannelPolicy::Allow(filters) if filters.is_exact()); + assert!(assert_allow); + } } diff --git a/crates/relayer/src/config/gas_multiplier.rs b/crates/relayer/src/config/gas_multiplier.rs index 7867f3f3fa..3917469b31 100644 --- a/crates/relayer/src/config/gas_multiplier.rs +++ b/crates/relayer/src/config/gas_multiplier.rs @@ -1,12 +1,6 @@ use serde::{ - de::{ - Error as _, - Unexpected, - }, - Deserialize, - Deserializer, - Serialize, - Serializer, + de::{Error as _, Unexpected}, + Deserialize, Deserializer, Serialize, Serializer, }; flex_error::define_error! { diff --git a/crates/relayer/src/config/proof_specs.rs b/crates/relayer/src/config/proof_specs.rs index ff278f65ee..e953b6e00a 100644 --- a/crates/relayer/src/config/proof_specs.rs +++ b/crates/relayer/src/config/proof_specs.rs @@ -3,12 +3,7 @@ use core::fmt; use ibc_relayer_types::core::ics23_commitment::specs::ProofSpecs; -use serde::{ - de, - ser, - Deserializer, - Serializer, -}; +use serde::{de, ser, Deserializer, Serializer}; pub fn serialize( proof_specs: &Option, diff --git a/crates/relayer/src/config/refresh_rate.rs b/crates/relayer/src/config/refresh_rate.rs index 0c14d6c84f..c3d359f830 100644 --- a/crates/relayer/src/config/refresh_rate.rs +++ b/crates/relayer/src/config/refresh_rate.rs @@ -1,11 +1,6 @@ use std::str::FromStr; -use serde::{ - Deserialize, - Deserializer, - Serialize, - Serializer, -}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct RefreshRate { diff --git a/crates/relayer/src/config/types.rs b/crates/relayer/src/config/types.rs index 4eb5670bbb..fc2394be22 100644 --- a/crates/relayer/src/config/types.rs +++ b/crates/relayer/src/config/types.rs @@ -57,14 +57,8 @@ pub mod max_msg_num { } use serde::{ - de::{ - Error as _, - Unexpected, - }, - Deserialize, - Deserializer, - Serialize, - Serializer, + de::{Error as _, Unexpected}, + Deserialize, Deserializer, Serialize, Serializer, }; impl<'de> Deserialize<'de> for MaxMsgNum { @@ -152,14 +146,8 @@ pub mod max_tx_size { } use serde::{ - de::{ - Error as _, - Unexpected, - }, - Deserialize, - Deserializer, - Serialize, - Serializer, + de::{Error as _, Unexpected}, + Deserialize, Deserializer, Serialize, Serializer, }; impl<'de> Deserialize<'de> for MaxTxSize { @@ -244,13 +232,7 @@ pub mod memo { } } - use serde::{ - de::Error as _, - Deserialize, - Deserializer, - Serialize, - Serializer, - }; + use serde::{de::Error as _, Deserialize, Deserializer, Serialize, Serializer}; impl<'de> Deserialize<'de> for Memo { fn deserialize(deserializer: D) -> Result @@ -277,11 +259,7 @@ pub mod memo { } } - use core::fmt::{ - Display, - Error as FmtError, - Formatter, - }; + use core::fmt::{Display, Error as FmtError, Formatter}; impl Display for Memo { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { @@ -294,10 +272,7 @@ pub mod ics20_field_size_limit { use std::fmt::Display; use byte_unit::Byte; - use serde_derive::{ - Deserialize, - Serialize, - }; + use serde_derive::{Deserialize, Serialize}; pub enum ValidationResult { Valid, diff --git a/crates/relayer/src/connection.rs b/crates/relayer/src/connection.rs index 2babdbea3d..15e850ec83 100644 --- a/crates/relayer/src/connection.rs +++ b/crates/relayer/src/connection.rs @@ -1,9 +1,5 @@ use core::{ - fmt::{ - Display, - Error as FmtError, - Formatter, - }, + fmt::{Display, Error as FmtError, Formatter}, time::Duration, }; use std::thread; @@ -13,63 +9,35 @@ use ibc_relayer_types::{ core::{ ics02_client::height::Height, ics03_connection::{ - connection::{ - ConnectionEnd, - Counterparty, - IdentifiedConnectionEnd, - State, - }, + connection::{ConnectionEnd, Counterparty, IdentifiedConnectionEnd, State}, msgs::{ - conn_open_ack::MsgConnectionOpenAck, - conn_open_confirm::MsgConnectionOpenConfirm, - conn_open_init::MsgConnectionOpenInit, - conn_open_try::MsgConnectionOpenTry, + conn_open_ack::MsgConnectionOpenAck, conn_open_confirm::MsgConnectionOpenConfirm, + conn_open_init::MsgConnectionOpenInit, conn_open_try::MsgConnectionOpenTry, }, }, - ics24_host::identifier::{ - ClientId, - ConnectionId, - }, + ics24_host::identifier::{ClientId, ConnectionId}, }, events::IbcEvent, timestamp::ZERO_DURATION, tx_msg::Msg, }; use serde::Serialize; -use tracing::{ - debug, - error, - info, - warn, -}; +use tracing::{debug, error, info, warn}; use crate::{ chain::{ counterparty::connection_state_on_destination, handle::ChainHandle, requests::{ - IncludeProof, - PageRequest, - QueryConnectionRequest, - QueryConnectionsRequest, - QueryHeight, + IncludeProof, PageRequest, QueryConnectionRequest, QueryConnectionsRequest, QueryHeight, }, tracking::TrackedMsgs, }, - foreign_client::{ - ForeignClient, - HasExpiredOrFrozenError, - }, + foreign_client::{ForeignClient, HasExpiredOrFrozenError}, object::Connection as WorkerConnectionObject, util::{ - pretty::{ - PrettyDuration, - PrettyOption, - }, - retry::{ - retry_with_index, - RetryResult, - }, + pretty::{PrettyDuration, PrettyOption}, + retry::{retry_with_index, RetryResult}, task::Next, }, }; @@ -84,36 +52,32 @@ mod handshake_retry { //! Provides utility methods and constants to configure the retry behavior //! for the connection handshake algorithm. + use crate::connection::ConnectionError; + use crate::util::retry::{clamp, ConstantGrowth}; use core::time::Duration; - use crate::{ - connection::ConnectionError, - util::retry::{ - clamp_total, - ConstantGrowth, - }, - }; + use crate::util::retry::clamp_total; /// Approximate number of retries per block. - const PER_BLOCK_RETRIES: u32 = 10; + const PER_BLOCK_RETRIES: u32 = 5; /// Defines the increment in delay between subsequent retries. /// A value of `0` will make the retry delay constant. - const DELAY_INCREMENT: u64 = 0; + const DELAY_INCREMENT: Duration = Duration::from_secs(0); - /// Maximum retry delay expressed in number of blocks - const BLOCK_NUMBER_DELAY: u32 = 10; + /// Maximum number of retries + const MAX_RETRIES: u32 = 10; /// The default retry strategy. /// We retry with a constant backoff strategy. The strategy is parametrized by the /// maximum block time expressed as a `Duration`. - pub fn default_strategy(max_block_times: Duration) -> impl Iterator { - let retry_delay = max_block_times / PER_BLOCK_RETRIES; + pub fn default_strategy(max_block_time: Duration) -> impl Iterator { + let retry_delay = max_block_time / PER_BLOCK_RETRIES; - clamp_total( - ConstantGrowth::new(retry_delay, Duration::from_secs(DELAY_INCREMENT)), - retry_delay, - max_block_times * BLOCK_NUMBER_DELAY, + clamp( + ConstantGrowth::new(retry_delay, DELAY_INCREMENT), + retry_delay + DELAY_INCREMENT * MAX_RETRIES, + MAX_RETRIES as usize, ) } @@ -1415,7 +1379,9 @@ fn check_destination_connection_state( && existing_connection.counterparty().client_id() == expected_connection.counterparty().client_id(); - let good_state = *existing_connection.state() as u32 <= *expected_connection.state() as u32; + let good_state = existing_connection + .state() + .less_or_equal_progress(*expected_connection.state()); let good_connection_ids = existing_connection.counterparty().connection_id().is_none() || existing_connection.counterparty().connection_id() diff --git a/crates/relayer/src/connection/error.rs b/crates/relayer/src/connection/error.rs index 8b77f83bf2..cb65cf19e3 100644 --- a/crates/relayer/src/connection/error.rs +++ b/crates/relayer/src/connection/error.rs @@ -1,30 +1,17 @@ use core::time::Duration; -use flex_error::{ - define_error, - ErrorMessageTracer, -}; +use flex_error::{define_error, ErrorMessageTracer}; use ibc_relayer_types::{ core::{ - ics03_connection::connection::{ - Counterparty, - State, - }, - ics24_host::identifier::{ - ChainId, - ClientId, - ConnectionId, - }, + ics03_connection::connection::{Counterparty, State}, + ics24_host::identifier::{ChainId, ClientId, ConnectionId}, }, events::IbcEvent, }; use crate::{ error::Error as RelayerError, - foreign_client::{ - ForeignClientError, - HasExpiredOrFrozenError, - }, + foreign_client::{ForeignClientError, HasExpiredOrFrozenError}, supervisor::Error as SupervisorError, }; @@ -130,7 +117,7 @@ define_error! { destination_chain_id: ChainId } |e| { - format!("the source chain of client a ({}) does not not match the destination chain of client b ({})", + format!("the source chain of client a ({}) does not match the destination chain of client b ({})", e.source_chain_id, e.destination_chain_id) }, diff --git a/crates/relayer/src/consensus_state.rs b/crates/relayer/src/consensus_state.rs index 8f1f9f9549..500fb3bcef 100644 --- a/crates/relayer/src/consensus_state.rs +++ b/crates/relayer/src/consensus_state.rs @@ -1,64 +1,35 @@ -#[cfg(test)] -use ibc_proto::ibc::mock::ConsensusState as RawMockConsensusState; -use ibc_proto::{ - google::protobuf::Any, - ibc::{ - core::client::v1::ConsensusStateWithHeight, - lightclients::tendermint::v1::ConsensusState as RawConsensusState, - }, - Protobuf, -}; -#[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::{ - clients::ics07_tendermint::consensus_state::{ - ConsensusState as TmConsensusState, - TENDERMINT_CONSENSUS_STATE_TYPE_URL, - }, - core::{ - ics02_client::{ - client_type::ClientType, - consensus_state::ConsensusState, - error::Error, - }, - ics23_commitment::commitment::CommitmentRoot, - }, - timestamp::Timestamp, - Height, -}; -use serde::{ - Deserialize, - Serialize, +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; +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::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; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(tag = "type")] -#[non_exhaustive] pub enum AnyConsensusState { Tendermint(TmConsensusState), - - #[cfg(test)] - Mock(MockConsensusState), } impl AnyConsensusState { pub fn timestamp(&self) -> Timestamp { match self { Self::Tendermint(cs_state) => cs_state.timestamp.into(), - - #[cfg(test)] - Self::Mock(mock_state) => mock_state.timestamp(), } } pub fn client_type(&self) -> ClientType { match self { AnyConsensusState::Tendermint(_cs) => ClientType::Tendermint, - - #[cfg(test)] - AnyConsensusState::Mock(_cs) => ClientType::Mock, } } } @@ -77,12 +48,6 @@ impl TryFrom for AnyConsensusState { .map_err(Error::decode_raw_client_state)?, )), - #[cfg(test)] - MOCK_CONSENSUS_STATE_TYPE_URL => Ok(AnyConsensusState::Mock( - Protobuf::::decode_vec(&value.value) - .map_err(Error::decode_raw_client_state)?, - )), - _ => Err(Error::unknown_consensus_state_type(value.type_url)), } } @@ -95,22 +60,10 @@ impl From for Any { type_url: TENDERMINT_CONSENSUS_STATE_TYPE_URL.to_string(), 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), - }, } } } -#[cfg(test)] -impl From for AnyConsensusState { - fn from(cs: MockConsensusState) -> Self { - Self::Mock(cs) - } -} - impl From for AnyConsensusState { fn from(cs: TmConsensusState) -> Self { Self::Tendermint(cs) @@ -162,9 +115,6 @@ impl ConsensusState for AnyConsensusState { fn root(&self) -> &CommitmentRoot { match self { Self::Tendermint(cs_state) => cs_state.root(), - - #[cfg(test)] - Self::Mock(mock_state) => mock_state.root(), } } diff --git a/crates/relayer/src/denom.rs b/crates/relayer/src/denom.rs index 73f8f6dd63..cd6d33bcdc 100644 --- a/crates/relayer/src/denom.rs +++ b/crates/relayer/src/denom.rs @@ -1,9 +1,6 @@ //! Data structures related to the denomination of coins used by the relayer. -use serde::{ - Deserialize, - Serialize, -}; +use serde::{Deserialize, Serialize}; /// The denom trace #[derive(Clone, Debug, Serialize, Deserialize)] diff --git a/crates/relayer/src/error.rs b/crates/relayer/src/error.rs index d561524a54..c36f8b3bba 100644 --- a/crates/relayer/src/error.rs +++ b/crates/relayer/src/error.rs @@ -1,79 +1,42 @@ -//! This module defines the various errors that be raised in the relayer. - use core::time::Duration; -use flex_error::{ - define_error, - DisplayOnly, - TraceError, -}; +use flex_error::{define_error, DisplayOnly, TraceError}; use http::uri::InvalidUri; use humantime::format_duration; -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, -}; -use prost::{ - DecodeError, - EncodeError, -}; +use prost::{DecodeError, EncodeError}; use regex::Regex; -use tendermint::{ - abci, - Error as TendermintError, -}; -use tendermint_light_client::{ - builder::error::Error as LightClientBuilderError, - components::io::IoError as LightClientIoError, - errors::{ - Error as LightClientError, - ErrorDetail as LightClientErrorDetail, - }, -}; -use tendermint_proto::Error as TendermintProtoError; -use tendermint_rpc::{ - endpoint::{ - abci_query::AbciQuery, - broadcast::tx_sync::Response as TxSyncResponse, - }, - Error as TendermintRpcError, -}; use tonic::{ - metadata::errors::InvalidMetadataValue, - transport::Error as TransportError, + metadata::errors::InvalidMetadataValue, transport::Error as TransportError, Status as GrpcStatus, }; -use crate::{ - chain::cosmos::{ - version, - BLOCK_MAX_BYTES_MAX_FRACTION, - }, - config::Error as ConfigError, - event::source, - keyring::{ - errors::Error as KeyringError, - KeyType, - }, - sdk_error::SdkError, +use tendermint::abci; +use tendermint::Error as TendermintError; +use tendermint_light_client::builder::error::Error as LightClientBuilderError; +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 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; +use crate::config::Error as ConfigError; +use crate::event::source; +use crate::keyring::{errors::Error as KeyringError, KeyType}; +use crate::sdk_error::SdkError; define_error! { Error { @@ -182,6 +145,9 @@ define_error! { EmptyUpgradedClientState |_| { "found no upgraded client state" }, + EmptyConnectionParams + |_| { "connection params not found" }, + ConsensusStateTypeMismatch { expected: ClientType, @@ -429,7 +395,6 @@ define_error! { address: String, endpoint: String, } - [ DisplayOnly ] |e| { format!("failed while fetching version info from endpoint {0} on the gRPC interface of chain {1}:{2}", e.endpoint, e.chain_id, e.address) @@ -533,14 +498,14 @@ define_error! { format!("semantic config validation failed for option `gas_multiplier` of chain '{}', reason: gas multiplier ({}) is smaller than `1.1`, which could trigger gas fee errors in production", e.chain_id, e.gas_multiplier) }, - SdkModuleVersion + CompatCheckFailed { chain_id: ChainId, address: String, cause: String } |e| { - format!("Hermes health check failed while verifying the application compatibility for chain {0}:{1}; caused by: {2}", + format!("compatibility check failed for chain '{0}' at '{1}': {2}", e.chain_id, e.address, e.cause) }, @@ -559,6 +524,10 @@ define_error! { { address: String } |e| { format!("Query/Account RPC returned an empty account for address: {}", e.address) }, + EmptyProposal + { proposal_id: String } + |e| { format!("Query/Proposal RPC returned an empty proposal for proposal id: {}", e.proposal_id) }, + NoHistoricalEntries { chain_id: ChainId } |e| { @@ -626,10 +595,50 @@ define_error! { [ 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" }, - Other { - source: Box, - } - |e| { format!("other error: {}", e.source) }, + HttpRequest + [ TraceError ] + |_| { "HTTP request error" }, + + HttpResponse + { status: reqwest::StatusCode } + |e| { format!("HTTP response error with status code {}", e.status) }, + + HttpResponseBody + [ TraceError ] + |_| { "HTTP response body error" }, + + JsonDeserialize + [ TraceError ] + |_| { "JSON deserialization error" }, + + JsonField + { field: String } + |e| { format!("Missing or invalid JSON field: {}", e.field) }, + + ParseFloat + [ TraceError ] + |_| { "Error parsing float" }, + + ParseInt + [ TraceError ] + |_| { "Error parsing integer" }, + + Base64Decode + [ TraceError ] + |_| { "Error decoding base64-encoded data" }, + + InvalidPortString + { port: String } + |e| { format!("invalid port string {}", e.port) }, + + InvalidChannelString + { channel: String } + |e| { format!("invalid channel string {}", e.channel) }, + + Other { + source: Box, + } + |e| { format!("other error: {}", e.source) }, } } @@ -721,6 +730,14 @@ impl GrpcStatusSubdetail { Some((expected, got)) => expected < got, } } + + /// Check whether this gRPC error message contains the string "invalid empty tx". + /// + /// ## Note + /// This error may happen for older chains that does not properly support simulation. + pub fn is_empty_tx_error(&self) -> bool { + self.status.message().contains("invalid empty tx") + } } /// Assumes that the cosmos-sdk account sequence mismatch error message, that may be seen diff --git a/crates/relayer/src/event.rs b/crates/relayer/src/event.rs index fa3fff5e54..f5219f4750 100644 --- a/crates/relayer/src/event.rs +++ b/crates/relayer/src/event.rs @@ -1,57 +1,39 @@ -use core::fmt::{ - Display, - Error as FmtError, - Formatter, -}; +use core::fmt::{Display, Error as FmtError, Formatter}; +use serde::Serialize; +use std::str::FromStr; +use subtle_encoding::hex; +use tendermint::abci::Event as AbciEvent; use ibc_relayer_types::{ applications::{ - ics29_fee::events::{ - DistributeFeePacket, - IncentivizedPacket, - }, + ics29_fee::events::{DistributeFeePacket, IncentivizedPacket}, ics31_icq::events::CrossChainQueryPacket, }, core::{ ics02_client::{ error::Error as ClientError, - events::{ - self as client_events, - Attributes as ClientAttributes, - HEADER_ATTRIBUTE_KEY, - }, - header::{ - decode_header, - AnyHeader, - }, + events::{self as client_events, Attributes as ClientAttributes, HEADER_ATTRIBUTE_KEY}, + header::{decode_header, AnyHeader}, height::HeightErrorDetail, }, ics03_connection::{ error::Error as ConnectionError, - events::{ - self as connection_events, - Attributes as ConnectionAttributes, - }, + events::{self as connection_events, Attributes as ConnectionAttributes}, }, ics04_channel::{ error::Error as ChannelError, events::{ - self as channel_events, - Attributes as ChannelAttributes, + self as channel_events, Attributes as ChannelAttributes, + UpgradeAttributes as ChannelUpgradeAttributes, }, - packet::Packet, + packet::{Packet, Sequence}, timeout::TimeoutHeight, }, }, - events::{ - Error as IbcEventError, - IbcEvent, - IbcEventType, - }, + events::{Error as IbcEventError, IbcEvent, IbcEventType}, + timestamp::Timestamp, Height, }; -use serde::Serialize; -use tendermint::abci::Event as AbciEvent; pub mod bus; pub mod error; @@ -136,6 +118,34 @@ pub fn ibc_event_try_from_abci_event(abci_event: &AbciEvent) -> Result Ok(IbcEvent::UpgradeInitChannel( + channel_upgrade_init_try_from_abci_event(abci_event).map_err(IbcEventError::channel)?, + )), + Ok(IbcEventType::UpgradeTryChannel) => Ok(IbcEvent::UpgradeTryChannel( + channel_upgrade_try_try_from_abci_event(abci_event).map_err(IbcEventError::channel)?, + )), + Ok(IbcEventType::UpgradeAckChannel) => Ok(IbcEvent::UpgradeAckChannel( + channel_upgrade_ack_try_from_abci_event(abci_event).map_err(IbcEventError::channel)?, + )), + Ok(IbcEventType::UpgradeConfirmChannel) => Ok(IbcEvent::UpgradeConfirmChannel( + channel_upgrade_confirm_try_from_abci_event(abci_event) + .map_err(IbcEventError::channel)?, + )), + Ok(IbcEventType::UpgradeOpenChannel) => Ok(IbcEvent::UpgradeOpenChannel( + channel_upgrade_open_try_from_abci_event(abci_event).map_err(IbcEventError::channel)?, + )), + Ok(IbcEventType::UpgradeCancelChannel) => Ok(IbcEvent::UpgradeCancelChannel( + channel_upgrade_cancelled_try_from_abci_event(abci_event) + .map_err(IbcEventError::channel)?, + )), + Ok(IbcEventType::UpgradeTimeoutChannel) => Ok(IbcEvent::UpgradeTimeoutChannel( + channel_upgrade_timeout_try_from_abci_event(abci_event) + .map_err(IbcEventError::channel)?, + )), + Ok(IbcEventType::UpgradeErrorChannel) => Ok(IbcEvent::UpgradeErrorChannel( + channel_upgrade_error_try_from_abci_event(abci_event) + .map_err(IbcEventError::channel)?, + )), Ok(IbcEventType::SendPacket) => Ok(IbcEvent::SendPacket( send_packet_try_from_abci_event(abci_event).map_err(IbcEventError::channel)?, )), @@ -277,6 +287,86 @@ pub fn channel_close_confirm_try_from_abci_event( } } +pub fn channel_upgrade_init_try_from_abci_event( + abci_event: &AbciEvent, +) -> Result { + match channel_upgrade_extract_attributes_from_tx(abci_event) { + Ok(attrs) => channel_events::UpgradeInit::try_from(attrs) + .map_err(|_| ChannelError::implementation_specific()), + Err(e) => Err(e), + } +} + +pub fn channel_upgrade_try_try_from_abci_event( + abci_event: &AbciEvent, +) -> Result { + match channel_upgrade_extract_attributes_from_tx(abci_event) { + Ok(attrs) => channel_events::UpgradeTry::try_from(attrs) + .map_err(|_| ChannelError::implementation_specific()), + Err(e) => Err(e), + } +} + +pub fn channel_upgrade_ack_try_from_abci_event( + abci_event: &AbciEvent, +) -> Result { + match channel_upgrade_extract_attributes_from_tx(abci_event) { + Ok(attrs) => channel_events::UpgradeAck::try_from(attrs) + .map_err(|_| ChannelError::implementation_specific()), + Err(e) => Err(e), + } +} + +pub fn channel_upgrade_confirm_try_from_abci_event( + abci_event: &AbciEvent, +) -> Result { + match channel_upgrade_extract_attributes_from_tx(abci_event) { + Ok(attrs) => channel_events::UpgradeConfirm::try_from(attrs) + .map_err(|_| ChannelError::implementation_specific()), + Err(e) => Err(e), + } +} + +pub fn channel_upgrade_open_try_from_abci_event( + abci_event: &AbciEvent, +) -> Result { + match channel_upgrade_extract_attributes_from_tx(abci_event) { + Ok(attrs) => channel_events::UpgradeOpen::try_from(attrs) + .map_err(|_| ChannelError::implementation_specific()), + Err(e) => Err(e), + } +} + +pub fn channel_upgrade_cancelled_try_from_abci_event( + abci_event: &AbciEvent, +) -> Result { + match channel_upgrade_extract_attributes_from_tx(abci_event) { + Ok(attrs) => channel_events::UpgradeCancel::try_from(attrs) + .map_err(|_| ChannelError::implementation_specific()), + Err(e) => Err(e), + } +} + +pub fn channel_upgrade_timeout_try_from_abci_event( + abci_event: &AbciEvent, +) -> Result { + match channel_upgrade_extract_attributes_from_tx(abci_event) { + Ok(attrs) => channel_events::UpgradeTimeout::try_from(attrs) + .map_err(|_| ChannelError::implementation_specific()), + Err(e) => Err(e), + } +} + +pub fn channel_upgrade_error_try_from_abci_event( + abci_event: &AbciEvent, +) -> Result { + match channel_upgrade_extract_attributes_from_tx(abci_event) { + Ok(attrs) => channel_events::UpgradeError::try_from(attrs) + .map_err(|_| ChannelError::implementation_specific()), + Err(e) => Err(e), + } +} + pub fn send_packet_try_from_abci_event( abci_event: &AbciEvent, ) -> Result { @@ -328,8 +418,14 @@ fn client_extract_attributes_from_tx(event: &AbciEvent) -> Result { attr.client_id = value @@ -355,9 +451,13 @@ fn client_extract_attributes_from_tx(event: &AbciEvent) -> Result Result { for tag in &event.attributes { - if tag.key == HEADER_ATTRIBUTE_KEY { - let header_bytes = - hex::decode(&tag.value).map_err(|_| ClientError::malformed_header())?; + if tag.key_bytes() == HEADER_ATTRIBUTE_KEY.as_bytes() { + let header_bytes = hex::decode( + tag.value_str() + .map_err(|_| ClientError::malformed_header())? + .to_lowercase(), + ) + .map_err(|_| ClientError::malformed_header())?; return decode_header(&header_bytes); } } @@ -371,8 +471,14 @@ fn connection_extract_attributes_from_tx( let mut attr = ConnectionAttributes::default(); for tag in &event.attributes { - let key = tag.key.as_str(); - let value = tag.value.as_str(); + let key = tag + .key_str() + .map_err(|_| ConnectionError::malformed_event_attribute_key())?; + + let value = tag + .value_str() + .map_err(|_| ConnectionError::malformed_event_attribute_value(key.to_owned()))?; + match key { connection_events::CONN_ID_ATTRIBUTE_KEY => { attr.connection_id = value.parse().ok(); @@ -400,8 +506,14 @@ fn channel_extract_attributes_from_tx( let mut attr = ChannelAttributes::default(); for tag in &event.attributes { - let key = tag.key.as_str(); - let value = tag.value.as_str(); + let key = tag + .key_str() + .map_err(|_| ChannelError::malformed_event_attribute_key())?; + + let value = tag + .value_str() + .map_err(|_| ChannelError::malformed_event_attribute_value(key.to_owned()))?; + match key { channel_events::PORT_ID_ATTRIBUTE_KEY => { attr.port_id = value.parse().map_err(ChannelError::identifier)? @@ -425,14 +537,73 @@ fn channel_extract_attributes_from_tx( Ok(attr) } +fn channel_upgrade_extract_attributes_from_tx( + event: &AbciEvent, +) -> Result { + let mut attr = ChannelUpgradeAttributes::default(); + + for tag in &event.attributes { + let key = tag + .key_str() + .map_err(|_| ChannelError::malformed_event_attribute_key())?; + + let value = tag + .value_str() + .map_err(|_| ChannelError::malformed_event_attribute_value(key.to_owned()))?; + + match key { + channel_events::PORT_ID_ATTRIBUTE_KEY => { + attr.port_id = value.parse().map_err(ChannelError::identifier)? + } + channel_events::CHANNEL_ID_ATTRIBUTE_KEY => { + attr.channel_id = value.parse().map_err(ChannelError::identifier)?; + } + channel_events::COUNTERPARTY_PORT_ID_ATTRIBUTE_KEY => { + attr.counterparty_port_id = value.parse().map_err(ChannelError::identifier)?; + } + channel_events::COUNTERPARTY_CHANNEL_ID_ATTRIBUTE_KEY => { + attr.counterparty_channel_id = value.parse().ok(); + } + channel_events::UPGRADE_SEQUENCE => { + attr.upgrade_sequence = + Sequence::from(value.parse::().map_err(|e| { + ChannelError::invalid_string_as_sequence(value.to_string(), e) + })?); + } + channel_events::UPGRADE_TIMEOUT_HEIGHT => { + let maybe_height = Height::from_str(value).ok(); + attr.upgrade_timeout_height = maybe_height; + } + channel_events::UPGRADE_TIMEOUT_TIMESTAMP => { + let maybe_timestamp = Timestamp::from_str(value).ok(); + attr.upgrade_timeout_timestamp = maybe_timestamp; + } + channel_events::UPGRADE_ERROR_RECEIPT => { + let maybe_error_receipt = value.to_string(); + attr.error_receipt = Some(maybe_error_receipt); + } + _ => {} + } + } + + Ok(attr) +} + pub fn extract_packet_and_write_ack_from_tx( event: &AbciEvent, ) -> Result<(Packet, Vec), ChannelError> { let mut packet = Packet::default(); let mut write_ack: Vec = Vec::new(); + for tag in &event.attributes { - let key = tag.key.as_str(); - let value = tag.value.as_str(); + let key = tag + .key_str() + .map_err(|_| ChannelError::malformed_event_attribute_key())?; + + let value = tag + .value_str() + .map_err(|_| ChannelError::malformed_event_attribute_value(key.to_owned()))?; + match key { channel_events::PKT_SRC_PORT_ATTRIBUTE_KEY => { packet.source_port = value.parse().map_err(ChannelError::identifier)?; @@ -459,10 +630,12 @@ pub fn extract_packet_and_write_ack_from_tx( packet.timeout_timestamp = value.parse().unwrap(); } channel_events::PKT_DATA_ATTRIBUTE_KEY => { - packet.data = Vec::from(value.as_bytes()); + packet.data = hex::decode(value.to_lowercase()) + .map_err(|_| ChannelError::invalid_packet_data(value.to_string()))?; } channel_events::PKT_ACK_ATTRIBUTE_KEY => { - write_ack = Vec::from(value.as_bytes()); + write_ack = hex::decode(value.to_lowercase()) + .map_err(|_| ChannelError::invalid_packet_ack(value.to_string()))?; } _ => {} } @@ -487,36 +660,8 @@ pub fn parse_timeout_height(s: &str) -> Result { #[cfg(test)] mod tests { - use ibc_proto::{ - google::protobuf::Any, - Protobuf, - }; - use ibc_relayer_types::{ - clients::ics07_tendermint::header::test_util::get_dummy_ics07_header, - core::{ - ics02_client::header::{ - decode_header, - AnyHeader, - }, - ics04_channel::packet::Sequence, - }, - timestamp::Timestamp, - }; - use super::*; - #[test] - fn extract_header() { - let header = get_dummy_ics07_header(); - let mut header_bytes = Vec::new(); - Protobuf::::encode(header.clone(), &mut header_bytes).unwrap(); - - let decoded_dyn_header = decode_header(&header_bytes).unwrap(); - let AnyHeader::Tendermint(decoded_tm_header) = decoded_dyn_header; - - assert_eq!(header, decoded_tm_header); - } - #[test] fn connection_event_to_abci_event() { let attributes = ConnectionAttributes { diff --git a/crates/relayer/src/event/bus.rs b/crates/relayer/src/event/bus.rs index d302e542fc..b7486ed693 100644 --- a/crates/relayer/src/event/bus.rs +++ b/crates/relayer/src/event/bus.rs @@ -47,10 +47,7 @@ impl EventBus { #[cfg(test)] mod tests { - use core::sync::atomic::{ - AtomicUsize, - Ordering, - }; + use core::sync::atomic::{AtomicUsize, Ordering}; use serial_test::serial; use test_log::test; diff --git a/crates/relayer/src/event/error.rs b/crates/relayer/src/event/error.rs index d81607d13e..8ec9592ffe 100644 --- a/crates/relayer/src/event/error.rs +++ b/crates/relayer/src/event/error.rs @@ -1,12 +1,6 @@ -use flex_error::{ - define_error, - TraceError, -}; +use flex_error::{define_error, TraceError}; use ibc_relayer_types::core::ics24_host::identifier::ChainId; -use tendermint_rpc::{ - Error as RpcError, - WebSocketClientUrl, -}; +use tendermint_rpc::{Error as RpcError, WebSocketClientUrl}; define_error! { #[derive(Debug, Clone)] diff --git a/crates/relayer/src/event/source.rs b/crates/relayer/src/event/source.rs index 1b62ae276f..58cc3e9537 100644 --- a/crates/relayer/src/event/source.rs +++ b/crates/relayer/src/event/source.rs @@ -1,35 +1,19 @@ pub mod rpc; pub mod websocket; -use std::{ - sync::Arc, - time::Duration, -}; +use std::{sync::Arc, time::Duration}; use crossbeam_channel as channel; use futures::Stream; -use ibc_relayer_types::core::{ - ics02_client::height::Height, - ics24_host::identifier::ChainId, -}; +use ibc_relayer_types::core::{ics02_client::height::Height, ics24_host::identifier::ChainId}; use tendermint_rpc::{ - client::CompatMode, - event::Event as RpcEvent, - Error as RpcError, - HttpClient, - WebSocketClientUrl, + client::CompatMode, event::Event as RpcEvent, Error as RpcError, HttpClient, WebSocketClientUrl, }; use tokio::runtime::Runtime as TokioRuntime; -pub use super::error::{ - Error, - ErrorDetail, -}; +pub use super::error::{Error, ErrorDetail}; use super::IbcEventWithHeight; -use crate::chain::{ - handle::Subscription, - tracking::TrackingId, -}; +use crate::chain::{handle::Subscription, tracking::TrackingId}; pub type Result = core::result::Result; @@ -58,9 +42,11 @@ impl EventSource { chain_id: ChainId, rpc_client: HttpClient, poll_interval: Duration, + max_retries: u32, rt: Arc, ) -> Result<(Self, TxEventSourceCmd)> { - let (source, tx) = rpc::EventSource::new(chain_id, rpc_client, poll_interval, rt)?; + let (source, tx) = + rpc::EventSource::new(chain_id, rpc_client, poll_interval, max_retries, rt)?; Ok((Self::Rpc(source), tx)) } @@ -117,10 +103,7 @@ pub enum EventSourceCmd { // TODO: These are SDK specific, should be eventually moved. pub mod queries { - use tendermint_rpc::query::{ - EventType, - Query, - }; + use tendermint_rpc::query::{EventType, Query}; pub fn all() -> Vec { // Note: Tendermint-go supports max 5 query specifiers! diff --git a/crates/relayer/src/event/source/rpc.rs b/crates/relayer/src/event/source/rpc.rs index 2e40d33956..2694d43ec7 100644 --- a/crates/relayer/src/event/source/rpc.rs +++ b/crates/relayer/src/event/source/rpc.rs @@ -5,50 +5,24 @@ use std::sync::Arc; use crossbeam_channel as channel; use ibc_relayer_types::{ core::{ - ics02_client::{ - events::NewBlock, - height::Height, - }, + ics02_client::{events::NewBlock, height::Height}, ics24_host::identifier::ChainId, }, events::IbcEvent, }; -use tendermint::{ - abci, - block::Height as BlockHeight, -}; -use tendermint_rpc::{ - Client, - HttpClient, -}; +use tendermint::{abci, block::Height as BlockHeight}; +use tendermint_rpc::{Client, HttpClient}; use tokio::{ runtime::Runtime as TokioRuntime, - time::{ - sleep, - Duration, - Instant, - }, -}; -use tracing::{ - debug, - error, - error_span, - trace, + time::{sleep, Duration, Instant}, }; +use tracing::{debug, error, error_span, trace}; use self::extract::extract_events; -use super::{ - EventBatch, - EventSourceCmd, - TxEventSourceCmd, -}; +use super::{EventBatch, EventSourceCmd, TxEventSourceCmd}; use crate::{ chain::tracking::TrackingId, - event::{ - bus::EventBus, - source::Error, - IbcEventWithHeight, - }, + event::{bus::EventBus, error::ErrorDetail, source::Error, IbcEventWithHeight}, telemetry, util::retry::ConstantGrowth, }; @@ -66,6 +40,9 @@ pub struct EventSource { /// Poll interval poll_interval: Duration, + /// Max retries to collect events + max_retries: u32, + /// Event bus for broadcasting events event_bus: EventBus>>, @@ -84,6 +61,7 @@ impl EventSource { chain_id: ChainId, rpc_client: HttpClient, poll_interval: Duration, + max_retries: u32, rt: Arc, ) -> Result<(Self, TxEventSourceCmd)> { let event_bus = EventBus::new(); @@ -94,6 +72,7 @@ impl EventSource { chain_id, rpc_client, poll_interval, + max_retries, event_bus, rx_cmd, last_fetched_height: BlockHeight::from(0_u32), @@ -224,19 +203,38 @@ impl EventSource { for height in heights { trace!("collecting events at height {height}"); - let result = collect_events(&self.rpc_client, &self.chain_id, height).await; + let mut attempts = 0; + let mut backoff = retries_backoff(self.max_retries); + + // NOTE: Even if we failed to collect events after max retries, + // we still need to update to move on next block + self.last_fetched_height = height; - match result { - Ok(batch) => { - self.last_fetched_height = height; + loop { + attempts += 1; - if let Some(batch) = batch { - batches.push(batch); + match collect_events(&self.rpc_client, &self.chain_id, height).await { + Ok(batch) => { + if let Some(batch) = batch { + batches.push(batch); + } + break; } - } - Err(e) => { - error!(%height, "failed to collect events: {e}"); - break; + Err(e) => match e.detail() { + ErrorDetail::Rpc(_) if attempts < self.max_retries => { + let delay = backoff.next().expect( + "backoff has attempted to make more iterates than is expected", + ); + + error!(%height, "failed to collect events: {e}, retrying in {delay:?}..."); + sleep(delay).await; + } + + _ => { + error!(%height, "failed to collect events after {attempts} attempts: {e}"); + break; + } + }, } } } @@ -265,11 +263,13 @@ fn poll_backoff(poll_interval: Duration) -> impl Iterator { .clamp(poll_interval * 5, usize::MAX) } +fn retries_backoff(collect_retries: u32) -> impl Iterator { + ConstantGrowth::new(Duration::from_secs(1), Duration::from_millis(500)) + .clamp(Duration::from_secs(4), collect_retries as usize) +} + fn dedupe(events: Vec) -> Vec { - use std::hash::{ - Hash, - Hasher, - }; + use std::hash::{Hash, Hasher}; use itertools::Itertools; @@ -288,7 +288,9 @@ fn dedupe(events: Vec) -> Vec { .attributes .iter() .zip(other.0.attributes.iter()) - .all(|(a, b)| a.key == b.key && a.value == b.value) + .all(|(a, b)| { + a.key_bytes() == b.key_bytes() && a.value_bytes() == b.value_bytes() + }) } } @@ -300,8 +302,8 @@ fn dedupe(events: Vec) -> Vec { for attr in &self.0.attributes { // NOTE: We don't hash the index because it is not deterministic - attr.key.hash(state); - attr.value.hash(state); + attr.key_bytes().hash(state); + attr.value_bytes().hash(state); } } } diff --git a/crates/relayer/src/event/source/rpc/extract.rs b/crates/relayer/src/event/source/rpc/extract.rs index 43188c33c4..819194c4b0 100644 --- a/crates/relayer/src/event/source/rpc/extract.rs +++ b/crates/relayer/src/event/source/rpc/extract.rs @@ -1,20 +1,13 @@ -use ibc_relayer_types::{ - applications::ics29_fee::events::DistributionType, - core::{ - ics02_client::height::Height, - ics24_host::identifier::ChainId, - }, - events::IbcEvent, -}; use tendermint::abci; -use crate::{ - event::{ - ibc_event_try_from_abci_event, - IbcEventWithHeight, - }, - telemetry, -}; +use ibc_relayer_types::applications::ics29_fee::events::DistributionType; +use ibc_relayer_types::core::ics02_client::height::Height; +use ibc_relayer_types::core::ics24_host::identifier::ChainId; +use ibc_relayer_types::events::IbcEvent; + +use crate::telemetry; + +use crate::event::{ibc_event_try_from_abci_event, IbcEventWithHeight}; pub fn extract_events( _chain_id: &ChainId, diff --git a/crates/relayer/src/event/source/websocket.rs b/crates/relayer/src/event/source/websocket.rs index db32ed5928..71b7a6dbda 100644 --- a/crates/relayer/src/event/source/websocket.rs +++ b/crates/relayer/src/event/source/websocket.rs @@ -7,61 +7,25 @@ use std::time::Duration; use crossbeam_channel as channel; use futures::{ pin_mut, - stream::{ - self, - select_all, - StreamExt, - }, - Stream, - TryStreamExt, -}; -use ibc_relayer_types::{ - core::ics24_host::identifier::ChainId, - events::IbcEvent, + stream::{self, select_all, StreamExt}, + Stream, TryStreamExt, }; +use ibc_relayer_types::{core::ics24_host::identifier::ChainId, events::IbcEvent}; use tendermint_rpc::{ - client::CompatMode, - event::Event as RpcEvent, - query::Query, - SubscriptionClient, - WebSocketClient, - WebSocketClientDriver, - WebSocketClientUrl, -}; -use tokio::{ - runtime::Runtime as TokioRuntime, - sync::mpsc, - task::JoinHandle, -}; -use tracing::{ - debug, - error, - info, - instrument, - trace, + client::CompatMode, event::Event as RpcEvent, query::Query, SubscriptionClient, + WebSocketClient, WebSocketClientDriver, WebSocketClientUrl, }; +use tokio::{runtime::Runtime as TokioRuntime, sync::mpsc, task::JoinHandle}; +use tracing::{debug, error, info, instrument, trace}; use self::extract::extract_events; -use super::{ - EventBatch, - EventSourceCmd, - Result, - SubscriptionStream, - TxEventSourceCmd, -}; +use super::{EventBatch, EventSourceCmd, Result, SubscriptionStream, TxEventSourceCmd}; use crate::{ chain::tracking::TrackingId, - event::{ - bus::EventBus, - error::*, - IbcEventWithHeight, - }, + event::{bus::EventBus, error::*, IbcEventWithHeight}, telemetry, util::{ - retry::{ - retry_with_index, - RetryResult, - }, + retry::{retry_with_index, RetryResult}, stream::try_group_while_timeout, }, }; @@ -164,7 +128,7 @@ impl EventSource { rx_cmd, ws_url, rpc_compat, - subscriptions: Box::new(futures::stream::empty()), + subscriptions: Box::new(stream::empty()), }; Ok((source, TxEventSourceCmd(tx_cmd))) @@ -330,8 +294,7 @@ impl EventSource { async fn run_loop(&mut self) -> Next { // Take ownership of the subscriptions - let subscriptions = - core::mem::replace(&mut self.subscriptions, Box::new(futures::stream::empty())); + let subscriptions = core::mem::replace(&mut self.subscriptions, Box::new(stream::empty())); // Convert the stream of RPC events into a stream of event batches. let batches = stream_batches(subscriptions, self.chain_id.clone(), self.batch_delay); diff --git a/crates/relayer/src/event/source/websocket/extract.rs b/crates/relayer/src/event/source/websocket/extract.rs index 0fcedb8fd5..ddc692054d 100644 --- a/crates/relayer/src/event/source/websocket/extract.rs +++ b/crates/relayer/src/event/source/websocket/extract.rs @@ -1,35 +1,20 @@ use alloc::collections::BTreeMap as HashMap; -use core::convert::TryFrom; +use ibc_relayer_types::applications::ics29_fee::events::DistributionType; -use ibc_relayer_types::{ - applications::{ - ics29_fee::events::DistributionType, - ics31_icq::events::CrossChainQueryPacket, - }, - core::{ - ics02_client::{ - events as ClientEvents, - height::Height, - }, - ics04_channel::events as ChannelEvents, - ics24_host::identifier::ChainId, - }, - events::IbcEvent, -}; -use tendermint_rpc::event::{ - Event as RpcEvent, - EventData as RpcEventData, -}; +use ibc_relayer_types::applications::ics31_icq; +use tendermint_rpc::{event::Event as RpcEvent, event::EventData as RpcEventData}; -use crate::{ - chain::cosmos::types::events::channel::RawObject, - event::{ - ibc_event_try_from_abci_event, - source::queries, - IbcEventWithHeight, - }, - telemetry, -}; +use ibc_relayer_types::applications::ics31_icq::events::CrossChainQueryPacket; +use ibc_relayer_types::core::ics02_client::{events as ClientEvents, height::Height}; +use ibc_relayer_types::core::ics04_channel::events as ChannelEvents; +use ibc_relayer_types::core::ics24_host::identifier::ChainId; +use ibc_relayer_types::events::IbcEvent; + +use crate::chain::cosmos::types::events::channel::RawObject; +use crate::event::source::queries; +use crate::telemetry; + +use crate::event::{ibc_event_try_from_abci_event, IbcEventWithHeight}; /// Extract IBC events from Tendermint RPC events /// @@ -250,6 +235,12 @@ fn event_is_type_channel(ev: &IbcEvent) -> bool { | IbcEvent::OpenConfirmChannel(_) | IbcEvent::CloseInitChannel(_) | IbcEvent::CloseConfirmChannel(_) + | IbcEvent::UpgradeInitChannel(_) + | IbcEvent::UpgradeTryChannel(_) + | IbcEvent::UpgradeAckChannel(_) + | IbcEvent::UpgradeConfirmChannel(_) + | IbcEvent::UpgradeOpenChannel(_) + | IbcEvent::UpgradeErrorChannel(_) | IbcEvent::SendPacket(_) | IbcEvent::ReceivePacket(_) | IbcEvent::WriteAcknowledgement(_) @@ -329,9 +320,14 @@ fn extract_block_events( extract_events(height, block_events, "channel_open_confirm", "channel_id"), height, ); + append_events::( + &mut events, + extract_events(height, block_events, "channel_upgrade_init", "channel_id"), + height, + ); append_events::( &mut events, - extract_events(height, block_events, "send_packet", "packet_data"), + extract_events(height, block_events, "send_packet", "packet_data_hex"), height, ); append_events::( @@ -344,10 +340,17 @@ fn extract_block_events( extract_events(height, block_events, "channel_close_confirm", "channel_id"), height, ); - // extract cross chain query event from block_events - if let Ok(ccq) = CrossChainQueryPacket::extract_query_event(block_events) { - events.push(IbcEventWithHeight::new(ccq, height)); - } + + append_events::( + &mut events, + extract_events( + height, + block_events, + ics31_icq::events::EVENT_TYPE_PREFIX, + "query_id", + ), + height, + ); events } diff --git a/crates/relayer/src/extension_options.rs b/crates/relayer/src/extension_options.rs index ceff3c50e3..f5eda5c08c 100644 --- a/crates/relayer/src/extension_options.rs +++ b/crates/relayer/src/extension_options.rs @@ -1,9 +1,6 @@ use ibc_proto::google::protobuf::Any; use prost::Message; -use serde_derive::{ - Deserialize, - Serialize, -}; +use serde_derive::{Deserialize, Serialize}; use crate::error::Error; @@ -12,7 +9,7 @@ use crate::error::Error; #[derive(Clone, PartialEq, Eq, Message, Serialize, Deserialize)] pub struct ExtensionOptionDynamicFeeTx { #[prost(string, tag = "1")] - pub max_priority_price: ::prost::alloc::string::String, + pub max_priority_price: String, } impl ExtensionOptionDynamicFeeTx { diff --git a/crates/relayer/src/foreign_client.rs b/crates/relayer/src/foreign_client.rs index eb1bb88fa2..e345b5727d 100644 --- a/crates/relayer/src/foreign_client.rs +++ b/crates/relayer/src/foreign_client.rs @@ -4,14 +4,8 @@ //! i.e. they are *foreign* to the relayer. In contrast, the term "local client" //! refers to light clients running *locally* as part of the relayer. -use core::{ - fmt, - time::Duration, -}; -use std::{ - thread, - time::Instant, -}; +use core::{fmt, time::Duration}; +use std::{thread, time::Instant}; use flex_error::define_error; use ibc_proto::google::protobuf::Any; @@ -22,69 +16,36 @@ use ibc_relayer_types::{ client_state::ClientState, error::Error as ClientError, events::UpdateClient, - header::{ - AnyHeader, - Header, - }, + header::{AnyHeader, Header}, msgs::{ - create_client::MsgCreateClient, - misbehaviour::MsgSubmitMisbehaviour, - update_client::MsgUpdateClient, - upgrade_client::MsgUpgradeClient, + create_client::MsgCreateClient, misbehaviour::MsgSubmitMisbehaviour, + update_client::MsgUpdateClient, upgrade_client::MsgUpgradeClient, }, trust_threshold::TrustThreshold, }, - ics24_host::identifier::{ - ChainId, - ClientId, - }, + ics24_host::identifier::{ChainId, ClientId}, }, downcast, - events::{ - IbcEvent, - IbcEventType, - WithBlockDataType, - }, - timestamp::{ - Timestamp, - TimestampOverflowError, - }, + events::{IbcEvent, IbcEventType, WithBlockDataType}, + timestamp::{Timestamp, TimestampOverflowError}, tx_msg::Msg, Height, }; use itertools::Itertools; -use tracing::{ - debug, - error, - info, - instrument, - trace, - warn, -}; +use tracing::{debug, error, info, instrument, trace, warn}; use crate::{ - chain::{ - client::ClientSettings, - handle::ChainHandle, - requests::*, - tracking::TrackedMsgs, - }, + chain::{client::ClientSettings, handle::ChainHandle, requests::*, tracking::TrackedMsgs}, client_state::AnyClientState, config::ChainConfig, consensus_state::AnyConsensusState, error::Error as RelayerError, event::IbcEventWithHeight, - misbehaviour::{ - AnyMisbehaviour, - MisbehaviourEvidence, - }, + misbehaviour::{AnyMisbehaviour, MisbehaviourEvidence}, telemetry, util::{ collate::CollatedIterExt, - pretty::{ - PrettyDuration, - PrettySlice, - }, + pretty::{PrettyDuration, PrettySlice}, }, }; @@ -1008,7 +969,7 @@ impl ForeignClient ForeignClient ForeignClient, ) -> Result, ForeignClientError> { + crate::time!( + "build_update_client_with_trusted", + { + "src_chain": self.src_chain().id(), + "dst_chain": self.dst_chain().id(), + } + ); // Get the latest client state on destination. let (client_state, _) = self.validated_client_state()?; @@ -1814,8 +1782,6 @@ impl ForeignClient Some(tm_misbehaviour.clone()), - #[cfg(test)] - _ => None, } .ok_or_else(|| { ForeignClientError::misbehaviour_desc(format!( diff --git a/crates/relayer/src/keyring.rs b/crates/relayer/src/keyring.rs index 5c21615132..1bea504caf 100644 --- a/crates/relayer/src/keyring.rs +++ b/crates/relayer/src/keyring.rs @@ -3,10 +3,7 @@ pub use any_signing_key_pair::AnySigningKeyPair; pub use ed25519_key_pair::Ed25519KeyPair; pub use key_type::KeyType; pub use secp256k1_key_pair::Secp256k1KeyPair; -pub use signing_key_pair::{ - SigningKeyPair, - SigningKeyPairSized, -}; +pub use signing_key_pair::{SigningKeyPair, SigningKeyPairSized}; mod any_signing_key_pair; mod ed25519_key_pair; @@ -19,19 +16,13 @@ mod signing_key_pair; use alloc::collections::btree_map::BTreeMap as HashMap; use std::{ ffi::OsStr, - fs::{ - self, - File, - }, + fs::{self, File}, path::PathBuf, }; use errors::Error; use ibc_relayer_types::core::ics24_host::identifier::ChainId; -use serde::{ - Deserialize, - Serialize, -}; +use serde::{Deserialize, Serialize}; pub const KEYSTORE_DEFAULT_FOLDER: &str = ".hermes/keys/"; pub const KEYSTORE_DISK_BACKEND: &str = "keyring-test"; diff --git a/crates/relayer/src/keyring/any_signing_key_pair.rs b/crates/relayer/src/keyring/any_signing_key_pair.rs index fc0c559086..f6aa27bd0b 100644 --- a/crates/relayer/src/keyring/any_signing_key_pair.rs +++ b/crates/relayer/src/keyring/any_signing_key_pair.rs @@ -1,11 +1,6 @@ use serde::Serialize; -use super::{ - Ed25519KeyPair, - KeyType, - Secp256k1KeyPair, - SigningKeyPair, -}; +use super::{Ed25519KeyPair, KeyType, Secp256k1KeyPair, SigningKeyPair}; #[derive(Clone, Debug, Serialize)] #[serde(untagged)] @@ -35,7 +30,7 @@ impl AnySigningKeyPair { Self::Ed25519(key_pair) => key_pair.as_any(), } .downcast_ref::() - .map(T::clone) + .cloned() } } diff --git a/crates/relayer/src/keyring/ed25519_key_pair.rs b/crates/relayer/src/keyring/ed25519_key_pair.rs index 93d8374322..34faa17d36 100644 --- a/crates/relayer/src/keyring/ed25519_key_pair.rs +++ b/crates/relayer/src/keyring/ed25519_key_pair.rs @@ -1,32 +1,13 @@ use core::any::Any; -use bip39::{ - Language, - Mnemonic, - Seed, -}; -use ed25519_dalek::{ - SigningKey, - VerifyingKey, -}; -use ed25519_dalek_bip32::{ - ChildIndex, - DerivationPath, - ExtendedSigningKey, -}; +use bip39::{Language, Mnemonic, Seed}; +use ed25519_dalek::{SigningKey, VerifyingKey}; +use ed25519_dalek_bip32::{ChildIndex, DerivationPath, ExtendedSigningKey}; use hdpath::StandardHDPath; -use serde::{ - Deserialize, - Serialize, -}; +use serde::{Deserialize, Serialize}; use signature::Signer; -use super::{ - errors::Error, - KeyFile, - KeyType, - SigningKeyPair, -}; +use super::{errors::Error, KeyFile, KeyType, SigningKeyPair}; use crate::config::AddressType; pub fn private_key_from_mnemonic( @@ -158,15 +139,14 @@ impl SigningKeyPair for Ed25519KeyPair { bs58::encode(&self.signing_key.verifying_key()).into_string() } Ed25519AddressType::Astria => { - use astria_core::{ - crypto::VerificationKey, - primitive::v1::Address, - }; + use astria_core::primitive::v1::Bech32m; + use astria_core::{crypto::VerificationKey, primitive::v1::Address}; + let verification_key = VerificationKey::try_from(self.signing_key.verifying_key().to_bytes()) .expect("can convert ed25519 public key bytes to astria verification key"); - let address = Address::builder() - .array(verification_key.address_bytes()) + let address: Address = Address::builder() + .array(*verification_key.address_bytes()) .prefix("astria") .try_build() .expect("can build astria address from ed25519 public key"); diff --git a/crates/relayer/src/keyring/errors.rs b/crates/relayer/src/keyring/errors.rs index 96b1af8fc1..d6b811b478 100644 --- a/crates/relayer/src/keyring/errors.rs +++ b/crates/relayer/src/keyring/errors.rs @@ -1,10 +1,6 @@ use std::io::Error as IoError; -use flex_error::{ - define_error, - DisplayOnly, - TraceError, -}; +use flex_error::{define_error, DisplayOnly, TraceError}; use super::KeyType; use crate::config::AddressType; diff --git a/crates/relayer/src/keyring/key_utils.rs b/crates/relayer/src/keyring/key_utils.rs index 18f5c86923..0defa4e81f 100644 --- a/crates/relayer/src/keyring/key_utils.rs +++ b/crates/relayer/src/keyring/key_utils.rs @@ -1,11 +1,5 @@ -use bech32::{ - FromBase32, - ToBase32, -}; -use tiny_keccak::{ - Hasher, - Keccak, -}; +use bech32::{FromBase32, ToBase32}; +use tiny_keccak::{Hasher, Keccak}; use super::errors::Error; diff --git a/crates/relayer/src/keyring/pub_key.rs b/crates/relayer/src/keyring/pub_key.rs index b9ad529174..923e7ad657 100644 --- a/crates/relayer/src/keyring/pub_key.rs +++ b/crates/relayer/src/keyring/pub_key.rs @@ -1,19 +1,10 @@ use core::str::FromStr; -use serde::{ - Deserialize, - Deserializer, -}; +use serde::{Deserialize, Deserializer}; use subtle_encoding::base64; -use tracing::{ - error, - trace, -}; +use tracing::{error, trace}; -use super::{ - errors::Error, - key_utils::decode_bech32, -}; +use super::{errors::Error, key_utils::decode_bech32}; #[derive(Debug)] pub enum EncodedPubKey { diff --git a/crates/relayer/src/keyring/secp256k1_key_pair.rs b/crates/relayer/src/keyring/secp256k1_key_pair.rs index 7655b3ab46..5f067696ef 100644 --- a/crates/relayer/src/keyring/secp256k1_key_pair.rs +++ b/crates/relayer/src/keyring/secp256k1_key_pair.rs @@ -1,53 +1,24 @@ use core::any::Any; -use bip39::{ - Language, - Mnemonic, - Seed, -}; +use bip39::{Language, Mnemonic, Seed}; use bitcoin::{ - bip32::{ - ChildNumber, - DerivationPath, - Xpriv, - Xpub, - }, + bip32::{ChildNumber, DerivationPath, Xpriv, Xpub}, network::Network, }; use digest::Digest; -use generic_array::{ - typenum::U32, - GenericArray, -}; +use generic_array::{typenum::U32, GenericArray}; use hdpath::StandardHDPath; use ripemd::Ripemd160; -use secp256k1::{ - Message, - PublicKey, - Secp256k1, - SecretKey, -}; -use serde::{ - Deserialize, - Serialize, -}; +use secp256k1::{Message, PublicKey, Secp256k1, SecretKey}; +use serde::{Deserialize, Serialize}; use sha2::Sha256; -use strum::{ - EnumIter, - IntoEnumIterator, -}; +use strum::{EnumIter, IntoEnumIterator}; use super::{ errors::Error, - key_utils::{ - decode_bech32, - encode_bech32, - keccak256_hash, - }, + key_utils::{decode_bech32, encode_bech32, keccak256_hash}, pub_key::EncodedPubKey, - KeyFile, - KeyType, - SigningKeyPair, + KeyFile, KeyType, SigningKeyPair, }; use crate::config::AddressType; diff --git a/crates/relayer/src/keyring/signing_key_pair.rs b/crates/relayer/src/keyring/signing_key_pair.rs index f8506a0e77..4609840f01 100644 --- a/crates/relayer/src/keyring/signing_key_pair.rs +++ b/crates/relayer/src/keyring/signing_key_pair.rs @@ -1,15 +1,9 @@ use core::any::Any; use hdpath::StandardHDPath; -use serde::{ - de::DeserializeOwned, - Serialize, -}; - -use super::{ - errors::Error, - KeyType, -}; +use serde::{de::DeserializeOwned, Serialize}; + +use super::{errors::Error, KeyType}; use crate::config::AddressType; pub trait SigningKeyPair { diff --git a/crates/relayer/src/lib.rs b/crates/relayer/src/lib.rs index 77030a327b..3ceac0c335 100644 --- a/crates/relayer/src/lib.rs +++ b/crates/relayer/src/lib.rs @@ -1,10 +1,8 @@ #![forbid(unsafe_code)] #![deny( - //warnings, trivial_casts, trivial_numeric_casts, unused_import_braces, - //unused_qualifications, rust_2018_idioms )] #![allow(clippy::too_many_arguments)] @@ -16,7 +14,7 @@ //! //! For the IBC relayer binary, please see [Hermes] (`ibc-relayer-cli` crate). //! -//! [Hermes]: https://docs.rs/ibc-relayer-cli/1.7.4/ +//! [Hermes]: https://docs.rs/ibc-relayer-cli/1.10.3/ extern crate alloc; @@ -49,3 +47,5 @@ pub mod transfer; pub mod upgrade_chain; pub mod util; pub mod worker; + +pub const HERMES_VERSION: &str = "1.10.3"; diff --git a/crates/relayer/src/light_client.rs b/crates/relayer/src/light_client.rs index 44e93d6adc..17e870b244 100644 --- a/crates/relayer/src/light_client.rs +++ b/crates/relayer/src/light_client.rs @@ -1,15 +1,10 @@ pub mod io; pub mod tendermint; -use ibc_relayer_types::{ - core::ics02_client::events::UpdateClient, - Height, -}; +use ibc_relayer_types::{core::ics02_client::events::UpdateClient, Height}; use crate::{ - chain::endpoint::ChainEndpoint, - client_state::AnyClientState, - error, + chain::endpoint::ChainEndpoint, client_state::AnyClientState, error, misbehaviour::MisbehaviourEvidence, }; diff --git a/crates/relayer/src/light_client/io.rs b/crates/relayer/src/light_client/io.rs index 3db93f723d..280a53db5a 100644 --- a/crates/relayer/src/light_client/io.rs +++ b/crates/relayer/src/light_client/io.rs @@ -1,14 +1,6 @@ -use tendermint::{ - account, - block::Height, -}; +use tendermint::{account, block::Height}; use tendermint_light_client::{ - components::io::{ - AtHeight, - Io, - IoError, - ProdIo, - }, + components::io::{AtHeight, Io, IoError, ProdIo}, types::LightBlock, }; diff --git a/crates/relayer/src/light_client/tendermint.rs b/crates/relayer/src/light_client/tendermint.rs index c6ac726294..c256352538 100644 --- a/crates/relayer/src/light_client/tendermint.rs +++ b/crates/relayer/src/light_client/tendermint.rs @@ -2,76 +2,42 @@ mod detector; use std::time::Duration; -#[cfg(test)] -use ibc_relayer_types::core::ics02_client::client_type::ClientType; -use ibc_relayer_types::{ - clients::ics07_tendermint::{ - header::Header as TmHeader, - misbehaviour::Misbehaviour as TmMisbehaviour, - }, - core::{ - ics02_client::{ - events::UpdateClient, - header::AnyHeader, - }, - ics24_host::identifier::ChainId, - }, - Height as ICSHeight, -}; use itertools::Itertools; use tendermint::Time; +use tracing::{debug, error, trace, warn}; + use tendermint_light_client::{ components::{ self, - io::{ - AtHeight, - Io, - ProdIo, - }, + io::{AtHeight, Io, ProdIo}, }, light_client::LightClient as TmLightClient, state::State as LightClientState, - store::{ - memory::MemoryStore, - LightStore, - }, - verifier::{ - types::{ - Height as TMHeight, - LightBlock, - PeerId, - Status, - }, - ProdVerifier, - }, + store::{memory::MemoryStore, LightStore}, + verifier::types::{Height as TMHeight, LightBlock, PeerId, Status}, + verifier::ProdVerifier, }; use tendermint_light_client_detector::Divergence; use tendermint_rpc as rpc; -use tracing::{ - debug, - error, - trace, - warn, -}; -use super::{ - io::{ - AnyIo, - RestartAwareIo, - }, - Verified, -}; +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; + use crate::{ - chain::cosmos::{ - config::CosmosSdkConfig, - CosmosSdkChain, - }, + chain::cosmos::{config::CosmosSdkConfig, CosmosSdkChain}, client_state::AnyClientState, error::Error, - misbehaviour::{ - AnyMisbehaviour, - MisbehaviourEvidence, - }, + misbehaviour::{AnyMisbehaviour, MisbehaviourEvidence}, + HERMES_VERSION, +}; + +use super::{ + io::{AnyIo, RestartAwareIo}, + Verified, }; pub struct LightClient { @@ -89,6 +55,12 @@ impl super::LightClient for LightClient { client_state: &AnyClientState, now: Time, ) -> Result, Error> { + crate::time!( + "light_client.tendermint.header_and_minimal_set", + { + "src_chain": self.chain_id.to_string(), + } + ); let Verified { target, supporting } = self.verify(trusted_height, target_height, client_state, now)?; @@ -115,6 +87,12 @@ impl super::LightClient for LightClient { client_state: &AnyClientState, now: Time, ) -> Result, Error> { + crate::time!( + "light_client.tendermint.verify", + { + "src_chain": self.chain_id.to_string(), + } + ); trace!(%trusted_height, %target_height, "light client verification"); if !self.enable_verification { @@ -181,12 +159,6 @@ impl super::LightClient for LightClient { 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 @@ -295,7 +267,10 @@ fn io_for_addr( peer_id: PeerId, timeout: Option, ) -> Result { - let rpc_client = rpc::HttpClient::new(addr.clone()).map_err(|e| Error::rpc(addr.clone(), e))?; + let rpc_client = rpc::HttpClient::builder(addr.clone().try_into().unwrap()) + .user_agent(format!("hermes/{}", HERMES_VERSION)) + .build() + .map_err(|e| Error::rpc(addr.clone(), e))?; Ok(ProdIo::new(peer_id, rpc_client, timeout)) } @@ -348,12 +323,6 @@ impl LightClient { 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( diff --git a/crates/relayer/src/light_client/tendermint/detector.rs b/crates/relayer/src/light_client/tendermint/detector.rs index 8914ee8663..8362f9a81c 100644 --- a/crates/relayer/src/light_client/tendermint/detector.rs +++ b/crates/relayer/src/light_client/tendermint/detector.rs @@ -1,45 +1,21 @@ use ibc_relayer_types::clients::ics07_tendermint::client_state::ClientState; use tendermint::{ - evidence::{ - Evidence, - LightClientAttackEvidence, - }, - Hash, - Time, + evidence::{Evidence, LightClientAttackEvidence}, + Hash, Time, }; use tendermint_light_client::{ builder::LightClientBuilder, - components::{ - clock::FixedClock, - io::ProdIo, - scheduler, - }, + components::{clock::FixedClock, io::ProdIo, scheduler}, predicates::ProdPredicates, store::memory::MemoryStore, - types::{ - LightBlock, - PeerId, - }, + types::{LightBlock, PeerId}, verifier::ProdVerifier, }; -use tendermint_light_client_detector::{ - detect_divergence, - Divergence, - Provider, -}; -use tendermint_rpc::{ - Client, - HttpClient, -}; -use tracing::{ - error, - info, -}; +use tendermint_light_client_detector::{detect_divergence, Divergence, Provider}; +use tendermint_rpc::{Client, HttpClient}; +use tracing::{error, info}; -use crate::{ - error::Error, - util::block_on, -}; +use crate::{error::Error, util::block_on}; type Hasher = tendermint::crypto::default::Sha256; diff --git a/crates/relayer/src/link.rs b/crates/relayer/src/link.rs index 873a0f95b0..e041f47a94 100644 --- a/crates/relayer/src/link.rs +++ b/crates/relayer/src/link.rs @@ -1,11 +1,9 @@ use ibc_relayer_types::core::{ ics03_connection::connection::State as ConnectionState, ics04_channel::channel::State as ChannelState, - ics24_host::identifier::{ - ChannelId, - PortChannelId, - PortId, - }, + ics04_channel::channel::UpgradeState, + ics04_channel::packet::Sequence, + ics24_host::identifier::{ChannelId, PortChannelId, PortId}, }; use tracing::info; @@ -13,17 +11,9 @@ use crate::{ chain::{ counterparty::check_channel_counterparty, handle::ChainHandle, - requests::{ - IncludeProof, - QueryChannelRequest, - QueryConnectionRequest, - QueryHeight, - }, - }, - channel::{ - Channel, - ChannelSide, + requests::{IncludeProof, QueryChannelRequest, QueryConnectionRequest, QueryHeight}, }, + channel::{Channel, ChannelSide}, config::types::ics20_field_size_limit::Ics20FieldSizeLimit, link::error::LinkError, }; @@ -39,10 +29,7 @@ mod relay_sender; mod relay_summary; mod tx_hashes; -pub use relay_path::{ - RelayPath, - Resubmit, -}; +pub use relay_path::{RelayPath, Resubmit}; // Re-export the telemetries summary pub use relay_summary::RelaySummary; use tx_hashes::TxHashes; @@ -53,6 +40,7 @@ pub struct LinkParameters { pub src_channel_id: ChannelId, pub max_memo_size: Ics20FieldSizeLimit, pub max_receiver_size: Ics20FieldSizeLimit, + pub exclude_src_sequences: Vec, } pub struct Link { @@ -98,7 +86,10 @@ impl Link { ) })?; - if !a_channel.state_matches(&ChannelState::Open) + if !a_channel.state_matches(&ChannelState::Open(UpgradeState::NotUpgrading)) + && !a_channel.state_matches(&ChannelState::Open(UpgradeState::Upgrading)) + && !a_channel.state_matches(&ChannelState::Flushing) + && !a_channel.state_matches(&ChannelState::FlushComplete) && !a_channel.state_matches(&ChannelState::Closed) { return Err(LinkError::invalid_channel_state( @@ -192,31 +183,4 @@ impl Link { Link::new(channel, with_tx_confirmation, opts) } - - /// Constructs a link around the channel that is reverse to the channel - /// in this link. - pub fn reverse( - &self, - with_tx_confirmation: bool, - auto_register_counterparty_payee: bool, - ) -> Result, LinkError> { - let opts = LinkParameters { - src_port_id: self.a_to_b.dst_port_id().clone(), - src_channel_id: self.a_to_b.dst_channel_id().clone(), - max_memo_size: self.a_to_b.max_memo_size, - max_receiver_size: self.a_to_b.max_receiver_size, - }; - let chain_b = self.a_to_b.dst_chain().clone(); - let chain_a = self.a_to_b.src_chain().clone(); - - // Some of the checks and initializations may be redundant; - // going slowly, but reliably. - Link::new_from_opts( - chain_b, - chain_a, - opts, - with_tx_confirmation, - auto_register_counterparty_payee, - ) - } } diff --git a/crates/relayer/src/link/cli.rs b/crates/relayer/src/link/cli.rs index fd7b78ba34..f07cd39e23 100644 --- a/crates/relayer/src/link/cli.rs +++ b/crates/relayer/src/link/cli.rs @@ -1,58 +1,31 @@ -use std::{ - convert::TryInto, - ops::RangeInclusive, - thread, - time::{ - Duration, - Instant, - }, -}; +use std::ops::RangeInclusive; +use std::thread; +use std::time::{Duration, Instant}; -use ibc_relayer_types::{ - core::ics04_channel::packet::Sequence, - events::IbcEvent, - utils::pretty::{ - PrettyDuration, - PrettySlice, - }, - Height, -}; +use ibc_relayer_types::core::ics04_channel::packet::Sequence; use itertools::Itertools; -use tracing::{ - error_span, - info, -}; - -use crate::{ - chain::{ - counterparty::{ - unreceived_acknowledgements, - unreceived_packets, - }, - handle::ChainHandle, - requests::Qualified, - tracking::TrackingId, - }, - error::Error, - event::IbcEventWithHeight, - link::{ - error::LinkError, - operational_data::{ - OperationalData, - TrackedEvents, - }, - packet_events::{ - query_packet_events_with, - query_send_packet_events, - query_write_ack_events, - }, - relay_sender::SyncSender, - Link, - RelayPath, - }, - path::PathIdentifiers, - util::collate::CollatedIterExt as _, +use tracing::{error_span, info}; + +use ibc_relayer_types::events::IbcEvent; +use ibc_relayer_types::Height; + +use crate::chain::counterparty::{unreceived_acknowledgements, unreceived_packets}; +use crate::chain::handle::ChainHandle; +use crate::chain::requests::{Paginate, Qualified}; +use crate::chain::tracking::TrackingId; +use crate::error::Error; +use crate::event::IbcEventWithHeight; +use crate::link::error::LinkError; +use crate::link::operational_data::{OperationalData, TrackedEvents}; +use crate::link::packet_events::{ + query_packet_events_with, query_send_packet_events, query_write_ack_events, }; +use crate::link::relay_path::RelayPath; +use crate::link::relay_sender::SyncSender; +use crate::link::Link; +use crate::path::PathIdentifiers; +use crate::util::collate::CollatedIterExt; +use crate::util::pretty::{PrettyDuration, PrettySlice}; impl RelayPath { /// Fetches an operational data that has fulfilled its predefined delay period. May _block_ @@ -124,6 +97,7 @@ impl Link { self.a_to_b.dst_chain(), self.a_to_b.src_chain(), &self.a_to_b.path_id, + Paginate::All, ) .map_err(LinkError::supervisor)?; @@ -136,10 +110,16 @@ impl Link { sequences.retain(|seq| sequence_filter.iter().any(|range| range.contains(seq))); } + // Retain only sequences which should not be filtered out + let raw_sequences: Vec = sequences + .into_iter() + .filter(|sequence| !self.a_to_b.exclude_src_sequences.contains(sequence)) + .collect(); + info!( "{} unreceived packets found: {} ", - sequences.len(), - PrettySlice(&sequences) + raw_sequences.len(), + PrettySlice(&raw_sequences) ); let query_height = match packet_data_query_height { @@ -154,7 +134,7 @@ impl Link { .map_or(50, |cfg| cfg.query_packets_chunk_size()); self.relay_packet_messages( - sequences, + raw_sequences, query_height, chunk_size, query_send_packet_events, @@ -189,6 +169,7 @@ impl Link { self.a_to_b.dst_chain(), self.a_to_b.src_chain(), &self.a_to_b.path_id, + Paginate::All, ) .map_err(LinkError::supervisor)? else { @@ -204,10 +185,16 @@ impl Link { sequences.retain(|seq| sequence_filter.iter().any(|range| range.contains(seq))); } + // Retain only sequences which should not be filtered out + let raw_sequences: Vec = sequences + .into_iter() + .filter(|sequence| !self.a_to_b.exclude_src_sequences.contains(sequence)) + .collect(); + info!( "{} unreceived acknowledgements found: {} ", - sequences.len(), - sequences.iter().copied().collated().format(", "), + raw_sequences.len(), + raw_sequences.iter().copied().collated().format(", "), ); let query_height = match packet_data_query_height { @@ -222,7 +209,7 @@ impl Link { .map_or(50, |cfg| cfg.query_packets_chunk_size()); self.relay_packet_messages( - sequences, + raw_sequences, query_height, chunk_size, query_write_ack_events, diff --git a/crates/relayer/src/link/error.rs b/crates/relayer/src/link/error.rs index d9ea749b50..57e2a15deb 100644 --- a/crates/relayer/src/link/error.rs +++ b/crates/relayer/src/link/error.rs @@ -2,11 +2,7 @@ use flex_error::define_error; use ibc_relayer_types::{ core::{ ics02_client::error::Error as Ics02Error, - ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }, + ics24_host::identifier::{ChainId, ChannelId, PortId}, }, events::IbcEvent, Height, @@ -16,10 +12,7 @@ use crate::{ channel::ChannelError, connection::ConnectionError, error::Error, - foreign_client::{ - ForeignClientError, - HasExpiredOrFrozenError, - }, + foreign_client::{ForeignClientError, HasExpiredOrFrozenError}, supervisor::Error as SupervisorError, transfer::TransferError, }; @@ -86,7 +79,7 @@ define_error! { Send { event: IbcEvent } |e| { - format!("chain error when sending messages: {0}", e.event) + format!("failed to send message: {0}", e.event) }, MissingChannelId diff --git a/crates/relayer/src/link/operational_data.rs b/crates/relayer/src/link/operational_data.rs index 8cc5820f04..385481425d 100644 --- a/crates/relayer/src/link/operational_data.rs +++ b/crates/relayer/src/link/operational_data.rs @@ -1,45 +1,24 @@ -use core::fmt::{ - Display, - Error as FmtError, - Formatter, -}; +use core::fmt::{Display, Error as FmtError, Formatter}; use std::{ ops::Add, - time::{ - Duration, - Instant, - }, + time::{Duration, Instant}, }; -use ibc_proto::google::protobuf::Any; -use ibc_relayer_types::{ - core::ics02_client::client_state::ClientState, - Height, -}; -use tracing::{ - debug, - info, -}; +use tracing::{debug, info}; -use crate::{ - chain::{ - handle::ChainHandle, - requests::{ - IncludeProof, - QueryClientStateRequest, - QueryHeight, - }, - tracking::{ - TrackedMsgs, - TrackingId, - }, - }, - event::IbcEventWithHeight, - link::{ - error::LinkError, - RelayPath, - }, -}; +use ibc_proto::google::protobuf::Any; +use ibc_relayer_types::core::ics02_client::client_state::ClientState; +use ibc_relayer_types::Height; + +use crate::chain::handle::ChainHandle; +use crate::chain::requests::IncludeProof; +use crate::chain::requests::QueryClientStateRequest; +use crate::chain::requests::QueryHeight; +use crate::chain::tracking::TrackedMsgs; +use crate::chain::tracking::TrackingId; +use crate::event::IbcEventWithHeight; +use crate::link::error::LinkError; +use crate::link::RelayPath; /// The chain that the events associated with a piece of [`OperationalData`] are bound for. #[derive(Clone, Copy, PartialEq, Eq)] diff --git a/crates/relayer/src/link/packet_events.rs b/crates/relayer/src/link/packet_events.rs index 9a2dcbc589..6615e0d267 100644 --- a/crates/relayer/src/link/packet_events.rs +++ b/crates/relayer/src/link/packet_events.rs @@ -1,26 +1,13 @@ //! Utility methods for querying packet event data. -use ibc_relayer_types::{ - core::ics04_channel::packet::Sequence, - events::WithBlockDataType, - Height, -}; +use ibc_relayer_types::{core::ics04_channel::packet::Sequence, events::WithBlockDataType, Height}; use itertools::Itertools; -use tracing::{ - info, - span, - warn, - Level, -}; +use tracing::{info, span, warn, Level}; use crate::{ chain::{ handle::ChainHandle, - requests::{ - Qualified, - QueryHeight, - QueryPacketEventDataRequest, - }, + requests::{Qualified, QueryHeight, QueryPacketEventDataRequest}, }, error::Error, event::IbcEventWithHeight, @@ -55,14 +42,21 @@ where Ok(events) => { events_left -= chunk.len(); - info!( - events.total = %events_total, - events.left = %events_left, - "pulled packet data for {} events out of {} sequences: {};", - events.len(), - chunk.len(), - chunk.iter().copied().collated().format(", "), - ); + if events.is_empty() && !chunk.is_empty() { + warn!("no packet data was pulled at height {query_height} for sequences {}, this might be due to the data not being available on the configured endpoint. \ + Please verify that the RPC endpoint has the required packet data, for more details see https://hermes.informal.systems/advanced/troubleshooting/cross-comp-config.html#uncleared-pending-packets", + chunk.iter().copied().collated().format(", ")); + } else { + info!( + events.total = %events_total, + events.left = %events_left, + "pulled packet data for {} out of {} events: {}", + events.len(), + chunk.len(), + chunk.iter().copied().collated().format(", "), + ); + } + // Because we use the first event height to do the client update, // if the heights of the events differ, we get proof verification failures. diff --git a/crates/relayer/src/link/pending.rs b/crates/relayer/src/link/pending.rs index c2284cc0a1..71642782f6 100644 --- a/crates/relayer/src/link/pending.rs +++ b/crates/relayer/src/link/pending.rs @@ -1,41 +1,22 @@ -use core::{ - iter::Iterator, - time::Duration, -}; +use core::time::Duration; use std::time::Instant; use ibc_relayer_types::{ - core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }, + core::ics24_host::identifier::{ChainId, ChannelId, PortId}, events::IbcEvent, }; -use tracing::{ - debug, - error, - trace, - trace_span, -}; +use tracing::{debug, error, trace, trace_span}; use crate::{ chain::{ handle::ChainHandle, - requests::{ - QueryTxHash, - QueryTxRequest, - }, + requests::{QueryTxHash, QueryTxRequest}, tracking::TrackingId, }, error::Error as RelayerError, link::{ - error::LinkError, - operational_data::OperationalData, - relay_sender::AsyncReply, - RelayPath, - RelaySummary, - TxHashes, + error::LinkError, operational_data::OperationalData, relay_sender::AsyncReply, RelayPath, + RelaySummary, TxHashes, }, telemetry, util::queue::Queue, diff --git a/crates/relayer/src/link/relay_path.rs b/crates/relayer/src/link/relay_path.rs index 2a3a5f228e..8038f03995 100644 --- a/crates/relayer/src/link/relay_path.rs +++ b/crates/relayer/src/link/relay_path.rs @@ -1,148 +1,72 @@ -use alloc::collections::{ - BTreeMap as HashMap, - VecDeque, -}; -use std::{ - ops::Sub, - time::{ - Duration, - Instant, - }, -}; +use alloc::collections::BTreeMap as HashMap; +use alloc::collections::VecDeque; +use ibc_relayer_types::core::ics04_channel::packet::Sequence; +use std::ops::Sub; +use std::time::{Duration, Instant}; + +use ibc_proto::google::protobuf::Any; +use ibc_proto::ibc::applications::transfer::v2::FungibleTokenPacketData as RawPacketData; +use itertools::Itertools; +use tracing::{debug, error, info, span, trace, warn, Level}; -use ibc_proto::{ - google::protobuf::Any, - ibc::applications::transfer::v2::FungibleTokenPacketData as RawPacketData, +use ibc_relayer_types::core::ics02_client::events::ClientMisbehaviour as ClientMisbehaviourEvent; +use ibc_relayer_types::core::ics04_channel::channel::{ + ChannelEnd, Ordering, State as ChannelState, }; -use ibc_relayer_types::{ - core::{ - ics02_client::events::ClientMisbehaviour, - ics04_channel::{ - channel::{ - ChannelEnd, - Ordering, - }, - events::{ - SendPacket, - WriteAcknowledgement, - }, - msgs::{ - acknowledgement::MsgAcknowledgement, - chan_close_confirm::MsgChannelCloseConfirm, - recv_packet::MsgRecvPacket, - timeout::MsgTimeout, - timeout_on_close::MsgTimeoutOnClose, - }, - packet::{ - Packet, - PacketMsgType, - }, - }, - ics24_host::identifier::{ - ChannelId, - ClientId, - ConnectionId, - PortId, - }, - }, - events::{ - IbcEvent, - IbcEventType, - WithBlockDataType, - }, - signer::Signer, - timestamp::Timestamp, - tx_msg::Msg, - Height, +use ibc_relayer_types::core::ics04_channel::events::{SendPacket, WriteAcknowledgement}; +use ibc_relayer_types::core::ics04_channel::msgs::{ + acknowledgement::MsgAcknowledgement, chan_close_confirm::MsgChannelCloseConfirm, + recv_packet::MsgRecvPacket, timeout::MsgTimeout, timeout_on_close::MsgTimeoutOnClose, }; -use itertools::Itertools; -use tracing::{ - debug, - error, - info, - span, - trace, - warn, - Level, -}; - -use crate::{ - chain::{ - counterparty::{ - unreceived_acknowledgements, - unreceived_packets, - }, - endpoint::ChainStatus, - handle::ChainHandle, - requests::{ - IncludeProof, - Qualified, - QueryChannelRequest, - QueryClientEventRequest, - QueryHeight, - QueryHostConsensusStateRequest, - QueryNextSequenceReceiveRequest, - QueryPacketCommitmentRequest, - QueryTxRequest, - QueryUnreceivedAcksRequest, - QueryUnreceivedPacketsRequest, - }, - tracking::{ - TrackedMsgs, - TrackingId, - }, - }, - channel::{ - error::ChannelError, - Channel, - }, - config::types::ics20_field_size_limit::{ - Ics20FieldSizeLimit, - ValidationResult, - }, - event::{ - source::EventBatch, - IbcEventWithHeight, - }, - foreign_client::{ - ForeignClient, - ForeignClientError, - }, - link::{ - error::{ - self, - LinkError, - }, - operational_data::{ - OperationalData, - OperationalDataTarget, - TrackedEvents, - TransitMessage, - }, - packet_events::{ - query_packet_events_with, - query_send_packet_events, - query_write_ack_events, - }, - pending, - pending::PendingTxs, - relay_sender, - relay_sender::{ - AsyncReply, - SubmitReply, - }, - relay_summary::RelaySummary, - ChannelState, - LinkParameters, - }, - path::PathIdentifiers, - telemetry, - util::{ - collate::CollatedIterExt, - pretty::PrettyEvents, - queue::Queue, - }, +use ibc_relayer_types::core::ics04_channel::packet::{Packet, PacketMsgType}; +use ibc_relayer_types::core::ics24_host::identifier::{ChannelId, ClientId, ConnectionId, PortId}; +use ibc_relayer_types::events::{IbcEvent, IbcEventType, WithBlockDataType}; +use ibc_relayer_types::signer::Signer; +use ibc_relayer_types::timestamp::Timestamp; +use ibc_relayer_types::tx_msg::Msg; +use ibc_relayer_types::Height; + +use crate::chain::counterparty::unreceived_acknowledgements; +use crate::chain::counterparty::unreceived_packets; +use crate::chain::endpoint::ChainStatus; +use crate::chain::handle::ChainHandle; +use crate::chain::requests::Paginate; +use crate::chain::requests::QueryChannelRequest; +use crate::chain::requests::QueryClientEventRequest; +use crate::chain::requests::QueryHeight; +use crate::chain::requests::QueryHostConsensusStateRequest; +use crate::chain::requests::QueryNextSequenceReceiveRequest; +use crate::chain::requests::QueryPacketCommitmentRequest; +use crate::chain::requests::QueryTxRequest; +use crate::chain::requests::QueryUnreceivedAcksRequest; +use crate::chain::requests::QueryUnreceivedPacketsRequest; +use crate::chain::requests::{IncludeProof, Qualified}; +use crate::chain::tracking::TrackedMsgs; +use crate::chain::tracking::TrackingId; +use crate::channel::error::ChannelError; +use crate::channel::Channel; +use crate::config::types::ics20_field_size_limit::Ics20FieldSizeLimit; +use crate::config::types::ics20_field_size_limit::ValidationResult; +use crate::event::source::EventBatch; +use crate::event::IbcEventWithHeight; +use crate::foreign_client::{ForeignClient, ForeignClientError}; +use crate::link::error::{self, LinkError}; +use crate::link::operational_data::{ + OperationalData, OperationalDataTarget, TrackedEvents, TransitMessage, }; +use crate::link::packet_events::query_packet_events_with; +use crate::link::packet_events::query_send_packet_events; +use crate::link::packet_events::query_write_ack_events; +use crate::link::pending::PendingTxs; +use crate::link::relay_sender::{AsyncReply, SubmitReply}; +use crate::link::relay_summary::RelaySummary; +use crate::link::LinkParameters; +use crate::link::{pending, relay_sender}; +use crate::path::PathIdentifiers; +use crate::telemetry; +use crate::util::collate::CollatedIterExt; +use crate::util::pretty::PrettyEvents; +use crate::util::queue::Queue; const MAX_RETRIES: usize = 5; @@ -193,6 +117,7 @@ pub struct RelayPath { pub max_memo_size: Ics20FieldSizeLimit, pub max_receiver_size: Ics20FieldSizeLimit, + pub exclude_src_sequences: Vec, } impl RelayPath { @@ -241,6 +166,8 @@ impl RelayPath { max_memo_size: link_parameters.max_memo_size, max_receiver_size: link_parameters.max_receiver_size, + + exclude_src_sequences: link_parameters.exclude_src_sequences, }) } @@ -428,10 +355,9 @@ impl RelayPath { } // Nothing to do if channel on destination is already closed - if self - .dst_channel(QueryHeight::Latest)? - .state_matches(&ChannelState::Closed) - { + let dst_channel = self.dst_channel(QueryHeight::Latest)?; + + if dst_channel.state_matches(&ChannelState::Closed) { return Ok(None); } @@ -441,12 +367,15 @@ impl RelayPath { .build_channel_proofs(self.src_port_id(), src_channel_id, event.height) .map_err(|e| LinkError::channel(ChannelError::channel_proof(e)))?; + let counterparty_upgrade_sequence = self.src_channel(QueryHeight::Latest)?.upgrade_sequence; + // Build the domain type message let new_msg = MsgChannelCloseConfirm { port_id: self.dst_port_id().clone(), channel_id: self.dst_channel_id().clone(), proofs, signer: self.dst_signer()?, + counterparty_upgrade_sequence, }; Ok(Some(new_msg.to_any())) @@ -501,20 +430,29 @@ impl RelayPath { TrackedEvents::new(result, tracking_id) } - fn relay_pending_packets(&self, height: Option) -> Result<(), LinkError> { + fn relay_pending_packets( + &self, + height: Option, + clear_limit: usize, + ) -> Result<(), LinkError> { let _span = span!(Level::ERROR, "relay_pending_packets", ?height).entered(); - let tracking_id = TrackingId::new_cleared_uuid(); + let tracking_id = TrackingId::new_packet_clearing(); telemetry!(received_event_batch, tracking_id); let src_config = self.src_chain().config().map_err(LinkError::relayer)?; let chunk_size = src_config.query_packets_chunk_size(); for i in 1..=MAX_RETRIES { - let cleared_recv = - self.schedule_recv_packet_and_timeout_msgs(height, chunk_size, tracking_id); + let cleared_recv = self.schedule_recv_packet_and_timeout_msgs( + height, + chunk_size, + clear_limit, + tracking_id, + ); - let cleared_ack = self.schedule_packet_ack_msgs(height, chunk_size, tracking_id); + let cleared_ack = + self.schedule_packet_ack_msgs(height, chunk_size, clear_limit, tracking_id); match cleared_recv.and(cleared_ack) { Ok(()) => return Ok(()), @@ -530,14 +468,18 @@ impl RelayPath { /// Clears any packets that were sent before `height`. /// If no height is passed in, then the latest height of the source chain is used. - pub fn schedule_packet_clearing(&self, height: Option) -> Result<(), LinkError> { + pub fn schedule_packet_clearing( + &self, + height: Option, + clear_limit: usize, + ) -> Result<(), LinkError> { let _span = span!(Level::ERROR, "schedule_packet_clearing", ?height).entered(); let clear_height = height .map(|h| h.decrement().map_err(|e| LinkError::decrement_height(h, e))) .transpose()?; - self.relay_pending_packets(clear_height)?; + self.relay_pending_packets(clear_height, clear_limit)?; debug!(height = ?clear_height, "done relaying pending packets at clear height"); @@ -646,6 +588,16 @@ impl RelayPath { self.max_memo_size, self.max_receiver_size, ) { + telemetry!( + filtered_packets, + &self.src_chain().id(), + &self.dst_chain().id(), + &packet.source_channel, + &packet.destination_channel, + &packet.source_port, + &packet.destination_port, + 1 + ); continue; } } @@ -777,12 +729,12 @@ impl RelayPath { return Ok(reply); } - Err(LinkError(error::LinkErrorDetail::Send(e), _)) => { - // This error means we could retry - error!("error {}", e.event); + Err(LinkError(error::LinkErrorDetail::Send(_), _)) => { if i + 1 == MAX_RETRIES { - error!("{}/{} retries exhausted. giving up", i + 1, MAX_RETRIES) + error!("{}/{} retries exhausted, giving up", i + 1, MAX_RETRIES) } else { + debug!("{}/{} retries exhausted, retrying with newly-generated operational data", i + 1, MAX_RETRIES); + // If we haven't exhausted all retries, regenerate the op. data & retry match self.regenerate_operational_data(odata.clone()) { None => return Ok(S::Reply::empty()), // Nothing to retry @@ -806,7 +758,7 @@ impl RelayPath { /// Return value: /// - `Some(..)`: a new operational data from which to retry sending, /// - `None`: all the events in the initial operational data were exhausted (i.e., turned - /// into timeouts), so there is nothing to retry. + /// into timeouts), so there is nothing to retry. /// /// Side effects: may schedule a new operational data targeting the source chain, comprising /// new timeout messages. @@ -1016,7 +968,11 @@ impl RelayPath { #[inline] fn event_per_type( mut tx_events: Vec, - ) -> (Option, Option, Option) { + ) -> ( + Option, + Option, + Option, + ) { let mut error = None; let mut update = None; let mut misbehaviour = None; @@ -1197,6 +1153,7 @@ impl RelayPath { &self, opt_query_height: Option, chunk_size: usize, + clear_limit: usize, tracking_id: TrackingId, ) -> Result<(), LinkError> { let _span = span!( @@ -1207,9 +1164,13 @@ impl RelayPath { .entered(); // Pull the s.n. of all packets that the destination chain has not yet received. - let (sequences, src_response_height) = - unreceived_packets(self.dst_chain(), self.src_chain(), &self.path_id) - .map_err(LinkError::supervisor)?; + let (sequences, src_response_height) = unreceived_packets( + self.dst_chain(), + self.src_chain(), + &self.path_id, + Paginate::All, + ) + .map_err(LinkError::supervisor)?; let query_height = opt_query_height.unwrap_or(src_response_height); @@ -1218,6 +1179,14 @@ impl RelayPath { return Ok(()); } + // Retain only sequences which should not be filtered out + let raw_sequences: Vec = sequences + .into_iter() + .filter(|sequence| !self.exclude_src_sequences.contains(sequence)) + .collect(); + + let sequences = &raw_sequences[..raw_sequences.len().min(clear_limit)]; + debug!( dst_chain = %self.dst_chain().id(), src_chain = %self.src_chain().id(), @@ -1229,7 +1198,7 @@ impl RelayPath { // Chunk-up the list of sequence nrs. into smaller parts, // and schedule operational data incrementally across each chunk. for events_chunk in query_packet_events_with( - &sequences, + sequences, Qualified::SmallerEqual(query_height), self.src_chain(), &self.path_id, @@ -1258,6 +1227,7 @@ impl RelayPath { &self, opt_query_height: Option, chunk_size: usize, + clear_limit: usize, tracking_id: TrackingId, ) -> Result<(), LinkError> { let _span = span!( @@ -1267,9 +1237,13 @@ impl RelayPath { ) .entered(); - let sequences_and_height = - unreceived_acknowledgements(self.dst_chain(), self.src_chain(), &self.path_id) - .map_err(LinkError::supervisor)?; + let sequences_and_height = unreceived_acknowledgements( + self.dst_chain(), + self.src_chain(), + &self.path_id, + Paginate::All, + ) + .map_err(LinkError::supervisor)?; let Some((sequences, src_response_height)) = sequences_and_height else { return Ok(()); @@ -1282,6 +1256,14 @@ impl RelayPath { return Ok(()); } + // Retain only sequences which should not be filtered out + let raw_sequences: Vec = sequences + .into_iter() + .filter(|sequence| !self.exclude_src_sequences.contains(sequence)) + .collect(); + + let sequences = &raw_sequences[..raw_sequences.len().min(clear_limit)]; + debug!( dst_chain = %self.dst_chain().id(), src_chain = %self.src_chain().id(), @@ -1292,7 +1274,7 @@ impl RelayPath { // Incrementally process all the available sequence numbers in chunks for events_chunk in query_packet_events_with( - &sequences, + sequences, Qualified::SmallerEqual(query_height), self.src_chain(), &self.path_id, @@ -1442,11 +1424,14 @@ impl RelayPath { ) .map_err(|e| LinkError::packet_proofs_constructor(self.dst_chain().id(), e))?; + let counterparty_upgrade_sequence = self.src_channel(QueryHeight::Latest)?.upgrade_sequence; + let msg = MsgTimeoutOnClose::new( packet.clone(), next_sequence_received, proofs.clone(), self.src_signer()?, + counterparty_upgrade_sequence, ); trace!(packet = %msg.packet, height = %proofs.height(), "built timeout on close msg"); @@ -1892,7 +1877,6 @@ impl RelayPath { } // we need fully qualified ChainId to avoid unneeded imports warnings - #[cfg(feature = "telemetry")] fn target_info( &self, target: OperationalDataTarget, @@ -1918,7 +1902,6 @@ impl RelayPath { } } - #[cfg(feature = "telemetry")] fn backlog_update(&self, event: &IbcEvent) { match event { IbcEvent::SendPacket(send_packet_ev) => { @@ -1952,7 +1935,6 @@ impl RelayPath { } } - #[cfg(feature = "telemetry")] fn record_cleared_send_packet(&self, event_with_height: &IbcEventWithHeight) { if let IbcEvent::SendPacket(send_packet_ev) = &event_with_height.event { ibc_telemetry::global().send_packet_events( @@ -1974,7 +1956,6 @@ impl RelayPath { } } - #[cfg(feature = "telemetry")] fn record_cleared_acknowledgments<'a>( &self, events_with_heights: impl Iterator, @@ -1994,7 +1975,7 @@ impl RelayPath { } } -#[tracing::instrument(skip(data))] +#[tracing::instrument(skip_all)] fn check_ics20_fields_size( data: &[u8], memo_limit: Ics20FieldSizeLimit, @@ -2009,9 +1990,9 @@ fn check_ics20_fields_size( (ValidationResult::Valid, ValidationResult::Valid) => true, (memo_validity, receiver_validity) => { - debug!("found invalid ICS-20 packet data, not relaying packet!"); - debug!(" ICS-20 memo: {memo_validity}"); - debug!(" ICS-20 receiver: {receiver_validity}"); + warn!("found invalid ICS-20 packet data, not relaying packet!"); + warn!(" ICS-20 memo: {memo_validity}"); + warn!(" ICS-20 receiver: {receiver_validity}"); false } diff --git a/crates/relayer/src/link/relay_sender.rs b/crates/relayer/src/link/relay_sender.rs index 185073c176..f07ebc4c51 100644 --- a/crates/relayer/src/link/relay_sender.rs +++ b/crates/relayer/src/link/relay_sender.rs @@ -1,26 +1,13 @@ -use core::fmt::{ - Display, - Error as FmtError, - Formatter, -}; +use core::fmt::{Display, Error as FmtError, Formatter}; use ibc_relayer_types::events::IbcEvent; use tendermint_rpc::endpoint::broadcast::tx_sync; use tracing::info; use crate::{ - chain::{ - handle::ChainHandle, - tracking::TrackedMsgs, - }, - link::{ - error::LinkError, - RelaySummary, - }, - util::pretty::{ - PrettyCode, - PrettyEvents, - }, + chain::{handle::ChainHandle, tracking::TrackedMsgs}, + link::{error::LinkError, RelaySummary}, + util::pretty::{PrettyCode, PrettyEvents}, }; pub trait SubmitReply { @@ -107,10 +94,11 @@ impl Submit for AsyncSender { type Reply = AsyncReply; fn submit(target: &impl ChainHandle, msgs: TrackedMsgs) -> Result { - let a = target + let responses = target .send_messages_and_wait_check_tx(msgs) .map_err(LinkError::relayer)?; - let reply = AsyncReply { responses: a }; + + let reply = AsyncReply { responses }; // Note: There may be errors in the reply, for example: // `Response { code: Err(11), data: Data([]), log: Log("Too much gas wanted: 35000000, maximum is 25000000: out of gas")` diff --git a/crates/relayer/src/link/relay_summary.rs b/crates/relayer/src/link/relay_summary.rs index 97164af99e..73260438fa 100644 --- a/crates/relayer/src/link/relay_summary.rs +++ b/crates/relayer/src/link/relay_summary.rs @@ -1,8 +1,4 @@ -use core::fmt::{ - Display, - Error as FmtError, - Formatter, -}; +use core::fmt::{Display, Error as FmtError, Formatter}; use ibc_relayer_types::events::IbcEvent; diff --git a/crates/relayer/src/link/tx_hashes.rs b/crates/relayer/src/link/tx_hashes.rs index d682e48297..4516d74f79 100644 --- a/crates/relayer/src/link/tx_hashes.rs +++ b/crates/relayer/src/link/tx_hashes.rs @@ -1,8 +1,4 @@ -use core::fmt::{ - Display, - Error as FmtError, - Formatter, -}; +use core::fmt::{Display, Error as FmtError, Formatter}; use tendermint::Hash as TxHash; diff --git a/crates/relayer/src/misbehaviour.rs b/crates/relayer/src/misbehaviour.rs index 2d6cfe19e2..69b533f462 100644 --- a/crates/relayer/src/misbehaviour.rs +++ b/crates/relayer/src/misbehaviour.rs @@ -1,27 +1,14 @@ +use serde::{Deserialize, Serialize}; + use ibc_proto::google::protobuf::Any; -#[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::{ - clients::ics07_tendermint::misbehaviour::{ - Misbehaviour as TmMisbehaviour, - TENDERMINT_MISBEHAVIOR_TYPE_URL, - }, - core::{ - ics02_client::{ - error::Error, - header::AnyHeader, - misbehaviour::Misbehaviour, - }, - ics24_host::identifier::ClientId, - }, - Height, -}; -use serde::{ - Deserialize, - Serialize, +use ibc_relayer_types::clients::ics07_tendermint::misbehaviour::{ + Misbehaviour as TmMisbehaviour, TENDERMINT_MISBEHAVIOR_TYPE_URL, }; +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; #[derive(Clone, Debug, PartialEq, Eq)] @@ -34,27 +21,18 @@ pub struct MisbehaviourEvidence { #[allow(clippy::large_enum_variant)] pub enum AnyMisbehaviour { Tendermint(TmMisbehaviour), - - #[cfg(test)] - Mock(MockMisbehaviour), } impl Misbehaviour for AnyMisbehaviour { fn client_id(&self) -> &ClientId { match self { Self::Tendermint(misbehaviour) => misbehaviour.client_id(), - - #[cfg(test)] - Self::Mock(misbehaviour) => misbehaviour.client_id(), } } fn height(&self) -> Height { match self { Self::Tendermint(misbehaviour) => misbehaviour.height(), - - #[cfg(test)] - Self::Mock(misbehaviour) => misbehaviour.height(), } } } @@ -70,11 +48,6 @@ impl TryFrom for AnyMisbehaviour { TmMisbehaviour::decode_vec(&raw.value).map_err(Error::decode_raw_misbehaviour)?, )), - #[cfg(test)] - MOCK_MISBEHAVIOUR_TYPE_URL => Ok(AnyMisbehaviour::Mock( - MockMisbehaviour::decode_vec(&raw.value).map_err(Error::decode_raw_misbehaviour)?, - )), - _ => Err(Error::unknown_misbehaviour_type(raw.type_url)), } } @@ -87,12 +60,6 @@ impl From for Any { type_url: TENDERMINT_MISBEHAVIOR_TYPE_URL.to_string(), value: misbehaviour.encode_vec(), }, - - #[cfg(test)] - AnyMisbehaviour::Mock(misbehaviour) => Any { - type_url: MOCK_MISBEHAVIOUR_TYPE_URL.to_string(), - value: misbehaviour.encode_vec(), - }, } } } @@ -101,9 +68,6 @@ impl core::fmt::Display for AnyMisbehaviour { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { match self { AnyMisbehaviour::Tendermint(tm) => write!(f, "{tm}"), - - #[cfg(test)] - AnyMisbehaviour::Mock(mock) => write!(f, "{mock:?}"), } } } @@ -113,10 +77,3 @@ impl From for AnyMisbehaviour { Self::Tendermint(misbehaviour) } } - -#[cfg(test)] -impl From for AnyMisbehaviour { - fn from(misbehaviour: MockMisbehaviour) -> Self { - Self::Mock(misbehaviour) - } -} diff --git a/crates/relayer/src/object.rs b/crates/relayer/src/object.rs index d1ac7e2a09..aac3efb257 100644 --- a/crates/relayer/src/object.rs +++ b/crates/relayer/src/object.rs @@ -1,50 +1,28 @@ use std::fmt::Display; use flex_error::define_error; -use ibc_relayer_types::{ - applications::ics29_fee::events::IncentivizedPacket, - core::{ - ics02_client::events::UpdateClient, - ics03_connection::events::Attributes as ConnectionAttributes, - ics04_channel::events::{ - Attributes, - CloseInit, - SendPacket, - TimeoutPacket, - WriteAcknowledgement, - }, - ics24_host::identifier::{ - ChainId, - ChannelId, - ClientId, - ConnectionId, - PortId, - }, +use serde::{Deserialize, Serialize}; + +use ibc_relayer_types::applications::ics29_fee::events::IncentivizedPacket; +use ibc_relayer_types::core::{ + ics02_client::events::UpdateClient, + ics03_connection::events::Attributes as ConnectionAttributes, + ics04_channel::events::{ + Attributes, CloseInit, SendPacket, TimeoutPacket, UpgradeAttributes, WriteAcknowledgement, }, -}; -use serde::{ - Deserialize, - Serialize, + ics24_host::identifier::{ChainId, ChannelId, ClientId, ConnectionId, PortId}, }; -use crate::{ - chain::{ - counterparty::{ - channel_connection_client, - channel_connection_client_no_checks, - counterparty_chain_from_channel, - counterparty_chain_from_connection, - }, - handle::ChainHandle, - requests::{ - IncludeProof, - QueryClientStateRequest, - QueryHeight, - }, +use crate::chain::{ + counterparty::{ + channel_connection_client, channel_connection_client_no_checks, + counterparty_chain_from_channel, counterparty_chain_from_connection, }, - error::Error as RelayerError, - supervisor::Error as SupervisorError, + handle::ChainHandle, + requests::{IncludeProof, QueryClientStateRequest, QueryHeight}, }; +use crate::error::Error as RelayerError; +use crate::supervisor::Error as SupervisorError; /// Client #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] @@ -469,6 +447,38 @@ impl Object { .into()) } + pub fn channel_from_chan_upgrade_events( + attributes: &UpgradeAttributes, + src_chain: &impl ChainHandle, + allow_non_open_connection: bool, + ) -> Result { + let channel_id = attributes.channel_id(); + + let port_id = attributes.port_id(); + + let dst_chain_id = if allow_non_open_connection { + // Get the destination chain allowing for the possibility that the connection is not yet open. + // This is to support the optimistic channel handshake by allowing the channel worker to get + // the channel events while the connection is being established. + // The channel worker will eventually finish the channel handshake via the retry mechanism. + channel_connection_client_no_checks(src_chain, port_id, channel_id) + .map(|c| c.client.client_state.chain_id()) + .map_err(ObjectError::supervisor)? + } else { + channel_connection_client(src_chain, port_id, channel_id) + .map(|c| c.client.client_state.chain_id()) + .map_err(ObjectError::supervisor)? + }; + + Ok(Channel { + dst_chain_id, + src_chain_id: src_chain.id(), + src_channel_id: channel_id.clone(), + src_port_id: port_id.clone(), + } + .into()) + } + /// Build the object associated with the given [`SendPacket`] event. pub fn for_send_packet( e: &SendPacket, diff --git a/crates/relayer/src/path.rs b/crates/relayer/src/path.rs index e37510cc9b..5f0513e376 100644 --- a/crates/relayer/src/path.rs +++ b/crates/relayer/src/path.rs @@ -1,9 +1,6 @@ use ibc_relayer_types::core::{ ics04_channel::channel::IdentifiedChannelEnd, - ics24_host::identifier::{ - ChannelId, - PortId, - }, + ics24_host::identifier::{ChannelId, PortId}, }; /// Defines the channel & port identifiers which comprise diff --git a/crates/relayer/src/registry.rs b/crates/relayer/src/registry.rs index ea0a254d9f..efafa3a8f5 100644 --- a/crates/relayer/src/registry.rs +++ b/crates/relayer/src/registry.rs @@ -1,29 +1,16 @@ //! Registry for keeping track of [`ChainHandle`]s indexed by a `ChainId`. -use alloc::{ - collections::btree_map::BTreeMap as HashMap, - sync::Arc, -}; -use std::sync::{ - RwLock, - RwLockReadGuard, - RwLockWriteGuard, -}; +use alloc::{collections::btree_map::BTreeMap as HashMap, sync::Arc}; +use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard}; use ibc_relayer_types::core::ics24_host::identifier::ChainId; use tokio::runtime::Runtime as TokioRuntime; -use tracing::{ - trace, - warn, -}; +use tracing::{trace, warn}; use crate::{ chain::handle::ChainHandle, config::Config, - spawn::{ - spawn_chain_runtime, - SpawnError, - }, + spawn::{spawn_chain_runtime, SpawnError}, util::lock::RwArc, }; diff --git a/crates/relayer/src/rest.rs b/crates/relayer/src/rest.rs index 91458c7ab4..4900c5e7bf 100644 --- a/crates/relayer/src/rest.rs +++ b/crates/relayer/src/rest.rs @@ -1,17 +1,10 @@ use crossbeam_channel::TryRecvError; use ibc_relayer_types::core::ics24_host::identifier::ChainId; -use tracing::{ - error, - trace, -}; +use tracing::{error, trace}; use crate::{ config::Config, - rest::request::{ - ReplySender, - Request, - VersionInfo, - }, + rest::request::{ReplySender, Request, VersionInfo}, supervisor::dump_state::SupervisorState, }; diff --git a/crates/relayer/src/rest/error.rs b/crates/relayer/src/rest/error.rs index cbb0665307..5751be7c64 100644 --- a/crates/relayer/src/rest/error.rs +++ b/crates/relayer/src/rest/error.rs @@ -1,12 +1,5 @@ -use ibc_relayer_types::core::ics24_host::{ - error::ValidationErrorDetail, - identifier::ChainId, -}; -use serde::ser::{ - Serialize, - SerializeMap, - Serializer, -}; +use ibc_relayer_types::core::ics24_host::{error::ValidationErrorDetail, identifier::ChainId}; +use serde::ser::{Serialize, SerializeMap, Serializer}; use thiserror::Error; #[derive(Error, Debug)] diff --git a/crates/relayer/src/rest/request.rs b/crates/relayer/src/rest/request.rs index c9d1252f74..84ac6b696b 100644 --- a/crates/relayer/src/rest/request.rs +++ b/crates/relayer/src/rest/request.rs @@ -1,14 +1,7 @@ use ibc_relayer_types::core::ics24_host::identifier::ChainId; -use serde::{ - Deserialize, - Serialize, -}; - -use crate::{ - config::ChainConfig, - rest::RestApiError, - supervisor::dump_state::SupervisorState, -}; +use serde::{Deserialize, Serialize}; + +use crate::{config::ChainConfig, rest::RestApiError, supervisor::dump_state::SupervisorState}; pub type ReplySender = crossbeam_channel::Sender>; pub type ReplyReceiver = crossbeam_channel::Receiver>; diff --git a/crates/relayer/src/sdk_error.rs b/crates/relayer/src/sdk_error.rs index ef48c06be9..f9694716a3 100644 --- a/crates/relayer/src/sdk_error.rs +++ b/crates/relayer/src/sdk_error.rs @@ -1,6 +1,8 @@ use flex_error::define_error; use tendermint::abci::Code; +use crate::chain::cosmos::estimate::EstimatedGas; + // Provides mapping for errors returned from ibc-go and cosmos-sdk define_error! { SdkError { @@ -24,9 +26,13 @@ define_error! { { code: u32 } | e | { format_args!("unknown TX sync response error: {}", e.code) }, - OutOfGas - { code: u32 } - |_| { "the gas requirement is higher than the configured maximum gas! please check the Hermes config.toml".to_string() }, + OutOfGasDefault + { code: u32, amount: u64 } + |e| { format_args!("due to the Tx simulation failing, the configured default gas was used. Please check the Hermes config.toml and increase the configured `default_gas`. Current value is `{}`", e.amount) }, + + OutOfGasSimulated + { code: u32, amount: u64 } + |e| { format_args!("the issue might have been caused by a misconfiguration of Hermes. Please check the Hermes config.toml and increase either the `max_gas` or `gas_multiplier` settings. Simulated gas was: {}", e.amount) }, InsufficientFee { code: u32 } @@ -186,12 +192,15 @@ pub fn sdk_error_from_tx_result(code: Code, codespace: &str) -> SdkError { /// into IBC relayer domain-type errors. /// See [`tendermint_rpc::endpoint::broadcast::tx_sync::Response`]. /// Cf: -pub fn sdk_error_from_tx_sync_error_code(code: u32) -> SdkError { +pub fn sdk_error_from_tx_sync_error_code(code: u32, estimated_gas: EstimatedGas) -> SdkError { match code { // The primary reason (we know of) causing broadcast_tx_sync to fail // is due to "out of gas" errors. These are unrecoverable at the moment // on Hermes side. We'll inform the user to check for misconfiguration. - 11 => SdkError::out_of_gas(code), + 11 => match estimated_gas { + EstimatedGas::Default(amount) => SdkError::out_of_gas_default(code, amount), + EstimatedGas::Simulated(amount) => SdkError::out_of_gas_simulated(code, amount), + }, 13 => SdkError::insufficient_fee(code), _ => SdkError::unknown_tx_sync(code), } diff --git a/crates/relayer/src/spawn.rs b/crates/relayer/src/spawn.rs index ad143d7868..38cdb10830 100644 --- a/crates/relayer/src/spawn.rs +++ b/crates/relayer/src/spawn.rs @@ -6,15 +6,9 @@ use tokio::runtime::Runtime as TokioRuntime; use crate::{ chain::{ - astria::AstriaEndpoint, - cosmos::CosmosSdkChain, - handle::ChainHandle, - runtime::ChainRuntime, - }, - config::{ - ChainConfig, - Config, + astria::AstriaEndpoint, cosmos::CosmosSdkChain, handle::ChainHandle, runtime::ChainRuntime, }, + config::{ChainConfig, Config}, error::Error as RelayerError, }; diff --git a/crates/relayer/src/supervisor.rs b/crates/relayer/src/supervisor.rs index 26830f08d4..0bdb5d4658 100644 --- a/crates/relayer/src/supervisor.rs +++ b/crates/relayer/src/supervisor.rs @@ -1,86 +1,40 @@ -use alloc::{ - collections::btree_map::BTreeMap as HashMap, - sync::Arc, -}; -use core::{ - convert::Infallible, - ops::Deref, - time::Duration, -}; +use alloc::{collections::btree_map::BTreeMap as HashMap, sync::Arc}; +use core::{convert::Infallible, ops::Deref, time::Duration}; use std::sync::RwLock; -use crossbeam_channel::{ - unbounded, - Receiver, - Sender, -}; +use crossbeam_channel::{unbounded, Receiver, Sender}; use ibc_relayer_types::{ - core::ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }, + core::ics24_host::identifier::{ChainId, ChannelId, PortId}, events::IbcEvent, Height, }; use itertools::Itertools; -use tracing::{ - debug, - error, - error_span, - info, - instrument, - trace, - warn, -}; +use tracing::{debug, error, error_span, info, instrument, trace, warn}; use crate::{ - chain::{ - endpoint::HealthCheck, - handle::ChainHandle, - tracking::TrackingId, - }, + chain::{endpoint::HealthCheck, handle::ChainHandle, tracking::TrackingId}, config::Config, event::{ - source::{ - self, - Error as EventError, - ErrorDetail as EventErrorDetail, - EventBatch, - }, + source::{self, Error as EventError, ErrorDetail as EventErrorDetail, EventBatch}, IbcEventWithHeight, }, object::Object, - registry::{ - Registry, - SharedRegistry, - }, + registry::{Registry, SharedRegistry}, rest, supervisor::scan::ScanMode, telemetry, util::{ lock::LockExt, - task::{ - spawn_background_task, - Next, - TaskError, - TaskHandle, - }, + task::{spawn_background_task, Next, TaskError, TaskHandle}, }, worker::WorkerMap, }; pub mod client_state_filter; -use client_state_filter::{ - FilterPolicy, - Permission, -}; +use client_state_filter::{FilterPolicy, Permission}; pub mod error; -pub use error::{ - Error, - ErrorDetail, -}; +pub use error::{Error, ErrorDetail}; pub mod dump_state; use dump_state::SupervisorState; @@ -91,10 +45,7 @@ pub mod spawn; pub mod cmd; use cmd::SupervisorCmd; -use self::{ - scan::ChainScanner, - spawn::SpawnContext, -}; +use self::{scan::ChainScanner, spawn::SpawnContext}; type ArcBatch = Arc>; type Subscription = Receiver; @@ -419,13 +370,15 @@ fn relay_on_object( }; // Then, apply the client filter + // If the object is a CrossChain query discard it if the destination chain + // is not configured let client_filter_outcome = match object { Object::Client(client) => client_state_filter.control_client_object(registry, client), Object::Connection(conn) => client_state_filter.control_conn_object(registry, conn), Object::Channel(chan) => client_state_filter.control_chan_object(registry, chan), Object::Packet(packet) => client_state_filter.control_packet_object(registry, packet), + Object::CrossChainQuery(_ccq) => Ok(Permission::Allow), Object::Wallet(_wallet) => Ok(Permission::Allow), - Object::CrossChainQuery(_) => Ok(Permission::Allow), }; match client_filter_outcome { @@ -584,6 +537,31 @@ pub fn collect_events( || Object::client_from_chan_open_events(&attributes, src_chain).ok(), ); } + IbcEvent::UpgradeInitChannel(..) + | IbcEvent::UpgradeTryChannel(..) + | IbcEvent::UpgradeAckChannel(..) + | IbcEvent::UpgradeOpenChannel(..) + | IbcEvent::UpgradeErrorChannel(..) => { + collect_event( + &mut collected, + event_with_height.clone(), + mode.channels.enabled, + || { + event_with_height + .event + .clone() + .channel_upgrade_attributes() + .and_then(|attr| { + Object::channel_from_chan_upgrade_events( + &attr, + src_chain, + mode.connections.enabled, + ) + .ok() + }) + }, + ); + } IbcEvent::SendPacket(ref packet) => { collect_event( &mut collected, @@ -834,8 +812,33 @@ fn process_batch( workers.notify_new_block(&src_chain.id(), batch.height, new_block); } - // Forward the IBC events. + // Forward the IBC events to the appropriate workers for (object, events_with_heights) in collected.per_object.into_iter() { + if events_with_heights.is_empty() { + // Event batch is empty, nothing to do + continue; + } + + let Ok(src_chain) = registry.get_or_spawn(object.src_chain_id()) else { + trace!( + "skipping events for '{}': source chain '{}' is not registered", + object.short_name(), + object.src_chain_id() + ); + + continue; + }; + + let Ok(dst_chain) = registry.get_or_spawn(object.dst_chain_id()) else { + trace!( + "skipping events for '{}': destination chain '{}' is not registered", + object.short_name(), + object.src_chain_id() + ); + + continue; + }; + if !relay_on_object( config, registry, @@ -844,32 +847,23 @@ fn process_batch( &object, ) { trace!( - "skipping events for '{}'. \ - reason: filtering is enabled and channel does not match any allowed channels", + "skipping events for '{}': rejected by filtering policy", object.short_name() ); continue; } - if events_with_heights.is_empty() { - continue; - } - - let src = registry - .get_or_spawn(object.src_chain_id()) - .map_err(Error::spawn)?; - - let dst = registry - .get_or_spawn(object.dst_chain_id()) - .map_err(Error::spawn)?; - if let Object::Packet(ref _path) = object { - // Update telemetry info - telemetry!(send_telemetry(&src, &dst, &events_with_heights, _path)); + telemetry!(send_telemetry( + &src_chain, + &dst_chain, + &events_with_heights, + _path + )); } - let worker = workers.get_or_spawn(object, src, dst, config); + let worker = workers.get_or_spawn(object, src_chain, dst_chain, config); worker.send_events( batch.height, @@ -893,7 +887,6 @@ fn process_batch( /// So successfully sending a packet from chain A to chain B will result in first a SendPacket /// event with `chain_id = A` and `counterparty_chain_id = B` and then a WriteAcknowlegment /// event with `chain_id = B` and `counterparty_chain_id = A`. -#[cfg(feature = "telemetry")] fn send_telemetry( src: &Src, dst: &Dst, diff --git a/crates/relayer/src/supervisor/client_state_filter.rs b/crates/relayer/src/supervisor/client_state_filter.rs index 0575a60f5e..bd1aebbde1 100644 --- a/crates/relayer/src/supervisor/client_state_filter.rs +++ b/crates/relayer/src/supervisor/client_state_filter.rs @@ -5,27 +5,15 @@ use ibc_relayer_types::core::{ ics02_client::trust_threshold::TrustThreshold, ics03_connection::connection::ConnectionEnd, ics04_channel::error::Error as ChannelError, - ics24_host::identifier::{ - ChainId, - ChannelId, - ClientId, - ConnectionId, - PortId, - }, -}; -use tracing::{ - debug, - trace, + ics24_host::identifier::{ChainId, ChannelId, ClientId, ConnectionId, PortId}, }; +use tracing::{debug, trace}; use crate::{ chain::{ handle::ChainHandle, requests::{ - IncludeProof, - QueryChannelRequest, - QueryClientStateRequest, - QueryConnectionRequest, + IncludeProof, QueryChannelRequest, QueryClientStateRequest, QueryConnectionRequest, QueryHeight, }, }, diff --git a/crates/relayer/src/supervisor/dump_state.rs b/crates/relayer/src/supervisor/dump_state.rs index da601611c5..31bf07c093 100644 --- a/crates/relayer/src/supervisor/dump_state.rs +++ b/crates/relayer/src/supervisor/dump_state.rs @@ -1,30 +1,16 @@ use alloc::{ collections::BTreeMap, - fmt::{ - Display, - Error as FmtError, - Formatter, - }, + fmt::{Display, Error as FmtError, Formatter}, }; use ibc_relayer_types::core::ics24_host::identifier::ChainId; use itertools::Itertools; -use serde::{ - Deserialize, - Serialize, -}; +use serde::{Deserialize, Serialize}; use tracing::info; use crate::{ - object::{ - Object, - ObjectType, - }, - worker::{ - WorkerData, - WorkerHandle, - WorkerId, - }, + object::{Object, ObjectType}, + worker::{WorkerData, WorkerHandle, WorkerId}, }; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] diff --git a/crates/relayer/src/supervisor/error.rs b/crates/relayer/src/supervisor/error.rs index 51f3f8d88e..97b22ffb97 100644 --- a/crates/relayer/src/supervisor/error.rs +++ b/crates/relayer/src/supervisor/error.rs @@ -1,18 +1,11 @@ use flex_error::define_error; use ibc_relayer_types::core::{ ics03_connection::connection::Counterparty, - ics24_host::identifier::{ - ChainId, - ChannelId, - ConnectionId, - PortId, - }, + ics24_host::identifier::{ChainId, ChannelId, ConnectionId, PortId}, }; use crate::{ - error::Error as RelayerError, - spawn::SpawnError, - supervisor::scan::Error as ScanError, + error::Error as RelayerError, spawn::SpawnError, supervisor::scan::Error as ScanError, }; define_error! { diff --git a/crates/relayer/src/supervisor/scan.rs b/crates/relayer/src/supervisor/scan.rs index ed3d4df4d5..0de73c5ed8 100644 --- a/crates/relayer/src/supervisor/scan.rs +++ b/crates/relayer/src/supervisor/scan.rs @@ -1,77 +1,40 @@ -use core::fmt::{ - Display, - Error as FmtError, - Formatter, -}; +use core::fmt::{Display, Error as FmtError, Formatter}; use std::collections::BTreeMap; use ibc_relayer_types::core::{ - ics03_connection::connection::{ - IdentifiedConnectionEnd, - State as ConnectionState, - }, + ics03_connection::connection::{IdentifiedConnectionEnd, State as ConnectionState}, ics04_channel::{ - channel::{ - IdentifiedChannelEnd, - State as ChannelState, - }, + channel::{IdentifiedChannelEnd, State as ChannelState}, packet::Sequence, }, - ics24_host::identifier::{ - ChainId, - ChannelId, - ClientId, - ConnectionId, - PortId, - }, + ics24_host::identifier::{ChainId, ChannelId, ClientId, ConnectionId, PortId}, }; use itertools::Itertools; -use tracing::{ - debug, - error, - error_span, - info, - warn, -}; +use tracing::{debug, error, error_span, info, warn}; use crate::{ chain::{ counterparty::{ - channel_on_destination, - connection_state_on_destination, - unreceived_acknowledgements, + channel_on_destination, connection_state_on_destination, unreceived_acknowledgements, unreceived_packets, }, handle::ChainHandle, requests::{ - IncludeProof, - PageRequest, - QueryChannelRequest, - QueryClientConnectionsRequest, - QueryClientStateRequest, - QueryClientStatesRequest, - QueryConnectionChannelsRequest, - QueryConnectionRequest, - QueryHeight, + IncludeProof, PageRequest, Paginate, QueryChannelRequest, + QueryClientConnectionsRequest, QueryClientStateRequest, QueryClientStatesRequest, + QueryConnectionChannelsRequest, QueryConnectionRequest, QueryHeight, }, }, client_state::IdentifiedAnyClientState, config::{ - filter::{ - ChannelFilters, - ChannelPolicy, - }, - ChainConfig, - Config, + filter::{ChannelFilters, ChannelPolicy}, + ChainConfig, Config, }, error::Error as RelayerError, path::PathIdentifiers, registry::Registry, spawn::SpawnError, - supervisor::client_state_filter::{ - FilterPolicy, - Permission, - }, + supervisor::client_state_filter::{FilterPolicy, Permission}, telemetry, }; @@ -271,9 +234,17 @@ impl ChannelScan { .as_ref() .and_then(|c| PathIdentifiers::from_channel_end(c.clone())) .map(|ids| { - unreceived_packets(counterparty_chain, chain, &ids) - .map(|(seq, _)| seq) - .unwrap_or_default() + unreceived_packets( + counterparty_chain, + chain, + &ids, + Paginate::PerPage { + per_page: 1, + total: 1, + }, + ) + .map(|(seq, _)| seq) + .unwrap_or_default() }) } @@ -287,9 +258,17 @@ impl ChannelScan { .as_ref() .and_then(|c| PathIdentifiers::from_channel_end(c.clone()))?; - let acks = unreceived_acknowledgements(counterparty_chain, chain, &ids) - .map(|sns| sns.map_or(vec![], |(sns, _)| sns)) - .unwrap_or_default(); + let acks = unreceived_acknowledgements( + counterparty_chain, + chain, + &ids, + Paginate::PerPage { + per_page: 1, + total: 1, + }, + ) + .map(|sns| sns.map_or(vec![], |(sns, _)| sns)) + .unwrap_or_default(); Some(acks) } diff --git a/crates/relayer/src/supervisor/spawn.rs b/crates/relayer/src/supervisor/spawn.rs index 132f4067e7..367989102b 100644 --- a/crates/relayer/src/supervisor/spawn.rs +++ b/crates/relayer/src/supervisor/spawn.rs @@ -2,36 +2,17 @@ use ibc_relayer_types::core::{ ics03_connection::connection::IdentifiedConnectionEnd, ics04_channel::channel::State as ChannelState, }; -use tracing::{ - error, - info, -}; +use tracing::{error, info}; use super::{ - scan::{ - ChainScan, - ChainsScan, - ChannelScan, - ClientScan, - ConnectionScan, - }, + scan::{ChainScan, ChainsScan, ChannelScan, ClientScan, ConnectionScan}, Error, }; use crate::{ - chain::{ - counterparty::connection_state_on_destination, - handle::ChainHandle, - }, + chain::{counterparty::connection_state_on_destination, handle::ChainHandle}, client_state::IdentifiedAnyClientState, config::Config, - object::{ - Channel, - Client, - Connection, - Object, - Packet, - Wallet, - }, + object::{Channel, Client, Connection, Object, Packet, Wallet}, registry::Registry, supervisor::error::Error as SupervisorError, telemetry, @@ -261,9 +242,12 @@ impl<'a, Chain: ChainHandle> SpawnContext<'a, Chain> { chan_state_dst ); + let is_channel_upgrading = channel_scan.channel.channel_end.is_upgrading(); + if (mode.clients.enabled || mode.packets.enabled) && chan_state_src.is_open() && (chan_state_dst.is_open() || chan_state_dst.is_closed()) + && !is_channel_upgrading { if mode.clients.enabled { // Spawn the client worker @@ -320,7 +304,7 @@ impl<'a, Chain: ChainHandle> SpawnContext<'a, Chain> { } Ok(mode.clients.enabled) - } else if mode.channels.enabled { + } else if mode.channels.enabled && !is_channel_upgrading { let has_packets = || { !channel_scan .unreceived_packets_on_counterparty(&counterparty_chain, &chain) @@ -356,6 +340,35 @@ impl<'a, Chain: ChainHandle> SpawnContext<'a, Chain> { } else { Ok(false) } + } else if is_channel_upgrading { + let path_object = Object::Packet(Packet { + dst_chain_id: counterparty_chain.id(), + src_chain_id: chain.id(), + src_channel_id: channel_scan.channel.channel_id.clone(), + src_port_id: channel_scan.channel.port_id.clone(), + }); + + self.workers + .spawn( + chain.clone(), + counterparty_chain.clone(), + &path_object, + self.config, + ) + .then(|| info!("spawned packet worker: {}", path_object.short_name())); + + let channel_object = Object::Channel(Channel { + dst_chain_id: counterparty_chain.id(), + src_chain_id: chain.id(), + src_channel_id: channel_scan.channel.channel_id, + src_port_id: channel_scan.channel.port_id, + }); + + self.workers + .spawn(chain, counterparty_chain, &channel_object, self.config) + .then(|| info!("spawned channel worker: {}", channel_object.short_name())); + + Ok(true) } else { Ok(false) } diff --git a/crates/relayer/src/telemetry.rs b/crates/relayer/src/telemetry.rs index 0734ee454b..bc8bc77ae6 100644 --- a/crates/relayer/src/telemetry.rs +++ b/crates/relayer/src/telemetry.rs @@ -1,15 +1,6 @@ // If the `telemetry` feature is enabled, re-export the `ibc-telemetry` state. -#[cfg(feature = "telemetry")] pub type Telemetry = alloc::sync::Arc; -// Otherwise, define and export a dummy type. -#[cfg(not(feature = "telemetry"))] -#[derive(Clone, Debug)] -pub struct TelemetryDisabled; - -#[cfg(not(feature = "telemetry"))] -pub type Telemetry = TelemetryDisabled; - /// A macro to send metric updates via a telemetry handle, /// only if the `telemetry` feature is enabled. /// Otherwise, it compiles to a no-op. @@ -32,7 +23,6 @@ pub type Telemetry = TelemetryDisabled; #[macro_export] macro_rules! telemetry { ($id:ident, $($args:expr),* $(,)*) => { - #[cfg(feature = "telemetry")] #[allow(unused_imports, unused_variables)] { use ::ibc_telemetry::state::WorkerType; @@ -42,7 +32,6 @@ macro_rules! telemetry { }; ($e:expr) => { - #[cfg(feature = "telemetry")] #[allow(unused_imports, unused_variables)] { use ::ibc_telemetry::state::WorkerType; diff --git a/crates/relayer/src/transfer.rs b/crates/relayer/src/transfer.rs index b776f68e57..94031c5ba0 100644 --- a/crates/relayer/src/transfer.rs +++ b/crates/relayer/src/transfer.rs @@ -1,53 +1,27 @@ use core::time::Duration; -use std::{ - ops::Add, - str::FromStr, -}; +use std::{ops::Add, str::FromStr}; -use flex_error::{ - define_error, - DetailOnly, -}; -use ibc_proto::{ - cosmos::base::v1beta1::Coin, - google::protobuf::Any, -}; +use flex_error::{define_error, DetailOnly}; +use ibc_proto::{cosmos::base::v1beta1::Coin, google::protobuf::Any}; use ibc_relayer_types::{ applications::transfer::{ error::Error as Ics20Error, - msgs::{ - transfer::MsgTransfer, - ASTRIA_WITHDRAWAL_TYPE_URL, - }, + msgs::{transfer::MsgTransfer, ASTRIA_WITHDRAWAL_TYPE_URL}, Amount, }, core::{ ics04_channel::timeout::TimeoutHeight, - ics24_host::identifier::{ - ChainId, - ChannelId, - PortId, - }, + ics24_host::identifier::{ChainId, ChannelId, PortId}, }, events::IbcEvent, - signer::{ - Signer, - SignerError, - }, - timestamp::{ - Timestamp, - TimestampOverflowError, - }, + signer::{Signer, SignerError}, + timestamp::{Timestamp, TimestampOverflowError}, tx_msg::Msg, }; use prost::Message; use crate::{ - chain::{ - endpoint::ChainStatus, - handle::ChainHandle, - tracking::TrackedMsgs, - }, + chain::{endpoint::ChainStatus, handle::ChainHandle, tracking::TrackedMsgs}, error::Error, event::IbcEventWithHeight, }; @@ -195,10 +169,8 @@ fn build_transfer_message_astria( timeout_height: TimeoutHeight, timeout_timestamp: Timestamp, ) -> Any { - use astria_core::primitive::v1::{ - asset::Denom, - Address, - }; + use astria_core::primitive::v1::{asset::Denom, Address}; + use prost::Message as _; let sender: Address = sender .as_ref() @@ -240,6 +212,7 @@ fn build_transfer_message_astria( .to_string(), memo: String::new(), bridge_address: None, + use_compat_address: false, // TODO: set to true for noble }; Any { diff --git a/crates/relayer/src/upgrade_chain.rs b/crates/relayer/src/upgrade_chain.rs index 145817804c..2889d7ab62 100644 --- a/crates/relayer/src/upgrade_chain.rs +++ b/crates/relayer/src/upgrade_chain.rs @@ -5,47 +5,25 @@ use std::ops::Add; use bytes::BufMut; use flex_error::define_error; -use ibc_proto::{ - cosmos::{ - gov::{ - v1::MsgSubmitProposal, - v1beta1::MsgSubmitProposal as LegacyMsgSubmitProposal, - }, - upgrade::v1beta1::Plan, - }, - google::protobuf::Any, - ibc::core::client::v1::{ - MsgIbcSoftwareUpgrade, - UpgradeProposal, - }, -}; -use ibc_relayer_types::{ - clients::ics07_tendermint::client_state::UpgradeOptions, - core::{ - ics02_client::client_state::ClientState, - ics24_host::identifier::{ - ChainId, - ClientId, - }, - }, - downcast, - Height, -}; + use tendermint::Hash as TxHash; -use crate::{ - chain::{ - handle::ChainHandle, - requests::{ - IncludeProof, - QueryClientStateRequest, - QueryHeight, - }, - tracking::TrackedMsgs, - }, - client_state::AnyClientState, - error::Error, -}; +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::{MsgIbcSoftwareUpgrade, UpgradeProposal}; +use ibc_relayer_types::clients::ics07_tendermint::client_state::UpgradeOptions; +use ibc_relayer_types::core::ics02_client::client_state::UpgradableClientState; +use ibc_relayer_types::core::ics24_host::identifier::{ChainId, ClientId}; +use ibc_relayer_types::{downcast, Height}; +use tracing::warn; + +use crate::chain::handle::ChainHandle; +use crate::chain::requests::{IncludeProof, QueryClientStateRequest, QueryHeight}; +use crate::chain::tracking::TrackedMsgs; +use crate::client_state::AnyClientState; +use crate::error::Error; define_error! { UpgradeChainError { @@ -119,22 +97,32 @@ pub fn build_and_send_ibc_upgrade_proposal( /// 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. +/// of Cosmos SDK is used, if any. If there is no SDK version, we assume that the legacy upgrade is required. pub fn requires_legacy_upgrade_proposal(dst_chain: impl ChainHandle) -> bool { - let version_specs = dst_chain.version_specs().unwrap(); + let Ok(version_specs) = dst_chain.version_specs() else { + warn!("failed to get version specs, assuming legacy upgrade proposal is required"); + return true; + }; + + let sdk_before_50 = version_specs + .cosmos_sdk + .as_ref() + .map(|s| s.minor < 50) + .unwrap_or(true); + match version_specs.ibc_go { + None => sdk_before_50, 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 + sdk_before_50 } else { ibc_version.major < 8 } } - None => version_specs.cosmos_sdk.minor < 50, } } diff --git a/crates/relayer/src/util.rs b/crates/relayer/src/util.rs index 4233f9d6e5..765792e92b 100644 --- a/crates/relayer/src/util.rs +++ b/crates/relayer/src/util.rs @@ -1,13 +1,11 @@ mod block_on; -pub use block_on::{ - block_on, - spawn_blocking, -}; +pub use block_on::{block_on, spawn_blocking}; pub mod collate; pub mod compat_mode; pub mod debug_section; pub mod diff; +pub mod excluded_sequences; pub mod iter; pub mod lock; pub mod pretty; @@ -17,3 +15,18 @@ pub mod retry; pub mod seq_range; pub mod stream; pub mod task; + +/// Helper function to create a gRPC client. +pub async fn create_grpc_client( + grpc_addr: tonic::transport::Uri, + client_constructor: impl FnOnce(tonic::transport::Channel) -> T, +) -> Result { + let tls_config = tonic::transport::ClientTlsConfig::new().with_native_roots(); + let channel = tonic::transport::Channel::builder(grpc_addr) + .tls_config(tls_config) + .map_err(crate::error::Error::grpc_transport)? + .connect() + .await + .map_err(crate::error::Error::grpc_transport)?; + Ok(client_constructor(channel)) +} diff --git a/crates/relayer/src/util/collate.rs b/crates/relayer/src/util/collate.rs index 4190c1e98b..092a579bd1 100644 --- a/crates/relayer/src/util/collate.rs +++ b/crates/relayer/src/util/collate.rs @@ -1,12 +1,6 @@ -use std::{ - fmt, - ops::Add, -}; - -use serde::{ - Deserialize, - Serialize, -}; +use std::{fmt, ops::Add}; + +use serde::{Deserialize, Serialize}; #[derive(Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Collated { diff --git a/crates/relayer/src/util/compat_mode.rs b/crates/relayer/src/util/compat_mode.rs index b5f3300f92..97d4ffd6e8 100644 --- a/crates/relayer/src/util/compat_mode.rs +++ b/crates/relayer/src/util/compat_mode.rs @@ -2,10 +2,7 @@ use tendermint::Version; use tendermint_rpc::client::CompatMode as TmCompatMode; use tracing::warn; -use crate::{ - config::compat_mode::CompatMode, - error::Error, -}; +use crate::{config::compat_mode::CompatMode, error::Error}; /// This is a wrapper around tendermint-rs CompatMode::from_version() method. /// diff --git a/crates/relayer/src/util/diff.rs b/crates/relayer/src/util/diff.rs index 802f81f7aa..e641213a84 100644 --- a/crates/relayer/src/util/diff.rs +++ b/crates/relayer/src/util/diff.rs @@ -1,8 +1,5 @@ use alloc::collections::BTreeMap as HashMap; -use core::{ - cmp::Ord, - hash::Hash, -}; +use core::{cmp::Ord, hash::Hash}; /// A change between two dictionaries. #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] diff --git a/crates/relayer/src/util/excluded_sequences.rs b/crates/relayer/src/util/excluded_sequences.rs new file mode 100644 index 0000000000..800a4c8c15 --- /dev/null +++ b/crates/relayer/src/util/excluded_sequences.rs @@ -0,0 +1,113 @@ +use serde::de::{Error, MapAccess, Visitor}; +use serde::ser::SerializeMap; +use serde::Deserializer; +use serde::Serializer; +use serde_derive::Deserialize; +use serde_derive::Serialize; +use std::collections::BTreeMap; +use std::fmt; +use std::str::FromStr; + +use ibc_relayer_types::core::ics04_channel::packet::Sequence; +use ibc_relayer_types::core::ics24_host::identifier::ChannelId; + +use crate::chain::cosmos::config::error::Error as ConfigError; + +#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] +pub struct ExcludedSequences { + #[serde( + deserialize_with = "deserialize_excluded_sequences", + serialize_with = "serialize_excluded_sequences", + flatten + )] + pub map: BTreeMap>, +} + +impl ExcludedSequences { + pub fn new(map: BTreeMap>) -> Self { + Self { map } + } +} + +fn serialize_excluded_sequences( + map: &BTreeMap>, + serializer: S, +) -> Result +where + S: Serializer, +{ + let mut seq = serializer.serialize_map(Some(map.len()))?; + for (k, v) in map { + seq.serialize_entry(k, v)?; + } + seq.end() +} + +fn deserialize_excluded_sequences<'de, D>( + deserializer: D, +) -> Result>, D::Error> +where + D: Deserializer<'de>, +{ + deserializer.deserialize_map(ExcludedSequencesVisitor) +} + +struct ExcludedSequencesVisitor; + +impl<'de> Visitor<'de> for ExcludedSequencesVisitor { + type Value = BTreeMap>; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("expected list of excluded sequences") + } + + fn visit_map(self, mut access: M) -> Result + where + M: MapAccess<'de>, + { + let mut map = BTreeMap::new(); + while let Some((key, value)) = access.next_entry::()? { + let channel_id = ChannelId::from_str(&key).map_err(|e| Error::custom(e.to_string()))?; + let sequences = + parse_sequence_range(&value).map_err(|e| Error::custom(e.to_string()))?; + map.insert(channel_id, sequences); + } + Ok(map) + } +} + +fn parse_sequence_range(value: &toml::Value) -> Result, ConfigError> { + let mut res = Vec::new(); + let sequences = value + .as_array() + .ok_or_else(ConfigError::expected_excluded_sequences_array)?; + for sequence in sequences.iter() { + if let Some(seq_str) = sequence.as_str() { + let (start, end) = get_start_and_end(seq_str)?; + for i in start..=end { + let seq = Sequence::from(i); + res.push(seq); + } + } else if let Some(seq) = sequence.as_integer() { + let seq = Sequence::from(seq as u64); + res.push(seq); + } + } + Ok(res) +} + +fn get_start_and_end(value: &str) -> Result<(u64, u64), ConfigError> { + let split: Vec<&str> = value.split('-').collect(); + let start: u64 = split + .first() + .ok_or_else(|| ConfigError::missing_start_excluded_sequence(value.to_string()))? + .parse() + .map_err(|e| ConfigError::parsing_start_excluded_sequence_failed(value.to_string(), e))?; + let end: u64 = split + .last() + .ok_or_else(|| ConfigError::missing_end_excluded_sequence(value.to_string()))? + .parse() + .map_err(|e| ConfigError::parsing_end_excluded_sequence_failed(value.to_string(), e))?; + + Ok((start, end)) +} diff --git a/crates/relayer/src/util/lock.rs b/crates/relayer/src/util/lock.rs index 66f7f5bb23..5fa139b9fd 100644 --- a/crates/relayer/src/util/lock.rs +++ b/crates/relayer/src/util/lock.rs @@ -1,9 +1,4 @@ -use std::sync::{ - Arc, - RwLock, - RwLockReadGuard, - RwLockWriteGuard, -}; +use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}; pub type RwArc = Arc>; diff --git a/crates/relayer/src/util/pretty.rs b/crates/relayer/src/util/pretty.rs index 5124b7b410..0b433bd289 100644 --- a/crates/relayer/src/util/pretty.rs +++ b/crates/relayer/src/util/pretty.rs @@ -1,29 +1,13 @@ -use core::fmt::{ - Debug, - Display, - Error as FmtError, - Formatter, -}; +use core::fmt::{Debug, Display, Error as FmtError, Formatter}; use std::time::Duration; use ibc_proto::{ cosmos::tx::v1beta1::Fee, google::protobuf::Any, ibc::core::{ - channel::v1::{ - Counterparty as ChannelCounterparty, - IdentifiedChannel, - }, - client::v1::{ - ConsensusStateWithHeight, - Height, - IdentifiedClientState, - }, - connection::v1::{ - Counterparty as ConnectionCounterparty, - IdentifiedConnection, - Version, - }, + channel::v1::{Counterparty as ChannelCounterparty, IdentifiedChannel}, + client::v1::{ConsensusStateWithHeight, Height, IdentifiedClientState}, + connection::v1::{Counterparty as ConnectionCounterparty, IdentifiedConnection, Version}, }, }; use tendermint::abci::Code; diff --git a/crates/relayer/src/util/profiling.rs b/crates/relayer/src/util/profiling.rs index 498b0255ca..fe27bd3fdb 100644 --- a/crates/relayer/src/util/profiling.rs +++ b/crates/relayer/src/util/profiling.rs @@ -1,14 +1,8 @@ use std::{ - fs::{ - File, - OpenOptions, - }, + fs::{File, OpenOptions}, path::Path, sync::{ - atomic::{ - AtomicUsize, - Ordering::Relaxed, - }, + atomic::{AtomicUsize, Ordering::Relaxed}, Mutex, }, }; @@ -18,7 +12,7 @@ use serde_derive::Serialize; use serde_json::Value; std::thread_local! { - pub static DEPTH: AtomicUsize = AtomicUsize::new(0); + pub static DEPTH: AtomicUsize = const { AtomicUsize::new(0) }; } static FILE: OnceCell> = OnceCell::new(); @@ -108,7 +102,6 @@ impl Drop for Timer { pub fn open_or_create_profile_file(file_name: &Path) { let file = OpenOptions::new() - .write(true) .append(true) .create(true) .open(file_name) diff --git a/crates/relayer/src/util/queue.rs b/crates/relayer/src/util/queue.rs index f270919a5b..2e9a0115eb 100644 --- a/crates/relayer/src/util/queue.rs +++ b/crates/relayer/src/util/queue.rs @@ -1,8 +1,5 @@ use alloc::collections::VecDeque; -use std::sync::{ - Arc, - RwLock, -}; +use std::sync::{Arc, RwLock}; use crate::util::lock::LockExt; diff --git a/crates/relayer/src/util/retry.rs b/crates/relayer/src/util/retry.rs index feeec67b94..e851fe1adb 100644 --- a/crates/relayer/src/util/retry.rs +++ b/crates/relayer/src/util/retry.rs @@ -1,13 +1,8 @@ use core::time::Duration; pub use retry::{ - delay::{ - Fibonacci, - Fixed, - }, - retry_with_index, - Error as RetryError, - OperationResult as RetryResult, + delay::{Fibonacci, Fixed}, + retry_with_index, Error as RetryError, OperationResult as RetryResult, }; #[derive(Copy, Clone, Debug)] diff --git a/crates/relayer/src/util/seq_range.rs b/crates/relayer/src/util/seq_range.rs index d569d156ef..229ab124e6 100644 --- a/crates/relayer/src/util/seq_range.rs +++ b/crates/relayer/src/util/seq_range.rs @@ -18,7 +18,7 @@ pub enum Error { /// - A range is specified as `start..end`, where `start` and `end` are sequence numbers. /// - If `start` is omitted, the range starts at the minimum sequence number. /// - If `end` is omitted, the range ends at the maximum sequence number. -/// - If both `start` and `end` are omitted, the range sastifies any sequence number. +/// - If both `start` and `end` are omitted, the range satisfies any sequence number. /// /// # Examples /// - `1` Single sequence number `1` @@ -39,7 +39,7 @@ pub fn parse_seq_ranges(s: &str) -> Result>, Error> /// - A range is specified as `start..end`, where `start` and `end` are sequence numbers. /// - If `start` is omitted, the range starts at the minimum sequence number. /// - If `end` is omitted, the range ends at the maximum sequence number.` -/// - If both `start` and `end` are omitted, the range sastifies any sequence number. +/// - If both `start` and `end` are omitted, the range satisfies any sequence number. /// /// # Examples /// - `1` Single sequence number `1` diff --git a/crates/relayer/src/util/stream.rs b/crates/relayer/src/util/stream.rs index 1f125a31b5..407fe0c47d 100644 --- a/crates/relayer/src/util/stream.rs +++ b/crates/relayer/src/util/stream.rs @@ -162,11 +162,7 @@ where #[cfg(test)] mod tests { - use futures::{ - executor::block_on, - stream, - StreamExt, - }; + use futures::{executor::block_on, stream, StreamExt}; use test_log::test; use super::*; diff --git a/crates/relayer/src/util/task.rs b/crates/relayer/src/util/task.rs index 32c63cd70d..707bda8ee9 100644 --- a/crates/relayer/src/util/task.rs +++ b/crates/relayer/src/util/task.rs @@ -1,25 +1,11 @@ -use core::{ - fmt::Display, - mem, - time::Duration, -}; +use core::{fmt::Display, mem, time::Duration}; use std::{ - sync::{ - Arc, - RwLock, - }, + sync::{Arc, RwLock}, thread, }; -use crossbeam_channel::{ - bounded, - Sender, -}; -use tracing::{ - debug, - error, - warn, -}; +use crossbeam_channel::{bounded, Sender}; +use tracing::{debug, error, warn}; use crate::util::lock::LockExt; diff --git a/crates/relayer/src/worker.rs b/crates/relayer/src/worker.rs index 71df19994e..5861b4d6ca 100644 --- a/crates/relayer/src/worker.rs +++ b/crates/relayer/src/worker.rs @@ -1,30 +1,16 @@ use alloc::sync::Arc; -use core::fmt::{ - Display, - Error as FmtError, - Formatter, -}; +use core::fmt::{Display, Error as FmtError, Formatter}; use std::sync::Mutex; use ibc_relayer_types::core::ics04_channel::channel::Ordering; -use serde::{ - Deserialize, - Serialize, -}; +use serde::{Deserialize, Serialize}; use tracing::error; use crate::{ - chain::handle::{ - ChainHandle, - ChainHandlePair, - }, + chain::handle::{ChainHandle, ChainHandlePair}, config::Config, foreign_client::ForeignClient, - link::{ - Link, - LinkParameters, - Resubmit, - }, + link::{Link, LinkParameters, Resubmit}, object::Object, }; @@ -34,10 +20,7 @@ mod error; pub use error::RunError; mod handle; -pub use handle::{ - WorkerData, - WorkerHandle, -}; +pub use handle::{WorkerData, WorkerHandle}; mod cmd; pub use cmd::WorkerCmd; @@ -128,6 +111,12 @@ pub fn spawn_worker_tasks( (Some(cmd_tx), None) } Object::Packet(path) => { + let exclude_src_sequences = config + .find_chain(&chains.a.id()) + .map(|chain_config| chain_config.excluded_sequences(&path.src_channel_id)) + .unwrap_or_default() + .to_vec(); + let packets_config = config.mode.packets; let link_res = Link::new_from_opts( chains.a.clone(), @@ -137,6 +126,7 @@ pub fn spawn_worker_tasks( src_channel_id: path.src_channel_id.clone(), max_memo_size: packets_config.ics20_max_memo_size, max_receiver_size: packets_config.ics20_max_receiver_size, + exclude_src_sequences, }, packets_config.tx_confirmation, packets_config.auto_register_counterparty_payee, @@ -146,7 +136,7 @@ pub fn spawn_worker_tasks( Ok(link) => { let channel_ordering = link.a_to_b.channel().ordering; let should_clear_on_start = - packets_config.clear_on_start || channel_ordering == Ordering::Ordered; + should_clear_on_start(&packets_config, channel_ordering); let (cmd_tx, cmd_rx) = crossbeam_channel::unbounded(); let link = Arc::new(Mutex::new(link)); @@ -180,19 +170,31 @@ pub fn spawn_worker_tasks( let resubmit = Resubmit::from_clear_interval(clear_interval); + let (clear_cmd_tx, clear_cmd_rx) = crossbeam_channel::unbounded(); + let clear_task = packet::spawn_clear_cmd_worker( + cmd_rx, + link.clone(), + should_clear_on_start, + clear_interval, + config.mode.packets.clear_limit, + clear_cmd_tx, + ); + task_handles.push(clear_task); + // 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( - cmd_rx, + clear_cmd_rx, link.clone(), path.clone(), filter, ), None => packet::spawn_packet_cmd_worker( - cmd_rx, + clear_cmd_rx, link.clone(), should_clear_on_start, clear_interval, + config.mode.packets.clear_limit, path.clone(), ), }; @@ -220,18 +222,34 @@ pub fn spawn_worker_tasks( } Object::CrossChainQuery(cross_chain_query) => { - let (cmd_tx, cmd_rx) = crossbeam_channel::unbounded(); - let cross_chain_query_task = cross_chain_query::spawn_cross_chain_query_worker( - chains.a.clone(), - chains.b, - cmd_rx, - cross_chain_query.clone(), - ); - task_handles.push(cross_chain_query_task); - - (Some(cmd_tx), None) + if config + .chains + .iter() + .any(|chain| chain.id() == &cross_chain_query.dst_chain_id && chain.allow_ccq()) + { + let (cmd_tx, cmd_rx) = crossbeam_channel::unbounded(); + let cross_chain_query_task = cross_chain_query::spawn_cross_chain_query_worker( + chains.a.clone(), + chains.b, + cmd_rx, + cross_chain_query.clone(), + ); + task_handles.push(cross_chain_query_task); + + (Some(cmd_tx), None) + } else { + (None, None) + } } }; WorkerHandle::new(id, object, data, cmd_tx, task_handles) } + +fn should_clear_on_start(config: &crate::config::Packets, channel_ordering: Ordering) -> bool { + if config.force_disable_clear_on_start { + false + } else { + config.clear_on_start || channel_ordering == Ordering::Ordered + } +} diff --git a/crates/relayer/src/worker/channel.rs b/crates/relayer/src/worker/channel.rs index d9f7269990..5c722cb262 100644 --- a/crates/relayer/src/worker/channel.rs +++ b/crates/relayer/src/worker/channel.rs @@ -1,39 +1,21 @@ use core::time::Duration; - use crossbeam_channel::Receiver; -use tracing::{ - debug, - error_span, -}; +use ibc_relayer_types::events::IbcEventType; +use tracing::{debug, error_span, warn}; -use super::{ - error::RunError, - WorkerCmd, -}; +use crate::chain::requests::QueryHeight; +use crate::channel::{channel_handshake_retry, Channel as RelayChannel}; +use crate::util::retry::RetryResult; +use crate::util::task::{spawn_background_task, Next, TaskError, TaskHandle}; use crate::{ - chain::handle::{ - ChainHandle, - ChainHandlePair, - }, - channel::{ - channel_handshake_retry, - Channel as RelayChannel, - }, + chain::handle::{ChainHandle, ChainHandlePair}, object::Channel, - util::{ - retry::{ - retry_with_index, - RetryResult, - }, - task::{ - spawn_background_task, - Next, - TaskError, - TaskHandle, - }, - }, + util::retry::retry_with_index, }; +use super::error::RunError; +use super::WorkerCmd; + fn max_block_times( chains: &ChainHandlePair, ) -> Duration { @@ -54,6 +36,7 @@ pub fn spawn_channel_worker( cmd_rx: Receiver, ) -> TaskHandle { let mut complete_handshake_on_new_block = true; + spawn_background_task( error_span!("worker.channel", channel = %channel.short_name()), Some(Duration::from_millis(200)), @@ -68,20 +51,68 @@ pub fn spawn_channel_worker( debug!("starts processing {:?}", last_event); complete_handshake_on_new_block = false; + if let Some(event_with_height) = last_event { - retry_with_index( - channel_handshake_retry::default_strategy(max_block_times), - |index| match RelayChannel::restore_from_event( - chains.a.clone(), - chains.b.clone(), - event_with_height.event.clone(), - ) { - Ok(mut handshake_channel) => handshake_channel - .step_event(&event_with_height.event, index), - Err(_) => RetryResult::Retry(index), - }, - ) - .map_err(|e| TaskError::Fatal(RunError::retry(e))) + match event_with_height.event.event_type() { + IbcEventType::UpgradeInitChannel + | IbcEventType::UpgradeTryChannel + | IbcEventType::UpgradeAckChannel + | IbcEventType::UpgradeConfirmChannel + | IbcEventType::UpgradeOpenChannel + | IbcEventType::UpgradeTimeoutChannel => retry_with_index( + channel_handshake_retry::default_strategy(max_block_times), + |index| match RelayChannel::restore_from_state( + chains.a.clone(), + chains.b.clone(), + channel.clone(), + QueryHeight::Latest, + ) { + Ok((mut handshake_channel, state)) => { + handshake_channel.step_state(state, index) + } + Err(_) => RetryResult::Retry(index), + }, + ) + .map_err(|e| TaskError::Fatal(RunError::retry(e))), + + IbcEventType::UpgradeErrorChannel => retry_with_index( + channel_handshake_retry::default_strategy(max_block_times), + |index| match RelayChannel::restore_from_state( + chains.a.clone(), + chains.b.clone(), + channel.clone(), + QueryHeight::Latest, + ) { + Ok((handshake_channel, _)) => { + match handshake_channel + .build_chan_upgrade_cancel_and_send() + { + Ok(_) => RetryResult::Ok(Next::Abort), + Err(e) => { + warn!("Channel upgrade cancel failed: {e}"); + RetryResult::Retry(index) + } + } + } + Err(_) => RetryResult::Retry(index), + }, + ) + .map_err(|e| TaskError::Fatal(RunError::retry(e))), + + _ => retry_with_index( + channel_handshake_retry::default_strategy(max_block_times), + |index| match RelayChannel::restore_from_event( + chains.a.clone(), + chains.b.clone(), + event_with_height.event.clone(), + ) { + Ok(mut handshake_channel) => handshake_channel + .step_event(&event_with_height.event, index), + Err(_) => RetryResult::Retry(index), + }, + ) + .map_err(|e| TaskError::Fatal(RunError::retry(e))), + } } else { Ok(Next::Continue) } @@ -93,18 +124,15 @@ pub fn spawn_channel_worker( } if complete_handshake_on_new_block => { debug!("starts processing block event at {:#?}", current_height); - let height = current_height - .decrement() - .map_err(|e| TaskError::Fatal(RunError::ics02(e)))?; - complete_handshake_on_new_block = false; + retry_with_index( channel_handshake_retry::default_strategy(max_block_times), |index| match RelayChannel::restore_from_state( chains.a.clone(), chains.b.clone(), channel.clone(), - height, + QueryHeight::Latest, ) { Ok((mut handshake_channel, state)) => { handshake_channel.step_state(state, index) diff --git a/crates/relayer/src/worker/client.rs b/crates/relayer/src/worker/client.rs index 068b062040..bb601106ba 100644 --- a/crates/relayer/src/worker/client.rs +++ b/crates/relayer/src/worker/client.rs @@ -1,40 +1,17 @@ -use core::{ - convert::Infallible, - time::Duration, -}; +use core::{convert::Infallible, time::Duration}; use crossbeam_channel::Receiver; -use ibc_relayer_types::{ - core::ics02_client::events::UpdateClient, - events::IbcEvent, -}; -use retry::{ - delay::Fibonacci, - retry_with_index, -}; -use tracing::{ - debug, - debug_span, - error_span, - trace, - warn, -}; +use ibc_relayer_types::{core::ics02_client::events::UpdateClient, events::IbcEvent}; +use retry::{delay::Fibonacci, retry_with_index}; +use tracing::{debug, debug_span, error_span, trace, warn}; use super::WorkerCmd; use crate::{ chain::handle::ChainHandle, - foreign_client::{ - ForeignClient, - MisbehaviourResults, - }, + foreign_client::{ForeignClient, MisbehaviourResults}, util::{ retry::clamp_total, - task::{ - spawn_background_task, - Next, - TaskError, - TaskHandle, - }, + task::{spawn_background_task, Next, TaskError, TaskHandle}, }, }; diff --git a/crates/relayer/src/worker/cmd.rs b/crates/relayer/src/worker/cmd.rs index 5cd2f6c0b7..f4113bc7a4 100644 --- a/crates/relayer/src/worker/cmd.rs +++ b/crates/relayer/src/worker/cmd.rs @@ -1,13 +1,6 @@ -use core::fmt::{ - Display, - Error as FmtError, - Formatter, -}; +use core::fmt::{Display, Error as FmtError, Formatter}; -use ibc_relayer_types::{ - core::ics02_client::events::NewBlock, - Height, -}; +use ibc_relayer_types::{core::ics02_client::events::NewBlock, Height}; use crate::event::source::EventBatch; diff --git a/crates/relayer/src/worker/connection.rs b/crates/relayer/src/worker/connection.rs index 18b8495ecb..724c7f1b79 100644 --- a/crates/relayer/src/worker/connection.rs +++ b/crates/relayer/src/worker/connection.rs @@ -1,30 +1,16 @@ use core::time::Duration; use crossbeam_channel::Receiver; -use tracing::{ - debug, - error_span, -}; +use tracing::{debug, error_span}; -use super::{ - error::RunError, - WorkerCmd, -}; +use super::{error::RunError, WorkerCmd}; use crate::{ - chain::handle::{ - ChainHandle, - ChainHandlePair, - }, + chain::handle::{ChainHandle, ChainHandlePair}, connection::Connection as RelayConnection, object::Connection, util::{ retry::retry_with_index, - task::{ - spawn_background_task, - Next, - TaskError, - TaskHandle, - }, + task::{spawn_background_task, Next, TaskError, TaskHandle}, }, worker::retry_strategy, }; diff --git a/crates/relayer/src/worker/cross_chain_query.rs b/crates/relayer/src/worker/cross_chain_query.rs index 04b6a05013..2fe96d9850 100644 --- a/crates/relayer/src/worker/cross_chain_query.rs +++ b/crates/relayer/src/worker/cross_chain_query.rs @@ -2,34 +2,21 @@ use std::time::Duration; use crossbeam_channel::Receiver; use ibc_relayer_types::core::ics02_client::height::Height; -use tracing::{ - info, - info_span, -}; +use tracing::{info, info_span}; use uuid::Uuid; use super::error::RunError; use crate::{ chain::{ handle::ChainHandle, - requests::{ - CrossChainQueryRequest, - IncludeProof, - QueryConnectionRequest, - QueryHeight, - }, + requests::{CrossChainQueryRequest, IncludeProof, QueryConnectionRequest, QueryHeight}, tracking::TrackedMsgs, }, error::Error, event::IbcEventWithHeight, foreign_client::ForeignClient, object::CrossChainQuery, - util::task::{ - spawn_background_task, - Next, - TaskError, - TaskHandle, - }, + util::task::{spawn_background_task, Next, TaskError, TaskHandle}, worker::WorkerCmd, }; diff --git a/crates/relayer/src/worker/error.rs b/crates/relayer/src/worker/error.rs index d967a5f7df..70561d1305 100644 --- a/crates/relayer/src/worker/error.rs +++ b/crates/relayer/src/worker/error.rs @@ -1,15 +1,8 @@ use crossbeam_channel::RecvError; -use flex_error::{ - define_error, - DisplayOnly, -}; +use flex_error::{define_error, DisplayOnly}; use ibc_relayer_types::core::ics02_client::error::Error as Ics02Error; -use crate::{ - channel::ChannelError, - connection::ConnectionError, - link::error::LinkError, -}; +use crate::{channel::ChannelError, connection::ConnectionError, link::error::LinkError}; define_error! { RunError { diff --git a/crates/relayer/src/worker/handle.rs b/crates/relayer/src/worker/handle.rs index 46ba388b33..e3fc4fa7bc 100644 --- a/crates/relayer/src/worker/handle.rs +++ b/crates/relayer/src/worker/handle.rs @@ -1,41 +1,20 @@ -use core::{ - fmt, - mem, -}; +use core::{fmt, mem}; use crossbeam_channel::Sender; use ibc_relayer_types::{ - core::{ - ics02_client::events::NewBlock, - ics24_host::identifier::ChainId, - }, + core::{ics02_client::events::NewBlock, ics24_host::identifier::ChainId}, Height, }; -use serde::{ - Deserialize, - Serialize, -}; -use tracing::{ - debug, - trace, -}; +use serde::{Deserialize, Serialize}; +use tracing::{debug, trace}; -use super::{ - WorkerCmd, - WorkerId, -}; +use super::{WorkerCmd, WorkerId}; use crate::{ chain::tracking::TrackingId, - event::{ - source::EventBatch, - IbcEventWithHeight, - }, + event::{source::EventBatch, IbcEventWithHeight}, object::Object, util::{ - lock::{ - LockExt, - RwArc, - }, + lock::{LockExt, RwArc}, task::TaskHandle, }, }; diff --git a/crates/relayer/src/worker/map.rs b/crates/relayer/src/worker/map.rs index 367057152d..3143052d8a 100644 --- a/crates/relayer/src/worker/map.rs +++ b/crates/relayer/src/worker/map.rs @@ -2,27 +2,14 @@ use alloc::collections::btree_map::BTreeMap as HashMap; use core::mem; use ibc_relayer_types::{ - core::{ - ics02_client::events::NewBlock, - ics24_host::identifier::ChainId, - }, + core::{ics02_client::events::NewBlock, ics24_host::identifier::ChainId}, Height, }; -use tracing::{ - debug, - trace, -}; +use tracing::{debug, trace}; -use super::{ - spawn_worker_tasks, - WorkerHandle, - WorkerId, -}; +use super::{spawn_worker_tasks, WorkerHandle, WorkerId}; use crate::{ - chain::handle::{ - ChainHandle, - ChainHandlePair, - }, + chain::handle::{ChainHandle, ChainHandlePair}, config::Config, object::Object, telemetry, @@ -265,7 +252,6 @@ impl Drop for WorkerMap { } } -#[cfg(feature = "telemetry")] fn metric_type(o: &Object) -> ibc_telemetry::state::WorkerType { use ibc_telemetry::state::WorkerType; diff --git a/crates/relayer/src/worker/packet.rs b/crates/relayer/src/worker/packet.rs index d175480a30..fdfa0022e9 100644 --- a/crates/relayer/src/worker/packet.rs +++ b/crates/relayer/src/worker/packet.rs @@ -1,84 +1,39 @@ use core::time::Duration; -use std::{ - borrow::BorrowMut, - sync::{ - Arc, - Mutex, - }, -}; - -use crossbeam_channel::Receiver; -use ibc_proto::ibc::{ - apps::fee::v1::{ - IdentifiedPacketFees, - QueryIncentivizedPacketRequest, - }, - core::channel::v1::PacketId, -}; -use ibc_relayer_types::{ - applications::{ - ics29_fee::events::IncentivizedPacket, - transfer::{ - Amount, - Coin, - RawCoin, - }, - }, - core::ics04_channel::{ - events::WriteAcknowledgement, - packet::Sequence, - }, - events::{ - IbcEvent, - IbcEventType, - }, - Height, -}; +use std::borrow::BorrowMut; +use std::sync::{Arc, Mutex}; + +use crossbeam_channel::{Receiver, Sender}; use itertools::Itertools; use moka::sync::Cache; -use tracing::{ - debug, - error, - error_span, - info, - trace, - warn, -}; -#[cfg(feature = "telemetry")] -use { - ibc_relayer_types::core::ics24_host::identifier::ChannelId, - ibc_relayer_types::core::ics24_host::identifier::PortId, -}; - -use super::{ - error::RunError, - WorkerCmd, -}; -use crate::{ - chain::handle::ChainHandle, - config::filter::FeePolicy, - event::source::EventBatch, - foreign_client::HasExpiredOrFrozenError, - link::{ - error::LinkError, - Link, - Resubmit, - }, - object::Packet, - telemetry, - util::{ - lock::{ - LockExt, - RwArc, - }, - task::{ - spawn_background_task, - Next, - TaskError, - TaskHandle, - }, - }, -}; +use tracing::{debug, error, error_span, info, trace, warn}; + +use ibc_proto::ibc::apps::fee::v1::{IdentifiedPacketFees, QueryIncentivizedPacketRequest}; +use ibc_proto::ibc::core::channel::v1::PacketId; +use ibc_relayer_types::applications::ics29_fee::events::IncentivizedPacket; +use ibc_relayer_types::applications::transfer::{Amount, Coin, RawCoin}; +use ibc_relayer_types::core::ics04_channel::channel::Ordering; +use ibc_relayer_types::core::ics04_channel::events::WriteAcknowledgement; +use ibc_relayer_types::core::ics04_channel::packet::Sequence; +use ibc_relayer_types::core::ics24_host::identifier::ChannelId; +use ibc_relayer_types::core::ics24_host::identifier::PortId; +use ibc_relayer_types::events::{IbcEvent, IbcEventType}; +use ibc_relayer_types::Height; + +use crate::chain::handle::ChainHandle; +use crate::chain::requests::QueryHeight; +use crate::config::filter::FeePolicy; +use crate::event::source::EventBatch; +use crate::event::IbcEventWithHeight; +use crate::foreign_client::HasExpiredOrFrozenError; +use crate::link::Resubmit; +use crate::link::{error::LinkError, Link}; +use crate::object::Packet; +use crate::telemetry; +use crate::util::lock::{LockExt, RwArc}; +use crate::util::task::{spawn_background_task, Next, TaskError, TaskHandle}; + +use super::error::RunError; +use super::WorkerCmd; const INCENTIVIZED_CACHE_TTL: Duration = Duration::from_secs(10 * 60); const INCENTIVIZED_CACHE_MAX_CAPACITY: u64 = 1000; @@ -128,6 +83,7 @@ pub fn spawn_packet_cmd_worker( link: Arc>>, mut should_clear_on_start: bool, clear_interval: u64, + clear_limit: usize, path: Packet, ) -> TaskHandle { let span = { @@ -162,6 +118,7 @@ pub fn spawn_packet_cmd_worker( &mut link.lock().unwrap(), &mut should_clear_on_start, clear_interval, + clear_limit, &path, cmd, )?; @@ -206,7 +163,7 @@ pub fn spawn_incentivized_packet_cmd_worker> = RwArc::new_lock( - moka::sync::Cache::builder() + Cache::builder() .time_to_live(INCENTIVIZED_CACHE_TTL) .max_capacity(INCENTIVIZED_CACHE_MAX_CAPACITY) .build(), @@ -227,13 +184,79 @@ pub fn spawn_incentivized_packet_cmd_worker( + cmd_rx: Receiver, + // Mutex is used to prevent race condition between the packet workers + link: Arc>>, + mut should_clear_on_start: bool, + clear_interval: u64, + clear_limit: usize, + clear_cmd_tx: Sender, +) -> TaskHandle { + let span = { + let relay_path = &link.lock().unwrap().a_to_b; + error_span!( + "worker.clear.cmd", + src_chain = %relay_path.src_chain().id(), + src_port = %relay_path.src_port_id(), + src_channel = %relay_path.src_channel_id(), + dst_chain = %relay_path.dst_chain().id(), + ) + }; + + let clear_cmd_worker_idle_timeout = if clear_interval > 0 { + clear_interval * 5 + } else { + IDLE_TIMEOUT_BLOCKS + }; + + let mut idle_worker_timer = 0; + + spawn_background_task(span, Some(Duration::from_millis(200)), move || { + if let Ok(cmd) = cmd_rx.try_recv() { + match clear_cmd_tx.send(cmd.clone()) { + Ok(_) => trace!("Successfully sent cmd to packet worker"), + Err(e) => { + error!("Failed to forward cmd from clear worker to packet worker. Cause: {e}") + } + } + let is_new_batch = cmd.is_ibc_events(); + + // Try to clear pending packets. At different levels down in `handle_clear_cmd` there + // are retries mechanisms for MAX_RETRIES (current value hardcoded at 5). + // If clearing fails after all these retries with ignorable error the task continues + // (see `handle_link_error_in_task`) and clearing is retried with the next + // (`NewBlock`) `cmd` that matches the clearing interval. + handle_clear_cmd( + &mut link.lock().unwrap(), + &mut should_clear_on_start, + clear_interval, + clear_limit, + cmd, + )?; + + if is_new_batch { + idle_worker_timer = 0; + trace!("clear worker processed an event batch, resetting idle timer"); + } else { + idle_worker_timer += 1; + trace!("clear worker has not processed an event batch after {idle_worker_timer} blocks, incrementing idle timer"); + } + + if idle_worker_timer > clear_cmd_worker_idle_timeout { + warn!("clear worker has been idle for more than {clear_cmd_worker_idle_timeout} blocks, aborting"); + + return Ok(Next::Abort); + } + } + + Ok(Next::Continue) + }) +} + /// Receives worker commands and handles them accordingly. /// -/// Given an `IbcEvent` command, updates the schedule and initiates -/// packet clearing if the `should_clear_on_start` flag has been toggled. -/// -/// Given a `NewBlock` command, checks if packet clearing should occur -/// and performs it if so. +/// Given an `IbcEvent` command, updates the schedule. /// /// Given a `ClearPendingPackets` command, clears pending packets. /// @@ -243,11 +266,60 @@ fn handle_packet_cmd( link: &mut Link, should_clear_on_start: &mut bool, clear_interval: u64, + clear_limit: usize, path: &Packet, cmd: WorkerCmd, +) -> Result<(), TaskError> { + // If the channel is Ordered, verify if clearing is required before proceeding + // to relaying. + match &cmd { + WorkerCmd::IbcEvents { batch } if link.a_to_b.channel().ordering == Ordering::Ordered => { + let lowest_sequence = lowest_sequence(&batch.events); + + let next_sequence = query_next_sequence_receive( + link.a_to_b.dst_chain(), + link.a_to_b.dst_port_id(), + link.a_to_b.dst_channel_id(), + QueryHeight::Specific(batch.height), + ) + .ok(); + + if *should_clear_on_start || next_sequence < lowest_sequence { + handle_clear_packet(link, clear_interval, path, Some(batch.height), clear_limit)?; + } + } + _ => {} + } + + // Handle command-specific task + if let WorkerCmd::IbcEvents { batch } = cmd { + handle_update_schedule(link, clear_interval, path, batch)?; + } + + Ok(()) +} + +/// Given an `IbcEvent` command, schedule packet clearing if the +/// `should_clear_on_start` flag has been toggled. +/// +/// Given a `NewBlock` command, checks if packet clearing should occur +/// and performs it if so. +fn handle_clear_cmd( + link: &mut Link, + should_clear_on_start: &mut bool, + clear_interval: u64, + clear_limit: usize, + cmd: WorkerCmd, ) -> Result<(), TaskError> { // Handle packet clearing which is triggered from a command let (do_clear, maybe_height) = match &cmd { + // Clearing for Ordered channels is handled by the packet_cmd_worker + WorkerCmd::IbcEvents { batch: _batch } + if link.a_to_b.channel().ordering == Ordering::Ordered => + { + (false, None) + } + WorkerCmd::IbcEvents { batch } => { if *should_clear_on_start { (true, Some(batch.height)) @@ -270,7 +342,7 @@ fn handle_packet_cmd( }; if do_clear { - info!("clearing packets"); + info!("packets clearing triggered, looking for packets to clear"); // Reset the `clear_on_start` flag and attempt packet clearing once now. // More clearing will be done at clear interval. @@ -278,12 +350,9 @@ fn handle_packet_cmd( *should_clear_on_start = false; } - handle_clear_packet(link, clear_interval, path, maybe_height)?; - } - - // Handle command-specific task - if let WorkerCmd::IbcEvents { batch } = cmd { - handle_update_schedule(link, clear_interval, path, batch)?; + link.a_to_b + .schedule_packet_clearing(maybe_height, clear_limit) + .map_err(handle_link_error_in_task)?; } Ok(()) @@ -404,7 +473,7 @@ fn retrieve_all_fees_from_incentivized_packet( incentivized_packet .total_recv_fee .iter() - .group_by(|a| &a.denom) + .chunk_by(|a| &a.denom) .into_iter() .map(|(key, group)| { let total_amount: Amount = group.map(|v| v.amount).sum::(); @@ -441,9 +510,10 @@ fn handle_clear_packet( clear_interval: u64, path: &Packet, height: Option, + clear_limit: usize, ) -> Result<(), TaskError> { link.a_to_b - .schedule_packet_clearing(height) + .schedule_packet_clearing(height, clear_limit) .map_err(handle_link_error_in_task)?; handle_execute_schedule(link, path, Resubmit::from_clear_interval(clear_interval)) @@ -483,10 +553,36 @@ fn handle_execute_schedule( Ok(()) } -#[cfg(feature = "telemetry")] +fn query_next_sequence_receive( + chain: &Chain, + port_id: &PortId, + channel_id: &ChannelId, + height: QueryHeight, +) -> Result { + use crate::chain::requests::{IncludeProof, QueryNextSequenceReceiveRequest}; + + chain + .query_next_sequence_receive( + QueryNextSequenceReceiveRequest { + port_id: port_id.clone(), + channel_id: channel_id.clone(), + height, + }, + IncludeProof::No, + ) + .map(|(seq, _height)| seq) + .map_err(|e| LinkError::query(chain.id(), e)) +} + +fn lowest_sequence(events: &[IbcEventWithHeight]) -> Option { + events + .iter() + .flat_map(|event| event.event.packet().map(|p| p.sequence)) + .min() +} + use crate::link::RelaySummary; -#[cfg(feature = "telemetry")] fn packet_metrics( path: &Packet, summary: &RelaySummary, @@ -498,7 +594,6 @@ fn packet_metrics( timeout_metrics(path, summary, dst_channel, dst_port); } -#[cfg(feature = "telemetry")] fn receive_packet_metrics( path: &Packet, summary: &RelaySummary, @@ -525,7 +620,6 @@ fn receive_packet_metrics( ); } -#[cfg(feature = "telemetry")] fn acknowledgment_metrics( path: &Packet, summary: &RelaySummary, @@ -552,7 +646,6 @@ fn acknowledgment_metrics( ); } -#[cfg(feature = "telemetry")] fn timeout_metrics( path: &Packet, summary: &RelaySummary, diff --git a/crates/relayer/src/worker/retry_strategy.rs b/crates/relayer/src/worker/retry_strategy.rs index c2a352078f..3ffb484457 100644 --- a/crates/relayer/src/worker/retry_strategy.rs +++ b/crates/relayer/src/worker/retry_strategy.rs @@ -1,9 +1,6 @@ use core::time::Duration; -use crate::util::retry::{ - clamp_total, - ConstantGrowth, -}; +use crate::util::retry::{clamp_total, ConstantGrowth}; /// A basic worker retry strategy. /// diff --git a/crates/relayer/src/worker/wallet.rs b/crates/relayer/src/worker/wallet.rs index ad3d6c57b0..a065274995 100644 --- a/crates/relayer/src/worker/wallet.rs +++ b/crates/relayer/src/worker/wallet.rs @@ -1,20 +1,11 @@ use std::time::Duration; -use tracing::{ - error_span, - trace, - warn, -}; +use tracing::{error_span, trace, warn}; use crate::{ chain::handle::ChainHandle, telemetry, - util::task::{ - spawn_background_task, - Next, - TaskError, - TaskHandle, - }, + util::task::{spawn_background_task, Next, TaskError, TaskHandle}, }; pub fn spawn_wallet_worker(chain: Chain) -> TaskHandle { diff --git a/crates/relayer/tests/config/fixtures/relayer_conf_example.toml b/crates/relayer/tests/config/fixtures/relayer_conf_example.toml index f864efecda..6033872b07 100644 --- a/crates/relayer/tests/config/fixtures/relayer_conf_example.toml +++ b/crates/relayer/tests/config/fixtures/relayer_conf_example.toml @@ -39,7 +39,10 @@ max_tx_size = 1048576 clock_drift = '5s' trusting_period = '14days' trust_threshold = { numerator = '1', denominator = '3' } -address_type = { derivation = 'cosmos' } + +[chains.excluded_sequences] +channel-0 = [1, "3-5", 7, "9-12", 14, "17-19"] +channel-1 = ["3-6"] [chains.packet_filter] policy = 'allow' @@ -62,4 +65,5 @@ gas_price = { price = 0.001, denom = 'stake' } clock_drift = '5s' trusting_period = '14days' trust_threshold = { numerator = '1', denominator = '3' } -address_type = { derivation = 'ethermint', proto_type = { pk_type = '/injective.crypto.v1beta1.ethsecp256k1.PubKey' } } \ No newline at end of file +address_type = { derivation = 'ethermint', proto_type = { pk_type = '/injective.crypto.v1beta1.ethsecp256k1.PubKey' } } +excluded_sequences = { 'channel-0' = [1, 3, 4, 5, 7, 9, 10, 11, 12, 14, 17, 18, 19], 'channel-1' = [3, 4, 5, 6] } \ No newline at end of file diff --git a/crates/relayer/tests/config/fixtures/relayer_conf_example_default_chain_type.toml b/crates/relayer/tests/config/fixtures/relayer_conf_example_default_chain_type.toml new file mode 100644 index 0000000000..6df007f2f7 --- /dev/null +++ b/crates/relayer/tests/config/fixtures/relayer_conf_example_default_chain_type.toml @@ -0,0 +1,56 @@ +[global] +log_level = 'error' + +[mode] + +[mode.clients] +enabled = true +refresh = true +misbehaviour = true + +[mode.connections] +enabled = false + +[mode.channels] +enabled = false + +[mode.packets] +enabled = true +clear_interval = 100 +clear_on_start = true +tx_confirmation = true + +[[chains]] +id = 'chain_A' +rpc_addr = 'http://127.0.0.1:26657' +grpc_addr = 'http://127.0.0.1:9090' +event_source = { mode = 'push', url = 'ws://localhost:26657/websocket', batch_delay = '500ms' } +rpc_timeout = '10s' +account_prefix = 'cosmos' +key_name = 'testkey' +store_prefix = 'ibc' +max_gas = 200000 +gas_price = { price = 0.001, denom = 'stake' } +max_msg_num = 4 +max_tx_size = 1048576 +max_grpc_decoding_size = '4MiB' +clock_drift = '5s' +trusting_period = '14days' +trust_threshold = { numerator = '1', denominator = '3' } +address_type = { derivation = 'cosmos' } + +[[chains]] +id = 'chain_B' +rpc_addr = 'http://127.0.0.1:26557' +grpc_addr = 'http://127.0.0.1:9090' +event_source = { mode = 'push', url = 'ws://localhost:26557/websocket', batch_delay = '500ms' } +rpc_timeout = '10s' +account_prefix = 'cosmos' +key_name = 'testkey' +store_prefix = 'ibc' +gas_price = { price = 0.001, denom = 'stake' } +max_grpc_decoding_size = '5.91 MB' +clock_drift = '5s' +trusting_period = '14days' +trust_threshold = { numerator = '1', denominator = '3' } +address_type = { derivation = 'ethermint', proto_type = { pk_type = '/injective.crypto.v1beta1.ethsecp256k1.PubKey' } } \ No newline at end of file diff --git a/crates/relayer/tests/config/fixtures/relayer_conf_example_invalid_excluded_sequences.toml b/crates/relayer/tests/config/fixtures/relayer_conf_example_invalid_excluded_sequences.toml new file mode 100644 index 0000000000..1e72497055 --- /dev/null +++ b/crates/relayer/tests/config/fixtures/relayer_conf_example_invalid_excluded_sequences.toml @@ -0,0 +1,68 @@ +[global] +log_level = 'error' + +[mode] + +[mode.clients] +enabled = true +refresh = true +misbehaviour = true + +[mode.connections] +enabled = false + +[mode.channels] +enabled = false + +[mode.packets] +enabled = true +clear_interval = 100 +clear_on_start = true +tx_confirmation = true +ics20_max_memo_size = { enabled = true, size = "32KiB" } +ics20_max_receiver_size = { enabled = true, size = "2KiB" } + +[[chains]] +type = "CosmosSdk" +id = 'chain_A' +rpc_addr = 'http://127.0.0.1:26657' +grpc_addr = 'http://127.0.0.1:9090' +event_source = { mode = 'push', url = 'ws://localhost:26657/websocket', batch_delay = '500ms' } +rpc_timeout = '10s' +account_prefix = 'cosmos' +key_name = 'testkey' +store_prefix = 'ibc' +max_gas = 200000 +gas_price = { price = 0.001, denom = 'stake' } +max_msg_num = 4 +max_tx_size = 1048576 +clock_drift = '5s' +trusting_period = '14days' +trust_threshold = { numerator = '1', denominator = '3' } +excluded_sequences = [ + ['channel-0', [1, 2, 3]], + ['channel-1', [4, 5, 6]] +] + +[chains.packet_filter] +policy = 'allow' +list = [ + ['ica*', '*'], + ['transfer', 'channel-0'], +] + +[[chains]] +type = "CosmosSdk" +id = 'chain_B' +rpc_addr = 'http://127.0.0.1:26557' +grpc_addr = 'http://127.0.0.1:9090' +event_source = { mode = 'push', url = 'ws://localhost:26557/websocket', batch_delay = '500ms' } +rpc_timeout = '10s' +account_prefix = 'cosmos' +key_name = 'testkey' +store_prefix = 'ibc' +gas_price = { price = 0.001, denom = 'stake' } +clock_drift = '5s' +trusting_period = '14days' +trust_threshold = { numerator = '1', denominator = '3' } +address_type = { derivation = 'ethermint', proto_type = { pk_type = '/injective.crypto.v1beta1.ethsecp256k1.PubKey' } } \ No newline at end of file diff --git a/crates/telemetry/Cargo.toml b/crates/telemetry/Cargo.toml index 4f4d6838e5..b6ab30faf6 100644 --- a/crates/telemetry/Cargo.toml +++ b/crates/telemetry/Cargo.toml @@ -1,32 +1,29 @@ [package] name = "ibc-telemetry" -version = "0.26.4" +version = "0.29.3" 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.71" +rust-version = "1.76.0" description = """ Telemetry service for the Hermes IBC relayer """ [dependencies] -ibc-relayer-types = { version = "0.26.4", path = "../relayer-types" } +ibc-relayer-types = { workspace = true } -once_cell = "1.19.0" -opentelemetry = { version = "0.19.0", features = ["metrics"] } -opentelemetry-prometheus = "0.12.0" -prometheus = "0.13.2" -moka = { version = "0.12.0", features = ["sync"] } -dashmap = "5.4.0" -serde_json = "1.0.94" -serde = "1.0.195" -axum = "0.6.18" -tokio = "1.26.0" -tracing = "0.1.36" - -[dependencies.tendermint] -version = "0.34.0" -default-features = false +axum = { workspace = true } +dashmap = { workspace = true } +moka = { workspace = true, features = ["sync"] } +once_cell = { workspace = true } +opentelemetry = { workspace = true, features = ["metrics"] } +opentelemetry-prometheus = { workspace = true } +prometheus = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +tendermint = { workspace = true } +tokio = { workspace = true } +tracing = { workspace = true } diff --git a/crates/telemetry/src/encoder.rs b/crates/telemetry/src/encoder.rs index eb6237dc6f..73d83b7542 100644 --- a/crates/telemetry/src/encoder.rs +++ b/crates/telemetry/src/encoder.rs @@ -2,21 +2,12 @@ use std::{ collections::BTreeMap, - io::{ - self, - Write, - }, + io::{self, Write}, }; use prometheus::{ - proto::{ - self, - MetricFamily, - MetricType, - }, - Encoder, - Error, - Result, + proto::{self, MetricFamily, MetricType}, + Encoder, Error, Result, }; use serde::Serialize; diff --git a/crates/telemetry/src/lib.rs b/crates/telemetry/src/lib.rs index ccd1cd1767..dfb66813d8 100644 --- a/crates/telemetry/src/lib.rs +++ b/crates/telemetry/src/lib.rs @@ -6,20 +6,14 @@ pub mod state; use std::{ error::Error, - net::{ - SocketAddr, - ToSocketAddrs, - }, + net::{SocketAddr, ToSocketAddrs}, ops::Range, sync::Arc, }; use once_cell::sync::OnceCell; use tokio::task::JoinHandle; -use tracing::{ - debug, - warn, -}; +use tracing::{debug, warn}; pub use crate::state::TelemetryState; diff --git a/crates/telemetry/src/server.rs b/crates/telemetry/src/server.rs index 2268334860..13e96c98d1 100644 --- a/crates/telemetry/src/server.rs +++ b/crates/telemetry/src/server.rs @@ -1,25 +1,9 @@ -use std::{ - error::Error, - net::SocketAddr, - sync::Arc, -}; +use std::{error::Error, net::SocketAddr, sync::Arc}; -use axum::{ - extract::Query, - response::IntoResponse, - routing::get, - Extension, - Router, -}; -use prometheus::{ - Encoder, - TextEncoder, -}; +use axum::{extract::Query, response::IntoResponse, routing::get, Extension, Router}; +use prometheus::{Encoder, TextEncoder}; -use crate::{ - encoder::JsonEncoder, - state::TelemetryState, -}; +use crate::{encoder::JsonEncoder, state::TelemetryState}; #[derive(Copy, Clone, Debug, Default, serde::Deserialize)] enum Format { diff --git a/crates/telemetry/src/state.rs b/crates/telemetry/src/state.rs index c4eb3e4ea5..e791a5859d 100644 --- a/crates/telemetry/src/state.rs +++ b/crates/telemetry/src/state.rs @@ -1,49 +1,26 @@ -use core::fmt::{ - Display, - Error as FmtError, - Formatter, -}; +use core::fmt::{Display, Error as FmtError, Formatter}; use std::{ ops::Range, sync::Mutex, - time::{ - Duration, - Instant, - }, + time::{Duration, Instant}, }; -use dashmap::{ - DashMap, - DashSet, -}; +use dashmap::{DashMap, DashSet}; use ibc_relayer_types::{ applications::transfer::Coin, - core::ics24_host::identifier::{ - ChainId, - ChannelId, - ClientId, - PortId, - }, + core::ics24_host::identifier::{ChainId, ChannelId, ClientId, PortId}, signer::Signer, }; use opentelemetry::{ global, - metrics::{ - Counter, - ObservableGauge, - UpDownCounter, - }, - Context, - KeyValue, + metrics::{Counter, ObservableGauge, UpDownCounter}, + Context, KeyValue, }; use opentelemetry_prometheus::PrometheusExporter; use prometheus::proto::MetricFamily; use tendermint::Time; -use crate::{ - broadcast_error::BroadcastError, - path_identifier::PathIdentifier, -}; +use crate::{broadcast_error::BroadcastError, path_identifier::PathIdentifier}; const EMPTY_BACKLOG_SYMBOL: u64 = 0; const BACKLOG_CAPACITY: usize = 1000; @@ -192,7 +169,7 @@ pub struct TelemetryState { backlog_oldest_sequence: ObservableGauge, /// 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. + /// The timestamp is the time passed since the unix epoch in seconds. backlog_latest_update_timestamp: ObservableGauge, /// Records the length of the backlog, i.e., how many packets are pending. @@ -221,6 +198,21 @@ pub struct TelemetryState { /// Number of errors observed by Hermes when broadcasting a Tx broadcast_errors: Counter, + + /// Number of errors observed by Hermes when simulating a Tx + simulate_errors: Counter, + + /// The EIP-1559 base fee queried + dynamic_gas_queried_fees: ObservableGauge, + + /// The EIP-1559 base fee paid + dynamic_gas_paid_fees: ObservableGauge, + + /// The EIP-1559 base fee successfully queried + dynamic_gas_queried_success_fees: ObservableGauge, + + /// Number of ICS-20 packets filtered because the memo and/or the receiver fields were exceeding the configured limits + filtered_packets: Counter, } impl TelemetryState { @@ -232,10 +224,7 @@ impl TelemetryState { ) -> Self { use opentelemetry::sdk::{ export::metrics::aggregation, - metrics::{ - controllers, - processors, - }, + metrics::{controllers, processors}, }; let controller = controllers::basic(processors::factory( @@ -407,6 +396,33 @@ impl TelemetryState { "Number of errors observed by Hermes when broadcasting a Tx", ) .init(), + + simulate_errors: meter + .u64_counter("simulate_errors") + .with_description( + "Number of errors observed by Hermes when simulating a Tx", + ) + .init(), + + dynamic_gas_queried_fees: meter + .f64_observable_gauge("dynamic_gas_queried_fees") + .with_description("The EIP-1559 base fee queried") + .init(), + + dynamic_gas_paid_fees: meter + .f64_observable_gauge("dynamic_gas_paid_fees") + .with_description("The EIP-1559 base fee paid") + .init(), + + dynamic_gas_queried_success_fees: meter + .f64_observable_gauge("dynamic_gas_queried_success_fees") + .with_description("The EIP-1559 base fee successfully queried") + .init(), + + filtered_packets: meter + .u64_counter("filtered_packets") + .with_description("Number of ICS-20 packets filtered because the memo and/or the receiver fields were exceeding the configured limits") + .init(), } } @@ -1153,6 +1169,73 @@ impl TelemetryState { self.broadcast_errors.add(&cx, 1, labels); } + + /// Add an error and its description to the list of errors observed after simulating + /// a Tx with a specific account. + pub fn simulate_errors(&self, address: &String, recoverable: bool, error_description: String) { + let cx = Context::current(); + + let labels = &[ + KeyValue::new("account", address.to_string()), + KeyValue::new("recoverable", recoverable.to_string()), + KeyValue::new("error_description", error_description.to_owned()), + ]; + + self.simulate_errors.add(&cx, 1, labels); + } + + pub fn dynamic_gas_queried_fees(&self, chain_id: &ChainId, amount: f64) { + let cx = Context::current(); + + let labels = &[KeyValue::new("identifier", chain_id.to_string())]; + + self.dynamic_gas_queried_fees.observe(&cx, amount, labels); + } + + pub fn dynamic_gas_paid_fees(&self, chain_id: &ChainId, amount: f64) { + let cx = Context::current(); + + let labels = &[KeyValue::new("identifier", chain_id.to_string())]; + + self.dynamic_gas_paid_fees.observe(&cx, amount, labels); + } + + pub fn dynamic_gas_queried_success_fees(&self, chain_id: &ChainId, amount: f64) { + let cx = Context::current(); + + let labels = &[KeyValue::new("identifier", chain_id.to_string())]; + + self.dynamic_gas_queried_success_fees + .observe(&cx, amount, labels); + } + + /// Increment number of packets filtered because the memo field is too big + #[allow(clippy::too_many_arguments)] + pub fn filtered_packets( + &self, + src_chain: &ChainId, + dst_chain: &ChainId, + src_channel: &ChannelId, + dst_channel: &ChannelId, + src_port: &PortId, + dst_port: &PortId, + count: u64, + ) { + let cx = Context::current(); + + if count > 0 { + let labels = &[ + KeyValue::new("src_chain", src_chain.to_string()), + KeyValue::new("dst_chain", dst_chain.to_string()), + KeyValue::new("src_channel", src_channel.to_string()), + KeyValue::new("dst_channel", dst_channel.to_string()), + KeyValue::new("src_port", src_port.to_string()), + KeyValue::new("dst_port", dst_port.to_string()), + ]; + + self.filtered_packets.add(&cx, count, labels); + } + } } use std::sync::Arc; @@ -1162,12 +1245,7 @@ use opentelemetry::{ sdk::{ export::metrics::AggregatorSelector, metrics::{ - aggregators::{ - histogram, - last_value, - sum, - Aggregator, - }, + aggregators::{histogram, last_value, sum, Aggregator}, sdk_api::Descriptor, }, }, @@ -1232,6 +1310,15 @@ impl AggregatorSelector for CustomAggregatorSelector { // TODO: Once quantile sketches are supported, replace histograms with that. "tx_latency_submitted" => Some(Arc::new(histogram(&self.get_submitted_range()))), "tx_latency_confirmed" => Some(Arc::new(histogram(&self.get_confirmed_range()))), + "dynamic_gas_queried_fees" => Some(Arc::new(histogram(&[ + 0.0025, 0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 5.0, + ]))), + "dynamic_gas_paid_fees" => Some(Arc::new(histogram(&[ + 0.0025, 0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 5.0, + ]))), + "dynamic_gas_queried_success_fees" => Some(Arc::new(histogram(&[ + 0.0025, 0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 5.0, + ]))), "ics29_period_fees" => Some(Arc::new(last_value())), _ => Some(Arc::new(sum())), } diff --git a/docs/architecture/adr-002-ibc-relayer.md b/docs/architecture/adr-002-ibc-relayer.md index 983ff24805..0ed5e63439 100644 --- a/docs/architecture/adr-002-ibc-relayer.md +++ b/docs/architecture/adr-002-ibc-relayer.md @@ -45,12 +45,12 @@ IBC protocol defines the minimal data set that must be made available to relayer #### Query Functionality IBC host state machines MUST expose an interface for inspecting their state. For Cosmos/Tendermint chains this means: - the IBC modules on chain correctly implement and respond to queries - - [IBC-Modules-Rust] an implementation for some queries currently exist in Cosmos-SDK and same and more need to be implemented in Rust. The full requirements are detailed in section Relayer Queries. + - [IBC-Modules-Rust] an implementation for some queries currently exists in Cosmos-SDK and the same and more need to be implemented in Rust. The full requirements are detailed in section Relayer Queries. - the relayer needs the ability to send rpc/http ABCI queries to and receive replies from Tendermint/Cosmos-SDK - [[ABCI Rust](https://github.com/tendermint/rust-abci)] - ABCI Rust implementation - [IBC-Modules-Rust] identifier validation is required (ICS-024) - [IBC-Modules-Rust] requires Rust types for all query responses - - [[Merkle-Proofs-Rust](https://github.com/confio/ics23/tree/master/rust)] (candidate implementation) - some query responses include proofs and included in IBC transactions by the relayer (some may be validated, TBD) + - [[Merkle-Proofs-Rust](https://github.com/confio/ics23/tree/master/rust)] (candidate implementation) - some query responses include proofs and are included in IBC transactions by the relayer (some may be validated, TBD) #### IBC Messages The relayer creates transactions that include IBC messages to manage clients, connections and channels, and send application packets to destination chains. These messages must be defined in the IBC Rust implementation [IBC-Modules-Rust]. diff --git a/docs/architecture/adr-003-handler-implementation.md b/docs/architecture/adr-003-handler-implementation.md index e552f7672e..dc78a0f56d 100644 --- a/docs/architecture/adr-003-handler-implementation.md +++ b/docs/architecture/adr-003-handler-implementation.md @@ -369,7 +369,7 @@ to deal with chain-specific datatypes, such as `Header`, `ClientState`, and To abstract over chain-specific datatypes, we introduce a trait which specifies both which types we need to abstract over, and their interface. -For the ICS 002 Client submodule, this trait looks as follow: +For the ICS 002 Client submodule, this trait looks as follows: ```rust pub trait ClientDef { @@ -379,7 +379,7 @@ pub trait ClientDef { } ``` -The `ClientDef` trait specifies three datatypes, and their corresponding interface, which is provided +The `ClientDef` trait specifies three datatypes, and their corresponding interface, which are provided via a trait defined in the same submodule. A production implementation of this interface would instantiate these types with the concrete @@ -632,4 +632,4 @@ Proposed ### Neutral -## References \ No newline at end of file +## References diff --git a/docs/architecture/adr-004-relayer-domain-decomposition.md b/docs/architecture/adr-004-relayer-domain-decomposition.md index b97f376339..c65aa638a3 100644 --- a/docs/architecture/adr-004-relayer-domain-decomposition.md +++ b/docs/architecture/adr-004-relayer-domain-decomposition.md @@ -91,7 +91,7 @@ Channel datagrams are built similarly. Packet datagrams are triggered by events, ### IBC Module -For every a transaction in a block of height H: +For every transaction in a block of height H: - call appropriate handler (this is realized by ICS26 routing sub-module), - If handler succeeds (transaction does not abort), then @@ -236,7 +236,7 @@ fn main() -> Result<(), Box> { let src_chain = ChainRuntime::new(); let dst_chain = ChainRuntime::new(); - /// chains expose handlers for commuicating with the chain related runtime + /// chains expose handlers for communicating with the chain related runtime /// which move into their own threads let src_chain_handle = src_chain.handle(); thread::spawn(move || { diff --git a/docs/architecture/adr-005-relayer-v0-implementation.md b/docs/architecture/adr-005-relayer-v0-implementation.md index bc35c3e1f0..78d381ba7b 100644 --- a/docs/architecture/adr-005-relayer-v0-implementation.md +++ b/docs/architecture/adr-005-relayer-v0-implementation.md @@ -221,7 +221,7 @@ Accepted [comment](https://github.com/informalsystems/hermes/pull/449#issuecomment-750248113) provides additional insights into development-time relayer `v0.1` environment. -- __Mock__: Has been removed after splittin the ibc-rs repository +- __Mock__: Has been removed after splitting the ibc-rs repository diff --git a/docs/architecture/adr-006-hermes-v0.2-usecases.md b/docs/architecture/adr-006-hermes-v0.2-usecases.md index e6e6488fec..2b4bad5dc3 100644 --- a/docs/architecture/adr-006-hermes-v0.2-usecases.md +++ b/docs/architecture/adr-006-hermes-v0.2-usecases.md @@ -80,7 +80,7 @@ connection, or reuse a connection in the creation of a new channel). #### Patterns -We propose two basic patterns that Hermes should be able to fulfil. +We propose two basic patterns that Hermes should be able to fulfill. 1. Simple invocations to perform basic actions. - By _action_ here we mean doing the complete handshake for an object from diff --git a/docs/architecture/adr-008-ics20-implementation.md b/docs/architecture/adr-008-ics20-implementation.md index afbdaa1531..8c8d872f1d 100644 --- a/docs/architecture/adr-008-ics20-implementation.md +++ b/docs/architecture/adr-008-ics20-implementation.md @@ -195,7 +195,7 @@ pub fn on_timeout_packet(ctx: &Ctx, data: &FungibleTokenPacketData) -> Resu refund_packet_token(ctx, data) } -/// Responds to the the success or failure of a packet +/// Responds to the success or failure of a packet /// acknowledgement written on the receiving chain. If the acknowledgement /// was a success then nothing occurs. If the acknowledgement failed, then /// the sender is refunded their tokens. diff --git a/docs/spec/relayer/Definitions.md b/docs/spec/relayer/Definitions.md index 5d8830a717..ce3ad90b2f 100644 --- a/docs/spec/relayer/Definitions.md +++ b/docs/spec/relayer/Definitions.md @@ -224,7 +224,7 @@ CreateUpdateClientDatagrams(shs []SignedHeader) IBCDatagram[] // Submit given datagram to a given chain Submit(chain Chain, datagram IBCDatagram) Error -// Return the correspondin chain for a given chainID +// Return the corresponding chain for a given chainID // We assume that the relayer maintains a map of known chainIDs and the corresponding chains. GetChain(chainID String) Chain ``` diff --git a/e2e/e2e/channel.py b/e2e/e2e/channel.py index 0036ae7fa3..75b5d23dd8 100644 --- a/e2e/e2e/channel.py +++ b/e2e/e2e/channel.py @@ -472,15 +472,16 @@ def handshake( split() a_chan_end = query_channel_end(c, side_a, port_id, a_chan_id) - if a_chan_end.state != 'Open': + if str(a_chan_end.state) != 'Open': l.error( - f'Channel end with id {a_chan_id} on chain {side_a} is not in Open state, got: {a_chan_end.state}') + f"Channel end with id {a_chan_id} on chain {side_a} is not in `Open` state, got: {a_chan_end.state}") exit(1) b_chan_end = query_channel_end(c, side_b, port_id, b_chan_id) - if b_chan_end.state != 'Open': + print(b_chan_end.state) + if str(b_chan_end.state) != 'Open': l.error( - f'Channel end with id {b_chan_id} on chain {side_b} is not in Open state, got: {b_chan_end.state}') + f'Channel end with id {b_chan_id} on chain {side_b} is not in `Open` state, got: {b_chan_end.state}') exit(1) a_chan_ends = query_channel_ends(c, side_a, port_id, a_chan_id) diff --git a/flake.lock b/flake.lock index 874e699bf9..ae1418f0a4 100644 --- a/flake.lock +++ b/flake.lock @@ -3,7 +3,6 @@ "akash-src": { "flake": false, "locked": { - "lastModified": 1648485085, "narHash": "sha256-33FPy0dn6QuqneEqZYkFoCRm9agG7PE+9C/pYH9Gwx4=", "owner": "ovrclk", "repo": "akash", @@ -17,19 +16,35 @@ "type": "github" } }, + "andromeda-src": { + "flake": false, + "locked": { + "narHash": "sha256-8nKekKLBZR7nDNXZ1UL0J7YOMRv6HbzT7pj0W+fV+4U=", + "owner": "andromedaprotocol", + "repo": "andromedad", + "rev": "a72f010f8e3f9db183da0ddaf4ef65069b690981", + "type": "github" + }, + "original": { + "owner": "andromedaprotocol", + "ref": "andromeda-1", + "repo": "andromedad", + "type": "github" + } + }, "apalache-src": { "flake": false, "locked": { - "lastModified": 1650241137, - "narHash": "sha256-15jzwbBc7ByxHJbpHmIukSNvih9oxTXeinNamgXirCU=", + "lastModified": 1714996894, + "narHash": "sha256-3xw7bajvhGL+wGne4MRh/HpDFdp+HGfnfzqq8YSx9tc=", "owner": "informalsystems", "repo": "apalache", - "rev": "40d9ec66b3defe8e72803ca9241a73366497eeee", + "rev": "5dee24e4d05dc3476977a2e49f4963e3802fae2f", "type": "github" }, "original": { "owner": "informalsystems", - "ref": "v0.24.0", + "ref": "v0.44.11", "repo": "apalache", "type": "github" } @@ -37,58 +52,55 @@ "beaker-src": { "flake": false, "locked": { - "lastModified": 1686823358, - "narHash": "sha256-bQiN5Q7RV4Uupc7rk1rGurRvCTy+5EiiB4p3bHct7M0=", + "narHash": "sha256-ZLDuTwB8PG0rMiDcLRxCf/xuoFowgK+aat9mSZVp+Dw=", "owner": "osmosis-labs", "repo": "beaker", - "rev": "f3c7a9fc6886aa2b4e0d259f70058d6c23c225e5", + "rev": "fc046f8fe9d8baecdd76404b57b31f5a4e100301", "type": "github" }, "original": { "owner": "osmosis-labs", - "ref": "v0.1.6", + "ref": "v0.1.8", "repo": "beaker", "type": "github" } }, - "celestia-src": { + "celestia-app-src": { "flake": false, "locked": { - "lastModified": 1700494564, - "narHash": "sha256-O6KrCStrZLmWy3xybQUNsWEb3O7vIRCFDE9MsEtsFro=", + "lastModified": 1722019080, + "narHash": "sha256-NN3O1nN+LTxDzYBzXjksfKl9DMCbFy+MsuxPBKgv9Dc=", "owner": "celestiaorg", "repo": "celestia-app", - "rev": "2dbfabf1849e166974c1287c35b43e5e07727643", + "rev": "b6db108a444c234e4b4656031d876bc45421c5f3", "type": "github" }, "original": { "owner": "celestiaorg", - "ref": "v1.4.0", + "ref": "v1.14.0", "repo": "celestia-app", "type": "github" } }, - "centauri-src": { + "celestia-node-src": { "flake": false, "locked": { - "lastModified": 1701431373, - "narHash": "sha256-EpZ1CQN0gMU8W1u3CMbqlaHeeVpQO2i1GPg6pOyOQTc=", - "owner": "ComposableFi", - "repo": "composable-cosmos", - "rev": "387c96b434db9d96b0506aa7f14536d9bdec968c", + "narHash": "sha256-O5a8Dy7WOSaLzYHTZAZFHFeJwqOLyajcHmGEcphOpKg=", + "owner": "celestiaorg", + "repo": "celestia-node", + "rev": "e55e1c88708b46839867bcbbed9bcdd8a3ffa830", "type": "github" }, "original": { - "owner": "ComposableFi", - "repo": "composable-cosmos", - "rev": "387c96b434db9d96b0506aa7f14536d9bdec968c", + "owner": "celestiaorg", + "ref": "v0.13.0", + "repo": "celestia-node", "type": "github" } }, "cometbft-src": { "flake": false, "locked": { - "lastModified": 1694550324, "narHash": "sha256-G5gchJMn/BFzwYx8/ikPDL5fS/TuFIBF4DKJbkalp/M=", "owner": "cometbft", "repo": "cometbft", @@ -102,18 +114,38 @@ "type": "github" } }, + "composable-cosmos-src": { + "flake": false, + "locked": { + "lastModified": 1710970443, + "narHash": "sha256-7h+vLGFxj2QvcTfXgHqS3pfnYzIzyf8DhO7adJKRe8c=", + "owner": "ComposableFi", + "repo": "composable-cosmos", + "rev": "a76ebd371059b778aa3e9799366b09e8453f114b", + "type": "github" + }, + "original": { + "owner": "ComposableFi", + "ref": "v6.4.88", + "repo": "composable-cosmos", + "type": "github" + } + }, "cosmos-nix": { "inputs": { "akash-src": "akash-src", + "andromeda-src": "andromeda-src", "apalache-src": "apalache-src", "beaker-src": "beaker-src", - "celestia-src": "celestia-src", - "centauri-src": "centauri-src", + "celestia-app-src": "celestia-app-src", + "celestia-node-src": "celestia-node-src", "cometbft-src": "cometbft-src", + "composable-cosmos-src": "composable-cosmos-src", "cosmos-sdk-src": "cosmos-sdk-src", "cosmwasm-src": "cosmwasm-src", - "crescent-src": "crescent-src", "cw-plus-src": "cw-plus-src", + "dydx-src": "dydx-src", + "dymension-src": "dymension-src", "evmos-src": "evmos-src", "flake-parts": "flake-parts", "gaia-main-src": "gaia-main-src", @@ -122,6 +154,10 @@ "gaia12-src": "gaia12-src", "gaia13-src": "gaia13-src", "gaia14-src": "gaia14-src", + "gaia15-src": "gaia15-src", + "gaia17-src": "gaia17-src", + "gaia18-src": "gaia18-src", + "gaia19-src": "gaia19-src", "gaia5-src": "gaia5-src", "gaia6-ordered-src": "gaia6-ordered-src", "gaia6-src": "gaia6-src", @@ -129,6 +165,8 @@ "gaia8-src": "gaia8-src", "gaia9-src": "gaia9-src", "gex-src": "gex-src", + "gomod2nix": "gomod2nix", + "haqq-src": "haqq-src", "hermes-src": "hermes-src", "ibc-go-v2-src": "ibc-go-v2-src", "ibc-go-v3-src": "ibc-go-v3-src", @@ -136,50 +174,62 @@ "ibc-go-v5-src": "ibc-go-v5-src", "ibc-go-v6-src": "ibc-go-v6-src", "ibc-go-v7-src": "ibc-go-v7-src", - "ibc-go-v8-channel-upgrade-src": "ibc-go-v8-channel-upgrade-src", + "ibc-go-v7-wasm-src": "ibc-go-v7-wasm-src", "ibc-go-v8-src": "ibc-go-v8-src", + "ibc-go-v8-wasm-src": "ibc-go-v8-wasm-src", + "ibc-go-v9-src": "ibc-go-v9-src", "ibc-rs-src": "ibc-rs-src", "ica-src": "ica-src", "ignite-cli-src": "ignite-cli-src", + "injective-src": "injective-src", "interchain-security-src": "interchain-security-src", "iris-src": "iris-src", "ixo-src": "ixo-src", "juno-src": "juno-src", "migaloo-src": "migaloo-src", + "namada-src": "namada-src", "neutron-src": "neutron-src", "nix-std": "nix-std", - "nixpkgs": "nixpkgs", + "nix2container": "nix2container", + "nixpkgs": "nixpkgs_2", "osmosis-src": "osmosis-src", "provenance-src": "provenance-src", "regen-src": "regen-src", "relayer-src": "relayer-src", + "rollapp-evm-src": "rollapp-evm-src", "rust-overlay": "rust-overlay", "sbt-derivation": "sbt-derivation", "sconfig-src": "sconfig-src", "sentinel-src": "sentinel-src", "sifchain-src": "sifchain-src", + "slinky-src": "slinky-src", "stargaze-src": "stargaze-src", "stoml-src": "stoml-src", - "stride-consumer-src": "stride-consumer-src", "stride-src": "stride-src", "umee-src": "umee-src", "wasmd-src": "wasmd-src", - "wasmd_next-src": "wasmd_next-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_2_6-src": "wasmvm_1_2_6-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" + "wasmvm_1_5_2-src": "wasmvm_1_5_2-src", + "wasmvm_1_5_4-src": "wasmvm_1_5_4-src", + "wasmvm_1_beta7-src": "wasmvm_1_beta7-src", + "wasmvm_2_0_0-src": "wasmvm_2_0_0-src", + "wasmvm_2_0_3-src": "wasmvm_2_0_3-src", + "wasmvm_2_1_0-src": "wasmvm_2_1_0-src", + "wasmvm_2_1_2-src": "wasmvm_2_1_2-src" }, "locked": { - "lastModified": 1701457684, - "narHash": "sha256-Tx3WsOM9scTXDHFyL5vNcQnCmT7Mx0dYg1Nmz8cFwt4=", + "lastModified": 1725007328, + "narHash": "sha256-DMRDFFpXIJyKRNhiVhXaIoOJkmVyKbt6DO6M5F8CCec=", "owner": "informalsystems", "repo": "cosmos.nix", - "rev": "c0bb979a518aa08ba064112a85e03fbc7a7d2869", + "rev": "d87f011075da3ee1afbbe3443ca25461af7d49fd", "type": "github" }, "original": { @@ -191,7 +241,6 @@ "cosmos-sdk-src": { "flake": false, "locked": { - "lastModified": 1658846655, "narHash": "sha256-Xs83vbgt4+YH2LRJx7692nIjRBr5QCYoUHI17njsjlw=", "owner": "cosmos", "repo": "cosmos-sdk", @@ -208,41 +257,22 @@ "cosmwasm-src": { "flake": false, "locked": { - "lastModified": 1698745412, - "narHash": "sha256-41s5jLFzw9Jo+dirAVOad1dtUqCBY6rIz/6TRc0frMw=", + "narHash": "sha256-F+INGtJZj272HZkj/lUPlskNqAPe9x5itNYXCQsezkA=", "owner": "CosmWasm", "repo": "cosmwasm", - "rev": "89891f0bb2de2c83d00600208695d0d5e1b617ac", + "rev": "3c33a0a5dfa5d1c30f474011c77117ec3bf4dc04", "type": "github" }, "original": { "owner": "CosmWasm", - "ref": "v1.5.0", + "ref": "v1.5.3", "repo": "cosmwasm", "type": "github" } }, - "crescent-src": { - "flake": false, - "locked": { - "lastModified": 1647869429, - "narHash": "sha256-c1xiTB/HgtQJSwD3ccFQIoSHPbJK6rf1nSjnM3r0oCE=", - "owner": "crescent-network", - "repo": "crescent", - "rev": "01980cfd06b06786109eaba78c154e6db1adc3d6", - "type": "github" - }, - "original": { - "owner": "crescent-network", - "ref": "v1.0.0-rc3", - "repo": "crescent", - "type": "github" - } - }, "cw-plus-src": { "flake": false, "locked": { - "lastModified": 1700757493, "narHash": "sha256-E5vkY+B4BDoTDtvuB+7Tm3k/5dCYPSjUujMWcgYsWf0=", "owner": "CosmWasm", "repo": "cw-plus", @@ -256,33 +286,102 @@ "type": "github" } }, + "devenv": { + "inputs": { + "flake-compat": "flake-compat", + "nix": "nix", + "nixpkgs": [ + "cosmos-nix", + "haqq-src", + "nixpkgs-unstable" + ], + "pre-commit-hooks": "pre-commit-hooks" + }, + "locked": { + "narHash": "sha256-NLvhvXBmX+WuqDN9PbRbQCsA+y57yGaf+jCWuJVdaIQ=", + "owner": "cachix", + "repo": "devenv", + "rev": "0c41b86406e910a75fbde28f81ec7f6fda74f7e1", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "dydx-src": { + "flake": false, + "locked": { + "narHash": "sha256-NiC+Nol8Cye0z/U5cgQ+zhvlbDJX6DouaMo8oYsRGDQ=", + "owner": "dydxprotocol", + "repo": "v4-chain", + "rev": "35b87db422b0ef4138101ba73b0f00d16780ba89", + "type": "github" + }, + "original": { + "owner": "dydxprotocol", + "ref": "protocol/v3.0.0-dev0", + "repo": "v4-chain", + "type": "github" + } + }, + "dymension-src": { + "flake": false, + "locked": { + "narHash": "sha256-K1F0kL4/HVxOJvXNvLJsZUFXS3MyuqrUotyyd5u6QTQ=", + "owner": "dymensionxyz", + "repo": "dymension", + "rev": "c3294dc8d2dce1aa8efbc967b1dfd3b0e965b095", + "type": "github" + }, + "original": { + "owner": "dymensionxyz", + "ref": "v3.0.0", + "repo": "dymension", + "type": "github" + } + }, "evmos-src": { "flake": false, "locked": { - "lastModified": 1666728289, - "narHash": "sha256-hMry1q+31jqSe0krg880LIMcz0xgftB3mwfywWoLX3w=", - "owner": "tharsis", + "narHash": "sha256-ECXXQ0hx/MXascMP6aXf880zts/dNPpQM9jOCIHTLZQ=", + "owner": "evmos", "repo": "evmos", - "rev": "80c38f659a65a983b221e2a568c6172b8ac3bffc", + "rev": "6f94d2002c01b7f7908a69089ed6996ac2bb450c", "type": "github" }, "original": { - "owner": "tharsis", - "ref": "v9.1.0", + "owner": "evmos", + "ref": "v16.0.0-rc4", "repo": "evmos", "type": "github" } }, + "flake-compat": { + "flake": false, + "locked": { + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-parts": { "inputs": { "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1698882062, - "narHash": "sha256-HkhafUayIqxXyHH1X8d9RDl1M2CkFgZLjKD3MzabiEo=", + "narHash": "sha256-YcVE5emp1qQ8ieHUnxt1wCZCC3ZfAS+SRRWZ2TMda7E=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "8c9fa2545007b49a5db5f650ae91f227672c3877", + "rev": "34fed993f1674c8d06d58b37ce1e0fe5eebcb9f5", "type": "github" }, "original": { @@ -296,11 +395,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1681202837, - "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", "owner": "numtide", "repo": "flake-utils", - "rev": "cfacdce06f30d2b68473a46042957675eebb3401", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", "type": "github" }, "original": { @@ -310,8 +409,77 @@ } }, "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_3": { + "inputs": { + "systems": "systems_3" + }, + "locked": { + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_4": { + "inputs": { + "systems": "systems_4" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_5": { + "inputs": { + "systems": "systems_5" + }, + "locked": { + "lastModified": 1705309234, + "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_6": { "locked": { - "lastModified": 1667395993, "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", "owner": "numtide", "repo": "flake-utils", @@ -324,16 +492,16 @@ "type": "github" } }, - "flake-utils_3": { + "flake-utils_7": { "inputs": { - "systems": "systems_2" + "systems": "systems_6" }, "locked": { - "lastModified": 1701680307, - "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { @@ -345,11 +513,10 @@ "gaia-main-src": { "flake": false, "locked": { - "lastModified": 1697456548, - "narHash": "sha256-iXcwU0/kDAGzQKYrHKTMX6/ayB6Ns0KBYMOpi5uNYJk=", + "narHash": "sha256-1O8ncSd0mUNEUHSTi2U9d21Dv1yszQKohjp/AS6IxcU=", "owner": "cosmos", "repo": "gaia", - "rev": "e6da2cc3d1602a6c64fc50c90ea60651177d911b", + "rev": "2dc2b82ea9da34b3c4823458919004f1a583a597", "type": "github" }, "original": { @@ -361,7 +528,6 @@ "gaia10-src": { "flake": false, "locked": { - "lastModified": 1688401730, "narHash": "sha256-F72AxDI1OdleE8If5s4HJbORqMsDVsdEO5q7nrK07E8=", "owner": "cosmos", "repo": "gaia", @@ -378,7 +544,6 @@ "gaia11-src": { "flake": false, "locked": { - "lastModified": 1690464504, "narHash": "sha256-bIegGSPDdDRbznfgsrojsGCwCPSesNknpffTFskc7fE=", "owner": "cosmos", "repo": "gaia", @@ -395,7 +560,6 @@ "gaia12-src": { "flake": false, "locked": { - "lastModified": 1692870038, "narHash": "sha256-KqpkazhGGQWzvHiiwCiE7ciA8+L2t2HgxN8270zuGd0=", "owner": "cosmos", "repo": "gaia", @@ -412,7 +576,6 @@ "gaia13-src": { "flake": false, "locked": { - "lastModified": 1699370179, "narHash": "sha256-bvJ33JL1Fr7ilnnYEjrjnbS/dbFkyhZ2uq6u39CeTa0=", "owner": "cosmos", "repo": "gaia", @@ -429,7 +592,6 @@ "gaia14-src": { "flake": false, "locked": { - "lastModified": 1700067649, "narHash": "sha256-7AnaIy/SElf/Uj2xTbHzLSgPY68SgQqqJZ2BPmt6czo=", "owner": "cosmos", "repo": "gaia", @@ -443,10 +605,77 @@ "type": "github" } }, + "gaia15-src": { + "flake": false, + "locked": { + "lastModified": 1712522710, + "narHash": "sha256-2LsF++HkbVpX9h4DgkNea5nnyEuhDQSlNOAICdhAggU=", + "owner": "cosmos", + "repo": "gaia", + "rev": "7281c9b9dc4e3087ee87f5b24e416802b52e8661", + "type": "github" + }, + "original": { + "owner": "cosmos", + "ref": "v15.2.0", + "repo": "gaia", + "type": "github" + } + }, + "gaia17-src": { + "flake": false, + "locked": { + "lastModified": 1717626378, + "narHash": "sha256-FiCnGz5ZQQv2NyPW/Z7puZw6oFKcdoNsspSCK8Nkc44=", + "owner": "cosmos", + "repo": "gaia", + "rev": "17f2ba0b90d1d2884f7b67518ec08dfd37f001a7", + "type": "github" + }, + "original": { + "owner": "cosmos", + "ref": "v17.2.0", + "repo": "gaia", + "type": "github" + } + }, + "gaia18-src": { + "flake": false, + "locked": { + "lastModified": 1720430036, + "narHash": "sha256-wATunCFeMgCP9usv2TK/IKDGZIWfOKx2zWip5qWDuqk=", + "owner": "cosmos", + "repo": "gaia", + "rev": "58b4e54a95c7fc6a64272ccd0f09f46213c005ad", + "type": "github" + }, + "original": { + "owner": "cosmos", + "ref": "v18.1.0", + "repo": "gaia", + "type": "github" + } + }, + "gaia19-src": { + "flake": false, + "locked": { + "lastModified": 1724235134, + "narHash": "sha256-iAljnCnviTZ0wpgUYtTj+adH6imx6g6+niLq72yuoTk=", + "owner": "cosmos", + "repo": "gaia", + "rev": "4106e7a673da18b518fd81231a8e8b99bbf0fd0d", + "type": "github" + }, + "original": { + "owner": "cosmos", + "ref": "v19.1.0", + "repo": "gaia", + "type": "github" + } + }, "gaia5-src": { "flake": false, "locked": { - "lastModified": 1634231239, "narHash": "sha256-NfR9GRBNBlm5hB3lFea+Vlf4dkapZIZg0sZuyOX2cn8=", "owner": "cosmos", "repo": "gaia", @@ -463,7 +692,6 @@ "gaia6-ordered-src": { "flake": false, "locked": { - "lastModified": 1648034337, "narHash": "sha256-yw3WUCLRvn46xlWAnk6nBmvc3T91aryvBcOOfJ2ocPA=", "owner": "informalsystems", "repo": "gaia", @@ -480,7 +708,6 @@ "gaia6-src": { "flake": false, "locked": { - "lastModified": 1646904235, "narHash": "sha256-JdD0DTdMo05ggGvpHN5hugEEtGA0/WQ4bhbryDlfGXo=", "owner": "cosmos", "repo": "gaia", @@ -497,7 +724,6 @@ "gaia7-src": { "flake": false, "locked": { - "lastModified": 1665762684, "narHash": "sha256-hsDqDASwTPIb1BGOqa9nu4C5Y5q3hBoXYhkAFY7B9Cs=", "owner": "cosmos", "repo": "gaia", @@ -514,7 +740,6 @@ "gaia8-src": { "flake": false, "locked": { - "lastModified": 1676667875, "narHash": "sha256-8XPcJRQEQDtTbGFg0pWexkNdWESn1FoKvz4T2Z8UPDw=", "owner": "cosmos", "repo": "gaia", @@ -531,7 +756,6 @@ "gaia9-src": { "flake": false, "locked": { - "lastModified": 1681924944, "narHash": "sha256-UIM6yfqs1yZZ2BO/bBB43pPYSW1IzaYsk2f500tDYzA=", "owner": "cosmos", "repo": "gaia", @@ -548,7 +772,6 @@ "gex-src": { "flake": false, "locked": { - "lastModified": 1697704475, "narHash": "sha256-lgJVxn7Q2I8TBdvbzyn7bl1MN5StEw3NvRzCvBFFuB8=", "owner": "cosmos", "repo": "gex", @@ -562,19 +785,112 @@ "type": "github" } }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "cosmos-nix", + "haqq-src", + "devenv", + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gomod2nix": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": [ + "cosmos-nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1722589758, + "narHash": "sha256-sbbA8b6Q2vB/t/r1znHawoXLysCyD4L/6n6/RykiSnA=", + "owner": "nix-community", + "repo": "gomod2nix", + "rev": "4e08ca09253ef996bd4c03afa383b23e35fe28a1", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "gomod2nix", + "type": "github" + } + }, + "gomod2nix_2": { + "inputs": { + "flake-utils": [ + "cosmos-nix", + "haqq-src", + "flake-utils" + ], + "nixpkgs": [ + "cosmos-nix", + "haqq-src", + "nixpkgs-unstable" + ] + }, + "locked": { + "narHash": "sha256-yfQQ67dLejP0FLK76LKHbkzcQqNIrux6MFe32MMFGNQ=", + "owner": "nix-community", + "repo": "gomod2nix", + "rev": "30e3c3a9ec4ac8453282ca7f67fca9e1da12c3e6", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "master", + "repo": "gomod2nix", + "type": "github" + } + }, + "haqq-src": { + "inputs": { + "devenv": "devenv", + "flake-utils": "flake-utils_3", + "gomod2nix": "gomod2nix_2", + "nixpkgs": "nixpkgs", + "nixpkgs-unstable": "nixpkgs-unstable" + }, + "locked": { + "narHash": "sha256-pXbLGvq6ZyZbtKYoe8GbgaxGV0SIbARrT6DkDmPwlYE=", + "owner": "haqq-network", + "repo": "haqq", + "rev": "18370cfb2f9aab35d311c4c75ab5586f50213830", + "type": "github" + }, + "original": { + "owner": "haqq-network", + "repo": "haqq", + "rev": "18370cfb2f9aab35d311c4c75ab5586f50213830", + "type": "github" + } + }, "hermes-src": { "flake": false, "locked": { - "lastModified": 1689751768, - "narHash": "sha256-yq+jdHSwUejMA1hURSHWHJ8QSyhDdnhpKE+tejgWSSE=", + "narHash": "sha256-JTZMp4By/pGsMdKzfi4H1LQS1RKYQHBq5NEju5ADX/s=", "owner": "informalsystems", "repo": "hermes", - "rev": "1c1cf02988db67507de7d484e1a7f317fe494d6c", + "rev": "ab732666fe35de129ada98731280d03411f6375f", "type": "github" }, "original": { "owner": "informalsystems", - "ref": "v1.6.0", + "ref": "v1.7.4", "repo": "hermes", "type": "github" } @@ -582,7 +898,6 @@ "ibc-go-v2-src": { "flake": false, "locked": { - "lastModified": 1663274791, "narHash": "sha256-LuJvlXmGRyJAiM6+uk+NuamjIsEqMqF20twBmB0p8+k=", "owner": "cosmos", "repo": "ibc-go", @@ -599,7 +914,6 @@ "ibc-go-v3-src": { "flake": false, "locked": { - "lastModified": 1663683283, "narHash": "sha256-Er24B1unLYR/gG4JSrV+vZ/cPD6t7OFvtqp7AJCtDSE=", "owner": "cosmos", "repo": "ibc-go", @@ -616,16 +930,16 @@ "ibc-go-v4-src": { "flake": false, "locked": { - "lastModified": 1667809128, - "narHash": "sha256-R1/AH6laXdaMftgwnV4t/pL3QoKnZ1UaBGoqOipOvQI=", + "lastModified": 1712304740, + "narHash": "sha256-CNv3uBCALT21ZczOmXcQaavOy7KsR0VTBahw5DrvO4w=", "owner": "cosmos", "repo": "ibc-go", - "rev": "ecb845d5e43f53decf48f8ed88c7847a9a4375cb", + "rev": "5480cf7fac99882a8833ddb7c95e8b4820ab7d4f", "type": "github" }, "original": { "owner": "cosmos", - "ref": "v4.2.0", + "ref": "v4.6.0", "repo": "ibc-go", "type": "github" } @@ -633,16 +947,16 @@ "ibc-go-v5-src": { "flake": false, "locked": { - "lastModified": 1668024626, - "narHash": "sha256-+Z78PyGODLr2Y5G8evubsoQE3tyUcxCHJDsLXKTmdlI=", + "lastModified": 1712304845, + "narHash": "sha256-CE6Nv6U3Jqn4c+5JB/rek9LHD+AXEnkS0FVJYz4/uSc=", "owner": "cosmos", "repo": "ibc-go", - "rev": "c0acd5bd1778f2b7ecdf593006f56bd3e273bd49", + "rev": "40cacfe075947f21520b014294f1f7948e4eda7c", "type": "github" }, "original": { "owner": "cosmos", - "ref": "v5.1.0", + "ref": "v5.4.0", "repo": "ibc-go", "type": "github" } @@ -650,16 +964,16 @@ "ibc-go-v6-src": { "flake": false, "locked": { - "lastModified": 1671525236, - "narHash": "sha256-V8kUNwgNfx1tZJazlnaTF6wBb7ztueh1KrAGgiP8hCM=", + "lastModified": 1712318519, + "narHash": "sha256-roRXZEOJIFJiXEQ+a71QdMmqoVJKVk2wvPgHJ9r/mQ8=", "owner": "cosmos", "repo": "ibc-go", - "rev": "d34cef7e075dda1a24a0a3e9b6d3eff406cc606c", + "rev": "8e31269c692d87ac65bfe70cf609925975a57203", "type": "github" }, "original": { "owner": "cosmos", - "ref": "v6.1.0", + "ref": "v6.3.0", "repo": "ibc-go", "type": "github" } @@ -667,33 +981,33 @@ "ibc-go-v7-src": { "flake": false, "locked": { - "lastModified": 1693509694, - "narHash": "sha256-umh/ckDALt0ugXwN8glcaCkGfAQvXY7S3Jd95Do2XeA=", + "lastModified": 1712318559, + "narHash": "sha256-uYiUNXLD48v3vRGK6/aQ7z7Ed5hY8VnEBGG/3Uv87Nc=", "owner": "cosmos", "repo": "ibc-go", - "rev": "c75650a1a037a9fecba5a9005df380f707520ff7", + "rev": "802ca265dba74a293747e1ccb8b7999aa985af19", "type": "github" }, "original": { "owner": "cosmos", - "ref": "v7.3.0", + "ref": "v7.4.0", "repo": "ibc-go", "type": "github" } }, - "ibc-go-v8-channel-upgrade-src": { + "ibc-go-v7-wasm-src": { "flake": false, "locked": { - "lastModified": 1695726576, - "narHash": "sha256-mM6h1KAi8lQUrJakxI6f8WI+vpmBhCnAysk3hTZBI7M=", + "lastModified": 1722365763, + "narHash": "sha256-ZYGCvm1Ek1RaXKzkkwQCc56I2HzmbrLR/lFD5IZZdLc=", "owner": "cosmos", "repo": "ibc-go", - "rev": "63c30108f0ecf954108cf51f50f3d36ec58c7e51", + "rev": "13c071f0b34d67342f0b7a8874d84d2e68b887e1", "type": "github" }, "original": { "owner": "cosmos", - "ref": "04-channel-upgrades-alpha.0", + "ref": "modules/light-clients/08-wasm/v0.3.1+ibc-go-v7.4-wasmvm-v1.5", "repo": "ibc-go", "type": "github" } @@ -701,16 +1015,50 @@ "ibc-go-v8-src": { "flake": false, "locked": { - "lastModified": 1699602904, - "narHash": "sha256-BcP3y874QviVsV+04p9CioolyvmWH82ORbb5EB2GyRI=", + "lastModified": 1716359952, + "narHash": "sha256-KTjyHwmXA/jgppDKRe85XfRmh8O7AHFKhDyyOb9VROU=", + "owner": "cosmos", + "repo": "ibc-go", + "rev": "9b6567bf818198ded336490d5f2d89c9d42fd87b", + "type": "github" + }, + "original": { + "owner": "cosmos", + "ref": "v8.3.1", + "repo": "ibc-go", + "type": "github" + } + }, + "ibc-go-v8-wasm-src": { + "flake": false, + "locked": { + "lastModified": 1722365433, + "narHash": "sha256-mgfbibipk09LtO0h0hQDfnVA0cQADaI6Bq+ruyP6xI4=", + "owner": "cosmos", + "repo": "ibc-go", + "rev": "ccd4dc278e720be87418028026ebd93a80fa5ac0", + "type": "github" + }, + "original": { + "owner": "cosmos", + "ref": "modules/light-clients/08-wasm/v0.4.1+ibc-go-v8.4-wasmvm-v2.0", + "repo": "ibc-go", + "type": "github" + } + }, + "ibc-go-v9-src": { + "flake": false, + "locked": { + "lastModified": 1723037346, + "narHash": "sha256-ba8gbJ0l4l8ZRT9XVN3hTcnxZSb5Fn20p1xiEG4/54c=", "owner": "cosmos", "repo": "ibc-go", - "rev": "2551dea41cd3c512845007ca895c8402afa9b79f", + "rev": "66ebf864d7bfe2193a96c972a9e74196b2ddf104", "type": "github" }, "original": { "owner": "cosmos", - "ref": "v8.0.0", + "ref": "v9.0.0-beta.1", "repo": "ibc-go", "type": "github" } @@ -718,7 +1066,6 @@ "ibc-rs-src": { "flake": false, "locked": { - "lastModified": 1661171856, "narHash": "sha256-M9KsPQdvyTArDe3sTi29+gfs69KHtpoNYLgI7IHYo9U=", "owner": "informalsystems", "repo": "ibc-rs", @@ -735,7 +1082,6 @@ "ica-src": { "flake": false, "locked": { - "lastModified": 1695202199, "narHash": "sha256-8RwZSnqqZzVjQsSMTckNhmTy3VYyubVmgE/hU6ntq9M=", "owner": "cosmos", "repo": "interchain-accounts-demo", @@ -765,14 +1111,30 @@ "type": "github" } }, + "injective-src": { + "flake": false, + "locked": { + "lastModified": 1722874193, + "narHash": "sha256-zDG32ogXMep0wKegDN8zm1YmadcVpwlrY+ITokefcVI=", + "owner": "OpenDeFiFoundation", + "repo": "injective-core", + "rev": "725af8f9ca6809d6b1026d5e8dddeb309ff97b42", + "type": "github" + }, + "original": { + "owner": "OpenDeFiFoundation", + "ref": "v1.13.1", + "repo": "injective-core", + "type": "github" + } + }, "interchain-security-src": { "flake": false, "locked": { - "lastModified": 1697113174, - "narHash": "sha256-J+duWnA9ipgHryO5+9sv6uwcPVN2ceL0PGoCyVvN5YQ=", + "narHash": "sha256-adBzn51PKoRsCL9gIzC5Tcqmu7u3GjxTcDj2jpZ/da8=", "owner": "cosmos", "repo": "interchain-security", - "rev": "28e0c14b34d5d15ea0eb19b694c74513667afe09", + "rev": "03aada4af3243dbf739a12adfacc7b37232df694", "type": "github" }, "original": { @@ -785,7 +1147,6 @@ "iris-src": { "flake": false, "locked": { - "lastModified": 1618986686, "narHash": "sha256-1nPJOuYeGjzBYFCS0IiC5j9TJd5KVa9IL0kROks328E=", "owner": "irisnet", "repo": "irishub", @@ -802,7 +1163,6 @@ "ixo-src": { "flake": false, "locked": { - "lastModified": 1645476442, "narHash": "sha256-Ewp9UyoH6z7YGrcXVpYJveRvDq02c1mNZj2hzlOoW8s=", "owner": "ixofoundation", "repo": "ixo-blockchain", @@ -819,61 +1179,117 @@ "juno-src": { "flake": false, "locked": { - "lastModified": 1697166503, - "narHash": "sha256-z9TOeDyUnn1T8Z662XqQJ9ydVIKKB54YISt7ms4xvos=", + "lastModified": 1724278445, + "narHash": "sha256-XvJqp36HSYqm6OMLQqJPX5sCT52GxSLFDMO+fJovh+0=", "owner": "CosmosContracts", "repo": "juno", - "rev": "48507ed9b83511089cbf1fdc5bae54cae4a7f4b2", + "rev": "2f119adacca3a1668ff150c225a3f423501e748c", "type": "github" }, "original": { "owner": "CosmosContracts", - "ref": "v17.1.1", + "ref": "v24.0.0", "repo": "juno", "type": "github" } }, - "migaloo-src": { + "lowdown-src": { "flake": false, "locked": { - "lastModified": 1699273936, - "narHash": "sha256-O+vGWFnV3+bvXinxl1QjVyDnQskp5H1VnlL+TaMfiSs=", - "owner": "White-Whale-Defi-Platform", - "repo": "migaloo-chain", - "rev": "de98de2dd96917ae1ab79161d573fc0b4ee1facf", + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", "type": "github" }, "original": { - "owner": "White-Whale-Defi-Platform", - "ref": "v3.0.2", - "repo": "migaloo-chain", + "owner": "kristapsdz", + "repo": "lowdown", "type": "github" } }, - "neutron-src": { + "migaloo-src": { "flake": false, "locked": { - "lastModified": 1701174344, - "narHash": "sha256-NuoOlrciBeL2f/A7wlQBqYlYJhSYucXRhLgxdasfyhI=", + "lastModified": 1720168667, + "narHash": "sha256-vOzOBNGaIOhTjTnycLp6sQKGAklkPVZdJLPPqdjufnM=", + "owner": "White-Whale-Defi-Platform", + "repo": "migaloo-chain", + "rev": "076c6d12ecadcf4db42592a8340cb3be2ed23349", + "type": "github" + }, + "original": { + "owner": "White-Whale-Defi-Platform", + "ref": "v4.2.0", + "repo": "migaloo-chain", + "type": "github" + } + }, + "namada-src": { + "flake": false, + "locked": { + "narHash": "sha256-WyIVffqszY3rz3ClQJlpDaexLGQk8pVK+Y3k/D9Lvxg=", + "owner": "anoma", + "repo": "namada", + "rev": "468d3d3bcadd2bd11760855d2bbfcc0b4ce27e14", + "type": "github" + }, + "original": { + "owner": "anoma", + "ref": "v0.28.1", + "repo": "namada", + "type": "github" + } + }, + "neutron-src": { + "flake": false, + "locked": { + "lastModified": 1724773633, + "narHash": "sha256-pHubObIv3p6IrzI/U7aeDjdF5kWBpI9qgDoH/Hjk+i8=", "owner": "neutron-org", "repo": "neutron", - "rev": "e605ed3db4381994ee8185ba4a0ff0877d34e67f", + "rev": "1b10cd282d5809ccdd87208918fd175aebec2b0b", "type": "github" }, "original": { "owner": "neutron-org", - "ref": "v2.0.0", + "ref": "v4.2.2", "repo": "neutron", "type": "github" } }, + "nix": { + "inputs": { + "lowdown-src": "lowdown-src", + "nixpkgs": [ + "cosmos-nix", + "haqq-src", + "devenv", + "nixpkgs" + ], + "nixpkgs-regression": "nixpkgs-regression" + }, + "locked": { + "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=", + "owner": "domenkozar", + "repo": "nix", + "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "relaxed-flakes", + "repo": "nix", + "type": "github" + } + }, "nix-std": { "locked": { - "lastModified": 1685917625, - "narHash": "sha256-2manVKofCZrCToVDnDYNvtYUFBYOM5JhdDoNGVY4fq4=", + "lastModified": 1710870712, + "narHash": "sha256-e+7MJF2gsgTBuOWv4mCimSP0D9+naeFSw9a7N3yEmv4=", "owner": "chessai", "repo": "nix-std", - "rev": "e20af8822b5739434b875643bfc61fe0195ea2fb", + "rev": "31bbc925750cc9d8f828fe55cee1a2bd985e0c00", "type": "github" }, "original": { @@ -882,30 +1298,48 @@ "type": "github" } }, - "nixpkgs": { + "nix2container": { + "inputs": { + "flake-utils": "flake-utils_4", + "nixpkgs": [ + "cosmos-nix", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1701040486, - "narHash": "sha256-vawYwoHA5CwvjfqaT3A5CT9V36Eq43gxdwpux32Qkjw=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "45827faa2132b8eade424f6bdd48d8828754341a", + "lastModified": 1712990762, + "narHash": "sha256-hO9W3w7NcnYeX8u8cleHiSpK2YJo7ecarFTUlbybl7k=", + "owner": "nlewo", + "repo": "nix2container", + "rev": "20aad300c925639d5d6cbe30013c8357ce9f2a2e", "type": "github" }, "original": { - "owner": "nixos", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", + "owner": "nlewo", + "repo": "nix2container", "type": "github" } }, + "nixpkgs": { + "locked": { + "narHash": "sha256-LahKBAfGbY836gtpVNnWwBTIzN7yf/uYM/S0g393r0Y=", + "rev": "9f2ee8c91ac42da3ae6c6a1d21555f283458247e", + "revCount": 555392, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.2311.555392%2Brev-9f2ee8c91ac42da3ae6c6a1d21555f283458247e/018d7c73-3161-76d5-aca1-5929105b0aa0/source.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/NixOS/nixpkgs/0.2311.%2A.tar.gz" + } + }, "nixpkgs-lib": { "locked": { "dir": "lib", - "lastModified": 1698611440, - "narHash": "sha256-jPjHjrerhYDy3q9+s5EAsuhyhuknNfowY6yt6pjn9pc=", + "narHash": "sha256-ztaDIyZ7HrTAfEEUt9AtTDNoCYxUdSd6NrRHaYOIxtk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "0cbe9f69c234a7700596e943bfae7ef27a31b735", + "rev": "e92039b55bcd58469325ded85d4f58dd5a4eaf58", "type": "github" }, "original": { @@ -916,17 +1350,62 @@ "type": "github" } }, - "nixpkgs_2": { + "nixpkgs-regression": { "locked": { - "lastModified": 1681358109, - "narHash": "sha256-eKyxW4OohHQx9Urxi7TQlFBTDWII+F+x2hklDOQPB50=", + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "96ba1c52e54e74c3197f4d43026b3f3d92e83ff9", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "c37ca420157f4abc31e26f436c1145f8951ff373", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-unstable": { + "locked": { + "narHash": "sha256-ZbHsm+mGk/izkWtT4xwwqz38fdlwu7nUUKXTOmm4SyE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "faf912b086576fd1a15fca610166c98d47bc667e", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1723603349, + "narHash": "sha256-VMg6N7MryOuvSJ8Sj6YydarnUCkL7cvMdrMcnsJnJCE=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "daf7bb95821b789db24fc1ac21f613db0c1bf2cb", + "type": "github" + }, + "original": { + "owner": "nixos", "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" @@ -934,7 +1413,22 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1674990008, + "lastModified": 1706487304, + "narHash": "sha256-LE8lVX28MV2jWJsidW13D2qrHU/RUUONendL2Q/WlJg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "90f456026d284c22b3e3497be980b2e47d0b28ac", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { "narHash": "sha256-4zOyp+hFW2Y7imxIpZqZGT8CEqKmDjwgfD6BzRUE0mQ=", "owner": "NixOS", "repo": "nixpkgs", @@ -948,13 +1442,13 @@ "type": "github" } }, - "nixpkgs_4": { + "nixpkgs_5": { "locked": { - "lastModified": 1701693815, - "narHash": "sha256-7BkrXykVWfkn6+c1EhFA3ko4MLi3gVG0p9G96PNnKTM=", + "lastModified": 1725194671, + "narHash": "sha256-tLGCFEFTB5TaOKkpfw3iYT9dnk4awTP/q4w+ROpMfuw=", "owner": "nixos", "repo": "nixpkgs", - "rev": "09ec6a0881e1a36c29d67497693a67a16f4da573", + "rev": "b833ff01a0d694b910daca6e2ff4a3f26dee478c", "type": "github" }, "original": { @@ -967,33 +1461,64 @@ "osmosis-src": { "flake": false, "locked": { - "lastModified": 1700576443, - "narHash": "sha256-UE3XEgdSp8mlgIKQRrBfb4wiPEeagB/wNWfDvDq4up4=", + "lastModified": 1719537675, + "narHash": "sha256-8Lb2SppNfq3+JwP3uanmCxuCek6tXOO/GcG27XGxRrE=", "owner": "osmosis-labs", "repo": "osmosis", - "rev": "d9965b09d3e8690c77050bb095bc5b69772ebdfb", + "rev": "b973bffdf127866f45624d7e5a81f31fdc8e8e0b", "type": "github" }, "original": { "owner": "osmosis-labs", - "ref": "v20.4.0", + "ref": "v25.2.0", "repo": "osmosis", "type": "github" } }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": [ + "cosmos-nix", + "haqq-src", + "devenv", + "flake-compat" + ], + "flake-utils": "flake-utils_2", + "gitignore": "gitignore", + "nixpkgs": [ + "cosmos-nix", + "haqq-src", + "devenv", + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "narHash": "sha256-2+SDlNRTKsgo3LBRiMUcoEUb6sDViRNQhzJquZ4koOI=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "5843cf069272d92b60c3ed9e55b7a8989c01d4c7", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, "provenance-src": { "flake": false, "locked": { - "lastModified": 1699901286, - "narHash": "sha256-dTX3kg2QUsC9SwsaommP4IFgIdQgWZrGQNtp/B+fzys=", + "lastModified": 1721946876, + "narHash": "sha256-4RAyX3ORmbojnmDlMQMWF7mdmbaiBbqegZt0SMd9cXE=", "owner": "provenance-io", "repo": "provenance", - "rev": "91b0813de2f93d03cefe8efb226dc32f02690840", + "rev": "d1119ab02c423d86a0f485a8f124e73511ec1b9b", "type": "github" }, "original": { "owner": "provenance-io", - "ref": "v1.17.0", + "ref": "v1.19.1", "repo": "provenance", "type": "github" } @@ -1001,7 +1526,6 @@ "regen-src": { "flake": false, "locked": { - "lastModified": 1645832054, "narHash": "sha256-lDb0/Bw4hAX71jsCQJUju1mKYNacWEVezx6+KdIdu6Q=", "owner": "regen-network", "repo": "regen-ledger", @@ -1018,7 +1542,6 @@ "relayer-src": { "flake": false, "locked": { - "lastModified": 1635197290, "narHash": "sha256-xD+xZG4Gb6557y/jkXTGdbt8qJ6izMgC4H3uo2/j5vU=", "owner": "cosmos", "repo": "relayer", @@ -1032,24 +1555,40 @@ "type": "github" } }, + "rollapp-evm-src": { + "flake": false, + "locked": { + "narHash": "sha256-bOH7QsNYjZVVHW7x5ysrO0IJmRNEUeE+bJRVPwdb5U8=", + "owner": "dymensionxyz", + "repo": "rollapp-evm", + "rev": "21b29f6e77f5c11a2036252d60819810abbbd7b8", + "type": "github" + }, + "original": { + "owner": "dymensionxyz", + "repo": "rollapp-evm", + "rev": "21b29f6e77f5c11a2036252d60819810abbbd7b8", + "type": "github" + } + }, "root": { "inputs": { "cosmos-nix": "cosmos-nix", - "flake-utils": "flake-utils_3", - "nixpkgs": "nixpkgs_4" + "flake-utils": "flake-utils_7", + "nixpkgs": "nixpkgs_5" } }, "rust-overlay": { "inputs": { - "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs_2" + "flake-utils": "flake-utils_5", + "nixpkgs": "nixpkgs_3" }, "locked": { - "lastModified": 1701310566, - "narHash": "sha256-CL9J3xUR2Ejni4LysrEGX0IdO+Y4BXCiH/By0lmF3eQ=", + "lastModified": 1710468700, + "narHash": "sha256-YGN6R0nLfB2L57J8T/DX+LcB06QipyYzHSz7AD8B0n0=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "6d3c6e185198b8bf7ad639f22404a75aa9a09bff", + "rev": "7ff8e9a04ac7777a3446788cb4018b452157ab8a", "type": "github" }, "original": { @@ -1060,11 +1599,10 @@ }, "sbt-derivation": { "inputs": { - "flake-utils": "flake-utils_2", - "nixpkgs": "nixpkgs_3" + "flake-utils": "flake-utils_6", + "nixpkgs": "nixpkgs_4" }, "locked": { - "lastModified": 1698464090, "narHash": "sha256-Pnej7WZIPomYWg8f/CZ65sfW85IfIUjYhphMMg7/LT0=", "owner": "zaninime", "repo": "sbt-derivation", @@ -1080,7 +1618,6 @@ "sconfig-src": { "flake": false, "locked": { - "lastModified": 1679585941, "narHash": "sha256-ywh9IcqMWbRHqJkGJezcDCvfbBYNJH7ualKvPJQRcHA=", "owner": "freshautomations", "repo": "sconfig", @@ -1096,7 +1633,6 @@ "sentinel-src": { "flake": false, "locked": { - "lastModified": 1647195309, "narHash": "sha256-+ZobsjLNxVL3+zi6OEFQhff6Gbd9kng8B0haqcOoiP0=", "owner": "sentinel-official", "repo": "hub", @@ -1113,7 +1649,6 @@ "sifchain-src": { "flake": false, "locked": { - "lastModified": 1648486445, "narHash": "sha256-n5fmWtdrc0Rhs6Uo+zjcSXmyEFVIsA5L9dlrbRXGDmU=", "owner": "Sifchain", "repo": "sifnode", @@ -1127,10 +1662,25 @@ "type": "github" } }, + "slinky-src": { + "flake": false, + "locked": { + "narHash": "sha256-gto9l+zeM1WLIv/VtVlrhTpUTMLN+niQTo5zlrbkx30=", + "owner": "skip-mev", + "repo": "slinky", + "rev": "642846e3517f4aa4ffe1cd29180fef4d459bfbfe", + "type": "github" + }, + "original": { + "owner": "skip-mev", + "ref": "v0.2.0", + "repo": "slinky", + "type": "github" + } + }, "stargaze-src": { "flake": false, "locked": { - "lastModified": 1645539964, "narHash": "sha256-5I5pdnBJHwNaI2Soet+zH3aH+pUbYdC9TgHBjOd1TmA=", "owner": "public-awesome", "repo": "stargaze", @@ -1147,7 +1697,6 @@ "stoml-src": { "flake": false, "locked": { - "lastModified": 1666796497, "narHash": "sha256-Adjag1/Hd2wrar2/anD6jQEMDvUc2TOIG7DlEgxpTXc=", "owner": "freshautomations", "repo": "stoml", @@ -1160,41 +1709,67 @@ "type": "github" } }, - "stride-consumer-src": { + "stride-src": { "flake": false, "locked": { - "lastModified": 1689464372, - "narHash": "sha256-DByig9ISs9x9Kvakc8LFL558VKhM+UBiaESWgyVzI0w=", + "lastModified": 1721921071, + "narHash": "sha256-EtsK7sjzQ2XfYt3DSV85IbKj7HEMy2Apt0m8kfgCEuk=", "owner": "Stride-Labs", "repo": "stride", - "rev": "bbf0bb7f52878f3205c76bb1e96662fe7bd7af8d", + "rev": "d6e4e686e54a6a3c41d3ca0645f91ee1dc3ec441", "type": "github" }, "original": { "owner": "Stride-Labs", - "ref": "v12.1.0", + "ref": "v23.0.1", "repo": "stride", "type": "github" } }, - "stride-src": { - "flake": false, + "systems": { "locked": { - "lastModified": 1679819302, - "narHash": "sha256-fdjnFHPBZNnhDyVoMuPfqNb6YUYRdcMO73FlZHjIuzA=", - "owner": "Stride-Labs", - "repo": "stride", - "rev": "3c69e7644859981b1fd9313eb1f0c5e5886e4a0d", + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", "type": "github" }, "original": { - "owner": "Stride-Labs", - "ref": "v8.0.0", - "repo": "stride", + "owner": "nix-systems", + "repo": "default", "type": "github" } }, - "systems": { + "systems_2": { + "locked": { + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_3": { + "locked": { + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_4": { "locked": { "lastModified": 1681028828, "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", @@ -1209,7 +1784,22 @@ "type": "github" } }, - "systems_2": { + "systems_5": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_6": { "locked": { "lastModified": 1681028828, "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", @@ -1227,7 +1817,6 @@ "umee-src": { "flake": false, "locked": { - "lastModified": 1649261156, "narHash": "sha256-hydRL/88fHCW/k7z7GoqAwvynZuvLEDLyA6A9Cm+6UY=", "owner": "umee-network", "repo": "umee", @@ -1244,33 +1833,16 @@ "wasmd-src": { "flake": false, "locked": { - "lastModified": 1669987561, - "narHash": "sha256-F0p555FEeA405tuLn82yUEbRZpJLs85GrUKvSrjTdjk=", + "lastModified": 1724231006, + "narHash": "sha256-X8Q93gqk+gBJwn4EIxFVeWqRpHcIxNAplfARejHwfbk=", "owner": "CosmWasm", "repo": "wasmd", - "rev": "a347ace2ff41539fe06c68168bc6f28d6ca9fa52", + "rev": "de7db0dc672e7beb201e06e7eb12b2de356ac7c9", "type": "github" }, "original": { "owner": "CosmWasm", - "ref": "v0.30.0", - "repo": "wasmd", - "type": "github" - } - }, - "wasmd_next-src": { - "flake": false, - "locked": { - "lastModified": 1682094944, - "narHash": "sha256-b+6XhBdKyQlrzsYxVRrDf4vHpv8GAJkGwHVfJ9sdf3U=", - "owner": "CosmWasm", - "repo": "wasmd", - "rev": "c2bb27d289f7f72f1471a4b33cb08fdfc8d66f63", - "type": "github" - }, - "original": { - "owner": "CosmWasm", - "ref": "v0.40.0-rc.1", + "ref": "v0.53.0", "repo": "wasmd", "type": "github" } @@ -1278,7 +1850,6 @@ "wasmvm_1-src": { "flake": false, "locked": { - "lastModified": 1652698028, "narHash": "sha256-4m64mPwFLz7aZEKVxM2lJQtX98BkhdKTZb3evpDOk/4=", "owner": "CosmWasm", "repo": "wasmvm", @@ -1295,7 +1866,6 @@ "wasmvm_1_1_1-src": { "flake": false, "locked": { - "lastModified": 1663600745, "narHash": "sha256-9K/G7Wu/TfW4Z+lseEutXbdtr+A40nbVejBphegF5z4=", "owner": "CosmWasm", "repo": "wasmvm", @@ -1312,7 +1882,6 @@ "wasmvm_1_1_2-src": { "flake": false, "locked": { - "lastModified": 1681833975, "narHash": "sha256-EbzMNkZUO94jEdX0WgAdy5qfhlCG3lpHpVHyT2FcSDw=", "owner": "CosmWasm", "repo": "wasmvm", @@ -1329,7 +1898,6 @@ "wasmvm_1_2_3-src": { "flake": false, "locked": { - "lastModified": 1681831436, "narHash": "sha256-GscUMJ0Tkg77S9IYA9komyKKoa1AyVXSSaU8hw3ZNwk=", "owner": "CosmWasm", "repo": "wasmvm", @@ -1346,7 +1914,6 @@ "wasmvm_1_2_4-src": { "flake": false, "locked": { - "lastModified": 1685977963, "narHash": "sha256-/GOvkKLQwsPms7h7yEZYLwbZn9Lzk5qQnBXXoZ/R6JM=", "owner": "CosmWasm", "repo": "wasmvm", @@ -1360,10 +1927,26 @@ "type": "github" } }, + "wasmvm_1_2_6-src": { + "flake": false, + "locked": { + "lastModified": 1704896412, + "narHash": "sha256-W0WuC9eRxp67UeQZ0HDZ9/iIC5JKsylB2g6YpYFjMGM=", + "owner": "CosmWasm", + "repo": "wasmvm", + "rev": "66763124d7dd49b775cb86b637376eecb1e3f56a", + "type": "github" + }, + "original": { + "owner": "CosmWasm", + "ref": "v1.2.6", + "repo": "wasmvm", + "type": "github" + } + }, "wasmvm_1_3_0-src": { "flake": false, "locked": { - "lastModified": 1689589428, "narHash": "sha256-rsTYvbkYpDkUE4IvILdSL3hXMgAWxz5ltGotJB2t1e4=", "owner": "CosmWasm", "repo": "wasmvm", @@ -1380,7 +1963,6 @@ "wasmvm_1_5_0-src": { "flake": false, "locked": { - "lastModified": 1698746477, "narHash": "sha256-l0cNF0YjviEl/JLJ4VdvDtIGuAYyFfncVo83ROfQFD8=", "owner": "CosmWasm", "repo": "wasmvm", @@ -1394,10 +1976,43 @@ "type": "github" } }, + "wasmvm_1_5_2-src": { + "flake": false, + "locked": { + "lastModified": 1705576719, + "narHash": "sha256-3KJq5jFllFSqlm85/iRWYMhu99iuokvR3Ib9Gq3gIjc=", + "owner": "CosmWasm", + "repo": "wasmvm", + "rev": "b742b2623cce98f04ae5d8bfb488c73988f3dd61", + "type": "github" + }, + "original": { + "owner": "CosmWasm", + "ref": "v1.5.2", + "repo": "wasmvm", + "type": "github" + } + }, + "wasmvm_1_5_4-src": { + "flake": false, + "locked": { + "lastModified": 1723135235, + "narHash": "sha256-DGQHC20eMa1CDIx9fWYTTBxdFDCPoS/SsEDJnWJ+7bA=", + "owner": "CosmWasm", + "repo": "wasmvm", + "rev": "9f85c0f44fb8a5573be8e461cad12f784c544c4b", + "type": "github" + }, + "original": { + "owner": "CosmWasm", + "ref": "v1.5.4", + "repo": "wasmvm", + "type": "github" + } + }, "wasmvm_1_beta7-src": { "flake": false, "locked": { - "lastModified": 1646675433, "narHash": "sha256-tt9aAPLxtIRsG1VFM1YAIHSotuBl170EiBcHSWTtARI=", "owner": "CosmWasm", "repo": "wasmvm", @@ -1410,6 +2025,74 @@ "repo": "wasmvm", "type": "github" } + }, + "wasmvm_2_0_0-src": { + "flake": false, + "locked": { + "lastModified": 1710250586, + "narHash": "sha256-OmETCXyhCXWOEW/emf1ZruLMPlH8iLvM8xrqFoDaxnw=", + "owner": "CosmWasm", + "repo": "wasmvm", + "rev": "5307690b77a5fef2da3747ec72abe8f29664aeca", + "type": "github" + }, + "original": { + "owner": "CosmWasm", + "ref": "v2.0.0", + "repo": "wasmvm", + "type": "github" + } + }, + "wasmvm_2_0_3-src": { + "flake": false, + "locked": { + "lastModified": 1723134607, + "narHash": "sha256-fFFP9sqlfgFbjAPP6VVXEcDQ3is2RHZYNE003Ls8Sfk=", + "owner": "CosmWasm", + "repo": "wasmvm", + "rev": "64b8c846dadb664eeb9da765a98fc370eb594f6d", + "type": "github" + }, + "original": { + "owner": "CosmWasm", + "ref": "v2.0.3", + "repo": "wasmvm", + "type": "github" + } + }, + "wasmvm_2_1_0-src": { + "flake": false, + "locked": { + "lastModified": 1720688907, + "narHash": "sha256-Ev/2cUKT0i9ytvfrzh15Ibja4TBXjoeB7RLHn28yRCY=", + "owner": "CosmWasm", + "repo": "wasmvm", + "rev": "d7906b3030061a959c54ee57c88e3256b8e90a0c", + "type": "github" + }, + "original": { + "owner": "CosmWasm", + "ref": "v2.1.0", + "repo": "wasmvm", + "type": "github" + } + }, + "wasmvm_2_1_2-src": { + "flake": false, + "locked": { + "lastModified": 1723135029, + "narHash": "sha256-Y3BVRR2T5MLOtXdPK38W8MX8etIuqGcTjvxkaEOyvVM=", + "owner": "CosmWasm", + "repo": "wasmvm", + "rev": "d8f06b73e4d49f8246e1569f032962122427882b", + "type": "github" + }, + "original": { + "owner": "CosmWasm", + "ref": "v2.1.2", + "repo": "wasmvm", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 7e2f5756e3..1a9ae4229a 100644 --- a/flake.nix +++ b/flake.nix @@ -32,8 +32,7 @@ cometbft evmos gaia6-ordered - gaia13 - gaia14 + gaia18 ibc-go-v2-simapp ibc-go-v3-simapp ibc-go-v4-simapp @@ -41,6 +40,7 @@ ibc-go-v6-simapp ibc-go-v7-simapp ibc-go-v8-simapp + ibc-go-v9-simapp interchain-security migaloo neutron @@ -49,9 +49,8 @@ provenance stride stride-no-admin - stride-consumer-no-admin - stride-consumer wasmd + injective ; python = nixpkgs.python3.withPackages (p: [ diff --git a/guide/README.md b/guide/README.md index 119ddbdef2..37a44860ba 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.7.4`. +Current version: `v1.10.3`. The version of this guide is aligned with the [versioning of the ibc crates](../README.md). diff --git a/guide/src/SUMMARY.md b/guide/src/SUMMARY.md index e85b810e6b..1813766c20 100644 --- a/guide/src/SUMMARY.md +++ b/guide/src/SUMMARY.md @@ -1,6 +1,6 @@ # Summary -# Hermes v1.7.4 +# Hermes v1.10.3 --- - [Introduction](./index.md) @@ -28,12 +28,13 @@ - [Start relaying](./tutorials/production/start-relaying.md) - [Configuration](./documentation/configuration/index.md) + - [CometBFT Compatibility modes](./documentation/configuration/comet-compat-mode.md) - [Configure Hermes](./documentation/configuration/configure-hermes.md) - [Description of the parameters](./documentation/configuration/description.md) + - [Dynamic gas fees](./documentation/configuration/dynamic-gas-fees.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) @@ -52,6 +53,7 @@ - [Cross Stack Misconfiguration](./advanced/troubleshooting/cross-comp-config.md) - [Genesis restart without IBC upgrade proposal](./advanced/troubleshooting/genesis-restart.md) - [Handling Clock Drift](./advanced/troubleshooting/clock-drift.md) + - [Gas Errors](./advanced/troubleshooting/gas-errors.md) - [Commands Reference](./documentation/commands/index.md) - [Global options and JSON output](./documentation/commands/global.md) diff --git a/guide/src/advanced/troubleshooting/gas-errors.md b/guide/src/advanced/troubleshooting/gas-errors.md new file mode 100644 index 0000000000..220e0f8d0d --- /dev/null +++ b/guide/src/advanced/troubleshooting/gas-errors.md @@ -0,0 +1,48 @@ +# Gas errors + +This section will expand on the out of gas error which can happen when simulating or sending Txs. The related configurations are: + +```toml +default_gas = 100000 +max_gas = 4000000 +gas_multiplier = 1.1 +``` + +Before sending a transaction, Hermes will retrieve an estimation of the gas required with the simulation capability of the chain. After retrieving the gas amount from the simulation, the `gas_multiplier` will be applied since the simulation might be slightly lower than the required amount of gas. +Since the `max_gas` is applied after the gas_multiplier, it can happen that the value `simulated_gas * gas_multiplier > max_gas`, in which case the `max_gas` value is used. + +Note that if the simulation fails with a recoverable error, Hermes will use the configured `default_gas`. + +## Simulating Tx + +The first instance where an error can happen is when the tracasction simulation succeeds but the gas amount retrieved exceeds the configured `max_gas`, Hermes will throw an unrecoverable error: + +``` + gas estimate from simulated Tx exceeds the maximum configured +``` + +This can be fixed by increasing the configured `max_gas`. + +## Broadcasting Tx + +> __NOTE__: This issue will only arise with Cosmos chains as this is a Cosmos SDK error. + +The second instance when an error can happen is when sending the transaction. If the gas included for the transaction is not enough Hermes will throw an error: + +``` +out of gas in location: ; gasWanted: , gasUsed: : out of gas +``` + +Two cases need to be verified in order to fix this issue. + +### Caused by max_gas + +If simulated gas is close to the `max_gas` configured, after multiplying the value with the `gas_multiplier`, it can be the case that the `max_gas` is used instead. And since the simulated gas might be slightly lower than the required gas, this can cause an out of gas error. +This can be fixed by increasing the configured `max_gas`. + +### Caused by default_gas + +When the transaction simulation fails with a recoverable error, the `default_gas` will be used. If the `default_gas` is too low an out of gas error will be thrown. This can be fixed by increasing the `default_gas`. +But there can also be a case similar to the one explained in the previous section [Caused by max_gas](./gas-errors.md#caused-by-max_gas). + +If the `default_gas` is too close to the `max_gas`, the `max_gas` will be used instead of `default_gas * gas_multiplier`, causing an out of gas error. In this situation both `max_gas` and `default_gas` need to be verified, and one or both need to be increased. \ No newline at end of file diff --git a/guide/src/documentation/commands/config.md b/guide/src/documentation/commands/config.md index 793a1a523c..40e6ab85a2 100644 --- a/guide/src/documentation/commands/config.md +++ b/guide/src/documentation/commands/config.md @@ -27,7 +27,7 @@ __Example__ Use `config auto` to generate a configuration file that is able to relay between `cosmoshub` and `osmosis`. This command assumes the existence of a key file for `cosmoshub-4` and `osmosis-1` in `$HOME/.hermes/keys`. ``` -{{#template ../../templates/commands/hermes/config/auto_1.md PATH=~/example_config.toml CHAIN_NAME:OPTIONAL_KEY_NAME=cosmoshub osmosis}} +{{#template ../../templates/commands/hermes/config/auto_1.md PATH=~/example_config.toml CHAIN1_NAME:OPTIONAL_KEY_NAME=cosmoshub osmosis}} 2022-08-16T17:27:26.966233Z INFO ThreadId(01) using default configuration from '~/.hermes/config.toml' 2022-08-16T17:27:27.800213Z INFO ThreadId(01) cosmoshub-4: uses key "key_cosmoshub" @@ -38,7 +38,7 @@ SUCCESS Config file written successfully at '~/example_config.toml' It is also possible to manually specify a key name for any chain. ``` -{{#template ../../templates/commands/hermes/config/auto_1.md PATH=~/example_config.toml CHAIN_NAME:OPTIONAL_KEY_NAME=cosmoshub:random_key osmosis}} +{{#template ../../templates/commands/hermes/config/auto_1.md PATH=~/example_config.toml CHAIN1_NAME:OPTIONAL_KEY_NAME=cosmoshub:random_key osmosis}} 2022-08-16T17:29:56.902499Z INFO ThreadId(01) using default configuration from '~/.hermes/config.toml' 2022-08-16T17:29:57.288874Z INFO ThreadId(01) cosmoshub-4: uses key "random_key" diff --git a/guide/src/documentation/configuration/configure-hermes.md b/guide/src/documentation/configuration/configure-hermes.md index cec76e4fb7..c63fab7200 100644 --- a/guide/src/documentation/configuration/configure-hermes.md +++ b/guide/src/documentation/configuration/configure-hermes.md @@ -27,7 +27,7 @@ hermes [--config CONFIG_FILE] COMMAND The simplest way to configure Hermes for a given chain is by running the command ```shell -{{#template ../../templates/commands/hermes/config/auto_1.md PATH=~//config.toml CHAIN_NAME:OPTIONAL_KEY_NAME= }} +{{#template ../../templates/commands/hermes/config/auto_1.md PATH=~//config.toml CHAIN1_NAME:OPTIONAL_KEY_NAME= }} ``` This will generate a `config.toml` file for some specified chains. Note, however, that the configuration is generated by pulling the chain data from the Cosmos [chain registry][chain-registry]. The specified chain(s) must exist in the registry for the command to work. Check out [this][config-auto-reference] section of the Hermes commands reference to find more information on the `config auto` command. diff --git a/guide/src/documentation/configuration/dynamic-gas-fees.md b/guide/src/documentation/configuration/dynamic-gas-fees.md new file mode 100644 index 0000000000..81762167ff --- /dev/null +++ b/guide/src/documentation/configuration/dynamic-gas-fees.md @@ -0,0 +1,21 @@ +# Dynamic Gas Fees + +Some chains use a dynamic gas price system instead of static gas price. By configuring the `dynamic_gas_price` for those chains, Hermes will query the gas price and apply the configured multiplier instead of using the configured static gas price: + +```toml +... +[.dynamic_gas_price] +enabled = true +multiplier = 1.1 +max = 0.6 +... +``` + +## Notes + +* If the query fails, Hermes will fallback to the configured static gas price. +* If the queried gas price is higher than the maximum configured gas price, Hermes will use the maximum gas price but this might cause the relaying of the packet to fail due to insufficient fees. + +## Monitoring + +As this feature can be delicate to handle, multiple metrics have been added in order to monitor the dynamic gas fees. Please consult the [Dynamic Gas Metrics](../telemetry/operators.md#dynamic-gas-fees) section for detailed information on these metrics. \ No newline at end of file diff --git a/guide/src/documentation/configuration/packet-clearing.md b/guide/src/documentation/configuration/packet-clearing.md index b12dd4d27d..805c061b31 100644 --- a/guide/src/documentation/configuration/packet-clearing.md +++ b/guide/src/documentation/configuration/packet-clearing.md @@ -2,7 +2,7 @@ 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. +There are four different configurations to determine when Hermes will clear packets. ## Global configurations @@ -32,7 +32,7 @@ This configuration defines how often Hermes will verify if there are pending pac ## Chain specific configuration -The third configuration is specific for each chain. +The third and fourth configurations are specific for each chain. ### 3. `clear_interval` @@ -42,4 +42,17 @@ The third configuration is specific for each chain. 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 +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. + +### 4. `excluded_sequences` + +```toml +[[chains]] +... +excluded_sequences = [ + ['channel-0', [1, 2, 3]], + ['channel-1', [4, 5, 6]] +] +``` + +It is possible to specify which packet sequences should be ignored when clearing packets for specific channels. This can be used when there are stuck packets which need to be handled in a specific way, but it is still required to clear the other stuck packets. This configuration will only filter packet when clearing, standard relaying will not filter the sequences configured in `excluded_sequences`. \ No newline at end of file diff --git a/guide/src/documentation/telemetry/operators.md b/guide/src/documentation/telemetry/operators.md index 96204843c4..dd0d137d2e 100644 --- a/guide/src/documentation/telemetry/operators.md +++ b/guide/src/documentation/telemetry/operators.md @@ -142,6 +142,8 @@ If this metric is increasing, it signals that the packet queue is increasing and | `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 | +| `simulate_errors_total` | Number of errors observed by Hermes when simulating a Tx, per error type, account and whether the error is recoverable or not | `u64` Counter | Packet workers enabled | +| `filtered_packets` | Number of ICS-20 packets filtered because the memo and/or the receiver fields were exceeding the configured limits | `u64` Counter | Packet workers enabled, and `ics20_max_memo_size` and/or `ics20_max_receiver_size` enabled | Notes: - The two metrics `cleared_send_packet_count_total` and `cleared_acknowledgment_count_total` are only populated if `tx_confirmation = true`. @@ -161,4 +163,20 @@ Note that this metrics is disabled if `misbehaviour = false` in your Hermes conf | Name | Description | OpenTelemetry type | Configuration Dependencies | | ------------------- | --------------------------------------------------------------------------- | ------------------- | -------------------------- | | `ics29_fee_amounts_total` | Total amount received from ICS29 fees  | `u64` Counter  | None | -| `ics29_period_fees` | Amount of ICS29 fees rewarded over the past 7 days type | `u64` ValueRecorder | None | \ No newline at end of file +| `ics29_period_fees` | Amount of ICS29 fees rewarded over the past 7 days type | `u64` ValueRecorder | None | + +## Dynamic gas fees + +The introduction of dynamic gas fees adds additional configuration which can be delicate to handle correctly. The following metrics can help correctly configure your relayer. + +| Name | Description | OpenTelemetry type | Configuration Dependencies | +| ---------------------------------- | -------------------------------------------------------------------- | ------------------- | -------------------------- | +| `dynamic_gas_queried_fees` | The EIP-1559 base fee queried  | `u64` ValueRecorder | None | +| `dynamic_gas_queried_success_fees` | The EIP-1559 base fee successfully queried   | `u64` ValueRecorder | None | +| `dynamic_gas_paid_fees` | The EIP-1559 base fee paid  | `u64` ValueRecorder | None | + +Notes: + +- The `dynamic_gas_queried_fees` contains the gas price used after the query but before filtering by configured `max`. This means that this metric might contain the static gas price if the query failed. +- The `dynamic_gas_queried_success_fees` will only contain the gas price when the query succeeds, if this metric doesn't contain values or less values that the `dynamic_gas_queried_fees` this could indicate an issue with the endpoint used to query the fees. +- `dynamic_gas_paid_fees` will contain the price used by the relayer, the maximum value for this metric is `max`. If there are multiple values in the same bucket as the `max` it could indicate that the gas price queried is often higher than the configured `max`. \ No newline at end of file diff --git a/guide/src/index.md b/guide/src/index.md index 0b364cd9f9..329ec05641 100644 --- a/guide/src/index.md +++ b/guide/src/index.md @@ -74,7 +74,7 @@ Hermes is actively developed and maintained by [Informal Systems](https://inform - The official GitHub repository for Hermes. - [IBC GitHub repository](https://github.com/cosmos/ics) - The official repository for the Inter-blockchain protocol (IBC). - - [IBC Protocol](https://ibcprotocol.org) + - [IBC Protocol](https://www.ibcprotocol.dev) - The official IBC protocol page. ## Contact diff --git a/guide/src/quick-start/pre-requisites.md b/guide/src/quick-start/pre-requisites.md index aefafe2c18..fa430166d8 100644 --- a/guide/src/quick-start/pre-requisites.md +++ b/guide/src/quick-start/pre-requisites.md @@ -12,8 +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.71` at -the moment. To check that your tool chain is up-to-date run: +Hermes is developed and tested using the latest stable version of Rust. To check that your tool chain is up-to-date run: ```shell rustc --version diff --git a/guide/src/templates/commands/hermes/config/auto_1.md b/guide/src/templates/commands/hermes/config/auto_1.md index c7c4e932b0..e7bec76e08 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]] +[[#BINARY hermes]][[#GLOBALOPTIONS]] config auto[[#OPTIONS]] --output [[#PATH]] --chain [[#CHAIN1_NAME:OPTIONAL_KEY_NAME]] --chain [[#CHAIN2_NAME:OPTIONAL_KEY_NAME]] diff --git a/guide/src/templates/commands/hermes/tx/chan-upgrade-ack_1.md b/guide/src/templates/commands/hermes/tx/chan-upgrade-ack_1.md new file mode 100644 index 0000000000..c39115bdf9 --- /dev/null +++ b/guide/src/templates/commands/hermes/tx/chan-upgrade-ack_1.md @@ -0,0 +1 @@ +[[#BINARY hermes]][[#GLOBALOPTIONS]] tx chan-upgrade-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]] --src-channel [[#SRC_CHANNEL_ID]] --dst-channel [[#DST_CHANNEL_ID]] diff --git a/guide/src/templates/commands/hermes/tx/chan-upgrade-cancel_1.md b/guide/src/templates/commands/hermes/tx/chan-upgrade-cancel_1.md new file mode 100644 index 0000000000..5f7fc7e0e1 --- /dev/null +++ b/guide/src/templates/commands/hermes/tx/chan-upgrade-cancel_1.md @@ -0,0 +1 @@ +[[#BINARY hermes]][[#GLOBALOPTIONS]] tx chan-upgrade-cancel --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]] --dst-channel [[#DST_CHANNEL_ID]] diff --git a/guide/src/templates/commands/hermes/tx/chan-upgrade-confirm_1.md b/guide/src/templates/commands/hermes/tx/chan-upgrade-confirm_1.md new file mode 100644 index 0000000000..4b9434eb3b --- /dev/null +++ b/guide/src/templates/commands/hermes/tx/chan-upgrade-confirm_1.md @@ -0,0 +1 @@ +[[#BINARY hermes]][[#GLOBALOPTIONS]] tx chan-upgrade-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]] --src-channel [[#SRC_CHANNEL_ID]] --dst-channel [[#DST_CHANNEL_ID]] diff --git a/guide/src/templates/commands/hermes/tx/chan-upgrade-open_1.md b/guide/src/templates/commands/hermes/tx/chan-upgrade-open_1.md new file mode 100644 index 0000000000..43fe8ee75a --- /dev/null +++ b/guide/src/templates/commands/hermes/tx/chan-upgrade-open_1.md @@ -0,0 +1 @@ +[[#BINARY hermes]][[#GLOBALOPTIONS]] tx chan-upgrade-open --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]] --dst-channel [[#DST_CHANNEL_ID]] diff --git a/guide/src/templates/commands/hermes/tx/chan-upgrade-timeout_1.md b/guide/src/templates/commands/hermes/tx/chan-upgrade-timeout_1.md new file mode 100644 index 0000000000..2ccf8b5d99 --- /dev/null +++ b/guide/src/templates/commands/hermes/tx/chan-upgrade-timeout_1.md @@ -0,0 +1 @@ +[[#BINARY hermes]][[#GLOBALOPTIONS]] tx chan-upgrade-timeout --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]] --dst-channel [[#DST_CHANNEL_ID]] diff --git a/guide/src/templates/commands/hermes/tx/chan-upgrade-try_1.md b/guide/src/templates/commands/hermes/tx/chan-upgrade-try_1.md new file mode 100644 index 0000000000..a2f0e74436 --- /dev/null +++ b/guide/src/templates/commands/hermes/tx/chan-upgrade-try_1.md @@ -0,0 +1 @@ +[[#BINARY hermes]][[#GLOBALOPTIONS]] tx chan-upgrade-try --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]] --dst-channel [[#DST_CHANNEL_ID]] diff --git a/guide/src/templates/help_templates/config/auto.md b/guide/src/templates/help_templates/config/auto.md index b1b9e1773e..1c0f7bc7af 100644 --- a/guide/src/templates/help_templates/config/auto.md +++ b/guide/src/templates/help_templates/config/auto.md @@ -2,7 +2,7 @@ DESCRIPTION: Automatically generate a config.toml for the specified chain(s) USAGE: - hermes config auto [OPTIONS] --output --chains + hermes config auto [OPTIONS] --output --chain --chain OPTIONS: --commit Commit hash from which the chain configs will be generated. If @@ -11,7 +11,9 @@ OPTIONS: REQUIRED: --chains ... - Names of the chains to include in the config. Every chain must be in the chain registry. + Names of the chains to include in the configuration, together with an optional key name. + Either repeat this argument for every chain or pass a space-separated list of chains. + Every chain must be found in the chain registry. --output Path to the configuration file diff --git a/guide/src/templates/help_templates/health-check.md b/guide/src/templates/help_templates/health-check.md index 75638bd5ee..ad6b954fa2 100644 --- a/guide/src/templates/help_templates/health-check.md +++ b/guide/src/templates/help_templates/health-check.md @@ -1,5 +1,5 @@ DESCRIPTION: -Performs a health check of all chains in the the config +Performs a health check of all chains in the config USAGE: hermes health-check diff --git a/guide/src/templates/help_templates/help.md b/guide/src/templates/help_templates/help.md index 8a0011bd76..0f0038d664 100644 --- a/guide/src/templates/help_templates/help.md +++ b/guide/src/templates/help_templates/help.md @@ -19,7 +19,7 @@ SUBCOMMANDS: 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 + health-check Performs a health check of all chains in 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 diff --git a/guide/src/templates/help_templates/tx.md b/guide/src/templates/help_templates/tx.md index 02590775c2..9d83c50de5 100644 --- a/guide/src/templates/help_templates/tx.md +++ b/guide/src/templates/help_templates/tx.md @@ -8,18 +8,24 @@ OPTIONS: -h, --help Print help information SUBCOMMANDS: - chan-close-confirm Confirm the closing of a channel (ChannelCloseConfirm) - chan-close-init Initiate the closing of a channel (ChannelCloseInit) - chan-open-ack Relay acknowledgment of a channel attempt (ChannelOpenAck) - chan-open-confirm Confirm opening of a channel (ChannelOpenConfirm) - chan-open-init Initialize a channel (ChannelOpenInit) - chan-open-try Relay the channel attempt (ChannelOpenTry) - conn-ack Relay acknowledgment of a connection attempt (ConnectionOpenAck) - conn-confirm Confirm opening of a connection (ConnectionOpenConfirm) - conn-init Initialize a connection (ConnectionOpenInit) - conn-try Relay the connection attempt (ConnectionOpenTry) - ft-transfer Send a fungible token transfer test transaction (ICS20 MsgTransfer) - help Print this message or the help of the given subcommand(s) - packet-ack Relay acknowledgment packets - packet-recv Relay receive or timeout packets - upgrade-chain Send an IBC upgrade plan + chan-close-confirm Confirm the closing of a channel (ChannelCloseConfirm) + chan-close-init Initiate the closing of a channel (ChannelCloseInit) + chan-open-ack Relay acknowledgment of a channel attempt (ChannelOpenAck) + chan-open-confirm Confirm opening of a channel (ChannelOpenConfirm) + chan-open-init Initialize a channel (ChannelOpenInit) + chan-open-try Relay the channel attempt (ChannelOpenTry) + chan-upgrade-ack Relay the channel upgrade attempt (ChannelUpgradeAck) + chan-upgrade-cancel Relay the channel upgrade cancellation (ChannelUpgradeCancel) + chan-upgrade-confirm Relay the channel upgrade attempt (ChannelUpgradeConfirm) + chan-upgrade-open Relay the channel upgrade attempt (ChannelUpgradeOpen) + chan-upgrade-timeout Relay the channel upgrade timeout (ChannelUpgradeTimeout) + chan-upgrade-try Relay the channel upgrade attempt (ChannelUpgradeTry) + conn-ack Relay acknowledgment of a connection attempt (ConnectionOpenAck) + conn-confirm Confirm opening of a connection (ConnectionOpenConfirm) + conn-init Initialize a connection (ConnectionOpenInit) + conn-try Relay the connection attempt (ConnectionOpenTry) + ft-transfer Send a fungible token transfer test transaction (ICS20 MsgTransfer) + help Print this message or the help of the given subcommand(s) + packet-ack Relay acknowledgment packets + packet-recv Relay receive or timeout packets + upgrade-chain Send an IBC upgrade plan diff --git a/guide/src/templates/help_templates/tx/chan-upgrade-ack.md b/guide/src/templates/help_templates/tx/chan-upgrade-ack.md new file mode 100644 index 0000000000..6c30bfa913 --- /dev/null +++ b/guide/src/templates/help_templates/tx/chan-upgrade-ack.md @@ -0,0 +1,30 @@ +DESCRIPTION: +Relay the channel upgrade attempt (ChannelUpgradeAck) + +USAGE: + hermes tx chan-upgrade-ack --dst-chain --src-chain --dst-connection --dst-port --src-port --src-channel --dst-channel + +OPTIONS: + -h, --help Print help information + +REQUIRED: + --dst-chain + Identifier of the destination chain + + --dst-channel + Identifier of the destination channel (optional) [aliases: dst-chan] + + --dst-connection + Identifier of the destination connection [aliases: dst-conn] + + --dst-port + Identifier of the destination port + + --src-chain + Identifier of the source chain + + --src-channel + Identifier of the source channel (required) [aliases: src-chan] + + --src-port + Identifier of the source port diff --git a/guide/src/templates/help_templates/tx/chan-upgrade-cancel.md b/guide/src/templates/help_templates/tx/chan-upgrade-cancel.md new file mode 100644 index 0000000000..ceb38a5f12 --- /dev/null +++ b/guide/src/templates/help_templates/tx/chan-upgrade-cancel.md @@ -0,0 +1,30 @@ +DESCRIPTION: +Relay the channel upgrade cancellation (ChannelUpgradeCancel) + +USAGE: + hermes tx chan-upgrade-cancel --dst-chain --src-chain --dst-connection --dst-port --src-port --src-channel --dst-channel + +OPTIONS: + -h, --help Print help information + +REQUIRED: + --dst-chain + Identifier of the destination chain + + --dst-channel + Identifier of the destination channel (optional) [aliases: dst-chan] + + --dst-connection + Identifier of the destination connection [aliases: dst-conn] + + --dst-port + Identifier of the destination port + + --src-chain + Identifier of the source chain + + --src-channel + Identifier of the source channel (required) [aliases: src-chan] + + --src-port + Identifier of the source port diff --git a/guide/src/templates/help_templates/tx/chan-upgrade-confirm.md b/guide/src/templates/help_templates/tx/chan-upgrade-confirm.md new file mode 100644 index 0000000000..e13588c59d --- /dev/null +++ b/guide/src/templates/help_templates/tx/chan-upgrade-confirm.md @@ -0,0 +1,30 @@ +DESCRIPTION: +Relay the channel upgrade attempt (ChannelUpgradeConfirm) + +USAGE: + hermes tx chan-upgrade-confirm --dst-chain --src-chain --dst-connection --dst-port --src-port --src-channel --dst-channel + +OPTIONS: + -h, --help Print help information + +REQUIRED: + --dst-chain + Identifier of the destination chain + + --dst-channel + Identifier of the destination channel (optional) [aliases: dst-chan] + + --dst-connection + Identifier of the destination connection [aliases: dst-conn] + + --dst-port + Identifier of the destination port + + --src-chain + Identifier of the source chain + + --src-channel + Identifier of the source channel (required) [aliases: src-chan] + + --src-port + Identifier of the source port diff --git a/guide/src/templates/help_templates/tx/chan-upgrade-open.md b/guide/src/templates/help_templates/tx/chan-upgrade-open.md new file mode 100644 index 0000000000..fb878cd41d --- /dev/null +++ b/guide/src/templates/help_templates/tx/chan-upgrade-open.md @@ -0,0 +1,30 @@ +DESCRIPTION: +Relay the channel upgrade attempt (ChannelUpgradeOpen) + +USAGE: + hermes tx chan-upgrade-open --dst-chain --src-chain --dst-connection --dst-port --src-port --src-channel --dst-channel + +OPTIONS: + -h, --help Print help information + +REQUIRED: + --dst-chain + Identifier of the destination chain + + --dst-channel + Identifier of the destination channel (optional) [aliases: dst-chan] + + --dst-connection + Identifier of the destination connection [aliases: dst-conn] + + --dst-port + Identifier of the destination port + + --src-chain + Identifier of the source chain + + --src-channel + Identifier of the source channel (required) [aliases: src-chan] + + --src-port + Identifier of the source port diff --git a/guide/src/templates/help_templates/tx/chan-upgrade-timeout.md b/guide/src/templates/help_templates/tx/chan-upgrade-timeout.md new file mode 100644 index 0000000000..3d783f1a3a --- /dev/null +++ b/guide/src/templates/help_templates/tx/chan-upgrade-timeout.md @@ -0,0 +1,30 @@ +DESCRIPTION: +Relay the channel upgrade timeout (ChannelUpgradeTimeout) + +USAGE: + hermes tx chan-upgrade-timeout --dst-chain --src-chain --dst-connection --dst-port --src-port --src-channel --dst-channel + +OPTIONS: + -h, --help Print help information + +REQUIRED: + --dst-chain + Identifier of the destination chain + + --dst-channel + Identifier of the destination channel (optional) [aliases: dst-chan] + + --dst-connection + Identifier of the destination connection [aliases: dst-conn] + + --dst-port + Identifier of the destination port + + --src-chain + Identifier of the source chain + + --src-channel + Identifier of the source channel (required) [aliases: src-chan] + + --src-port + Identifier of the source port diff --git a/guide/src/templates/help_templates/tx/chan-upgrade-try.md b/guide/src/templates/help_templates/tx/chan-upgrade-try.md new file mode 100644 index 0000000000..6a00fbc211 --- /dev/null +++ b/guide/src/templates/help_templates/tx/chan-upgrade-try.md @@ -0,0 +1,30 @@ +DESCRIPTION: +Relay the channel upgrade attempt (ChannelUpgradeTry) + +USAGE: + hermes tx chan-upgrade-try --dst-chain --src-chain --dst-connection --dst-port --src-port --src-channel --dst-channel + +OPTIONS: + -h, --help Print help information + +REQUIRED: + --dst-chain + Identifier of the destination chain + + --dst-channel + Identifier of the destination channel (optional) [aliases: dst-chan] + + --dst-connection + Identifier of the destination connection [aliases: dst-conn] + + --dst-port + Identifier of the destination port + + --src-chain + Identifier of the source chain + + --src-channel + Identifier of the source channel (required) [aliases: src-chan] + + --src-port + Identifier of the source port diff --git a/guide/src/templates/hermes-version.md b/guide/src/templates/hermes-version.md index a9bbd79f98..d9c8fd4074 100644 --- a/guide/src/templates/hermes-version.md +++ b/guide/src/templates/hermes-version.md @@ -1 +1 @@ -v1.7.4 +v1.10.3 diff --git a/guide/src/tutorials/production/setup-hermes.md b/guide/src/tutorials/production/setup-hermes.md index 81c4509061..7f666b0372 100644 --- a/guide/src/tutorials/production/setup-hermes.md +++ b/guide/src/tutorials/production/setup-hermes.md @@ -36,7 +36,7 @@ Then, you need to create a configuration file for Hermes (more details in the [d The command `hermes config auto` provides a way to automatically generate a configuration file for chains in the [chain-registry](https://github.com/cosmos/chain-registry): ```shell -{{#template ../../templates/commands/hermes/config/auto_1.md PATH=$HOME/.hermes/config.toml CHAIN_NAME:OPTIONAL_KEY_NAME=cosmoshub:keyhub osmosis:keyosmosis}} +{{#template ../../templates/commands/hermes/config/auto_1.md PATH=$HOME/.hermes/config.toml CHAIN1_NAME:OPTIONAL_KEY_NAME=cosmoshub:keyhub osmosis:keyosmosis}} ``` >__NOTE__: This command also automatically finds IBC paths and generates packet filters from the [_IBC](https://github.com/cosmos/chain-registry/tree/master/_IBC) folder in the chain-registry. diff --git a/scripts/auto_gen_templates.sh b/scripts/auto_gen_templates.sh index aaf0c605d8..bbf0650a09 100755 --- a/scripts/auto_gen_templates.sh +++ b/scripts/auto_gen_templates.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # This script is used to generate the templates for the guide SCRIPT_NAME="$0" diff --git a/scripts/one-chain b/scripts/one-chain index 47bf41365e..7ad2e0dfe2 100755 --- a/scripts/one-chain +++ b/scripts/one-chain @@ -89,25 +89,25 @@ sleep 1 # Add samoleans to user USER=$($BINARY --home $CHAIN_DIR/$CHAIN_ID keys --keyring-backend="test" show user -a) -$BINARY --home $CHAIN_DIR/$CHAIN_ID add-genesis-account $USER $USER_COINS &> /dev/null +$BINARY --home $CHAIN_DIR/$CHAIN_ID genesis add-genesis-account $USER $USER_COINS &> /dev/null sleep 1 # Add samoleans to user2 USER2=$($BINARY --home $CHAIN_DIR/$CHAIN_ID keys --keyring-backend="test" show user2 -a) -$BINARY --home $CHAIN_DIR/$CHAIN_ID add-genesis-account $USER2 $USER_COINS &> /dev/null +$BINARY --home $CHAIN_DIR/$CHAIN_ID genesis add-genesis-account $USER2 $USER_COINS &> /dev/null sleep 1 # Add stake to validator VALIDATOR=$($BINARY --home $CHAIN_DIR/$CHAIN_ID keys --keyring-backend="test" show validator -a) -$BINARY --home $CHAIN_DIR/$CHAIN_ID add-genesis-account $VALIDATOR $STAKE &> /dev/null +$BINARY --home $CHAIN_DIR/$CHAIN_ID genesis add-genesis-account $VALIDATOR $STAKE &> /dev/null sleep 1 # Stake everything -$BINARY --home $CHAIN_DIR/$CHAIN_ID gentx validator --keyring-backend="test" --chain-id $CHAIN_ID $STAKE &> /dev/null +$BINARY --home $CHAIN_DIR/$CHAIN_ID genesis gentx validator --keyring-backend="test" --chain-id $CHAIN_ID $STAKE &> /dev/null sleep 1 -$BINARY --home $CHAIN_DIR/$CHAIN_ID collect-gentxs &> /dev/null +$BINARY --home $CHAIN_DIR/$CHAIN_ID genesis collect-gentxs &> /dev/null sleep 1 # Check platform @@ -121,23 +121,25 @@ fi echo "Change settings in config.toml file..." if [ $platform = 'linux' ]; then sed -i 's#"172800s"#"200s"#g' $CHAIN_DIR/$CHAIN_ID/config/genesis.json - sed -i 's#"tcp://127.0.0.1:26657"#"tcp://0.0.0.0:'"$RPC_PORT"'"#g' $CHAIN_DIR/$CHAIN_ID/config/config.toml + sed -i 's#"tcp://0.0.0.0:26657"#"tcp://0.0.0.0:'"$RPC_PORT"'"#g' $CHAIN_DIR/$CHAIN_ID/config/config.toml sed -i 's#"tcp://0.0.0.0:26656"#"tcp://0.0.0.0:'"$P2P_PORT"'"#g' $CHAIN_DIR/$CHAIN_ID/config/config.toml sed -i 's#"localhost:6060"#"localhost:'"$PROF_PORT"'"#g' $CHAIN_DIR/$CHAIN_ID/config/config.toml sed -i 's/timeout_commit = "5s"/timeout_commit = "1s"/g' $CHAIN_DIR/$CHAIN_ID/config/config.toml sed -i 's/timeout_propose = "3s"/timeout_propose = "1s"/g' $CHAIN_DIR/$CHAIN_ID/config/config.toml sed -i 's/index_all_keys = false/index_all_keys = true/g' $CHAIN_DIR/$CHAIN_ID/config/config.toml sed -i '/^\[grpc-web\]/,/^\[/s/^enable = true/enable = false/' $CHAIN_DIR/$CHAIN_ID/config/app.toml + sed -i 's/minimum-gas-prices = ""/minimum-gas-prices = "0stake"/g' $CHAIN_DIR/$CHAIN_ID/config/app.toml # sed -i '' 's#index-events = \[\]#index-events = \["message.action","send_packet.packet_src_channel","send_packet.packet_sequence"\]#g' $CHAIN_DIR/$CHAIN_ID/config/app.toml else sed -i '' 's#"172800s"#"200s"#g' $CHAIN_DIR/$CHAIN_ID/config/genesis.json - sed -i '' 's#"tcp://127.0.0.1:26657"#"tcp://0.0.0.0:'"$RPC_PORT"'"#g' $CHAIN_DIR/$CHAIN_ID/config/config.toml + sed -i '' 's#"tcp://0.0.0.0:26657"#"tcp://0.0.0.0:'"$RPC_PORT"'"#g' $CHAIN_DIR/$CHAIN_ID/config/config.toml sed -i '' 's#"tcp://0.0.0.0:26656"#"tcp://0.0.0.0:'"$P2P_PORT"'"#g' $CHAIN_DIR/$CHAIN_ID/config/config.toml sed -i '' 's#"localhost:6060"#"localhost:'"$PROF_PORT"'"#g' $CHAIN_DIR/$CHAIN_ID/config/config.toml sed -i '' 's/timeout_commit = "5s"/timeout_commit = "1s"/g' $CHAIN_DIR/$CHAIN_ID/config/config.toml sed -i '' 's/timeout_propose = "3s"/timeout_propose = "1s"/g' $CHAIN_DIR/$CHAIN_ID/config/config.toml sed -i '' 's/index_all_keys = false/index_all_keys = true/g' $CHAIN_DIR/$CHAIN_ID/config/config.toml sed -i '' '/^\[grpc-web\]/,/^\[/s/^enable = true/enable = false/' $CHAIN_DIR/$CHAIN_ID/config/app.toml + sed -i '' 's/minimum-gas-prices = ""/minimum-gas-prices = "0stake"/g' $CHAIN_DIR/$CHAIN_ID/config/app.toml # sed -i '' 's/min-retain-blocks = 0/min-retain-blocks = 100/g' $CHAIN_DIR/$CHAIN_ID/config/app.toml # sed -i '' 's#index-events = \[\]#index-events = \["message.action","send_packet.packet_src_channel","send_packet.packet_sequence"\]#g' $CHAIN_DIR/$CHAIN_ID/config/app.toml # sed -i '' 's/error/debug/g' $CHAIN_DIR/$CHAIN_ID/config/config.toml @@ -146,7 +148,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 info > $CHAIN_DIR/$CHAIN_ID.log 2>&1 & +$BINARY --home $CHAIN_DIR/$CHAIN_ID start --pruning=nothing --rpc.laddr="tcp://0.0.0.0:$RPC_PORT" --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 735f88c9a3..645b211df2 100644 --- a/tools/check-guide/Cargo.lock +++ b/tools/check-guide/Cargo.lock @@ -23,7 +23,7 @@ dependencies = [ "termcolor", "toml 0.5.11", "tracing", - "tracing-log", + "tracing-log 0.1.4", "tracing-subscriber", "wait-timeout", ] @@ -58,18 +58,18 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "1.1.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "ammonia" -version = "3.3.0" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e6d1c7838db705c9b756557ee27c384ce695a1c51a6fe528784cb1c6840170" +checksum = "1ab99eae5ee58501ab236beb6f20f6ca39be615267b014899c89b2f0bc18a459" dependencies = [ "html5ever", "maplit", @@ -95,63 +95,76 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.4" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.1" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "arc-swap" -version = "1.6.0" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" + +[[package]] +name = "arrayref" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "async-stream" @@ -172,33 +185,34 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.65", ] [[package]] name = "async-trait" -version = "0.1.73" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.65", ] [[package]] name = "async-tungstenite" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e9efbe14612da0a19fb983059a0b621e9cf6225d7018ecab4f9988215540dc" +checksum = "3609af4bbf701ddaf1f6bb4e6257dff4ff8932327d0e685d3f653724c258b1ac" dependencies = [ "futures-io", "futures-util", "log", "pin-project-lite", - "rustls-native-certs", + "rustls-native-certs 0.7.0", + "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.25.0", "tungstenite", ] @@ -215,9 +229,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "axum" @@ -230,7 +244,7 @@ dependencies = [ "bitflags 1.3.2", "bytes", "futures-util", - "http", + "http 0.2.12", "http-body", "hyper", "itoa", @@ -260,7 +274,7 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http", + "http 0.2.12", "http-body", "mime", "rustversion", @@ -270,13 +284,13 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", - "cfg-if 1.0.0", + "cfg-if", "libc", "miniz_oxide", "object", @@ -291,15 +305,15 @@ checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" [[package]] name = "base64" -version = "0.13.1" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64" -version = "0.21.4" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" @@ -313,6 +327,12 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" +[[package]] +name = "bech32" +version = "0.10.0-beta" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98f7eed2b2781a6f0b5c903471d48e15f56fb4e1165df8a9a2337fd1a59d45ea" + [[package]] name = "bit-set" version = "0.5.3" @@ -330,31 +350,36 @@ checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" [[package]] name = "bitcoin" -version = "0.30.1" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e99ff7289b20a7385f66a0feda78af2fc119d28fb56aea8886a9cd0a4abdd75" +checksum = "6c85783c2fe40083ea54a33aa2f0ba58831d90fcd190f5bdc47e74e84d2a96ae" dependencies = [ - "bech32", - "bitcoin-private", + "bech32 0.10.0-beta", + "bitcoin-internals", "bitcoin_hashes", + "hex-conservative", "hex_lit", "secp256k1", "serde", ] [[package]] -name = "bitcoin-private" -version = "0.1.0" +name = "bitcoin-internals" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73290177011694f38ec25e165d0387ab7ea749a4b81cd4c80dae5988229f7a57" +checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" +dependencies = [ + "serde", +] [[package]] name = "bitcoin_hashes" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d7066118b13d4b20b23645932dfb3a81ce7e29f95726c2036fa33cd7b092501" +checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" dependencies = [ - "bitcoin-private", + "bitcoin-internals", + "hex-conservative", "serde", ] @@ -366,9 +391,31 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "blake3" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", +] [[package]] name = "block-buffer" @@ -390,29 +437,29 @@ dependencies = [ [[package]] name = "bs58" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" dependencies = [ "tinyvec", ] [[package]] name = "bstr" -version = "1.6.2" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2f7349907b712260e64b0afe2f84692af14a454be26187d9df565c7f69266a" +checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" dependencies = [ "memchr", - "regex-automata 0.3.9", + "regex-automata 0.4.6", "serde", ] [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byte-unit" @@ -424,32 +471,17 @@ dependencies = [ "utf8-width", ] -[[package]] -name = "bytecount" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad152d03a2c813c80bb94fedbf3a3f02b28f793e39e7c214c8a0bcc196343de7" - [[package]] name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" -dependencies = [ - "serde", -] +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] -name = "camino" -version = "1.1.6" +name = "bytes" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" dependencies = [ "serde", ] @@ -460,42 +492,11 @@ version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e9e01327e6c86e92ec72b1c798d4a94810f147209bbe3ffab6a86954937a6f" -[[package]] -name = "cargo-platform" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo_metadata" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" -dependencies = [ - "camino", - "cargo-platform", - "semver", - "serde", - "serde_json", -] - [[package]] name = "cc" -version = "1.0.83" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" [[package]] name = "cfg-if" @@ -517,14 +518,14 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "num-traits", - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] [[package]] @@ -539,30 +540,30 @@ dependencies = [ "clap_lex 0.2.4", "indexmap 1.9.3", "once_cell", - "strsim", + "strsim 0.10.0", "termcolor", "textwrap", ] [[package]] name = "clap" -version = "4.4.6" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.4.6" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ "anstream", "anstyle", - "clap_lex 0.5.1", - "strsim", + "clap_lex 0.7.0", + "strsim 0.11.1", "terminal_size", ] @@ -577,11 +578,11 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.4.3" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ae8ba90b9d8b007efe66e55e48fb936272f5ca00349b5b0e89877520d35ea7" +checksum = "dd79504325bf38b10165b02e89b4347300f855f273c4cb30c4a3209e6583275e" dependencies = [ - "clap 4.4.6", + "clap 4.5.4", ] [[package]] @@ -608,15 +609,15 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "color-eyre" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204" +checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5" dependencies = [ "backtrace", "color-spantrace", @@ -629,9 +630,9 @@ dependencies = [ [[package]] name = "color-spantrace" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba75b3d9449ecdccb27ecbc479fdc0b87fa2dd43d2f8298f9bf0e59aacc8dce" +checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" dependencies = [ "once_cell", "owo-colors", @@ -641,28 +642,34 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "console" -version = "0.15.7" +version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" dependencies = [ "encode_unicode", "lazy_static", "libc", "unicode-width", - "windows-sys 0.45.0", + "windows-sys 0.52.0", ] [[package]] name = "const-oid" -version = "0.9.5" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "constant_time_eq" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" [[package]] name = "contracts" @@ -677,9 +684,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -687,71 +694,52 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] [[package]] name = "crossbeam-channel" -version = "0.4.4" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ - "crossbeam-utils 0.7.2", - "maybe-uninit", + "crossbeam-utils", ] [[package]] -name = "crossbeam-channel" -version = "0.5.8" +name = "crossbeam-deque" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils 0.8.16", + "crossbeam-epoch", + "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if 1.0.0", - "crossbeam-utils 0.8.16", - "memoffset", - "scopeguard", + "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.7.2" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" -dependencies = [ - "autocfg", - "cfg-if 0.1.10", - "lazy_static", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if 1.0.0", -] +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crunchy" @@ -761,9 +749,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" -version = "0.5.3" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "740fe28e594155f10cfc383984cbefd529d7396050557148f79cb0f621204124" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", "rand_core", @@ -783,11 +771,11 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.1" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest 0.10.7", @@ -800,13 +788,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.37", + "syn 2.0.65", ] [[package]] @@ -828,8 +816,8 @@ version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ - "cfg-if 1.0.0", - "hashbrown 0.14.1", + "cfg-if", + "hashbrown 0.14.5", "lock_api", "once_cell", "parking_lot_core", @@ -837,15 +825,26 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.4.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" + +[[package]] +name = "dbus" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b" +dependencies = [ + "libc", + "libdbus-sys", + "winapi", +] [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "zeroize", @@ -853,9 +852,12 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.8" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] [[package]] name = "derivation-path" @@ -876,13 +878,14 @@ dependencies = [ [[package]] name = "dialoguer" -version = "0.10.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59c6f2989294b9a498d3ad5491a79c6deb604617378e1cdc4bfc1c1361fe2f87" +checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de" dependencies = [ "console", "shell-words", "tempfile", + "thiserror", "zeroize", ] @@ -913,7 +916,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "dirs-sys-next", ] @@ -930,9 +933,9 @@ dependencies = [ [[package]] name = "ecdsa" -version = "0.16.8" +version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", "digest 0.10.7", @@ -944,9 +947,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", @@ -968,15 +971,16 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7277392b266383ef8396db7fdeb1e77b6c52fed775f5df15bb24f35b72156980" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek", "ed25519", "rand_core", "serde", "sha2 0.10.8", + "subtle", "zeroize", ] @@ -994,9 +998,9 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "elasticlunr-rs" @@ -1012,9 +1016,9 @@ dependencies = [ [[package]] name = "elliptic-curve" -version = "0.13.6" +version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97ca172ae9dc9f9b779a6e3a65d308f2af74e5b8c921299075bdb4a0370e914" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "crypto-bigint", @@ -1037,11 +1041,21 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", +] + +[[package]] +name = "env_filter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +dependencies = [ + "log", + "regex", ] [[package]] @@ -1059,15 +1073,15 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.10.0" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" dependencies = [ + "anstream", + "anstyle", + "env_filter", "humantime", - "is-terminal", "log", - "regex", - "termcolor", ] [[package]] @@ -1078,39 +1092,19 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ - "cc", "libc", -] - -[[package]] -name = "error-chain" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" -dependencies = [ - "version_check", + "windows-sys 0.52.0", ] [[package]] name = "eyre" -version = "0.6.8" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" dependencies = [ "indenter", "once_cell", @@ -1128,9 +1122,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "ff" @@ -1144,20 +1138,20 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.1" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0870c84016d4b481be5c9f323c24f65e31e901ae618f0e80f4308fb00de1d2d" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "filetime" -version = "0.2.22" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", - "redox_syscall 0.3.5", - "windows-sys 0.48.0", + "redox_syscall 0.4.1", + "windows-sys 0.52.0", ] [[package]] @@ -1175,7 +1169,6 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c606d892c9de11507fa0dcffc116434f94e105d0bbdc4e405b61519464c49d7b" dependencies = [ - "anyhow", "eyre", "paste", ] @@ -1188,18 +1181,21 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] [[package]] name = "fs-err" -version = "2.9.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" +checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41" +dependencies = [ + "autocfg", +] [[package]] name = "fsevent-sys" @@ -1222,9 +1218,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -1237,9 +1233,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -1247,15 +1243,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -1264,38 +1260,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.65", ] [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -1322,11 +1318,11 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "libc", "wasi", @@ -1335,27 +1331,21 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" - -[[package]] -name = "glob" -version = "0.3.1" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "globset" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" +checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" dependencies = [ "aho-corasick", "bstr", - "fnv", "log", - "regex", + "regex-automata 0.4.6", + "regex-syntax 0.8.3", ] [[package]] @@ -1369,39 +1359,19 @@ dependencies = [ "subtle", ] -[[package]] -name = "gumdrop" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bc700f989d2f6f0248546222d9b4258f5b02a171a431f8285a81c08142629e3" -dependencies = [ - "gumdrop_derive", -] - -[[package]] -name = "gumdrop_derive" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "729f9bd3449d77e7831a18abfb7ba2f99ee813dfd15b8c2167c9a54ba20aa99d" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "h2" -version = "0.3.21" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", "futures-core", "futures-sink", "futures-util", - "http", - "indexmap 1.9.3", + "http 0.2.12", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", @@ -1410,15 +1380,15 @@ dependencies = [ [[package]] name = "half" -version = "1.8.2" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" [[package]] name = "handlebars" -version = "4.4.0" +version = "5.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39b3bc2a8f715298032cf5087e58573809374b08160aa7d750582bdb82d2683" +checksum = "d08485b96a0e6393e9e4d1b8d48cf74ad6c063cd905eb33f42c1ce3f0377539b" dependencies = [ "log", "pest", @@ -1436,9 +1406,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.1" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hdpath" @@ -1455,10 +1425,10 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" dependencies = [ - "base64 0.21.4", + "base64 0.21.7", "bytes", "headers-core", - "http", + "http 0.2.12", "httpdate", "mime", "sha1", @@ -1470,7 +1440,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" dependencies = [ - "http", + "http 0.2.12", ] [[package]] @@ -1490,9 +1460,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -1500,6 +1470,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex-conservative" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212ab92002354b4819390025006c897e8140934349e8635c9b077f47b4dcbd20" + [[package]] name = "hex_lit" version = "0.1.1" @@ -1517,23 +1493,34 @@ dependencies = [ [[package]] name = "html5ever" -version = "0.26.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" +checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" dependencies = [ "log", "mac", "markup5ever", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.65", ] [[package]] name = "http" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", "fnv", @@ -1542,12 +1529,12 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.12", "pin-project-lite", ] @@ -1581,22 +1568,22 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", "h2", - "http", + "http 0.2.12", "http-body", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "socket2", "tokio", "tower-service", "tracing", @@ -1605,16 +1592,16 @@ 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", + "http 0.2.12", "hyper", - "rustls", + "rustls 0.21.12", "tokio", - "tokio-rustls", + "tokio-rustls 0.24.1", ] [[package]] @@ -1631,16 +1618,16 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -1654,15 +1641,15 @@ dependencies = [ [[package]] name = "ibc-chain-registry" -version = "0.26.1" +version = "0.27.2" dependencies = [ "async-trait", "flex-error", "futures", - "http", + "http 0.2.12", "ibc-proto", "ibc-relayer-types", - "itertools 0.10.5", + "itertools", "reqwest", "serde", "serde_json", @@ -1673,14 +1660,15 @@ dependencies = [ [[package]] name = "ibc-proto" -version = "0.39.0" +version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b5aca9ca863246a2b358e0a1845759780860673e54c0a76335faccc504981c" +checksum = "66080040d5a4800d52966d55b055400f86b79c34b854b935bef03c87aacda62a" dependencies = [ - "base64 0.21.4", + "base64 0.22.1", "bytes", "flex-error", "ics23", + "informalsystems-pbjson", "prost", "serde", "subtle-encoding", @@ -1690,16 +1678,16 @@ dependencies = [ [[package]] name = "ibc-relayer" -version = "0.26.1" +version = "0.27.2" dependencies = [ "anyhow", "async-stream", - "bech32", + "bech32 0.9.1", "bitcoin", "bs58", "byte-unit", "bytes", - "crossbeam-channel 0.5.8", + "crossbeam-channel", "digest 0.10.7", "dirs-next", "ed25519", @@ -1710,19 +1698,20 @@ dependencies = [ "generic-array", "hdpath", "hex", - "http", + "http 0.2.12", "humantime", "humantime-serde", "ibc-proto", "ibc-relayer-types", "ibc-telemetry", - "itertools 0.10.5", + "itertools", "moka", "num-bigint", "num-rational", "once_cell", "prost", "regex", + "reqwest", "retry", "ripemd", "secp256k1", @@ -1745,37 +1734,37 @@ dependencies = [ "tiny-keccak", "tokio", "tokio-stream", - "toml 0.7.8", + "toml 0.8.13", "tonic", "tracing", "tracing-subscriber", - "uuid 1.4.1", + "uuid", ] [[package]] name = "ibc-relayer-cli" -version = "1.7.1" +version = "1.8.2" dependencies = [ "abscissa_core", "clap 3.2.25", "clap_complete 3.2.5", "color-eyre", "console", - "crossbeam-channel 0.5.8", + "crossbeam-channel", "dialoguer", "dirs-next", "eyre", "flex-error", "futures", "hdpath", - "http", + "http 0.2.12", "humantime", "ibc-chain-registry", "ibc-relayer", "ibc-relayer-rest", "ibc-relayer-types", "ibc-telemetry", - "itertools 0.10.5", + "itertools", "oneline-eyre", "regex", "serde", @@ -1793,10 +1782,10 @@ dependencies = [ [[package]] name = "ibc-relayer-rest" -version = "0.26.1" +version = "0.27.2" dependencies = [ "axum", - "crossbeam-channel 0.5.8", + "crossbeam-channel", "ibc-relayer", "ibc-relayer-types", "serde", @@ -1806,14 +1795,14 @@ dependencies = [ [[package]] name = "ibc-relayer-types" -version = "0.26.1" +version = "0.27.2" dependencies = [ "bytes", "derive_more", "flex-error", "ibc-proto", "ics23", - "itertools 0.10.5", + "itertools", "num-rational", "primitive-types", "prost", @@ -1825,14 +1814,14 @@ dependencies = [ "tendermint", "tendermint-light-client-verifier", "tendermint-proto", - "tendermint-testgen", "time", + "tracing", "uint", ] [[package]] name = "ibc-telemetry" -version = "0.26.1" +version = "0.27.2" dependencies = [ "axum", "dashmap", @@ -1851,11 +1840,13 @@ dependencies = [ [[package]] name = "ics23" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "661e2d6f79952a65bc92b1c81f639ebd37228dae6ff412a5aba7d474bdc4b957" +checksum = "dc3b8be84e7285c73b88effdc3294b552277d6b0ec728ee016c861b7b9a2c19c" dependencies = [ "anyhow", + "blake2", + "blake3", "bytes", "hex", "informalsystems-pbjson", @@ -1874,9 +1865,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -1884,17 +1875,16 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" +checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" dependencies = [ + "crossbeam-deque", "globset", - "lazy_static", "log", "memchr", - "regex", + "regex-automata 0.4.6", "same-file", - "thread_local", "walkdir", "winapi-util", ] @@ -1926,21 +1916,21 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.2" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.1", + "hashbrown 0.14.5", ] [[package]] name = "informalsystems-pbjson" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4eecd90f87bea412eac91c6ef94f6b1e390128290898cbe14f2b926787ae1fb" +checksum = "9aa4a0980c8379295100d70854354e78df2ee1c6ca0f96ffe89afeb3140e3a3d" dependencies = [ - "base64 0.13.1", + "base64 0.21.7", "serde", ] @@ -1966,61 +1956,47 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" - -[[package]] -name = "is-terminal" -version = "0.4.9" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" -dependencies = [ - "hermit-abi 0.3.3", - "rustix", - "windows-sys 0.48.0", -] +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] -name = "itertools" -version = "0.10.5" +name = "is_terminal_polyfill" +version = "1.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" [[package]] name = "itertools" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] [[package]] name = "k256" -version = "0.13.1" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "ecdsa", "elliptic-curve", "sha2 0.10.8", @@ -2028,9 +2004,9 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ "cpufeatures", ] @@ -2063,21 +2039,41 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.148" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "libdbus-sys" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72" +dependencies = [ + "cc", + "pkg-config", +] + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.5.0", + "libc", +] [[package]] name = "linux-raw-sys" -version = "0.4.8" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -2085,9 +2081,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "mac" @@ -2095,15 +2091,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" -[[package]] -name = "mach2" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d0d1830bcd151a6fc4aea1369af235b36c1528fe976b8ff678683c9995eade8" -dependencies = [ - "libc", -] - [[package]] name = "maplit" version = "1.0.2" @@ -2112,9 +2099,9 @@ checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] name = "markup5ever" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" +checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" dependencies = [ "log", "phf", @@ -2139,25 +2126,19 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" - [[package]] name = "mdbook" -version = "0.4.35" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c3f88addd34930bc5f01b9dc19f780447e51c92bf2536e3ded058018271775d" +checksum = "b45a38e19bd200220ef07c892b0157ad3d2365e5b5a267ca01ad12182491eea5" dependencies = [ "ammonia", "anyhow", "chrono", - "clap 4.4.6", - "clap_complete 4.4.3", + "clap 4.5.4", + "clap_complete 4.5.2", "elasticlunr-rs", - "env_logger 0.10.0", + "env_logger 0.11.3", "futures-util", "handlebars", "ignore", @@ -2167,6 +2148,7 @@ dependencies = [ "notify-debouncer-mini", "once_cell", "opener", + "pathdiff", "pulldown-cmark", "regex", "serde", @@ -2176,14 +2158,15 @@ dependencies = [ "tokio", "toml 0.5.11", "topological-sort", + "walkdir", "warp", ] [[package]] name = "mdbook-template" -version = "1.1.0" +version = "1.1.1+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "920f69694a682c1100d64ca342278fc289d7d89b905a60c39ca39e0ea04ce0f1" +checksum = "24ababe45effcc8453d4dc68de0d699d6858399b6f20ecfaf616a1ca2e0c6aa3" dependencies = [ "anyhow", "clap 3.2.25", @@ -2198,18 +2181,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" - -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "mime" @@ -2229,18 +2203,18 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", @@ -2250,38 +2224,37 @@ dependencies = [ [[package]] name = "moka" -version = "0.12.1" +version = "0.12.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8017ec3548ffe7d4cef7ac0e12b044c01164a74c0f3119420faeaf13490ad8b" +checksum = "9e0d88686dc561d743b40de8269b26eaf0dc58781bde087b0984646602021d08" dependencies = [ - "crossbeam-channel 0.5.8", + "crossbeam-channel", "crossbeam-epoch", - "crossbeam-utils 0.8.16", + "crossbeam-utils", "once_cell", "parking_lot", "quanta", "rustc_version", - "skeptic", "smallvec", "tagptr", "thiserror", "triomphe", - "uuid 1.4.1", + "uuid", ] [[package]] name = "new_debug_unreachable" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "normpath" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec60c60a693226186f5d6edf073232bfb6464ed97eb22cf3b01c1e8198fd97f5" +checksum = "5831952a9476f2fed74b77d74182fa5ddc4d21c72ec45a333b250e3ed0272804" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2290,8 +2263,8 @@ version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags 2.4.0", - "crossbeam-channel 0.5.8", + "bitflags 2.5.0", + "crossbeam-channel", "filetime", "fsevent-sys", "inotify", @@ -2305,11 +2278,12 @@ dependencies = [ [[package]] name = "notify-debouncer-mini" -version = "0.3.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e55ee272914f4563a2f8b8553eb6811f3c0caea81c756346bad15b7e3ef969f0" +checksum = "5d40b221972a1fc5ef4d858a2f671fb34c75983eb385463dff3780eeff6a9d43" dependencies = [ - "crossbeam-channel 0.5.8", + "crossbeam-channel", + "log", "notify", ] @@ -2325,44 +2299,36 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" dependencies = [ - "autocfg", "num-integer", "num-traits", "serde", ] [[package]] -name = "num-derive" -version = "0.3.3" +name = "num-conv" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-rational" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", "num-bigint", "num-integer", "num-traits", @@ -2371,9 +2337,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -2384,24 +2350,24 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.3", + "hermit-abi 0.3.9", "libc", ] [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "oneline-eyre" @@ -2414,19 +2380,20 @@ dependencies = [ [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "opener" -version = "0.6.1" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c62dcb6174f9cb326eac248f07e955d5d559c272730b6c03e396b443b562788" +checksum = "f8df34be653210fbe9ffaff41d3b92721c56ce82dfee58ee684f9afb5e3a90c0" dependencies = [ "bstr", + "dbus", "normpath", - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -2479,7 +2446,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b3a2a91fdbfdd4d212c0dcc2ab540de2c2bcbbd90be17de7a7daf8822d010c1" dependencies = [ "async-trait", - "crossbeam-channel 0.5.8", + "crossbeam-channel", "dashmap", "fnv", "futures-channel", @@ -2494,9 +2461,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" @@ -2512,9 +2479,9 @@ checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" dependencies = [ "lock_api", "parking_lot_core", @@ -2522,22 +2489,28 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall 0.5.1", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pathdiff" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" [[package]] name = "pbkdf2" @@ -2550,9 +2523,9 @@ dependencies = [ [[package]] name = "peg" -version = "0.7.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07c0b841ea54f523f7aa556956fbd293bcbe06f2e67d2eb732b7278aaf1d166a" +checksum = "8a625d12ad770914cbf7eff6f9314c3ef803bfe364a1b20bc36ddf56673e71e5" dependencies = [ "peg-macros", "peg-runtime", @@ -2560,9 +2533,9 @@ dependencies = [ [[package]] name = "peg-macros" -version = "0.7.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aa52829b8decbef693af90202711348ab001456803ba2a98eb4ec8fb70844c" +checksum = "f241d42067ed3ab6a4fece1db720838e1418f36d868585a27931f95d6bc03582" dependencies = [ "peg-runtime", "proc-macro2", @@ -2571,21 +2544,21 @@ dependencies = [ [[package]] name = "peg-runtime" -version = "0.7.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c719dcf55f09a3a7e764c6649ab594c18a177e3599c467983cdf644bfc0a4088" +checksum = "e3aeb8f54c078314c2065ee649a7241f46b9d8e418e1a9581ba0546657d7aa3a" [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.4" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c022f1e7b65d6a24c0dbbd5fb344c66881bc01f3e5ae74a1c8100f2f985d98a4" +checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" dependencies = [ "memchr", "thiserror", @@ -2594,9 +2567,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.4" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35513f630d46400a977c4cb58f78e1bfbe01434316e60c37d27b9ad6139c66d8" +checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" dependencies = [ "pest", "pest_generator", @@ -2604,22 +2577,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.4" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc9fc1b9e7057baba189b5c626e2d6f40681ae5b6eb064dc7c7834101ec8123a" +checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.65", ] [[package]] name = "pest_meta" -version = "2.7.4" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df74e9e7ec4053ceb980e7c0c8bd3594e977fde1af91daba9c928e8e8c6708d" +checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" dependencies = [ "once_cell", "pest", @@ -2628,21 +2601,21 @@ dependencies = [ [[package]] name = "phf" -version = "0.10.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ - "phf_shared", + "phf_shared 0.11.2", ] [[package]] name = "phf_codegen" -version = "0.10.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.11.2", + "phf_shared 0.11.2", ] [[package]] @@ -2651,7 +2624,17 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" dependencies = [ - "phf_shared", + "phf_shared 0.10.0", + "rand", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared 0.11.2", "rand", ] @@ -2664,31 +2647,40 @@ dependencies = [ "siphasher", ] +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.65", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -2706,11 +2698,23 @@ dependencies = [ "spki", ] +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + [[package]] name = "platforms" -version = "3.1.2" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" + +[[package]] +name = "powerfmt" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4503fa043bf02cee09a9582e9554b4c6403b2ef55e4612e96561d294419429f8" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" @@ -2726,9 +2730,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[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", @@ -2761,20 +2765,20 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.67" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" dependencies = [ "unicode-ident", ] [[package]] name = "prometheus" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c" +checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "fnv", "lazy_static", "memchr", @@ -2785,9 +2789,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.12.1" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fdd22f3b9c31b53c060df4a0613a1c7f062d4115a2b984dd15b1858f7e340d" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", "prost-derive", @@ -2795,22 +2799,22 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.12.1" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "265baba7fabd416cf5078179f7d2cbeca4ce7a9041111900675ea7c4cb8a4c32" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools", "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.65", ] [[package]] name = "prost-types" -version = "0.12.1" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e081b29f63d83a4bc75cfc9f3fe424f9156cf92d8a4f0c9407cce9a1b67327cf" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" dependencies = [ "prost", ] @@ -2823,24 +2827,30 @@ checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" [[package]] name = "pulldown-cmark" -version = "0.9.3" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" +checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", "memchr", + "pulldown-cmark-escape", "unicase", ] +[[package]] +name = "pulldown-cmark-escape" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd348ff538bc9caeda7ee8cad2d1d48236a1f443c1fa3913c6a02fe0043b1dd3" + [[package]] name = "quanta" -version = "0.11.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17e662a7a8291a865152364c20c7abc5e60486ab2001e8ec10b24862de0b9ab" +checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5" dependencies = [ - "crossbeam-utils 0.8.16", + "crossbeam-utils", "libc", - "mach2", "once_cell", "raw-cpuid", "wasi", @@ -2850,9 +2860,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -2889,52 +2899,52 @@ dependencies = [ [[package]] name = "raw-cpuid" -version = "10.7.0" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332" +checksum = "e29830cbb1290e404f24c73af91c5d8d631ce7e128691e9477556b540cd01ecd" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", ] [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", ] [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ "getrandom", - "redox_syscall 0.2.16", + "libredox", "thiserror", ] [[package]] name = "regex" -version = "1.9.6" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.3.9", - "regex-syntax 0.7.5", + "regex-automata 0.4.6", + "regex-syntax 0.8.3", ] [[package]] @@ -2948,13 +2958,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.9" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.5", + "regex-syntax 0.8.3", ] [[package]] @@ -2965,23 +2975,23 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.5" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "reqwest" -version = "0.11.22" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ - "base64 0.21.4", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", "futures-util", "h2", - "http", + "http 0.2.12", "http-body", "hyper", "hyper-rustls", @@ -2992,21 +3002,21 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls", - "rustls-native-certs", - "rustls-pemfile", + "rustls 0.21.12", + "rustls-native-certs 0.6.3", + "rustls-pemfile 1.0.4", "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", "system-configuration", "tokio", - "tokio-rustls", + "tokio-rustls 0.24.1", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots", "winreg", ] @@ -3028,17 +3038,17 @@ dependencies = [ [[package]] name = "ring" -version = "0.16.20" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", + "getrandom", "libc", - "once_cell", "spin", "untrusted", - "web-sys", - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -3052,9 +3062,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" @@ -3073,29 +3083,43 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.17" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f25469e9ae0f3d0047ca8b93fc56843f38e6774f0914a107ff8b41be8be8e0b7" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "rustls" -version = "0.21.7" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring", - "rustls-webpki", + "rustls-webpki 0.101.7", "sct", ] +[[package]] +name = "rustls" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" +dependencies = [ + "log", + "ring", + "rustls-pki-types", + "rustls-webpki 0.102.4", + "subtle", + "zeroize", +] + [[package]] name = "rustls-native-certs" version = "0.6.3" @@ -3103,41 +3127,81 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ "openssl-probe", - "rustls-pemfile", + "rustls-pemfile 1.0.4", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-native-certs" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" +dependencies = [ + "openssl-probe", + "rustls-pemfile 2.1.2", + "rustls-pki-types", "schannel", "security-framework", ] [[package]] name = "rustls-pemfile" -version = "1.0.3" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +dependencies = [ + "base64 0.22.1", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "base64 0.21.4", + "ring", + "untrusted", ] [[package]] name = "rustls-webpki" -version = "0.101.6" +version = "0.102.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe" +checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" dependencies = [ "ring", + "rustls-pki-types", "untrusted", ] [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -3150,11 +3214,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -3171,9 +3235,9 @@ 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", @@ -3195,9 +3259,9 @@ dependencies = [ [[package]] name = "secp256k1" -version = "0.27.0" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" dependencies = [ "bitcoin_hashes", "rand", @@ -3207,9 +3271,9 @@ dependencies = [ [[package]] name = "secp256k1-sys" -version = "0.8.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" +checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" dependencies = [ "cc", ] @@ -3226,11 +3290,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", "core-foundation", "core-foundation-sys", "libc", @@ -3239,9 +3303,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" dependencies = [ "core-foundation-sys", "libc", @@ -3249,27 +3313,27 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.19" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.188" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" dependencies = [ "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.12" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" +checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" dependencies = [ "serde", ] @@ -3286,20 +3350,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.65", ] [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", "ryu", @@ -3308,9 +3372,9 @@ dependencies = [ [[package]] name = "serde_path_to_error" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4beec8bce849d58d06238cb50db2e1c417cfeafa4c63f692b15c82b7c80f8335" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" dependencies = [ "itoa", "serde", @@ -3318,20 +3382,20 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.16" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.65", ] [[package]] name = "serde_spanned" -version = "0.6.3" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" dependencies = [ "serde", ] @@ -3354,7 +3418,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.10.7", ] @@ -3366,7 +3430,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ "block-buffer 0.9.0", - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.9.0", "opaque-debug", @@ -3378,7 +3442,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.10.7", ] @@ -3410,9 +3474,9 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "shlex" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook" @@ -3426,50 +3490,29 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] [[package]] name = "signature" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest 0.10.7", "rand_core", ] -[[package]] -name = "simple-error" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc47a29ce97772ca5c927f75bac34866b16d64e07f330c3248e2d7226623901b" - [[package]] name = "siphasher" version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" -[[package]] -name = "skeptic" -version = "0.13.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d23b015676c90a0f01c197bfdc786c20342c73a0afdda9025adb0bc42940a8" -dependencies = [ - "bytecount", - "cargo_metadata", - "error-chain", - "glob", - "pulldown-cmark", - "tempfile", - "walkdir", -] - [[package]] name = "slab" version = "0.4.9" @@ -3481,41 +3524,31 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" - -[[package]] -name = "socket2" -version = "0.4.9" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" -dependencies = [ - "libc", - "winapi", -] +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.4" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.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" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", "der", @@ -3536,7 +3569,7 @@ dependencies = [ "new_debug_unreachable", "once_cell", "parking_lot", - "phf_shared", + "phf_shared 0.10.0", "precomputed-hash", "serde", ] @@ -3547,8 +3580,8 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.10.0", + "phf_shared 0.10.0", "proc-macro2", "quote", ] @@ -3559,6 +3592,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "strum" version = "0.25.0" @@ -3570,15 +3609,15 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.25.2" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8d03b598d3d0fff69bf533ee3ef19b8eeb342729596df84bcc7e1f96ec4059" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" dependencies = [ "heck", "proc-macro2", "quote", "rustversion", - "syn 2.0.37", + "syn 2.0.65", ] [[package]] @@ -3615,9 +3654,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.37" +version = "2.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106" dependencies = [ "proc-macro2", "quote", @@ -3671,22 +3710,21 @@ checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" [[package]] name = "tempfile" -version = "3.8.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "fastrand", - "redox_syscall 0.3.5", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "tendermint" -version = "0.34.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc2294fa667c8b548ee27a9ba59115472d0a09c2ba255771092a7f1dcf03a789" +checksum = "8b50aae6ec24c3429149ad59b5b8d3374d7804d4c7d6125ceb97cb53907fb68d" dependencies = [ "bytes", "digest 0.10.7", @@ -3715,26 +3753,26 @@ dependencies = [ [[package]] name = "tendermint-config" -version = "0.34.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a25dbe8b953e80f3d61789fbdb83bf9ad6c0ef16df5ca6546f49912542cc137" +checksum = "e07b383dc8780ebbec04cfb603f3fdaba6ea6663d8dd861425b1ffa7761fe90d" dependencies = [ "flex-error", "serde", "serde_json", "tendermint", - "toml 0.5.11", + "toml 0.8.13", "url", ] [[package]] name = "tendermint-light-client" -version = "0.34.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94aecbdccbc4b557649b2d1b1a4bfc27ec85205e00fb8020fce044245a4c9e3f" +checksum = "331544139bbcf353acb5f56e733093d8e4bf2522cda0491b4bba7039ef0b944e" dependencies = [ "contracts", - "crossbeam-channel 0.4.4", + "crossbeam-channel", "derive_more", "flex-error", "futures", @@ -3754,12 +3792,11 @@ dependencies = [ [[package]] name = "tendermint-light-client-detector" -version = "0.34.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea83654b03e3ddc6782c9704a3fefd4d0671bd6c5e3f09d29e31fcb45e75636c" +checksum = "73d0ffaf614bd2db605c4762e3a31a536b73cd45488fa5bace050135ca348f28" dependencies = [ - "contracts", - "crossbeam-channel 0.4.4", + "crossbeam-channel", "derive_more", "flex-error", "futures", @@ -3778,9 +3815,9 @@ dependencies = [ [[package]] name = "tendermint-light-client-verifier" -version = "0.34.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74994da9de4b1144837a367ca2c60c650f5526a7c1a54760a3020959b522e474" +checksum = "4216e487165e5dbd7af79952eaa0d5f06c5bde861eb76c690acd7f2d2a19395c" dependencies = [ "derive_more", "flex-error", @@ -3791,14 +3828,12 @@ dependencies = [ [[package]] name = "tendermint-proto" -version = "0.34.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc728a4f9e891d71adf66af6ecaece146f9c7a11312288a3107b3e1d6979aaf" +checksum = "46f193d04afde6592c20fd70788a10b8cb3823091c07456db70d8a93f5fb99c1" dependencies = [ "bytes", "flex-error", - "num-derive", - "num-traits", "prost", "prost-types", "serde", @@ -3809,9 +3844,9 @@ dependencies = [ [[package]] name = "tendermint-rpc" -version = "0.34.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbf0a4753b46a190f367337e0163d0b552a2674a6bac54e74f9f2cdcde2969b" +checksum = "21e3c231a3632cab53f92ad4161c730c468c08cfe4f0aa5a6735b53b390aecbd" dependencies = [ "async-trait", "async-tungstenite", @@ -3821,6 +3856,7 @@ dependencies = [ "getrandom", "peg", "pin-project", + "rand", "reqwest", "semver", "serde", @@ -3836,26 +3872,10 @@ dependencies = [ "tokio", "tracing", "url", - "uuid 0.8.2", + "uuid", "walkdir", ] -[[package]] -name = "tendermint-testgen" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19d4f02b7e38ce790da973fdc9edc71a0e35340ac57737bf278c8379037c1f5" -dependencies = [ - "ed25519-consensus", - "gumdrop", - "serde", - "serde_json", - "simple-error", - "tempfile", - "tendermint", - "time", -] - [[package]] name = "tendril" version = "0.4.3" @@ -3869,9 +3889,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.3.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] @@ -3888,47 +3908,49 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "thiserror" -version = "1.0.49" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.49" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.65", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "once_cell", ] [[package]] name = "time" -version = "0.3.29" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "426f806f4089c493dcac0d24c29c01e2c38baf8e30f1b716ee37e83d200b18fe" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", + "num-conv", + "powerfmt", "serde", "time-core", "time-macros", @@ -3942,10 +3964,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] @@ -3994,9 +4017,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.32.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", @@ -4006,7 +4029,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.4", + "socket2", "tokio-macros", "windows-sys 0.48.0", ] @@ -4023,13 +4046,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.37", + "syn 2.0.65", ] [[package]] @@ -4038,15 +4061,26 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls", + "rustls 0.21.12", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +dependencies = [ + "rustls 0.22.4", + "rustls-pki-types", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", "pin-project-lite", @@ -4055,9 +4089,9 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" +checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" dependencies = [ "futures-util", "log", @@ -4067,16 +4101,15 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.9" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] @@ -4090,9 +4123,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.8" +version = "0.8.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +checksum = "a4e43f8cc456c9704c851ae29c67e17ef65d2c30017c17a9765b89c382dc8bba" dependencies = [ "serde", "serde_spanned", @@ -4102,20 +4135,20 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.15" +version = "0.22.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +checksum = "c127785850e8c20836d49732ae6abfa47616e60bf9d9f57c43c250361a9db96c" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", @@ -4124,28 +4157,28 @@ dependencies = [ [[package]] name = "tonic" -version = "0.10.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d560933a0de61cf715926b9cac824d4c883c2c43142f787595e48280c40a1d0e" +checksum = "76c4eb7a4e9ef9d4763600161f12f5070b92a578e1b634db88a6887844c91a13" dependencies = [ "async-stream", "async-trait", "axum", - "base64 0.21.4", + "base64 0.21.7", "bytes", "h2", - "http", + "http 0.2.12", "http-body", "hyper", "hyper-timeout", "percent-encoding", "pin-project", "prost", - "rustls", - "rustls-native-certs", - "rustls-pemfile", + "rustls-native-certs 0.7.0", + "rustls-pemfile 2.1.2", + "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.25.0", "tokio-stream", "tower", "tower-layer", @@ -4193,11 +4226,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", @@ -4206,20 +4238,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.37", + "syn 2.0.65", ] [[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", @@ -4237,12 +4269,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 = [ + "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 = [ - "lazy_static", "log", + "once_cell", "tracing-core", ] @@ -4258,9 +4301,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", @@ -4273,36 +4316,37 @@ dependencies = [ "thread_local", "tracing", "tracing-core", - "tracing-log", + "tracing-log 0.2.0", "tracing-serde", ] [[package]] name = "triomphe" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee8098afad3fb0c54a9007aab6804558410503ad676d4633f9c2559a00ac0f" +checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3" [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tungstenite" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" dependencies = [ "byteorder", "bytes", "data-encoding", - "http", + "http 1.1.0", "httparse", "log", "rand", - "rustls", + "rustls 0.22.4", + "rustls-pki-types", "sha1", "thiserror", "url", @@ -4344,9 +4388,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -4356,18 +4400,18 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" [[package]] name = "unicode-xid" @@ -4377,15 +4421,15 @@ checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[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" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -4406,9 +4450,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "utf8-width" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5190c9442dcdaf0ddd50f37420417d219ae5261bbf5db120d0f9bab996c9cba1" +checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" [[package]] name = "utf8parse" @@ -4418,15 +4462,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" - -[[package]] -name = "uuid" -version = "1.4.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" dependencies = [ "getrandom", ] @@ -4454,9 +4492,9 @@ dependencies = [ [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -4473,28 +4511,26 @@ dependencies = [ [[package]] name = "warp" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e92e22e03ff1230c03a1a8ee37d2f89cd489e2e541b7550d6afad96faed169" +checksum = "4378d202ff965b011c64817db11d5829506d3404edeadb61f190d111da3f231c" dependencies = [ "bytes", "futures-channel", "futures-util", "headers", - "http", + "http 0.2.12", "hyper", "log", "mime", "mime_guess", "percent-encoding", "pin-project", - "rustls-pemfile", "scoped-tls", "serde", "serde_json", "serde_urlencoded", "tokio", - "tokio-stream", "tokio-tungstenite", "tokio-util", "tower-service", @@ -4509,36 +4545,36 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.65", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "wasm-bindgen", "web-sys", @@ -4546,9 +4582,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4556,39 +4592,33 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.65", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", ] -[[package]] -name = "webpki-roots" -version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" - [[package]] name = "winapi" version = "0.3.9" @@ -4607,11 +4637,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -4621,21 +4651,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" +name = "windows-core" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.42.2", + "windows-targets 0.52.5", ] [[package]] @@ -4648,18 +4669,12 @@ dependencies = [ ] [[package]] -name = "windows-targets" -version = "0.42.2" +name = "windows-sys" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets 0.52.5", ] [[package]] @@ -4678,10 +4693,20 @@ dependencies = [ ] [[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" +name = "windows-targets" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] [[package]] name = "windows_aarch64_gnullvm" @@ -4690,10 +4715,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" +name = "windows_aarch64_gnullvm" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -4702,10 +4727,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] -name = "windows_i686_gnu" -version = "0.42.2" +name = "windows_aarch64_msvc" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -4714,10 +4739,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] -name = "windows_i686_msvc" -version = "0.42.2" +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -4726,10 +4757,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" +name = "windows_i686_msvc" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -4738,10 +4769,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" +name = "windows_x86_64_gnu" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -4750,10 +4781,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" +name = "windows_x86_64_gnullvm" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -4761,11 +4792,17 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + [[package]] name = "winnow" -version = "0.5.15" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc" +checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d" dependencies = [ "memchr", ] @@ -4776,15 +4813,15 @@ version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "windows-sys 0.48.0", ] [[package]] name = "zeroize" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" dependencies = [ "zeroize_derive", ] @@ -4797,5 +4834,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.65", ] diff --git a/tools/check-guide/Cargo.toml b/tools/check-guide/Cargo.toml index a69316ec10..e5a77be25f 100644 --- a/tools/check-guide/Cargo.toml +++ b/tools/check-guide/Cargo.toml @@ -1,11 +1,9 @@ [package] -name = "check-guide" +name = "check-guide" version = "0.1.0" edition = "2021" publish = false -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] ibc-relayer-cli = { path = "../../crates/relayer-cli" } clap = "3.2" @@ -13,4 +11,3 @@ 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 3b2327aff1..8d896cdab1 100644 --- a/tools/integration-test/Cargo.toml +++ b/tools/integration-test/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "ibc-integration-test" -version = "0.26.4" +version = "0.29.3" edition = "2021" -rust-version = "1.71" +rust-version = "1.76.0" license = "Apache-2.0" readme = "README.md" keywords = ["blockchain", "consensus", "cosmos", "ibc", "tendermint"] @@ -13,51 +13,44 @@ description = "Integration tests for Hermes" publish = false [dependencies] -ibc-relayer-types = { path = "../../crates/relayer-types" } -ibc-relayer = { path = "../../crates/relayer" } -ibc-test-framework = { path = "../test-framework" } - -http = "0.2.9" -serde_json = "1" -time = "0.3" -toml = "0.8" -prost = { version = "0.12" } -tonic = { version = "0.10", features = ["tls", "tls-roots"] } -serde = "1.0.195" +ibc-relayer-types = { workspace = true } +ibc-relayer = { workspace = true } +ibc-test-framework = { workspace = true } + +byte-unit = { workspace = true, features = ["serde"] } +http = { workspace = true } +prost = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +tendermint-rpc = { workspace = true, features = ["http-client"] } +tendermint = { workspace = true } +time = { workspace = true } +toml = { workspace = true } +tonic = { workspace = true, features = ["tls", "tls-roots"] } [features] -default = [] -example = [] -manual = [] -ordered = [] -ica = [] -ics29-fee = [] -experimental = [] -mbt = [] -forward-packet = [] -ics31 = [] -clean-workers = [] -fee-grant = [] -interchain-security = [] -celestia = [] -async-icq = [] -juno = [] +default = [] +example = [] +manual = [] +ordered = [] +ica = [] +ics29-fee = [] +experimental = [] +forward-packet = [] +ics31 = [] +clean-workers = [] +fee-grant = [] +channel-upgrade = [] +interchain-security = [] +celestia = [] +async-icq = [] +juno = [] +dynamic-gas-fee = [] +new-register-interchain-account = [] +authz = [] +benchmark = [] +no-denom-trace = [] [[bin]] name = "test_setup_with_binary_channel" -doc = true - -[dev-dependencies] -tempfile = "3.6.0" - -[dependencies.tendermint] -version = "0.34.0" - -[dependencies.tendermint-rpc] -version = "0.34.0" -features = ["http-client"] - -[dependencies.byte-unit] -version = "4.0.19" -default-features = false -features = ["serde"] \ No newline at end of file +doc = true 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 66a5f4e54e..44d6cb40e4 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,16 +25,11 @@ ``` */ -use std::{ - env, - path::PathBuf, -}; - -use ibc_relayer::{ - config::ChainConfig, - keyring::Store, -}; +use ibc_relayer::config::ChainConfig; +use ibc_relayer::keyring::Store; use ibc_test_framework::prelude::*; +use std::env; +use std::path::PathBuf; struct Test { store_dir: PathBuf, @@ -42,13 +37,13 @@ struct Test { impl TestOverrides for Test { fn modify_test_config(&self, config: &mut TestConfig) { - config.chain_store_dir = self.store_dir.clone(); + config.chain_store_dir.clone_from(&self.store_dir); } fn modify_relayer_config(&self, config: &mut Config) { for chain in config.chains.iter_mut() { match chain { - ChainConfig::CosmosSdk(chain_config) | ChainConfig::Astria(chain_config) => { + 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. 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 4200ee68e8..ac938158d2 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,17 +25,12 @@ ``` */ -use std::{ - env, - path::PathBuf, -}; - -use ibc_relayer::{ - config::ChainConfig, - keyring::Store, -}; +use ibc_relayer::config::ChainConfig; +use ibc_relayer::keyring::Store; use ibc_relayer_types::core::ics04_channel::version::Version; use ibc_test_framework::prelude::*; +use std::env; +use std::path::PathBuf; struct Test { store_dir: PathBuf, @@ -43,13 +38,13 @@ struct Test { impl TestOverrides for Test { fn modify_test_config(&self, config: &mut TestConfig) { - config.chain_store_dir = self.store_dir.clone(); + config.chain_store_dir.clone_from(&self.store_dir); } fn modify_relayer_config(&self, config: &mut Config) { for chain in config.chains.iter_mut() { match chain { - ChainConfig::CosmosSdk(chain_config) | ChainConfig::Astria(chain_config) => { + 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. 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 8062f3f993..1cfcd0f921 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,16 +25,11 @@ ``` */ -use std::{ - env, - path::PathBuf, -}; - -use ibc_relayer::{ - config::ChainConfig, - keyring::Store, -}; +use ibc_relayer::config::ChainConfig; +use ibc_relayer::keyring::Store; use ibc_test_framework::prelude::*; +use std::env; +use std::path::PathBuf; struct Test { store_dir: PathBuf, @@ -42,13 +37,13 @@ struct Test { impl TestOverrides for Test { fn modify_test_config(&self, config: &mut TestConfig) { - config.chain_store_dir = self.store_dir.clone(); + config.chain_store_dir.clone_from(&self.store_dir); } fn modify_relayer_config(&self, config: &mut Config) { for chain in config.chains.iter_mut() { match chain { - ChainConfig::CosmosSdk(chain_config) | ChainConfig::Astria(chain_config) => { + 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. diff --git a/tools/integration-test/src/lib.rs b/tools/integration-test/src/lib.rs index f4b83a25c4..75d580024e 100644 --- a/tools/integration-test/src/lib.rs +++ b/tools/integration-test/src/lib.rs @@ -1,7 +1,3 @@ #[allow(clippy::too_many_arguments)] #[cfg(test)] pub mod tests; - -#[cfg(any(all(test, feature = "mbt"), doc))] -#[macro_use] -pub mod mbt; diff --git a/tools/integration-test/src/mbt/README.md b/tools/integration-test/src/mbt/README.md deleted file mode 100644 index f2c0311b28..0000000000 --- a/tools/integration-test/src/mbt/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# MBT for Hermes Integration Test - -Make sure [`apalache-mc`](https://github.com/informalsystems/apalache) is installed and setup properly. Check `apalache-mc version`. - -```bash -cargo test -p ibc-integration-test --features mbt mbt::transfer -``` diff --git a/tools/integration-test/src/mbt/handlers.rs b/tools/integration-test/src/mbt/handlers.rs index 5cd677e848..49b2128fe1 100644 --- a/tools/integration-test/src/mbt/handlers.rs +++ b/tools/integration-test/src/mbt/handlers.rs @@ -1,44 +1,22 @@ -use ibc_relayer::{ - util::task::TaskHandle, - worker::client::spawn_refresh_client, -}; +use ibc_relayer::{util::task::TaskHandle, worker::client::spawn_refresh_client}; use ibc_test_framework::{ - bootstrap::binary::{ - chain::bootstrap_foreign_client_pair, - connection::bootstrap_connection, - }, - chain::{ - ext::transfer::ChainTransferMethodsExt, - tagged::TaggedChainDriverExt, - }, + bootstrap::binary::{chain::bootstrap_foreign_client_pair, connection::bootstrap_connection}, + chain::{ext::transfer::ChainTransferMethodsExt, tagged::TaggedChainDriverExt}, ibc::denom::derive_ibc_denom, prelude::*, relayer::{ - channel::{ - assert_eventually_channel_established, - init_channel, - }, - connection::{ - assert_eventually_connection_established, - init_connection, - }, + channel::{assert_eventually_channel_established, init_channel}, + connection::{assert_eventually_connection_established, init_connection}, }, types::{ - binary::{ - client::ClientIdPair, - connection::ConnectedConnection, - }, + binary::{client::ClientIdPair, connection::ConnectedConnection}, tagged::mono::Tagged, }, }; use super::{ state::Packet, - utils::{ - get_denom, - get_wallet, - wait_for_client, - }, + utils::{get_denom, get_wallet, wait_for_client}, }; pub fn setup_chains( diff --git a/tools/integration-test/src/mbt/itf.rs b/tools/integration-test/src/mbt/itf.rs index 72cb6bcbb2..57a87aadb8 100644 --- a/tools/integration-test/src/mbt/itf.rs +++ b/tools/integration-test/src/mbt/itf.rs @@ -1,8 +1,4 @@ -use serde::{ - Deserialize, - Deserializer, - Serialize, -}; +use serde::{Deserialize, Deserializer, Serialize}; #[derive(Debug, Serialize, Deserialize)] pub struct Meta { @@ -64,10 +60,7 @@ where } mod test { - use super::{ - Map, - Set, - }; + use super::{Map, Set}; #[test] fn test_empty_set() { @@ -108,10 +101,7 @@ mod test { #[test] #[cfg(feature = "manual")] fn parse_itf() { - use super::super::{ - itf::InformalTrace, - state::State, - }; + use super::super::{itf::InformalTrace, state::State}; let itf_path = concat!( env!("CARGO_MANIFEST_DIR"), diff --git a/tools/integration-test/src/mbt/mod.rs b/tools/integration-test/src/mbt/mod.rs deleted file mode 100644 index 173f132abb..0000000000 --- a/tools/integration-test/src/mbt/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -pub mod utils; - -pub mod itf; -pub mod state; - -pub mod handlers; - -pub mod transfer; diff --git a/tools/integration-test/src/mbt/state.rs b/tools/integration-test/src/mbt/state.rs deleted file mode 100644 index e6050763c5..0000000000 --- a/tools/integration-test/src/mbt/state.rs +++ /dev/null @@ -1,91 +0,0 @@ -use serde::{ - Deserialize, - Serialize, -}; - -use super::itf::{ - Map, - Set, -}; - -pub type ChainId = u128; -pub type DenomId = ChainId; -pub type AccountId = u128; -pub type PacketId = u128; -pub type Balance = u128; - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct Packet { - pub id: PacketId, - pub from: AccountId, - pub source_chain_id: ChainId, - pub to: AccountId, - pub target_chain_id: ChainId, - pub denom: DenomId, - pub amount: Balance, -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct LocalPackets { - pub list: Map, - pub pending: Set, - pub expired: Set, - pub success: Set, -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct Chain { - pub id: ChainId, - pub bank: Map>, - pub supply: Map, - pub local_packets: LocalPackets, - pub remote_packets: Map>, - pub escrow: Map>, - pub next_packet_id: PacketId, -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(tag = "name")] -pub enum Action { - Null, - #[serde(rename_all = "camelCase")] - LocalTransfer { - chain_id: ChainId, - source: AccountId, - target: AccountId, - denom: DenomId, - amount: Balance, - }, - RestoreRelay, - InterruptRelay, - IBCTransferSendPacket { - packet: Packet, - }, - IBCTransferReceivePacket { - packet: Packet, - }, - IBCTransferAcknowledgePacket { - packet: Packet, - }, - IBCTransferTimeoutPacket { - packet: Packet, - }, -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(tag = "name")] -pub enum Outcome { - Success, - Error, -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct State { - pub chains: Map, - pub action: Action, - pub outcome: Outcome, -} diff --git a/tools/integration-test/src/mbt/transfer.rs b/tools/integration-test/src/mbt/transfer.rs index e07688d9ec..3404ef6f3e 100644 --- a/tools/integration-test/src/mbt/transfer.rs +++ b/tools/integration-test/src/mbt/transfer.rs @@ -1,34 +1,18 @@ use std::{ io::Write, - panic::{ - RefUnwindSafe, - UnwindSafe, - }, + panic::{RefUnwindSafe, UnwindSafe}, }; use ibc_relayer::config::{ - ChainConfig, - Channels as ConfigChannels, - Clients as ConfigClients, - Connections as ConfigConnections, - ModeConfig, - Packets as ConfigPackets, -}; -use ibc_test_framework::{ - prelude::*, - types::tagged::mono::Tagged, + ChainConfig, Channels as ConfigChannels, Clients as ConfigClients, + Connections as ConfigConnections, ModeConfig, Packets as ConfigPackets, }; +use ibc_test_framework::{prelude::*, types::tagged::mono::Tagged}; use super::{ itf::InformalTrace, - state::{ - Action, - State, - }, - utils::{ - get_chain, - CLIENT_EXPIRY, - }, + state::{Action, State}, + utils::{get_chain, CLIENT_EXPIRY}, }; const TEST_NAMES: &[&str] = &[ @@ -144,8 +128,7 @@ fn test_ibc_transfer() -> Result<(), Error> { #[cfg(feature = "manual")] fn test_self_connected_ibc_transfer() -> Result<(), Error> { use ibc_test_framework::framework::binary::{ - chain::run_self_connected_binary_chain_test, - channel::RunBinaryChannelTest, + chain::run_self_connected_binary_chain_test, channel::RunBinaryChannelTest, }; execute_mbt(|trace| { diff --git a/tools/integration-test/src/mbt/utils.rs b/tools/integration-test/src/mbt/utils.rs index fdd8215a82..3f638fcc12 100644 --- a/tools/integration-test/src/mbt/utils.rs +++ b/tools/integration-test/src/mbt/utils.rs @@ -1,27 +1,15 @@ -use std::{ - thread::sleep, - time::Duration, -}; +use std::{thread::sleep, time::Duration}; use ibc_relayer::chain::requests::{ - QueryPacketAcknowledgementsRequest, - QueryPacketCommitmentsRequest, - QueryUnreceivedAcksRequest, + QueryPacketAcknowledgementsRequest, QueryPacketCommitmentsRequest, QueryUnreceivedAcksRequest, QueryUnreceivedPacketsRequest, }; use ibc_relayer_types::core::ics04_channel::packet::Sequence; -use ibc_test_framework::{ - ibc::denom::Denom, - prelude::*, - types::tagged::mono::Tagged, -}; +use ibc_test_framework::{ibc::denom::Denom, prelude::*, types::tagged::mono::Tagged}; use super::{ itf::InformalTrace, - state::{ - DenomId, - State, - }, + state::{DenomId, State}, }; pub const CLIENT_EXPIRY: Duration = Duration::from_secs(15); diff --git a/tools/integration-test/src/tests/async_icq/contracts/counter.wasm b/tools/integration-test/src/tests/async_icq/contracts/counter.wasm new file mode 100644 index 0000000000..407509573e Binary files /dev/null and b/tools/integration-test/src/tests/async_icq/contracts/counter.wasm differ diff --git a/tools/integration-test/src/tests/async_icq/contracts/echo.wasm b/tools/integration-test/src/tests/async_icq/contracts/echo.wasm new file mode 100644 index 0000000000..e8a1bdeced Binary files /dev/null and b/tools/integration-test/src/tests/async_icq/contracts/echo.wasm differ diff --git a/tools/integration-test/src/tests/async_icq/simple_query.rs b/tools/integration-test/src/tests/async_icq/simple_query.rs index ad06cea3b0..493d034b1a 100644 --- a/tools/integration-test/src/tests/async_icq/simple_query.rs +++ b/tools/integration-test/src/tests/async_icq/simple_query.rs @@ -1,40 +1,42 @@ -use ibc_relayer::{ - channel::version::Version, - config::ChainConfig, +use std::env; + +use ibc_relayer::channel::version::Version; +use ibc_relayer::config::ChainConfig; +use ibc_test_framework::chain::config::{ + add_allow_message_interchainquery, set_floor_gas_price, set_max_deposit_period, + set_min_deposit_amount, set_voting_period, }; -use ibc_test_framework::{ - chain::{ - config::{ - set_max_deposit_period, - set_voting_period, - }, - ext::{ - async_icq::AsyncIcqMethodsExt, - bootstrap::ChainBootstrapMethodsExt, - }, - }, - prelude::*, - relayer::channel::{ - assert_eventually_channel_established, - init_channel_version, - }, - util::proposal_status::ProposalStatus, +use ibc_test_framework::chain::ext::async_icq::AsyncIcqMethodsExt; +use ibc_test_framework::chain::ext::bootstrap::ChainBootstrapMethodsExt; +use ibc_test_framework::chain::ext::wasm_client::StoreWasmClientCodeMethodsExt; +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, -}; +use tendermint_rpc::{Client, HttpClient}; #[test] fn test_async_icq() -> Result<(), Error> { run_binary_connection_test(&AsyncIcqTest) } +#[test] +fn test_failed_async_icq() -> Result<(), Error> { + run_binary_connection_test(&FailedAsyncIcqTest) +} + const MAX_DEPOSIT_PERIOD: &str = "10s"; +const MIN_DEPOSIT: u64 = 10000; const VOTING_PERIOD: u64 = 10; const MAX_RETRIES: usize = 10; +enum EventOracleQueryStatus { + Success(Event), + Error(Event), +} + pub struct AsyncIcqTest; impl TestOverrides for AsyncIcqTest { @@ -45,26 +47,13 @@ impl TestOverrides for AsyncIcqTest { // 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_min_deposit_amount(genesis, MIN_DEPOSIT)?; set_voting_period(genesis, VOTING_PERIOD)?; + add_allow_message_interchainquery(genesis, "/provenance.oracle.v1.Query/Oracle")?; + set_floor_gas_price(genesis, "5", "nhash", "25000")?; - 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"))) - } + Ok(()) } fn channel_version(&self) -> Version { @@ -80,8 +69,8 @@ impl BinaryConnectionTest for AsyncIcqTest { chains: ConnectedChains, connection: ConnectedConnection, ) -> Result<(), Error> { - let fee_denom_a: MonoTagged = - MonoTagged::new(Denom::base(&config.native_tokens[0])); + let fee_denom_b: MonoTagged = + MonoTagged::new(Denom::base(config.native_token(1))); let port_a = DualTagged::new(PortId::oracle()); let port_b = DualTagged::new(PortId::icqhost()); let (channel_id_b, channel_id_a) = init_channel_version( @@ -104,39 +93,229 @@ impl BinaryConnectionTest for AsyncIcqTest { &port_b.as_ref(), )?; - let driver = chains.node_a.chain_driver(); + let driver_b = chains.node_b.chain_driver(); let wallet_a = chains.node_a.wallets().user1().cloned(); - let relayer_a = chains.node_a.wallets().relayer().cloned(); + let relayer_b = chains.node_b.wallets().relayer().cloned(); + + let oracle_auth_address = driver_b.query_auth_module("gov")?; + + let current_dir = env::current_dir()?; + let echo_wasm_path = format!( + "{}/src/tests/async_icq/contracts/counter.wasm", + current_dir.display() + ); + + driver_b.store_wasm_contract( + "counter wasm", + "counter wasm", + &echo_wasm_path, + &oracle_auth_address, + &relayer_b.address().to_string(), + &fee_denom_b.with_amount(923290636u64).to_string(), + &fee_denom_b.with_amount(11000000000u64).to_string(), + "14472508", + )?; + + driver_b.value().assert_proposal_status( + driver_b.value().chain_id.as_str(), + &driver_b.value().command_path, + &driver_b.value().home_path, + &driver_b.value().rpc_listen_address(), + ProposalStatus::VotingPeriod, + "1", + )?; + + driver_b.vote_proposal(&fee_denom_b.with_amount(381000000u64).to_string(), "1")?; + + info!("Assert that the wasm contract is successfully uploaded"); + + driver_b.value().assert_proposal_status( + driver_b.value().chain_id.as_str(), + &driver_b.value().command_path, + &driver_b.value().home_path, + &driver_b.value().rpc_listen_address(), + ProposalStatus::Passed, + "1", + )?; + + let init_args = r#"{"count": 1}"#; + driver_b.update_oracle( + &relayer_b.address().to_string(), + &fee_denom_b.with_amount(381000000u64).to_string(), + init_args, + )?; + + driver_b.value().assert_proposal_status( + driver_b.value().chain_id.as_str(), + &driver_b.value().command_path, + &driver_b.value().home_path, + &driver_b.value().rpc_listen_address(), + ProposalStatus::VotingPeriod, + "2", + )?; + + driver_b.vote_proposal(&fee_denom_b.with_amount(381000000u64).to_string(), "2")?; + + info!("Assert that the update oracle proposal is eventually passed"); - driver.update_oracle( - &relayer_a.address().to_string(), + driver_b.value().assert_proposal_status( + driver_b.value().chain_id.as_str(), + &driver_b.value().command_path, + &driver_b.value().home_path, + &driver_b.value().rpc_listen_address(), + ProposalStatus::Passed, + "2", + )?; + + let query = r#"{"get_count":{"addr": "{my_addr}"}}"#; + let query = query.replace("{my_addr}", &relayer_b.address().to_string()); + + chains.node_a.chain_driver().async_icq( + channel_id_a.a_side.channel_id().unwrap(), + &query, &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(), + assert_eventual_async_icq_success(&chains, &relayer)?; + + Ok(()) + } +} + +pub struct FailedAsyncIcqTest; + +impl TestOverrides for FailedAsyncIcqTest { + 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> { + set_max_deposit_period(genesis, MAX_DEPOSIT_PERIOD)?; + set_min_deposit_amount(genesis, MIN_DEPOSIT)?; + set_voting_period(genesis, VOTING_PERIOD)?; + add_allow_message_interchainquery(genesis, "/provenance.oracle.v1.Query/Oracle")?; + set_floor_gas_price(genesis, "5", "nhash", "25000")?; + + Ok(()) + } + + fn channel_version(&self) -> Version { + Version::new("icq-1".to_owned()) + } +} + +impl BinaryConnectionTest for FailedAsyncIcqTest { + fn run( + &self, + config: &TestConfig, + relayer: RelayerDriver, + chains: ConnectedChains, + connection: ConnectedConnection, + ) -> Result<(), Error> { + let fee_denom_b: MonoTagged = + MonoTagged::new(Denom::base(config.native_token(1))); + 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_b = chains.node_b.chain_driver(); + + let wallet_a = chains.node_a.wallets().user1().cloned(); + + let relayer_b = chains.node_b.wallets().relayer().cloned(); + + let oracle_auth_address = driver_b.query_auth_module("gov")?; + + let current_dir = env::current_dir()?; + let echo_wasm_path = format!( + "{}/src/tests/async_icq/contracts/echo.wasm", + current_dir.display() + ); + + driver_b.store_wasm_contract( + "echo wasm", + "echo wasm", + &echo_wasm_path, + &oracle_auth_address, + &relayer_b.address().to_string(), + &fee_denom_b.with_amount(923290636u64).to_string(), + &fee_denom_b.with_amount(11000000000u64).to_string(), + "9972508", + )?; + + driver_b.value().assert_proposal_status( + driver_b.value().chain_id.as_str(), + &driver_b.value().command_path, + &driver_b.value().home_path, + &driver_b.value().rpc_listen_address(), ProposalStatus::VotingPeriod, "1", )?; - driver.vote_proposal(&fee_denom_a.with_amount(381000000u64).to_string())?; + driver_b.vote_proposal(&fee_denom_b.with_amount(381000000u64).to_string(), "1")?; 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(), + driver_b.value().assert_proposal_status( + driver_b.value().chain_id.as_str(), + &driver_b.value().command_path, + &driver_b.value().home_path, + &driver_b.value().rpc_listen_address(), ProposalStatus::Passed, "1", )?; + let init_args = r#"{}"#; + driver_b.update_oracle( + &relayer_b.address().to_string(), + &fee_denom_b.with_amount(381000000u64).to_string(), + init_args, + )?; + + driver_b.value().assert_proposal_status( + driver_b.value().chain_id.as_str(), + &driver_b.value().command_path, + &driver_b.value().home_path, + &driver_b.value().rpc_listen_address(), + ProposalStatus::VotingPeriod, + "2", + )?; + + driver_b.vote_proposal(&fee_denom_b.with_amount(381000000u64).to_string(), "2")?; + + info!("Assert that the update oracle proposal is eventually passed"); + + driver_b.value().assert_proposal_status( + driver_b.value().chain_id.as_str(), + &driver_b.value().command_path, + &driver_b.value().home_path, + &driver_b.value().rpc_listen_address(), + ProposalStatus::Passed, + "2", + )?; + let query = r#"{"query_version":{}}"#; chains.node_a.chain_driver().async_icq( channel_id_a.a_side.channel_id().unwrap(), @@ -144,7 +323,7 @@ impl BinaryConnectionTest for AsyncIcqTest { &wallet_a.address().to_string(), )?; - assert_eventual_async_icq_success(&chains, &relayer)?; + assert_eventual_async_icq_error(&chains, &relayer)?; Ok(()) } @@ -161,11 +340,56 @@ fn assert_eventual_async_icq_success( }; let mut rpc_client = HttpClient::new(rpc_addr).unwrap(); - rpc_client.set_compat_mode(tendermint_rpc::client::CompatMode::V0_34); + rpc_client.set_compat_mode(tendermint_rpc::client::CompatMode::V0_37); + + for _ in 0..MAX_RETRIES { + if let Ok(result) = check_events_for_success(chains, &rpc_client) { + match result { + EventOracleQueryStatus::Success(e) => { + debug!("async query successful with event: {e:#?}"); + return Ok(()); + } + EventOracleQueryStatus::Error(e) => { + return Err(Error::generic(eyre!( + "async query failed with response event: {e:#?}" + ))) + } + } + } + sleep(Duration::from_secs(1)); + } + + Err(Error::generic(eyre!( + "failed to find EventOracleQueryError or EventOracleQuerySuccess after {MAX_RETRIES} tries" + ))) +} + +/// Listen to events on the controller side to assert if the async ICQ is eventually +/// successful +fn assert_eventual_async_icq_error( + 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_37); for _ in 0..MAX_RETRIES { - if check_events(chains, &rpc_client).is_ok() { - return Ok(()); + if let Ok(result) = check_events_for_error(chains, &rpc_client) { + match result { + EventOracleQueryStatus::Success(e) => { + debug!("async query successful with event: {e:#?}"); + return Ok(()); + } + EventOracleQueryStatus::Error(e) => { + return Err(Error::generic(eyre!( + "async query failed with response event: {e:#?}" + ))) + } + } } sleep(Duration::from_secs(1)); } @@ -176,10 +400,10 @@ fn assert_eventual_async_icq_success( } /// Checks if there is an Oracle event in the given events -fn check_events( +fn check_events_for_success( chains: &ConnectedChains, rpc_client: &HttpClient, -) -> Result<(), Error> { +) -> Result { let response = chains .node_a .chain_driver() @@ -193,7 +417,34 @@ fn check_events( .iter() .find_map(|v| find_oracle_event(&v.events)) { - return assert_async_icq_success(events); + return Ok(assert_async_icq_success(events)); + } + } + + Err(Error::generic(eyre!( + "No EventOracleQueryError or EventOracleQuerySuccess" + ))) +} + +/// Checks if there is an Oracle event in the given events +fn check_events_for_error( + chains: &ConnectedChains, + rpc_client: &HttpClient, +) -> Result { + 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 Ok(assert_async_icq_error(events)); } } @@ -207,18 +458,41 @@ fn check_events( fn find_oracle_event(event: &[Event]) -> Option { event .iter() - .find(|&e| e.kind.contains("provenance.oracle.v1.EventOracleQuery")) + .find(|&e| { + e.kind.contains("provenance.oracle.v1.EventOracleQuery") + || e.kind + .contains("provenance.oracle.v1.EventOracleQueryError") + }) .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> { +fn assert_async_icq_success(event: Event) -> EventOracleQueryStatus { if event.kind == "provenance.oracle.v1.EventOracleQuerySuccess" { - debug!("async query successful with event: {event:#?}"); - Ok(()) + EventOracleQueryStatus::Success(event) + } else { + EventOracleQueryStatus::Error(event) + } +} + +/// This method is used to assert if the found Oracle event is successful or not +fn assert_async_icq_error(event: Event) -> EventOracleQueryStatus { + if event.kind == "provenance.oracle.v1.EventOracleQueryError" { + let error_message = event + .attributes + .iter() + .find(|attribute| attribute.key_str().unwrap() == "error") + .and_then(|error_attribute| error_attribute.value_str().ok()) + .unwrap(); + // The ABCI error code 29 refers to the following: + // Error calling the VM: Error resolving Wasm function: Could not get export: Missing export query: wasmvm error + // This is caused by the echo.wasm contract not having a query endpoint, causing the ICQ to fail. + assert_eq!( + error_message, + "\"ABCI code: 29: error handling packet: see events for details\"" + ); + EventOracleQueryStatus::Success(event) } else { - Err(Error::generic(eyre!( - "async query failed with response event: {event:#?}" - ))) + EventOracleQueryStatus::Error(event) } } diff --git a/tools/integration-test/src/tests/authz.rs b/tools/integration-test/src/tests/authz.rs new file mode 100644 index 0000000000..28f5c11a18 --- /dev/null +++ b/tools/integration-test/src/tests/authz.rs @@ -0,0 +1,199 @@ +//! This test tests relaying messages from authz: +//! +//! - The `AuthzTest` will grant authorization for `MsgTransfer` from `user2` (granter) +//! to `user1` (grantee). It will then execute an IBC transfer using the chain's +//! `tx authz exec` command and assert that the transfer successfully completes. +//! +//! - The `NoAuthzTest` will skip granting authorization and assert that the +//! `MsgTransfer` is not authorized and that the chain's `tx authz exec` +//! command fails. + +use ibc_test_framework::chain::ext::authz::AuthzMethodsExt; +use ibc_test_framework::prelude::*; + +#[test] +fn test_authz() -> Result<(), Error> { + run_binary_channel_test(&AuthzTest) +} + +#[test] +fn test_no_authz() -> Result<(), Error> { + run_binary_channel_test(&NoAuthzTest) +} + +struct AuthzTest; + +impl TestOverrides for AuthzTest {} + +impl BinaryChannelTest for AuthzTest { + fn run( + &self, + config: &TestConfig, + _relayer: RelayerDriver, + chains: ConnectedChains, + channels: ConnectedChannel, + ) -> Result<(), Error> { + let denom_a = chains.node_a.denom(); + let fee_denom_a: MonoTagged = + MonoTagged::new(Denom::base(config.native_token(0))); + let wallet_b = chains.node_b.wallets().user1().cloned(); + + let a_to_b_amount = 12345u64; + let granter = chains + .node_a + .wallets() + .user2() + .address() + .value() + .to_string(); + let grantee = chains + .node_a + .wallets() + .user1() + .address() + .value() + .to_string(); + + let fees = fee_denom_a.with_amount(390000000u64).to_string(); + + chains.node_a.chain_driver().authz_grant( + &granter, + &grantee, + "/ibc.applications.transfer.v1.MsgTransfer", + &fees, + )?; + + chains.node_a.chain_driver().assert_eventual_grant( + &granter, + &grantee, + "/ibc.applications.transfer.v1.MsgTransfer", + )?; + + let granter_balance = chains + .node_a + .chain_driver() + .query_balance(&chains.node_a.wallets().user2().address(), &denom_a)?; + + let denom_b = derive_ibc_denom( + &channels.port_b.as_ref(), + &channels.channel_id_b.as_ref(), + &denom_a, + )?; + + chains.node_a.chain_driver().exec_ibc_transfer_grant( + &granter, + &grantee, + channels.port_a.value(), + channels.channel_id_a.value(), + &wallet_b.address(), + &denom_a.with_amount(a_to_b_amount).as_ref(), + &fees, + )?; + + // Assert that user on chain B received the tokens + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &wallet_b.address(), + &denom_b.with_amount(a_to_b_amount).as_ref(), + )?; + + // Assert that user on chain A sent the tokens + chains.node_a.chain_driver().assert_eventual_wallet_amount( + &chains.node_a.wallets().user2().address(), + &(granter_balance - a_to_b_amount).as_ref(), + )?; + + Ok(()) + } +} + +struct NoAuthzTest; + +impl TestOverrides for NoAuthzTest {} + +impl BinaryChannelTest for NoAuthzTest { + fn run( + &self, + config: &TestConfig, + _relayer: RelayerDriver, + chains: ConnectedChains, + channels: ConnectedChannel, + ) -> Result<(), Error> { + let denom_a = chains.node_a.denom(); + let fee_denom_a: MonoTagged = + MonoTagged::new(Denom::base(config.native_token(0))); + let wallet_b = chains.node_b.wallets().user1().cloned(); + + let a_to_b_amount = 12345u64; + let granter = chains + .node_a + .wallets() + .user2() + .address() + .value() + .to_string(); + let grantee = chains + .node_a + .wallets() + .user1() + .address() + .value() + .to_string(); + + let denom_b = derive_ibc_denom( + &channels.port_b.as_ref(), + &channels.channel_id_b.as_ref(), + &denom_a, + )?; + + assert!( + chains + .node_a + .chain_driver() + .assert_eventual_grant( + &granter, + &grantee, + "/ibc.applications.transfer.v1.MsgTransfer", + ) + .is_err(), + "there should be no grants" + ); + + let granter_balance = chains + .node_a + .chain_driver() + .query_balance(&chains.node_a.wallets().user2().address(), &denom_a)?; + + let fees = fee_denom_a.with_amount(390000000u64).to_string(); + + assert!( + chains + .node_a + .chain_driver() + .exec_ibc_transfer_grant( + &granter, + &grantee, + channels.port_a.value(), + channels.channel_id_a.value(), + &wallet_b.address(), + &denom_a.with_amount(a_to_b_amount).as_ref(), + &fees, + ) + .is_err(), + "expected authz grant exec to fail" + ); + + // Assert that user on chain B has not received tokens + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &wallet_b.address(), + &denom_b.with_amount(0u128).as_ref(), + )?; + + // Assert that user on chain A has not sent tokens + chains.node_a.chain_driver().assert_eventual_wallet_amount( + &chains.node_a.wallets().user2().address(), + &granter_balance.as_ref(), + )?; + + Ok(()) + } +} diff --git a/tools/integration-test/src/tests/benchmark/mod.rs b/tools/integration-test/src/tests/benchmark/mod.rs new file mode 100644 index 0000000000..169d3ccaca --- /dev/null +++ b/tools/integration-test/src/tests/benchmark/mod.rs @@ -0,0 +1 @@ +pub mod query_commitments; diff --git a/tools/integration-test/src/tests/benchmark/query_commitments.rs b/tools/integration-test/src/tests/benchmark/query_commitments.rs new file mode 100644 index 0000000000..b05b02f5c4 --- /dev/null +++ b/tools/integration-test/src/tests/benchmark/query_commitments.rs @@ -0,0 +1,82 @@ +use ibc_test_framework::prelude::*; + +#[test] +fn benchmark_query_commitments() -> Result<(), Error> { + run_binary_channel_test(&QueryCommitmentsBenchmark) +} + +pub struct QueryCommitmentsBenchmark; + +impl TestOverrides for QueryCommitmentsBenchmark { + fn modify_relayer_config(&self, config: &mut Config) { + config.mode.packets.clear_on_start = false; + config.mode.packets.clear_interval = 0; + } + + fn should_spawn_supervisor(&self) -> bool { + false + } +} + +impl BinaryChannelTest for QueryCommitmentsBenchmark { + fn run( + &self, + config: &TestConfig, + relayer: RelayerDriver, + chains: ConnectedChains, + channel: ConnectedChannel, + ) -> Result<(), Error> { + use std::path::Path; + + use ibc_relayer::util::profiling::open_or_create_profile_file; + + let now = time::OffsetDateTime::now_utc(); + let path_str = format!( + "{}/hermes-{:04}-{:02}-{:02}-{:02}{:02}{:02}-prof.json", + config.chain_store_dir.as_path().display(), + now.year(), + now.month(), + now.day(), + now.hour(), + now.minute(), + now.second() + ); + + open_or_create_profile_file(Path::new(&path_str)); + ibc_relayer::util::profiling::enable(false, true); + + 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 a_to_b_amount = 12u64; + let num_msgs = 1000000u64; + + info!( + "Sending {num_msgs} IBC transfers from chain {} to chain {} with amount of {} {}", + chains.chain_id_a(), + chains.chain_id_b(), + a_to_b_amount, + denom_a + ); + + chains.node_a.chain_driver().ibc_transfer_token_multiple( + &channel.port_a.as_ref(), + &channel.channel_id_a.as_ref(), + &wallet_a.as_ref(), + &wallet_b.address(), + &denom_a.with_amount(a_to_b_amount).as_ref(), + num_msgs as usize, + None, + )?; + + info!("Waiting for profiling to be populated"); + + relayer.with_supervisor(|| { + std::thread::sleep(core::time::Duration::from_secs(180)); + + Ok(()) + }) + } +} diff --git a/tools/integration-test/src/tests/channel_upgrade/flushing.rs b/tools/integration-test/src/tests/channel_upgrade/flushing.rs new file mode 100644 index 0000000000..0e4bdf7143 --- /dev/null +++ b/tools/integration-test/src/tests/channel_upgrade/flushing.rs @@ -0,0 +1,422 @@ +//! Tests that the relayer correctly flushes in-flight packets during channel upgrade. +//! +//! - `ChannelUpgradeFlushing` tests that the channel worker will complete the +//! upgrade handshake when there are pending packets before starting the channel upgrade. +//! +//! - `ChannelUpgradeHandshakeFlushPackets` tests that the channel worker will complete the +//! upgrade handshake when packets need to be flushed during the handshake. + +use ibc_relayer::chain::requests::{IncludeProof, QueryChannelRequest, QueryHeight}; +use ibc_relayer_types::core::ics04_channel::channel::State as ChannelState; +use ibc_relayer_types::core::ics04_channel::packet::Sequence; +use ibc_relayer_types::core::ics04_channel::version::Version; +use ibc_test_framework::chain::config::{set_max_deposit_period, set_voting_period}; +use ibc_test_framework::prelude::*; +use ibc_test_framework::relayer::channel::{ + assert_eventually_channel_established, assert_eventually_channel_upgrade_ack, + assert_eventually_channel_upgrade_init, assert_eventually_channel_upgrade_open, + assert_eventually_channel_upgrade_try, ChannelUpgradableAttributes, +}; +use ibc_test_framework::util::random::random_u128_range; + +#[test] +fn test_channel_upgrade_simple_flushing() -> Result<(), Error> { + run_binary_channel_test(&ChannelUpgradeFlushing) +} + +#[test] +fn test_channel_upgrade_handshake_flush_packets() -> Result<(), Error> { + run_binary_channel_test(&ChannelUpgradeHandshakeFlushPackets) +} + +const MAX_DEPOSIT_PERIOD: &str = "10s"; +const VOTING_PERIOD: u64 = 10; + +pub struct ChannelUpgradeFlushing; + +impl TestOverrides for ChannelUpgradeFlushing { + fn modify_relayer_config(&self, config: &mut Config) { + config.mode.channels.enabled = true; + config.mode.packets.auto_register_counterparty_payee = true; + config.mode.packets.clear_interval = 0; + config.mode.packets.clear_on_start = true; + + config.mode.clients.misbehaviour = false; + } + + 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)?; + Ok(()) + } + + fn should_spawn_supervisor(&self) -> bool { + false + } +} + +impl BinaryChannelTest for ChannelUpgradeFlushing { + fn run( + &self, + _config: &TestConfig, + relayer: RelayerDriver, + chains: ConnectedChains, + channels: ConnectedChannel, + ) -> Result<(), Error> { + info!("Check that channels are both in OPEN State"); + + assert_eventually_channel_established( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + )?; + + let channel_end_a = chains + .handle_a + .query_channel( + QueryChannelRequest { + port_id: channels.port_a.0.clone(), + channel_id: channels.channel_id_a.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd A: {e}"))?; + + let channel_end_b = chains + .handle_b + .query_channel( + QueryChannelRequest { + port_id: channels.port_b.0.clone(), + channel_id: channels.channel_id_b.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd B: {e}"))?; + + let chain_driver_a = chains.node_a.chain_driver(); + let chain_driver_b = chains.node_b.chain_driver(); + + let denom_a = chains.node_a.denom(); + + let port_a = channels.port_a.as_ref(); + let channel_id_a = channels.channel_id_a.as_ref(); + + let wallets_a = chains.node_a.wallets(); + let wallets_b = chains.node_b.wallets(); + + let user_a = wallets_a.user1(); + let user_b = wallets_b.user1(); + + let send_amount = random_u128_range(1000, 2000); + + chain_driver_a.ibc_transfer_token( + &port_a, + &channel_id_a, + &user_a, + &user_b.address(), + &denom_a.with_amount(send_amount).as_ref(), + )?; + + sleep(Duration::from_secs(3)); + + chain_driver_a.ibc_transfer_token( + &port_a, + &channel_id_a, + &user_a, + &user_b.address(), + &denom_a.with_amount(send_amount).as_ref(), + )?; + + let old_ordering = channel_end_a.ordering; + let old_connection_hops_a = channel_end_a.connection_hops; + let old_connection_hops_b = channel_end_b.connection_hops; + + let channel = channels.channel; + let new_version = Version::ics20_with_fee(); + + let upgraded_attrs = ChannelUpgradableAttributes::new( + new_version.clone(), + new_version.clone(), + old_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b, + Sequence::from(1), + ); + + info!("Will initialise upgrade handshake with governance proposal..."); + + chains.node_a.chain_driver().initialise_channel_upgrade( + channel.src_port_id().as_str(), + channel.src_channel_id().unwrap().as_str(), + old_ordering.as_str(), + old_connection_hops_a.first().unwrap().as_str(), + &serde_json::to_string(&new_version.0).unwrap(), + chains.handle_a().get_signer().unwrap().as_ref(), + "1", + )?; + + sleep(Duration::from_secs(5)); + + info!("Check that the channel upgrade successfully upgraded the version..."); + + relayer.with_supervisor(|| { + let denom_b = derive_ibc_denom( + &channels.port_b.as_ref(), + &channels.channel_id_b.as_ref(), + &denom_a, + )?; + + chain_driver_b.assert_eventual_wallet_amount( + &user_b.address(), + &denom_b.with_amount(send_amount + send_amount).as_ref(), + )?; + + assert_eventually_channel_upgrade_open( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + &upgraded_attrs, + )?; + + Ok(()) + }) + } +} + +struct ChannelUpgradeHandshakeFlushPackets; + +impl TestOverrides for ChannelUpgradeHandshakeFlushPackets { + 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)?; + Ok(()) + } + + fn modify_relayer_config(&self, config: &mut Config) { + config.mode.channels.enabled = true; + + config.mode.clients.misbehaviour = false; + } + + fn should_spawn_supervisor(&self) -> bool { + false + } +} + +impl BinaryChannelTest for ChannelUpgradeHandshakeFlushPackets { + fn run( + &self, + _config: &TestConfig, + relayer: RelayerDriver, + chains: ConnectedChains, + channels: ConnectedChannel, + ) -> Result<(), Error> { + info!("Check that channels are both in OPEN State"); + + assert_eventually_channel_established( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + )?; + + let channel_end_a = chains + .handle_a + .query_channel( + QueryChannelRequest { + port_id: channels.port_a.0.clone(), + channel_id: channels.channel_id_a.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd A: {e}"))?; + + let channel_end_b = chains + .handle_b + .query_channel( + QueryChannelRequest { + port_id: channels.port_b.0.clone(), + channel_id: channels.channel_id_b.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd B: {e}"))?; + + let old_version = channel_end_a.version; + let old_ordering = channel_end_a.ordering; + let old_connection_hops_a = channel_end_a.connection_hops; + let old_connection_hops_b = channel_end_b.connection_hops; + + let channel = channels.channel; + let new_version = Version::ics20_with_fee(); + + let old_attrs = ChannelUpgradableAttributes::new( + old_version.clone(), + old_version.clone(), + old_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b.clone(), + Sequence::from(1), + ); + + let upgraded_attrs = ChannelUpgradableAttributes::new( + new_version.clone(), + new_version.clone(), + old_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b, + Sequence::from(1), + ); + + info!("Will initialise upgrade handshake with governance proposal..."); + + chains.node_a.chain_driver().initialise_channel_upgrade( + channel.src_port_id().as_str(), + channel.src_channel_id().unwrap().as_str(), + old_ordering.as_str(), + old_connection_hops_a.first().unwrap().as_str(), + &serde_json::to_string(&new_version.0).unwrap(), + chains.handle_a().get_signer().unwrap().as_ref(), + "1", + )?; + + info!("Check that the step ChanUpgradeInit was correctly executed..."); + + assert_eventually_channel_upgrade_init( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + &old_attrs, + )?; + + // send a IBC transfer message from chain a to chain b + // so that we have an in-flight packet and chain a + // will move to `FLUSHING` during Ack + 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 a_to_b_amount = random_u128_range(1000, 5000); + + info!( + "Sending IBC transfer from chain {} to chain {} with amount of {} {}", + chains.chain_id_a(), + chains.chain_id_b(), + a_to_b_amount, + denom_a + ); + + chains.node_a.chain_driver().ibc_transfer_token( + &channels.port_a.as_ref(), + &channels.channel_id_a.as_ref(), + &wallet_a.as_ref(), + &wallet_b.address(), + &denom_a.with_amount(a_to_b_amount).as_ref(), + )?; + + // send a IBC transfer message from chain b to chain a + // so that we have an in-flight packet and chain a + // will move to `FLUSHING` during Try + let denom_b = chains.node_b.denom(); + let b_to_a_amount = random_u128_range(1000, 5000); + + info!( + "Sending IBC transfer from chain {} to chain {} with amount of {} {}", + chains.chain_id_b(), + chains.chain_id_a(), + b_to_a_amount, + denom_b + ); + + chains.node_b.chain_driver().ibc_transfer_token( + &channels.port_b.as_ref(), + &channels.channel_id_b.as_ref(), + &wallet_b.as_ref(), + &wallet_a.address(), + &denom_b.with_amount(b_to_a_amount).as_ref(), + )?; + + info!("Will run ChanUpgradeTry step..."); + + channel.build_chan_upgrade_try_and_send()?; + + info!("Check that the step ChanUpgradeTry was correctly executed..."); + + assert_eventually_channel_upgrade_try( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + &old_attrs.flipped(), + )?; + + info!("Will run ChanUpgradeAck step..."); + + channel.flipped().build_chan_upgrade_ack_and_send()?; + + info!("Check that the step ChanUpgradeAck was correctly executed..."); + + // channel a is `FLUSHING` because the packet + // from a to b has not been cleared yet + assert_eventually_channel_upgrade_ack( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + ChannelState::Flushing, + ChannelState::Flushing, + &old_attrs, + )?; + + info!("Check that the channel upgrade successfully upgraded the version..."); + + // start supervisor to clear in-flight packets + // and move channel ends to `FLUSH_COMPLETE` + relayer.with_supervisor(|| { + let ibc_denom_a = derive_ibc_denom( + &channels.port_a.as_ref(), + &channels.channel_id_a.as_ref(), + &denom_b, + )?; + + chains.node_a.chain_driver().assert_eventual_wallet_amount( + &wallet_a.address(), + &ibc_denom_a.with_amount(b_to_a_amount).as_ref(), + )?; + + let ibc_denom_b = derive_ibc_denom( + &channels.port_b.as_ref(), + &channels.channel_id_b.as_ref(), + &denom_a, + )?; + + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &wallet_b.address(), + &ibc_denom_b.with_amount(a_to_b_amount).as_ref(), + )?; + + // This will assert that both channel ends are eventually + // in Open state, and that the fields targeted by the upgrade + // have been correctly updated. + assert_eventually_channel_upgrade_open( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + &upgraded_attrs, + )?; + + Ok(()) + }) + } +} diff --git a/tools/integration-test/src/tests/channel_upgrade/ica.rs b/tools/integration-test/src/tests/channel_upgrade/ica.rs new file mode 100644 index 0000000000..8ddd4fb5c7 --- /dev/null +++ b/tools/integration-test/src/tests/channel_upgrade/ica.rs @@ -0,0 +1,526 @@ +//! Tests channel upgrade features: +//! +//! - `ChannelUpgradeICACloseChannel` tests that after the upgrade handshake is completed +//! and the channel version has been updated to ICS29 a packet timeout closes the channel. +//! +//! - `ChannelUpgradeICAUnordered` tests that after the after sending a packet on an ordered +//! ICA channel, the upgrade handshake is completed when the channel is upgraded to unordered. + +use serde_json as json; +use std::collections::HashMap; +use std::str::FromStr; + +use ibc_relayer::chain::requests::{IncludeProof, QueryChannelRequest, QueryHeight}; +use ibc_relayer::chain::tracking::TrackedMsgs; +use ibc_relayer::config::{ + filter::{ChannelFilters, ChannelPolicy, FilterPattern}, + ChainConfig, PacketFilter, +}; +use ibc_relayer::event::IbcEventWithHeight; + +use ibc_relayer_types::applications::{ + ics27_ica, + ics27_ica::{ + cosmos_tx::CosmosTx, msgs::send_tx::MsgSendTx, packet_data::InterchainAccountPacketData, + }, + transfer::{msgs::send::MsgSend, Amount, Coin}, +}; +use ibc_relayer_types::bigint::U256; +use ibc_relayer_types::core::ics04_channel::packet::Sequence; +use ibc_relayer_types::core::ics04_channel::version::Version; +use ibc_relayer_types::signer::Signer; +use ibc_relayer_types::timestamp::Timestamp; +use ibc_relayer_types::tx_msg::Msg; + +use ibc_test_framework::chain::config::{ + add_allow_message_interchainaccounts, set_max_deposit_period, set_voting_period, +}; +use ibc_test_framework::chain::ext::ica::register_ordered_interchain_account; +use ibc_test_framework::prelude::*; +use ibc_test_framework::relayer::channel::{ + assert_eventually_channel_closed, assert_eventually_channel_established, + assert_eventually_channel_upgrade_open, ChannelUpgradableAttributes, +}; + +#[test] +fn test_channel_upgrade_ica_close_channel() -> Result<(), Error> { + run_binary_connection_test(&ChannelUpgradeICACloseChannel) +} + +#[test] +fn test_channel_upgrade_ica_unordered() -> Result<(), Error> { + run_binary_connection_test(&ChannelUpgradeICAUnordered::new(PacketFilter::new( + ChannelPolicy::Allow(ChannelFilters::new(vec![( + FilterPattern::Wildcard("ica*".parse().unwrap()), + FilterPattern::Wildcard("*".parse().unwrap()), + )])), + HashMap::new(), + ))) +} + +const MAX_DEPOSIT_PERIOD: &str = "10s"; +const VOTING_PERIOD: u64 = 10; + +pub struct ChannelUpgradeICACloseChannel; + +impl TestOverrides for ChannelUpgradeICACloseChannel { + fn modify_relayer_config(&self, config: &mut Config) { + config.mode.channels.enabled = true; + + config.mode.clients.misbehaviour = false; + } + + 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)?; + + Ok(()) + } + + fn should_spawn_supervisor(&self) -> bool { + false + } +} + +impl BinaryConnectionTest for ChannelUpgradeICACloseChannel { + fn run( + &self, + config: &TestConfig, + relayer: RelayerDriver, + chains: ConnectedChains, + connection: ConnectedConnection, + ) -> Result<(), Error> { + let fee_denom_host: MonoTagged = + MonoTagged::new(Denom::base(config.native_token(1))); + let stake_denom: MonoTagged = MonoTagged::new(Denom::base("stake")); + + // Run the block with supervisor in order to open and then upgrade the ICA channel + let (wallet, ica_address, controller_channel_id, controller_port_id) = relayer + .with_supervisor(|| { + // Register an interchain account on behalf of + // controller wallet `user1` where the counterparty chain is the interchain accounts host. + let (wallet, controller_channel_id, controller_port_id) = + register_ordered_interchain_account( + &chains.node_a, + chains.handle_a(), + &connection, + )?; + + // Check that the corresponding ICA channel is eventually established. + let _counterparty_channel_id = assert_eventually_channel_established( + chains.handle_a(), + chains.handle_b(), + &controller_channel_id.as_ref(), + &controller_port_id.as_ref(), + )?; + + let channel_end_a = chains + .handle_a + .query_channel( + QueryChannelRequest { + port_id: controller_port_id.value().clone(), + channel_id: controller_channel_id.value().clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd A: {e}"))?; + + let host_port_id = channel_end_a.remote.port_id; + let host_channel_id = channel_end_a + .remote + .channel_id + .ok_or_else(|| eyre!("expect to find counterparty channel id"))?; + + let channel_end_b = chains + .handle_b + .query_channel( + QueryChannelRequest { + port_id: host_port_id.clone(), + channel_id: host_channel_id.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd B: {e}"))?; + + let old_ordering = channel_end_a.ordering; + let old_connection_hops_a = channel_end_a.connection_hops; + let old_connection_hops_b = channel_end_b.connection_hops; + + // Query the controller chain for the address of the ICA wallet on the host chain. + let ica_address = chains.node_a.chain_driver().query_interchain_account( + &wallet.address(), + &connection.connection_id_a.as_ref(), + )?; + + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &ica_address.as_ref(), + &stake_denom.with_amount(0u64).as_ref(), + )?; + + let app_version = json::json!({ + "version": ics27_ica::VERSION, + "encoding": "proto3", + "tx_type": "sdk_multi_msg", + "address": ica_address.to_string(), + "controller_connection_id": connection.connection_id_a.0, + "host_connection_id": connection.connection_id_b.0, + }); + let new_version = Version::app_version_with_fee(&app_version.to_string()); + + let upgraded_attrs = ChannelUpgradableAttributes::new( + new_version.clone(), + new_version.clone(), + old_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b.clone(), + Sequence::from(1), + ); + + info!("Will initialise upgrade handshake with governance proposal..."); + + chains.node_a.chain_driver().initialise_channel_upgrade( + controller_port_id.to_string().as_str(), + controller_channel_id.to_string().as_str(), + old_ordering.as_str(), + old_connection_hops_a.first().unwrap().as_str(), + &serde_json::to_string(&new_version.0).unwrap(), + chains.handle_a().get_signer().unwrap().as_ref(), + "1", + )?; + + info!("Check that the channel upgrade successfully upgraded the version..."); + + assert_eventually_channel_upgrade_open( + &chains.handle_a, + &chains.handle_b, + &controller_channel_id.as_ref(), + &controller_port_id.as_ref(), + &upgraded_attrs, + )?; + sleep(Duration::from_secs(5)); + + Ok(( + wallet, + ica_address, + controller_channel_id, + controller_port_id, + )) + })?; + + // Create a pending ICA transfer without supervisor in order to created a timed out + // packet + + // Send funds to the interchain account. + let ica_fund = 42000u64; + + chains.node_b.chain_driver().local_transfer_token( + &chains.node_b.wallets().user1(), + &ica_address.as_ref(), + &stake_denom.with_amount(ica_fund).as_ref(), + &fee_denom_host.with_amount(381000000u64).as_ref(), + )?; + + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &ica_address.as_ref(), + &stake_denom.with_amount(ica_fund).as_ref(), + )?; + + let amount = 12345u64; + + let msg = MsgSend { + from_address: ica_address.to_string(), + to_address: chains.node_b.wallets().user2().address().to_string(), + amount: vec![Coin { + denom: stake_denom.to_string(), + amount: Amount(U256::from(amount)), + }], + }; + + let raw_msg = msg.to_any(); + + let cosmos_tx = CosmosTx { + messages: vec![raw_msg], + }; + + let raw_cosmos_tx = cosmos_tx.to_any(); + + let interchain_account_packet_data = InterchainAccountPacketData::new(raw_cosmos_tx.value); + + let signer = Signer::from_str(&wallet.address().to_string()).unwrap(); + + let balance_user2 = chains.node_b.chain_driver().query_balance( + &chains.node_b.wallets().user2().address(), + &stake_denom.as_ref(), + )?; + sleep(Duration::from_secs(5)); + + interchain_send_tx( + chains.handle_a(), + &signer, + &connection.connection_id_a.0, + interchain_account_packet_data.clone(), + Timestamp::from_nanoseconds(1000000000).unwrap(), + )?; + + sleep(Duration::from_nanos(3000000000)); + + // Start the supervisor which will relay the timed out packet and close the channel + relayer.with_supervisor(|| { + // Check that user2 has not received the sent amount. + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &chains.node_b.wallets().user2().address(), + &(balance_user2).as_ref(), + )?; + sleep(Duration::from_secs(5)); + + // Check that the ICA account's balance has not been debited the sent amount. + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &ica_address.as_ref(), + &stake_denom.with_amount(ica_fund).as_ref(), + )?; + + info!("Check that the channel closed after packet timeout..."); + + assert_eventually_channel_closed( + &chains.handle_a, + &chains.handle_b, + &controller_channel_id.as_ref(), + &controller_port_id.as_ref(), + )?; + + Ok(()) + }) + } +} + +pub struct ChannelUpgradeICAUnordered { + packet_filter: PacketFilter, +} + +impl ChannelUpgradeICAUnordered { + pub fn new(packet_filter: PacketFilter) -> Self { + Self { packet_filter } + } +} + +impl TestOverrides for ChannelUpgradeICAUnordered { + fn modify_relayer_config(&self, config: &mut Config) { + config.mode.channels.enabled = true; + + config.mode.clients.misbehaviour = false; + + for chain in &mut config.chains { + match chain { + ChainConfig::CosmosSdk(chain_config) => { + chain_config.packet_filter = self.packet_filter.clone(); + } + } + } + } + + fn modify_genesis_file(&self, genesis: &mut serde_json::Value) -> Result<(), Error> { + add_allow_message_interchainaccounts(genesis, "/cosmos.bank.v1beta1.MsgSend")?; + set_max_deposit_period(genesis, MAX_DEPOSIT_PERIOD)?; + set_voting_period(genesis, VOTING_PERIOD)?; + + Ok(()) + } + + fn should_spawn_supervisor(&self) -> bool { + true + } +} + +impl BinaryConnectionTest for ChannelUpgradeICAUnordered { + fn run( + &self, + config: &TestConfig, + _relayer: RelayerDriver, + chains: ConnectedChains, + connection: ConnectedConnection, + ) -> Result<(), Error> { + let fee_denom_host: MonoTagged = + MonoTagged::new(Denom::base(config.native_token(1))); + let stake_denom: MonoTagged = MonoTagged::new(Denom::base("stake")); + + info!("Will register interchain account..."); + + // Register an interchain account on behalf of + // controller wallet `user1` where the counterparty chain is the interchain accounts host. + let (wallet, controller_channel_id, controller_port_id) = + register_ordered_interchain_account(&chains.node_a, chains.handle_a(), &connection)?; + + // Check that the corresponding ICA channel is eventually established. + let _counterparty_channel_id = assert_eventually_channel_established( + chains.handle_a(), + chains.handle_b(), + &controller_channel_id.as_ref(), + &controller_port_id.as_ref(), + )?; + + // Query the controller chain for the address of the ICA wallet on the host chain. + let ica_address = chains + .node_a + .chain_driver() + .query_interchain_account(&wallet.address(), &connection.connection_id_a.as_ref())?; + + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &ica_address.as_ref(), + &stake_denom.with_amount(0u64).as_ref(), + )?; + + info!("Will send a message to the interchain account..."); + + // Send funds to the interchain account. + let ica_fund = 42000u64; + + chains.node_b.chain_driver().local_transfer_token( + &chains.node_b.wallets().user1(), + &ica_address.as_ref(), + &stake_denom.with_amount(ica_fund).as_ref(), + &fee_denom_host.with_amount(381000000u64).as_ref(), + )?; + + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &ica_address.as_ref(), + &stake_denom.with_amount(ica_fund).as_ref(), + )?; + + let amount = 12345u64; + + let msg = MsgSend { + from_address: ica_address.to_string(), + to_address: chains.node_b.wallets().user2().address().to_string(), + amount: vec![Coin { + denom: stake_denom.to_string(), + amount: Amount(U256::from(amount)), + }], + }; + + let raw_msg = msg.to_any(); + + let cosmos_tx = CosmosTx { + messages: vec![raw_msg], + }; + + let raw_cosmos_tx = cosmos_tx.to_any(); + + let interchain_account_packet_data = InterchainAccountPacketData::new(raw_cosmos_tx.value); + + let signer = Signer::from_str(&wallet.address().to_string()).unwrap(); + + interchain_send_tx( + chains.handle_a(), + &signer, + &connection.connection_id_a.0, + interchain_account_packet_data.clone(), + Timestamp::from_nanoseconds(10000000000).unwrap(), + )?; + + // Check that the ICA account's balance has been debited the sent amount. + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &ica_address.as_ref(), + &stake_denom.with_amount(ica_fund - amount).as_ref(), + )?; + + let channel_end_a = chains + .handle_a + .query_channel( + QueryChannelRequest { + port_id: controller_port_id.value().clone(), + channel_id: controller_channel_id.value().clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd A: {e}"))?; + + let host_port_id = channel_end_a.remote.port_id; + let host_channel_id = channel_end_a + .remote + .channel_id + .ok_or_else(|| eyre!("expect to find counterparty channel id"))?; + + let channel_end_b = chains + .handle_b + .query_channel( + QueryChannelRequest { + port_id: host_port_id.clone(), + channel_id: host_channel_id.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd B: {e}"))?; + + let old_version_a = channel_end_a.version; + let old_version_b = channel_end_b.version; + let old_connection_hops_a = channel_end_a.connection_hops; + let old_connection_hops_b = channel_end_b.connection_hops; + + let new_ordering = Ordering::Unordered; + + let upgraded_attrs = ChannelUpgradableAttributes::new( + old_version_a.clone(), + old_version_b.clone(), + new_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b.clone(), + Sequence::from(1), + ); + + info!("Will initialise upgrade handshake with governance proposal..."); + + chains.node_a.chain_driver().initialise_channel_upgrade( + controller_port_id.to_string().as_str(), + controller_channel_id.to_string().as_str(), + new_ordering.as_str(), + old_connection_hops_a.first().unwrap().as_str(), + &serde_json::to_string(&old_version_a.0).unwrap(), + &chains.node_a.wallets().user2().address().to_string(), + "1", + )?; + + info!("Check that the channel upgrade successfully upgraded the ordering..."); + + assert_eventually_channel_upgrade_open( + &chains.handle_a, + &chains.handle_b, + &controller_channel_id.as_ref(), + &controller_port_id.as_ref(), + &upgraded_attrs, + )?; + sleep(Duration::from_secs(5)); + + Ok(()) + } +} + +fn interchain_send_tx( + chain: &ChainA, + from: &Signer, + connection: &ConnectionId, + msg: InterchainAccountPacketData, + relative_timeout: Timestamp, +) -> Result, Error> { + let msg = MsgSendTx { + owner: from.clone(), + connection_id: connection.clone(), + packet_data: msg, + relative_timeout, + }; + + let msg_any = msg.to_any(); + + let tm = TrackedMsgs::new_static(vec![msg_any], "SendTx"); + + chain + .send_messages_and_wait_commit(tm) + .map_err(Error::relayer) +} diff --git a/tools/integration-test/src/tests/channel_upgrade/ics29.rs b/tools/integration-test/src/tests/channel_upgrade/ics29.rs new file mode 100644 index 0000000000..02f90b2745 --- /dev/null +++ b/tools/integration-test/src/tests/channel_upgrade/ics29.rs @@ -0,0 +1,227 @@ +//! Tests channel upgrade features: +//! +//! - `ChannelUpgradeICS29` tests that only after the upgrade handshake is completed +//! and the channel version has been updated to ICS29 can Incentivized packets be +//! relayed. + +use ibc_relayer::chain::requests::{IncludeProof, QueryChannelRequest, QueryHeight}; +use ibc_relayer_types::core::ics04_channel::packet::Sequence; +use ibc_relayer_types::core::ics04_channel::version::Version; +use ibc_test_framework::chain::config::{set_max_deposit_period, set_voting_period}; +use ibc_test_framework::prelude::*; +use ibc_test_framework::relayer::channel::{ + assert_eventually_channel_established, assert_eventually_channel_upgrade_open, + ChannelUpgradableAttributes, +}; +use ibc_test_framework::util::random::random_u128_range; + +#[test] +fn test_channel_upgrade_ics29() -> Result<(), Error> { + run_binary_channel_test(&ChannelUpgradeICS29) +} + +const MAX_DEPOSIT_PERIOD: &str = "10s"; +const VOTING_PERIOD: u64 = 10; + +pub struct ChannelUpgradeICS29; + +impl TestOverrides for ChannelUpgradeICS29 { + fn modify_relayer_config(&self, config: &mut Config) { + config.mode.channels.enabled = true; + config.mode.packets.auto_register_counterparty_payee = true; + config.mode.packets.clear_interval = 0; + config.mode.packets.clear_on_start = false; + + config.mode.clients.misbehaviour = false; + } + + 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)?; + Ok(()) + } +} + +impl BinaryChannelTest for ChannelUpgradeICS29 { + fn run( + &self, + _config: &TestConfig, + _relayer: RelayerDriver, + chains: ConnectedChains, + channels: ConnectedChannel, + ) -> Result<(), Error> { + info!("Check that channels are both in OPEN State"); + + assert_eventually_channel_established( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + )?; + + let channel_end_a = chains + .handle_a + .query_channel( + QueryChannelRequest { + port_id: channels.port_a.0.clone(), + channel_id: channels.channel_id_a.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd A: {e}"))?; + + let channel_end_b = chains + .handle_b + .query_channel( + QueryChannelRequest { + port_id: channels.port_b.0.clone(), + channel_id: channels.channel_id_b.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd B: {e}"))?; + + let chain_driver_a = chains.node_a.chain_driver(); + let chain_driver_b = chains.node_b.chain_driver(); + + let denom_a = chains.node_a.denom(); + + let port_a = channels.port_a.as_ref(); + let channel_id_a = channels.channel_id_a.as_ref(); + + let wallets_a = chains.node_a.wallets(); + let wallets_b = chains.node_b.wallets(); + + let relayer_a = wallets_a.relayer(); + + let user_a = wallets_a.user1(); + let user_b = wallets_b.user1(); + + let balance_a1 = chain_driver_a.query_balance(&user_a.address(), &denom_a)?; + + let relayer_balance_a = chain_driver_a.query_balance(&relayer_a.address(), &denom_a)?; + + let send_amount = random_u128_range(1000, 2000); + let receive_fee = random_u128_range(300, 400); + let ack_fee = random_u128_range(200, 300); + let timeout_fee = random_u128_range(100, 200); + + let total_sent = send_amount + receive_fee + ack_fee + timeout_fee; + + let balance_a2 = balance_a1 - total_sent; + + let ics29_transfer = chain_driver_a.ibc_token_transfer_with_fee( + &port_a, + &channel_id_a, + &user_a, + &user_b.address(), + &denom_a.with_amount(send_amount).as_ref(), + &denom_a.with_amount(receive_fee).as_ref(), + &denom_a.with_amount(ack_fee).as_ref(), + &denom_a.with_amount(timeout_fee).as_ref(), + Duration::from_secs(60), + ); + + assert!(ics29_transfer.is_err(), "{ics29_transfer:?}"); + + let old_ordering = channel_end_a.ordering; + let old_connection_hops_a = channel_end_a.connection_hops; + let old_connection_hops_b = channel_end_b.connection_hops; + + let channel = channels.channel; + let new_version = Version::ics20_with_fee(); + + let upgraded_attrs = ChannelUpgradableAttributes::new( + new_version.clone(), + new_version.clone(), + old_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b, + Sequence::from(1), + ); + + info!("Will initialise upgrade handshake with governance proposal..."); + + chains.node_a.chain_driver().initialise_channel_upgrade( + channel.src_port_id().as_str(), + channel.src_channel_id().unwrap().as_str(), + old_ordering.as_str(), + old_connection_hops_a.first().unwrap().as_str(), + &serde_json::to_string(&new_version.0).unwrap(), + chains.handle_a().get_signer().unwrap().as_ref(), + "1", + )?; + + info!("Check that the channel upgrade successfully upgraded the version..."); + + assert_eventually_channel_upgrade_open( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + &upgraded_attrs, + )?; + + // Since the channel has been updated to ICS29 version after the Hermes instance + // was started, the `auto_register_counterparty_payee` has not registered the + // counterparty payee. It is required to register it manually. + chain_driver_b.register_counterparty_payee( + &wallets_b.relayer(), + &relayer_a.address(), + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + )?; + + { + let counterparty_payee = chain_driver_b.query_counterparty_payee( + &channels.channel_id_b.as_ref(), + &wallets_b.relayer().address(), + )?; + + assert_eq( + "counterparty address should match registered address", + &counterparty_payee, + &Some(relayer_a.address().cloned()), + )?; + } + + chain_driver_a.ibc_token_transfer_with_fee( + &port_a, + &channel_id_a, + &user_a, + &user_b.address(), + &denom_a.with_amount(send_amount).as_ref(), + &denom_a.with_amount(receive_fee).as_ref(), + &denom_a.with_amount(ack_fee).as_ref(), + &denom_a.with_amount(timeout_fee).as_ref(), + Duration::from_secs(60), + )?; + + let denom_b = derive_ibc_denom( + &channels.port_b.as_ref(), + &channels.channel_id_b.as_ref(), + &denom_a, + )?; + + chain_driver_b.assert_eventual_wallet_amount( + &user_b.address(), + &denom_b.with_amount(send_amount).as_ref(), + )?; + + chain_driver_a.assert_eventual_wallet_amount( + &user_a.address(), + &(balance_a2 + timeout_fee).as_ref(), + )?; + + chain_driver_a.assert_eventual_wallet_amount( + &relayer_a.address(), + &(relayer_balance_a + ack_fee + receive_fee).as_ref(), + )?; + + Ok(()) + } +} diff --git a/tools/integration-test/src/tests/channel_upgrade/mod.rs b/tools/integration-test/src/tests/channel_upgrade/mod.rs new file mode 100644 index 0000000000..2e40d3bd5e --- /dev/null +++ b/tools/integration-test/src/tests/channel_upgrade/mod.rs @@ -0,0 +1,6 @@ +pub mod flushing; +pub mod ica; +pub mod ics29; +pub mod timeout; +pub mod upgrade_handshake; +pub mod upgrade_handshake_steps; diff --git a/tools/integration-test/src/tests/channel_upgrade/timeout.rs b/tools/integration-test/src/tests/channel_upgrade/timeout.rs new file mode 100644 index 0000000000..42bdd288ed --- /dev/null +++ b/tools/integration-test/src/tests/channel_upgrade/timeout.rs @@ -0,0 +1,1067 @@ +//! Tests channel upgrade: +//! +//! - `ChannelUpgradeTimeoutAckHandshake` tests that the channel worker will timeout the +//! upgrade handshake if too much time passes before relaying the Upgrade Ack. +//! +//! - `ChannelUpgradeTimeoutConfirmHandshake` tests that the channel worker will timeout the +//! upgrade handshake if too much time passes before relaying the Upgrade Confirm. +//! +//! - `ChannelUpgradeManualTimeoutWhenFlushingHandshake` tests that the channel upgrade can be timed out +//! and cancelled if the packets take too much time to be flushed. +//! +//! - `ChannelUpgradeHandshakeTimeoutWhenFlushing` tests that the channel worker will timeout the +//! upgrade handshake if the counterparty does not finish flushing the packets before the upgrade timeout. +//! +//! - `ChannelUpgradeHandshakeTimeoutOnAck` tests that the channel worker will cancel the +//! upgrade handshake if the Ack step fails due to an upgrade timeout. +//! +//! - `ChannelUpgradeHandshakeTimeoutOnPacketAck` tests that the channel worker will cancel the +//! upgrade handshake if the chain acknowledges a packet after the upgrade timeout expired. +//! +//! +//! +use std::thread::sleep; + +use ibc_relayer::chain::requests::{IncludeProof, QueryChannelRequest, QueryHeight}; +use ibc_relayer_types::core::ics04_channel::channel::State as ChannelState; +use ibc_relayer_types::core::ics04_channel::packet::Sequence; +use ibc_relayer_types::core::ics04_channel::version::Version; +use ibc_relayer_types::events::IbcEventType; +use ibc_test_framework::chain::config::{set_max_deposit_period, set_voting_period}; +use ibc_test_framework::prelude::*; +use ibc_test_framework::relayer::channel::{ + assert_eventually_channel_established, assert_eventually_channel_upgrade_ack, + assert_eventually_channel_upgrade_cancel, assert_eventually_channel_upgrade_flushing, + assert_eventually_channel_upgrade_init, assert_eventually_channel_upgrade_try, + ChannelUpgradableAttributes, +}; + +#[test] +fn test_channel_upgrade_timeout_ack_handshake() -> Result<(), Error> { + run_binary_channel_test(&ChannelUpgradeTimeoutAckHandshake) +} + +#[test] +fn test_channel_upgrade_timeout_confirm_handshake() -> Result<(), Error> { + run_binary_channel_test(&ChannelUpgradeTimeoutConfirmHandshake) +} + +#[test] +fn test_channel_upgrade_manual_timeout_when_flushing() -> Result<(), Error> { + run_binary_channel_test(&ChannelUpgradeManualTimeoutWhenFlushing) +} + +#[test] +fn test_channel_upgrade_handshake_timeout_when_flushing() -> Result<(), Error> { + run_binary_channel_test(&ChannelUpgradeHandshakeTimeoutWhenFlushing) +} + +#[test] +fn test_channel_upgrade_handshake_timeout_on_ack() -> Result<(), Error> { + run_binary_channel_test(&ChannelUpgradeHandshakeTimeoutOnAck) +} + +#[test] +fn test_channel_upgrade_handshake_timeout_on_packet_ack() -> Result<(), Error> { + run_binary_channel_test(&ChannelUpgradeHandshakeTimeoutOnPacketAck) +} + +const MAX_DEPOSIT_PERIOD: &str = "10s"; +const VOTING_PERIOD: u64 = 10; + +struct ChannelUpgradeTestOverrides; + +impl TestOverrides for ChannelUpgradeTestOverrides { + 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)?; + Ok(()) + } + + fn modify_relayer_config(&self, config: &mut Config) { + config.mode.channels.enabled = true; + + config.mode.clients.misbehaviour = false; + } + + fn should_spawn_supervisor(&self) -> bool { + false + } +} + +struct ChannelUpgradeTimeoutAckHandshake; + +impl BinaryChannelTest for ChannelUpgradeTimeoutAckHandshake { + fn run( + &self, + _config: &TestConfig, + relayer: RelayerDriver, + chains: ConnectedChains, + channels: ConnectedChannel, + ) -> Result<(), Error> { + info!("Check that channels are both in OPEN State"); + + assert_eventually_channel_established( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + )?; + + let channel_end_a = chains + .handle_a + .query_channel( + QueryChannelRequest { + port_id: channels.port_a.0.clone(), + channel_id: channels.channel_id_a.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd A: {e}"))?; + + let channel_end_b = chains + .handle_b + .query_channel( + QueryChannelRequest { + port_id: channels.port_b.0.clone(), + channel_id: channels.channel_id_b.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd B: {e}"))?; + + let old_version = channel_end_a.version; + let old_ordering = channel_end_a.ordering; + let old_connection_hops_a = channel_end_a.connection_hops; + let old_connection_hops_b = channel_end_b.connection_hops; + + let channel = channels.channel; + let new_version = Version::ics20_with_fee(); + + let old_attrs = ChannelUpgradableAttributes::new( + old_version.clone(), + old_version.clone(), + old_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b.clone(), + Sequence::from(1), + ); + + info!("Will update channel params to set a short upgrade timeout..."); + + chains.node_b.chain_driver().update_channel_params( + 5000000000, + chains.handle_b().get_signer().unwrap().as_ref(), + "1", + )?; + + info!("Will initialise upgrade handshake with governance proposal..."); + + chains.node_a.chain_driver().initialise_channel_upgrade( + channel.src_port_id().as_str(), + channel.src_channel_id().unwrap().as_str(), + old_ordering.as_str(), + old_connection_hops_a.first().unwrap().as_str(), + &serde_json::to_string(&new_version.0).unwrap(), + chains.handle_a().get_signer().unwrap().as_ref(), + "1", + )?; + + info!("Will run ChanUpgradeTry step..."); + + channel.build_chan_upgrade_try_and_send()?; + + info!("Check that the step ChanUpgradeTry was correctly executed..."); + + assert_eventually_channel_upgrade_try( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + &old_attrs.flipped(), + )?; + + std::thread::sleep(Duration::from_secs(10)); + + info!("Check that the channel upgrade was successfully cancelled..."); + + // This will assert that both channel ends are eventually + // in Open state, and that the fields have not changed. + relayer.with_supervisor(|| { + assert_eventually_channel_upgrade_cancel( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + &old_attrs, + )?; + + Ok(()) + }) + } +} + +struct ChannelUpgradeTimeoutConfirmHandshake; + +impl BinaryChannelTest for ChannelUpgradeTimeoutConfirmHandshake { + fn run( + &self, + _config: &TestConfig, + relayer: RelayerDriver, + chains: ConnectedChains, + channels: ConnectedChannel, + ) -> Result<(), Error> { + info!("Check that channels are both in OPEN State"); + + assert_eventually_channel_established( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + )?; + + let channel_end_a = chains + .handle_a + .query_channel( + QueryChannelRequest { + port_id: channels.port_a.0.clone(), + channel_id: channels.channel_id_a.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd A: {e}"))?; + + let channel_end_b = chains + .handle_b + .query_channel( + QueryChannelRequest { + port_id: channels.port_b.0.clone(), + channel_id: channels.channel_id_b.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd B: {e}"))?; + + let old_version = channel_end_a.version; + let old_ordering = channel_end_a.ordering; + let old_connection_hops_a = channel_end_a.connection_hops; + let old_connection_hops_b = channel_end_b.connection_hops; + + let channel = channels.channel; + let new_version = Version::ics20_with_fee(); + + let old_attrs = ChannelUpgradableAttributes::new( + old_version.clone(), + old_version.clone(), + old_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b.clone(), + Sequence::from(1), + ); + + info!("Will update channel params to set a short upgrade timeout..."); + + chains.node_a.chain_driver().update_channel_params( + 5000000000, + chains.handle_a().get_signer().unwrap().as_ref(), + "1", + )?; + + info!("Will initialise upgrade handshake with governance proposal..."); + + chains.node_a.chain_driver().initialise_channel_upgrade( + channel.src_port_id().as_str(), + channel.src_channel_id().unwrap().as_str(), + old_ordering.as_str(), + old_connection_hops_a.first().unwrap().as_str(), + &serde_json::to_string(&new_version.0).unwrap(), + chains.handle_a().get_signer().unwrap().as_ref(), + "2", + )?; + + info!("Will run ChanUpgradeTry step..."); + + channel.build_chan_upgrade_try_and_send()?; + + info!("Check that the step ChanUpgradeTry was correctly executed..."); + + assert_eventually_channel_upgrade_try( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + &old_attrs.flipped(), + )?; + + info!("Will run ChanUpgradeAck step..."); + + channel.flipped().build_chan_upgrade_ack_and_send()?; + + info!("Check that the step ChanUpgradeAck was correctly executed..."); + + assert_eventually_channel_upgrade_ack( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + ChannelState::FlushComplete, + ChannelState::Flushing, + &old_attrs, + )?; + + std::thread::sleep(Duration::from_secs(10)); + + info!("Check that the channel upgrade was successfully cancelled..."); + + // This will assert that both channel ends are eventually + // in Open state, and that the fields have not changed. + relayer.with_supervisor(|| { + assert_eventually_channel_upgrade_cancel( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + &old_attrs, + )?; + + Ok(()) + }) + } +} + +struct ChannelUpgradeHandshakeTimeoutWhenFlushing; + +impl BinaryChannelTest for ChannelUpgradeHandshakeTimeoutWhenFlushing { + fn run( + &self, + _config: &TestConfig, + relayer: RelayerDriver, + chains: ConnectedChains, + channels: ConnectedChannel, + ) -> Result<(), Error> { + info!("Check that channels are both in OPEN State"); + + assert_eventually_channel_established( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + )?; + + let channel_end_a = chains + .handle_a + .query_channel( + QueryChannelRequest { + port_id: channels.port_a.0.clone(), + channel_id: channels.channel_id_a.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd A: {e}"))?; + + let channel_end_b = chains + .handle_b + .query_channel( + QueryChannelRequest { + port_id: channels.port_b.0.clone(), + channel_id: channels.channel_id_b.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd B: {e}"))?; + + let old_version = channel_end_a.version; + let old_ordering = channel_end_a.ordering; + let old_connection_hops_a = channel_end_a.connection_hops; + let old_connection_hops_b = channel_end_b.connection_hops; + + let channel = channels.channel; + let new_version = Version::ics20_with_fee(); + + let old_attrs = ChannelUpgradableAttributes::new( + old_version.clone(), + old_version.clone(), + old_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b.clone(), + Sequence::from(1), + ); + + info!("Will update channel params to set a shorter upgrade timeout..."); + + // the upgrade timeout should be long enough for chain a + // to complete Ack successfully so that it goes into `FLUSHING` + chains.node_b.chain_driver().update_channel_params( + 25000000000, + chains.handle_b().get_signer().unwrap().as_ref(), + "1", + )?; + + info!("Will initialise upgrade handshake with governance proposal..."); + + chains.node_a.chain_driver().initialise_channel_upgrade( + channel.src_port_id().as_str(), + channel.src_channel_id().unwrap().as_str(), + old_ordering.as_str(), + old_connection_hops_a.first().unwrap().as_str(), + &serde_json::to_string(&new_version.0).unwrap(), + chains.handle_a().get_signer().unwrap().as_ref(), + "1", + )?; + + info!("Will run ChanUpgradeTry step..."); + + channel.build_chan_upgrade_try_and_send()?; + + info!("Check that the step ChanUpgradeTry was correctly executed..."); + + assert_eventually_channel_upgrade_try( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + &old_attrs.flipped(), + )?; + + // send a IBC transfer message from chain a to chain b + // so that we have an in-flight packet and chain a + // will move to `FLUSHING` during Ack + 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 a_to_b_amount = 12345u64; + + info!( + "Sending IBC transfer from chain {} to chain {} with amount of {} {}", + chains.chain_id_a(), + chains.chain_id_b(), + a_to_b_amount, + denom_a + ); + + chains.node_a.chain_driver().ibc_transfer_token( + &channels.port_a.as_ref(), + &channels.channel_id_a.as_ref(), + &wallet_a.as_ref(), + &wallet_b.address(), + &denom_a.with_amount(a_to_b_amount).as_ref(), + )?; + + info!("Will run ChanUpgradeAck step..."); + + channel.flipped().build_chan_upgrade_ack_and_send()?; + + info!("Check that the step ChanUpgradeAck was correctly executed..."); + + assert_eventually_channel_upgrade_flushing( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + &old_attrs, + )?; + + // wait enough time so that timeout expires while chain a is in FLUSHING + sleep(Duration::from_nanos(35000000000)); + + info!("Will run ChanUpgradeTimeout step..."); + + // Since the chain a has not moved to `FLUSH_COMPLETE` before the upgrade timeout + // expired, then we can submit `MsgChannelUpgradeTimeout` on chain b + // to cancel the upgrade and move the channel back to `OPEN` + let timeout_event = channel.build_chan_upgrade_timeout_and_send()?; + assert_eq!( + timeout_event.event_type(), + IbcEventType::UpgradeTimeoutChannel + ); + + relayer.with_supervisor(|| { + info!("Check that the step ChanUpgradeTimeout was correctly executed..."); + + assert_eventually_channel_upgrade_cancel( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + &old_attrs.flipped(), + )?; + + Ok(()) + }) + } +} + +struct ChannelUpgradeManualTimeoutWhenFlushing; + +impl BinaryChannelTest for ChannelUpgradeManualTimeoutWhenFlushing { + fn run( + &self, + _config: &TestConfig, + _relayer: RelayerDriver, + chains: ConnectedChains, + channels: ConnectedChannel, + ) -> Result<(), Error> { + info!("Check that channels are both in OPEN State"); + + assert_eventually_channel_established( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + )?; + + let channel_end_a = chains + .handle_a + .query_channel( + QueryChannelRequest { + port_id: channels.port_a.0.clone(), + channel_id: channels.channel_id_a.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd A: {e}"))?; + + let channel_end_b = chains + .handle_b + .query_channel( + QueryChannelRequest { + port_id: channels.port_b.0.clone(), + channel_id: channels.channel_id_b.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd B: {e}"))?; + + let old_version = channel_end_a.version; + let old_ordering = channel_end_a.ordering; + let old_connection_hops_a = channel_end_a.connection_hops; + let old_connection_hops_b = channel_end_b.connection_hops; + + let channel = channels.channel; + let new_version = Version::ics20_with_fee(); + + let old_attrs = ChannelUpgradableAttributes::new( + old_version.clone(), + old_version.clone(), + old_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b.clone(), + Sequence::from(1), + ); + + info!("Will update channel params to set a shorter upgrade timeout..."); + + // the upgrade timeout should be long enough for chain a + // to complete Ack successfully so that it goes into `FLUSHING` + chains.node_b.chain_driver().update_channel_params( + 25000000000, + chains.handle_b().get_signer().unwrap().as_ref(), + "1", + )?; + + info!("Will initialise upgrade handshake with governance proposal..."); + + chains.node_a.chain_driver().initialise_channel_upgrade( + channel.src_port_id().as_str(), + channel.src_channel_id().unwrap().as_str(), + old_ordering.as_str(), + old_connection_hops_a.first().unwrap().as_str(), + &serde_json::to_string(&new_version.0).unwrap(), + chains.handle_a().get_signer().unwrap().as_ref(), + "1", + )?; + + info!("Check that the step ChanUpgradeInit was correctly executed..."); + + assert_eventually_channel_upgrade_init( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + &old_attrs, + )?; + + info!("Will run ChanUpgradeTry step..."); + + channel.build_chan_upgrade_try_and_send()?; + + info!("Check that the step ChanUpgradeTry was correctly executed..."); + + assert_eventually_channel_upgrade_try( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + &old_attrs.flipped(), + )?; + + // send a IBC transfer message from chain a to chain b + // so that we have an in-flight packet and chain a + // will move to `FLUSHING` during Ack + 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 a_to_b_amount = 12345u128; + + info!( + "Sending IBC transfer from chain {} to chain {} with amount of {} {}", + chains.chain_id_a(), + chains.chain_id_b(), + a_to_b_amount, + denom_a + ); + + chains.node_a.chain_driver().ibc_transfer_token( + &channels.port_a.as_ref(), + &channels.channel_id_a.as_ref(), + &wallet_a.as_ref(), + &wallet_b.address(), + &denom_a.with_amount(a_to_b_amount).as_ref(), + )?; + + info!("Will run ChanUpgradeAck step..."); + + channel.flipped().build_chan_upgrade_ack_and_send()?; + + info!("Check that the step ChanUpgradeAck was correctly executed..."); + + assert_eventually_channel_upgrade_flushing( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + &old_attrs, + )?; + + // wait enough time so that timeout expires while chain a is in FLUSHING + sleep(Duration::from_nanos(35000000000)); + + info!("Will run ChanUpgradeTimeout step..."); + + // Since the chain a has not moved to `FLUSH_COMPLETE` before the upgrade timeout + // expired, then we can submit `MsgChannelUpgradeTimeout` on chain b + // to cancel the upgrade and move the channel back to `OPEN` + let timeout_event = channel.build_chan_upgrade_timeout_and_send()?; + assert_eq!( + timeout_event.event_type(), + IbcEventType::UpgradeTimeoutChannel + ); + + let cancel_event = channel.flipped().build_chan_upgrade_cancel_and_send()?; + assert_eq!( + cancel_event.event_type(), + IbcEventType::UpgradeCancelChannel + ); + + info!("Check that the step ChanUpgradeTimeout was correctly executed..."); + + assert_eventually_channel_upgrade_cancel( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + &old_attrs.flipped(), + )?; + + Ok(()) + } +} + +struct ChannelUpgradeHandshakeTimeoutOnAck; + +impl BinaryChannelTest for ChannelUpgradeHandshakeTimeoutOnAck { + fn run( + &self, + _config: &TestConfig, + _relayer: RelayerDriver, + chains: ConnectedChains, + channels: ConnectedChannel, + ) -> Result<(), Error> { + info!("Check that channels are both in OPEN State"); + + assert_eventually_channel_established( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + )?; + + let channel_end_a = chains + .handle_a + .query_channel( + QueryChannelRequest { + port_id: channels.port_a.0.clone(), + channel_id: channels.channel_id_a.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd A: {e}"))?; + + let channel_end_b = chains + .handle_b + .query_channel( + QueryChannelRequest { + port_id: channels.port_b.0.clone(), + channel_id: channels.channel_id_b.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd B: {e}"))?; + + let old_version = channel_end_a.version; + let old_ordering = channel_end_a.ordering; + let old_connection_hops_a = channel_end_a.connection_hops; + let old_connection_hops_b = channel_end_b.connection_hops; + + let channel = channels.channel; + let new_version = Version::ics20_with_fee(); + + let old_attrs = ChannelUpgradableAttributes::new( + old_version.clone(), + old_version.clone(), + old_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b.clone(), + Sequence::from(1), + ); + + info!("Will update channel params to set a short upgrade timeout..."); + + chains.node_b.chain_driver().update_channel_params( + 5000000000, + chains.handle_b().get_signer().unwrap().as_ref(), + "1", + )?; + + info!("Will initialise upgrade handshake with governance proposal..."); + + chains.node_a.chain_driver().initialise_channel_upgrade( + channel.src_port_id().as_str(), + channel.src_channel_id().unwrap().as_str(), + old_ordering.as_str(), + old_connection_hops_a.first().unwrap().as_str(), + &serde_json::to_string(&new_version.0).unwrap(), + chains.handle_a().get_signer().unwrap().as_ref(), + "1", + )?; + + info!("Check that the step ChanUpgradeInit was correctly executed..."); + + assert_eventually_channel_upgrade_init( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + &old_attrs, + )?; + + info!("Will run ChanUpgradeTry step..."); + + channel.build_chan_upgrade_try_and_send()?; + + info!("Check that the step ChanUpgradeTry was correctly executed..."); + + assert_eventually_channel_upgrade_try( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + &old_attrs.flipped(), + )?; + + // wait enough time so that ACK fails due to upgrade timeout + sleep(Duration::from_secs(10)); + + info!("Will run ChanUpgradeAck step..."); + + let ack_event = channel.flipped().build_chan_upgrade_ack_and_send()?; + + info!("Check that the step ChanUpgradeAck timed out..."); + + // ACK should fail because the upgrade has timed out + assert_eq!(ack_event.event_type(), IbcEventType::UpgradeErrorChannel); + + info!("Will run ChanUpgradeCancel step..."); + + // Since the following assertion checks that the fields of channel ends + // have not been updated, asserting there is a `UpgradeCancelChannel` event + // avoids having a passing test due to the Upgrade Init step failing + let cancel_event = channel.build_chan_upgrade_cancel_and_send()?; + assert_eq!( + cancel_event.event_type(), + IbcEventType::UpgradeCancelChannel + ); + + info!("Check that the step ChanUpgradeCancel was correctly executed..."); + + assert_eventually_channel_upgrade_cancel( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + &old_attrs.flipped(), + )?; + + Ok(()) + } +} + +struct ChannelUpgradeHandshakeTimeoutOnPacketAck; + +impl BinaryChannelTest for ChannelUpgradeHandshakeTimeoutOnPacketAck { + fn run( + &self, + _config: &TestConfig, + relayer: RelayerDriver, + chains: ConnectedChains, + channels: ConnectedChannel, + ) -> Result<(), Error> { + info!("Check that channels are both in OPEN State"); + + assert_eventually_channel_established( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + )?; + + let channel_end_a = chains + .handle_a + .query_channel( + QueryChannelRequest { + port_id: channels.port_a.0.clone(), + channel_id: channels.channel_id_a.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd A: {e}"))?; + + let channel_end_b = chains + .handle_b + .query_channel( + QueryChannelRequest { + port_id: channels.port_b.0.clone(), + channel_id: channels.channel_id_b.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd B: {e}"))?; + + let old_version = channel_end_a.version; + let old_ordering = channel_end_a.ordering; + let old_connection_hops_a = channel_end_a.connection_hops; + let old_connection_hops_b = channel_end_b.connection_hops; + + let channel = channels.channel; + let new_version = Version::ics20_with_fee(); + + let old_attrs = ChannelUpgradableAttributes::new( + old_version.clone(), + old_version.clone(), + old_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b.clone(), + Sequence::from(1), + ); + + info!("Will update channel params to set a short upgrade timeout..."); + + // the upgrade timeout should be long enough for chain a + // to complete Ack successfully so that it goes into `FLUSHING` + chains.node_b.chain_driver().update_channel_params( + 80000000000, + chains.handle_b().get_signer().unwrap().as_ref(), + "1", + )?; + + info!("Will initialise upgrade handshake with governance proposal..."); + + chains.node_a.chain_driver().initialise_channel_upgrade( + channel.src_port_id().as_str(), + channel.src_channel_id().unwrap().as_str(), + old_ordering.as_str(), + old_connection_hops_a.first().unwrap().as_str(), + &serde_json::to_string(&new_version.0).unwrap(), + chains.handle_a().get_signer().unwrap().as_ref(), + "1", + )?; + + info!("Check that the step ChanUpgradeInit was correctly executed..."); + + assert_eventually_channel_upgrade_init( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + &old_attrs, + )?; + + // send a IBC transfer message from chain a to chain b + // so that we have an in-flight packet and chain a + // will move to `FLUSHING` during Ack + 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 a_to_b_amount = 12345u128; + + info!( + "Sending IBC transfer from chain {} to chain {} with amount of {} {}", + chains.chain_id_a(), + chains.chain_id_b(), + a_to_b_amount, + denom_a + ); + + chains + .node_a + .chain_driver() + .ibc_transfer_token_with_memo_and_timeout( + &channels.port_a.as_ref(), + &channels.channel_id_a.as_ref(), + &wallet_a.as_ref(), + &wallet_b.address(), + &denom_a.with_amount(a_to_b_amount).as_ref(), + None, + Some(Duration::from_secs(600)), + )?; + + info!("Will run ChanUpgradeTry step..."); + + channel.build_chan_upgrade_try_and_send()?; + + info!("Check that the step ChanUpgradeTry was correctly executed..."); + + assert_eventually_channel_upgrade_try( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + &old_attrs.flipped(), + )?; + + info!("Will run ChanUpgradeAck step..."); + + channel.flipped().build_chan_upgrade_ack_and_send()?; + + info!("Check that the step ChanUpgradeAck was correctly executed..."); + + // channel a is `FLUSHING` because the packet + // from a to b has not been cleared yet + assert_eventually_channel_upgrade_ack( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + ChannelState::Flushing, + ChannelState::Flushing, + &old_attrs, + )?; + + // wait enough time so that timeout expires while chain a is in FLUSHING + // and when packet lifecycle completes with acknowledge packet on chain a + // it will abort the upgrade + sleep(Duration::from_nanos(80000000000)); + + info!("Check that the channel upgrade aborted..."); + + // start supervisor to clear in-flight packets + // and move channel ends to `FLUSH_COMPLETE` + relayer.with_supervisor(|| { + let ibc_denom_b = derive_ibc_denom( + &channels.port_b.as_ref(), + &channels.channel_id_b.as_ref(), + &denom_a, + )?; + + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &wallet_b.address(), + &ibc_denom_b.with_amount(a_to_b_amount).as_ref(), + )?; + + // This will assert that both channel ends are eventually + // in Open state, and that the fields targeted by the upgrade + // have NOT been correctly updated, because chain a aborted the upgrade + assert_eventually_channel_upgrade_cancel( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + &old_attrs, + )?; + + Ok(()) + }) + } +} + +impl HasOverrides for ChannelUpgradeTimeoutAckHandshake { + type Overrides = ChannelUpgradeTestOverrides; + + fn get_overrides(&self) -> &ChannelUpgradeTestOverrides { + &ChannelUpgradeTestOverrides + } +} + +impl HasOverrides for ChannelUpgradeTimeoutConfirmHandshake { + type Overrides = ChannelUpgradeTestOverrides; + + fn get_overrides(&self) -> &ChannelUpgradeTestOverrides { + &ChannelUpgradeTestOverrides + } +} + +impl HasOverrides for ChannelUpgradeManualTimeoutWhenFlushing { + type Overrides = ChannelUpgradeTestOverrides; + + fn get_overrides(&self) -> &ChannelUpgradeTestOverrides { + &ChannelUpgradeTestOverrides + } +} + +impl HasOverrides for ChannelUpgradeHandshakeTimeoutWhenFlushing { + type Overrides = ChannelUpgradeTestOverrides; + + fn get_overrides(&self) -> &ChannelUpgradeTestOverrides { + &ChannelUpgradeTestOverrides + } +} + +impl HasOverrides for ChannelUpgradeHandshakeTimeoutOnAck { + type Overrides = ChannelUpgradeTestOverrides; + + fn get_overrides(&self) -> &ChannelUpgradeTestOverrides { + &ChannelUpgradeTestOverrides + } +} + +impl HasOverrides for ChannelUpgradeHandshakeTimeoutOnPacketAck { + type Overrides = ChannelUpgradeTestOverrides; + + fn get_overrides(&self) -> &ChannelUpgradeTestOverrides { + &ChannelUpgradeTestOverrides + } +} diff --git a/tools/integration-test/src/tests/channel_upgrade/upgrade_handshake.rs b/tools/integration-test/src/tests/channel_upgrade/upgrade_handshake.rs new file mode 100644 index 0000000000..1a8dbe27ed --- /dev/null +++ b/tools/integration-test/src/tests/channel_upgrade/upgrade_handshake.rs @@ -0,0 +1,247 @@ +//! Tests channel upgrade: +//! +//! - `ChannelUpgradeHandshake` tests that after the upgrade handshake is completed +//! after initialising the upgrade with `build_chan_upgrade_init_and_send` without +//! any in-flight packets. +//! +//! - `ChannelUpgradeClearHandshake` tests that if the upgrade handshake is initialised +//! before the relayer, the upgrade will complete upon starting the relayer. +use std::thread::sleep; + +use ibc_relayer::chain::requests::{IncludeProof, QueryChannelRequest, QueryHeight}; +use ibc_relayer_types::core::ics04_channel::packet::Sequence; +use ibc_relayer_types::core::ics04_channel::version::Version; +use ibc_test_framework::chain::config::{set_max_deposit_period, set_voting_period}; +use ibc_test_framework::prelude::*; +use ibc_test_framework::relayer::channel::{ + assert_eventually_channel_established, assert_eventually_channel_upgrade_open, + ChannelUpgradableAttributes, +}; + +#[test] +fn test_channel_upgrade_handshake() -> Result<(), Error> { + run_binary_channel_test(&ChannelUpgradeHandshake) +} + +#[test] +fn test_channel_upgrade_clear_handshake() -> Result<(), Error> { + run_binary_channel_test(&ChannelUpgradeClearHandshake) +} + +const MAX_DEPOSIT_PERIOD: &str = "10s"; +const VOTING_PERIOD: u64 = 10; + +pub struct ChannelUpgradeHandshake; + +impl TestOverrides for ChannelUpgradeHandshake { + fn modify_relayer_config(&self, config: &mut Config) { + config.mode.channels.enabled = true; + config.mode.clients.misbehaviour = false; + } + + 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)?; + Ok(()) + } +} + +impl BinaryChannelTest for ChannelUpgradeHandshake { + fn run( + &self, + _config: &TestConfig, + _relayer: RelayerDriver, + chains: ConnectedChains, + channels: ConnectedChannel, + ) -> Result<(), Error> { + info!("Check that channels are both in OPEN State"); + + assert_eventually_channel_established( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + )?; + + let channel_end_a = chains + .handle_a + .query_channel( + QueryChannelRequest { + port_id: channels.port_a.0.clone(), + channel_id: channels.channel_id_a.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd A: {e}"))?; + + let channel_end_b = chains + .handle_b + .query_channel( + QueryChannelRequest { + port_id: channels.port_b.0.clone(), + channel_id: channels.channel_id_b.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd B: {e}"))?; + + let old_ordering = channel_end_a.ordering; + let old_connection_hops_a = channel_end_a.connection_hops; + let old_connection_hops_b = channel_end_b.connection_hops; + + let channel = channels.channel; + let new_version = Version::ics20_with_fee(); + + let upgraded_attrs = ChannelUpgradableAttributes::new( + new_version.clone(), + new_version.clone(), + old_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b, + Sequence::from(1), + ); + + info!("Will initialise upgrade handshake with governance proposal..."); + + chains.node_a.chain_driver().initialise_channel_upgrade( + channel.src_port_id().as_str(), + channel.src_channel_id().unwrap().as_str(), + old_ordering.as_str(), + old_connection_hops_a.first().unwrap().as_str(), + &serde_json::to_string(&new_version.0).unwrap(), + &chains.node_a.wallets().user2().address().to_string(), + "1", + )?; + + info!("Check that the channel upgrade successfully upgraded the version..."); + + // This will assert that both channel ends are eventually + // in Open state, and that the fields targeted by the upgrade + // have been correctly updated. + assert_eventually_channel_upgrade_open( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + &upgraded_attrs, + )?; + + Ok(()) + } +} + +pub struct ChannelUpgradeClearHandshake; + +impl TestOverrides for ChannelUpgradeClearHandshake { + fn modify_relayer_config(&self, config: &mut Config) { + config.mode.channels.enabled = true; + config.mode.clients.misbehaviour = false; + } + + 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)?; + Ok(()) + } + + fn should_spawn_supervisor(&self) -> bool { + false + } +} + +impl BinaryChannelTest for ChannelUpgradeClearHandshake { + fn run( + &self, + _config: &TestConfig, + relayer: RelayerDriver, + chains: ConnectedChains, + channels: ConnectedChannel, + ) -> Result<(), Error> { + info!("Check that channels are both in OPEN State"); + + assert_eventually_channel_established( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + )?; + + let channel_end_a = chains + .handle_a + .query_channel( + QueryChannelRequest { + port_id: channels.port_a.0.clone(), + channel_id: channels.channel_id_a.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd A: {e}"))?; + + let channel_end_b = chains + .handle_b + .query_channel( + QueryChannelRequest { + port_id: channels.port_b.0.clone(), + channel_id: channels.channel_id_b.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd B: {e}"))?; + + let old_ordering = channel_end_a.ordering; + let old_connection_hops_a = channel_end_a.connection_hops; + let old_connection_hops_b = channel_end_b.connection_hops; + + let channel = channels.channel; + let new_version = Version::ics20_with_fee(); + + let upgraded_attrs = ChannelUpgradableAttributes::new( + new_version.clone(), + new_version.clone(), + old_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b, + Sequence::from(1), + ); + + info!("Will initialise upgrade handshake with governance proposal..."); + + chains.node_a.chain_driver().initialise_channel_upgrade( + channel.src_port_id().as_str(), + channel.src_channel_id().unwrap().as_str(), + old_ordering.as_str(), + old_connection_hops_a.first().unwrap().as_str(), + &serde_json::to_string(&new_version.0).unwrap(), + chains.handle_a().get_signer().unwrap().as_ref(), + "1", + )?; + + // After the governance proposal, wait a few blocks before starting the Hermes instance + sleep(Duration::from_secs(5)); + + info!("Check that the channel upgrade successfully upgraded the version..."); + + relayer.with_supervisor(|| { + // This will assert that both channel ends are eventually + // in Open state, and that the fields targeted by the upgrade + // have been correctly updated. + assert_eventually_channel_upgrade_open( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + &upgraded_attrs, + )?; + + Ok(()) + }) + } +} diff --git a/tools/integration-test/src/tests/channel_upgrade/upgrade_handshake_steps.rs b/tools/integration-test/src/tests/channel_upgrade/upgrade_handshake_steps.rs new file mode 100644 index 0000000000..31b665bc9a --- /dev/null +++ b/tools/integration-test/src/tests/channel_upgrade/upgrade_handshake_steps.rs @@ -0,0 +1,915 @@ +//! Tests channel upgrade: +//! +//! - `ChannelUpgradeManualHandshake` tests each step of the channel upgrade manually, +//! without relaying on the supervisor. +//! +//! - `ChannelUpgradeHandshakeFromTry` tests that the channel worker will finish the +//! upgrade handshake if the channel is being upgraded and is at the Try step. +//! +//! - `ChannelUpgradeHandshakeFromAck` tests that the channel worker will finish the +//! upgrade handshake if the channel is being upgraded and is at the Ack step. +//! +//! - `ChannelUpgradeHandshakeFromConfirm` tests that the channel worker will finish the +//! upgrade handshake if the channel is being upgraded and is at the Confirm step. +//! +//! - `ChannelUpgradeHandshakeTimeoutOnAck` tests that the channel worker will cancel the +//! upgrade handshake if the Ack step fails due to an upgrade timeout. +//! +//! - `ChannelUpgradeHandshakeTimeoutWhenFlushing` tests that the channel worker will timeout the +//! upgrade handshake if the counterparty does not finish flushing the packets before the upgrade timeout. +//! +//! - `ChannelUpgradeHandshakeInitiateNewUpgrade` tests that the channel worker will +//! finish the upgrade handshake if the side that moved to `OPEN` initiates a +//! new upgrade before the counterparty moved to `OPEN`. +//! +//! - `ChannelUpgradeHandshakeTimeoutOnPacketAck` tests that the channel worker will cancel the +//! upgrade handshake if the chain acknowledges a packet after the upgrade timeout expired. + +use ibc_relayer::chain::requests::{IncludeProof, QueryChannelRequest, QueryHeight}; +use ibc_relayer_types::core::ics04_channel::channel::{State as ChannelState, UpgradeState}; +use ibc_relayer_types::core::ics04_channel::packet::Sequence; +use ibc_relayer_types::core::ics04_channel::version::Version; +use ibc_test_framework::chain::config::{set_max_deposit_period, set_voting_period}; +use ibc_test_framework::prelude::*; +use ibc_test_framework::relayer::channel::{ + assert_eventually_channel_established, assert_eventually_channel_upgrade_ack, + assert_eventually_channel_upgrade_confirm, assert_eventually_channel_upgrade_init, + assert_eventually_channel_upgrade_open, assert_eventually_channel_upgrade_try, + ChannelUpgradableAttributes, +}; + +#[test] +fn test_channel_upgrade_manual_handshake() -> Result<(), Error> { + run_binary_channel_test(&ChannelUpgradeManualHandshake) +} + +#[test] +fn test_channel_upgrade_handshake_from_try() -> Result<(), Error> { + run_binary_channel_test(&ChannelUpgradeHandshakeFromTry) +} + +#[test] +fn test_channel_upgrade_handshake_from_ack() -> Result<(), Error> { + run_binary_channel_test(&ChannelUpgradeHandshakeFromAck) +} + +#[test] +fn test_channel_upgrade_handshake_from_confirm() -> Result<(), Error> { + run_binary_channel_test(&ChannelUpgradeHandshakeFromConfirm) +} + +#[test] +fn test_channel_upgrade_handshake_initiate_new_upgrade() -> Result<(), Error> { + run_binary_channel_test(&ChannelUpgradeHandshakeInitiateNewUpgrade) +} + +const MAX_DEPOSIT_PERIOD: &str = "10s"; +const VOTING_PERIOD: u64 = 10; + +struct ChannelUpgradeTestOverrides; + +impl TestOverrides for ChannelUpgradeTestOverrides { + 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)?; + Ok(()) + } + + fn modify_relayer_config(&self, config: &mut Config) { + config.mode.channels.enabled = true; + + config.mode.clients.misbehaviour = false; + } + + fn should_spawn_supervisor(&self) -> bool { + false + } +} + +struct ChannelUpgradeManualHandshake; + +impl BinaryChannelTest for ChannelUpgradeManualHandshake { + fn run( + &self, + _config: &TestConfig, + _relayer: RelayerDriver, + chains: ConnectedChains, + channels: ConnectedChannel, + ) -> Result<(), Error> { + info!("Check that channels are both in OPEN State"); + + assert_eventually_channel_established( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + )?; + + let channel_end_a = chains + .handle_a + .query_channel( + QueryChannelRequest { + port_id: channels.port_a.0.clone(), + channel_id: channels.channel_id_a.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd A: {e}"))?; + + let channel_end_b = chains + .handle_b + .query_channel( + QueryChannelRequest { + port_id: channels.port_b.0.clone(), + channel_id: channels.channel_id_b.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd B: {e}"))?; + + let old_version = channel_end_a.version; + let old_ordering = channel_end_a.ordering; + let old_connection_hops_a = channel_end_a.connection_hops; + let old_connection_hops_b = channel_end_b.connection_hops; + + let channel = channels.channel; + let new_version = Version::ics20_with_fee(); + + let old_attrs = ChannelUpgradableAttributes::new( + old_version.clone(), + old_version.clone(), + old_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b.clone(), + Sequence::from(1), + ); + + let interm_attrs = ChannelUpgradableAttributes::new( + old_version, + new_version.clone(), + old_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b.clone(), + Sequence::from(1), + ); + + let upgraded_attrs = ChannelUpgradableAttributes::new( + new_version.clone(), + new_version.clone(), + old_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b, + Sequence::from(1), + ); + + info!("Will initialise upgrade handshake with governance proposal..."); + + chains.node_a.chain_driver().initialise_channel_upgrade( + channel.src_port_id().as_str(), + channel.src_channel_id().unwrap().as_str(), + old_ordering.as_str(), + old_connection_hops_a.first().unwrap().as_str(), + &serde_json::to_string(&new_version.0).unwrap(), + chains.handle_a().get_signer().unwrap().as_ref(), + "1", + )?; + + info!("Check that the step ChanUpgradeInit was correctly executed..."); + + assert_eventually_channel_upgrade_init( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + &old_attrs, + )?; + + info!("Will run ChanUpgradeTry step..."); + + channel.build_chan_upgrade_try_and_send()?; + + info!("Check that the step ChanUpgradeTry was correctly executed..."); + + assert_eventually_channel_upgrade_try( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + &old_attrs.flipped(), + )?; + + info!("Will run ChanUpgradeAck step..."); + + channel.flipped().build_chan_upgrade_ack_and_send()?; + + info!("Check that the step ChanUpgradeAck was correctly executed..."); + + assert_eventually_channel_upgrade_ack( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + ChannelState::FlushComplete, + ChannelState::Flushing, + &old_attrs, + )?; + + info!("Will run ChanUpgradeConfirm step..."); + + channel.build_chan_upgrade_confirm_and_send()?; + + info!("Check that the step ChanUpgradeConfirm was correctly executed..."); + + assert_eventually_channel_upgrade_confirm( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + &interm_attrs.flipped(), + )?; + + info!("Will run ChanUpgradeOpen step..."); + + channel.flipped().build_chan_upgrade_open_and_send()?; + + info!("Check that the ChanUpgradeOpen steps were correctly executed..."); + + // This will assert that both channel ends are eventually + // in Open state, and that the fields targeted by the upgrade + // have been correctly updated. + assert_eventually_channel_upgrade_open( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + &upgraded_attrs, + )?; + + Ok(()) + } +} + +struct ChannelUpgradeHandshakeFromTry; + +impl BinaryChannelTest for ChannelUpgradeHandshakeFromTry { + fn run( + &self, + _config: &TestConfig, + relayer: RelayerDriver, + chains: ConnectedChains, + channels: ConnectedChannel, + ) -> Result<(), Error> { + info!("Check that channels are both in OPEN State"); + + assert_eventually_channel_established( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + )?; + + let channel_end_a = chains + .handle_a + .query_channel( + QueryChannelRequest { + port_id: channels.port_a.0.clone(), + channel_id: channels.channel_id_a.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd A: {e}"))?; + + let channel_end_b = chains + .handle_b + .query_channel( + QueryChannelRequest { + port_id: channels.port_b.0.clone(), + channel_id: channels.channel_id_b.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd B: {e}"))?; + + let old_version = channel_end_a.version; + let old_ordering = channel_end_a.ordering; + let old_connection_hops_a = channel_end_a.connection_hops; + let old_connection_hops_b = channel_end_b.connection_hops; + + let channel = channels.channel; + let new_version = Version::ics20_with_fee(); + + let old_attrs = ChannelUpgradableAttributes::new( + old_version.clone(), + old_version.clone(), + old_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b.clone(), + Sequence::from(1), + ); + + let upgraded_attrs = ChannelUpgradableAttributes::new( + new_version.clone(), + new_version.clone(), + old_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b, + Sequence::from(1), + ); + + info!("Will initialise upgrade handshake with governance proposal..."); + + chains.node_a.chain_driver().initialise_channel_upgrade( + channel.src_port_id().as_str(), + channel.src_channel_id().unwrap().as_str(), + old_ordering.as_str(), + old_connection_hops_a.first().unwrap().as_str(), + &serde_json::to_string(&new_version.0).unwrap(), + chains.handle_a().get_signer().unwrap().as_ref(), + "1", + )?; + + info!("Will run ChanUpgradeTry step..."); + + channel.build_chan_upgrade_try_and_send()?; + + info!("Check that the step ChanUpgradeTry was correctly executed..."); + + assert_eventually_channel_upgrade_try( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + &old_attrs.flipped(), + )?; + + info!("Check that the channel upgrade successfully upgraded the version..."); + + relayer.with_supervisor(|| { + // This will assert that both channel ends are eventually + // in Open state, and that the fields targeted by the upgrade + // have been correctly updated. + assert_eventually_channel_upgrade_open( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + &upgraded_attrs, + )?; + + Ok(()) + }) + } +} + +struct ChannelUpgradeHandshakeFromAck; + +impl BinaryChannelTest for ChannelUpgradeHandshakeFromAck { + fn run( + &self, + _config: &TestConfig, + relayer: RelayerDriver, + chains: ConnectedChains, + channels: ConnectedChannel, + ) -> Result<(), Error> { + info!("Check that channels are both in OPEN State"); + + assert_eventually_channel_established( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + )?; + + let channel_end_a = chains + .handle_a + .query_channel( + QueryChannelRequest { + port_id: channels.port_a.0.clone(), + channel_id: channels.channel_id_a.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd A: {e}"))?; + + let channel_end_b = chains + .handle_b + .query_channel( + QueryChannelRequest { + port_id: channels.port_b.0.clone(), + channel_id: channels.channel_id_b.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd B: {e}"))?; + + let old_version = channel_end_a.version; + let old_ordering = channel_end_a.ordering; + let old_connection_hops_a = channel_end_a.connection_hops; + let old_connection_hops_b = channel_end_b.connection_hops; + + let channel = channels.channel; + let new_version = Version::ics20_with_fee(); + + let old_attrs = ChannelUpgradableAttributes::new( + old_version.clone(), + old_version.clone(), + old_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b.clone(), + Sequence::from(1), + ); + + let upgraded_attrs = ChannelUpgradableAttributes::new( + new_version.clone(), + new_version.clone(), + old_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b, + Sequence::from(1), + ); + + info!("Will initialise upgrade handshake with governance proposal..."); + + chains.node_a.chain_driver().initialise_channel_upgrade( + channel.src_port_id().as_str(), + channel.src_channel_id().unwrap().as_str(), + old_ordering.as_str(), + old_connection_hops_a.first().unwrap().as_str(), + &serde_json::to_string(&new_version.0).unwrap(), + chains.handle_a().get_signer().unwrap().as_ref(), + "1", + )?; + + info!("Will run ChanUpgradeTry step..."); + + channel.build_chan_upgrade_try_and_send()?; + + info!("Check that the step ChanUpgradeTry was correctly executed..."); + + assert_eventually_channel_upgrade_try( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + &old_attrs.flipped(), + )?; + + info!("Will run ChanUpgradeAck step..."); + + channel.flipped().build_chan_upgrade_ack_and_send()?; + + info!("Check that the step ChanUpgradeAck was correctly executed..."); + + assert_eventually_channel_upgrade_ack( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + ChannelState::FlushComplete, + ChannelState::Flushing, + &old_attrs, + )?; + + info!("Check that the channel upgrade successfully upgraded the version..."); + + relayer.with_supervisor(|| { + // This will assert that both channel ends are eventually + // in Open state, and that the fields targeted by the upgrade + // have been correctly updated. + assert_eventually_channel_upgrade_open( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + &upgraded_attrs, + )?; + + Ok(()) + }) + } +} +struct ChannelUpgradeHandshakeFromConfirm; + +impl BinaryChannelTest for ChannelUpgradeHandshakeFromConfirm { + fn run( + &self, + _config: &TestConfig, + relayer: RelayerDriver, + chains: ConnectedChains, + channels: ConnectedChannel, + ) -> Result<(), Error> { + info!("Check that channels are both in OPEN State"); + + assert_eventually_channel_established( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + )?; + + let channel_end_a = chains + .handle_a + .query_channel( + QueryChannelRequest { + port_id: channels.port_a.0.clone(), + channel_id: channels.channel_id_a.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd A: {e}"))?; + + let channel_end_b = chains + .handle_b + .query_channel( + QueryChannelRequest { + port_id: channels.port_b.0.clone(), + channel_id: channels.channel_id_b.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd B: {e}"))?; + + let old_version = channel_end_a.version; + let old_ordering = channel_end_a.ordering; + let old_connection_hops_a = channel_end_a.connection_hops; + let old_connection_hops_b = channel_end_b.connection_hops; + + let channel = channels.channel; + let new_version = Version::ics20_with_fee(); + + let old_attrs = ChannelUpgradableAttributes::new( + old_version.clone(), + old_version.clone(), + old_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b.clone(), + Sequence::from(1), + ); + + let interm_attrs = ChannelUpgradableAttributes::new( + old_version, + new_version.clone(), + old_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b.clone(), + Sequence::from(1), + ); + + let upgraded_attrs = ChannelUpgradableAttributes::new( + new_version.clone(), + new_version.clone(), + old_ordering, + old_connection_hops_a.clone(), + old_connection_hops_b, + Sequence::from(1), + ); + + info!("Will initialise upgrade handshake with governance proposal..."); + + chains.node_a.chain_driver().initialise_channel_upgrade( + channel.src_port_id().as_str(), + channel.src_channel_id().unwrap().as_str(), + old_ordering.as_str(), + old_connection_hops_a.first().unwrap().as_str(), + &serde_json::to_string(&new_version.0).unwrap(), + chains.handle_a().get_signer().unwrap().as_ref(), + "1", + )?; + + info!("Will run ChanUpgradeTry step..."); + + channel.build_chan_upgrade_try_and_send()?; + + info!("Check that the step ChanUpgradeTry was correctly executed..."); + + assert_eventually_channel_upgrade_try( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + &old_attrs.flipped(), + )?; + + info!("Will run ChanUpgradeAck step..."); + + channel.flipped().build_chan_upgrade_ack_and_send()?; + + info!("Check that the step ChanUpgradeAck was correctly executed..."); + + assert_eventually_channel_upgrade_ack( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + ChannelState::FlushComplete, + ChannelState::Flushing, + &old_attrs, + )?; + + info!("Will run ChanUpgradeConfirm step..."); + + channel.build_chan_upgrade_confirm_and_send()?; + + info!("Check that the step ChanUpgradeConfirm was correctly executed..."); + + assert_eventually_channel_upgrade_confirm( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + &interm_attrs.flipped(), + )?; + + info!("Check that the channel upgrade successfully upgraded the version..."); + + relayer.with_supervisor(|| { + // This will assert that both channel ends are eventually + // in Open state, and that the fields targeted by the upgrade + // have been correctly updated. + assert_eventually_channel_upgrade_open( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + &upgraded_attrs, + )?; + + Ok(()) + }) + } +} + +struct ChannelUpgradeHandshakeInitiateNewUpgrade; + +impl BinaryChannelTest for ChannelUpgradeHandshakeInitiateNewUpgrade { + fn run( + &self, + _config: &TestConfig, + _relayer: RelayerDriver, + chains: ConnectedChains, + channels: ConnectedChannel, + ) -> Result<(), Error> { + info!("Check that channels are both in OPEN State"); + + assert_eventually_channel_established( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + )?; + + let mut channel_end_a = chains + .handle_a + .query_channel( + QueryChannelRequest { + port_id: channels.port_a.0.clone(), + channel_id: channels.channel_id_a.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd A: {e}"))?; + + let mut channel_end_b = chains + .handle_b + .query_channel( + QueryChannelRequest { + port_id: channels.port_b.0.clone(), + channel_id: channels.channel_id_b.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::No, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd B: {e}"))?; + + let pre_upgrade_1_version = channel_end_a.version; + let pre_upgrade_1_ordering = channel_end_a.ordering; + let pre_upgrade_1_connection_hops_a = channel_end_a.connection_hops.clone(); + let pre_upgrade_1_connection_hops_b = channel_end_b.connection_hops.clone(); + + let channel = channels.channel; + let post_upgrade_1_version = Version::ics20_with_fee(); + + let pre_upgrade_1_attrs = ChannelUpgradableAttributes::new( + pre_upgrade_1_version.clone(), + pre_upgrade_1_version.clone(), + pre_upgrade_1_ordering, + pre_upgrade_1_connection_hops_a.clone(), + pre_upgrade_1_connection_hops_b.clone(), + Sequence::from(1), + ); + + let interm_upgrade_1_attrs = ChannelUpgradableAttributes::new( + pre_upgrade_1_version, + post_upgrade_1_version.clone(), + pre_upgrade_1_ordering, + pre_upgrade_1_connection_hops_a.clone(), + pre_upgrade_1_connection_hops_b.clone(), + Sequence::from(1), + ); + + info!("Will initialise on chain A upgrade handshake with governance proposal..."); + + chains.node_a.chain_driver().initialise_channel_upgrade( + channel.src_port_id().as_str(), + channel.src_channel_id().unwrap().as_str(), + pre_upgrade_1_ordering.as_str(), + pre_upgrade_1_connection_hops_a.first().unwrap().as_str(), + &serde_json::to_string(&post_upgrade_1_version.0).unwrap(), + chains.handle_a().get_signer().unwrap().as_ref(), + "1", + )?; + + info!("Check that the step ChanUpgradeInit was correctly executed..."); + + assert_eventually_channel_upgrade_init( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + &pre_upgrade_1_attrs, + )?; + + info!("Will run ChanUpgradeTry step..."); + + channel.build_chan_upgrade_try_and_send()?; + + info!("Check that the step ChanUpgradeTry was correctly executed..."); + + assert_eventually_channel_upgrade_try( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + &pre_upgrade_1_attrs.flipped(), + )?; + + info!("Will run ChanUpgradeAck step..."); + + channel.flipped().build_chan_upgrade_ack_and_send()?; + + info!("Check that the step ChanUpgradeAck was correctly executed..."); + + assert_eventually_channel_upgrade_ack( + &chains.handle_a, + &chains.handle_b, + &channels.channel_id_a.as_ref(), + &channels.port_a.as_ref(), + ChannelState::FlushComplete, + ChannelState::Flushing, + &pre_upgrade_1_attrs, + )?; + + info!("Will run ChanUpgradeConfirm step..."); + + channel.build_chan_upgrade_confirm_and_send()?; + + info!("Check that the step ChanUpgradeConfirm was correctly executed..."); + + assert_eventually_channel_upgrade_confirm( + &chains.handle_b, + &chains.handle_a, + &channels.channel_id_b.as_ref(), + &channels.port_b.as_ref(), + &interm_upgrade_1_attrs.flipped(), + )?; + + // ChannelEnd B is now `OPEN` (because both ends did not have in-flight packets) + // Initialise a new upgrade handshake on chain B before ChannelEnd A moves to `OPEN` + + let pre_upgrade_2_ordering = channel_end_a.ordering; + let pre_upgrade_2_connection_hops_b = channel_end_b.connection_hops.clone(); + + let post_upgrade_2_version = Version::ics20(); + + info!("Will initialise on chain B upgrade handshake with governance proposal..."); + + chains.node_b.chain_driver().initialise_channel_upgrade( + channel.dst_port_id().as_str(), + channel.dst_channel_id().unwrap().as_str(), + pre_upgrade_2_ordering.as_str(), + pre_upgrade_2_connection_hops_b.first().unwrap().as_str(), + &serde_json::to_string(&post_upgrade_2_version.0).unwrap(), + chains.handle_b().get_signer().unwrap().as_ref(), + "1", + )?; + + info!("Check that the step ChanUpgradeInit was correctly executed..."); + + channel_end_b = chains + .handle_b + .query_channel( + QueryChannelRequest { + port_id: channels.port_b.0.clone(), + channel_id: channels.channel_id_b.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::Yes, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd B: {e}"))?; + + // upgrade sequence should have been incremented + let upgrade_sequence_b = Sequence::from(2); + assert_eq!( + channel_end_b.upgrade_sequence, upgrade_sequence_b, + "expected channel end B upgrade sequence to be `{}`, but it is instead `{}`", + upgrade_sequence_b, channel_end_b.upgrade_sequence + ); + + // Finish upgrade 1 on ChannelEnd A + + info!("Will run ChanUpgradeOpen step..."); + + channel.flipped().build_chan_upgrade_open_and_send()?; + + info!("Check that the step ChanUpgradeOpen was correctly executed..."); + + channel_end_a = chains + .handle_a + .query_channel( + QueryChannelRequest { + port_id: channels.port_a.0.clone(), + channel_id: channels.channel_id_a.0.clone(), + height: QueryHeight::Latest, + }, + IncludeProof::Yes, + ) + .map(|(channel_end, _)| channel_end) + .map_err(|e| eyre!("Error querying ChannelEnd A: {e}"))?; + + if !channel_end_a.is_open() { + return Err(Error::generic(eyre!( + "expected channel end A state to be `{}`, but is instead `{}`", + ChannelState::Open(UpgradeState::NotUpgrading), + channel_end_a.state() + ))); + } + + assert_eq!( + channel_end_a.version, post_upgrade_1_version, + "expected channel end A version to be `{}`, but is instead `{}`", + post_upgrade_1_version, channel_end_a.version + ); + + Ok(()) + } +} + +impl HasOverrides for ChannelUpgradeManualHandshake { + type Overrides = ChannelUpgradeTestOverrides; + + fn get_overrides(&self) -> &ChannelUpgradeTestOverrides { + &ChannelUpgradeTestOverrides + } +} + +impl HasOverrides for ChannelUpgradeHandshakeFromTry { + type Overrides = ChannelUpgradeTestOverrides; + + fn get_overrides(&self) -> &ChannelUpgradeTestOverrides { + &ChannelUpgradeTestOverrides + } +} + +impl HasOverrides for ChannelUpgradeHandshakeFromAck { + type Overrides = ChannelUpgradeTestOverrides; + + fn get_overrides(&self) -> &ChannelUpgradeTestOverrides { + &ChannelUpgradeTestOverrides + } +} + +impl HasOverrides for ChannelUpgradeHandshakeFromConfirm { + type Overrides = ChannelUpgradeTestOverrides; + + fn get_overrides(&self) -> &ChannelUpgradeTestOverrides { + &ChannelUpgradeTestOverrides + } +} + +impl HasOverrides for ChannelUpgradeHandshakeInitiateNewUpgrade { + type Overrides = ChannelUpgradeTestOverrides; + + fn get_overrides(&self) -> &ChannelUpgradeTestOverrides { + &ChannelUpgradeTestOverrides + } +} diff --git a/tools/integration-test/src/tests/clean_workers.rs b/tools/integration-test/src/tests/clean_workers.rs index 5edfec50c7..b69637780a 100644 --- a/tools/integration-test/src/tests/clean_workers.rs +++ b/tools/integration-test/src/tests/clean_workers.rs @@ -1,15 +1,7 @@ -use ibc_relayer::{ - config::{ - self, - ModeConfig, - }, - object::ObjectType, -}; -use ibc_test_framework::{ - prelude::*, - relayer::channel::init_channel, - util::random::random_u128_range, -}; +use ibc_relayer::config::{self, ModeConfig}; +use ibc_relayer::object::ObjectType; +use ibc_test_framework::relayer::channel::init_channel; +use ibc_test_framework::{prelude::*, util::random::random_u128_range}; #[test] fn test_clean_packet_workers() -> Result<(), Error> { diff --git a/tools/integration-test/src/tests/clear_packet.rs b/tools/integration-test/src/tests/clear_packet.rs index f2287c4aa4..cf09b6dbad 100644 --- a/tools/integration-test/src/tests/clear_packet.rs +++ b/tools/integration-test/src/tests/clear_packet.rs @@ -1,18 +1,14 @@ use std::thread; -use ibc_relayer::{ - chain::counterparty::pending_packet_summary, - config::ChainConfig, -}; -use ibc_test_framework::{ - prelude::*, - relayer::channel::query_identified_channel_end, - util::random::random_u128_range, -}; +use ibc_relayer::chain::{counterparty::pending_packet_summary, requests::Paginate}; +use ibc_relayer::config::ChainConfig; +use ibc_test_framework::prelude::*; +use ibc_test_framework::relayer::channel::query_identified_channel_end; +use ibc_test_framework::util::random::random_u128_range; #[test] -fn test_clear_packet() -> Result<(), Error> { - run_binary_channel_test(&ClearPacketTest) +fn test_disabled_clear_packet() -> Result<(), Error> { + run_binary_channel_test(&DisabledClearPacketTest) } #[test] @@ -35,13 +31,19 @@ fn test_clear_packet_sequences() -> Result<(), Error> { run_binary_channel_test(&ClearPacketSequencesTest) } -pub struct ClearPacketTest; +#[test] +fn test_limited_clear_packet() -> Result<(), Error> { + run_binary_channel_test(&LimitedClearPacketTest) +} + +pub struct DisabledClearPacketTest; pub struct ClearPacketRecoveryTest; pub struct ClearPacketNoScanTest; pub struct ClearPacketOverrideTest; pub struct ClearPacketSequencesTest; +pub struct LimitedClearPacketTest; -impl TestOverrides for ClearPacketTest { +impl TestOverrides for DisabledClearPacketTest { 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. @@ -64,18 +66,7 @@ impl TestOverrides for ClearPacketTest { } } -impl TestOverrides for ClearPacketRecoveryTest { - fn modify_relayer_config(&self, config: &mut Config) { - config.mode.packets.enabled = true; - config.mode.packets.clear_on_start = true; - } - - fn should_spawn_supervisor(&self) -> bool { - false - } -} - -impl BinaryChannelTest for ClearPacketTest { +impl BinaryChannelTest for DisabledClearPacketTest { fn run( &self, _config: &TestConfig, @@ -151,14 +142,27 @@ impl BinaryChannelTest for ClearPacketTest { } } +impl TestOverrides for ClearPacketRecoveryTest { + fn modify_relayer_config(&self, config: &mut Config) { + config.mode.packets.enabled = true; + config.mode.packets.clear_on_start = true; + } + + fn should_spawn_supervisor(&self) -> bool { + false + } +} + impl BinaryChannelTest for ClearPacketRecoveryTest { fn run( &self, - _config: &TestConfig, + config: &TestConfig, relayer: RelayerDriver, chains: ConnectedChains, channel: ConnectedChannel, ) -> Result<(), Error> { + let fee_denom_b: MonoTagged = + MonoTagged::new(Denom::base(config.native_token(1))); let denom_a = chains.node_a.denom(); let denom_b1 = chains.node_b.denom(); @@ -172,6 +176,7 @@ impl BinaryChannelTest for ClearPacketRecoveryTest { &relayer_wallet_b.as_ref(), &wallet_b.address(), &denom_b1.with_amount(100u64).as_ref(), + &fee_denom_b.with_amount(381000000u64).as_ref(), )?; let amount1 = random_u128_range(1000, 5000); @@ -228,7 +233,7 @@ impl BinaryChannelTest for ClearPacketNoScanTest { channel: ConnectedChannel, ) -> Result<(), Error> { let denom_a = chains.node_a.denom(); - let fee_denom_a = MonoTagged::new(Denom::base(&config.native_tokens[0])); + let fee_denom_a = MonoTagged::new(Denom::base(config.native_token(0))); let wallet_a = chains.node_a.wallets().user1().cloned(); let wallet_b = chains.node_b.wallets().user1().cloned(); @@ -348,7 +353,7 @@ impl BinaryChannelTest for ClearPacketOverrideTest { channel: ConnectedChannel, ) -> Result<(), Error> { let denom_a = chains.node_a.denom(); - let fee_denom_a = MonoTagged::new(Denom::base(&config.native_tokens[0])); + let fee_denom_a = MonoTagged::new(Denom::base(config.native_token(0))); let wallet_a = chains.node_a.wallets().user1().cloned(); let wallet_b = chains.node_b.wallets().user1().cloned(); @@ -439,10 +444,7 @@ impl TestOverrides for ClearPacketSequencesTest { } } -use ibc_relayer::link::{ - Link, - LinkParameters, -}; +use ibc_relayer::link::{Link, LinkParameters}; impl BinaryChannelTest for ClearPacketSequencesTest { fn run( @@ -482,8 +484,12 @@ impl BinaryChannelTest for ClearPacketSequencesTest { channel.port_a.as_ref(), )?; - let pending_packets_a = - pending_packet_summary(chains.handle_a(), chains.handle_b(), channel_end_a.value())?; + let pending_packets_a = pending_packet_summary( + chains.handle_a(), + chains.handle_b(), + channel_end_a.value(), + Paginate::All, + )?; info!("Pending packets: {:?}", pending_packets_a); @@ -494,6 +500,15 @@ impl BinaryChannelTest for ClearPacketSequencesTest { src_channel_id: channel.channel_id_a.clone().into_value(), max_memo_size: packet_config.ics20_max_memo_size, max_receiver_size: packet_config.ics20_max_receiver_size, + exclude_src_sequences: vec![], + }; + + let rev_opts = LinkParameters { + src_port_id: channel.port_b.clone().into_value(), + src_channel_id: channel.channel_id_b.clone().into_value(), + max_memo_size: packet_config.ics20_max_memo_size, + max_receiver_size: packet_config.ics20_max_receiver_size, + exclude_src_sequences: vec![], }; // Clear all even packets @@ -521,8 +536,12 @@ impl BinaryChannelTest for ClearPacketSequencesTest { sleep(Duration::from_secs(10)); - let pending_packets = - pending_packet_summary(chains.handle_a(), chains.handle_b(), channel_end_a.value())?; + let pending_packets = pending_packet_summary( + chains.handle_a(), + chains.handle_b(), + channel_end_a.value(), + Paginate::All, + )?; info!("Pending packets: {pending_packets:?}"); @@ -539,11 +558,22 @@ impl BinaryChannelTest for ClearPacketSequencesTest { info!("Clearing all unreceived ack packets ({})", to_clear.len()); - let rev_link = link.reverse(false, false).unwrap(); - rev_link.relay_ack_packet_messages(to_clear).unwrap(); + let rev_link = Link::new_from_opts( + chains.handle_b().clone(), + chains.handle_a().clone(), + rev_opts, + false, + false, + )?; - let pending_packets_a = - pending_packet_summary(chains.handle_a(), chains.handle_b(), channel_end_a.value())?; + rev_link.relay_ack_packet_messages(to_clear)?; + + let pending_packets_a = pending_packet_summary( + chains.handle_a(), + chains.handle_b(), + channel_end_a.value(), + Paginate::All, + )?; info!("Pending packets: {pending_packets_a:?}"); @@ -561,3 +591,92 @@ impl BinaryChannelTest for ClearPacketSequencesTest { Ok(()) } } + +impl TestOverrides for LimitedClearPacketTest { + 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 = true; + config.mode.packets.clear_interval = 0; + } + + fn should_spawn_supervisor(&self) -> bool { + false + } + + // Unordered channel: will permit gaps in the sequence of relayed packets + fn channel_order(&self) -> Ordering { + Ordering::Unordered + } +} + +impl BinaryChannelTest for LimitedClearPacketTest { + fn run( + &self, + _config: &TestConfig, + relayer: RelayerDriver, + chains: ConnectedChains, + channel: ConnectedChannel, + ) -> Result<(), Error> { + 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 balance_a = chains + .node_a + .chain_driver() + .query_balance(&wallet_a.address(), &denom_a)?; + + let raw_amount = random_u128_range(1000, 5000); + + let num_transfers = 70; + + let amount = denom_a.with_amount(raw_amount); + let sent_amount = denom_a.with_amount(raw_amount * num_transfers); + let cleared_amount = denom_a.with_amount(raw_amount * 50); + + info!("Performing {num_transfers} IBC transfers with amount {amount}, for a total of {sent_amount}"); + + chains.node_a.chain_driver().ibc_transfer_token_multiple( + &channel.port_a.as_ref(), + &channel.channel_id_a.as_ref(), + &wallet_a.as_ref(), + &wallet_b.address(), + &amount.as_ref(), + 70, + None, + )?; + + sleep(Duration::from_secs(10)); + + // Spawn the supervisor only after the first IBC transfer + relayer.with_supervisor(|| { + let amount_b = cleared_amount + .transfer(&channel.port_b.as_ref(), &channel.channel_id_b.as_ref())?; + + info!("Assert that {sent_amount} was escrowed from sending chain"); + + // Wallet on chain A should have both amount deducted. + chains.node_a.chain_driver().assert_eventual_wallet_amount( + &wallet_a.address(), + &(balance_a - sent_amount.amount()).as_ref(), + )?; + + info!("Assert that only {amount_b} was received"); + + // Wallet on chain B should only receive the second IBC transfer + chains + .node_b + .chain_driver() + .assert_eventual_wallet_amount(&wallet_b.address(), &amount_b.as_ref())?; + + Ok(()) + }) + } +} diff --git a/tools/integration-test/src/tests/client_expiration.rs b/tools/integration-test/src/tests/client_expiration.rs index a4ded4a522..082cacf70a 100644 --- a/tools/integration-test/src/tests/client_expiration.rs +++ b/tools/integration-test/src/tests/client_expiration.rs @@ -1,41 +1,20 @@ -use core::time::Duration; -use std::thread::sleep; - -use ibc_relayer::config::{ - self, - ChainConfig, - Config, - ModeConfig, +use ibc_relayer::config::{self, ChainConfig, ModeConfig}; +use ibc_relayer_types::core::ics03_connection::connection::State as ConnectionState; +use ibc_relayer_types::core::ics04_channel::channel::State as ChannelState; + +use ibc_test_framework::bootstrap::binary::chain::bootstrap_foreign_client_pair; +use ibc_test_framework::bootstrap::binary::channel::{ + bootstrap_channel_with_chains, bootstrap_channel_with_connection, }; -use ibc_relayer_types::core::{ - ics03_connection::connection::State as ConnectionState, - ics04_channel::channel::State as ChannelState, +use ibc_test_framework::bootstrap::binary::connection::bootstrap_connection; +use ibc_test_framework::prelude::*; +use ibc_test_framework::relayer::channel::{ + assert_eventually_channel_established, init_channel, query_channel_end, }; -use ibc_test_framework::{ - bootstrap::binary::{ - chain::bootstrap_foreign_client_pair, - channel::{ - bootstrap_channel_with_chains, - bootstrap_channel_with_connection, - }, - connection::bootstrap_connection, - }, - ibc::denom::derive_ibc_denom, - prelude::*, - relayer::{ - channel::{ - assert_eventually_channel_established, - init_channel, - query_channel_end, - }, - connection::{ - assert_eventually_connection_established, - init_connection, - query_connection_end, - }, - refresh::spawn_refresh_client_tasks, - }, +use ibc_test_framework::relayer::connection::{ + assert_eventually_connection_established, init_connection, query_connection_end, }; +use ibc_test_framework::relayer::refresh::spawn_refresh_client_tasks; // The cosmos ChainHandle handles requests in serial, and a refresh client // request may get blocked by other operations and cause the refresh to fail diff --git a/tools/integration-test/src/tests/client_filter.rs b/tools/integration-test/src/tests/client_filter.rs index 2b010e55de..0410a91ba4 100644 --- a/tools/integration-test/src/tests/client_filter.rs +++ b/tools/integration-test/src/tests/client_filter.rs @@ -16,26 +16,15 @@ //! is allowed through the filter. It then asserts that client workers were //! established as a result of the connection being allowed through. -use std::time::Duration; - -use ibc_relayer::{ - chain::requests::{ - IncludeProof, - QueryClientStateRequest, - QueryHeight, - }, - client_state::AnyClientState, - foreign_client::CreateOptions, - object::ObjectType, - supervisor::client_state_filter::{ - FilterPolicy, - Permission, - }, -}; -use ibc_relayer_types::{ - clients::ics07_tendermint::client_state::ClientState as TmClientState, - core::ics02_client::trust_threshold::TrustThreshold, -}; +use ibc_relayer::supervisor::client_state_filter::{FilterPolicy, Permission}; +use ibc_relayer_types::core::ics02_client::trust_threshold::TrustThreshold; + +use ibc_relayer::chain::requests::{IncludeProof, QueryClientStateRequest, QueryHeight}; +use ibc_relayer::client_state::AnyClientState; +use ibc_relayer::foreign_client::CreateOptions; +use ibc_relayer::object::ObjectType; +use ibc_relayer_types::clients::ics07_tendermint::client_state::ClientState as TmClientState; + use ibc_test_framework::prelude::*; struct ClientFilterBlocksConnectionTest; diff --git a/tools/integration-test/src/tests/client_refresh.rs b/tools/integration-test/src/tests/client_refresh.rs index 14f86e2106..e29adbb821 100644 --- a/tools/integration-test/src/tests/client_refresh.rs +++ b/tools/integration-test/src/tests/client_refresh.rs @@ -1,20 +1,12 @@ -use std::time::Duration; - -use ibc_relayer::{ - config::{ - gas_multiplier::GasMultiplier, - ChainConfig, - }, - foreign_client::CreateOptions, -}; +use ibc_relayer::config::gas_multiplier::GasMultiplier; +use ibc_relayer::config::ChainConfig; +use ibc_relayer::foreign_client::CreateOptions; use ibc_relayer_types::core::ics02_client::trust_threshold::TrustThreshold; -use ibc_test_framework::{ - bootstrap::binary::chain::{ - add_chain_config, - new_registry, - spawn_chain_handle, - }, - prelude::*, + +use ibc_test_framework::prelude::*; + +use ibc_test_framework::bootstrap::binary::chain::{ + add_chain_config, new_registry, spawn_chain_handle, }; #[test] diff --git a/tools/integration-test/src/tests/client_settings.rs b/tools/integration-test/src/tests/client_settings.rs index 6553d401a8..0a3c7656a4 100644 --- a/tools/integration-test/src/tests/client_settings.rs +++ b/tools/integration-test/src/tests/client_settings.rs @@ -1,19 +1,10 @@ -use std::time::Duration; +use ibc_relayer::chain::requests::{IncludeProof, QueryClientStateRequest, QueryHeight}; +use ibc_relayer::client_state::AnyClientState; +use ibc_relayer::config::ChainConfig; +use ibc_relayer::foreign_client::CreateOptions; +use ibc_relayer_types::clients::ics07_tendermint::client_state::ClientState as TmClientState; +use ibc_relayer_types::core::ics02_client::trust_threshold::TrustThreshold; -use ibc_relayer::{ - chain::requests::{ - IncludeProof, - QueryClientStateRequest, - QueryHeight, - }, - client_state::AnyClientState, - config::ChainConfig, - foreign_client::CreateOptions, -}; -use ibc_relayer_types::{ - clients::ics07_tendermint::client_state::ClientState as TmClientState, - core::ics02_client::trust_threshold::TrustThreshold, -}; use ibc_test_framework::prelude::*; /// A test to exercise default foreign client settings. diff --git a/tools/integration-test/src/tests/client_upgrade.rs b/tools/integration-test/src/tests/client_upgrade.rs index e072b8bc22..9480a4a105 100644 --- a/tools/integration-test/src/tests/client_upgrade.rs +++ b/tools/integration-test/src/tests/client_upgrade.rs @@ -12,39 +12,27 @@ //! - The `test_height_too_low_client_upgrade`tests the case where the client //! fails to upgrade because a height too small is given as input. +use http::Uri; use std::str::FromStr; -use http::Uri; -use ibc_relayer::{ - chain::requests::{ - IncludeProof, - QueryClientStateRequest, - QueryHeight, - }, - client_state::AnyClientState, - upgrade_chain::{ - build_and_send_ibc_upgrade_proposal, - UpgradePlanOptions, - }, -}; +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_min_deposit_amount, - set_voting_period, - }, - ext::bootstrap::ChainBootstrapMethodsExt, - }, - prelude::*, - util::proposal_status::ProposalStatus, +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: u64 = 10; const DELTA_HEIGHT: u64 = 15; const WAIT_CHAIN_UPGRADE: Duration = Duration::from_secs(4); +const WAIT_CHAIN_HEIGHT: Duration = Duration::from_secs(3); const MIN_DEPOSIT: u64 = 10000000u64; #[test] @@ -95,7 +83,7 @@ impl BinaryChainTest for ClientUpgradeTest { ) -> 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])); + MonoTagged::new(Denom::base(config.native_token(0))); let foreign_clients = chains.clone().foreign_clients; // Create and send an chain upgrade proposal @@ -134,7 +122,7 @@ impl BinaryChainTest for ClientUpgradeTest { .map_err(handle_generic_error)?; // Vote on the proposal so the chain will upgrade - driver.vote_proposal(&fee_denom_a.with_amount(381000000u64).to_string())?; + driver.vote_proposal(&fee_denom_a.with_amount(381000000u64).to_string(), "1")?; info!("Assert that the chain upgrade proposal is eventually passed"); @@ -147,15 +135,28 @@ impl BinaryChainTest for ClientUpgradeTest { "1", )?; - // Wait for the chain to upgrade - std::thread::sleep(WAIT_CHAIN_UPGRADE); + let halt_height = (client_upgrade_height - 1).unwrap(); + + // Wait for the chain to get to the halt height + loop { + let latest_height = chains.handle_a().query_latest_height()?; + info!("latest height: {latest_height}"); + + if latest_height >= halt_height { + break; + } + std::thread::sleep(WAIT_CHAIN_HEIGHT); + } + // Wait for an additional height which is required to fetch + // the header + std::thread::sleep(WAIT_CHAIN_HEIGHT); // Trigger the client upgrade // 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)); + std::thread::sleep(WAIT_CHAIN_UPGRADE); let (state, _) = chains.handle_b().query_client_state( QueryClientStateRequest { @@ -241,7 +242,7 @@ impl BinaryChainTest for HeightTooHighClientUpgradeTest { ) -> 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])); + MonoTagged::new(Denom::base(config.native_token(0))); let foreign_clients = chains.clone().foreign_clients; // Create and send an chain upgrade proposal @@ -280,7 +281,7 @@ impl BinaryChainTest for HeightTooHighClientUpgradeTest { .map_err(handle_generic_error)?; // Vote on the proposal so the chain will upgrade - driver.vote_proposal(&fee_denom_a.with_amount(381000000u64).to_string())?; + driver.vote_proposal(&fee_denom_a.with_amount(381000000u64).to_string(), "1")?; // The application height reports a height of 1 less than the height according to Tendermint client_upgrade_height.increment(); @@ -339,7 +340,7 @@ impl BinaryChainTest for HeightTooLowClientUpgradeTest { ) -> 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])); + MonoTagged::new(Denom::base(config.native_token(0))); let foreign_clients = chains.clone().foreign_clients; let opts = create_upgrade_plan(config, &chains, &upgraded_chain_id)?; @@ -377,7 +378,7 @@ impl BinaryChainTest for HeightTooLowClientUpgradeTest { .map_err(handle_generic_error)?; // Vote on the proposal so the chain will upgrade - driver.vote_proposal(&fee_denom_a.with_amount(381000000u64).to_string())?; + driver.vote_proposal(&fee_denom_a.with_amount(381000000u64).to_string(), "1")?; // The application height reports a height of 1 less than the height according to Tendermint client_upgrade_height @@ -432,7 +433,7 @@ fn create_upgrade_plan( upgraded_chain_id: &ChainId, ) -> Result { let fee_denom_a: MonoTagged = - MonoTagged::new(Denom::base(&config.native_tokens[0])); + MonoTagged::new(Denom::base(config.native_token(0))); let foreign_clients = chains.clone().foreign_clients; let src_client_id = foreign_clients.client_id_b().0.clone(); diff --git a/tools/integration-test/src/tests/connection_delay.rs b/tools/integration-test/src/tests/connection_delay.rs index 31210aa147..0c8ca19e57 100644 --- a/tools/integration-test/src/tests/connection_delay.rs +++ b/tools/integration-test/src/tests/connection_delay.rs @@ -1,12 +1,8 @@ -use core::time::Duration; - -use ibc_test_framework::{ - ibc::denom::derive_ibc_denom, - prelude::*, - util::random::random_u128_range, -}; use time::OffsetDateTime; +use ibc_test_framework::prelude::*; +use ibc_test_framework::util::random::random_u128_range; + const CONNECTION_DELAY: Duration = Duration::from_secs(10); #[test] diff --git a/tools/integration-test/src/tests/consensus_states.rs b/tools/integration-test/src/tests/consensus_states.rs index 6872dd32a3..bfd0891679 100644 --- a/tools/integration-test/src/tests/consensus_states.rs +++ b/tools/integration-test/src/tests/consensus_states.rs @@ -1,13 +1,8 @@ -use std::time::Duration; - use ibc_relayer::chain::{ cosmos::query::consensus_state::query_consensus_states, - requests::{ - PageRequest, - QueryConsensusStateHeightsRequest, - QueryConsensusStatesRequest, - }, + requests::{PageRequest, QueryConsensusStateHeightsRequest, QueryConsensusStatesRequest}, }; + use ibc_test_framework::prelude::*; #[test] diff --git a/tools/integration-test/src/tests/denom_trace.rs b/tools/integration-test/src/tests/denom_trace.rs index daada2ff45..3c56efbdcb 100644 --- a/tools/integration-test/src/tests/denom_trace.rs +++ b/tools/integration-test/src/tests/denom_trace.rs @@ -1,7 +1,4 @@ -use ibc_test_framework::{ - ibc::denom::derive_ibc_denom, - prelude::*, -}; +use ibc_test_framework::prelude::*; #[test] fn test_ibc_denom_trace() -> Result<(), Error> { diff --git a/tools/integration-test/src/tests/dynamic_gas_fee.rs b/tools/integration-test/src/tests/dynamic_gas_fee.rs new file mode 100644 index 0000000000..3e30ec468d --- /dev/null +++ b/tools/integration-test/src/tests/dynamic_gas_fee.rs @@ -0,0 +1,214 @@ +//! The [`DynamicGasTest`] test ensures that the [`DynamicGas`] +//! configuration works correctly. The test can enable or disable the dynamic +//! gas price for the second chain. +//! +//! To test dynamic gas configuration, it will enable dynamic gas price on the +//! second chain only. It will then create and relay a first IBC transfer with a +//! big memo. The gas fee paid is then recorded. +//! A second IBC transfer without memo will then be relayed. The gas fee paid +//! will also be recorded. The test will assert that the Tx with a big memo +//! and dynamic gas enabled is lower than the Tx without memo and dynamic gas +//! disabled. +//! +//! The second test disables the dynamic gas price on both chains in +//! order to ensure that the first IBC transfer will cost more if dynamic +//! gas is disabled. + +use ibc_relayer::config::dynamic_gas::DynamicGasPrice; +use ibc_relayer::config::ChainConfig; +use ibc_relayer::config::GasPrice; +use ibc_test_framework::prelude::*; + +#[test] +fn test_dynamic_gas_transfer() -> Result<(), Error> { + run_binary_channel_test(&DynamicGasTest { + dynamic_gas_enabled: true, + }) +} + +#[test] +fn test_static_gas_transfer() -> Result<(), Error> { + run_binary_channel_test(&DynamicGasTest { + dynamic_gas_enabled: false, + }) +} + +const MEMO_CHAR: &str = "a"; +const MEMO_SIZE: usize = 10000; + +pub struct DynamicGasTest { + dynamic_gas_enabled: bool, +} + +impl TestOverrides for DynamicGasTest { + fn modify_relayer_config(&self, config: &mut Config) { + config.mode.clients.misbehaviour = false; + config.mode.clients.refresh = false; + config.mode.packets.clear_interval = 0; + + match &mut config.chains[0] { + ChainConfig::CosmosSdk(chain_config_a) => { + chain_config_a.gas_price = + GasPrice::new(0.1, chain_config_a.gas_price.denom.clone()); + chain_config_a.dynamic_gas_price = DynamicGasPrice::unsafe_new(false, 1.1, 0.6); + } + } + + match &mut config.chains[1] { + ChainConfig::CosmosSdk(chain_config_b) => { + chain_config_b.gas_price = + GasPrice::new(0.1, chain_config_b.gas_price.denom.clone()); + chain_config_b.dynamic_gas_price = + DynamicGasPrice::unsafe_new(self.dynamic_gas_enabled, 1.1, 0.6); + } + } + } + + fn should_spawn_supervisor(&self) -> bool { + false + } +} + +impl BinaryChannelTest for DynamicGasTest { + fn run( + &self, + _config: &TestConfig, + relayer: RelayerDriver, + chains: ConnectedChains, + channel: ConnectedChannel, + ) -> Result<(), Error> { + 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 a_to_b_amount = 12345u64; + + let denom_a_to_b = derive_ibc_denom( + &channel.port_b.as_ref(), + &channel.channel_id_b.as_ref(), + &denom_a, + )?; + + let gas_denom_a: MonoTagged = + MonoTagged::new(Denom::Base("stake".to_owned())); + let gas_denom_b: MonoTagged = + MonoTagged::new(Denom::Base("stake".to_owned())); + + let balance_relayer_b_before = chains.node_b.chain_driver().query_balance( + &chains.node_b.wallets().relayer().address(), + &gas_denom_b.as_ref(), + )?; + + let memo: String = MEMO_CHAR.repeat(MEMO_SIZE); + + chains + .node_a + .chain_driver() + .ibc_transfer_token_with_memo_and_timeout( + &channel.port_a.as_ref(), + &channel.channel_id_a.as_ref(), + &wallet_a.as_ref(), + &wallet_b.address(), + &denom_a.with_amount(a_to_b_amount).as_ref(), + Some(memo), + None, + )?; + + // Do a simple IBC transfer with the dynamic gas configuration + let tx1_paid_gas_relayer = relayer.with_supervisor(|| { + // Assert that user on chain B received the tokens + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &wallet_b.address(), + &denom_a_to_b.with_amount(a_to_b_amount).as_ref(), + )?; + + // Wait for a bit before querying the new balance + sleep(Duration::from_secs(5)); + + let balance_relayer_b_after = chains.node_b.chain_driver().query_balance( + &chains.node_b.wallets().relayer().address(), + &gas_denom_b.as_ref(), + )?; + + let paid_fees_relayer_b = balance_relayer_b_before + .amount() + .checked_sub(balance_relayer_b_after.amount()); + + assert!( + paid_fees_relayer_b.is_some(), + "subtraction between queried amounts for relayer should be Some" + ); + + info!("IBC transfer with memo was successful"); + + Ok(paid_fees_relayer_b.unwrap()) + })?; + + let b_to_a_amount = 23456u64; + let denom_b = chains.node_b.denom(); + + let denom_b_to_a = derive_ibc_denom( + &channel.port_a.as_ref(), + &channel.channel_id_a.as_ref(), + &denom_b, + )?; + + let balance_relayer_a_before = chains.node_a.chain_driver().query_balance( + &chains.node_a.wallets().relayer().address(), + &gas_denom_a.as_ref(), + )?; + + chains.node_b.chain_driver().ibc_transfer_token( + &channel.port_b.as_ref(), + &channel.channel_id_b.as_ref(), + &chains.node_b.wallets().user1(), + &chains.node_a.wallets().user1().address(), + &denom_b.with_amount(b_to_a_amount).as_ref(), + )?; + + let tx2_paid_gas_relayer = relayer.with_supervisor(|| { + // Assert that user on chain B received the tokens + chains.node_a.chain_driver().assert_eventual_wallet_amount( + &chains.node_a.wallets().user1().address(), + &denom_b_to_a.with_amount(b_to_a_amount).as_ref(), + )?; + + // Wait for a bit before querying the new balance + sleep(Duration::from_secs(5)); + + let balance_relayer_a_after = chains.node_a.chain_driver().query_balance( + &chains.node_a.wallets().relayer().address(), + &gas_denom_a.as_ref(), + )?; + + let paid_fees_relayer_a = balance_relayer_a_before + .amount() + .checked_sub(balance_relayer_a_after.amount()); + + assert!( + paid_fees_relayer_a.is_some(), + "subtraction between queried amounts for relayer should be Some" + ); + + info!("IBC transfer without memo was successful"); + + Ok(paid_fees_relayer_a.unwrap()) + })?; + + info!("paid gas fees for Tx with memo `{tx1_paid_gas_relayer}`, without memo `{tx2_paid_gas_relayer}`"); + + if self.dynamic_gas_enabled { + assert!( + tx1_paid_gas_relayer < tx2_paid_gas_relayer, + "with dynamic gas enabled, gas paid for the first TX should be lower" + ); + } else { + assert!( + tx1_paid_gas_relayer > tx2_paid_gas_relayer, + "with dynamic gas disabled, gas paid for the second TX should be lower" + ); + } + + Ok(()) + } +} diff --git a/tools/integration-test/src/tests/error_events.rs b/tools/integration-test/src/tests/error_events.rs index abfc76c4e1..24602d0122 100644 --- a/tools/integration-test/src/tests/error_events.rs +++ b/tools/integration-test/src/tests/error_events.rs @@ -1,9 +1,7 @@ use ibc_relayer::chain::tracking::TrackedMsgs; use ibc_relayer_types::events::IbcEvent; -use ibc_test_framework::{ - prelude::*, - relayer::transfer::build_transfer_message, -}; +use ibc_test_framework::prelude::*; +use ibc_test_framework::relayer::transfer::build_transfer_message; #[test] fn test_error_events() -> Result<(), Error> { diff --git a/tools/integration-test/src/tests/execute_schedule.rs b/tools/integration-test/src/tests/execute_schedule.rs index 5cb10a9a86..163439afad 100644 --- a/tools/integration-test/src/tests/execute_schedule.rs +++ b/tools/integration-test/src/tests/execute_schedule.rs @@ -12,14 +12,10 @@ //! later found in the pending queue), but all of the subsequent messages should //! exist in the pending queue. -use ibc_relayer::link::{ - Link, - LinkParameters, -}; -use ibc_test_framework::{ - prelude::*, - util::random::random_u128_range, -}; +use ibc_test_framework::prelude::*; +use ibc_test_framework::util::random::random_u128_range; + +use ibc_relayer::link::{Link, LinkParameters}; /// The number of messages to be sent in a batch contained in a piece of operational data. const BATCH_SIZE: usize = 10; @@ -53,6 +49,7 @@ impl BinaryChannelTest for ExecuteScheduleTest { src_channel_id: channel.channel_id_a.clone().into_value(), max_memo_size: packet_config.ics20_max_memo_size, max_receiver_size: packet_config.ics20_max_receiver_size, + exclude_src_sequences: vec![], }; let chain_a_link = Link::new_from_opts( @@ -75,7 +72,8 @@ impl BinaryChannelTest for ExecuteScheduleTest { &chains.node_a.denom().with_amount(amount1).as_ref(), )?; - relay_path_a_to_b.schedule_packet_clearing(None)?; + relay_path_a_to_b + .schedule_packet_clearing(None, relayer.config.mode.packets.clear_limit)?; info!("Performing IBC send packet with a token transfer #{} from chain A to be received by chain B", i); } diff --git a/tools/integration-test/src/tests/fee/auto_forward_relayer.rs b/tools/integration-test/src/tests/fee/auto_forward_relayer.rs index 5e35c9c233..ca120394a5 100644 --- a/tools/integration-test/src/tests/fee/auto_forward_relayer.rs +++ b/tools/integration-test/src/tests/fee/auto_forward_relayer.rs @@ -10,10 +10,8 @@ //! correct parties involved in the transaction. use ibc_relayer_types::core::ics04_channel::version::Version; -use ibc_test_framework::{ - prelude::*, - util::random::random_u128_range, -}; +use ibc_test_framework::prelude::*; +use ibc_test_framework::util::random::random_u128_range; #[test] fn test_auto_forward_relayer() -> Result<(), Error> { @@ -56,7 +54,7 @@ impl BinaryChannelTest for AutoForwardRelayerTest { let user_a = wallets_a.user1(); let user_b = wallets_b.user1(); - let balance_a1 = chain_driver_a.query_balance(&user_a.address(), &denom_a)?; + let balance_a = chain_driver_a.query_balance(&user_a.address(), &denom_a)?; let relayer_balance_a = chain_driver_a.query_balance(&relayer_a.address(), &denom_a)?; @@ -65,10 +63,6 @@ impl BinaryChannelTest for AutoForwardRelayerTest { let ack_fee = random_u128_range(200, 300); let timeout_fee = random_u128_range(100, 200); - let total_sent = send_amount + receive_fee + ack_fee + timeout_fee; - - let balance_a2 = balance_a1 - total_sent; - chain_driver_a.ibc_token_transfer_with_fee( &port_a, &channel_id_a, @@ -87,18 +81,22 @@ impl BinaryChannelTest for AutoForwardRelayerTest { &denom_a, )?; - chain_driver_a.assert_eventual_wallet_amount(&user_a.address(), &balance_a2.as_ref())?; + info!("Will assert user b received the transferred token"); chain_driver_b.assert_eventual_wallet_amount( &user_b.address(), &denom_b.with_amount(send_amount).as_ref(), )?; + info!("Will assert user a transferred the sent amount, the recv fee and ack fee"); + chain_driver_a.assert_eventual_wallet_amount( &user_a.address(), - &(balance_a2 + timeout_fee).as_ref(), + &(balance_a - send_amount - receive_fee - ack_fee).as_ref(), )?; + info!("Will assert the relayer received the recv fee and ack fee"); + chain_driver_a.assert_eventual_wallet_amount( &relayer_a.address(), &(relayer_balance_a + ack_fee + receive_fee).as_ref(), diff --git a/tools/integration-test/src/tests/fee/filter_fees.rs b/tools/integration-test/src/tests/fee/filter_fees.rs index 66df617743..963e93e2d8 100644 --- a/tools/integration-test/src/tests/fee/filter_fees.rs +++ b/tools/integration-test/src/tests/fee/filter_fees.rs @@ -1,20 +1,12 @@ +#![allow(clippy::mutable_key_type)] + use std::collections::HashMap; -use ibc_relayer::config::{ - filter::{ - ChannelPolicy, - FeePolicy, - FilterPattern, - MinFee, - }, - ChainConfig, - PacketFilter, -}; +use ibc_relayer::config::filter::{ChannelPolicy, FeePolicy, FilterPattern, MinFee}; +use ibc_relayer::config::{ChainConfig, PacketFilter}; use ibc_relayer_types::core::ics04_channel::version::Version; -use ibc_test_framework::{ - prelude::*, - util::random::random_u128_range, -}; +use ibc_test_framework::prelude::*; +use ibc_test_framework::util::random::random_u128_range; #[test] fn test_filter_incentivized_fees_relayer() -> Result<(), Error> { @@ -85,9 +77,7 @@ impl BinaryChannelTest for FilterIncentivizedFeesRelayerTest { let ack_fee = random_u128_range(200, 300); let timeout_fee = random_u128_range(100, 200); - let total_sent_fail = send_amount + receive_fee_fail + ack_fee + timeout_fee; - - let balance_a2_fail = balance_a1 - total_sent_fail; + let balance_a2 = balance_a1.clone() - send_amount; chain_driver_a.ibc_token_transfer_with_fee( &port_a, @@ -109,17 +99,19 @@ impl BinaryChannelTest for FilterIncentivizedFeesRelayerTest { std::thread::sleep(Duration::from_secs(10)); - chain_driver_a - .assert_eventual_wallet_amount(&user_a.address(), &balance_a2_fail.as_ref())?; + chain_driver_a.assert_eventual_escrowed_amount_ics29( + &user_a.address(), + &balance_a2.as_ref(), + receive_fee_fail, + ack_fee, + timeout_fee, + )?; chain_driver_b.assert_eventual_wallet_amount( &user_b.address(), &denom_b.with_amount(0u128).as_ref(), )?; - chain_driver_a - .assert_eventual_wallet_amount(&user_a.address(), &(balance_a2_fail).as_ref())?; - chain_driver_a.assert_eventual_wallet_amount( &relayer_a.address(), &(relayer_balance_a).as_ref(), @@ -128,7 +120,7 @@ impl BinaryChannelTest for FilterIncentivizedFeesRelayerTest { { info!("Verify that packet with enough fees is relayed"); - let balance_a1 = chain_driver_a.query_balance(&user_a.address(), &denom_a)?; + let balance_a = chain_driver_a.query_balance(&user_a.address(), &denom_a)?; let relayer_balance_a = chain_driver_a.query_balance(&relayer_a.address(), &denom_a)?; let send_amount = random_u128_range(1000, 2000); @@ -136,10 +128,6 @@ impl BinaryChannelTest for FilterIncentivizedFeesRelayerTest { let ack_fee = random_u128_range(200, 300); let timeout_fee = random_u128_range(100, 200); - let total_sent_success = send_amount + receive_fee_success + ack_fee + timeout_fee; - - let balance_a2_success = balance_a1 - total_sent_success; - chain_driver_a.ibc_token_transfer_with_fee( &port_a, &channel_id_a, @@ -158,9 +146,6 @@ impl BinaryChannelTest for FilterIncentivizedFeesRelayerTest { &denom_a, )?; - chain_driver_a - .assert_eventual_wallet_amount(&user_a.address(), &balance_a2_success.as_ref())?; - chain_driver_b.assert_eventual_wallet_amount( &user_b.address(), &denom_b.with_amount(send_amount).as_ref(), @@ -170,6 +155,11 @@ impl BinaryChannelTest for FilterIncentivizedFeesRelayerTest { &relayer_a.address(), &(relayer_balance_a + receive_fee_success + ack_fee).as_ref(), )?; + + chain_driver_a.assert_eventual_wallet_amount( + &user_a.address(), + &(balance_a - send_amount - receive_fee_success - ack_fee).as_ref(), + )?; } Ok(()) @@ -234,9 +224,7 @@ impl BinaryChannelTest for FilterByChannelIncentivizedFeesRelayerTest { let ack_fee = random_u128_range(200, 300); let timeout_fee = random_u128_range(100, 200); - let total_sent = send_amount + receive_fee + ack_fee + timeout_fee; - - let balance_a2 = balance_a1 - total_sent; + let balance_a2 = balance_a1.clone() - send_amount; let denom_b = derive_ibc_denom( &channel.port_b.as_ref(), @@ -258,7 +246,13 @@ impl BinaryChannelTest for FilterByChannelIncentivizedFeesRelayerTest { Duration::from_secs(60), )?; - chain_driver_a.assert_eventual_wallet_amount(&user_a.address(), &balance_a2.as_ref())?; + chain_driver_a.assert_eventual_escrowed_amount_ics29( + &user_a.address(), + &balance_a2.as_ref(), + receive_fee, + ack_fee, + timeout_fee, + )?; chain_driver_b.assert_eventual_wallet_amount( &user_b.address(), @@ -267,7 +261,7 @@ impl BinaryChannelTest for FilterByChannelIncentivizedFeesRelayerTest { chain_driver_a.assert_eventual_wallet_amount( &user_a.address(), - &(balance_a2 + timeout_fee).as_ref(), + &(balance_a1 - send_amount - receive_fee - ack_fee).as_ref(), )?; chain_driver_a.assert_eventual_wallet_amount( diff --git a/tools/integration-test/src/tests/fee/forward_relayer.rs b/tools/integration-test/src/tests/fee/forward_relayer.rs index f9ec7da7be..daa5bcf317 100644 --- a/tools/integration-test/src/tests/fee/forward_relayer.rs +++ b/tools/integration-test/src/tests/fee/forward_relayer.rs @@ -9,10 +9,8 @@ //! correct parties involved in the transaction. use ibc_relayer_types::core::ics04_channel::version::Version; -use ibc_test_framework::{ - prelude::*, - util::random::random_u128_range, -}; +use ibc_test_framework::prelude::*; +use ibc_test_framework::util::random::random_u128_range; #[test] fn test_forward_relayer() -> Result<(), Error> { @@ -95,7 +93,7 @@ impl BinaryChannelTest for ForwardRelayerTest { let user_a = wallets_a.user1(); let user_b = wallets_b.user1(); - let balance_a1 = chain_driver_a.query_balance(&user_a.address(), &denom_a)?; + let balance_a = chain_driver_a.query_balance(&user_a.address(), &denom_a)?; let relayer_balance_a = chain_driver_a.query_balance(&relayer_a.address(), &denom_a)?; @@ -104,10 +102,6 @@ impl BinaryChannelTest for ForwardRelayerTest { let ack_fee = random_u128_range(200, 300); let timeout_fee = random_u128_range(100, 200); - let total_sent = send_amount + receive_fee + ack_fee + timeout_fee; - - let balance_a2 = balance_a1 - total_sent; - chain_driver_a.ibc_token_transfer_with_fee( &port_a, &channel_id_a, @@ -126,8 +120,6 @@ impl BinaryChannelTest for ForwardRelayerTest { &denom_a, )?; - chain_driver_a.assert_eventual_wallet_amount(&user_a.address(), &balance_a2.as_ref())?; - chain_driver_b.assert_eventual_wallet_amount( &user_b.address(), &denom_b.with_amount(send_amount).as_ref(), @@ -135,7 +127,7 @@ impl BinaryChannelTest for ForwardRelayerTest { chain_driver_a.assert_eventual_wallet_amount( &user_a.address(), - &(balance_a2 + timeout_fee).as_ref(), + &(balance_a - send_amount - receive_fee - ack_fee).as_ref(), )?; chain_driver_a.assert_eventual_wallet_amount( diff --git a/tools/integration-test/src/tests/fee/no_forward_relayer.rs b/tools/integration-test/src/tests/fee/no_forward_relayer.rs index 753546d212..8b840640e8 100644 --- a/tools/integration-test/src/tests/fee/no_forward_relayer.rs +++ b/tools/integration-test/src/tests/fee/no_forward_relayer.rs @@ -11,10 +11,8 @@ //! refunded to the payer. use ibc_relayer_types::core::ics04_channel::version::Version; -use ibc_test_framework::{ - prelude::*, - util::random::random_u128_range, -}; +use ibc_test_framework::prelude::*; +use ibc_test_framework::util::random::random_u128_range; #[test] fn test_no_forward_relayer() -> Result<(), Error> { @@ -73,7 +71,7 @@ impl BinaryChannelTest for NoForwardRelayerTest { let user_a = wallets_a.user1(); let user_b = wallets_b.user1(); - let balance_a1 = chain_driver_a.query_balance(&user_a.address(), &denom_a)?; + let balance_a = chain_driver_a.query_balance(&user_a.address(), &denom_a)?; let relayer_balance_a = chain_driver_a.query_balance(&relayer_a.address(), &denom_a)?; @@ -82,10 +80,6 @@ impl BinaryChannelTest for NoForwardRelayerTest { let ack_fee = random_u128_range(200, 300); let timeout_fee = random_u128_range(100, 200); - let total_sent = send_amount + receive_fee + ack_fee + timeout_fee; - - let balance_a2 = balance_a1 - total_sent; - chain_driver_a.ibc_token_transfer_with_fee( &port_a, &channel_id_a, @@ -104,8 +98,6 @@ impl BinaryChannelTest for NoForwardRelayerTest { &denom_a, )?; - chain_driver_a.assert_eventual_wallet_amount(&user_a.address(), &balance_a2.as_ref())?; - chain_driver_b.assert_eventual_wallet_amount( &user_b.address(), &denom_b.with_amount(send_amount).as_ref(), @@ -115,7 +107,7 @@ impl BinaryChannelTest for NoForwardRelayerTest { // as there is no counterparty address registered. chain_driver_a.assert_eventual_wallet_amount( &user_a.address(), - &(balance_a2 + receive_fee + timeout_fee).as_ref(), + &(balance_a - send_amount - ack_fee).as_ref(), )?; chain_driver_a.assert_eventual_wallet_amount( @@ -155,7 +147,7 @@ impl BinaryChannelTest for InvalidForwardRelayerTest { let user_a = wallets_a.user1(); let user_b = wallets_b.user1(); - let balance_a1 = chain_driver_a.query_balance(&user_a.address(), &denom_a)?; + let balance_a = chain_driver_a.query_balance(&user_a.address(), &denom_a)?; let relayer_balance_a = chain_driver_a.query_balance(&relayer_a.address(), &denom_a)?; @@ -164,10 +156,6 @@ impl BinaryChannelTest for InvalidForwardRelayerTest { let ack_fee = random_u128_range(200, 300); let timeout_fee = random_u128_range(100, 200); - let total_sent = send_amount + receive_fee + ack_fee + timeout_fee; - - let balance_a2 = balance_a1 - total_sent; - let invalid_address = MonoTagged::new(WalletAddress("a very long and invalid address".to_string())); @@ -196,18 +184,16 @@ impl BinaryChannelTest for InvalidForwardRelayerTest { &denom_a, )?; - chain_driver_a.assert_eventual_wallet_amount(&user_a.address(), &balance_a2.as_ref())?; - chain_driver_b.assert_eventual_wallet_amount( &user_b.address(), &denom_b.with_amount(send_amount).as_ref(), )?; // receive fee and timeout fee should be refunded, - // as thecounterparty address registered is invalid. + // as the counterparty address registered is invalid. chain_driver_a.assert_eventual_wallet_amount( &user_a.address(), - &(balance_a2 + receive_fee + timeout_fee).as_ref(), + &(balance_a - send_amount - ack_fee).as_ref(), )?; chain_driver_a.assert_eventual_wallet_amount( diff --git a/tools/integration-test/src/tests/fee/non_fee_channel.rs b/tools/integration-test/src/tests/fee/non_fee_channel.rs index be124078d1..b7b026ae3a 100644 --- a/tools/integration-test/src/tests/fee/non_fee_channel.rs +++ b/tools/integration-test/src/tests/fee/non_fee_channel.rs @@ -8,10 +8,8 @@ //! ensures then that the transaction still follows through using //! `ibc_transfer_token` if the transfer without fees is used. -use ibc_test_framework::{ - prelude::*, - util::random::random_u128_range, -}; +use ibc_test_framework::prelude::*; +use ibc_test_framework::util::random::random_u128_range; #[test] fn test_non_fee_channel() -> Result<(), Error> { diff --git a/tools/integration-test/src/tests/fee/pay_fee_async.rs b/tools/integration-test/src/tests/fee/pay_fee_async.rs index dc34d49e5f..dc8f5a816d 100644 --- a/tools/integration-test/src/tests/fee/pay_fee_async.rs +++ b/tools/integration-test/src/tests/fee/pay_fee_async.rs @@ -18,14 +18,10 @@ //! Finally, the test initializes the supervisor in order to relay the pending packets so that the //! balances on the two chains can be asserted. -use ibc_relayer_types::{ - core::ics04_channel::version::Version, - events::IbcEvent, -}; -use ibc_test_framework::{ - prelude::*, - util::random::random_u128_range, -}; +use ibc_relayer_types::core::ics04_channel::version::Version; +use ibc_relayer_types::events::IbcEvent; +use ibc_test_framework::prelude::*; +use ibc_test_framework::util::random::random_u128_range; #[test] fn test_pay_packet_fee_async() -> Result<(), Error> { @@ -109,13 +105,18 @@ impl BinaryChannelTest for PayPacketFeeAsyncTest { &denom_a.with_amount(receive_fee).as_ref(), &denom_a.with_amount(ack_fee).as_ref(), &denom_a.with_amount(timeout_fee).as_ref(), - Duration::from_secs(60), + Duration::from_secs(300), )?; - let total_sent = send_amount + receive_fee + ack_fee + timeout_fee; - let balance_a2 = balance_a1 - total_sent; + let balance_a2 = balance_a1.clone() - send_amount; - chain_driver_a.assert_eventual_wallet_amount(&user_a.address(), &balance_a2.as_ref())?; + chain_driver_a.assert_eventual_escrowed_amount_ics29( + &user_a.address(), + &balance_a2.clone().as_ref(), + receive_fee, + ack_fee, + timeout_fee, + )?; let sequence = { let send_packet_event = events @@ -211,10 +212,13 @@ impl BinaryChannelTest for PayPacketFeeAsyncTest { &denom_a.with_amount(timeout_fee_2).as_ref(), )?; - let total_sent_2 = receive_fee_2 + ack_fee_2 + timeout_fee_2; - let balance_a3 = balance_a2 - total_sent_2; - - chain_driver_a.assert_eventual_wallet_amount(&user_a.address(), &balance_a3.as_ref())?; + chain_driver_a.assert_eventual_escrowed_amount_ics29( + &user_a.address(), + &balance_a2.as_ref(), + receive_fee + receive_fee_2, + ack_fee + ack_fee_2, + timeout_fee + timeout_fee_2, + )?; { let event = events2 @@ -263,7 +267,8 @@ impl BinaryChannelTest for PayPacketFeeAsyncTest { chain_driver_a.assert_eventual_wallet_amount( &user_a.address(), - &(balance_a3 + timeout_fee + timeout_fee_2).as_ref(), + &(balance_a1 - send_amount - receive_fee - receive_fee_2 - ack_fee - ack_fee_2) + .as_ref(), )?; chain_driver_a.assert_eventual_wallet_amount( diff --git a/tools/integration-test/src/tests/fee/register_payee.rs b/tools/integration-test/src/tests/fee/register_payee.rs index 22c99bf2bd..638800c846 100644 --- a/tools/integration-test/src/tests/fee/register_payee.rs +++ b/tools/integration-test/src/tests/fee/register_payee.rs @@ -12,10 +12,8 @@ //! `ack_fee` in separate wallets. use ibc_relayer_types::core::ics04_channel::version::Version; -use ibc_test_framework::{ - prelude::*, - util::random::random_u128_range, -}; +use ibc_test_framework::prelude::*; +use ibc_test_framework::util::random::random_u128_range; #[test] fn test_register_payee() -> Result<(), Error> { @@ -109,7 +107,7 @@ impl BinaryChannelTest for ForwardRelayerTest { let user_a = wallets_a.user1(); let user_b = wallets_b.user1(); - let balance_a1 = chain_driver_a.query_balance(&user_a.address(), &denom_a)?; + let balance_a = chain_driver_a.query_balance(&user_a.address(), &denom_a)?; let relayer_balance_a = chain_driver_a.query_balance(&relayer_a.address(), &denom_a)?; let payee_balance_a = chain_driver_a.query_balance(&payee_a.address(), &denom_a)?; @@ -119,10 +117,6 @@ impl BinaryChannelTest for ForwardRelayerTest { let ack_fee = random_u128_range(200, 300); let timeout_fee = random_u128_range(100, 200); - let total_sent = send_amount + receive_fee + ack_fee + timeout_fee; - - let balance_a2 = balance_a1 - total_sent; - chain_driver_a.ibc_token_transfer_with_fee( &port_a, &channel_id_a, @@ -141,8 +135,6 @@ impl BinaryChannelTest for ForwardRelayerTest { &denom_a, )?; - chain_driver_a.assert_eventual_wallet_amount(&user_a.address(), &balance_a2.as_ref())?; - chain_driver_b.assert_eventual_wallet_amount( &user_b.address(), &denom_b.with_amount(send_amount).as_ref(), @@ -150,7 +142,7 @@ impl BinaryChannelTest for ForwardRelayerTest { chain_driver_a.assert_eventual_wallet_amount( &user_a.address(), - &(balance_a2 + timeout_fee).as_ref(), + &(balance_a - send_amount - receive_fee - ack_fee).as_ref(), )?; chain_driver_a.assert_eventual_wallet_amount( diff --git a/tools/integration-test/src/tests/fee/timeout_fee.rs b/tools/integration-test/src/tests/fee/timeout_fee.rs index 6bc533fe14..1d3068db01 100644 --- a/tools/integration-test/src/tests/fee/timeout_fee.rs +++ b/tools/integration-test/src/tests/fee/timeout_fee.rs @@ -2,13 +2,10 @@ //! the case that it relays a timeout packet when an `ibc_token_transfer_with_fee` //! operation times out. -use std::thread; - use ibc_relayer_types::core::ics04_channel::version::Version; -use ibc_test_framework::{ - prelude::*, - util::random::random_u128_range, -}; +use ibc_test_framework::prelude::*; +use ibc_test_framework::util::random::random_u128_range; +use std::thread; #[test] fn test_timeout_fee() -> Result<(), Error> { @@ -75,10 +72,6 @@ impl BinaryChannelTest for TimeoutFeeTest { Duration::from_secs(5), )?; - info!("Expect user A's balance after transfer: {}", balance_a2); - - chain_driver_a.assert_eventual_wallet_amount(&user_a.address(), &balance_a2.as_ref())?; - // Sleep to wait for IBC packet to timeout before start relaying thread::sleep(Duration::from_secs(6)); diff --git a/tools/integration-test/src/tests/fee_grant.rs b/tools/integration-test/src/tests/fee_grant.rs index 704185bf0e..a936c02e20 100644 --- a/tools/integration-test/src/tests/fee_grant.rs +++ b/tools/integration-test/src/tests/fee_grant.rs @@ -14,10 +14,8 @@ use std::thread; use ibc_relayer::config::ChainConfig; use ibc_relayer_types::bigint::U256; -use ibc_test_framework::{ - chain::ext::fee_grant::FeeGrantMethodsExt, - prelude::*, -}; +use ibc_test_framework::chain::ext::fee_grant::FeeGrantMethodsExt; +use ibc_test_framework::prelude::*; #[test] fn test_fee_grant() -> Result<(), Error> { @@ -44,7 +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 fee_denom_a = MonoTagged::new(Denom::base(config.native_token(0))); let a_to_b_amount = 12345u64; let granter = chains @@ -187,7 +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 fee_denom_a = MonoTagged::new(Denom::base(config.native_token(0))); let a_to_b_amount = 12345u64; let granter = chains diff --git a/tools/integration-test/src/tests/forward/forward_hop_transfer.rs b/tools/integration-test/src/tests/forward/forward_hop_transfer.rs index 432dc6bf0d..f42376c5b7 100644 --- a/tools/integration-test/src/tests/forward/forward_hop_transfer.rs +++ b/tools/integration-test/src/tests/forward/forward_hop_transfer.rs @@ -6,11 +6,7 @@ //! - The `AtomicIbcForwardHopTransferTest` tests the case where the //! hop between chain C and D fails. In this case the sender is still refunded. -use ibc_relayer::config::{ - self, - Config, - ModeConfig, -}; +use ibc_relayer::config::{self, ModeConfig}; use ibc_test_framework::prelude::*; use crate::tests::forward::memo::HopMemoField; @@ -57,7 +53,7 @@ impl NaryChannelTest<4> for IbcForwardHopTransferTest { chains: NaryConnectedChains, channels: NaryConnectedChannels, ) -> Result<(), Error> { - let connected_chains = chains.connected_chains_at::<0, 3>()?; + let connected_chains = chains.connected_chains_at::<0, 1>()?; let node_a = chains.full_node_at::<0>()?; let node_b = chains.full_node_at::<1>()?; @@ -178,7 +174,7 @@ impl NaryChannelTest<4> for AtomicIbcForwardHopTransferTest { chains: NaryConnectedChains, channels: NaryConnectedChannels, ) -> Result<(), Error> { - let connected_chains = chains.connected_chains_at::<0, 3>()?; + let connected_chains = chains.connected_chains_at::<0, 1>()?; let node_a = chains.full_node_at::<0>()?; let node_b = chains.full_node_at::<1>()?; diff --git a/tools/integration-test/src/tests/forward/forward_transfer.rs b/tools/integration-test/src/tests/forward/forward_transfer.rs index 93c0aced5a..a9569c8528 100644 --- a/tools/integration-test/src/tests/forward/forward_transfer.rs +++ b/tools/integration-test/src/tests/forward/forward_transfer.rs @@ -18,19 +18,11 @@ //! the memo fields are misspelled: //! - Misspelled receiver address, port or channel: The intermediary chain will refund the sender. -use ibc_relayer::config::{ - self, - Config, - ModeConfig, -}; +use ibc_relayer::config::{self, ModeConfig}; use ibc_test_framework::prelude::*; use crate::tests::forward::memo::{ - MemoField, - MemoInfo, - MemoMisspelledField, - MisspelledChannelMemoInfo, - MisspelledPortMemoInfo, + MemoField, MemoInfo, MemoMisspelledField, MisspelledChannelMemoInfo, MisspelledPortMemoInfo, MisspelledReceiverMemoInfo, }; @@ -81,7 +73,7 @@ impl NaryChannelTest<3> for IbcForwardTransferTest { chains: NaryConnectedChains, channels: NaryConnectedChannels, ) -> Result<(), Error> { - let connected_chains = chains.connected_chains_at::<0, 2>()?; + let connected_chains = chains.connected_chains_at::<0, 1>()?; let node_a = chains.full_node_at::<0>()?; let node_b = chains.full_node_at::<1>()?; @@ -184,7 +176,7 @@ impl NaryChannelTest<3> for MisspelledMemoFieldsIbcForwardTransferTest { chains: NaryConnectedChains, channels: NaryConnectedChannels, ) -> Result<(), Error> { - let connected_chains = chains.connected_chains_at::<0, 2>()?; + let connected_chains = chains.connected_chains_at::<0, 1>()?; let node_a = chains.full_node_at::<0>()?; let node_b = chains.full_node_at::<1>()?; @@ -430,7 +422,7 @@ impl NaryChannelTest<3> for MisspelledMemoContentIbcForwardTransferTest { chains: NaryConnectedChains, channels: NaryConnectedChannels, ) -> Result<(), Error> { - let connected_chains = chains.connected_chains_at::<0, 2>()?; + let connected_chains = chains.connected_chains_at::<0, 1>()?; let node_a = chains.full_node_at::<0>()?; let node_b = chains.full_node_at::<1>()?; diff --git a/tools/integration-test/src/tests/forward/memo.rs b/tools/integration-test/src/tests/forward/memo.rs index f581109f81..6f5b173592 100644 --- a/tools/integration-test/src/tests/forward/memo.rs +++ b/tools/integration-test/src/tests/forward/memo.rs @@ -2,10 +2,7 @@ //! The base structure of the memos are taken from //! https://github.com/strangelove-ventures/packet-forward-middleware#examples -use serde::{ - Deserialize, - Serialize, -}; +use serde::{Deserialize, Serialize}; pub trait HasForwardMemoInfo { fn new_memo(receiver: String, port: String, channel: String) -> Self; diff --git a/tools/integration-test/src/tests/handshake_on_start.rs b/tools/integration-test/src/tests/handshake_on_start.rs index 2ef80986ec..e5b744fc3d 100644 --- a/tools/integration-test/src/tests/handshake_on_start.rs +++ b/tools/integration-test/src/tests/handshake_on_start.rs @@ -2,16 +2,11 @@ use ibc_test_framework::{ prelude::*, relayer::{ channel::{ - ack_channel, - assert_eventually_channel_established, - init_channel, - init_channel_optimistic, - try_channel, + ack_channel, assert_eventually_channel_established, init_channel, + init_channel_optimistic, try_channel, }, connection::{ - ack_connection, - assert_eventually_connection_established, - init_connection, + ack_connection, assert_eventually_connection_established, init_connection, try_connection, }, }, diff --git a/tools/integration-test/src/tests/ica.rs b/tools/integration-test/src/tests/ica.rs index 47237bf578..0fe90d43ad 100644 --- a/tools/integration-test/src/tests/ica.rs +++ b/tools/integration-test/src/tests/ica.rs @@ -1,18 +1,30 @@ -use std::{ - collections::HashMap, - str::FromStr, -}; +use std::collections::HashMap; +use std::str::FromStr; -use ibc_test_framework::{ - chain::ext::ica::register_interchain_account, - ibc::denom::Denom, - prelude::*, - relayer::channel::{ - assert_eventually_channel_closed, - assert_eventually_channel_established, - query_channel_end, - }, +use ibc_relayer::config::{ + filter::{ChannelFilters, ChannelPolicy, FilterPattern}, + ChainConfig, PacketFilter, +}; +use ibc_relayer_types::applications::ics27_ica::packet_data::InterchainAccountPacketData; +use ibc_relayer_types::applications::{ + ics27_ica::cosmos_tx::CosmosTx, + transfer::{msgs::send::MsgSend, Amount, Coin}, +}; +use ibc_relayer_types::bigint::U256; +use ibc_relayer_types::core::ics04_channel::channel::State; +use ibc_relayer_types::signer::Signer; +use ibc_relayer_types::timestamp::Timestamp; +use ibc_relayer_types::tx_msg::Msg; + +use ibc_test_framework::chain::{ + config::add_allow_message_interchainaccounts, + ext::ica::{register_ordered_interchain_account, register_unordered_interchain_account}, +}; +use ibc_test_framework::prelude::*; +use ibc_test_framework::relayer::channel::{ + assert_eventually_channel_closed, assert_eventually_channel_established, query_channel_end, }; +use ibc_test_framework::util::interchain_security::interchain_send_tx; #[test] fn test_ica_filter_default() -> Result<(), Error> { @@ -35,6 +47,7 @@ fn test_ica_filter_deny() -> Result<(), Error> { run_binary_connection_test(&IcaFilterTestDeny) } +#[cfg(any(doc, feature = "new-register-interchain-account"))] #[test] fn test_ica_close_channel() -> Result<(), Error> { run_binary_connection_test(&ICACloseChannelTest) @@ -54,6 +67,7 @@ impl TestOverrides for IcaFilterTestAllow { // Enable channel workers and allow relaying on ICA channels fn modify_relayer_config(&self, config: &mut Config) { config.mode.channels.enabled = true; + config.mode.clients.misbehaviour = false; for chain in &mut config.chains { match chain { @@ -66,37 +80,26 @@ impl TestOverrides for IcaFilterTestAllow { // Allow MsgSend messages over ICA fn modify_genesis_file(&self, genesis: &mut serde_json::Value) -> Result<(), Error> { - use serde_json::Value; - - let allow_messages = genesis - .get_mut("app_state") - .and_then(|app_state| app_state.get_mut("interchainaccounts")) - .and_then(|ica| ica.get_mut("host_genesis_state")) - .and_then(|state| state.get_mut("params")) - .and_then(|params| params.get_mut("allow_messages")) - .and_then(|allow_messages| allow_messages.as_array_mut()); - - if let Some(allow_messages) = allow_messages { - allow_messages.push(Value::String("/cosmos.bank.v1beta1.MsgSend".to_string())); - Ok(()) - } else { - Err(Error::generic(eyre!("failed to update genesis file"))) - } + add_allow_message_interchainaccounts(genesis, "/cosmos.bank.v1beta1.MsgSend")?; + + Ok(()) } } impl BinaryConnectionTest for IcaFilterTestAllow { fn run( &self, - _config: &TestConfig, + config: &TestConfig, _relayer: RelayerDriver, chains: ConnectedChains, connection: ConnectedConnection, ) -> Result<(), Error> { + let fee_denom_host: MonoTagged = + MonoTagged::new(Denom::base(config.native_token(1))); // Register an interchain account on behalf of // controller wallet `user1` where the counterparty chain is the interchain accounts host. let (wallet, channel_id, port_id) = - register_interchain_account(&chains.node_a, chains.handle_a(), &connection)?; + register_unordered_interchain_account(&chains.node_a, chains.handle_a(), &connection)?; // Check that the corresponding ICA channel is eventually established. let _counterparty_channel_id = assert_eventually_channel_established( @@ -126,6 +129,7 @@ impl BinaryConnectionTest for IcaFilterTestAllow { &chains.node_b.wallets().user1(), &ica_address.as_ref(), &stake_denom.with_amount(ica_fund).as_ref(), + &fee_denom_host.with_amount(381000000u64).as_ref(), )?; chains.node_b.chain_driver().assert_eventual_wallet_amount( @@ -174,6 +178,7 @@ impl BinaryConnectionTest for IcaFilterTestAllow { Ok(()) } } + pub struct IcaFilterTestDeny; impl TestOverrides for IcaFilterTestDeny { @@ -206,7 +211,7 @@ impl BinaryConnectionTest for IcaFilterTestDeny { // Register an interchain account on behalf of controller wallet `user1` // where the counterparty chain is the interchain accounts host. let (_, channel_id, port_id) = - register_interchain_account(&chains.node_a, chains.handle_a(), &connection)?; + register_unordered_interchain_account(&chains.node_a, chains.handle_a(), &connection)?; // Wait a bit, the relayer will refuse to complete the channel handshake // because the port is explicitly disallowed by the filter. @@ -241,18 +246,24 @@ impl TestOverrides for ICACloseChannelTest { impl BinaryConnectionTest for ICACloseChannelTest { fn run( &self, - _config: &TestConfig, + config: &TestConfig, relayer: RelayerDriver, chains: ConnectedChains, connection: ConnectedConnection, ) -> Result<(), Error> { + let fee_denom_host: MonoTagged = + MonoTagged::new(Denom::base(config.native_token(1))); let stake_denom: MonoTagged = MonoTagged::new(Denom::base("stake")); let (wallet, ica_address, controller_channel_id, controller_port_id) = relayer .with_supervisor(|| { // Register an interchain account on behalf of // controller wallet `user1` where the counterparty chain is the interchain accounts host. let (wallet, controller_channel_id, controller_port_id) = - register_interchain_account(&chains.node_a, chains.handle_a(), &connection)?; + register_ordered_interchain_account( + &chains.node_a, + chains.handle_a(), + &connection, + )?; // Check that the corresponding ICA channel is eventually established. let _counterparty_channel_id = assert_eventually_channel_established( @@ -288,6 +299,7 @@ impl BinaryConnectionTest for ICACloseChannelTest { &chains.node_b.wallets().user1(), &ica_address.as_ref(), &stake_denom.with_amount(ica_fund).as_ref(), + &fee_denom_host.with_amount(381000000u64).as_ref(), )?; chains.node_b.chain_driver().assert_eventual_wallet_amount( @@ -360,26 +372,3 @@ impl BinaryConnectionTest for ICACloseChannelTest { }) } } - -fn interchain_send_tx( - chain: &ChainA, - from: &Signer, - connection: &ConnectionId, - msg: InterchainAccountPacketData, - relative_timeout: Timestamp, -) -> Result, Error> { - let msg = MsgSendTx { - owner: from.clone(), - connection_id: connection.clone(), - packet_data: msg, - relative_timeout, - }; - - let msg_any = msg.to_any(); - - let tm = TrackedMsgs::new_static(vec![msg_any], "SendTx"); - - chain - .send_messages_and_wait_commit(tm) - .map_err(Error::relayer) -} diff --git a/tools/integration-test/src/tests/ics20_filter/memo.rs b/tools/integration-test/src/tests/ics20_filter/memo.rs index c8e2b30b0e..0ec207af37 100644 --- a/tools/integration-test/src/tests/ics20_filter/memo.rs +++ b/tools/integration-test/src/tests/ics20_filter/memo.rs @@ -1,4 +1,5 @@ use byte_unit::Byte; + use ibc_relayer::config::types::ics20_field_size_limit::Ics20FieldSizeLimit; use ibc_test_framework::prelude::*; diff --git a/tools/integration-test/src/tests/ics31.rs b/tools/integration-test/src/tests/ics31.rs index f79830bed7..33065dc091 100644 --- a/tools/integration-test/src/tests/ics31.rs +++ b/tools/integration-test/src/tests/ics31.rs @@ -9,25 +9,18 @@ //! The test then waits for a Cross-chain Query to be pending and //! then processed. -use ibc_relayer::config::{ - self, - ModeConfig, -}; -use ibc_test_framework::{ - chain::{ - cli::host_zone::register_host_zone, - config::{ - set_crisis_denom, - set_mint_mint_denom, - set_staking_bond_denom, - set_staking_max_entries, - set_voting_period, - }, - ext::crosschainquery::CrossChainQueryMethodsExt, +use ibc_relayer::config::{self, ModeConfig}; + +use ibc_test_framework::chain::{ + cli::host_zone::register_host_zone, + config::{ + set_crisis_denom, set_mint_mint_denom, set_staking_bond_denom, set_staking_max_entries, + set_voting_period, }, - prelude::*, - util::random::random_u128_range, + ext::crosschainquery::CrossChainQueryMethodsExt, }; +use ibc_test_framework::prelude::*; +use ibc_test_framework::util::random::random_u128_range; #[test] fn test_ics31_cross_chain_queries() -> Result<(), Error> { diff --git a/tools/integration-test/src/tests/interchain_security/dynamic_gas_fee.rs b/tools/integration-test/src/tests/interchain_security/dynamic_gas_fee.rs new file mode 100644 index 0000000000..3d2f217554 --- /dev/null +++ b/tools/integration-test/src/tests/interchain_security/dynamic_gas_fee.rs @@ -0,0 +1,255 @@ +//! The [`DynamicGasTest`] test ensures that the [`DynamicGas`] +//! configuration works correctly. The test can enable or disable the dynamic +//! gas price for the second chain. +//! +//! To test dynamic gas configuration, it will enable dynamic gas price on the +//! second chain only. It will then create and relay a first IBC transfer with a +//! big memo. The gas fee paid is then recorded. +//! A second IBC transfer without memo will then be relayed. The gas fee paid +//! will also be recorded. The test will assert that the Tx with a big memo +//! and dynamic gas enabled is lower than the Tx without memo and dynamic gas +//! disabled. +//! +//! The second test disables the dynamic gas price on both chains in +//! order to ensure that the first IBC transfer will cost more if dynamic +//! gas is disabled. + +use ibc_relayer::config::dynamic_gas::DynamicGasPrice; +use ibc_relayer::config::gas_multiplier::GasMultiplier; +use ibc_relayer::config::ChainConfig; +use ibc_relayer::config::GasPrice; +use ibc_test_framework::framework::binary::channel::run_binary_interchain_security_channel_test; +use ibc_test_framework::prelude::*; +use ibc_test_framework::util::interchain_security::update_genesis_for_consumer_chain; +use ibc_test_framework::util::interchain_security::update_relayer_config_for_consumer_chain; + +#[test] +fn test_fee_market_dynamic_gas_transfer() -> Result<(), Error> { + run_binary_interchain_security_channel_test(&DynamicGasTest { + dynamic_gas_enabled: true, + }) +} + +#[test] +fn test_fee_market_static_gas_transfer() -> Result<(), Error> { + run_binary_interchain_security_channel_test(&DynamicGasTest { + dynamic_gas_enabled: false, + }) +} + +const MEMO_CHAR: &str = "a"; +const MEMO_SIZE: usize = 10000; + +pub struct DynamicGasTest { + dynamic_gas_enabled: bool, +} + +impl TestOverrides for DynamicGasTest { + fn modify_genesis_file(&self, genesis: &mut serde_json::Value) -> Result<(), Error> { + update_genesis_for_consumer_chain(genesis)?; + // This is a configuration specifically for chains with feemarket + if genesis + .get_mut("app_state") + .and_then(|app_state| app_state.get("feemarket")) + .is_some() + { + let params = genesis + .get_mut("app_state") + .and_then(|app_state| app_state.get_mut("feemarket")) + .and_then(|feemarket| feemarket.get_mut("params")) + .and_then(|params| params.as_object_mut()) + .ok_or_else(|| eyre!("failed to get feemarket params in genesis file"))?; + params.insert( + "min_base_fee".to_owned(), + serde_json::Value::String("0.0025".to_owned()), + ); + } + + Ok(()) + } + + // The `ccv_consumer_chain` must be `true` for the Consumer chain. + // The `trusting_period` must be strictly smaller than the `unbonding_period` + // specified in the Consumer chain proposal. The test framework uses 100s in + // the proposal. + fn modify_relayer_config(&self, config: &mut Config) { + config.mode.clients.misbehaviour = false; + config.mode.clients.refresh = false; + config.mode.packets.clear_interval = 0; + + update_relayer_config_for_consumer_chain(config); + + match &mut config.chains[0] { + ChainConfig::CosmosSdk(chain_config_a) => { + chain_config_a.gas_price = + GasPrice::new(0.3, chain_config_a.gas_price.denom.clone()); + + chain_config_a.dynamic_gas_price = DynamicGasPrice::unsafe_new(false, 1.1, 0.6); + } + } + + match &mut config.chains[1] { + ChainConfig::CosmosSdk(chain_config_b) => { + chain_config_b.gas_price = + GasPrice::new(0.3, chain_config_b.gas_price.denom.clone()); + + chain_config_b.gas_multiplier = Some(GasMultiplier::unsafe_new(1.8)); + + chain_config_b.dynamic_gas_price = + DynamicGasPrice::unsafe_new(self.dynamic_gas_enabled, 1.1, 0.6); + } + } + } + + fn should_spawn_supervisor(&self) -> bool { + false + } +} + +impl BinaryChannelTest for DynamicGasTest { + fn run( + &self, + _config: &TestConfig, + relayer: RelayerDriver, + chains: ConnectedChains, + channel: ConnectedChannel, + ) -> Result<(), Error> { + 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 a_to_b_amount = 12345u64; + + let denom_a_to_b = derive_ibc_denom( + &channel.port_b.as_ref(), + &channel.channel_id_b.as_ref(), + &denom_a, + )?; + + let gas_denom_a: MonoTagged = + MonoTagged::new(Denom::Base("stake".to_owned())); + let gas_denom_b: MonoTagged = + MonoTagged::new(Denom::Base("stake".to_owned())); + + let balance_relayer_b_before = chains.node_b.chain_driver().query_balance( + &chains.node_b.wallets().relayer().address(), + &gas_denom_b.as_ref(), + )?; + + let memo: String = MEMO_CHAR.repeat(MEMO_SIZE); + + chains + .node_a + .chain_driver() + .ibc_transfer_token_with_memo_and_timeout( + &channel.port_a.as_ref(), + &channel.channel_id_a.as_ref(), + &wallet_a.as_ref(), + &wallet_b.address(), + &denom_a.with_amount(a_to_b_amount).as_ref(), + Some(memo), + None, + )?; + + // Do a simple IBC transfer with the dynamic gas configuration + let tx1_paid_gas_relayer = relayer.with_supervisor(|| { + // Assert that user on chain B received the tokens + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &wallet_b.address(), + &denom_a_to_b.with_amount(a_to_b_amount).as_ref(), + )?; + + // Wait for a bit before querying the new balance + sleep(Duration::from_secs(5)); + + let balance_relayer_b_after = chains.node_b.chain_driver().query_balance( + &chains.node_b.wallets().relayer().address(), + &gas_denom_b.as_ref(), + )?; + + let paid_fees_relayer_b = balance_relayer_b_before + .amount() + .checked_sub(balance_relayer_b_after.amount()); + + assert!( + paid_fees_relayer_b.is_some(), + "subtraction between queried amounts for relayer should be Some" + ); + + info!("IBC transfer with memo was successful"); + + Ok(paid_fees_relayer_b.unwrap()) + })?; + + let b_to_a_amount = 23456u64; + let denom_b = chains.node_b.denom(); + + let denom_b_to_a = derive_ibc_denom( + &channel.port_a.as_ref(), + &channel.channel_id_a.as_ref(), + &denom_b, + )?; + + let balance_relayer_a_before = chains.node_a.chain_driver().query_balance( + &chains.node_a.wallets().relayer().address(), + &gas_denom_a.as_ref(), + )?; + + info!("Will ibc transfer"); + + chains.node_b.chain_driver().ibc_transfer_token( + &channel.port_b.as_ref(), + &channel.channel_id_b.as_ref(), + &chains.node_b.wallets().user1(), + &chains.node_a.wallets().user1().address(), + &denom_b.with_amount(b_to_a_amount).as_ref(), + )?; + + info!("Done ibc transfer"); + + let tx2_paid_gas_relayer = relayer.with_supervisor(|| { + // Assert that user on chain B received the tokens + chains.node_a.chain_driver().assert_eventual_wallet_amount( + &chains.node_a.wallets().user1().address(), + &denom_b_to_a.with_amount(b_to_a_amount).as_ref(), + )?; + + // Wait for a bit before querying the new balance + sleep(Duration::from_secs(5)); + + let balance_relayer_a_after = chains.node_a.chain_driver().query_balance( + &chains.node_a.wallets().relayer().address(), + &gas_denom_a.as_ref(), + )?; + + let paid_fees_relayer_a = balance_relayer_a_before + .amount() + .checked_sub(balance_relayer_a_after.amount()); + + assert!( + paid_fees_relayer_a.is_some(), + "subtraction between queried amounts for relayer should be Some" + ); + + info!("IBC transfer without memo was successful"); + + Ok(paid_fees_relayer_a.unwrap()) + })?; + + info!("paid gas fees for Tx with memo `{tx1_paid_gas_relayer}`, without memo `{tx2_paid_gas_relayer}`"); + + if self.dynamic_gas_enabled { + assert!( + tx1_paid_gas_relayer < tx2_paid_gas_relayer, + "with dynamic gas enabled, gas paid for the first TX should be lower" + ); + } else { + assert!( + tx1_paid_gas_relayer > tx2_paid_gas_relayer, + "with dynamic gas disabled, gas paid for the second TX should be lower" + ); + } + + Ok(()) + } +} diff --git a/tools/integration-test/src/tests/interchain_security/ica_ordered_channel.rs b/tools/integration-test/src/tests/interchain_security/ica_ordered_channel.rs new file mode 100644 index 0000000000..7498d724f2 --- /dev/null +++ b/tools/integration-test/src/tests/interchain_security/ica_ordered_channel.rs @@ -0,0 +1,217 @@ +//! Verifies the behaviour of ordered channels with Interchain Accounts. +//! +//! In order to ensure that ordered channels correctly clear packets on ICA +//! channels, this test sends some sequential packets with the supervisor enabled, +//! sends the next packet *without* the supervisor enabled, then sends additional +//! packets with the supervisor enabled again. The pending packet that was sent +//! without the supervisor enabled should be relayed in order along with the +//! other packets, as expected of ordered channel behaviour. + +use std::str::FromStr; + +use ibc_relayer_types::applications::ics27_ica::cosmos_tx::CosmosTx; +use ibc_relayer_types::applications::ics27_ica::packet_data::InterchainAccountPacketData; +use ibc_relayer_types::applications::transfer::msgs::send::MsgSend; +use ibc_relayer_types::applications::transfer::{Amount, Coin}; +use ibc_relayer_types::bigint::U256; +use ibc_relayer_types::signer::Signer; +use ibc_relayer_types::timestamp::Timestamp; +use ibc_relayer_types::tx_msg::Msg; +use ibc_test_framework::chain::config::add_allow_message_interchainaccounts; +use ibc_test_framework::chain::ext::ica::register_ordered_interchain_account; +use ibc_test_framework::framework::binary::channel::run_binary_interchain_security_channel_test; +use ibc_test_framework::prelude::*; +use ibc_test_framework::relayer::channel::assert_eventually_channel_established; +use ibc_test_framework::relayer::channel::query_channel_end; +use ibc_test_framework::util::interchain_security::{ + interchain_send_tx, update_genesis_for_consumer_chain, update_relayer_config_for_consumer_chain, +}; + +#[test] +fn test_ica_ordered_channel() -> Result<(), Error> { + run_binary_interchain_security_channel_test(&IcaOrderedChannelTest) +} + +struct IcaOrderedChannelTest; + +impl TestOverrides for IcaOrderedChannelTest { + fn modify_genesis_file(&self, genesis: &mut serde_json::Value) -> Result<(), Error> { + add_allow_message_interchainaccounts(genesis, "/cosmos.bank.v1beta1.MsgSend")?; + update_genesis_for_consumer_chain(genesis)?; + + Ok(()) + } + + fn modify_relayer_config(&self, config: &mut Config) { + config.mode.clients.misbehaviour = false; + + config.mode.channels.enabled = true; + + // Disable packet clearing so that packets sent without the supervisor + // enabled enter a pending state. + config.mode.packets.enabled = true; + config.mode.packets.clear_on_start = false; + config.mode.packets.clear_interval = 0; + // This is needed for ordered channels + config.mode.packets.force_disable_clear_on_start = true; + + update_relayer_config_for_consumer_chain(config); + } + + fn should_spawn_supervisor(&self) -> bool { + false + } +} + +impl BinaryChannelTest for IcaOrderedChannelTest { + fn run( + &self, + config: &TestConfig, + relayer: RelayerDriver, + chains: ConnectedChains, + channel: ConnectedChannel, + ) -> Result<(), Error> { + let fee_denom_a: MonoTagged = + MonoTagged::new(Denom::base(config.native_token(0))); + let connection_b_to_a = channel.connection.clone().flip(); + let (wallet, channel_id, port_id) = register_ordered_interchain_account( + &chains.node_b, + chains.handle_b(), + &connection_b_to_a, + )?; + + relayer.with_supervisor(|| { + // Check that the corresponding ICA channel is eventually established. + let _counterparty_channel_id = assert_eventually_channel_established( + chains.handle_b(), + chains.handle_a(), + &channel_id.as_ref(), + &port_id.as_ref(), + )?; + + Ok(()) + })?; + + // Assert that the channel returned by `register_interchain_account` is an ordered channel + let channel_end = + query_channel_end(chains.handle_b(), &channel_id.as_ref(), &port_id.as_ref())?; + + assert_eq!(channel_end.value().ordering(), &Ordering::Ordered); + + // Query the controller chain for the address of the ICA wallet on the host chain. + let ica_address = chains.node_b.chain_driver().query_interchain_account( + &wallet.address(), + &channel.connection.connection_id_b.as_ref(), + )?; + + let stake_denom: MonoTagged = MonoTagged::new(Denom::base("stake")); + + chains.node_a.chain_driver().assert_eventual_wallet_amount( + &ica_address.as_ref(), + &stake_denom.with_amount(0u64).as_ref(), + )?; + + // Send funds to the interchain account. + let ica_fund = 42000u64; + + chains.node_a.chain_driver().local_transfer_token( + &chains.node_a.wallets().user1(), + &ica_address.as_ref(), + &stake_denom.with_amount(ica_fund).as_ref(), + &fee_denom_a.with_amount(381000000u64).as_ref(), + )?; + + chains.node_a.chain_driver().assert_eventual_wallet_amount( + &ica_address.as_ref(), + &stake_denom.with_amount(ica_fund).as_ref(), + )?; + + let amount = 1200; + + let msg = MsgSend { + from_address: ica_address.to_string(), + to_address: chains.node_a.wallets().user2().address().to_string(), + amount: vec![Coin { + denom: stake_denom.to_string(), + amount: Amount(U256::from(amount)), + }], + }; + + let raw_msg = msg.to_any(); + + let cosmos_tx = CosmosTx { + messages: vec![raw_msg], + }; + + let raw_cosmos_tx = cosmos_tx.to_any(); + + let interchain_account_packet_data = InterchainAccountPacketData::new(raw_cosmos_tx.value); + + let signer = Signer::from_str(&wallet.address().to_string()).unwrap(); + + let user2_balance = chains.node_a.chain_driver().query_balance( + &chains.node_a.wallets().user2().address(), + &stake_denom.as_ref(), + )?; + + relayer.with_supervisor(|| { + let ica_events = interchain_send_tx( + chains.handle_b(), + &signer, + &channel.connection.connection_id_b.0, + interchain_account_packet_data.clone(), + Timestamp::from_nanoseconds(120000000000).unwrap(), + )?; + + // Check that the ICA account's balance has been debited the sent amount. + chains.node_a.chain_driver().assert_eventual_wallet_amount( + &ica_address.as_ref(), + &stake_denom.with_amount(ica_fund - amount).as_ref(), + )?; + + chains.node_a.chain_driver().assert_eventual_wallet_amount( + &chains.node_a.wallets().user2().address(), + &(user2_balance.clone() + amount).as_ref(), + )?; + + info!("First ICA transfer made with supervisor: {ica_events:#?}"); + + Ok(()) + })?; + + let ica_events = interchain_send_tx( + chains.handle_b(), + &signer, + &channel.connection.connection_id_b.0, + interchain_account_packet_data.clone(), + Timestamp::from_nanoseconds(120000000000).unwrap(), + )?; + + info!("Second ICA transfer made without supervisor: {ica_events:#?}"); + + relayer.with_supervisor(|| { + let ica_events = interchain_send_tx( + chains.handle_b(), + &signer, + &channel.connection.connection_id_b.0, + interchain_account_packet_data, + Timestamp::from_nanoseconds(120000000000).unwrap(), + )?; + + // Check that the ICA account's balance has been debited the sent amount. + chains.node_a.chain_driver().assert_eventual_wallet_amount( + &ica_address.as_ref(), + &stake_denom.with_amount(ica_fund - 3 * amount).as_ref(), + )?; + + info!("Third ICA transfer made with supervisor: {ica_events:#?}"); + + chains.node_a.chain_driver().assert_eventual_wallet_amount( + &chains.node_a.wallets().user2().address(), + &(user2_balance + (3 * amount)).as_ref(), + )?; + + Ok(()) + }) + } +} diff --git a/tools/integration-test/src/tests/interchain_security/ica_transfer.rs b/tools/integration-test/src/tests/interchain_security/ica_transfer.rs index 583d247561..ec12f6b591 100644 --- a/tools/integration-test/src/tests/interchain_security/ica_transfer.rs +++ b/tools/integration-test/src/tests/interchain_security/ica_transfer.rs @@ -3,37 +3,21 @@ //! the second chain a Consumer chain. use std::str::FromStr; -use ibc_relayer::{ - chain::tracking::TrackedMsgs, - event::IbcEventWithHeight, -}; -use ibc_relayer_types::{ - applications::{ - ics27_ica::{ - cosmos_tx::CosmosTx, - msgs::send_tx::MsgSendTx, - packet_data::InterchainAccountPacketData, - }, - transfer::{ - msgs::send::MsgSend, - Amount, - Coin, - }, - }, - bigint::U256, - signer::Signer, - timestamp::Timestamp, - tx_msg::Msg, -}; -use ibc_test_framework::{ - chain::ext::ica::register_interchain_account, - framework::binary::channel::run_binary_interchain_security_channel_test, - prelude::*, - relayer::channel::assert_eventually_channel_established, - util::interchain_security::{ - update_genesis_for_consumer_chain, - update_relayer_config_for_consumer_chain, - }, +use ibc_relayer_types::applications::ics27_ica::cosmos_tx::CosmosTx; +use ibc_relayer_types::applications::ics27_ica::packet_data::InterchainAccountPacketData; +use ibc_relayer_types::applications::transfer::msgs::send::MsgSend; +use ibc_relayer_types::applications::transfer::{Amount, Coin}; +use ibc_relayer_types::bigint::U256; +use ibc_relayer_types::signer::Signer; +use ibc_relayer_types::timestamp::Timestamp; +use ibc_relayer_types::tx_msg::Msg; +use ibc_test_framework::chain::config::add_allow_message_interchainaccounts; +use ibc_test_framework::chain::ext::ica::register_unordered_interchain_account; +use ibc_test_framework::framework::binary::channel::run_binary_interchain_security_channel_test; +use ibc_test_framework::prelude::*; +use ibc_test_framework::relayer::channel::assert_eventually_channel_established; +use ibc_test_framework::util::interchain_security::{ + interchain_send_tx, update_genesis_for_consumer_chain, update_relayer_config_for_consumer_chain, }; #[test] @@ -45,23 +29,7 @@ struct InterchainSecurityIcaTransferTest; impl TestOverrides for InterchainSecurityIcaTransferTest { fn modify_genesis_file(&self, genesis: &mut serde_json::Value) -> Result<(), Error> { - use serde_json::Value; - - // Allow MsgSend messages over ICA - let allow_messages = genesis - .get_mut("app_state") - .and_then(|app_state| app_state.get_mut("interchainaccounts")) - .and_then(|ica| ica.get_mut("host_genesis_state")) - .and_then(|state| state.get_mut("params")) - .and_then(|params| params.get_mut("allow_messages")) - .and_then(|allow_messages| allow_messages.as_array_mut()); - - if let Some(allow_messages) = allow_messages { - allow_messages.push(Value::String("/cosmos.bank.v1beta1.MsgSend".to_string())); - } else { - return Err(Error::generic(eyre!("failed to update genesis file"))); - } - + add_allow_message_interchainaccounts(genesis, "/cosmos.bank.v1beta1.MsgSend")?; update_genesis_for_consumer_chain(genesis)?; Ok(()) @@ -81,14 +49,19 @@ impl TestOverrides for InterchainSecurityIcaTransferTest { impl BinaryChannelTest for InterchainSecurityIcaTransferTest { fn run( &self, - _config: &TestConfig, + config: &TestConfig, _relayer: RelayerDriver, chains: ConnectedChains, channel: ConnectedChannel, ) -> Result<(), Error> { + let fee_denom_a: MonoTagged = + MonoTagged::new(Denom::base(config.native_token(0))); let connection_b_to_a = channel.connection.clone().flip(); - let (wallet, channel_id, port_id) = - register_interchain_account(&chains.node_b, chains.handle_b(), &connection_b_to_a)?; + let (wallet, channel_id, port_id) = register_unordered_interchain_account( + &chains.node_b, + chains.handle_b(), + &connection_b_to_a, + )?; // Check that the corresponding ICA channel is eventually established. let _counterparty_channel_id = assert_eventually_channel_established( @@ -118,6 +91,7 @@ impl BinaryChannelTest for InterchainSecurityIcaTransferTest { &chains.node_a.wallets().user1(), &ica_address.as_ref(), &stake_denom.with_amount(ica_fund).as_ref(), + &fee_denom_a.with_amount(381000000u64).as_ref(), )?; chains.node_a.chain_driver().assert_eventual_wallet_amount( @@ -165,29 +139,7 @@ impl BinaryChannelTest for InterchainSecurityIcaTransferTest { &ica_address.as_ref(), &stake_denom.with_amount(ica_fund - amount).as_ref(), )?; + Ok(()) } } - -fn interchain_send_tx( - chain: &ChainA, - from: &Signer, - connection: &ConnectionId, - msg: InterchainAccountPacketData, - relative_timeout: Timestamp, -) -> Result, Error> { - let msg = MsgSendTx { - owner: from.clone(), - connection_id: connection.clone(), - packet_data: msg, - relative_timeout, - }; - - let msg_any = msg.to_any(); - - let tm = TrackedMsgs::new_static(vec![msg_any], "SendTx"); - - chain - .send_messages_and_wait_commit(tm) - .map_err(Error::relayer) -} diff --git a/tools/integration-test/src/tests/interchain_security/icq.rs b/tools/integration-test/src/tests/interchain_security/icq.rs index 79c94660d6..19f2a84efb 100644 --- a/tools/integration-test/src/tests/interchain_security/icq.rs +++ b/tools/integration-test/src/tests/interchain_security/icq.rs @@ -9,39 +9,36 @@ //! The test then waits for a Cross-chain Query to be pending and //! then processed. -use ibc_relayer::config::{ - self, - ModeConfig, +use ibc_relayer::config::ChainConfig; +use ibc_test_framework::chain::cli::host_zone::register_host_zone; +use ibc_test_framework::chain::config::{ + set_crisis_denom, set_mint_mint_denom, set_staking_bond_denom, set_staking_max_entries, + set_voting_period, }; -use ibc_test_framework::{ - chain::{ - cli::host_zone::register_host_zone, - config::{ - set_crisis_denom, - set_mint_mint_denom, - set_staking_bond_denom, - set_staking_max_entries, - set_voting_period, - }, - ext::crosschainquery::CrossChainQueryMethodsExt, - }, - framework::binary::channel::run_binary_interchain_security_channel_test, - prelude::*, - util::{ - interchain_security::{ - update_genesis_for_consumer_chain, - update_relayer_config_for_consumer_chain, - }, - random::random_u128_range, - }, +use ibc_test_framework::chain::ext::crosschainquery::CrossChainQueryMethodsExt; +use ibc_test_framework::framework::binary::channel::run_binary_interchain_security_channel_test; +use ibc_test_framework::prelude::*; +use ibc_test_framework::relayer::channel::{ + assert_eventually_channel_established, query_identified_channel_ends, }; +use ibc_test_framework::util::interchain_security::{ + update_genesis_for_consumer_chain, update_relayer_config_for_consumer_chain, +}; +use ibc_test_framework::util::random::random_u128_range; #[test] fn test_ics31_cross_chain_queries() -> Result<(), Error> { - run_binary_interchain_security_channel_test(&InterchainSecurityIcqTest) + run_binary_interchain_security_channel_test(&InterchainSecurityIcqTest { allow_ccq: true }) } -struct InterchainSecurityIcqTest; +#[test] +fn test_disable_ics31_cross_chain_queries() -> Result<(), Error> { + run_binary_interchain_security_channel_test(&InterchainSecurityIcqTest { allow_ccq: false }) +} + +struct InterchainSecurityIcqTest { + pub allow_ccq: bool, +} impl TestOverrides for InterchainSecurityIcqTest { fn modify_genesis_file(&self, genesis: &mut serde_json::Value) -> Result<(), Error> { @@ -62,7 +59,14 @@ impl TestOverrides for InterchainSecurityIcqTest { .get_mut("duration") .ok_or_else(|| eyre!("failed to get duration"))?; - *duration = serde_json::Value::String("20s".to_owned()); + *duration = serde_json::Value::String("25s".to_owned()); + } else if identifier.as_str() == Some("day") { + // The stride epoch must be 1/4th the length of the day epoch + let duration = v + .get_mut("duration") + .ok_or_else(|| eyre!("failed to get duration"))?; + + *duration = serde_json::Value::String("100s".to_owned()); } } set_voting_period(genesis, 10)?; @@ -80,13 +84,19 @@ impl TestOverrides for InterchainSecurityIcqTest { // When calling `strided tx stakeibc register-host-zone` new channel // will be created. So the channel worker needs to be enabled. fn modify_relayer_config(&self, config: &mut Config) { - config.mode = ModeConfig { - connections: config::Connections { enabled: false }, - channels: config::Channels { enabled: true }, - ..Default::default() - }; + config.mode.clients.misbehaviour = false; + config.mode.connections.enabled = true; + config.mode.channels.enabled = true; update_relayer_config_for_consumer_chain(config); + + for chain in config.chains.iter_mut() { + match chain { + ChainConfig::CosmosSdk(chain_config) => { + chain_config.allow_ccq = self.allow_ccq; + } + } + } } } @@ -147,6 +157,33 @@ impl BinaryChannelTest for InterchainSecurityIcqTest { &wallet_b.0.id.to_string(), )?; + // Wait for channel to initialise so that the query can find + // all the channels related to registering a host-zone + std::thread::sleep(Duration::from_secs(5)); + + let channels = query_identified_channel_ends::(chains.handle_a())?; + + // Wait for channel created by registering a host-zone to be Open + for channel in channels.iter() { + let tagged_channel_id: TaggedChannelId = + DualTagged::new(channel.0.channel_id.clone()); + let tagged_port_id: TaggedPortId = + DualTagged::new(channel.0.port_id.clone()); + + if channel.0.port_id.as_str() == "icahost" { + info!( + "Will assert that channel {}/{} is eventually Open", + channel.0.channel_id, channel.0.port_id + ); + assert_eventually_channel_established( + chains.handle_a(), + chains.handle_b(), + &tagged_channel_id.as_ref(), + &tagged_port_id.as_ref(), + )?; + } + } + // Wait for the cross chain query to be pending. chains .node_b @@ -154,10 +191,17 @@ impl BinaryChannelTest for InterchainSecurityIcqTest { .assert_pending_cross_chain_query()?; // After there is a pending cross chain query, wait for it to be processed - chains + let processed_ccqs = chains .node_b .chain_driver() - .assert_processed_cross_chain_query()?; + .assert_processed_cross_chain_query(); + + if self.allow_ccq { + assert!(processed_ccqs.is_ok()); + } else { + assert!(processed_ccqs.is_err()); + } + Ok(()) } } diff --git a/tools/integration-test/src/tests/interchain_security/mod.rs b/tools/integration-test/src/tests/interchain_security/mod.rs index a2acc74d92..6081fc7e53 100644 --- a/tools/integration-test/src/tests/interchain_security/mod.rs +++ b/tools/integration-test/src/tests/interchain_security/mod.rs @@ -1,3 +1,7 @@ +#[cfg(any(doc, feature = "dynamic-gas-fee"))] +pub mod dynamic_gas_fee; +#[cfg(any(doc, feature = "ica"))] +pub mod ica_ordered_channel; #[cfg(any(doc, feature = "ica"))] pub mod ica_transfer; #[cfg(any(doc, feature = "ics31"))] diff --git a/tools/integration-test/src/tests/interchain_security/simple_transfer.rs b/tools/integration-test/src/tests/interchain_security/simple_transfer.rs index cc3a437457..05317917ed 100644 --- a/tools/integration-test/src/tests/interchain_security/simple_transfer.rs +++ b/tools/integration-test/src/tests/interchain_security/simple_transfer.rs @@ -1,17 +1,12 @@ //! The following tests are for the Interchain Security. //! These tests require the first chain to be a Provider chain and //! the second chain a Consumer chain. -use ibc_test_framework::{ - framework::binary::channel::run_binary_interchain_security_channel_test, - prelude::*, - util::{ - interchain_security::{ - update_genesis_for_consumer_chain, - update_relayer_config_for_consumer_chain, - }, - random::random_u128_range, - }, +use ibc_test_framework::framework::binary::channel::run_binary_interchain_security_channel_test; +use ibc_test_framework::prelude::*; +use ibc_test_framework::util::interchain_security::{ + update_genesis_for_consumer_chain, update_relayer_config_for_consumer_chain, }; +use ibc_test_framework::util::random::random_u128_range; #[test] fn test_ics_transfer() -> Result<(), Error> { diff --git a/tools/integration-test/src/tests/manual/simulation.rs b/tools/integration-test/src/tests/manual/simulation.rs index 0133ec3555..30c801bfcf 100644 --- a/tools/integration-test/src/tests/manual/simulation.rs +++ b/tools/integration-test/src/tests/manual/simulation.rs @@ -11,19 +11,8 @@ ``` */ -use core::time::Duration; - -use ibc_relayer::{ - config::{ - types::MaxMsgNum, - ChainConfig, - Config, - }, - transfer::{ - build_and_send_transfer_messages, - TransferOptions, - }, -}; +use ibc_relayer::config::{types::MaxMsgNum, ChainConfig}; +use ibc_relayer::transfer::{build_and_send_transfer_messages, TransferOptions}; use ibc_relayer_types::events::IbcEvent; use ibc_test_framework::prelude::*; diff --git a/tools/integration-test/src/tests/memo.rs b/tools/integration-test/src/tests/memo.rs index c37d74d330..cf59bb712d 100644 --- a/tools/integration-test/src/tests/memo.rs +++ b/tools/integration-test/src/tests/memo.rs @@ -4,21 +4,15 @@ //! You can find a more thorough walkthrough of this test at //! `tools/test-framework/src/docs/walkthroughs/memo.rs`. -use ibc_relayer::config::{ - types::Memo, - ChainConfig, - Config, -}; -use ibc_test_framework::{ - ibc::denom::derive_ibc_denom, - prelude::*, - util::random::{ - random_string, - random_u128_range, - }, -}; +use ibc_relayer::config::types::Memo; +use ibc_relayer::config::ChainConfig; use serde_json as json; +use ibc_test_framework::prelude::*; +use ibc_test_framework::util::random::{random_string, random_u128_range}; + +const OVERWRITE_MEMO: &str = "Overwritten memo"; + #[test] fn test_memo() -> Result<(), Error> { let memo = Memo::new(random_string()).unwrap(); @@ -26,6 +20,13 @@ fn test_memo() -> Result<(), Error> { run_binary_channel_test(&test) } +#[test] +fn test_memo_overwrite() -> Result<(), Error> { + let memo = Memo::new(random_string()).unwrap(); + let test = MemoOverwriteTest { memo }; + run_binary_channel_test(&test) +} + pub struct MemoTest { memo: Memo, } @@ -89,6 +90,70 @@ impl BinaryChannelTest for MemoTest { } } +pub struct MemoOverwriteTest { + memo: Memo, +} + +impl TestOverrides for MemoOverwriteTest { + fn modify_relayer_config(&self, config: &mut Config) { + for chain in config.chains.iter_mut() { + match chain { + ChainConfig::CosmosSdk(chain_config) => { + chain_config.memo_prefix = self.memo.clone(); + chain_config.memo_overwrite = Some(Memo::new(OVERWRITE_MEMO).unwrap()) + } + } + } + } +} + +impl BinaryChannelTest for MemoOverwriteTest { + fn run( + &self, + _config: &TestConfig, + _relayer: RelayerDriver, + chains: ConnectedChains, + channel: ConnectedChannel, + ) -> Result<(), Error> { + info!( + "testing IBC transfer with memo configured: \"{}\"", + self.memo + ); + + let denom_a = chains.node_a.denom(); + + let a_to_b_amount = random_u128_range(1000, 5000); + + chains.node_a.chain_driver().ibc_transfer_token( + &channel.port_a.as_ref(), + &channel.channel_id_a.as_ref(), + &chains.node_a.wallets().user1(), + &chains.node_b.wallets().user1().address(), + &denom_a.with_amount(a_to_b_amount).as_ref(), + )?; + + let denom_b = derive_ibc_denom( + &channel.port_b.as_ref(), + &channel.channel_id_b.as_ref(), + &denom_a, + )?; + + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &chains.node_b.wallets().user1().address(), + &denom_b.with_amount(a_to_b_amount).as_ref(), + )?; + + let tx_info = chains + .node_b + .chain_driver() + .query_recipient_transactions(&chains.node_b.wallets().user1().address())?; + + assert_tx_memo_equals(&tx_info, OVERWRITE_MEMO)?; + + Ok(()) + } +} + fn assert_tx_memo_equals(tx_info: &json::Value, expected_memo: &str) -> Result<(), Error> { debug!("comparing memo field from json value {}", tx_info); diff --git a/tools/integration-test/src/tests/mod.rs b/tools/integration-test/src/tests/mod.rs index b56c22b49d..e8812377d6 100644 --- a/tools/integration-test/src/tests/mod.rs +++ b/tools/integration-test/src/tests/mod.rs @@ -10,10 +10,11 @@ pub mod client_expiration; pub mod client_filter; pub mod client_refresh; pub mod client_settings; -#[cfg(not(any(feature = "celestia", feature = "juno")))] +#[cfg(not(feature = "celestia"))] pub mod client_upgrade; pub mod connection_delay; pub mod consensus_states; +#[cfg(not(feature = "no-denom-trace"))] pub mod denom_trace; pub mod error_events; pub mod execute_schedule; @@ -22,6 +23,8 @@ pub mod ics20_filter; pub mod memo; pub mod python; pub mod query_packet; +#[cfg(not(feature = "celestia"))] +pub mod sequence_filter; pub mod supervisor; pub mod tendermint; #[cfg(not(feature = "celestia"))] @@ -31,6 +34,12 @@ pub mod transfer; #[cfg(any(doc, feature = "async-icq"))] pub mod async_icq; +#[cfg(any(doc, feature = "authz"))] +pub mod authz; + +#[cfg(any(doc, feature = "channel-upgrade"))] +pub mod channel_upgrade; + #[cfg(any(doc, feature = "ics29-fee"))] pub mod fee; @@ -63,3 +72,9 @@ pub mod fee_grant; #[cfg(any(doc, feature = "interchain-security"))] pub mod interchain_security; + +#[cfg(any(doc, feature = "dynamic-gas-fee"))] +pub mod dynamic_gas_fee; + +#[cfg(any(doc, feature = "benchmark"))] +pub mod benchmark; diff --git a/tools/integration-test/src/tests/ordered_channel.rs b/tools/integration-test/src/tests/ordered_channel.rs index 35050f451f..a72126d3f2 100644 --- a/tools/integration-test/src/tests/ordered_channel.rs +++ b/tools/integration-test/src/tests/ordered_channel.rs @@ -13,11 +13,8 @@ //! A more thorough walkthrough of this test can be found at //! `tools/test-framework/src/docs/walkthroughs/ordered_channel.rs`. -use ibc_test_framework::{ - ibc::denom::derive_ibc_denom, - prelude::*, - util::random::random_u128_range, -}; +use ibc_test_framework::prelude::*; +use ibc_test_framework::util::random::random_u128_range; #[test] fn test_ordered_channel() -> Result<(), Error> { @@ -76,11 +73,9 @@ impl BinaryChannelTest for OrderedChannelTest { &denom_a.with_amount(amount1).as_ref(), )?; - sleep(Duration::from_secs(1)); + sleep(Duration::from_secs(2)); relayer.with_supervisor(|| { - sleep(Duration::from_secs(1)); - let amount2 = random_u128_range(1000, 5000); info!( diff --git a/tools/integration-test/src/tests/ordered_channel_clear.rs b/tools/integration-test/src/tests/ordered_channel_clear.rs index 0774bbeb60..ed6e124e64 100644 --- a/tools/integration-test/src/tests/ordered_channel_clear.rs +++ b/tools/integration-test/src/tests/ordered_channel_clear.rs @@ -1,23 +1,9 @@ -use ibc_relayer::{ - config::{ - types::MaxMsgNum, - ChainConfig, - }, - link::{ - Link, - LinkParameters, - }, - transfer::{ - build_and_send_transfer_messages, - TransferOptions, - }, -}; +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; -use ibc_test_framework::{ - ibc::denom::derive_ibc_denom, - prelude::*, - util::random::random_u64_range, -}; +use ibc_test_framework::prelude::*; +use ibc_test_framework::util::random::random_u64_range; #[test] fn test_ordered_channel_clear_no_conf_parallel() -> Result<(), Error> { @@ -61,6 +47,7 @@ impl OrderedChannelClearTest { impl TestOverrides for OrderedChannelClearTest { fn modify_relayer_config(&self, config: &mut Config) { config.mode.packets.tx_confirmation = self.tx_confirmation; + config.mode.packets.clear_limit = 150; { let chain_a = &mut config.chains[0]; match chain_a { @@ -134,6 +121,7 @@ impl BinaryChannelTest for OrderedChannelClearTest { src_channel_id: channel.channel_id_a.clone().into_value(), max_memo_size: packet_config.ics20_max_memo_size, max_receiver_size: packet_config.ics20_max_receiver_size, + exclude_src_sequences: vec![], }; let chain_a_link = Link::new_from_opts( @@ -149,6 +137,7 @@ impl BinaryChannelTest for OrderedChannelClearTest { src_channel_id: channel.channel_id_b.clone().into_value(), max_memo_size: packet_config.ics20_max_memo_size, max_receiver_size: packet_config.ics20_max_receiver_size, + exclude_src_sequences: vec![], }; let chain_b_link = Link::new_from_opts( @@ -161,7 +150,8 @@ impl BinaryChannelTest for OrderedChannelClearTest { // Send the transfer (recv) packets from A to B over the channel. let mut relay_path_a_to_b = chain_a_link.a_to_b; - relay_path_a_to_b.schedule_packet_clearing(None)?; + relay_path_a_to_b + .schedule_packet_clearing(None, relayer.config.mode.packets.clear_limit)?; relay_path_a_to_b.execute_schedule()?; sleep(Duration::from_secs(10)); @@ -180,7 +170,8 @@ impl BinaryChannelTest for OrderedChannelClearTest { // Send the packet acknowledgments from B to A. let mut relay_path_b_to_a = chain_b_link.a_to_b; - relay_path_b_to_a.schedule_packet_clearing(None)?; + relay_path_b_to_a + .schedule_packet_clearing(None, relayer.config.mode.packets.clear_limit)?; relay_path_b_to_a.execute_schedule()?; sleep(Duration::from_secs(10)); @@ -285,6 +276,7 @@ impl BinaryChannelTest for OrderedChannelClearEqualCLITest { src_channel_id: channel.channel_id_a.into_value(), max_memo_size: packet_config.ics20_max_memo_size, max_receiver_size: packet_config.ics20_max_receiver_size, + exclude_src_sequences: vec![], }; let chain_a_link = Link::new_from_opts( diff --git a/tools/integration-test/src/tests/python.rs b/tools/integration-test/src/tests/python.rs index 74381db1c1..29d6457885 100644 --- a/tools/integration-test/src/tests/python.rs +++ b/tools/integration-test/src/tests/python.rs @@ -1,16 +1,8 @@ -use std::{ - env, - process::{ - Command, - Stdio, - }, -}; - -use ibc_relayer::{ - config::ChainConfig, - keyring::Store, -}; +use ibc_relayer::config::ChainConfig; +use ibc_relayer::keyring::Store; use ibc_test_framework::prelude::*; +use std::env; +use std::process::{Command, Stdio}; struct PythonTest; diff --git a/tools/integration-test/src/tests/query_packet.rs b/tools/integration-test/src/tests/query_packet.rs index 6567c0bfab..7bd3f7ad1b 100644 --- a/tools/integration-test/src/tests/query_packet.rs +++ b/tools/integration-test/src/tests/query_packet.rs @@ -1,21 +1,11 @@ -use ibc_relayer::{ - chain::counterparty::{ - channel_on_destination, - pending_packet_summary, - }, - link::{ - Link, - LinkParameters, - }, -}; -use ibc_test_framework::{ - prelude::*, - relayer::{ - channel::query_identified_channel_end, - connection::query_identified_connection_end, - }, - util::random::random_u128_range, -}; +use ibc_relayer::chain::counterparty::{channel_on_destination, pending_packet_summary}; +use ibc_relayer::chain::requests::Paginate; +use ibc_relayer::link::{Link, LinkParameters}; + +use ibc_test_framework::prelude::*; +use ibc_test_framework::relayer::channel::query_identified_channel_end; +use ibc_test_framework::relayer::connection::query_identified_connection_end; +use ibc_test_framework::util::random::random_u128_range; #[test] fn test_query_packet_pending() -> Result<(), Error> { @@ -73,7 +63,17 @@ impl BinaryChannelTest for QueryPacketPendingTest { src_channel_id: channel.channel_id_a.clone().into_value(), max_memo_size: packet_config.ics20_max_memo_size, max_receiver_size: packet_config.ics20_max_receiver_size, + exclude_src_sequences: vec![], }; + + let rev_opts = LinkParameters { + src_port_id: channel.port_b.clone().into_value(), + src_channel_id: channel.channel_id_b.clone().into_value(), + max_memo_size: packet_config.ics20_max_memo_size, + max_receiver_size: packet_config.ics20_max_receiver_size, + exclude_src_sequences: vec![], + }; + let link = Link::new_from_opts( chains.handle_a().clone(), chains.handle_b().clone(), @@ -88,8 +88,12 @@ impl BinaryChannelTest for QueryPacketPendingTest { channel.port_a.as_ref(), )?; - let summary = - pending_packet_summary(chains.handle_a(), chains.handle_b(), channel_end.value())?; + let summary = pending_packet_summary( + chains.handle_a(), + chains.handle_b(), + channel_end.value(), + Paginate::All, + )?; assert_eq!(summary.unreceived_packets, [1.into()]); assert!(summary.unreceived_acks.is_empty()); @@ -97,18 +101,34 @@ impl BinaryChannelTest for QueryPacketPendingTest { // Receive the packet on the destination chain link.relay_recv_packet_and_timeout_messages(vec![])?; - let summary = - pending_packet_summary(chains.handle_a(), chains.handle_b(), channel_end.value())?; + let summary = pending_packet_summary( + chains.handle_a(), + chains.handle_b(), + channel_end.value(), + Paginate::All, + )?; assert!(summary.unreceived_packets.is_empty()); assert_eq!(summary.unreceived_acks, [1.into()]); // Acknowledge the packet on the source chain - let link = link.reverse(false, false)?; - link.relay_ack_packet_messages(vec![])?; - let summary = - pending_packet_summary(chains.handle_a(), chains.handle_b(), channel_end.value())?; + let rev_link = Link::new_from_opts( + chains.handle_b().clone(), + chains.handle_a().clone(), + rev_opts, + false, + false, + )?; + + rev_link.relay_ack_packet_messages(vec![])?; + + let summary = pending_packet_summary( + chains.handle_a(), + chains.handle_b(), + channel_end.value(), + Paginate::All, + )?; assert!(summary.unreceived_packets.is_empty()); assert!(summary.unreceived_acks.is_empty()); @@ -147,6 +167,7 @@ impl BinaryChannelTest for QueryPacketPendingTest { chains.handle_b(), chains.handle_a(), &counterparty_channel_end, + Paginate::All, )?; assert_eq!(summary.unreceived_packets, [1.into()]); diff --git a/tools/integration-test/src/tests/sequence_filter.rs b/tools/integration-test/src/tests/sequence_filter.rs new file mode 100644 index 0000000000..a880f7720e --- /dev/null +++ b/tools/integration-test/src/tests/sequence_filter.rs @@ -0,0 +1,570 @@ +//! This tests different scenarios for the packet sequence filter. +//! The purpose of this filter is to only filter out packets when clearing, +//! standard relaying should not be affected by this configuration. +//! +//! `FilterClearOnStartTest` tests that the packets sequences configured in +//! `excluded_sequences` are not relayed when clearing packet on start. +//! +//! `FilterClearIntervalTest` tests that the packet sequences configured in +//! `excluded_sequences` are not relayed when the clear interval is triggered. +//! +//! `ClearNoFilterTest` tests that packets are correctly cleared if there is no +//! packet sequence configured in `excluded_sequences`. +//! +//! `StandardRelayingNoFilterTest` tests that even if a packet sequence is +//! configured in the `excluded_sequences` it will be relayed by the running +//! instance. + +use std::collections::BTreeMap; + +use ibc_relayer::config::ChainConfig; +use ibc_relayer::util::excluded_sequences::ExcludedSequences; +use ibc_test_framework::{ + prelude::*, + relayer::channel::{assert_eventually_channel_established, init_channel}, +}; + +#[test] +fn test_filter_clear_on_start() -> Result<(), Error> { + run_binary_channel_test(&FilterClearOnStartTest) +} + +#[test] +fn test_filter_clear_interval() -> Result<(), Error> { + run_binary_channel_test(&FilterClearIntervalTest) +} + +#[test] +fn test_clear_no_filter() -> Result<(), Error> { + run_binary_channel_test(&ClearNoFilterTest) +} + +#[test] +fn test_no_filter_standard_relaying() -> Result<(), Error> { + run_binary_channel_test(&StandardRelayingNoFilterTest) +} + +pub struct FilterClearOnStartTest; + +impl TestOverrides for FilterClearOnStartTest { + fn modify_relayer_config(&self, config: &mut Config) { + let mut excluded_sequences = BTreeMap::new(); + excluded_sequences.insert(ChannelId::new(2), vec![2.into()]); + let chain_a = &mut config.chains[0]; + match chain_a { + ChainConfig::CosmosSdk(chain_config) => { + chain_config.excluded_sequences = ExcludedSequences::new(excluded_sequences); + } + } + config.mode.channels.enabled = true; + + config.mode.packets.clear_on_start = true; + config.mode.packets.clear_interval = 0; + + config.mode.clients.misbehaviour = false; + } + + fn should_spawn_supervisor(&self) -> bool { + false + } +} + +impl BinaryChannelTest for FilterClearOnStartTest { + fn run( + &self, + _config: &TestConfig, + relayer: RelayerDriver, + chains: ConnectedChains, + channels: ConnectedChannel, + ) -> Result<(), Error> { + run_sequence_filter_test(relayer, chains, channels) + } +} + +pub struct FilterClearIntervalTest; + +impl TestOverrides for FilterClearIntervalTest { + fn modify_relayer_config(&self, config: &mut Config) { + let mut excluded_sequences = BTreeMap::new(); + excluded_sequences.insert(ChannelId::new(2), vec![2.into()]); + let chain_a = &mut config.chains[0]; + match chain_a { + ChainConfig::CosmosSdk(chain_config) => { + chain_config.excluded_sequences = ExcludedSequences::new(excluded_sequences); + } + } + config.mode.channels.enabled = true; + + config.mode.packets.clear_on_start = false; + config.mode.packets.clear_interval = 10; + + config.mode.clients.misbehaviour = false; + } + + fn should_spawn_supervisor(&self) -> bool { + false + } +} + +impl BinaryChannelTest for FilterClearIntervalTest { + fn run( + &self, + _config: &TestConfig, + relayer: RelayerDriver, + chains: ConnectedChains, + channels: ConnectedChannel, + ) -> Result<(), Error> { + run_sequence_filter_test(relayer, chains, channels) + } +} + +pub struct ClearNoFilterTest; + +impl TestOverrides for ClearNoFilterTest { + fn modify_relayer_config(&self, config: &mut Config) { + config.mode.channels.enabled = true; + + config.mode.packets.clear_on_start = true; + config.mode.packets.clear_interval = 0; + + config.mode.clients.misbehaviour = false; + } + + fn should_spawn_supervisor(&self) -> bool { + false + } +} + +impl BinaryChannelTest for ClearNoFilterTest { + fn run( + &self, + _config: &TestConfig, + relayer: RelayerDriver, + chains: ConnectedChains, + channels: ConnectedChannel, + ) -> Result<(), Error> { + let denom_a = chains.node_a.denom(); + let denom_a_to_b = derive_ibc_denom( + &channels.port_b.as_ref(), + &channels.channel_id_b.as_ref(), + &denom_a, + )?; + let denom_b = chains.node_b.denom(); + let denom_b_to_a = derive_ibc_denom( + &channels.port_a.as_ref(), + &channels.channel_id_a.as_ref(), + &denom_b, + )?; + + let wallet_a = chains.node_a.wallets().user1().cloned(); + let wallet_b = chains.node_b.wallets().user1().cloned(); + + let a_to_b_amount = 12345u64; + let b_to_a_amount = 54321u64; + + let balance_a = chains + .node_a + .chain_driver() + .query_balance(&wallet_a.address(), &denom_a)?; + + let balance_b = chains + .node_b + .chain_driver() + .query_balance(&wallet_b.address(), &denom_b)?; + + // Create a pending transfer from A to B with sequence 1 + chains.node_a.chain_driver().ibc_transfer_token( + &channels.port_a.as_ref(), + &channels.channel_id_a.as_ref(), + &wallet_a.as_ref(), + &wallet_b.address(), + &denom_a.with_amount(a_to_b_amount).as_ref(), + )?; + + // Create a pending transfer from A to B with sequence 2 + chains.node_a.chain_driver().ibc_transfer_token( + &channels.port_a.as_ref(), + &channels.channel_id_a.as_ref(), + &wallet_a.as_ref(), + &wallet_b.address(), + &denom_a.with_amount(a_to_b_amount).as_ref(), + )?; + + // Create a pending transfer from B to A with sequence 1 + chains.node_b.chain_driver().ibc_transfer_token( + &channels.port_b.as_ref(), + &channels.channel_id_b.as_ref(), + &wallet_b.as_ref(), + &wallet_a.address(), + &denom_b.with_amount(b_to_a_amount).as_ref(), + )?; + + // Create a pending transfer from B to A with sequence 2 + chains.node_b.chain_driver().ibc_transfer_token( + &channels.port_b.as_ref(), + &channels.channel_id_b.as_ref(), + &wallet_b.as_ref(), + &wallet_a.address(), + &denom_b.with_amount(b_to_a_amount).as_ref(), + )?; + + relayer.with_supervisor(|| { + info!("Assert that the send from A escrowed tokens for both transfers"); + + chains.node_a.chain_driver().assert_eventual_wallet_amount( + &wallet_a.address(), + &(balance_a - 2 * a_to_b_amount).as_ref(), + )?; + + info!("Assert that only the first transfer A to B was cleared"); + + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &wallet_b.address(), + &denom_a_to_b.with_amount(2 * a_to_b_amount).as_ref(), + )?; + info!("Assert that the sender from B escrowed tokens for both transfers"); + + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &wallet_b.address(), + &(balance_b - 2 * b_to_a_amount).as_ref(), + )?; + + info!("Assert that both transfers from B to A were cleared"); + + chains.node_a.chain_driver().assert_eventual_wallet_amount( + &wallet_a.address(), + &denom_b_to_a.with_amount(2 * b_to_a_amount).as_ref(), + )?; + Ok(()) + }) + } +} + +pub struct StandardRelayingNoFilterTest; + +impl TestOverrides for StandardRelayingNoFilterTest { + fn modify_relayer_config(&self, config: &mut Config) { + let mut excluded_sequences = BTreeMap::new(); + excluded_sequences.insert(ChannelId::new(2), vec![2.into()]); + let chain_a = &mut config.chains[0]; + match chain_a { + ChainConfig::CosmosSdk(chain_config) => { + chain_config.excluded_sequences = ExcludedSequences::new(excluded_sequences); + } + } + config.mode.packets.clear_on_start = true; + config.mode.packets.clear_interval = 0; + } + + fn should_spawn_supervisor(&self) -> bool { + true + } +} + +impl BinaryChannelTest for StandardRelayingNoFilterTest { + fn run( + &self, + _config: &TestConfig, + _relayer: RelayerDriver, + chains: ConnectedChains, + channels: ConnectedChannel, + ) -> Result<(), Error> { + let denom_a = chains.node_a.denom(); + let denom_a_to_b = derive_ibc_denom( + &channels.port_b.as_ref(), + &channels.channel_id_b.as_ref(), + &denom_a, + )?; + let denom_b = chains.node_b.denom(); + let denom_b_to_a = derive_ibc_denom( + &channels.port_a.as_ref(), + &channels.channel_id_a.as_ref(), + &denom_b, + )?; + + let wallet_a = chains.node_a.wallets().user1().cloned(); + let wallet_b = chains.node_b.wallets().user1().cloned(); + + let a_to_b_amount = 12345u64; + let b_to_a_amount = 54321u64; + + let balance_a = chains + .node_a + .chain_driver() + .query_balance(&wallet_a.address(), &denom_a)?; + + let balance_b = chains + .node_b + .chain_driver() + .query_balance(&wallet_b.address(), &denom_b)?; + + // Create a pending transfer from A to B with sequence 1 + chains.node_a.chain_driver().ibc_transfer_token( + &channels.port_a.as_ref(), + &channels.channel_id_a.as_ref(), + &wallet_a.as_ref(), + &wallet_b.address(), + &denom_a.with_amount(a_to_b_amount).as_ref(), + )?; + + // Create a pending transfer from A to B with sequence 2 + chains.node_a.chain_driver().ibc_transfer_token( + &channels.port_a.as_ref(), + &channels.channel_id_a.as_ref(), + &wallet_a.as_ref(), + &wallet_b.address(), + &denom_a.with_amount(a_to_b_amount).as_ref(), + )?; + + // Create a pending transfer from B to A with sequence 1 + chains.node_b.chain_driver().ibc_transfer_token( + &channels.port_b.as_ref(), + &channels.channel_id_b.as_ref(), + &wallet_b.as_ref(), + &wallet_a.address(), + &denom_b.with_amount(b_to_a_amount).as_ref(), + )?; + + // Create a pending transfer from B to A with sequence 2 + chains.node_b.chain_driver().ibc_transfer_token( + &channels.port_b.as_ref(), + &channels.channel_id_b.as_ref(), + &wallet_b.as_ref(), + &wallet_a.address(), + &denom_b.with_amount(b_to_a_amount).as_ref(), + )?; + + info!("Assert that the send from A escrowed tokens for both transfers"); + + chains.node_a.chain_driver().assert_eventual_wallet_amount( + &wallet_a.address(), + &(balance_a - 2 * a_to_b_amount).as_ref(), + )?; + + info!("Assert that only the first transfer A to B was cleared"); + + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &wallet_b.address(), + &denom_a_to_b.with_amount(2 * a_to_b_amount).as_ref(), + )?; + info!("Assert that the sender from B escrowed tokens for both transfers"); + + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &wallet_b.address(), + &(balance_b - 2 * b_to_a_amount).as_ref(), + )?; + + info!("Assert that both transfers from B to A were cleared"); + + chains.node_a.chain_driver().assert_eventual_wallet_amount( + &wallet_a.address(), + &denom_b_to_a.with_amount(2 * b_to_a_amount).as_ref(), + )?; + Ok(()) + } +} + +fn run_sequence_filter_test( + relayer: RelayerDriver, + chains: ConnectedChains, + channels: ConnectedChannel, +) -> Result<(), Error> { + let (channel_id_a_2, channel_id_b_2, channel_b_2) = relayer.with_supervisor(|| { + // During test bootstrap channel padding initialises a channel with ID 0. + // Before creating the new channel with sequence filter, complete the handshake of + // the pad channel in order to insure that the retrieved channel IDs `channel_id_a_2` and + // `channel_id_b_2` are `channel-2` + let pad_channel_id = DualTagged::new(ChannelId::new(0)); + let _ = assert_eventually_channel_established( + chains.handle_b(), + chains.handle_a(), + &pad_channel_id.as_ref(), + &channels.port_b.as_ref(), + )?; + let (channel_id_b_2, channel_b_2) = init_channel( + chains.handle_a(), + chains.handle_b(), + &chains.client_id_a(), + &chains.client_id_b(), + &channels.connection.connection_id_a.as_ref(), + &channels.connection.connection_id_b.as_ref(), + &channels.port_a.as_ref(), + &channels.port_b.as_ref(), + )?; + + let channel_id_a_2 = assert_eventually_channel_established( + chains.handle_b(), + chains.handle_a(), + &channel_id_b_2.as_ref(), + &channels.port_b.as_ref(), + )?; + Ok((channel_id_a_2, channel_id_b_2, channel_b_2)) + })?; + + let denom_a = chains.node_a.denom(); + let denom_a_to_b_1 = derive_ibc_denom( + &channels.port_b.as_ref(), + &channels.channel_id_b.as_ref(), + &denom_a, + )?; + let denom_a_to_b_2 = derive_ibc_denom( + &channels.port_b.as_ref(), + &channel_id_b_2.as_ref(), + &denom_a, + )?; + let denom_b = chains.node_b.denom(); + let denom_b_to_a_1 = derive_ibc_denom( + &channels.port_a.as_ref(), + &channels.channel_id_a.as_ref(), + &denom_b, + )?; + let denom_b_to_a_2 = derive_ibc_denom( + &channels.port_a.as_ref(), + &channel_id_a_2.as_ref(), + &denom_b, + )?; + + let wallet_a_1 = chains.node_a.wallets().user1().cloned(); + let wallet_a_2 = chains.node_a.wallets().user2().cloned(); + let wallet_b_1 = chains.node_b.wallets().user1().cloned(); + let wallet_b_2 = chains.node_b.wallets().user2().cloned(); + + let a_to_b_amount = 12345u64; + let b_to_a_amount = 54321u64; + + let balance_a_1 = chains + .node_a + .chain_driver() + .query_balance(&wallet_a_1.address(), &denom_a)?; + + let balance_b_1 = chains + .node_b + .chain_driver() + .query_balance(&wallet_b_1.address(), &denom_b)?; + + let balance_a_2 = chains + .node_a + .chain_driver() + .query_balance(&wallet_a_2.address(), &denom_a)?; + + let balance_b_2 = chains + .node_b + .chain_driver() + .query_balance(&wallet_b_2.address(), &denom_b)?; + + // Double transfer from A to B on channel with filter + double_transfer( + chains.node_a.chain_driver(), + &channels.port_a.as_ref(), + &channels.channel_id_a.as_ref(), + &wallet_a_1.as_ref(), + &wallet_b_1.address(), + &denom_a.with_amount(a_to_b_amount).as_ref(), + )?; + + let port_b_2: DualTagged = + DualTagged::new(channel_b_2.a_side.port_id()); + let port_a_2: DualTagged = + DualTagged::new(channel_b_2.clone().flipped().a_side.port_id().clone()); + + // Double transfer from A to B on channel without filter + double_transfer( + chains.node_a.chain_driver(), + &port_a_2.as_ref(), + &channel_id_a_2.as_ref(), + &wallet_a_2.as_ref(), + &wallet_b_2.address(), + &denom_a.with_amount(a_to_b_amount).as_ref(), + )?; + + // Double transfer from B to A on channel with filter + double_transfer( + chains.node_b.chain_driver(), + &channels.port_b.as_ref(), + &channels.channel_id_b.as_ref(), + &wallet_b_1.as_ref(), + &wallet_a_1.address(), + &denom_b.with_amount(b_to_a_amount).as_ref(), + )?; + + // Double transfer from B to A on channel without filter + double_transfer( + chains.node_b.chain_driver(), + &port_b_2, + &channel_id_b_2.as_ref(), + &wallet_b_2.as_ref(), + &wallet_a_2.address(), + &denom_b.with_amount(b_to_a_amount).as_ref(), + )?; + + relayer.with_supervisor(|| { + info!("Assert that the send from A escrowed tokens for both transfers"); + + chains.node_a.chain_driver().assert_eventual_wallet_amount( + &wallet_a_1.address(), + &(balance_a_1 - 2 * a_to_b_amount).as_ref(), + )?; + + chains.node_a.chain_driver().assert_eventual_wallet_amount( + &wallet_a_2.address(), + &(balance_a_2 - 2 * a_to_b_amount).as_ref(), + )?; + + info!("Assert that only the first transfer A to B was cleared on channel with filter"); + + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &wallet_b_2.address(), + &denom_a_to_b_2.with_amount(a_to_b_amount).as_ref(), + )?; + + info!("Assert that both transfer A to B were cleared on channel without filter"); + + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &wallet_b_1.address(), + &denom_a_to_b_1.with_amount(2 * a_to_b_amount).as_ref(), + )?; + + info!("Assert that the sender from B escrowed tokens for both transfers on both channels"); + + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &wallet_b_1.address(), + &(balance_b_1 - 2 * b_to_a_amount).as_ref(), + )?; + + chains.node_b.chain_driver().assert_eventual_wallet_amount( + &wallet_b_2.address(), + &(balance_b_2 - 2 * b_to_a_amount).as_ref(), + )?; + + info!("Assert that both transfers from B to A were cleared on both channels"); + + chains.node_a.chain_driver().assert_eventual_wallet_amount( + &wallet_a_1.address(), + &denom_b_to_a_1.with_amount(2 * b_to_a_amount).as_ref(), + )?; + + chains.node_a.chain_driver().assert_eventual_wallet_amount( + &wallet_a_2.address(), + &denom_b_to_a_2.with_amount(2 * b_to_a_amount).as_ref(), + )?; + + Ok(()) + }) +} + +fn double_transfer( + chain_driver: MonoTagged, + port_id: &TaggedPortIdRef, + channel_id: &TaggedChannelIdRef, + sender: &MonoTagged, + recipient: &MonoTagged, + token: &TaggedTokenRef, +) -> Result<(), Error> { + // Create a pending transfer from B to A with sequence 1 + chain_driver.ibc_transfer_token(port_id, channel_id, sender, recipient, token)?; + + // Create a pending transfer from B to A with sequence 2 + chain_driver.ibc_transfer_token(port_id, channel_id, sender, recipient, token)?; + + Ok(()) +} diff --git a/tools/integration-test/src/tests/supervisor.rs b/tools/integration-test/src/tests/supervisor.rs index 5ea032b14b..17ee1b5af7 100644 --- a/tools/integration-test/src/tests/supervisor.rs +++ b/tools/integration-test/src/tests/supervisor.rs @@ -1,25 +1,13 @@ -use ibc_relayer::config::{ - self, - Config, - ModeConfig, -}; -use ibc_test_framework::{ - ibc::denom::derive_ibc_denom, - prelude::*, - relayer::{ - channel::{ - assert_eventually_channel_established, - init_channel, - }, - connection::{ - assert_eventually_connection_established, - init_connection, - }, - }, +use ibc_relayer::config::{self, ModeConfig}; + +use ibc_test_framework::prelude::*; +use ibc_test_framework::relayer::channel::{assert_eventually_channel_established, init_channel}; +use ibc_test_framework::relayer::connection::{ + assert_eventually_connection_established, init_connection, }; #[test] -fn test_supervisor() -> Result<(), Error> { +fn test_supervisor1() -> Result<(), Error> { run_binary_chain_test(&SupervisorTest) } @@ -63,10 +51,14 @@ impl TestOverrides for SupervisorTest { impl BinaryChainTest for SupervisorTest { fn run( &self, - _config: &TestConfig, + config: &TestConfig, _relayer: RelayerDriver, chains: ConnectedChains, ) -> Result<(), Error> { + let fee_denom_a: MonoTagged = + MonoTagged::new(Denom::base(config.native_token(0))); + let fee_denom_b: MonoTagged = + MonoTagged::new(Denom::base(config.native_token(1))); let (connection_id_b, _) = init_connection( &chains.handle_a, &chains.handle_b, @@ -124,12 +116,14 @@ impl BinaryChainTest for SupervisorTest { &chains.node_a.wallets().relayer(), &chains.node_a.wallets().user2().address(), &denom_a.with_amount(1000u64).as_ref(), + &fee_denom_a.with_amount(381000000u64).as_ref(), )?; chains.node_b.chain_driver().local_transfer_token( &chains.node_b.wallets().relayer(), &chains.node_b.wallets().user2().address(), &chains.node_b.denom().with_amount(1000u64).as_ref(), + &fee_denom_b.with_amount(381000000u64).as_ref(), )?; info!( @@ -205,7 +199,7 @@ impl BinaryChannelTest for SupervisorScanTest { channels: ConnectedChannel, ) -> Result<(), Error> { let denom_a = chains.node_a.denom(); - let fee_denom_a = MonoTagged::new(Denom::base(&config.native_tokens[0])); + let fee_denom_a = MonoTagged::new(Denom::base(config.native_token(0))); let denom_b = derive_ibc_denom( &channels.port_b.as_ref(), diff --git a/tools/integration-test/src/tests/tendermint/sequential.rs b/tools/integration-test/src/tests/tendermint/sequential.rs index 7a9422df41..be9d254873 100644 --- a/tools/integration-test/src/tests/tendermint/sequential.rs +++ b/tools/integration-test/src/tests/tendermint/sequential.rs @@ -1,17 +1,11 @@ use std::time::Instant; -use ibc_relayer::{ - chain::tracking::TrackedMsgs, - config::{ - types::max_msg_num::MaxMsgNum, - ChainConfig, - }, -}; -use ibc_test_framework::{ - chain::config, - prelude::*, - relayer::transfer::build_transfer_message, -}; +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; const MESSAGES_PER_BATCH: usize = 5; const TOTAL_TRANSACTIONS: usize = 5; @@ -40,14 +34,14 @@ 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 match &mut config.chains[0] { - ChainConfig::CosmosSdk(chain_config_a) | ChainConfig::Astria(chain_config_a) => { + 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) | ChainConfig::Astria(chain_config_b) => { + ChainConfig::CosmosSdk(chain_config_b) => { chain_config_b.max_msg_num = MaxMsgNum::new(MESSAGES_PER_BATCH).unwrap(); chain_config_b.sequential_batch_tx = false; } diff --git a/tools/integration-test/src/tests/ternary_transfer.rs b/tools/integration-test/src/tests/ternary_transfer.rs index 4e435fe855..527c085629 100644 --- a/tools/integration-test/src/tests/ternary_transfer.rs +++ b/tools/integration-test/src/tests/ternary_transfer.rs @@ -1,7 +1,5 @@ -use ibc_test_framework::{ - ibc::denom::derive_ibc_denom, - prelude::*, -}; +use ibc_test_framework::prelude::*; +use ibc_test_framework::types::topology::TopologyType; #[test] fn test_ternary_ibc_transfer() -> Result<(), Error> { @@ -14,6 +12,10 @@ impl TestOverrides for TernaryIbcTransferTest { fn modify_relayer_config(&self, config: &mut Config) { config.mode.clients.misbehaviour = false; } + + fn topology(&self) -> Option { + Some(TopologyType::Cyclic) + } } impl PortsOverride<3> for TernaryIbcTransferTest {} diff --git a/tools/integration-test/src/tests/transfer.rs b/tools/integration-test/src/tests/transfer.rs index 169a971005..f117dc742f 100644 --- a/tools/integration-test/src/tests/transfer.rs +++ b/tools/integration-test/src/tests/transfer.rs @@ -1,7 +1,5 @@ -use ibc_test_framework::{ - prelude::*, - util::random::random_u128_range, -}; +use ibc_test_framework::prelude::*; +use ibc_test_framework::util::random::random_u128_range; #[test] fn test_ibc_transfer() -> Result<(), Error> { diff --git a/tools/query-events/Cargo.lock b/tools/query-events/Cargo.lock new file mode 100644 index 0000000000..2c67070e4e --- /dev/null +++ b/tools/query-events/Cargo.lock @@ -0,0 +1,2197 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" + +[[package]] +name = "async-trait" +version = "0.1.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.53", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +dependencies = [ + "serde", +] + +[[package]] +name = "cc" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "3.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "clap_lex", + "indexmap 1.9.3", + "once_cell", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_derive" +version = "3.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "curve25519-dalek-ng" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c359b7249347e46fb28804470d071c921156ad62b3eef5d34e2ba867533dec8" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core", + "subtle-ng", + "zeroize", +] + +[[package]] +name = "der" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "crypto-common", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-consensus" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c8465edc8ee7436ffea81d21a019b16676ee3db267aa8d5a8d729581ecf998b" +dependencies = [ + "curve25519-dalek-ng", + "hex", + "rand_core", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "either" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" + +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "flex-error" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c606d892c9de11507fa0dcffc116434f94e105d0bbdc4e405b61519464c49d7b" +dependencies = [ + "eyre", + "paste", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.53", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 2.2.5", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http", + "hyper", + "rustls", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", +] + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +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.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi 0.3.9", + "libc", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "os_str_bytes" +version = "6.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.48.5", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "peg" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "400bcab7d219c38abf8bd7cc2054eb9bbbd4312d66f6a5557d572a203f646f61" +dependencies = [ + "peg-macros", + "peg-runtime", +] + +[[package]] +name = "peg-macros" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46e61cce859b76d19090f62da50a9fe92bab7c2a5f09e183763559a2ac392c90" +dependencies = [ + "peg-runtime", + "proc-macro2", + "quote", +] + +[[package]] +name = "peg-runtime" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36bae92c60fa2398ce4678b98b2c4b5a7c61099961ca1fa305aec04a9ad28922" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.53", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +dependencies = [ + "anyhow", + "itertools 0.11.0", + "proc-macro2", + "quote", + "syn 2.0.53", +] + +[[package]] +name = "prost-types" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" +dependencies = [ + "prost", +] + +[[package]] +name = "query-events" +version = "0.1.0" +dependencies = [ + "clap", + "futures", + "itertools 0.10.5", + "tendermint", + "tendermint-rpc", + "tokio", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.6", + "regex-syntax 0.8.2", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.2", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "reqwest" +version = "0.11.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-native-certs", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-rustls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustls" +version = "0.21.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "security-framework" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" + +[[package]] +name = "serde" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.53", +] + +[[package]] +name = "serde_json" +version = "1.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_repr" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.53", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "subtle-encoding" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dcb1ed7b8330c5eed5441052651dd7a12c75e2ed88f2ec024ae1fa3a5e59945" +dependencies = [ + "zeroize", +] + +[[package]] +name = "subtle-ng" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tendermint" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15ab8f0a25d0d2ad49ac615da054d6a76aa6603ff95f7d18bafdd34450a1a04b" +dependencies = [ + "bytes", + "digest 0.10.7", + "ed25519", + "ed25519-consensus", + "flex-error", + "futures", + "num-traits", + "once_cell", + "prost", + "prost-types", + "serde", + "serde_bytes", + "serde_json", + "serde_repr", + "sha2 0.10.8", + "signature", + "subtle", + "subtle-encoding", + "tendermint-proto", + "time", + "zeroize", +] + +[[package]] +name = "tendermint-config" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1a02da769166e2052cd537b1a97c78017632c2d9e19266367b27e73910434fc" +dependencies = [ + "flex-error", + "serde", + "serde_json", + "tendermint", + "toml", + "url", +] + +[[package]] +name = "tendermint-proto" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b797dd3d2beaaee91d2f065e7bdf239dc8d80bba4a183a288bc1279dd5a69a1e" +dependencies = [ + "bytes", + "flex-error", + "num-derive", + "num-traits", + "prost", + "prost-types", + "serde", + "serde_bytes", + "subtle-encoding", + "time", +] + +[[package]] +name = "tendermint-rpc" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71afae8bb5f6b14ed48d4e1316a643b6c2c3cbad114f510be77b4ed20b7b3e42" +dependencies = [ + "async-trait", + "bytes", + "flex-error", + "futures", + "getrandom", + "peg", + "pin-project", + "rand", + "reqwest", + "semver", + "serde", + "serde_bytes", + "serde_json", + "subtle", + "subtle-encoding", + "tendermint", + "tendermint-config", + "tendermint-proto", + "thiserror", + "time", + "tokio", + "tracing", + "url", + "uuid", + "walkdir", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" + +[[package]] +name = "thiserror" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.53", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.53", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.53", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[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", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "uuid" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.53", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.53", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.4", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "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]] +name = "windows-targets" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.53", +] diff --git a/tools/test-framework/Cargo.toml b/tools/test-framework/Cargo.toml index c29cb6aa89..34f5a08182 100644 --- a/tools/test-framework/Cargo.toml +++ b/tools/test-framework/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ibc-test-framework" -version = "0.26.4" +version = "0.29.3" edition = "2021" license = "Apache-2.0" readme = "README.md" @@ -14,31 +14,31 @@ description = """ """ [dependencies] -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.41.0", features = ["serde"] } -tendermint-rpc = { version = "0.34.0", features = ["http-client", "websocket-client"] } +ibc-relayer-types = { workspace = true } +ibc-relayer = { workspace = true } +ibc-relayer-cli = { workspace = true } +ibc-proto = { workspace = true, features = ["serde"] } +tendermint-rpc = { workspace = true, features = ["http-client", "websocket-client"] } -http = "0.2.9" -tokio = { version = "1.0", features = ["full"] } -tracing = "0.1.36" -tracing-subscriber = "0.3.14" -eyre = "0.6.8" -color-eyre = "0.6" -rand = "0.8.5" -hex = "0.4.3" -serde = "1.0" -serde_json = "1" -serde_yaml = "0.9.16" -itertools = "0.10" -toml = "0.8" -subtle-encoding = "0.5.1" -sha2 = "0.10.6" -crossbeam-channel = "0.5.11" -semver = "1.0.16" -flex-error = "0.4.4" -prost = { version = "0.12" } -tonic = { version = "0.10", features = ["tls", "tls-roots"] } -hdpath = "0.6.3" -once_cell = "1.19.0" +color-eyre = { workspace = true } +crossbeam-channel = { workspace = true } +eyre = { workspace = true } +flex-error = { workspace = true } +hdpath = { workspace = true } +hex = { workspace = true } +http = { workspace = true } +itertools = { workspace = true } +once_cell = { workspace = true } +prost = { workspace = true } +rand = { workspace = true } +semver = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +serde_yaml = { workspace = true } +sha2 = { workspace = true } +subtle-encoding = { workspace = true } +tokio = { workspace = true, features = ["full"] } +toml = { workspace = true } +tonic = { workspace = true, features = ["tls", "tls-roots"] } +tracing = { workspace = true } +tracing-subscriber = { workspace = true } diff --git a/tools/test-framework/src/bootstrap/binary/chain.rs b/tools/test-framework/src/bootstrap/binary/chain.rs index 788f203895..365c079e8c 100644 --- a/tools/test-framework/src/bootstrap/binary/chain.rs +++ b/tools/test-framework/src/bootstrap/binary/chain.rs @@ -3,52 +3,29 @@ with connected foreign clients. */ -use std::{ - fs, - path::Path, - thread, - time::Duration, -}; - use eyre::Report as Error; -use ibc_relayer::{ - chain::handle::{ - ChainHandle, - CountingAndCachingChainHandle, - }, - config::Config, - error::ErrorDetail as RelayerErrorDetail, - foreign_client::{ - extract_client_id, - CreateOptions as ClientOptions, - ForeignClient, - }, - keyring::errors::ErrorDetail as KeyringErrorDetail, - registry::SharedRegistry, +use ibc_relayer::chain::handle::{ChainHandle, CountingAndCachingChainHandle}; +use ibc_relayer::config::Config; +use ibc_relayer::error::ErrorDetail as RelayerErrorDetail; +use ibc_relayer::foreign_client::{ + extract_client_id, CreateOptions as ClientOptions, ForeignClient, }; +use ibc_relayer::keyring::errors::ErrorDetail as KeyringErrorDetail; +use ibc_relayer::registry::SharedRegistry; use ibc_relayer_types::core::ics24_host::identifier::ClientId; -use tracing::{ - debug, - info, -}; - -use crate::{ - relayer::driver::RelayerDriver, - types::{ - binary::{ - chains::ConnectedChains, - foreign_client::ForeignClientPair, - }, - config::TestConfig, - single::node::FullNode, - tagged::*, - wallet::{ - TestWallets, - Wallet, - }, - }, - util::random::random_u64_range, -}; +use std::path::Path; +use std::time::Duration; +use std::{fs, thread}; +use tracing::{debug, info}; + +use crate::relayer::driver::RelayerDriver; +use crate::types::binary::chains::ConnectedChains; +use crate::types::binary::foreign_client::ForeignClientPair; +use crate::types::config::TestConfig; +use crate::types::single::node::FullNode; +use crate::types::tagged::*; +use crate::types::wallet::{TestWallets, Wallet}; +use crate::util::random::random_u64_range; #[derive(Default)] pub struct BootstrapClientOptions { diff --git a/tools/test-framework/src/bootstrap/binary/channel.rs b/tools/test-framework/src/bootstrap/binary/channel.rs index efbda6621d..4b1439568a 100644 --- a/tools/test-framework/src/bootstrap/binary/channel.rs +++ b/tools/test-framework/src/bootstrap/binary/channel.rs @@ -2,46 +2,22 @@ Helper functions for bootstrapping a channel between two chains. */ -use eyre::{ - eyre, - Report as Error, -}; -use ibc_relayer::{ - chain::handle::ChainHandle, - channel::{ - Channel, - ChannelSide, - }, -}; -use ibc_relayer_types::core::{ - ics04_channel::{ - channel::Ordering, - version::Version, - }, - ics24_host::identifier::PortId, -}; -use tracing::{ - debug, - info, -}; - -use super::connection::{ - bootstrap_connection, - BootstrapConnectionOptions, -}; -use crate::{ - types::{ - binary::{ - chains::ConnectedChains, - channel::ConnectedChannel, - connection::ConnectedConnection, - foreign_client::ForeignClientPair, - }, - id::TaggedPortIdRef, - tagged::*, - }, - util::random::random_u64_range, -}; +use eyre::{eyre, Report as Error}; +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::channel::{Channel, ChannelSide}; +use ibc_relayer_types::core::ics04_channel::channel::Ordering; +use ibc_relayer_types::core::ics04_channel::version::Version; +use ibc_relayer_types::core::ics24_host::identifier::PortId; +use tracing::{debug, info}; + +use super::connection::{bootstrap_connection, BootstrapConnectionOptions}; +use crate::types::binary::chains::ConnectedChains; +use crate::types::binary::channel::ConnectedChannel; +use crate::types::binary::connection::ConnectedConnection; +use crate::types::binary::foreign_client::ForeignClientPair; +use crate::types::id::TaggedPortIdRef; +use crate::types::tagged::*; +use crate::util::random::random_u64_range; pub struct BootstrapChannelOptions { pub order: Ordering, diff --git a/tools/test-framework/src/bootstrap/binary/connection.rs b/tools/test-framework/src/bootstrap/binary/connection.rs index b762fdc8a2..8066dba454 100644 --- a/tools/test-framework/src/bootstrap/binary/connection.rs +++ b/tools/test-framework/src/bootstrap/binary/connection.rs @@ -3,37 +3,19 @@ */ use core::time::Duration; - -use eyre::{ - eyre, - Report as Error, -}; -use ibc_relayer::{ - chain::handle::ChainHandle, - config::default::connection_delay as default_connection_delay, - connection::{ - Connection, - ConnectionSide, - }, -}; +use eyre::{eyre, Report as Error}; +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::config::default::connection_delay as default_connection_delay; +use ibc_relayer::connection::{Connection, ConnectionSide}; use ibc_relayer_types::timestamp::ZERO_DURATION; -use tracing::{ - debug, - info, -}; - -use crate::{ - relayer::connection::TaggedConnectionExt, - types::{ - binary::{ - client::ClientIdPair, - connection::ConnectedConnection, - foreign_client::ForeignClientPair, - }, - id::TaggedClientIdRef, - }, - util::random::random_u64_range, -}; +use tracing::{debug, info}; + +use crate::relayer::connection::TaggedConnectionExt; +use crate::types::binary::client::ClientIdPair; +use crate::types::binary::connection::ConnectedConnection; +use crate::types::binary::foreign_client::ForeignClientPair; +use crate::types::id::TaggedClientIdRef; +use crate::util::random::random_u64_range; pub struct BootstrapConnectionOptions { pub connection_delay: Duration, diff --git a/tools/test-framework/src/bootstrap/consumer.rs b/tools/test-framework/src/bootstrap/consumer.rs index 72d8227a08..6c85595331 100644 --- a/tools/test-framework/src/bootstrap/consumer.rs +++ b/tools/test-framework/src/bootstrap/consumer.rs @@ -1,35 +1,18 @@ /*! Helper functions for bootstrapping a consumer full node. */ -use std::{ - sync::{ - Arc, - RwLock, - }, - thread, - time::Duration, -}; - use eyre::eyre; -use toml; +use std::sync::{Arc, RwLock}; +use std::thread; +use std::time::Duration; use tracing::info; -use crate::{ - chain::{ - builder::ChainBuilder, - config, - ext::bootstrap::ChainBootstrapMethodsExt, - }, - error::Error, - prelude::{ - ChainDriver, - Denom, - FullNode, - TestWallets, - Token, - }, - util::random::random_u128_range, -}; +use crate::chain::builder::ChainBuilder; +use crate::chain::config; +use crate::chain::ext::bootstrap::ChainBootstrapMethodsExt; +use crate::error::Error; +use crate::prelude::{ChainDriver, Denom, FullNode, TestWallets, Token}; +use crate::util::random::random_u128_range; pub fn bootstrap_consumer_node( builder: &ChainBuilder, @@ -91,6 +74,7 @@ pub fn bootstrap_consumer_node( 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)?; + config::set_retry_delay_period(genesis, "100s")?; Ok(()) })?; diff --git a/tools/test-framework/src/bootstrap/init.rs b/tools/test-framework/src/bootstrap/init.rs index 0762fb0c0d..795f19787c 100644 --- a/tools/test-framework/src/bootstrap/init.rs +++ b/tools/test-framework/src/bootstrap/init.rs @@ -3,28 +3,20 @@ session. */ -use std::{ - env, - fs, - sync::Once, -}; - use eyre::Report as Error; use ibc_relayer_cli::components::enable_ansi; +use std::env; +use std::fs; +use std::sync::Once; use tracing_subscriber::{ self as ts, - filter::{ - EnvFilter, - LevelFilter, - }, + filter::{EnvFilter, LevelFilter}, layer::SubscriberExt, util::SubscriberInitExt, }; -use crate::{ - types::config::TestConfig, - util::random::random_u32, -}; +use crate::types::config::TestConfig; +use crate::util::random::random_u32; static INIT: Once = Once::new(); diff --git a/tools/test-framework/src/bootstrap/nary/chain.rs b/tools/test-framework/src/bootstrap/nary/chain.rs index 3c80d7e86d..3a758b7446 100644 --- a/tools/test-framework/src/bootstrap/nary/chain.rs +++ b/tools/test-framework/src/bootstrap/nary/chain.rs @@ -2,37 +2,19 @@ Functions for bootstrapping N-ary number of chains. */ -use core::convert::TryInto; +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::config::Config; +use ibc_relayer::registry::SharedRegistry; -use ibc_relayer::{ - chain::handle::ChainHandle, - config::Config, - foreign_client::ForeignClient, - registry::SharedRegistry, -}; - -use crate::{ - bootstrap::binary::chain::{ - add_chain_config, - add_keys_to_chain_handle, - bootstrap_foreign_client, - new_registry, - save_relayer_config, - }, - error::{ - handle_generic_error, - Error, - }, - relayer::driver::RelayerDriver, - types::{ - config::TestConfig, - nary::chains::{ - DynamicConnectedChains, - NaryConnectedChains, - }, - single::node::FullNode, - }, +use crate::bootstrap::binary::chain::{ + add_chain_config, add_keys_to_chain_handle, new_registry, save_relayer_config, }; +use crate::error::{handle_generic_error, Error}; +use crate::relayer::driver::RelayerDriver; +use crate::types::config::TestConfig; +use crate::types::nary::chains::{DynamicConnectedChains, NaryConnectedChains}; +use crate::types::single::node::FullNode; +use crate::types::topology::{bootstrap_topology, TopologyType}; /** Bootstrap a fixed number of chains specified by `SIZE`. @@ -40,10 +22,15 @@ use crate::{ pub fn boostrap_chains_with_nodes( test_config: &TestConfig, full_nodes: [FullNode; SIZE], + topology_override: Option, config_modifier: impl FnOnce(&mut Config), ) -> Result<(RelayerDriver, NaryConnectedChains), Error> { - let (relayer, chains) = - boostrap_chains_with_any_nodes(test_config, full_nodes.into(), config_modifier)?; + let (relayer, chains) = boostrap_chains_with_any_nodes( + test_config, + full_nodes.into(), + topology_override, + config_modifier, + )?; Ok((relayer, chains.try_into()?)) } @@ -55,11 +42,16 @@ pub fn boostrap_chains_with_nodes( pub fn boostrap_chains_with_self_connected_node( test_config: &TestConfig, full_node: FullNode, + topology_override: Option, config_modifier: impl FnOnce(&mut Config), ) -> Result<(RelayerDriver, NaryConnectedChains), Error> { let full_nodes = vec![full_node; SIZE]; - let (relayer, chains) = - boostrap_chains_with_any_nodes(test_config, full_nodes, config_modifier)?; + let (relayer, chains) = boostrap_chains_with_any_nodes( + test_config, + full_nodes, + topology_override, + config_modifier, + )?; Ok((relayer, chains.try_into()?)) } @@ -67,10 +59,13 @@ pub fn boostrap_chains_with_self_connected_node( /** Bootstrap a dynamic number of chains, according to the number of full nodes in the `Vec`. + The topology will be retrieved and set in this method, + see [`crate::types::topology`] for more information. */ pub fn boostrap_chains_with_any_nodes( test_config: &TestConfig, full_nodes: Vec, + topology_override: Option, config_modifier: impl FnOnce(&mut Config), ) -> Result<(RelayerDriver, DynamicConnectedChains), Error> { let mut config = Config::default(); @@ -94,19 +89,24 @@ pub fn boostrap_chains_with_any_nodes( chain_handles.push(handle); } - let mut foreign_clients: Vec>> = Vec::new(); - - for handle_a in chain_handles.iter() { - let mut foreign_clients_b = Vec::new(); - - for handle_b in chain_handles.iter() { - let foreign_client = bootstrap_foreign_client(handle_a, handle_b, Default::default())?; - - foreign_clients_b.push(foreign_client); + // Retrieve the topology or fallback to the Linear topology + let topology_type = if let Some(topology_type) = topology_override { + topology_type + } else { + let topology_str = std::env::var("TOPOLOGY").unwrap_or_else(|_| "linear".to_owned()); + match topology_str.parse() { + Ok(topology_type) => topology_type, + Err(_) => { + tracing::warn!( + "Failed to parse topology type `{topology_str}`. Will fallback to Linear topology" + ); + TopologyType::Linear + } } + }; + let topology = bootstrap_topology(topology_type); - foreign_clients.push(foreign_clients_b); - } + let foreign_clients = topology.create_topology(&chain_handles)?; let relayer = RelayerDriver { config_path, diff --git a/tools/test-framework/src/bootstrap/nary/channel.rs b/tools/test-framework/src/bootstrap/nary/channel.rs index b96b123bf8..6c4e65f582 100644 --- a/tools/test-framework/src/bootstrap/nary/channel.rs +++ b/tools/test-framework/src/bootstrap/nary/channel.rs @@ -2,105 +2,61 @@ Functions for bootstrapping N-ary number of channels. */ -use core::{ - convert::TryInto, - time::Duration, -}; - +use core::time::Duration; use ibc_relayer::chain::handle::ChainHandle; -use ibc_relayer_types::core::{ - ics04_channel::channel::Ordering, - ics24_host::identifier::PortId, -}; +use ibc_relayer_types::core::ics04_channel::channel::Ordering; +use ibc_relayer_types::core::ics24_host::identifier::PortId; -use crate::{ - bootstrap::{ - binary::channel::{ - bootstrap_channel_with_connection, - BootstrapChannelOptions, - }, - nary::connection::bootstrap_connections_dynamic, - }, - error::{ - handle_generic_error, - Error, - }, - types::{ - binary::channel::ConnectedChannel, - nary::{ - chains::{ - DynamicConnectedChains, - NaryConnectedChains, - }, - channel::{ - ConnectedChannels, - DynamicConnectedChannels, - }, - connection::{ - ConnectedConnections, - DynamicConnectedConnections, - }, - }, - tagged::*, - }, - util::array::{ - assert_same_dimension, - into_nested_vec, - }, +use crate::bootstrap::binary::channel::{ + bootstrap_channel_with_connection, BootstrapChannelOptions, }; +use crate::bootstrap::nary::connection::bootstrap_connections_dynamic; +use crate::error::{handle_generic_error, Error}; +use crate::types::binary::channel::ConnectedChannel; +use crate::types::nary::chains::{DynamicConnectedChains, NaryConnectedChains}; +use crate::types::nary::channel::{ConnectedChannels, DynamicConnectedChannels}; +use crate::types::nary::connection::{ConnectedConnections, DynamicConnectedConnections}; +use crate::types::tagged::*; +use crate::util::array::into_nested_vec; +use crate::util::two_dim_hash_map::TwoDimMap; /** Bootstrap a dynamic number of channels based on the number of connections in `DynamicConnectedConnections`. + See [`crate::types::topology`] for more information. */ pub fn bootstrap_channels_with_connections_dynamic( connections: DynamicConnectedConnections, - chains: &Vec, ports: &Vec>, order: Ordering, bootstrap_with_random_ids: bool, ) -> Result, Error> { - let size = chains.len(); - - assert_same_dimension(size, connections.connections())?; - assert_same_dimension(size, ports)?; - - let mut channels: Vec>> = Vec::new(); - - for (i, connections_b) in connections.connections().iter().enumerate() { - let mut channels_b: Vec> = Vec::new(); - - for (j, connection) in connections_b.iter().enumerate() { - if i <= j { - let chain_a = &chains[i]; - let chain_b = &chains[j]; - - let port_a = &ports[i][j]; - let port_b = &ports[j][i]; - - let bootstrap_options = BootstrapChannelOptions::default() - .order(order) - .bootstrap_with_random_ids(bootstrap_with_random_ids); - - let channel = bootstrap_channel_with_connection( - chain_a, - chain_b, - connection.clone(), - &DualTagged::new(port_a), - &DualTagged::new(port_b), - bootstrap_options, - )?; - - channels_b.push(channel); - } else { - let counter_channel = &channels[j][i]; - let channel = counter_channel.clone().flip(); - - channels_b.push(channel); - } - } - - channels.push(channels_b); + let mut channels: TwoDimMap> = TwoDimMap::new(); + + for (src_chain, dst_chain, connection) in connections.connections().iter() { + let channel = if let Some(counterparty_channel) = channels.get((dst_chain, src_chain)) { + counterparty_channel.clone().flip() + } else { + // No channel is found, will create one + let chain_a = &connection.connection.a_chain(); + let chain_b = &connection.connection.b_chain(); + let port_a = ports[src_chain][dst_chain].clone(); + let port_b = ports[dst_chain][src_chain].clone(); + + let bootstrap_options = BootstrapChannelOptions::default() + .order(order) + .bootstrap_with_random_ids(bootstrap_with_random_ids); + + bootstrap_channel_with_connection( + chain_a, + chain_b, + connection.clone(), + &DualTagged::new(&port_a), + &DualTagged::new(&port_b), + bootstrap_options, + )? + }; + channels.insert((src_chain, dst_chain), channel); } Ok(DynamicConnectedChannels::new(channels)) @@ -112,14 +68,12 @@ pub fn bootstrap_channels_with_connections_dynamic( */ pub fn bootstrap_channels_with_connections( connections: ConnectedConnections, - chains: [Handle; SIZE], ports: [[PortId; SIZE]; SIZE], order: Ordering, bootstrap_with_random_ids: bool, ) -> Result, Error> { let channels = bootstrap_channels_with_connections_dynamic( connections.into(), - &chains.into(), &into_nested_vec(ports), order, bootstrap_with_random_ids, @@ -148,7 +102,6 @@ pub fn bootstrap_channels_and_connections_dynamic( bootstrap_channels_with_connections_dynamic( connections, - chains.chain_handles(), ports, order, bootstrap_with_random_ids, diff --git a/tools/test-framework/src/bootstrap/nary/connection.rs b/tools/test-framework/src/bootstrap/nary/connection.rs index 03c4bd092c..065ef1385a 100644 --- a/tools/test-framework/src/bootstrap/nary/connection.rs +++ b/tools/test-framework/src/bootstrap/nary/connection.rs @@ -2,78 +2,55 @@ Functions for bootstrapping N-ary number of connections. */ -use core::{ - convert::TryInto, - time::Duration, -}; - -use ibc_relayer::{ - chain::handle::ChainHandle, - foreign_client::ForeignClient, -}; - -use crate::{ - bootstrap::binary::connection::{ - bootstrap_connection, - BootstrapConnectionOptions, - }, - error::Error, - types::{ - binary::{ - connection::ConnectedConnection, - foreign_client::ForeignClientPair, - }, - nary::{ - connection::{ - ConnectedConnections, - DynamicConnectedConnections, - }, - foreign_client::ForeignClientPairs, - }, - }, - util::array::assert_same_dimension, -}; +use core::time::Duration; +use eyre::eyre; +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::foreign_client::ForeignClient; + +use crate::bootstrap::binary::connection::{bootstrap_connection, BootstrapConnectionOptions}; +use crate::error::Error; +use crate::types::binary::connection::ConnectedConnection; +use crate::types::binary::foreign_client::ForeignClientPair; +use crate::types::nary::connection::{ConnectedConnections, DynamicConnectedConnections}; +use crate::types::nary::foreign_client::ForeignClientPairs; +use crate::util::two_dim_hash_map::TwoDimMap; /** Bootstrap a dynamic number of connections based on the - given foreign client NxN matrix. + given foreign clients. + See [`crate::types::topology`] for more information. */ pub fn bootstrap_connections_dynamic( - foreign_clients: &Vec>>, + foreign_clients: &TwoDimMap>, connection_delay: Duration, bootstrap_with_random_ids: bool, ) -> Result, Error> { - let size = foreign_clients.len(); - - assert_same_dimension(size, foreign_clients)?; - - let mut connections: Vec>> = Vec::new(); - - for (i, foreign_clients_b) in foreign_clients.iter().enumerate() { - let mut connections_b: Vec> = Vec::new(); - - for (j, foreign_client) in foreign_clients_b.iter().enumerate() { - if i <= j { - let counter_foreign_client = &foreign_clients[j][i]; - let foreign_clients = - ForeignClientPair::new(foreign_client.clone(), counter_foreign_client.clone()); - - let bootstrap_options = BootstrapConnectionOptions::default() - .connection_delay(connection_delay) - .bootstrap_with_random_ids(bootstrap_with_random_ids); - - let connection = bootstrap_connection(&foreign_clients, bootstrap_options)?; - - connections_b.push(connection); - } else { - let counter_connection = &connections[j][i]; - let connection = counter_connection.clone().flip(); - - connections_b.push(connection); - } - } - - connections.push(connections_b); + let mut connections: TwoDimMap> = TwoDimMap::new(); + + for (src_chain, dst_chain, foreign_client) in foreign_clients.iter() { + let connection = if let Some(counterparty_connection) = + connections.get((dst_chain, src_chain)) + { + counterparty_connection.clone().flip() + } else { + // No connection is found, will create one + let client_a_to_b = foreign_client.clone(); + let client_b_to_a = foreign_clients.get((dst_chain, src_chain)).ok_or_else(|| { + Error::generic(eyre!( + "No client entry found from chain `{}` to `{}`", + dst_chain, + src_chain, + )) + })?; + let foreign_clients = ForeignClientPair::new(client_a_to_b, client_b_to_a.clone()); + + let bootstrap_options = BootstrapConnectionOptions::default() + .connection_delay(connection_delay) + .bootstrap_with_random_ids(bootstrap_with_random_ids); + + bootstrap_connection(&foreign_clients, bootstrap_options)? + }; + connections.insert((src_chain, dst_chain), connection); } Ok(DynamicConnectedConnections::new(connections)) diff --git a/tools/test-framework/src/bootstrap/single.rs b/tools/test-framework/src/bootstrap/single.rs index d75d64b2ce..508d0b28ba 100644 --- a/tools/test-framework/src/bootstrap/single.rs +++ b/tools/test-framework/src/bootstrap/single.rs @@ -2,39 +2,20 @@ Helper functions for bootstrapping a single full node. */ use core::time::Duration; -use std::sync::{ - Arc, - RwLock, -}; - use eyre::eyre; -use toml; +use std::sync::{Arc, RwLock}; use tracing::info; -use crate::{ - chain::{ - builder::ChainBuilder, - config, - driver::ChainDriver, - ext::bootstrap::ChainBootstrapMethodsExt, - }, - error::Error, - ibc::{ - denom::Denom, - token::Token, - }, - types::{ - single::node::FullNode, - wallet::{ - TestWallets, - Wallet, - }, - }, - util::random::{ - random_u128_range, - random_u32, - }, -}; +use crate::chain::builder::ChainBuilder; +use crate::chain::config; +use crate::chain::driver::ChainDriver; +use crate::chain::ext::bootstrap::ChainBootstrapMethodsExt; +use crate::error::Error; +use crate::ibc::denom::Denom; +use crate::ibc::token::Token; +use crate::types::single::node::FullNode; +use crate::types::wallet::{TestWallets, Wallet}; +use crate::util::random::{random_u128_range, random_u32}; /** Bootstrap a single full node with the provided [`ChainBuilder`] and diff --git a/tools/test-framework/src/chain/builder.rs b/tools/test-framework/src/chain/builder.rs index 4637e4ea73..ff23be521f 100644 --- a/tools/test-framework/src/chain/builder.rs +++ b/tools/test-framework/src/chain/builder.rs @@ -2,20 +2,19 @@ Builder construct that spawn new chains with some common parameters. */ -use alloc::sync::Arc; +use eyre::eyre; use std::str::FromStr; -use eyre::eyre; +use alloc::sync::Arc; use ibc_relayer::config::compat_mode::CompatMode; use tokio::runtime::Runtime; +use crate::chain::driver::ChainDriver; +use crate::error::Error; +use crate::types::config::TestConfig; +use crate::util::random::random_unused_tcp_port; + use super::chain_type::ChainType; -use crate::{ - chain::driver::ChainDriver, - error::Error, - types::config::TestConfig, - util::random::random_unused_tcp_port, -}; /** Used for holding common configuration needed to create new `ChainDriver`s. diff --git a/tools/test-framework/src/chain/chain_type.rs b/tools/test-framework/src/chain/chain_type.rs index 160d3f3a36..309a91b00e 100644 --- a/tools/test-framework/src/chain/chain_type.rs +++ b/tools/test-framework/src/chain/chain_type.rs @@ -1,15 +1,9 @@ use core::str::FromStr; - use ibc_relayer::config::AddressType; use ibc_relayer_types::core::ics24_host::identifier::ChainId; -use crate::{ - error::Error, - util::random::{ - random_u32, - random_unused_tcp_port, - }, -}; +use crate::error::Error; +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"; @@ -17,33 +11,40 @@ const PROVENANCE_HD_PATH: &str = "m/44'/505'/0'/0/0"; #[derive(Clone, Debug)] pub enum ChainType { - Cosmos, + Cosmos { dynamic_fee: bool }, + Osmosis, Evmos, - Astria, Provenance, + Injective, } impl ChainType { pub fn hd_path(&self) -> &str { match self { - Self::Cosmos => COSMOS_HD_PATH, - Self::Evmos => EVMOS_HD_PATH, - Self::Astria => todo!("Astria HD path not yet implemented"), + Self::Cosmos { dynamic_fee: _ } | Self::Osmosis => COSMOS_HD_PATH, + Self::Evmos | Self::Injective => EVMOS_HD_PATH, Self::Provenance => PROVENANCE_HD_PATH, } } pub fn chain_id(&self, prefix: &str, use_random_id: bool) -> ChainId { match self { - Self::Cosmos => { + Self::Cosmos { dynamic_fee: _ } => { if use_random_id { ChainId::from_string(&format!("ibc-{}-{:x}", prefix, random_u32())) } else { ChainId::from_string(&format!("ibc{prefix}")) } } + Self::Osmosis => { + if use_random_id { + ChainId::from_string(&format!("osmosis-{}-{:x}", prefix, random_u32())) + } else { + ChainId::from_string(&format!("osmosis{prefix}")) + } + } + Self::Injective => ChainId::from_string(&format!("injective-{prefix}")), Self::Evmos => ChainId::from_string(&format!("evmos_9000-{prefix}")), - Self::Astria => todo!("Astria chain id not yet implemented"), Self::Provenance => ChainId::from_string(&format!("pio-mainnet-{prefix}")), } } @@ -53,27 +54,48 @@ impl ChainType { let mut res = vec![]; let json_rpc_port = random_unused_tcp_port(); match self { - Self::Cosmos => {} + Self::Cosmos { dynamic_fee: _ } | Self::Injective | Self::Provenance => {} + Self::Osmosis => { + res.push("--reject-config-defaults".to_owned()); + } Self::Evmos => { res.push("--json-rpc.address".to_owned()); res.push(format!("localhost:{json_rpc_port}")); } - Self::Astria => todo!("Astria extra start args not yet implemented"), - Self::Provenance => {} + } + res + } + + // Extra arguments required to run ` add-genesis-account` + pub fn extra_add_genesis_account_args(&self, chain_id: &ChainId) -> Vec { + let mut res = vec![]; + match self { + Self::Cosmos { dynamic_fee: _ } | Self::Osmosis | Self::Evmos | Self::Provenance => {} + Self::Injective => { + res.push("--chain-id".to_owned()); + res.push(format!("{chain_id}")); + } } res } pub fn address_type(&self) -> AddressType { match self { - Self::Cosmos => AddressType::default(), + Self::Cosmos { dynamic_fee: _ } | Self::Osmosis | Self::Provenance => { + AddressType::default() + } Self::Evmos => AddressType::Ethermint { pk_type: "/ethermint.crypto.v1.ethsecp256k1.PubKey".to_string(), }, - Self::Astria => AddressType::Astria, - Self::Provenance => AddressType::default(), + Self::Injective => AddressType::Ethermint { + pk_type: "/injective.crypto.v1beta1.ethsecp256k1.PubKey".to_string(), + }, } } + + pub fn enable_dynamic_fee(&self) -> bool { + matches!(self, Self::Cosmos { dynamic_fee } if *dynamic_fee) + } } impl FromStr for ChainType { @@ -81,14 +103,14 @@ impl FromStr for ChainType { fn from_str(s: &str) -> Result { match s { - name if name.contains("gaiad") => Ok(ChainType::Cosmos), - name if name.contains("simd") => Ok(ChainType::Cosmos), - name if name.contains("wasmd") => Ok(ChainType::Cosmos), - name if name.contains("icad") => Ok(ChainType::Cosmos), + name if name.contains("gaiad") || name.contains("neutrond") => { + Ok(ChainType::Cosmos { dynamic_fee: true }) + } name if name.contains("evmosd") => Ok(ChainType::Evmos), - name if name.contains("astria") => Ok(ChainType::Astria), + name if name.contains("injectived") => Ok(ChainType::Injective), name if name.contains("provenanced") => Ok(ChainType::Provenance), - _ => Ok(ChainType::Cosmos), + name if name.contains("osmosisd") => Ok(ChainType::Osmosis), + _ => Ok(ChainType::Cosmos { dynamic_fee: false }), } } } diff --git a/tools/test-framework/src/chain/cli/async_icq.rs b/tools/test-framework/src/chain/cli/async_icq.rs index ed97f32893..345bf80058 100644 --- a/tools/test-framework/src/chain/cli/async_icq.rs +++ b/tools/test-framework/src/chain/cli/async_icq.rs @@ -1,9 +1,6 @@ -use std::str; - -use crate::{ - chain::exec::simple_exec, - error::Error, -}; +use crate::chain::cli::query::query_tx_hash; +use crate::chain::exec::simple_exec; +use crate::error::Error; pub fn update_oracle( chain_id: &str, @@ -13,7 +10,7 @@ pub fn update_oracle( account: &str, relayer: &str, ) -> Result<(), Error> { - simple_exec( + let raw_output = simple_exec( chain_id, command_path, &[ @@ -23,8 +20,8 @@ pub fn update_oracle( chain_id, "--node", rpc_listen_address, - "-b", - "block", + "--keyring-backend", + "test", "tx", "oracle", "update", @@ -35,10 +32,26 @@ pub fn update_oracle( relayer, "--fees", "381000000nhash", + "--title", + "Update oracle", + "--summary", + "Update oracle", + "--output", + "json", "--yes", ], )?; + std::thread::sleep(core::time::Duration::from_secs(1)); + + query_tx_hash( + chain_id, + command_path, + home_path, + rpc_listen_address, + &raw_output.stdout, + )?; + Ok(()) } @@ -51,7 +64,7 @@ pub fn async_icq( query_json: &str, from: &str, ) -> Result<(), Error> { - simple_exec( + let raw_output = simple_exec( chain_id, command_path, &[ @@ -61,21 +74,33 @@ pub fn async_icq( chain_id, "--node", rpc_listen_address, + "--keyring-backend", + "test", "tx", "oracle", "send-query", channel_id, query_json, - "-b", - "block", "--from", from, "--fees", "381000000nhash", + "--output", + "json", "--yes", ], )?; + std::thread::sleep(core::time::Duration::from_secs(1)); + + query_tx_hash( + chain_id, + command_path, + home_path, + rpc_listen_address, + &raw_output.stdout, + )?; + Ok(()) } diff --git a/tools/test-framework/src/chain/cli/authz.rs b/tools/test-framework/src/chain/cli/authz.rs new file mode 100644 index 0000000000..d6bcf22a20 --- /dev/null +++ b/tools/test-framework/src/chain/cli/authz.rs @@ -0,0 +1,165 @@ +use eyre::eyre; +use std::collections::HashMap; +use std::thread; + +use crate::chain::exec::simple_exec; +use crate::error::Error; +use crate::prelude::*; + +pub fn authz_grant( + chain_id: &str, + command_path: &str, + home_path: &str, + rpc_listen_address: &str, + granter: &str, + grantee: &str, + msg_type: &str, + fees: &str, +) -> Result<(), Error> { + simple_exec( + chain_id, + command_path, + &[ + "--home", + home_path, + "--node", + rpc_listen_address, + "--chain-id", + chain_id, + "--keyring-backend", + "test", + "tx", + "authz", + "grant", + grantee, + "generic", + "--msg-type", + msg_type, + "--from", + granter, + "--fees", + fees, + "--yes", + "--log_format=json", + ], + )?; + + Ok(()) +} + +pub fn query_authz_grant( + chain_id: &str, + command_path: &str, + home_path: &str, + rpc_listen_address: &str, + granter: &str, + grantee: &str, + msg_type: &str, +) -> Result<(), Error> { + simple_exec( + chain_id, + command_path, + &[ + "--home", + home_path, + "--node", + rpc_listen_address, + "query", + "authz", + "grants", + granter, + grantee, + msg_type, + "--output", + "json", + ], + )?; + + Ok(()) +} + +pub fn exec_grant( + chain_id: &str, + command_path: &str, + home_path: &str, + rpc_listen_address: &str, + ibc_transfer_tx: &str, + grantee: &str, + fees: &str, +) -> Result<(), Error> { + let grant_exec_output = simple_exec( + chain_id, + command_path, + &[ + "--home", + home_path, + "--node", + rpc_listen_address, + "--keyring-backend", + "test", + "--chain-id", + chain_id, + "tx", + "authz", + "exec", + ibc_transfer_tx, + "--from", + grantee, + "--fees", + fees, + "--yes", + "--output", + "json", + ], + )?; + + let json_res: HashMap = + serde_json::from_str(&grant_exec_output.stdout).map_err(handle_generic_error)?; + + let txhash = json_res + .get("txhash") + .ok_or_else(|| eyre!("expect `txhash` string field to be present in json result"))? + .as_str() + .ok_or_else(|| eyre!("expected `txhash` to be an array"))?; + + thread::sleep(Duration::from_secs(2)); + + let query_txhash_output = simple_exec( + chain_id, + command_path, + &[ + "--home", + home_path, + "--node", + rpc_listen_address, + "query", + "tx", + "--type=hash", + txhash, + "--output", + "json", + ], + )?; + + let json_res: HashMap = + serde_json::from_str(&query_txhash_output.stdout).map_err(handle_generic_error)?; + + let raw_log = json_res + .get("raw_log") + .ok_or_else(|| eyre!("expect `raw_log` string field to be present in json result"))? + .as_str() + .ok_or_else(|| eyre!("expected `raw_log` to be a string"))?; + + let code = json_res + .get("code") + .ok_or_else(|| eyre!("expect `code` string field to be present in json result"))? + .as_u64() + .ok_or_else(|| eyre!("expected `code` to be a u64"))?; + + if !raw_log.is_empty() && code != 0 { + return Err(Error::generic(eyre!( + "expected authz exec to succeed but failed with code: {code} and logs: {raw_log}" + ))); + } + Ok(()) +} diff --git a/tools/test-framework/src/chain/cli/bootstrap.rs b/tools/test-framework/src/chain/cli/bootstrap.rs index ebdc848b4e..fbe530e2ff 100644 --- a/tools/test-framework/src/chain/cli/bootstrap.rs +++ b/tools/test-framework/src/chain/cli/bootstrap.rs @@ -1,22 +1,14 @@ use core::time::Duration; -use std::{ - fs, - process::{ - Command, - Stdio, - }, - str, - thread::sleep, -}; - use eyre::eyre; +use std::fs; +use std::process::{Command, Stdio}; +use std::str; +use std::thread::sleep; -use crate::{ - chain::exec::simple_exec, - error::Error, - types::process::ChildProcess, - util::file::pipe_to_file, -}; +use crate::chain::exec::simple_exec; +use crate::error::Error; +use crate::types::process::ChildProcess; +use crate::util::file::pipe_to_file; pub fn initialize(chain_id: &str, command_path: &str, home_path: &str) -> Result<(), Error> { simple_exec( @@ -70,35 +62,37 @@ pub fn add_genesis_account( home_path: &str, wallet_address: &str, amounts: &[String], + extra_start_args: &[&str], ) -> Result<(), Error> { let amounts_str = itertools::join(amounts, ","); + + let legacy_base_args = [ + "--home", + home_path, + "add-genesis-account", + wallet_address, + &amounts_str, + ]; + let mut legacy_args: Vec<&str> = legacy_base_args.to_vec(); + legacy_args.extend(extra_start_args.iter()); + + let base_args = [ + "--home", + home_path, + "genesis", + "add-genesis-account", + wallet_address, + &amounts_str, + ]; + let mut args: Vec<&str> = base_args.to_vec(); + args.extend(extra_start_args.iter()); + // 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, - ], - ) { + match simple_exec(chain_id, command_path, &args) { Ok(_) => Ok(()), Err(_) => { - simple_exec( - chain_id, - command_path, - &[ - "--home", - home_path, - "add-genesis-account", - wallet_address, - &amounts_str, - ], - )?; + simple_exec(chain_id, command_path, &legacy_args)?; Ok(()) } } diff --git a/tools/test-framework/src/chain/cli/fee_grant.rs b/tools/test-framework/src/chain/cli/fee_grant.rs index 738f4e991d..b20e425d90 100644 --- a/tools/test-framework/src/chain/cli/fee_grant.rs +++ b/tools/test-framework/src/chain/cli/fee_grant.rs @@ -1,7 +1,5 @@ -use crate::{ - chain::exec::simple_exec, - error::Error, -}; +use crate::chain::exec::simple_exec; +use crate::error::Error; pub fn feegrant_grant( chain_id: &str, diff --git a/tools/test-framework/src/chain/cli/host_zone.rs b/tools/test-framework/src/chain/cli/host_zone.rs index ab6883fa80..94e2400e2a 100644 --- a/tools/test-framework/src/chain/cli/host_zone.rs +++ b/tools/test-framework/src/chain/cli/host_zone.rs @@ -1,7 +1,5 @@ -use crate::{ - chain::exec::simple_exec, - error::Error, -}; +use crate::chain::exec::simple_exec; +use crate::error::Error; pub fn register_host_zone( chain_id: &str, @@ -33,13 +31,16 @@ pub fn register_host_zone( bech32_prefix, ibc_denom, channel_id, - "1", + "10", + "false", "--from", sender, "--chain-id", chain_id, "--gas", "auto", + "--gas-adjustment", + "1.3", "--yes", ], )?; diff --git a/tools/test-framework/src/chain/cli/ica.rs b/tools/test-framework/src/chain/cli/ica.rs index 3c2cd98d58..5524543745 100644 --- a/tools/test-framework/src/chain/cli/ica.rs +++ b/tools/test-framework/src/chain/cli/ica.rs @@ -1,13 +1,8 @@ use eyre::eyre; use serde_json as json; -use crate::{ - chain::exec::simple_exec, - error::{ - handle_generic_error, - Error, - }, -}; +use crate::chain::exec::simple_exec; +use crate::error::{handle_generic_error, Error}; /// Register a new interchain account controlled by the given account /// over the given connection. diff --git a/tools/test-framework/src/chain/cli/mod.rs b/tools/test-framework/src/chain/cli/mod.rs index 5b2415d964..2d68ec6820 100644 --- a/tools/test-framework/src/chain/cli/mod.rs +++ b/tools/test-framework/src/chain/cli/mod.rs @@ -1,10 +1,13 @@ pub mod async_icq; +pub mod authz; pub mod bootstrap; pub mod fee_grant; pub mod host_zone; pub mod ica; +pub mod proposal; pub mod provider; pub mod query; pub mod transfer; pub mod upgrade; pub mod version; +pub mod wasm; diff --git a/tools/test-framework/src/chain/cli/proposal.rs b/tools/test-framework/src/chain/cli/proposal.rs new file mode 100644 index 0000000000..b8a0bc95e5 --- /dev/null +++ b/tools/test-framework/src/chain/cli/proposal.rs @@ -0,0 +1,181 @@ +/*! + Methods for voting on a proposal. +*/ +use eyre::eyre; +use tracing::warn; + +use crate::chain::cli::query::query_tx_hash; +use crate::chain::exec::simple_exec; +use crate::error::Error; +use crate::prelude::{handle_generic_error, ChainDriver}; + +pub fn vote_proposal(driver: &ChainDriver, proposal_id: &str, fees: &str) -> Result<(), Error> { + let output = simple_exec( + driver.chain_id.as_str(), + &driver.command_path, + &[ + "tx", + "gov", + "vote", + proposal_id, + "yes", + "--chain-id", + driver.chain_id.as_str(), + "--home", + &driver.home_path, + "--node", + &driver.rpc_listen_address(), + "--keyring-backend", + "test", + "--from", + "validator", + "--fees", + fees, + "--yes", + "--output", + "json", + ], + )?; + + std::thread::sleep(core::time::Duration::from_secs(1)); + + query_tx_hash( + driver.chain_id.as_str(), + &driver.command_path, + &driver.home_path, + &driver.rpc_listen_address(), + &output.stdout, + )?; + + Ok(()) +} + +pub fn deposit_proposal( + driver: &ChainDriver, + amount: &str, + proposal_id: &str, + fees: &str, + gas: &str, +) -> Result<(), Error> { + let output = simple_exec( + driver.chain_id.as_str(), + &driver.command_path, + &[ + "tx", + "gov", + "deposit", + proposal_id, + amount, + "--chain-id", + driver.chain_id.as_str(), + "--home", + &driver.home_path, + "--node", + &driver.rpc_listen_address(), + "--keyring-backend", + "test", + "--from", + "validator", + "--gas", + gas, + "--yes", + "--output", + "json", + "--fees", + fees, + ], + )?; + + std::thread::sleep(core::time::Duration::from_secs(1)); + + query_tx_hash( + driver.chain_id.as_str(), + &driver.command_path, + &driver.home_path, + &driver.rpc_listen_address(), + &output.stdout, + )?; + + Ok(()) +} + +pub fn submit_gov_proposal( + chain_id: &str, + command_path: &str, + home_path: &str, + rpc_listen_address: &str, + signer: &str, + proposal_file: &str, +) -> Result<(), Error> { + let proposal_file = format!("{}/{}", home_path, proposal_file); + let output = simple_exec( + chain_id, + command_path, + &[ + "--node", + rpc_listen_address, + "tx", + "gov", + "submit-proposal", + &proposal_file, + "--chain-id", + chain_id, + "--home", + home_path, + "--keyring-backend", + "test", + "--gas", + "20000000", + "--from", + signer, + "--output", + "json", + "--yes", + ], + )?; + + let json_output: serde_json::Value = + serde_json::from_str(&output.stdout).map_err(handle_generic_error)?; + + if json_output + .get("code") + .ok_or_else(|| eyre!("expected `code` field in output"))? + .as_u64() + .ok_or_else(|| eyre!("expected `code` to be a u64"))? + != 0 + { + let raw_log = json_output + .get("raw_log") + .ok_or_else(|| eyre!("expected `code` field in output"))? + .as_str() + .ok_or_else(|| eyre!("expected `raw_log` to be a str"))?; + warn!("failed to submit governance proposal due to `{raw_log}`. Will retry..."); + simple_exec( + chain_id, + command_path, + &[ + "--node", + rpc_listen_address, + "tx", + "gov", + "submit-proposal", + &proposal_file, + "--chain-id", + chain_id, + "--home", + home_path, + "--keyring-backend", + "test", + "--gas", + "20000000", + "--from", + signer, + "--output", + "json", + "--yes", + ], + )?; + } + + Ok(()) +} diff --git a/tools/test-framework/src/chain/cli/provider.rs b/tools/test-framework/src/chain/cli/provider.rs index f62204fdd2..2c5dc6f8cd 100644 --- a/tools/test-framework/src/chain/cli/provider.rs +++ b/tools/test-framework/src/chain/cli/provider.rs @@ -1,32 +1,27 @@ -use std::{ - collections::HashMap, - str, -}; - -use crate::{ - chain::exec::{ - simple_exec, - ExecOutput, - }, - error::Error, -}; +use eyre::eyre; +use std::collections::HashMap; +use std::str; + +use crate::chain::exec::{simple_exec, ExecOutput}; +use crate::error::{handle_generic_error, Error}; pub fn submit_consumer_chain_proposal( chain_id: &str, command_path: &str, home_path: &str, rpc_listen_address: &str, + fees: &str, ) -> Result<(), Error> { let proposal_file = format!("{}/consumer_proposal.json", home_path); // The submission might fail silently if there is not enough gas - simple_exec( + let raw_output = simple_exec( chain_id, command_path, &[ "tx", "gov", - "submit-proposal", + "submit-legacy-proposal", "consumer-addition", &proposal_file, "--chain-id", @@ -41,10 +36,24 @@ pub fn submit_consumer_chain_proposal( "test", "--gas", "2000000", + "--fees", + fees, + "--output", + "json", "--yes", ], )?; + let output: serde_json::Value = + serde_json::from_str(&raw_output.stdout).map_err(handle_generic_error)?; + + let output_code = output.get("code").and_then(|code| code.as_u64()).ok_or_else(|| Error::generic(eyre!("failed to extract 'code' from 'tx gov submit-legacy-proposal consumer-addition' command")))?; + + if output_code != 0 { + let output_logs = output.get("raw_log").and_then(|code| code.as_str()).ok_or_else(|| Error::generic(eyre!("failed to extract 'raw_logs' from 'tx gov submit-legacy-proposal consumer-addition' command")))?; + return Err(Error::generic(eyre!("output code for commande 'tx gov submit-legacy-proposal consumer-addition' should be 0, but is instead '{output_code}'. Detail: {output_logs}", ))); + } + Ok(()) } diff --git a/tools/test-framework/src/chain/cli/query.rs b/tools/test-framework/src/chain/cli/query.rs index a6e12d49ea..9c662a7161 100644 --- a/tools/test-framework/src/chain/cli/query.rs +++ b/tools/test-framework/src/chain/cli/query.rs @@ -1,19 +1,13 @@ use core::str::FromStr; -use std::collections::HashMap; - 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, - error::{ - handle_generic_error, - Error, - }, -}; +use crate::chain::exec::simple_exec; +use crate::error::{handle_generic_error, Error}; pub fn query_balance( chain_id: &str, @@ -298,3 +292,59 @@ pub fn query_auth_module( Ok(res.to_owned()) } + +pub fn query_tx_hash( + chain_id: &str, + command_path: &str, + home_path: &str, + rpc_listen_address: &str, + command_output: &str, +) -> Result<(), Error> { + let json_output: serde_json::Value = + serde_json::from_str(command_output).map_err(handle_generic_error)?; + + let output_tx_hash = json_output + .get("txhash") + .and_then(|code| code.as_str()) + .ok_or_else(|| { + Error::generic(eyre!( + "failed to extract 'txhash' from command output: {command_output}" + )) + })?; + + let raw_output = simple_exec( + chain_id, + command_path, + &[ + "--home", + home_path, + "--node", + rpc_listen_address, + "query", + "tx", + output_tx_hash, + "--output", + "json", + ], + )?; + + let json_output: serde_json::Value = + serde_json::from_str(&raw_output.stdout).map_err(handle_generic_error)?; + + let code = json_output + .get("code") + .and_then(|code| code.as_u64()) + .ok_or_else(|| eyre!("Failed to retrieve 'code' from 'query tx' command output"))?; + + if code != 0 { + let raw_log = json_output + .get("raw_log") + .and_then(|code| code.as_str()) + .ok_or_else(|| eyre!("Failed to retrieve 'raw_log' from 'query tx' command output"))?; + return Err(Error::generic(eyre!( + "command failed with error code {code}. Detail: {raw_log}" + ))); + } + + Ok(()) +} diff --git a/tools/test-framework/src/chain/cli/transfer.rs b/tools/test-framework/src/chain/cli/transfer.rs index a35df3a1da..b1da0efb15 100644 --- a/tools/test-framework/src/chain/cli/transfer.rs +++ b/tools/test-framework/src/chain/cli/transfer.rs @@ -1,11 +1,10 @@ /*! Methods for performing IBC token transfer on a chain. */ +use eyre::eyre; -use crate::{ - chain::exec::simple_exec, - error::Error, -}; +use crate::chain::exec::simple_exec; +use crate::error::{handle_generic_error, Error}; pub fn local_transfer_token( chain_id: &str, @@ -15,8 +14,9 @@ pub fn local_transfer_token( sender: &str, recipient: &str, token: &str, + fees: &str, ) -> Result<(), Error> { - simple_exec( + let raw_output = simple_exec( chain_id, command_path, &[ @@ -34,10 +34,36 @@ pub fn local_transfer_token( home_path, "--keyring-backend", "test", + "--fees", + fees, + "--output", + "json", "--yes", ], )?; + let output: serde_json::Value = + serde_json::from_str(&raw_output.stdout).map_err(handle_generic_error)?; + + let output_code = output + .get("code") + .and_then(|code| code.as_u64()) + .ok_or_else(|| { + Error::generic(eyre!("failed to extract 'code' from 'tx gov vote' command")) + })?; + + if output_code != 0 { + let output_logs = output + .get("raw_log") + .and_then(|code| code.as_str()) + .ok_or_else(|| { + Error::generic(eyre!( + "failed to extract 'raw_logs' from 'tx gov vote' command" + )) + })?; + return Err(Error::generic(eyre!("output code for commande 'tx gov vote' should be 0, but is instead '{output_code}'. Detail: {output_logs}", ))); + } + Ok(()) } @@ -85,3 +111,42 @@ pub fn transfer_from_chain( Ok(()) } + +pub fn generate_transfer_from_chain_tx( + chain_id: &str, + command_path: &str, + home_path: &str, + rpc_listen_address: &str, + sender: &str, + src_port: &str, + src_channel: &str, + recipient: &str, + token: &str, +) -> Result { + let output = simple_exec( + chain_id, + command_path, + &[ + "--node", + rpc_listen_address, + "tx", + "ibc-transfer", + "transfer", + src_port, + src_channel, + recipient, + token, + "--from", + sender, + "--chain-id", + chain_id, + "--home", + home_path, + "--keyring-backend", + "test", + "--generate-only", + ], + )?; + + Ok(output.stdout) +} diff --git a/tools/test-framework/src/chain/cli/upgrade.rs b/tools/test-framework/src/chain/cli/upgrade.rs index a723163482..a781fbaa38 100644 --- a/tools/test-framework/src/chain/cli/upgrade.rs +++ b/tools/test-framework/src/chain/cli/upgrade.rs @@ -1,10 +1,11 @@ /*! Methods for voting on a proposal. */ -use crate::{ - chain::exec::simple_exec, - error::Error, -}; +use eyre::eyre; + +use crate::chain::cli::query::query_tx_hash; +use crate::chain::exec::simple_exec; +use crate::prelude::*; pub fn vote_proposal( chain_id: &str, @@ -12,8 +13,9 @@ pub fn vote_proposal( home_path: &str, rpc_listen_address: &str, fees: &str, + proposal_id: &str, ) -> Result<(), Error> { - simple_exec( + let output = simple_exec( chain_id, command_path, &[ @@ -22,7 +24,7 @@ pub fn vote_proposal( "tx", "gov", "vote", - "1", + proposal_id, "yes", "--chain-id", chain_id, @@ -34,9 +36,102 @@ pub fn vote_proposal( "validator", "--fees", fees, + "--output", + "json", "--yes", ], )?; + std::thread::sleep(core::time::Duration::from_secs(1)); + + query_tx_hash( + chain_id, + command_path, + home_path, + rpc_listen_address, + &output.stdout, + )?; + + Ok(()) +} + +pub fn submit_gov_proposal( + chain_id: &str, + command_path: &str, + home_path: &str, + rpc_listen_address: &str, + signer: &str, + proposal_file: &str, +) -> Result<(), Error> { + let proposal_file = format!("{}/{}", home_path, proposal_file); + let output = simple_exec( + chain_id, + command_path, + &[ + "--node", + rpc_listen_address, + "tx", + "gov", + "submit-proposal", + &proposal_file, + "--chain-id", + chain_id, + "--home", + home_path, + "--keyring-backend", + "test", + "--gas", + "20000000", + "--from", + signer, + "--output", + "json", + "--yes", + ], + )?; + + let json_output: serde_json::Value = + serde_json::from_str(&output.stdout).map_err(handle_generic_error)?; + + if json_output + .get("code") + .ok_or_else(|| eyre!("expected `code` field in output"))? + .as_u64() + .ok_or_else(|| eyre!("expected `code` to be a u64"))? + != 0 + { + let raw_log = json_output + .get("raw_log") + .ok_or_else(|| eyre!("expected `code` field in output"))? + .as_str() + .ok_or_else(|| eyre!("expected `raw_log` to be a str"))?; + warn!("failed to submit governance proposal due to `{raw_log}`. Will retry..."); + simple_exec( + chain_id, + command_path, + &[ + "--node", + rpc_listen_address, + "tx", + "gov", + "submit-proposal", + &proposal_file, + "--chain-id", + chain_id, + "--home", + home_path, + "--keyring-backend", + "test", + "--gas", + "20000000", + "--from", + signer, + "--output", + "json", + "--yes", + ], + )?; + } + Ok(()) } diff --git a/tools/test-framework/src/chain/cli/version.rs b/tools/test-framework/src/chain/cli/version.rs index 8286f88f2b..d48a61f012 100644 --- a/tools/test-framework/src/chain/cli/version.rs +++ b/tools/test-framework/src/chain/cli/version.rs @@ -1,8 +1,6 @@ -use crate::{ - chain::exec::simple_exec, - error::Error, - prelude::handle_generic_error, -}; +use crate::chain::exec::simple_exec; +use crate::error::Error; +use crate::prelude::handle_generic_error; pub fn major_version(command_path: &str) -> Result { let output = simple_exec("version", command_path, &["version"])?; diff --git a/tools/test-framework/src/chain/cli/wasm/contract.rs b/tools/test-framework/src/chain/cli/wasm/contract.rs new file mode 100644 index 0000000000..f8dc207b60 --- /dev/null +++ b/tools/test-framework/src/chain/cli/wasm/contract.rs @@ -0,0 +1,162 @@ +use std::path::Path; + +use crate::chain::cli::query::query_tx_hash; +use crate::chain::exec::simple_exec; +use crate::error::Error; +use crate::prelude::ChainDriver; + +pub fn store_wasm_contract( + driver: &ChainDriver, + title: &str, + summary: &str, + wasm_file: &str, + authority: &str, + from: &str, + deposit: &str, + fees: &str, + gas: &str, +) -> Result { + let output = simple_exec( + driver.chain_id.as_str(), + &driver.command_path, + &[ + "--chain-id", + driver.chain_id.as_str(), + "--node", + &driver.rpc_listen_address(), + "--home", + &driver.home_path, + "--keyring-backend", + "test", + "tx", + "wasm", + "submit-proposal", + "wasm-store", + wasm_file, + "--title", + title, + "--summary", + summary, + "--authority", + authority, + "--deposit", + deposit, + "--output", + "json", + "--from", + from, + "--fees", + fees, + "--yes", + "--gas", + gas, + ], + )?; + + std::thread::sleep(core::time::Duration::from_secs(1)); + + query_tx_hash( + driver.chain_id.as_str(), + &driver.command_path, + &driver.home_path, + &driver.rpc_listen_address(), + &output.stdout, + )?; + + Ok(output.stdout) +} + +pub fn store_wasm_client_code( + driver: &ChainDriver, + code_path: &Path, + title: &str, + summary: &str, + signer: &str, +) -> Result { + let output = simple_exec( + driver.chain_id.as_str(), + &driver.command_path, + &[ + "tx", + "ibc-wasm", + "store-code", + code_path.to_str().unwrap(), + "--title", + title, + "--summary", + summary, + "--chain-id", + driver.chain_id.as_str(), + "--node", + &driver.rpc_listen_address(), + "--home", + &driver.home_path, + "--from", + signer, + "--keyring-backend", + "test", + "--gas", + "auto", + "--deposit", + "200000stake", + "-y", + "--output", + "json", + ], + )?; + + Ok(output.stdout) +} + +pub fn instantiate_wasm_contract( + chain_id: &str, + command_path: &str, + home_path: &str, + rpc_listen_address: &str, + address: &str, + fees: &str, + code: &str, + init_args: &str, +) -> Result<(), Error> { + let exec_output = simple_exec( + chain_id, + command_path, + &[ + "--home", + home_path, + "--chain-id", + chain_id, + "--node", + rpc_listen_address, + "--keyring-backend", + "test", + "tx", + "wasm", + "instantiate", + code, + init_args, + "--from", + address, + "--yes", + "--label", + "echo", + "--no-admin", + "--fees", + fees, + "--output", + "json", + ], + )?; + + std::thread::sleep(core::time::Duration::from_secs(1)); + + query_tx_hash( + chain_id, + command_path, + home_path, + rpc_listen_address, + &exec_output.stdout, + )?; + + Ok(()) +} diff --git a/tools/test-framework/src/chain/cli/wasm/mod.rs b/tools/test-framework/src/chain/cli/wasm/mod.rs new file mode 100644 index 0000000000..fec57bbb9f --- /dev/null +++ b/tools/test-framework/src/chain/cli/wasm/mod.rs @@ -0,0 +1,2 @@ +pub mod contract; +pub mod query; diff --git a/tools/test-framework/src/chain/cli/wasm/query.rs b/tools/test-framework/src/chain/cli/wasm/query.rs new file mode 100644 index 0000000000..fb2835c54b --- /dev/null +++ b/tools/test-framework/src/chain/cli/wasm/query.rs @@ -0,0 +1,81 @@ +use eyre::eyre; + +use crate::chain::exec::simple_exec; +use crate::error::{handle_generic_error, Error}; + +pub fn query_wasm_list_code( + 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", + "wasm", + "list-codes", + "--output", + "json", + ], + )?; + + let json_output: serde_json::Value = + serde_json::from_str(&exec_output.stdout).map_err(handle_generic_error)?; + + let code_id = json_output + .get("code_infos") + .and_then(|code_infos| code_infos.as_array()) + .and_then(|code_infos| code_infos.first()) + .and_then(|code_info| code_info.get("code_id")) + .and_then(|code_infos| code_infos.as_str()) + .ok_or_else(|| eyre!("Failed to retrieve wasm code ID"))?; + + Ok(code_id.to_string()) +} + +pub fn query_wasm_list_contracts_by_code( + chain_id: &str, + command_path: &str, + home_path: &str, + rpc_listen_address: &str, + code_id: &str, +) -> Result { + let exec_output = simple_exec( + chain_id, + command_path, + &[ + "--home", + home_path, + "--chain-id", + chain_id, + "--node", + rpc_listen_address, + "query", + "wasm", + "list-contract-by-code", + code_id, + "--output", + "json", + ], + )?; + + let json_output: serde_json::Value = + serde_json::from_str(&exec_output.stdout).map_err(handle_generic_error)?; + + let contrat = json_output + .get("contracts") + .and_then(|contracts| contracts.as_array()) + .and_then(|contracts| contracts.first()) + .and_then(|contract| contract.as_str()) + .ok_or_else(|| eyre!("Failed to retrieve wasm contract address"))?; + + Ok(contrat.to_string()) +} diff --git a/tools/test-framework/src/chain/config.rs b/tools/test-framework/src/chain/config.rs index 29fcc6b956..9d98f9702d 100644 --- a/tools/test-framework/src/chain/config.rs +++ b/tools/test-framework/src/chain/config.rs @@ -7,11 +7,7 @@ */ use core::time::Duration; - -use eyre::{ - eyre, - Report as Error, -}; +use eyre::{eyre, Report as Error}; use toml::Value; use tracing::debug; @@ -194,6 +190,51 @@ pub fn set_max_deposit_period(genesis: &mut serde_json::Value, period: &str) -> Ok(()) } +pub fn add_allow_message_interchainaccounts( + genesis: &mut serde_json::Value, + message: &str, +) -> Result<(), Error> { + let allow_messages = genesis + .get_mut("app_state") + .and_then(|app_state| app_state.get_mut("interchainaccounts")) + .and_then(|ica| ica.get_mut("host_genesis_state")) + .and_then(|state| state.get_mut("params")) + .and_then(|params| params.get_mut("allow_messages")) + .and_then(|allow_messages| allow_messages.as_array_mut()) + .ok_or_else(|| { + eyre!("failed to retrieve allow_messages as a vector, in the genesis file") + })?; + + // Only add `MsgSend` if the wildcard '*' is not specified + if allow_messages.iter().all(|v| v.as_str() != Some("*")) { + allow_messages.push(serde_json::Value::String(message.to_string())); + } + + Ok(()) +} + +pub fn add_allow_message_interchainquery( + genesis: &mut serde_json::Value, + message: &str, +) -> Result<(), Error> { + 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()) + .ok_or_else(|| { + eyre!("failed to retrieve allow_messages as a vector, in the genesis file") + })?; + + // Only add `MsgSend` if the wildcard '*' is not specified + if allow_messages.iter().all(|v| v.as_str() != Some("*")) { + allow_messages.push(serde_json::Value::String(message.to_string())); + } + + Ok(()) +} + pub fn set_min_deposit_amount( genesis: &mut serde_json::Value, min_deposit_amount: u64, @@ -363,11 +404,18 @@ 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"))?; + let block = match genesis.get_mut("consensus_params") { + Some(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"))?, + None => genesis + .get_mut("consensus") + .and_then(|consensus| consensus.get_mut("params")) + .and_then(|params| 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(), @@ -401,6 +449,60 @@ pub fn globalfee_minimum_gas_prices( Ok(()) } +pub fn set_retry_delay_period( + genesis: &mut serde_json::Value, + retry_delay_period: &str, +) -> Result<(), Error> { + let params = genesis + .get_mut("app_state") + .and_then(|app_state| app_state.get_mut("ccvconsumer")) + .and_then(|ccvconsumer| ccvconsumer.get_mut("params")) + .and_then(|params| params.as_object_mut()) + .ok_or_else(|| eyre!("failed to get ccvconsumer params in genesis file"))?; + + params.insert( + "retry_delay_period".to_owned(), + serde_json::Value::String(retry_delay_period.to_string()), + ); + + Ok(()) +} + +pub fn set_floor_gas_price( + genesis: &mut serde_json::Value, + amount: &str, + denom: &str, + nhash_per_usd_mil: &str, +) -> Result<(), Error> { + let params = genesis + .get_mut("app_state") + .and_then(|app_state| app_state.get_mut("msgfees")) + .and_then(|msgfees| msgfees.get_mut("params")) + .and_then(|params| params.as_object_mut()) + .ok_or_else(|| eyre!("failed to get `msgfees params` in genesis file"))?; + + params.insert( + "nhash_per_usd_mil".to_owned(), + serde_json::Value::String(nhash_per_usd_mil.to_string()), + ); + + let floor_gas_price = params + .get_mut("floor_gas_price") + .and_then(|floor_gas_price| floor_gas_price.as_object_mut()) + .ok_or_else(|| eyre!("failed to get `floor_gas_price` params in genesis file"))?; + + floor_gas_price.insert( + "amount".to_owned(), + serde_json::Value::String(amount.to_string()), + ); + floor_gas_price.insert( + "denom".to_owned(), + serde_json::Value::String(denom.to_string()), + ); + + 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 c5592917c6..85830caf5e 100644 --- a/tools/test-framework/src/chain/driver.rs +++ b/tools/test-framework/src/chain/driver.rs @@ -4,38 +4,24 @@ use alloc::sync::Arc; use core::time::Duration; - use eyre::eyre; -use ibc_relayer::{ - chain::cosmos::types::config::TxConfig, - config::compat_mode::CompatMode, -}; -use ibc_relayer_types::{ - applications::transfer::amount::Amount, - core::ics24_host::identifier::ChainId, -}; +use ibc_relayer::config::compat_mode::CompatMode; +use std::cmp::max; use tokio::runtime::Runtime; -use crate::{ - chain::{ - chain_type::ChainType, - cli::query::query_balance, - }, - error::Error, - ibc::{ - denom::Denom, - token::Token, - }, - relayer::tx::new_tx_config_for_test, - types::{ - env::{ - EnvWriter, - ExportEnv, - }, - wallet::WalletAddress, - }, - util::retry::assert_eventually_succeed, -}; +use ibc_relayer::chain::cosmos::types::config::TxConfig; +use ibc_relayer_types::applications::transfer::amount::Amount; +use ibc_relayer_types::core::ics24_host::identifier::ChainId; + +use crate::chain::chain_type::ChainType; +use crate::chain::cli::query::query_balance; +use crate::error::Error; +use crate::ibc::denom::Denom; +use crate::ibc::token::Token; +use crate::relayer::tx::new_tx_config_for_test; +use crate::types::env::{EnvWriter, ExportEnv}; +use crate::types::wallet::WalletAddress; +use crate::util::retry::assert_eventually_succeed; /** Number of times (seconds) to try and query a wallet to reach the @@ -142,6 +128,7 @@ impl ChainDriver { ) -> Result { let tx_config = new_tx_config_for_test( chain_id.clone(), + chain_type.clone(), format!("http://localhost:{rpc_port}"), format!("http://localhost:{grpc_port}"), chain_type.address_type(), @@ -246,4 +233,63 @@ impl ChainDriver { Ok(()) } + + /** + Assert that a wallet should eventually have escrowed the amount for ICS29 + fees of a given denomination. + Legacy ICS29 will escrow recv_fee + ack_fee + timeout_fee while more recent + versions will escrow max(recv_fee + ack_fee, timeout_fee). + */ + pub fn assert_eventual_escrowed_amount_ics29( + &self, + wallet: &WalletAddress, + token: &Token, + recv_fee: u128, + ack_fee: u128, + timeout_fee: u128, + ) -> Result<(), Error> { + assert_eventually_succeed( + &format!("wallet reach {wallet} amount {token}"), + WAIT_WALLET_AMOUNT_ATTEMPTS, + Duration::from_secs(1), + || { + let amount: Amount = self.query_balance(wallet, &token.denom)?; + + let legacy_escrow = token + .amount + .checked_sub(recv_fee + ack_fee + timeout_fee) + .ok_or_else(|| { + Error::generic(eyre!( + "error computing the following subtraction: {}-{}", + token.amount, + recv_fee + ack_fee + timeout_fee + )) + })?; + let escrow = token + .amount + .checked_sub(max(recv_fee + ack_fee, timeout_fee)) + .ok_or_else(|| { + Error::generic(eyre!( + "error computing the following subtraction: {}-{}", + token.amount, + max(recv_fee + ack_fee, timeout_fee) + )) + })?; + + // Assert either the legacy or current ICS29 amount has been escrowed + if amount == legacy_escrow || amount == escrow { + Ok(()) + } else { + Err(Error::generic(eyre!( + "current balance of account {} with amount {} does not match the target amount {}", + wallet, + amount, + token + ))) + } + }, + )?; + + Ok(()) + } } diff --git a/tools/test-framework/src/chain/exec.rs b/tools/test-framework/src/chain/exec.rs index 2e2d649276..c9b958de3f 100644 --- a/tools/test-framework/src/chain/exec.rs +++ b/tools/test-framework/src/chain/exec.rs @@ -1,19 +1,9 @@ -use std::{ - process::Command, - str, -}; - use eyre::eyre; -use tracing::{ - debug, - trace, -}; - -use crate::error::{ - handle_exec_error, - handle_generic_error, - Error, -}; +use std::process::Command; +use std::str; +use tracing::{debug, trace}; + +use crate::error::{handle_exec_error, handle_generic_error, Error}; pub struct ExecOutput { pub stdout: String, diff --git a/tools/test-framework/src/chain/ext/async_icq.rs b/tools/test-framework/src/chain/ext/async_icq.rs index cbbef12ba8..88dd7f7aa6 100644 --- a/tools/test-framework/src/chain/ext/async_icq.rs +++ b/tools/test-framework/src/chain/ext/async_icq.rs @@ -1,31 +1,51 @@ -use crate::{ - chain::{ - cli::async_icq::{ - async_icq, - update_oracle, - }, - driver::ChainDriver, - }, - error::Error, - prelude::*, - types::tagged::*, -}; +use crate::chain::cli::async_icq::{async_icq, update_oracle}; +use crate::chain::cli::wasm::contract::instantiate_wasm_contract; +use crate::chain::cli::wasm::query::{query_wasm_list_code, query_wasm_list_contracts_by_code}; +use crate::prelude::*; +use crate::types::tagged::*; pub trait AsyncIcqMethodsExt { - fn update_oracle(&self, relayer: &str, account: &str) -> Result<(), Error>; + fn update_oracle(&self, relayer: &str, fees: &str, init_args: &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> { + fn update_oracle(&self, relayer: &str, fees: &str, init_args: &str) -> Result<(), Error> { let driver = *self.value(); + + let wasm_code = query_wasm_list_code( + driver.chain_id.as_str(), + &driver.command_path, + &driver.home_path, + &driver.rpc_listen_address(), + )?; + + instantiate_wasm_contract( + driver.chain_id.as_str(), + &driver.command_path, + &driver.home_path, + &driver.rpc_listen_address(), + relayer, + fees, + &wasm_code, + init_args, + )?; + + let address = query_wasm_list_contracts_by_code( + driver.chain_id.as_str(), + &driver.command_path, + &driver.home_path, + &driver.rpc_listen_address(), + &wasm_code, + )?; + update_oracle( driver.chain_id.as_str(), &driver.command_path, &driver.home_path, &driver.rpc_listen_address(), - account, + &address, relayer, ) } diff --git a/tools/test-framework/src/chain/ext/authz.rs b/tools/test-framework/src/chain/ext/authz.rs new file mode 100644 index 0000000000..e6a8ad09a7 --- /dev/null +++ b/tools/test-framework/src/chain/ext/authz.rs @@ -0,0 +1,124 @@ +use crate::chain::cli::authz::{authz_grant, exec_grant, query_authz_grant}; +use crate::chain::cli::transfer::generate_transfer_from_chain_tx; +use crate::error::Error; +use crate::prelude::*; +use crate::types::tagged::MonoTagged; + +use super::bootstrap::ChainBootstrapMethodsExt; + +const WAIT_GRANT_ATTEMPTS: u16 = 5; + +pub trait AuthzMethodsExt { + fn authz_grant( + &self, + granter: &str, + grantee: &str, + msg_type: &str, + fees: &str, + ) -> Result<(), Error>; + + fn assert_eventual_grant( + &self, + granter: &str, + grantee: &str, + msg_type: &str, + ) -> Result<(), Error>; + + fn exec_ibc_transfer_grant( + &self, + granter: &str, + grantee: &str, + port: &PortId, + channel: &ChannelId, + recipient: &MonoTagged, + token: &TaggedTokenRef, + fees: &str, + ) -> Result<(), Error>; +} + +impl<'a, Chain: Send> AuthzMethodsExt for MonoTagged { + fn authz_grant( + &self, + granter: &str, + grantee: &str, + msg_type: &str, + fees: &str, + ) -> Result<(), Error> { + authz_grant( + self.value().chain_id.as_str(), + &self.value().command_path, + &self.value().home_path, + &self.value().rpc_listen_address(), + granter, + grantee, + msg_type, + fees, + ) + } + + fn assert_eventual_grant( + &self, + granter: &str, + grantee: &str, + msg_type: &str, + ) -> Result<(), Error> { + assert_eventually_succeed( + &format!("successful grant from granter {granter} to grantee {grantee}"), + WAIT_GRANT_ATTEMPTS, + Duration::from_secs(1), + || { + query_authz_grant( + self.value().chain_id.as_str(), + &self.value().command_path, + &self.value().home_path, + &self.value().rpc_listen_address(), + granter, + grantee, + msg_type, + ) + }, + )?; + + Ok(()) + } + + fn exec_ibc_transfer_grant( + &self, + granter: &str, + grantee: &str, + port: &PortId, + channel: &ChannelId, + recipient: &MonoTagged, + token: &TaggedTokenRef, + fees: &str, + ) -> Result<(), Error> { + let ibc_transfer_tx = generate_transfer_from_chain_tx( + self.value().chain_id.as_str(), + &self.value().command_path, + &self.value().home_path, + &self.value().rpc_listen_address(), + granter, + port.as_ref(), + channel.as_ref(), + recipient.value().as_str(), + &token.value().to_string(), + )?; + + let ibc_transfer_tx_filename = "ibc-transfer.json"; + + self.value() + .write_file(ibc_transfer_tx_filename, &ibc_transfer_tx)?; + + exec_grant( + self.value().chain_id.as_str(), + &self.value().command_path, + &self.value().home_path, + &self.value().rpc_listen_address(), + &format!("{}/{ibc_transfer_tx_filename}", self.value().home_path), + grantee, + fees, + )?; + + Ok(()) + } +} diff --git a/tools/test-framework/src/chain/ext/bootstrap.rs b/tools/test-framework/src/chain/ext/bootstrap.rs index 51be41f773..4fef50083d 100644 --- a/tools/test-framework/src/chain/ext/bootstrap.rs +++ b/tools/test-framework/src/chain/ext/bootstrap.rs @@ -1,59 +1,31 @@ use core::str::FromStr; -use std::{ - fs, - path::PathBuf, - str, - time::Duration, -}; - use eyre::eyre; use hdpath::StandardHDPath; -use ibc_relayer::keyring::{ - Secp256k1KeyPair, - SigningKeyPair, -}; use serde_json as json; -use toml; +use std::fs; +use std::path::PathBuf; +use std::str; +use std::time::Duration; use tracing::debug; -use crate::{ - chain::{ - cli::{ - bootstrap::{ - add_genesis_account, - add_genesis_validator, - add_wallet, - collect_gen_txs, - initialize, - start_chain, - }, - provider::{ - copy_validator_key_pair, - query_consumer_genesis, - query_gov_proposal, - replace_genesis_state, - submit_consumer_chain_proposal, - }, - }, - driver::ChainDriver, - exec::simple_exec, - }, - error::{ - handle_generic_error, - Error, - }, - ibc::token::Token, - prelude::assert_eventually_succeed, - types::{ - process::ChildProcess, - wallet::{ - Wallet, - WalletAddress, - WalletId, - }, - }, - util::proposal_status::ProposalStatus, +use ibc_relayer::keyring::{Secp256k1KeyPair, SigningKeyPair}; + +use crate::chain::cli::bootstrap::{ + add_genesis_account, add_genesis_validator, add_wallet, collect_gen_txs, initialize, + start_chain, +}; +use crate::chain::cli::provider::{ + 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; +use crate::error::{handle_generic_error, Error}; +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 { /** @@ -134,6 +106,7 @@ pub trait ChainBootstrapMethodsExt { fn submit_consumer_chain_proposal( &self, consumer_chain_id: &str, + fees: &str, spawn_time: &str, ) -> Result<(), Error>; @@ -258,6 +231,9 @@ impl ChainBootstrapMethodsExt for ChainDriver { fn add_genesis_account(&self, wallet: &WalletAddress, amounts: &[&Token]) -> Result<(), Error> { let amounts_str = amounts.iter().map(|t| t.to_string()).collect::>(); + let extra_args = self + .chain_type + .extra_add_genesis_account_args(&self.chain_id); add_genesis_account( self.chain_id.as_str(), @@ -265,6 +241,7 @@ impl ChainBootstrapMethodsExt for ChainDriver { &self.home_path, &wallet.0, &amounts_str, + &extra_args.iter().map(|s| s.as_ref()).collect::>(), ) } @@ -300,6 +277,7 @@ impl ChainBootstrapMethodsExt for ChainDriver { fn submit_consumer_chain_proposal( &self, consumer_chain_id: &str, + fees: &str, _spawn_time: &str, ) -> Result<(), Error> { let res = simple_exec( @@ -317,7 +295,7 @@ impl ChainBootstrapMethodsExt for ChainDriver { let raw_proposal = r#" { "title": "Create consumer chain", - "description": "First consumer chain", + "summary": "First consumer chain", "chain_id": "{consumer_chain_id}", "initial_height": { "revision_number": 1, @@ -333,7 +311,12 @@ impl ChainBootstrapMethodsExt for ChainDriver { "transfer_timeout_period": 100000000000, "ccv_timeout_period": 100000000000, "unbonding_period": 100000000000, - "deposit": "10000001stake" + "deposit": "10000001stake", + "top_N": 95, + "validators_power_cap": 0, + "validator_set_cap": 0, + "allowlist": [], + "denylist": [] }"#; let proposal = raw_proposal.replace("{consumer_chain_id}", consumer_chain_id); @@ -346,6 +329,7 @@ impl ChainBootstrapMethodsExt for ChainDriver { &self.command_path, &self.home_path, &self.rpc_listen_address(), + fees, ) } @@ -361,7 +345,7 @@ impl ChainBootstrapMethodsExt for ChainDriver { assert_eventually_succeed( &format!("proposal `{}` status: {}", proposal_id, status.as_str()), 10, - Duration::from_secs(2), + Duration::from_secs(3), || match query_gov_proposal( chain_id, command_path, diff --git a/tools/test-framework/src/chain/ext/crosschainquery.rs b/tools/test-framework/src/chain/ext/crosschainquery.rs index eea4426bee..dbdbaa9500 100644 --- a/tools/test-framework/src/chain/ext/crosschainquery.rs +++ b/tools/test-framework/src/chain/ext/crosschainquery.rs @@ -1,18 +1,11 @@ -use std::time::Duration; - use eyre::eyre; use serde_json as json; +use std::time::Duration; -use crate::{ - chain::cli::query::query_cross_chain_query, - error::Error, - prelude::{ - assert_eventually_succeed, - handle_generic_error, - ChainDriver, - }, - types::tagged::MonoTagged, -}; +use crate::chain::cli::query::query_cross_chain_query; +use crate::error::Error; +use crate::prelude::{assert_eventually_succeed, handle_generic_error, ChainDriver}; +use crate::types::tagged::MonoTagged; /** Number of times (seconds) to try and query the list of cross chain @@ -21,7 +14,7 @@ use crate::{ If you encounter retry error, verify the value of `stride_epoch`in the `stride_epoch` configuration in Stride's `genesis.toml` file. */ -const WAIT_CROSS_CHAIN_QUERY_ATTEMPTS: u16 = 60; +const WAIT_CROSS_CHAIN_QUERY_ATTEMPTS: u16 = 30; pub trait CrossChainQueryMethodsExt { fn assert_pending_cross_chain_query(&self) -> Result<(), Error>; @@ -78,15 +71,14 @@ impl<'a, Chain: Send> CrossChainQueryMethodsExt for MonoTagged(&output) + // Verify that there are no more pending Cross Chain Queries. + if !json::from_str::(&output) .map_err(handle_generic_error)? .get("pending_queries") .ok_or_else(|| eyre!("no pending cross chain queries"))? .as_array() .ok_or_else(|| eyre!("pending cross chain queries is not an array"))? - .first() - .is_some() + .is_empty() { return Err(Error::generic(eyre!( "Pending query has not been processed" diff --git a/tools/test-framework/src/chain/ext/fee.rs b/tools/test-framework/src/chain/ext/fee.rs index 3380bcd32c..b3783304fa 100644 --- a/tools/test-framework/src/chain/ext/fee.rs +++ b/tools/test-framework/src/chain/ext/fee.rs @@ -1,38 +1,19 @@ use core::time::Duration; - use ibc_relayer::event::IbcEventWithHeight; -use ibc_relayer_types::{ - applications::ics29_fee::packet_fee::IdentifiedPacketFees, - core::ics04_channel::packet::Sequence, -}; +use ibc_relayer_types::applications::ics29_fee::packet_fee::IdentifiedPacketFees; +use ibc_relayer_types::core::ics04_channel::packet::Sequence; -use crate::{ - chain::{ - driver::ChainDriver, - tagged::TaggedChainDriverExt, - }, - error::Error, - ibc::token::TaggedTokenRef, - relayer::fee::{ - ibc_token_transfer_with_fee, - pay_packet_fee, - query_counterparty_payee, - query_incentivized_packets, - register_counterparty_payee, - register_payee, - }, - types::{ - id::{ - TaggedChannelIdRef, - TaggedPortIdRef, - }, - tagged::*, - wallet::{ - Wallet, - WalletAddress, - }, - }, +use crate::chain::driver::ChainDriver; +use crate::chain::tagged::TaggedChainDriverExt; +use crate::error::Error; +use crate::ibc::token::TaggedTokenRef; +use crate::relayer::fee::{ + ibc_token_transfer_with_fee, pay_packet_fee, query_counterparty_payee, + query_incentivized_packets, register_counterparty_payee, register_payee, }; +use crate::types::id::{TaggedChannelIdRef, TaggedPortIdRef}; +use crate::types::tagged::*; +use crate::types::wallet::{Wallet, WalletAddress}; pub trait ChainFeeMethodsExt { fn ibc_token_transfer_with_fee( diff --git a/tools/test-framework/src/chain/ext/fee_grant.rs b/tools/test-framework/src/chain/ext/fee_grant.rs index 907f0edd11..ca8dcb156e 100644 --- a/tools/test-framework/src/chain/ext/fee_grant.rs +++ b/tools/test-framework/src/chain/ext/fee_grant.rs @@ -1,12 +1,7 @@ -use crate::{ - chain::cli::fee_grant::feegrant_grant, - error::Error, - prelude::{ - ChainDriver, - TaggedTokenRef, - }, - types::tagged::MonoTagged, -}; +use crate::chain::cli::fee_grant::feegrant_grant; +use crate::error::Error; +use crate::prelude::{ChainDriver, TaggedTokenRef}; +use crate::types::tagged::MonoTagged; pub trait FeeGrantMethodsExt { fn feegrant_grant( &self, diff --git a/tools/test-framework/src/chain/ext/forward.rs b/tools/test-framework/src/chain/ext/forward.rs index acaafc2d80..f56a31b72e 100644 --- a/tools/test-framework/src/chain/ext/forward.rs +++ b/tools/test-framework/src/chain/ext/forward.rs @@ -1,16 +1,9 @@ -use ibc_relayer_types::core::ics24_host::identifier::{ - ChannelId, - PortId, -}; +use ibc_relayer_types::core::ics24_host::identifier::{ChannelId, PortId}; -use crate::prelude::{ - DualTagged, - MonoTagged, - WalletAddress, -}; +use crate::prelude::{DualTagged, MonoTagged, WalletAddress}; /// Build the recipient address as following: -/// {intermediate_refund_address}|{foward_port}/{forward_channel}:{final_destination_address} +/// {intermediate_refund_address}|{forward_port}/{forward_channel}:{final_destination_address} /// See pub fn build_forward_address<'a, ChainB, ChainC>( intermediate_destination_address: MonoTagged, diff --git a/tools/test-framework/src/chain/ext/ica.rs b/tools/test-framework/src/chain/ext/ica.rs index 73edc5328b..b97b3ad2d8 100644 --- a/tools/test-framework/src/chain/ext/ica.rs +++ b/tools/test-framework/src/chain/ext/ica.rs @@ -1,29 +1,17 @@ -use ibc_relayer::chain::{ - handle::ChainHandle, - tracking::TrackedMsgs, -}; -use ibc_relayer_types::{ - applications::ics27_ica::msgs::register::MsgRegisterInterchainAccount, - core::ics04_channel::version::Version, - events::IbcEvent, - tx_msg::Msg, -}; +use ibc_relayer::upgrade_chain::requires_legacy_upgrade_proposal; +use serde_json::json; -use crate::{ - chain::{ - cli::ica::{ - query_interchain_account, - register_interchain_account_cli, - }, - driver::ChainDriver, - }, - error::Error, - prelude::*, - types::{ - tagged::*, - wallet::WalletAddress, - }, +use ibc_relayer::chain::tracking::TrackedMsgs; +use ibc_relayer_types::applications::ics27_ica::msgs::register::{ + LegacyMsgRegisterInterchainAccount, MsgRegisterInterchainAccount, }; +use ibc_relayer_types::core::ics04_channel::version::Version; +use ibc_relayer_types::events::IbcEvent; +use ibc_relayer_types::tx_msg::Msg; + +use crate::chain::cli::ica::{query_interchain_account, register_interchain_account_cli}; +use crate::prelude::*; +use crate::types::tagged::*; pub trait InterchainAccountMethodsExt { fn register_interchain_account_cli( @@ -76,7 +64,7 @@ impl<'a, Chain: Send> InterchainAccountMethodsExt for MonoTagged( +pub fn register_unordered_interchain_account( chain: &MonoTagged, handle: &Chain, connection: &ConnectedConnection, @@ -92,14 +80,97 @@ pub fn register_interchain_account( + chain: &MonoTagged, + handle: &Chain, + connection: &ConnectedConnection, +) -> Result< + ( + MonoTagged, + TaggedChannelId, + TaggedPortId, + ), + Error, +> { + let wallet = chain.wallets().relayer().cloned(); + + let owner = handle.get_signer()?; + + let version_obj = json!({ + "version": "ics27-1", + "encoding": "proto3", + "tx_type": "sdk_multi_msg", + "controller_connection_id": connection.connection_id_a.0, + "host_connection_id": connection.connection_id_b.0 + }); + + let msg_any = if requires_legacy_upgrade_proposal(handle.clone()) { + let msg = LegacyMsgRegisterInterchainAccount { + owner, + connection_id: connection.connection_id_a.0.clone(), + version: Version::new(version_obj.to_string()), + }; + + msg.to_any() + } else { + let msg = MsgRegisterInterchainAccount { + owner, + connection_id: connection.connection_id_a.0.clone(), + version: Version::new(version_obj.to_string()), + ordering: Ordering::Ordered, + }; + msg.to_any() + }; let tm = TrackedMsgs::new_static(vec![msg_any], "RegisterInterchainAccount"); @@ -109,7 +180,10 @@ pub fn register_interchain_account Result; - fn vote_proposal(&self, fees: &str) -> Result<(), Error>; + fn vote_proposal(&self, fees: &str, proposal_id: &str) -> Result<(), Error>; + + fn deposit_proposal( + &self, + amount: &str, + proposal_id: &str, + fees: &str, + gas: &str, + ) -> Result<(), Error>; + + fn initialise_channel_upgrade( + &self, + port_id: &str, + channel_id: &str, + ordering: &str, + connection_hops: &str, + version: &str, + signer: &str, + proposal_id: &str, + ) -> Result<(), Error>; + + fn update_channel_params( + &self, + timestamp: u64, + signer: &str, + proposal_id: &str, + ) -> Result<(), Error>; } impl<'a, Chain: Send> ChainProposalMethodsExt for MonoTagged { @@ -47,14 +64,134 @@ impl<'a, Chain: Send> ChainProposalMethodsExt for MonoTagged Result<(), Error> { + fn vote_proposal(&self, fees: &str, proposal_id: &str) -> Result<(), Error> { vote_proposal( self.value().chain_id.as_str(), &self.value().command_path, &self.value().home_path, &self.value().rpc_listen_address(), fees, + proposal_id, + )?; + Ok(()) + } + + fn deposit_proposal( + &self, + amount: &str, + proposal_id: &str, + fees: &str, + gas: &str, + ) -> Result<(), Error> { + deposit_proposal(self.value(), amount, proposal_id, fees, gas)?; + Ok(()) + } + + fn initialise_channel_upgrade( + &self, + port_id: &str, + channel_id: &str, + ordering: &str, + connection_hops: &str, + version: &str, + signer: &str, + proposal_id: &str, + ) -> Result<(), Error> { + let gov_address = self.query_auth_module("gov")?; + let channel_upgrade_proposal = create_channel_upgrade_proposal( + self.value(), + port_id, + channel_id, + ordering, + connection_hops, + version, + &gov_address, + )?; + submit_gov_proposal( + self.value().chain_id.as_str(), + &self.value().command_path, + &self.value().home_path, + &self.value().rpc_listen_address(), + signer, + &channel_upgrade_proposal, + )?; + + self.value().assert_proposal_status( + self.value().chain_id.as_str(), + &self.value().command_path, + &self.value().home_path, + &self.value().rpc_listen_address(), + ProposalStatus::VotingPeriod, + proposal_id, + )?; + + vote_proposal( + self.value().chain_id.as_str(), + &self.value().command_path, + &self.value().home_path, + &self.value().rpc_listen_address(), + "1200stake", + proposal_id, + )?; + + self.value().assert_proposal_status( + self.value().chain_id.as_str(), + &self.value().command_path, + &self.value().home_path, + &self.value().rpc_listen_address(), + ProposalStatus::Passed, + proposal_id, + )?; + + Ok(()) + } + + // The timestamp is in nanoseconds + fn update_channel_params( + &self, + timestamp: u64, + signer: &str, + proposal_id: &str, + ) -> Result<(), Error> { + let gov_address = self.query_auth_module("gov")?; + let channel_update_params_proposal = + create_channel_update_params_proposal(self.value(), timestamp, &gov_address)?; + submit_gov_proposal( + self.value().chain_id.as_str(), + &self.value().command_path, + &self.value().home_path, + &self.value().rpc_listen_address(), + signer, + &channel_update_params_proposal, + )?; + + self.value().assert_proposal_status( + self.value().chain_id.as_str(), + &self.value().command_path, + &self.value().home_path, + &self.value().rpc_listen_address(), + ProposalStatus::VotingPeriod, + proposal_id, + )?; + + vote_proposal( + self.value().chain_id.as_str(), + &self.value().command_path, + &self.value().home_path, + &self.value().rpc_listen_address(), + "1200stake", + proposal_id, + )?; + + self.value().assert_proposal_status( + self.value().chain_id.as_str(), + &self.value().command_path, + &self.value().home_path, + &self.value().rpc_listen_address(), + ProposalStatus::Passed, + proposal_id, )?; + Ok(()) } } @@ -83,10 +220,10 @@ pub async fn query_upgrade_proposal_height( .map(|r| r.into_inner()) .map_err(|e| RelayerError::grpc_status(e, "query_upgrade_proposal_height".to_owned()))?; - // Querying for a balance might fail, i.e. if the account doesn't actually exist + // Querying for proposal might not exist if the proposal id is incorrect let proposal = response .proposal - .ok_or_else(|| RelayerError::empty_query_account(proposal_id.to_string()))?; + .ok_or_else(|| RelayerError::empty_proposal(proposal_id.to_string()))?; let proposal_content = proposal .content @@ -122,3 +259,77 @@ pub async fn query_upgrade_proposal_height( Ok(height) } + +fn create_channel_upgrade_proposal( + chain_driver: &ChainDriver, + port_id: &str, + channel_id: &str, + ordering: &str, + connection_hops: &str, + version: &str, + gov_address: &str, +) -> Result { + let raw_proposal = r#" + { + "messages": [ + { + "@type": "/ibc.core.channel.v1.MsgChannelUpgradeInit", + "port_id": "{port_id}", + "channel_id": "{channel_id}", + "fields": { + "ordering": "{ordering}", + "connection_hops": ["{connection_hops}"], + "version": {version} + }, + "signer":"{signer}" + } + ], + "deposit": "10000001stake", + "title": "Channel upgrade", + "summary": "Upgrade channel version", + "expedited": false + }"#; + + let proposal = raw_proposal.replace("{port_id}", port_id); + let proposal = proposal.replace("{channel_id}", channel_id); + let proposal = proposal.replace("{ordering}", ordering); + let proposal = proposal.replace("{connection_hops}", connection_hops); + let proposal = proposal.replace("{version}", version); + let proposal = proposal.replace("{signer}", gov_address); + + chain_driver.write_file("channel_upgrade_proposal.json", &proposal)?; + Ok("channel_upgrade_proposal.json".to_owned()) +} + +fn create_channel_update_params_proposal( + chain_driver: &ChainDriver, + timestamp: u64, + gov_address: &str, +) -> Result { + let raw_proposal = r#" + { + "messages": [ + { + "@type": "/ibc.core.channel.v1.MsgUpdateParams", + "params": { + "upgrade_timeout": { + "timestamp": {timestamp} + } + }, + "authority":"{signer}" + } + ], + "deposit": "10000001stake", + "title": "Channel update params", + "summary": "Update channel params", + "expedited": false + }"#; + + let proposal = raw_proposal.replace("{timestamp}", ×tamp.to_string()); + let proposal = proposal.replace("{signer}", gov_address); + + let output_file = "channel_update_params_proposal.json"; + + chain_driver.write_file(output_file, &proposal)?; + Ok(output_file.to_owned()) +} diff --git a/tools/test-framework/src/chain/ext/transfer.rs b/tools/test-framework/src/chain/ext/transfer.rs index 2a3d1a975d..e1c50cd546 100644 --- a/tools/test-framework/src/chain/ext/transfer.rs +++ b/tools/test-framework/src/chain/ext/transfer.rs @@ -1,41 +1,18 @@ use core::time::Duration; -use ibc_relayer_types::core::{ - ics02_client::height::Height, - ics04_channel::packet::Packet, - ics24_host::identifier::{ - ChannelId, - PortId, - }, -}; - -use crate::{ - chain::{ - cli::transfer::{ - local_transfer_token, - transfer_from_chain, - }, - driver::ChainDriver, - tagged::TaggedChainDriverExt, - }, - error::Error, - ibc::token::TaggedTokenRef, - relayer::transfer::{ - batched_ibc_token_transfer, - ibc_token_transfer, - }, - types::{ - id::{ - TaggedChannelIdRef, - TaggedPortIdRef, - }, - tagged::*, - wallet::{ - Wallet, - WalletAddress, - }, - }, -}; +use ibc_relayer_types::core::ics02_client::height::Height; +use ibc_relayer_types::core::ics04_channel::packet::Packet; +use ibc_relayer_types::core::ics24_host::identifier::{ChannelId, PortId}; + +use crate::chain::cli::transfer::{local_transfer_token, transfer_from_chain}; +use crate::chain::driver::ChainDriver; +use crate::chain::tagged::TaggedChainDriverExt; +use crate::error::Error; +use crate::ibc::token::TaggedTokenRef; +use crate::relayer::transfer::{batched_ibc_token_transfer, ibc_token_transfer}; +use crate::types::id::{TaggedChannelIdRef, TaggedPortIdRef}; +use crate::types::tagged::*; +use crate::types::wallet::{Wallet, WalletAddress}; pub trait ChainTransferMethodsExt { /** @@ -94,6 +71,7 @@ pub trait ChainTransferMethodsExt { sender: &MonoTagged, recipient: &MonoTagged, token: &TaggedTokenRef, + fees: &TaggedTokenRef, ) -> Result<(), Error>; fn transfer_from_chain( @@ -184,6 +162,7 @@ impl<'a, Chain: Send> ChainTransferMethodsExt for MonoTagged, recipient: &MonoTagged, token: &TaggedTokenRef, + fees: &TaggedTokenRef, ) -> Result<(), Error> { let driver = *self.value(); local_transfer_token( @@ -194,6 +173,7 @@ impl<'a, Chain: Send> ChainTransferMethodsExt for MonoTagged Result; diff --git a/tools/test-framework/src/chain/ext/wasm_client.rs b/tools/test-framework/src/chain/ext/wasm_client.rs new file mode 100644 index 0000000000..cfcb657dd0 --- /dev/null +++ b/tools/test-framework/src/chain/ext/wasm_client.rs @@ -0,0 +1,85 @@ +use std::path::Path; + +use crate::chain::cli::wasm::contract::{store_wasm_client_code, store_wasm_contract}; +use crate::chain::driver::ChainDriver; +use crate::error::Error; +use crate::types::tagged::*; + +pub trait StoreWasmClientCodeMethodsExt { + fn store_wasm_client_code( + &self, + wasm_path: &Path, + title: &str, + summary: &str, + signer: &str, + ) -> Result; + + fn store_wasm_contract( + &self, + title: &str, + summary: &str, + wasm_file: &str, + authority: &str, + from: &str, + deposit: &str, + fees: &str, + gas: &str, + ) -> Result; +} + +impl<'a, Chain: Send> StoreWasmClientCodeMethodsExt for MonoTagged { + fn store_wasm_client_code( + &self, + wasm_path: &Path, + title: &str, + summary: &str, + signer: &str, + ) -> Result { + self.value() + .store_wasm_client_code(wasm_path, title, summary, signer) + } + + fn store_wasm_contract( + &self, + title: &str, + summary: &str, + wasm_file: &str, + authority: &str, + from: &str, + deposit: &str, + fees: &str, + gas: &str, + ) -> Result { + self.value().store_wasm_contract( + title, summary, wasm_file, authority, from, deposit, fees, gas, + ) + } +} + +impl StoreWasmClientCodeMethodsExt for ChainDriver { + fn store_wasm_client_code( + &self, + wasm_path: &Path, + title: &str, + summary: &str, + signer: &str, + ) -> Result { + store_wasm_client_code(self, wasm_path, title, summary, signer) + } + + fn store_wasm_contract( + &self, + title: &str, + summary: &str, + wasm_file: &str, + authority: &str, + from: &str, + deposit: &str, + fees: &str, + gas: &str, + ) -> Result { + store_wasm_contract( + self, title, summary, wasm_file, authority, from, deposit, fees, gas, + ) + } +} diff --git a/tools/test-framework/src/chain/tagged.rs b/tools/test-framework/src/chain/tagged.rs index f45d2efa93..8a17e8df55 100644 --- a/tools/test-framework/src/chain/tagged.rs +++ b/tools/test-framework/src/chain/tagged.rs @@ -3,49 +3,22 @@ */ use ibc_proto::google::protobuf::Any; -use ibc_relayer::{ - chain::cosmos::{ - tx::simple_send_tx, - types::config::TxConfig, - }, - event::IbcEventWithHeight, - util::compat_mode::compat_mode_from_version, -}; +use ibc_relayer::chain::cosmos::tx::simple_send_tx; +use ibc_relayer::chain::cosmos::types::config::TxConfig; +use ibc_relayer::event::IbcEventWithHeight; +use ibc_relayer::util::compat_mode::compat_mode_from_version; use serde_json as json; -use tendermint_rpc::client::{ - Client, - HttpClient, -}; - -use crate::{ - chain::{ - cli::query::{ - query_auth_module, - query_recipient_transactions, - }, - driver::ChainDriver, - }, - error::{ - handle_generic_error, - Error, - }, - ibc::{ - denom::Denom, - token::{ - TaggedDenomExt, - TaggedToken, - TaggedTokenRef, - }, - }, - types::{ - id::TaggedChainIdRef, - tagged::*, - wallet::{ - Wallet, - WalletAddress, - }, - }, -}; +use tendermint_rpc::client::{Client, HttpClient}; + +use crate::chain::cli::query::query_auth_module; +use crate::chain::cli::query::query_recipient_transactions; +use crate::chain::driver::ChainDriver; +use crate::error::{handle_generic_error, Error}; +use crate::ibc::denom::Denom; +use crate::ibc::token::{TaggedDenomExt, TaggedToken, TaggedTokenRef}; +use crate::types::id::TaggedChainIdRef; +use crate::types::tagged::*; +use crate::types::wallet::{Wallet, WalletAddress}; /** A [`ChainDriver`] may be tagged with a `Chain` tag in the form @@ -98,6 +71,23 @@ pub trait TaggedChainDriverExt { token: &TaggedTokenRef, ) -> Result<(), Error>; + /** + Tagged version of [`ChainDriver::assert_eventual_escrowed_amount_ics29`]. + + Assert that a wallet should eventually have escrowed the amount for ICS29 + fees of a given denomination. + Legacy ICS29 will escrow recv_fee + ack_fee + timeout_fee while more recent + versions will escrow max(recv_fee + ack_fee, timeout_fee). + */ + fn assert_eventual_escrowed_amount_ics29( + &self, + user: &MonoTagged, + token: &TaggedTokenRef, + recv_fee: u128, + ack_fee: u128, + timeout_fee: u128, + ) -> Result<(), Error>; + /** Tagged version of [`query_recipient_transactions`]. @@ -178,6 +168,23 @@ impl<'a, Chain: Send> TaggedChainDriverExt for MonoTagged, + token: &TaggedTokenRef, + recv_fee: u128, + ack_fee: u128, + timeout_fee: u128, + ) -> Result<(), Error> { + self.value().assert_eventual_escrowed_amount_ics29( + user.value(), + token.value(), + recv_fee, + ack_fee, + timeout_fee, + ) + } + fn query_recipient_transactions( &self, recipient_address: &MonoTagged, diff --git a/tools/test-framework/src/chain/version.rs b/tools/test-framework/src/chain/version.rs index 96438b5f70..db27cd0948 100644 --- a/tools/test-framework/src/chain/version.rs +++ b/tools/test-framework/src/chain/version.rs @@ -1,13 +1,8 @@ use semver::Version; use tracing::debug; -use crate::{ - chain::exec::simple_exec, - error::{ - handle_generic_error, - Error, - }, -}; +use crate::chain::exec::simple_exec; +use crate::error::{handle_generic_error, Error}; pub fn get_chain_command_version(command: &str) -> Result, Error> { let output = simple_exec("version-command", command, &["version"])?; diff --git a/tools/test-framework/src/docs/walkthroughs/memo.rs b/tools/test-framework/src/docs/walkthroughs/memo.rs index c13a667df1..7c0887a76c 100644 --- a/tools/test-framework/src/docs/walkthroughs/memo.rs +++ b/tools/test-framework/src/docs/walkthroughs/memo.rs @@ -11,10 +11,12 @@ //! ```no_run //! # use serde_json as json; //! # use ibc_relayer::config::{types::Memo, Config}; +//! # use ibc_relayer::config::ChainConfig; //! # use ibc_test_framework::ibc::denom::derive_ibc_denom; //! # use ibc_test_framework::prelude::*; //! # use ibc_test_framework::util::random::{random_string, random_u128_range}; //! +//! //! #[test] //! fn test_memo() -> Result<(), Error> { //! let memo = Memo::new(random_string()).unwrap(); @@ -29,7 +31,11 @@ //! impl TestOverrides for MemoTest { //! fn modify_relayer_config(&self, config: &mut Config) { //! for mut 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/test-framework/src/error.rs b/tools/test-framework/src/error.rs index 270ef44506..796660e731 100644 --- a/tools/test-framework/src/error.rs +++ b/tools/test-framework/src/error.rs @@ -1,29 +1,18 @@ //! Error type used for the tests. -use core::convert::{ - From, - Into, -}; -use std::io::{ - Error as IoError, - ErrorKind as IoErrorKind, -}; +use std::io::{Error as IoError, ErrorKind as IoErrorKind}; use eyre::Report; -use flex_error::{ - define_error, - TraceError, -}; -use ibc_relayer::{ - channel::error::ChannelError, - connection::ConnectionError, - error::Error as RelayerError, - foreign_client::ForeignClientError, - link::error::LinkError, - supervisor::error::Error as SupervisorError, - transfer::TransferError, - upgrade_chain::UpgradeChainError, -}; +use flex_error::{define_error, TraceError}; + +use ibc_relayer::channel::error::ChannelError; +use ibc_relayer::connection::ConnectionError; +use ibc_relayer::error::Error as RelayerError; +use ibc_relayer::foreign_client::ForeignClientError; +use ibc_relayer::link::error::LinkError; +use ibc_relayer::supervisor::error::Error as SupervisorError; +use ibc_relayer::transfer::TransferError; +use ibc_relayer::upgrade_chain::UpgradeChainError; define_error! { Error { diff --git a/tools/test-framework/src/framework/base.rs b/tools/test-framework/src/framework/base.rs index f0137e7f3e..0ba59ea9fb 100644 --- a/tools/test-framework/src/framework/base.rs +++ b/tools/test-framework/src/framework/base.rs @@ -4,16 +4,13 @@ */ use alloc::sync::Arc; - use tokio::runtime::Runtime; use tracing::info; -use crate::{ - bootstrap::init::init_test, - chain::builder::ChainBuilder, - error::Error, - types::config::TestConfig, -}; +use crate::bootstrap::init::init_test; +use crate::chain::builder::ChainBuilder; +use crate::error::Error; +use crate::types::config::TestConfig; /** Runs a primitive test case implementing [`PrimitiveTest`]. diff --git a/tools/test-framework/src/framework/binary/chain.rs b/tools/test-framework/src/framework/binary/chain.rs index 980fa726e9..47eed73001 100644 --- a/tools/test-framework/src/framework/binary/chain.rs +++ b/tools/test-framework/src/framework/binary/chain.rs @@ -3,51 +3,27 @@ together with the relayer setup with chain handles and foreign clients. */ -use ibc_relayer::{ - chain::handle::ChainHandle, - config::Config, - foreign_client::CreateOptions as ClientOptions, -}; +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::config::Config; +use ibc_relayer::foreign_client::CreateOptions as ClientOptions; use tracing::info; -use crate::{ - bootstrap::binary::chain::{ - bootstrap_chains_with_full_nodes, - BootstrapClientOptions, - }, - error::Error, - framework::{ - base::{ - HasOverrides, - TestConfigOverride, - }, - binary::{ - ics::InterchainSecurityChainTest, - node::{ - run_binary_node_test, - run_single_node_test, - BinaryNodeTest, - NodeConfigOverride, - NodeGenesisOverride, - }, - }, - supervisor::{ - RunWithSupervisor, - SupervisorOverride, - }, - }, - relayer::driver::RelayerDriver, - types::{ - binary::chains::{ - ConnectedChains, - DropChainHandle, - }, - config::TestConfig, - env::write_env, - single::node::FullNode, - }, - util::suspend::hang_on_error, +use crate::bootstrap::binary::chain::{bootstrap_chains_with_full_nodes, BootstrapClientOptions}; +use crate::error::Error; +use crate::framework::base::{HasOverrides, TestConfigOverride}; +use crate::framework::binary::ics::InterchainSecurityChainTest; +use crate::framework::binary::node::{ + run_binary_node_test, run_single_node_test, BinaryNodeTest, NodeConfigOverride, + NodeGenesisOverride, }; +use crate::framework::supervisor::{RunWithSupervisor, SupervisorOverride}; +use crate::relayer::driver::RelayerDriver; +use crate::types::binary::chains::{ConnectedChains, DropChainHandle}; +use crate::types::config::TestConfig; +use crate::types::env::write_env; +use crate::types::single::node::FullNode; +use crate::types::topology::TopologyType; +use crate::util::suspend::hang_on_error; /** Runs a test case that implements [`BinaryChainTest`], with @@ -138,6 +114,10 @@ pub trait RelayerConfigOverride { fn modify_relayer_config(&self, config: &mut Config); } +pub trait TopologyOverride { + fn topology(&self) -> Option; +} + /// An internal trait that can be implemented by test cases to override the /// settings for the foreign clients bootstrapped for the test. /// diff --git a/tools/test-framework/src/framework/binary/channel.rs b/tools/test-framework/src/framework/binary/channel.rs index db79994023..00ae9efd89 100644 --- a/tools/test-framework/src/framework/binary/channel.rs +++ b/tools/test-framework/src/framework/binary/channel.rs @@ -4,63 +4,37 @@ connected IBC channels with completed handshakes. */ -use ibc_relayer::chain::handle::ChainHandle; -use ibc_relayer_types::core::{ - ics04_channel::{ - channel::Ordering, - version::Version, - }, - ics24_host::identifier::PortId, -}; use tracing::info; -use crate::{ - bootstrap::binary::channel::{ - bootstrap_channel_with_connection, - BootstrapChannelOptions, - }, - error::Error, - framework::{ - base::{ - HasOverrides, - TestConfigOverride, - }, - binary::{ - chain::{ - ClientOptionsOverride, - RelayerConfigOverride, - RunBinaryChainTest, - }, - connection::{ - BinaryConnectionTest, - ConnectionDelayOverride, - RunBinaryConnectionTest, - }, - ics::run_binary_interchain_security_node_test, - node::{ - run_binary_node_test, - NodeConfigOverride, - NodeGenesisOverride, - }, - }, - supervisor::{ - RunWithSupervisor, - SupervisorOverride, - }, - }, - relayer::driver::RelayerDriver, - types::{ - binary::{ - chains::ConnectedChains, - channel::ConnectedChannel, - connection::ConnectedConnection, - }, - config::TestConfig, - env::write_env, - tagged::*, - }, - util::suspend::hang_on_error, +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer_types::core::ics04_channel::channel::Ordering; +use ibc_relayer_types::core::ics04_channel::version::Version; +use ibc_relayer_types::core::ics24_host::identifier::PortId; + +use crate::bootstrap::binary::channel::{ + bootstrap_channel_with_connection, BootstrapChannelOptions, +}; +use crate::error::Error; +use crate::framework::base::{HasOverrides, TestConfigOverride}; +use crate::framework::binary::chain::{ + ClientOptionsOverride, RelayerConfigOverride, RunBinaryChainTest, +}; +use crate::framework::binary::connection::{ + BinaryConnectionTest, ConnectionDelayOverride, RunBinaryConnectionTest, +}; +use crate::framework::binary::ics::run_binary_interchain_security_node_test; +use crate::framework::binary::node::{ + run_binary_node_test, NodeConfigOverride, NodeGenesisOverride, }; +use crate::framework::supervisor::{RunWithSupervisor, SupervisorOverride}; +use crate::relayer::driver::RelayerDriver; +use crate::types::binary::chains::ConnectedChains; +use crate::types::binary::channel::ConnectedChannel; +use crate::types::binary::connection::ConnectedConnection; +use crate::types::config::TestConfig; +use crate::types::env::write_env; +use crate::types::tagged::*; +use crate::util::suspend::hang_on_error; /** Runs a test case that implements [`BinaryChannelTest`], with diff --git a/tools/test-framework/src/framework/binary/connection.rs b/tools/test-framework/src/framework/binary/connection.rs index 0b99f62b03..9e96a7665e 100644 --- a/tools/test-framework/src/framework/binary/connection.rs +++ b/tools/test-framework/src/framework/binary/connection.rs @@ -5,50 +5,26 @@ */ use core::time::Duration; - use ibc_relayer::chain::handle::ChainHandle; use tracing::info; -use crate::{ - bootstrap::binary::connection::{ - bootstrap_connection, - BootstrapConnectionOptions, - }, - error::Error, - framework::{ - base::{ - HasOverrides, - TestConfigOverride, - }, - binary::{ - chain::{ - BinaryChainTest, - ClientOptionsOverride, - RelayerConfigOverride, - RunBinaryChainTest, - }, - node::{ - run_binary_node_test, - NodeConfigOverride, - NodeGenesisOverride, - }, - }, - supervisor::{ - RunWithSupervisor, - SupervisorOverride, - }, - }, - relayer::driver::RelayerDriver, - types::{ - binary::{ - chains::ConnectedChains, - connection::ConnectedConnection, - }, - config::TestConfig, - env::write_env, - }, - util::suspend::hang_on_error, +use crate::bootstrap::binary::connection::{bootstrap_connection, BootstrapConnectionOptions}; +use crate::error::Error; +use crate::framework::base::HasOverrides; +use crate::framework::base::TestConfigOverride; +use crate::framework::binary::chain::{ + BinaryChainTest, ClientOptionsOverride, RelayerConfigOverride, RunBinaryChainTest, +}; +use crate::framework::binary::node::{ + run_binary_node_test, NodeConfigOverride, NodeGenesisOverride, }; +use crate::framework::supervisor::{RunWithSupervisor, SupervisorOverride}; +use crate::relayer::driver::RelayerDriver; +use crate::types::binary::chains::ConnectedChains; +use crate::types::binary::connection::ConnectedConnection; +use crate::types::config::TestConfig; +use crate::types::env::write_env; +use crate::util::suspend::hang_on_error; /** Runs a test case that implements [`BinaryConnectionTest`], with diff --git a/tools/test-framework/src/framework/binary/ics.rs b/tools/test-framework/src/framework/binary/ics.rs index 4842cf1369..24086eff6c 100644 --- a/tools/test-framework/src/framework/binary/ics.rs +++ b/tools/test-framework/src/framework/binary/ics.rs @@ -1,33 +1,17 @@ use std::str::FromStr; -use crate::{ - bootstrap::{ - consumer::bootstrap_consumer_node, - single::bootstrap_single_node, - }, - chain::{ - builder::ChainBuilder, - chain_type::ChainType, - cli::upgrade::vote_proposal, - ext::bootstrap::ChainBootstrapMethodsExt, - }, - error::Error, - framework::{ - base::{ - run_basic_test, - BasicTest, - HasOverrides, - TestConfigOverride, - }, - binary::node::{ - NodeConfigOverride, - NodeGenesisOverride, - }, - }, - prelude::FullNode, - types::config::TestConfig, - util::proposal_status::ProposalStatus, -}; +use crate::bootstrap::consumer::bootstrap_consumer_node; +use crate::bootstrap::single::bootstrap_single_node; +use crate::chain::builder::ChainBuilder; +use crate::chain::chain_type::ChainType; +use crate::chain::cli::upgrade::vote_proposal; +use crate::chain::ext::bootstrap::ChainBootstrapMethodsExt; +use crate::error::Error; +use crate::framework::base::{run_basic_test, BasicTest, HasOverrides, TestConfigOverride}; +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`]. @@ -81,15 +65,17 @@ where 0, )?; let provider_native_token = builder.native_tokens[0].clone(); - let provider_fee = format!("1200{}", provider_native_token); + let provider_fee = format!("381000000{provider_native_token}"); // Get consumer chain id let chain_type = ChainType::from_str(&builder.command_paths[1])?; let chain_id = chain_type.chain_id("consumer", false); - node_a - .chain_driver - .submit_consumer_chain_proposal(chain_id.as_str(), "2023-05-31T12:09:47.048227Z")?; + node_a.chain_driver.submit_consumer_chain_proposal( + chain_id.as_str(), + &provider_fee, + "2023-05-31T12:09:47.048227Z", + )?; node_a.chain_driver.assert_proposal_status( node_a.chain_driver.chain_id.as_str(), @@ -106,6 +92,7 @@ where &node_a.chain_driver.home_path, &node_a.chain_driver.rpc_listen_address(), &provider_fee, + "1", )?; node_a.chain_driver.assert_proposal_status( diff --git a/tools/test-framework/src/framework/binary/node.rs b/tools/test-framework/src/framework/binary/node.rs index 579ebe87d8..ff59b4a13e 100644 --- a/tools/test-framework/src/framework/binary/node.rs +++ b/tools/test-framework/src/framework/binary/node.rs @@ -3,23 +3,13 @@ running without setting up the relayer. */ -use toml; - -use crate::{ - bootstrap::single::bootstrap_single_node, - chain::builder::ChainBuilder, - error::Error, - framework::base::{ - run_basic_test, - BasicTest, - HasOverrides, - TestConfigOverride, - }, - types::{ - config::TestConfig, - single::node::FullNode, - }, -}; +use crate::bootstrap::single::bootstrap_single_node; +use crate::chain::builder::ChainBuilder; +use crate::error::Error; +use crate::framework::base::HasOverrides; +use crate::framework::base::{run_basic_test, BasicTest, TestConfigOverride}; +use crate::types::config::TestConfig; +use crate::types::single::node::FullNode; /** Runs a test case that implements [`BinaryNodeTest`]. diff --git a/tools/test-framework/src/framework/nary/chain.rs b/tools/test-framework/src/framework/nary/chain.rs index 872593e961..4584ba2df7 100644 --- a/tools/test-framework/src/framework/nary/chain.rs +++ b/tools/test-framework/src/framework/nary/chain.rs @@ -6,43 +6,22 @@ use ibc_relayer::chain::handle::ChainHandle; use tracing::info; -use crate::{ - bootstrap::nary::chain::{ - boostrap_chains_with_nodes, - boostrap_chains_with_self_connected_node, - }, - error::Error, - framework::{ - base::{ - HasOverrides, - TestConfigOverride, - }, - binary::{ - chain::RelayerConfigOverride, - node::{ - NodeConfigOverride, - NodeGenesisOverride, - }, - }, - nary::node::{ - run_nary_node_test, - NaryNodeTest, - }, - supervisor::{ - RunWithSupervisor, - SupervisorOverride, - }, - }, - relayer::driver::RelayerDriver, - types::{ - binary::chains::DropChainHandle, - config::TestConfig, - env::write_env, - nary::chains::NaryConnectedChains, - single::node::FullNode, - }, - util::suspend::hang_on_error, +use crate::bootstrap::nary::chain::{ + boostrap_chains_with_nodes, boostrap_chains_with_self_connected_node, }; +use crate::error::Error; +use crate::framework::base::{HasOverrides, TestConfigOverride}; +use crate::framework::binary::chain::{RelayerConfigOverride, TopologyOverride}; +use crate::framework::binary::node::{NodeConfigOverride, NodeGenesisOverride}; +use crate::framework::nary::node::{run_nary_node_test, NaryNodeTest}; +use crate::framework::supervisor::{RunWithSupervisor, SupervisorOverride}; +use crate::relayer::driver::RelayerDriver; +use crate::types::binary::chains::DropChainHandle; +use crate::types::config::TestConfig; +use crate::types::env::write_env; +use crate::types::nary::chains::NaryConnectedChains; +use crate::types::single::node::FullNode; +use crate::util::suspend::hang_on_error; /** Runs a test case that implements [`NaryChainTest`] with a `SIZE` number of @@ -69,7 +48,8 @@ where + NodeConfigOverride + NodeGenesisOverride + RelayerConfigOverride - + SupervisorOverride, + + SupervisorOverride + + TopologyOverride, { run_nary_node_test(&RunNaryChainTest::new(&RunWithSupervisor::new(test))) } @@ -98,7 +78,8 @@ where + NodeConfigOverride + NodeGenesisOverride + RelayerConfigOverride - + SupervisorOverride, + + SupervisorOverride + + TopologyOverride, { run_nary_node_test(&RunSelfConnectedNaryChainTest::new( &RunWithSupervisor::new(test), @@ -146,12 +127,17 @@ impl<'a, Test, Overrides, const SIZE: usize> NaryNodeTest for RunNaryChain where Test: NaryChainTest, Test: HasOverrides, - Overrides: RelayerConfigOverride, + Overrides: RelayerConfigOverride + TopologyOverride, { fn run(&self, config: &TestConfig, nodes: [FullNode; SIZE]) -> Result<(), Error> { - let (relayer, chains) = boostrap_chains_with_nodes(config, nodes, |config| { - self.test.get_overrides().modify_relayer_config(config); - })?; + let (relayer, chains) = boostrap_chains_with_nodes( + config, + nodes, + self.test.get_overrides().topology(), + |config| { + self.test.get_overrides().modify_relayer_config(config); + }, + )?; let env_path = config.chain_store_dir.join("nary-chains.env"); @@ -176,13 +162,17 @@ impl<'a, Test, Overrides, const SIZE: usize> NaryNodeTest<1> where Test: NaryChainTest, Test: HasOverrides, - Overrides: RelayerConfigOverride, + Overrides: RelayerConfigOverride + TopologyOverride, { fn run(&self, config: &TestConfig, nodes: [FullNode; 1]) -> Result<(), Error> { - let (relayer, chains) = - boostrap_chains_with_self_connected_node(config, nodes[0].clone(), |config| { + let (relayer, chains) = boostrap_chains_with_self_connected_node( + config, + nodes[0].clone(), + self.test.get_overrides().topology(), + |config| { self.test.get_overrides().modify_relayer_config(config); - })?; + }, + )?; let env_path = config.chain_store_dir.join("nary-chains.env"); diff --git a/tools/test-framework/src/framework/nary/channel.rs b/tools/test-framework/src/framework/nary/channel.rs index ac780d4eaf..38896a2a2a 100644 --- a/tools/test-framework/src/framework/nary/channel.rs +++ b/tools/test-framework/src/framework/nary/channel.rs @@ -8,51 +8,24 @@ use ibc_relayer::chain::handle::ChainHandle; use ibc_relayer_types::core::ics24_host::identifier::PortId; use tracing::info; -use crate::{ - bootstrap::nary::channel::bootstrap_channels_with_connections, - error::Error, - framework::{ - base::{ - HasOverrides, - TestConfigOverride, - }, - binary::{ - chain::RelayerConfigOverride, - channel::{ - BinaryChannelTest, - ChannelOrderOverride, - }, - connection::ConnectionDelayOverride, - node::{ - NodeConfigOverride, - NodeGenesisOverride, - }, - }, - nary::{ - chain::RunNaryChainTest, - connection::{ - NaryConnectionTest, - RunNaryConnectionTest, - }, - node::run_nary_node_test, - }, - supervisor::{ - RunWithSupervisor, - SupervisorOverride, - }, - }, - relayer::driver::RelayerDriver, - types::{ - config::TestConfig, - env::write_env, - nary::{ - chains::NaryConnectedChains, - channel::ConnectedChannels, - connection::ConnectedConnections, - }, - }, - util::suspend::hang_on_error, -}; +use crate::bootstrap::nary::channel::bootstrap_channels_with_connections; +use crate::error::Error; +use crate::framework::base::{HasOverrides, TestConfigOverride}; +use crate::framework::binary::chain::{RelayerConfigOverride, TopologyOverride}; +use crate::framework::binary::channel::{BinaryChannelTest, ChannelOrderOverride}; +use crate::framework::binary::connection::ConnectionDelayOverride; +use crate::framework::binary::node::{NodeConfigOverride, NodeGenesisOverride}; +use crate::framework::nary::chain::RunNaryChainTest; +use crate::framework::nary::connection::{NaryConnectionTest, RunNaryConnectionTest}; +use crate::framework::nary::node::run_nary_node_test; +use crate::framework::supervisor::{RunWithSupervisor, SupervisorOverride}; +use crate::relayer::driver::RelayerDriver; +use crate::types::config::TestConfig; +use crate::types::env::write_env; +use crate::types::nary::chains::NaryConnectedChains; +use crate::types::nary::channel::ConnectedChannels; +use crate::types::nary::connection::ConnectedConnections; +use crate::util::suspend::hang_on_error; pub fn run_nary_channel_test(test: &Test) -> Result<(), Error> where @@ -65,7 +38,8 @@ where + SupervisorOverride + ConnectionDelayOverride + PortsOverride - + ChannelOrderOverride, + + ChannelOrderOverride + + TopologyOverride, { run_nary_node_test(&RunNaryChainTest::new(&RunNaryConnectionTest::new( &RunNaryChannelTest::new(&RunWithSupervisor::new(test)), @@ -83,7 +57,8 @@ where + SupervisorOverride + ConnectionDelayOverride + PortsOverride<2> - + ChannelOrderOverride, + + ChannelOrderOverride + + TopologyOverride, { run_nary_channel_test(&RunBinaryAsNaryChannelTest::new(test)) } @@ -202,7 +177,6 @@ where let channels = bootstrap_channels_with_connections( connections, - chains.chain_handles().clone(), port_ids, order, config.bootstrap_with_random_ids, diff --git a/tools/test-framework/src/framework/nary/connection.rs b/tools/test-framework/src/framework/nary/connection.rs index c66e20823f..6870d3be9e 100644 --- a/tools/test-framework/src/framework/nary/connection.rs +++ b/tools/test-framework/src/framework/nary/connection.rs @@ -7,48 +7,21 @@ use ibc_relayer::chain::handle::ChainHandle; use tracing::info; -use crate::{ - bootstrap::nary::connection::bootstrap_connections, - error::Error, - framework::{ - base::{ - HasOverrides, - TestConfigOverride, - }, - binary::{ - chain::RelayerConfigOverride, - connection::{ - BinaryConnectionTest, - ConnectionDelayOverride, - }, - node::{ - NodeConfigOverride, - NodeGenesisOverride, - }, - }, - nary::{ - chain::{ - NaryChainTest, - RunNaryChainTest, - }, - node::run_nary_node_test, - }, - supervisor::{ - RunWithSupervisor, - SupervisorOverride, - }, - }, - relayer::driver::RelayerDriver, - types::{ - config::TestConfig, - env::write_env, - nary::{ - chains::NaryConnectedChains, - connection::ConnectedConnections, - }, - }, - util::suspend::hang_on_error, -}; +use crate::bootstrap::nary::connection::bootstrap_connections; +use crate::error::Error; +use crate::framework::base::{HasOverrides, TestConfigOverride}; +use crate::framework::binary::chain::{RelayerConfigOverride, TopologyOverride}; +use crate::framework::binary::connection::{BinaryConnectionTest, ConnectionDelayOverride}; +use crate::framework::binary::node::{NodeConfigOverride, NodeGenesisOverride}; +use crate::framework::nary::chain::{NaryChainTest, RunNaryChainTest}; +use crate::framework::nary::node::run_nary_node_test; +use crate::framework::supervisor::{RunWithSupervisor, SupervisorOverride}; +use crate::relayer::driver::RelayerDriver; +use crate::types::config::TestConfig; +use crate::types::env::write_env; +use crate::types::nary::chains::NaryConnectedChains; +use crate::types::nary::connection::ConnectedConnections; +use crate::util::suspend::hang_on_error; pub fn run_nary_connection_test( test: &Test, @@ -61,7 +34,8 @@ where + NodeGenesisOverride + RelayerConfigOverride + SupervisorOverride - + ConnectionDelayOverride, + + ConnectionDelayOverride + + TopologyOverride, { run_nary_node_test(&RunNaryChainTest::new(&RunNaryConnectionTest::new( &RunWithSupervisor::new(test), diff --git a/tools/test-framework/src/framework/nary/node.rs b/tools/test-framework/src/framework/nary/node.rs index 5666d34c8c..cea7c81ac4 100644 --- a/tools/test-framework/src/framework/nary/node.rs +++ b/tools/test-framework/src/framework/nary/node.rs @@ -3,28 +3,15 @@ running without setting up the relayer. */ -use crate::{ - bootstrap::single::bootstrap_single_node, - chain::builder::ChainBuilder, - error::Error, - framework::{ - base::{ - run_basic_test, - BasicTest, - HasOverrides, - TestConfigOverride, - }, - binary::node::{ - NodeConfigOverride, - NodeGenesisOverride, - }, - }, - types::{ - config::TestConfig, - single::node::FullNode, - }, - util::array::try_into_array, -}; +use crate::bootstrap::single::bootstrap_single_node; +use crate::chain::builder::ChainBuilder; +use crate::error::Error; +use crate::framework::base::HasOverrides; +use crate::framework::base::{run_basic_test, BasicTest, TestConfigOverride}; +use crate::framework::binary::node::{NodeConfigOverride, NodeGenesisOverride}; +use crate::types::config::TestConfig; +use crate::types::single::node::FullNode; +use crate::util::array::try_into_array; pub fn run_nary_node_test(test: &Test) -> Result<(), Error> where diff --git a/tools/test-framework/src/framework/overrides.rs b/tools/test-framework/src/framework/overrides.rs index 3b14dcd3d4..70398de376 100644 --- a/tools/test-framework/src/framework/overrides.rs +++ b/tools/test-framework/src/framework/overrides.rs @@ -3,50 +3,28 @@ */ use core::time::Duration; - -use ibc_relayer::{ - config::{ - default::connection_delay as default_connection_delay, - Config, - }, - foreign_client::CreateOptions as ClientOptions, -}; -use ibc_relayer_types::core::{ - ics04_channel::{ - channel::Ordering, - version::Version, - }, - ics24_host::identifier::PortId, +use ibc_relayer::config::default::connection_delay as default_connection_delay; +use ibc_relayer::config::Config; +use ibc_relayer::foreign_client::CreateOptions as ClientOptions; +use ibc_relayer_types::core::ics04_channel::channel::Ordering; +use ibc_relayer_types::core::ics04_channel::version::Version; +use ibc_relayer_types::core::ics24_host::identifier::PortId; + +use crate::error::Error; +use crate::framework::base::HasOverrides; +use crate::framework::base::TestConfigOverride; +use crate::framework::binary::chain::{ClientOptionsOverride, RelayerConfigOverride}; +use crate::framework::binary::channel::{ + ChannelOrderOverride, ChannelVersionOverride, PortsOverride, }; +use crate::framework::binary::connection::ConnectionDelayOverride; +use crate::framework::binary::node::{NodeConfigOverride, NodeGenesisOverride}; +use crate::framework::nary::channel::PortsOverride as NaryPortsOverride; +use crate::framework::supervisor::SupervisorOverride; +use crate::types::config::TestConfig; +use crate::types::topology::TopologyType; -use crate::{ - error::Error, - framework::{ - base::{ - HasOverrides, - TestConfigOverride, - }, - binary::{ - chain::{ - ClientOptionsOverride, - RelayerConfigOverride, - }, - channel::{ - ChannelOrderOverride, - ChannelVersionOverride, - PortsOverride, - }, - connection::ConnectionDelayOverride, - node::{ - NodeConfigOverride, - NodeGenesisOverride, - }, - }, - nary::channel::PortsOverride as NaryPortsOverride, - supervisor::SupervisorOverride, - }, - types::config::TestConfig, -}; +use super::binary::chain::TopologyOverride; /** This trait should be implemented for all test cases to allow overriding @@ -170,6 +148,10 @@ pub trait TestOverrides { fn channel_version(&self) -> Version { Version::ics20() } + + fn topology(&self) -> Option { + None + } } impl HasOverrides for Test { @@ -256,3 +238,9 @@ impl NaryPortsOverride<2> for Test { [[port_a.clone(), port_b.clone()], [port_b, port_a]] } } + +impl TopologyOverride for Test { + fn topology(&self) -> Option { + TestOverrides::topology(self) + } +} diff --git a/tools/test-framework/src/ibc/denom.rs b/tools/test-framework/src/ibc/denom.rs index 9627abf473..965a56b1b7 100644 --- a/tools/test-framework/src/ibc/denom.rs +++ b/tools/test-framework/src/ibc/denom.rs @@ -2,29 +2,14 @@ Helper functions for deriving IBC denom. */ -use core::fmt::{ - self, - Display, -}; - +use core::fmt::{self, Display}; use eyre::Report as Error; -use ibc_relayer_types::core::ics24_host::identifier::{ - ChannelId, - PortId, -}; -use sha2::{ - Digest, - Sha256, -}; +use ibc_relayer_types::core::ics24_host::identifier::{ChannelId, PortId}; +use sha2::{Digest, Sha256}; use subtle_encoding::hex; -use crate::types::{ - id::{ - TaggedChannelIdRef, - TaggedPortIdRef, - }, - tagged::*, -}; +use crate::types::id::{TaggedChannelIdRef, TaggedPortIdRef}; +use crate::types::tagged::*; /** A newtype wrapper to represent a denomination string. diff --git a/tools/test-framework/src/ibc/token.rs b/tools/test-framework/src/ibc/token.rs index 438e1dcb9b..ac7b6785ad 100644 --- a/tools/test-framework/src/ibc/token.rs +++ b/tools/test-framework/src/ibc/token.rs @@ -1,32 +1,11 @@ -use core::ops::{ - Add, - Sub, -}; - -use ibc_relayer_types::applications::transfer::{ - amount::Amount, - coin::{ - Coin, - RawCoin, - }, -}; - -use crate::{ - error::Error, - ibc::denom::{ - derive_ibc_denom, - Denom, - TaggedDenom, - TaggedDenomRef, - }, - types::{ - id::{ - TaggedChannelIdRef, - TaggedPortIdRef, - }, - tagged::MonoTagged, - }, -}; +use core::ops::{Add, Sub}; +use ibc_relayer_types::applications::transfer::amount::Amount; +use ibc_relayer_types::applications::transfer::coin::{Coin, RawCoin}; + +use crate::error::Error; +use crate::ibc::denom::{derive_ibc_denom, Denom, TaggedDenom, TaggedDenomRef}; +use crate::types::id::{TaggedChannelIdRef, TaggedPortIdRef}; +use crate::types::tagged::MonoTagged; pub type Token = Coin; diff --git a/tools/test-framework/src/prelude.rs b/tools/test-framework/src/prelude.rs index 1bd81a6574..cf84da30f0 100644 --- a/tools/test-framework/src/prelude.rs +++ b/tools/test-framework/src/prelude.rs @@ -3,163 +3,75 @@ */ pub use core::time::Duration; +pub use eyre::eyre; +pub use ibc_relayer::chain::handle::ChainHandle; +pub use ibc_relayer::config::Config; +pub use ibc_relayer::foreign_client::ForeignClient; +pub use ibc_relayer::registry::SharedRegistry; +pub use ibc_relayer::supervisor::SupervisorHandle; +pub use ibc_relayer_types::core::ics04_channel::channel::Ordering; +pub use ibc_relayer_types::core::ics24_host::identifier::{ + ChainId, ChannelId, ClientId, ConnectionId, PortId, +}; pub use std::thread::sleep; +pub use tracing::{debug, error, info, warn}; -pub use eyre::eyre; -pub use ibc_relayer::{ - chain::handle::ChainHandle, - config::Config, - foreign_client::ForeignClient, - registry::SharedRegistry, - supervisor::SupervisorHandle, +pub use crate::chain::driver::ChainDriver; +pub use crate::chain::ext::fee::ChainFeeMethodsExt; +pub use crate::chain::ext::ica::InterchainAccountMethodsExt; +pub use crate::chain::ext::proposal::ChainProposalMethodsExt; +pub use crate::chain::ext::transfer::ChainTransferMethodsExt; +pub use crate::chain::tagged::TaggedChainDriverExt; +pub use crate::error::{handle_generic_error, Error}; +pub use crate::framework::base::HasOverrides; +pub use crate::framework::binary::chain::{ + run_binary_chain_test, run_self_connected_binary_chain_test, run_two_way_binary_chain_test, + BinaryChainTest, RunBinaryChainTest, RunSelfConnectedBinaryChainTest, }; -pub use ibc_relayer_types::core::{ - ics04_channel::channel::Ordering, - ics24_host::identifier::{ - ChainId, - ChannelId, - ClientId, - ConnectionId, - PortId, - }, +pub use crate::framework::binary::channel::{ + run_binary_channel_test, run_two_way_binary_channel_test, BinaryChannelTest, + RunBinaryChannelTest, }; -pub use tracing::{ - debug, - error, - info, - warn, +pub use crate::framework::binary::connection::{ + run_binary_connection_test, run_two_way_binary_connection_test, BinaryConnectionTest, + RunBinaryConnectionTest, }; - -pub use crate::{ - chain::{ - driver::ChainDriver, - ext::{ - fee::ChainFeeMethodsExt, - ica::InterchainAccountMethodsExt, - proposal::ChainProposalMethodsExt, - transfer::ChainTransferMethodsExt, - }, - tagged::TaggedChainDriverExt, - }, - error::{ - handle_generic_error, - Error, - }, - framework::{ - base::HasOverrides, - binary::{ - chain::{ - run_binary_chain_test, - run_self_connected_binary_chain_test, - run_two_way_binary_chain_test, - BinaryChainTest, - RunBinaryChainTest, - RunSelfConnectedBinaryChainTest, - }, - channel::{ - run_binary_channel_test, - run_two_way_binary_channel_test, - BinaryChannelTest, - RunBinaryChannelTest, - }, - connection::{ - run_binary_connection_test, - run_two_way_binary_connection_test, - BinaryConnectionTest, - RunBinaryConnectionTest, - }, - node::{ - run_binary_node_test, - BinaryNodeTest, - RunBinaryNodeTest, - }, - }, - nary::{ - chain::{ - run_nary_chain_test, - run_self_connected_nary_chain_test, - NaryChainTest, - RunNaryChainTest, - RunSelfConnectedNaryChainTest, - }, - channel::{ - run_binary_as_nary_channel_test, - run_nary_channel_test, - NaryChannelTest, - PortsOverride, - RunBinaryAsNaryChannelTest, - RunNaryChannelTest, - }, - connection::{ - run_nary_connection_test, - NaryConnectionTest, - RunNaryConnectionTest, - }, - node::{ - run_nary_node_test, - NaryNodeTest, - RunNaryNodeTest, - }, - }, - overrides::TestOverrides, - supervisor::RunWithSupervisor, - }, - ibc::{ - denom::{ - derive_ibc_denom, - Denom, - }, - token::{ - TaggedDenomExt, - TaggedToken, - TaggedTokenExt, - TaggedTokenRef, - Token, - }, - }, - relayer::{ - channel::TaggedChannelEndExt, - connection::{ - TaggedConnectionEndExt, - TaggedConnectionExt, - }, - driver::RelayerDriver, - foreign_client::TaggedForeignClientExt, - }, - types::{ - binary::{ - chains::ConnectedChains, - channel::ConnectedChannel, - connection::ConnectedConnection, - foreign_client::ForeignClientPair, - }, - config::TestConfig, - id::*, - nary::{ - chains::NaryConnectedChains, - channel::ConnectedChannels as NaryConnectedChannels, - connection::ConnectedConnections as NaryConnectedConnections, - }, - single::node::{ - FullNode, - TaggedFullNodeExt, - }, - tagged::{ - DualTagged, - MonoTagged, - }, - wallet::{ - TaggedTestWalletsExt, - TaggedWallet, - TestWallets, - Wallet, - WalletAddress, - WalletId, - }, - }, - util::{ - assert::*, - retry::assert_eventually_succeed, - suspend::suspend, - }, +pub use crate::framework::binary::node::{run_binary_node_test, BinaryNodeTest, RunBinaryNodeTest}; +pub use crate::framework::nary::chain::{ + run_nary_chain_test, run_self_connected_nary_chain_test, NaryChainTest, RunNaryChainTest, + RunSelfConnectedNaryChainTest, +}; +pub use crate::framework::nary::channel::{ + run_binary_as_nary_channel_test, run_nary_channel_test, NaryChannelTest, PortsOverride, + RunBinaryAsNaryChannelTest, RunNaryChannelTest, +}; +pub use crate::framework::nary::connection::{ + run_nary_connection_test, NaryConnectionTest, RunNaryConnectionTest, +}; +pub use crate::framework::nary::node::{run_nary_node_test, NaryNodeTest, RunNaryNodeTest}; +pub use crate::framework::overrides::TestOverrides; +pub use crate::framework::supervisor::RunWithSupervisor; +pub use crate::ibc::denom::derive_ibc_denom; +pub use crate::ibc::denom::Denom; +pub use crate::ibc::token::{TaggedDenomExt, TaggedToken, TaggedTokenExt, TaggedTokenRef, Token}; +pub use crate::relayer::channel::TaggedChannelEndExt; +pub use crate::relayer::connection::{TaggedConnectionEndExt, TaggedConnectionExt}; +pub use crate::relayer::driver::RelayerDriver; +pub use crate::relayer::foreign_client::TaggedForeignClientExt; +pub use crate::types::binary::chains::ConnectedChains; +pub use crate::types::binary::channel::ConnectedChannel; +pub use crate::types::binary::connection::ConnectedConnection; +pub use crate::types::binary::foreign_client::ForeignClientPair; +pub use crate::types::config::TestConfig; +pub use crate::types::id::*; +pub use crate::types::nary::chains::NaryConnectedChains; +pub use crate::types::nary::channel::ConnectedChannels as NaryConnectedChannels; +pub use crate::types::nary::connection::ConnectedConnections as NaryConnectedConnections; +pub use crate::types::single::node::{FullNode, TaggedFullNodeExt}; +pub use crate::types::tagged::{DualTagged, MonoTagged}; +pub use crate::types::wallet::{ + TaggedTestWalletsExt, TaggedWallet, TestWallets, Wallet, WalletAddress, WalletId, }; +pub use crate::util::assert::*; +pub use crate::util::retry::assert_eventually_succeed; +pub use crate::util::suspend::suspend; diff --git a/tools/test-framework/src/relayer/chain.rs b/tools/test-framework/src/relayer/chain.rs index 68f1a74bf1..7c68839d30 100644 --- a/tools/test-framework/src/relayer/chain.rs +++ b/tools/test-framework/src/relayer/chain.rs @@ -21,81 +21,46 @@ */ use crossbeam_channel as channel; +use ibc_proto::ibc::core::channel::v1::{QueryUpgradeErrorRequest, QueryUpgradeRequest}; +use ibc_relayer::chain::cosmos::version::Specs; +use ibc_relayer_types::core::ics04_channel::upgrade::{ErrorReceipt, Upgrade}; +use tracing::Span; + use ibc_proto::ibc::apps::fee::v1::{ - QueryIncentivizedPacketRequest, - QueryIncentivizedPacketResponse, -}; -use ibc_relayer::{ - account::Balance, - chain::{ - client::ClientSettings, - cosmos::version::Specs, - endpoint::{ - ChainStatus, - HealthCheck, - }, - handle::{ - ChainHandle, - ChainRequest, - Subscription, - }, - requests::*, - tracking::TrackedMsgs, - }, - client_state::{ - AnyClientState, - IdentifiedAnyClientState, - }, - config::ChainConfig, - connection::ConnectionMsgType, - consensus_state::AnyConsensusState, - denom::DenomTrace, - error::Error, - event::IbcEventWithHeight, - keyring::AnySigningKeyPair, - misbehaviour::MisbehaviourEvidence, -}; -use ibc_relayer_types::{ - applications::ics31_icq::response::CrossChainQueryResponse, - core::{ - ics02_client::{ - events::UpdateClient, - header::AnyHeader, - }, - ics03_connection::{ - connection::{ - ConnectionEnd, - IdentifiedConnectionEnd, - }, - version::Version, - }, - ics04_channel::{ - channel::{ - ChannelEnd, - IdentifiedChannelEnd, - }, - packet::{ - PacketMsgType, - Sequence, - }, - }, - ics23_commitment::{ - commitment::CommitmentPrefix, - merkle::MerkleProof, - }, - ics24_host::identifier::{ - ChainId, - ChannelId, - ClientId, - ConnectionId, - PortId, - }, - }, - proofs::Proofs, - signer::Signer, - Height, + QueryIncentivizedPacketRequest, QueryIncentivizedPacketResponse, }; -use tracing::Span; +use ibc_relayer::account::Balance; +use ibc_relayer::chain::client::ClientSettings; +use ibc_relayer::chain::endpoint::{ChainStatus, HealthCheck}; +use ibc_relayer::chain::handle::{ChainHandle, ChainRequest, Subscription}; +use ibc_relayer::chain::requests::*; +use ibc_relayer::chain::tracking::TrackedMsgs; +use ibc_relayer::client_state::{AnyClientState, IdentifiedAnyClientState}; +use ibc_relayer::config::ChainConfig; +use ibc_relayer::connection::ConnectionMsgType; +use ibc_relayer::consensus_state::AnyConsensusState; +use ibc_relayer::denom::DenomTrace; +use ibc_relayer::error::Error; +use ibc_relayer::event::IbcEventWithHeight; +use ibc_relayer::keyring::AnySigningKeyPair; +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; +use ibc_relayer_types::core::ics04_channel::channel::ChannelEnd; +use ibc_relayer_types::core::ics04_channel::channel::IdentifiedChannelEnd; +use ibc_relayer_types::core::ics04_channel::packet::{PacketMsgType, Sequence}; +use ibc_relayer_types::core::ics23_commitment::commitment::CommitmentPrefix; +use ibc_relayer_types::core::ics23_commitment::merkle::MerkleProof; +use ibc_relayer_types::core::ics24_host::identifier::ChainId; +use ibc_relayer_types::core::ics24_host::identifier::ChannelId; +use ibc_relayer_types::core::ics24_host::identifier::{ClientId, ConnectionId, PortId}; +use ibc_relayer_types::proofs::Proofs; +use ibc_relayer_types::signer::Signer; +use ibc_relayer_types::Height; use crate::types::tagged::*; @@ -472,4 +437,23 @@ where fn query_consumer_chains(&self) -> Result, Error> { self.value().query_consumer_chains() } + + fn query_upgrade( + &self, + request: QueryUpgradeRequest, + height: Height, + include_proof: IncludeProof, + ) -> Result<(Upgrade, Option), Error> { + self.value().query_upgrade(request, height, include_proof) + } + + fn query_upgrade_error( + &self, + request: QueryUpgradeErrorRequest, + height: Height, + include_proof: IncludeProof, + ) -> Result<(ErrorReceipt, Option), Error> { + self.value() + .query_upgrade_error(request, height, include_proof) + } } diff --git a/tools/test-framework/src/relayer/channel.rs b/tools/test-framework/src/relayer/channel.rs index 61374eea3d..2ea35886c9 100644 --- a/tools/test-framework/src/relayer/channel.rs +++ b/tools/test-framework/src/relayer/channel.rs @@ -1,47 +1,25 @@ use core::time::Duration; - use eyre::eyre; -use ibc_relayer::{ - chain::{ - handle::ChainHandle, - requests::{ - IncludeProof, - QueryChannelRequest, - QueryHeight, - }, - }, - channel::{ - extract_channel_id, - version::Version, - Channel, - ChannelSide, - }, +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::chain::requests::{ + IncludeProof, QueryChannelRequest, QueryChannelsRequest, QueryHeight, }; -use ibc_relayer_types::core::{ - ics04_channel::channel::{ - ChannelEnd, - IdentifiedChannelEnd, - Ordering, - State as ChannelState, - }, - ics24_host::identifier::ConnectionId, +use ibc_relayer::channel::version::Version as ChannelEndVersion; +use ibc_relayer::channel::{extract_channel_id, Channel, ChannelSide}; +use ibc_relayer_types::core::ics04_channel::channel::{ + ChannelEnd, IdentifiedChannelEnd, Ordering, State as ChannelState, UpgradeState, }; - -use crate::{ - error::Error, - types::{ - id::{ - TaggedChannelId, - TaggedChannelIdRef, - TaggedClientIdRef, - TaggedConnectionIdRef, - TaggedPortId, - TaggedPortIdRef, - }, - tagged::DualTagged, - }, - util::retry::assert_eventually_succeed, +use ibc_relayer_types::core::ics04_channel::packet::Sequence; +use ibc_relayer_types::core::ics04_channel::version::Version; +use ibc_relayer_types::core::ics24_host::identifier::ConnectionId; + +use crate::error::Error; +use crate::types::id::{ + TaggedChannelId, TaggedChannelIdRef, TaggedClientIdRef, TaggedConnectionIdRef, TaggedPortId, + TaggedPortIdRef, }; +use crate::types::tagged::DualTagged; +use crate::util::retry::assert_eventually_succeed; pub trait TaggedChannelEndExt { fn tagged_counterparty_channel_id(&self) -> Option>; @@ -61,6 +39,71 @@ impl TaggedChannelEndExt } } +/// This struct contains the attributes which can be modified with a channel upgrade +pub struct ChannelUpgradableAttributes { + version_a: Version, + version_b: Version, + ordering: Ordering, + connection_hops_a: Vec, + connection_hops_b: Vec, + upgrade_sequence: Sequence, +} + +impl ChannelUpgradableAttributes { + pub fn new( + version_a: Version, + version_b: Version, + ordering: Ordering, + connection_hops_a: Vec, + connection_hops_b: Vec, + upgrade_sequence: Sequence, + ) -> Self { + Self { + version_a, + version_b, + ordering, + connection_hops_a, + connection_hops_b, + upgrade_sequence, + } + } + + pub fn flipped(&self) -> Self { + Self { + version_a: self.version_b.clone(), + version_b: self.version_a.clone(), + ordering: self.ordering, + connection_hops_a: self.connection_hops_b.clone(), + connection_hops_b: self.connection_hops_a.clone(), + upgrade_sequence: self.upgrade_sequence, + } + } + + pub fn version_a(&self) -> &Version { + &self.version_a + } + + pub fn version_b(&self) -> &Version { + &self.version_b + } + + pub fn ordering(&self) -> &Ordering { + &self.ordering + } + + pub fn connection_hops_a(&self) -> &Vec { + &self.connection_hops_a + } + + pub fn connection_hops_b(&self) -> &Vec { + &self.connection_hops_b + } + + pub fn upgrade_sequence(&self) -> &Sequence { + &self.upgrade_sequence + } +} + pub fn init_channel( handle_a: &ChainA, handle_b: &ChainB, @@ -108,7 +151,7 @@ pub fn init_channel_version( connection_id_b: &TaggedConnectionIdRef, src_port_id: &TaggedPortIdRef, dst_port_id: &TaggedPortIdRef, - version: Version, + version: ChannelEndVersion, ) -> Result<(TaggedChannelId, Channel), Error> { let channel = Channel { connection_delay: Default::default(), @@ -208,7 +251,7 @@ pub fn query_channel_end( channel_id: channel_id.into_value().clone(), height: QueryHeight::Latest, }, - IncludeProof::No, + IncludeProof::Yes, )?; Ok(DualTagged::new(channel_end)) @@ -234,6 +277,23 @@ pub fn query_identified_channel_end( ))) } +pub fn query_identified_channel_ends( + handle: &ChainA, +) -> Result>, Error> { + let channel_ends = handle.query_channels(QueryChannelsRequest { pagination: None })?; + let identified_channels = channel_ends + .iter() + .map(|c| { + DualTagged::new(IdentifiedChannelEnd::new( + c.port_id.clone(), + c.channel_id.clone(), + c.channel_end.clone(), + )) + }) + .collect(); + Ok(identified_channels) +} + pub fn assert_eventually_channel_established( handle_a: &ChainA, handle_b: &ChainB, @@ -247,7 +307,10 @@ pub fn assert_eventually_channel_established( + handle_a: &ChainA, + handle_b: &ChainB, + channel_id_a: &TaggedChannelIdRef, + port_id_a: &TaggedPortIdRef, + upgrade_attrs: &ChannelUpgradableAttributes, +) -> Result, Error> { + assert_eventually_succeed( + "channel upgrade should be initialised", + 20, + Duration::from_secs(1), + || { + assert_eventually_succeed( + "channel upgrade should be initialised", + 20, + Duration::from_secs(1), + || { + assert_channel_upgrade_state( + ChannelState::Open(UpgradeState::Upgrading), + ChannelState::Open(UpgradeState::NotUpgrading), + handle_a, + handle_b, + channel_id_a, + port_id_a, + upgrade_attrs, + &Sequence::from(1), + &Sequence::from(0), + ) + }, + ) + }, + ) +} + +pub fn assert_eventually_channel_upgrade_try( + handle_a: &ChainA, + handle_b: &ChainB, + channel_id_a: &TaggedChannelIdRef, + port_id_a: &TaggedPortIdRef, + upgrade_attrs: &ChannelUpgradableAttributes, +) -> Result, Error> { + assert_eventually_succeed( + "channel upgrade try step should be done", + 20, + Duration::from_secs(2), + || { + assert_channel_upgrade_state( + ChannelState::Flushing, + ChannelState::Open(UpgradeState::Upgrading), + handle_a, + handle_b, + channel_id_a, + port_id_a, + upgrade_attrs, + &Sequence::from(1), + &Sequence::from(1), + ) + }, + ) +} + +pub fn assert_eventually_channel_upgrade_ack( + handle_a: &ChainA, + handle_b: &ChainB, + channel_id_a: &TaggedChannelIdRef, + port_id_a: &TaggedPortIdRef, + channel_state_a: ChannelState, + channel_state_b: ChannelState, + upgrade_attrs: &ChannelUpgradableAttributes, +) -> Result, Error> { + assert_eventually_succeed( + "channel upgrade ack step should be done", + 20, + Duration::from_secs(1), + || { + assert_channel_upgrade_state( + channel_state_a, + channel_state_b, + handle_a, + handle_b, + channel_id_a, + port_id_a, + upgrade_attrs, + &Sequence::from(1), + &Sequence::from(1), + ) + }, + ) +} + +pub fn assert_eventually_channel_upgrade_flushing( + handle_a: &ChainA, + handle_b: &ChainB, + channel_id_a: &TaggedChannelIdRef, + port_id_a: &TaggedPortIdRef, + upgrade_attrs: &ChannelUpgradableAttributes, +) -> Result, Error> { + assert_eventually_succeed( + "channel upgrade ack step should be done", + 20, + Duration::from_secs(1), + || { + assert_channel_upgrade_state( + ChannelState::Flushing, + ChannelState::Flushing, + handle_a, + handle_b, + channel_id_a, + port_id_a, + upgrade_attrs, + &Sequence::from(1), + &Sequence::from(1), + ) + }, + ) +} + +pub fn assert_eventually_channel_upgrade_confirm( + handle_a: &ChainA, + handle_b: &ChainB, + channel_id_a: &TaggedChannelIdRef, + port_id_a: &TaggedPortIdRef, + upgrade_attrs: &ChannelUpgradableAttributes, +) -> Result, Error> { + assert_eventually_succeed( + "channel upgrade confirm step should be done", + 20, + Duration::from_secs(1), + || { + assert_channel_upgrade_state( + ChannelState::Open(UpgradeState::NotUpgrading), + ChannelState::FlushComplete, + handle_a, + handle_b, + channel_id_a, + port_id_a, + upgrade_attrs, + &Sequence::from(1), + &Sequence::from(1), + ) + }, + ) +} + +pub fn assert_eventually_channel_upgrade_open( + handle_a: &ChainA, + handle_b: &ChainB, + channel_id_a: &TaggedChannelIdRef, + port_id_a: &TaggedPortIdRef, + upgrade_attrs: &ChannelUpgradableAttributes, +) -> Result, Error> { + assert_eventually_succeed( + "channel upgrade open step should be done", + 20, + Duration::from_secs(1), + || { + assert_channel_upgrade_state( + ChannelState::Open(UpgradeState::NotUpgrading), + ChannelState::Open(UpgradeState::NotUpgrading), + handle_a, + handle_b, + channel_id_a, + port_id_a, + upgrade_attrs, + &Sequence::from(1), + &Sequence::from(1), + ) + }, + ) +} + +pub fn assert_eventually_channel_upgrade_cancel( + handle_a: &ChainA, + handle_b: &ChainB, + channel_id_a: &TaggedChannelIdRef, + port_id_a: &TaggedPortIdRef, + upgrade_attrs: &ChannelUpgradableAttributes, +) -> Result, Error> { + assert_eventually_succeed( + "channel upgrade cancel step should be done", + 20, + Duration::from_secs(1), + || { + assert_channel_upgrade_state( + ChannelState::Open(UpgradeState::NotUpgrading), + ChannelState::Open(UpgradeState::NotUpgrading), + handle_a, + handle_b, + channel_id_a, + port_id_a, + upgrade_attrs, + &Sequence::from(1), + &Sequence::from(1), + ) + }, + ) +} + +/// Note that the field modified by the channel upgrade are only updated when +/// the channel returns in the OPEN State +fn assert_channel_upgrade_state( + a_side_state: ChannelState, + b_side_state: ChannelState, + handle_a: &ChainA, + handle_b: &ChainB, + channel_id_a: &TaggedChannelIdRef, + port_id_a: &TaggedPortIdRef, + upgrade_attrs: &ChannelUpgradableAttributes, + upgrade_sequence_a: &Sequence, + upgrade_sequence_b: &Sequence, +) -> Result, Error> { + let channel_end_a = query_channel_end(handle_a, channel_id_a, port_id_a)?; + + if !channel_end_a.value().state_matches(&a_side_state) { + return Err(Error::generic(eyre!( + "expected channel end A state to be `{}`, but is instead `{}`", + a_side_state, + channel_end_a.value().state() + ))); + } + + if !channel_end_a + .value() + .version_matches(upgrade_attrs.version_a()) + { + return Err(Error::generic(eyre!( + "expected channel end A version to be `{}`, but it is instead `{}`", + upgrade_attrs.version_a(), + channel_end_a.value().version() + ))); + } + + if !channel_end_a + .value() + .order_matches(upgrade_attrs.ordering()) + { + return Err(Error::generic(eyre!( + "expected channel end A ordering to be `{}`, but it is instead `{}`", + upgrade_attrs.ordering(), + channel_end_a.value().ordering() + ))); + } + + if !channel_end_a + .value() + .connection_hops_matches(upgrade_attrs.connection_hops_a()) + { + return Err(Error::generic(eyre!( + "expected channel end A connection hops to be `{:?}`, but it is instead `{:?}`", + upgrade_attrs.connection_hops_a(), + channel_end_a.value().connection_hops() + ))); + } + + if !channel_end_a + .value() + .upgrade_sequence + .eq(upgrade_sequence_a) + { + return Err(Error::generic(eyre!( + "expected channel end A upgrade sequence to be `{}`, but it is instead `{}`", + upgrade_sequence_a, + channel_end_a.value().upgrade_sequence + ))); + } + + let channel_id_b = channel_end_a + .tagged_counterparty_channel_id() + .ok_or_else(|| eyre!("expected counterparty channel id to present on open channel"))?; + + let port_id_b = channel_end_a.tagged_counterparty_port_id(); + + let channel_end_b = query_channel_end(handle_b, &channel_id_b.as_ref(), &port_id_b.as_ref())?; + + if !channel_end_b.value().state_matches(&b_side_state) { + return Err(Error::generic(eyre!( + "expected channel end B state to be `{}`, but is instead `{}`", + b_side_state, + channel_end_b.value().state() + ))); + } + + if !channel_end_b + .value() + .version_matches(upgrade_attrs.version_b()) + { + return Err(Error::generic(eyre!( + "expected channel end B version to be `{}`, but it is instead `{}`", + upgrade_attrs.version_b(), + channel_end_b.value().version() + ))); + } + + if !channel_end_b + .value() + .order_matches(upgrade_attrs.ordering()) + { + return Err(Error::generic(eyre!( + "expected channel end B ordering to be `{}`, but it is instead `{}`", + upgrade_attrs.ordering(), + channel_end_b.value().ordering() + ))); + } + + if !channel_end_b + .value() + .connection_hops_matches(upgrade_attrs.connection_hops_b()) + { + return Err(Error::generic(eyre!( + "expected channel end B connection hops to be `{:?}`, but it is instead `{:?}`", + upgrade_attrs.connection_hops_b(), + channel_end_b.value().connection_hops() + ))); + } + + if !channel_end_b + .value() + .upgrade_sequence + .eq(upgrade_sequence_b) + { + return Err(Error::generic(eyre!( + "expected channel end B upgrade sequence to be `{}`, but it is instead `{}`", + upgrade_sequence_b, + channel_end_b.value().upgrade_sequence + ))); + } + + Ok(channel_id_b) +} diff --git a/tools/test-framework/src/relayer/connection.rs b/tools/test-framework/src/relayer/connection.rs index dde6c477cd..1c9b3d375c 100644 --- a/tools/test-framework/src/relayer/connection.rs +++ b/tools/test-framework/src/relayer/connection.rs @@ -3,44 +3,20 @@ */ use core::time::Duration; - use eyre::eyre; -use ibc_relayer::{ - chain::{ - handle::ChainHandle, - requests::{ - IncludeProof, - QueryConnectionRequest, - QueryHeight, - }, - }, - connection::{ - extract_connection_id, - Connection, - ConnectionSide, - }, -}; -use ibc_relayer_types::{ - core::ics03_connection::connection::{ - ConnectionEnd, - IdentifiedConnectionEnd, - State as ConnectionState, - }, - timestamp::ZERO_DURATION, +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::chain::requests::{IncludeProof, QueryConnectionRequest, QueryHeight}; +use ibc_relayer::connection::{extract_connection_id, Connection, ConnectionSide}; +use ibc_relayer_types::core::ics03_connection::connection::State as ConnectionState; +use ibc_relayer_types::core::ics03_connection::connection::{ + ConnectionEnd, IdentifiedConnectionEnd, }; +use ibc_relayer_types::timestamp::ZERO_DURATION; -use crate::{ - error::Error, - types::{ - id::{ - TaggedClientIdRef, - TaggedConnectionId, - TaggedConnectionIdRef, - }, - tagged::DualTagged, - }, - util::retry::assert_eventually_succeed, -}; +use crate::error::Error; +use crate::types::id::{TaggedClientIdRef, TaggedConnectionId, TaggedConnectionIdRef}; +use crate::types::tagged::DualTagged; +use crate::util::retry::assert_eventually_succeed; /** An extension trait that provide helper methods to get tagged identifiers diff --git a/tools/test-framework/src/relayer/driver.rs b/tools/test-framework/src/relayer/driver.rs index 8db9d79f9c..967df6355b 100644 --- a/tools/test-framework/src/relayer/driver.rs +++ b/tools/test-framework/src/relayer/driver.rs @@ -2,27 +2,15 @@ Driver for spawning the relayer. */ +use ibc_relayer::chain::handle::CountingAndCachingChainHandle; +use ibc_relayer::config::Config; +use ibc_relayer::registry::SharedRegistry; +use ibc_relayer::supervisor::{spawn_supervisor, SupervisorHandle, SupervisorOptions}; use std::path::PathBuf; -use ibc_relayer::{ - chain::handle::CountingAndCachingChainHandle, - config::Config, - registry::SharedRegistry, - supervisor::{ - spawn_supervisor, - SupervisorHandle, - SupervisorOptions, - }, -}; - -use crate::{ - error::Error, - types::env::{ - EnvWriter, - ExportEnv, - }, - util::suspend::hang_on_error, -}; +use crate::error::Error; +use crate::types::env::{EnvWriter, ExportEnv}; +use crate::util::suspend::hang_on_error; /** Encapsulates the parameters needed to spawn the relayer supervisor. diff --git a/tools/test-framework/src/relayer/fee.rs b/tools/test-framework/src/relayer/fee.rs index 288dd3041c..51b1ff6814 100644 --- a/tools/test-framework/src/relayer/fee.rs +++ b/tools/test-framework/src/relayer/fee.rs @@ -1,58 +1,27 @@ use core::time::Duration; - use http::uri::Uri; -use ibc_relayer::{ - chain::cosmos::{ - query::fee::{ - query_counterparty_payee as raw_query_counterparty_payee, - query_incentivized_packets as raw_query_incentivized_packets, - }, - tx::simple_send_tx, - types::config::TxConfig, - }, - event::IbcEventWithHeight, +use ibc_relayer::chain::cosmos::query::fee::{ + query_counterparty_payee as raw_query_counterparty_payee, + query_incentivized_packets as raw_query_incentivized_packets, }; -use ibc_relayer_types::{ - applications::ics29_fee::{ - msgs::{ - pay_packet::build_pay_packet_message, - pay_packet_async::build_pay_packet_fee_async_message, - register_payee::{ - build_register_counterparty_payee_message, - build_register_payee_message, - }, - }, - packet_fee::IdentifiedPacketFees, - }, - core::ics04_channel::packet::Sequence, +use ibc_relayer::chain::cosmos::tx::simple_send_tx; +use ibc_relayer::chain::cosmos::types::config::TxConfig; +use ibc_relayer::event::IbcEventWithHeight; +use ibc_relayer_types::applications::ics29_fee::msgs::pay_packet::build_pay_packet_message; +use ibc_relayer_types::applications::ics29_fee::msgs::pay_packet_async::build_pay_packet_fee_async_message; +use ibc_relayer_types::applications::ics29_fee::msgs::register_payee::{ + build_register_counterparty_payee_message, build_register_payee_message, }; +use ibc_relayer_types::applications::ics29_fee::packet_fee::IdentifiedPacketFees; +use ibc_relayer_types::core::ics04_channel::packet::Sequence; use tendermint_rpc::HttpClient; -use crate::{ - error::{ - handle_generic_error, - Error, - }, - ibc::token::{ - TaggedTokenExt, - TaggedTokenRef, - }, - relayer::transfer::build_transfer_message, - types::{ - id::{ - TaggedChannelIdRef, - TaggedPortIdRef, - }, - tagged::{ - DualTagged, - MonoTagged, - }, - wallet::{ - Wallet, - WalletAddress, - }, - }, -}; +use crate::error::{handle_generic_error, Error}; +use crate::ibc::token::{TaggedTokenExt, TaggedTokenRef}; +use crate::relayer::transfer::build_transfer_message; +use crate::types::id::{TaggedChannelIdRef, TaggedPortIdRef}; +use crate::types::tagged::{DualTagged, MonoTagged}; +use crate::types::wallet::{Wallet, WalletAddress}; pub async fn ibc_token_transfer_with_fee( rpc_client: MonoTagged, diff --git a/tools/test-framework/src/relayer/foreign_client.rs b/tools/test-framework/src/relayer/foreign_client.rs index 74b4bfec00..beb94641cc 100644 --- a/tools/test-framework/src/relayer/foreign_client.rs +++ b/tools/test-framework/src/relayer/foreign_client.rs @@ -2,18 +2,11 @@ Definition for extension trait methods for [`ForeignClient`] */ -use ibc_relayer::{ - chain::handle::ChainHandle, - foreign_client::ForeignClient, -}; - -use crate::types::{ - id::{ - TaggedChainId, - TaggedClientIdRef, - }, - tagged::*, -}; +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::foreign_client::ForeignClient; + +use crate::types::id::{TaggedChainId, TaggedClientIdRef}; +use crate::types::tagged::*; /** An extension trait for providing methods for getting tagged identifiers diff --git a/tools/test-framework/src/relayer/refresh.rs b/tools/test-framework/src/relayer/refresh.rs index 364474835f..04f373548e 100644 --- a/tools/test-framework/src/relayer/refresh.rs +++ b/tools/test-framework/src/relayer/refresh.rs @@ -1,14 +1,10 @@ use eyre::eyre; -use ibc_relayer::{ - chain::handle::ChainHandle, - util::task::TaskHandle, - worker::client::spawn_refresh_client, -}; +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::util::task::TaskHandle; +use ibc_relayer::worker::client::spawn_refresh_client; -use crate::{ - error::Error, - types::binary::foreign_client::ForeignClientPair, -}; +use crate::error::Error; +use crate::types::binary::foreign_client::ForeignClientPair; pub fn spawn_refresh_client_tasks( foreign_clients: &ForeignClientPair, diff --git a/tools/test-framework/src/relayer/transfer.rs b/tools/test-framework/src/relayer/transfer.rs index 8b086aadb1..26595051a5 100644 --- a/tools/test-framework/src/relayer/transfer.rs +++ b/tools/test-framework/src/relayer/transfer.rs @@ -3,55 +3,28 @@ `hermes tx ft-transfer`. */ -use core::{ - ops::Add, - time::Duration, -}; - +use core::ops::Add; +use core::time::Duration; use eyre::eyre; +use ibc_relayer_types::core::ics04_channel::packet::Packet; +use ibc_relayer_types::events::IbcEvent; + use ibc_proto::google::protobuf::Any; -use ibc_relayer::{ - chain::cosmos::{ - tx::{ - batched_send_tx, - simple_send_tx, - }, - types::config::TxConfig, - }, - transfer::{ - build_transfer_message as raw_build_transfer_message, - TransferError, - }, -}; -use ibc_relayer_types::{ - applications::transfer::error::Error as Ics20Error, - core::ics04_channel::{ - packet::Packet, - timeout::TimeoutHeight, - }, - events::IbcEvent, - timestamp::Timestamp, -}; +use ibc_relayer::chain::cosmos::tx::batched_send_tx; +use ibc_relayer::chain::cosmos::tx::simple_send_tx; +use ibc_relayer::chain::cosmos::types::config::TxConfig; +use ibc_relayer::transfer::build_transfer_message as raw_build_transfer_message; +use ibc_relayer::transfer::TransferError; +use ibc_relayer_types::applications::transfer::error::Error as Ics20Error; +use ibc_relayer_types::core::ics04_channel::timeout::TimeoutHeight; +use ibc_relayer_types::timestamp::Timestamp; use tendermint_rpc::HttpClient; -use crate::{ - error::{ - handle_generic_error, - Error, - }, - ibc::token::TaggedTokenRef, - types::{ - id::{ - TaggedChannelIdRef, - TaggedPortIdRef, - }, - tagged::*, - wallet::{ - Wallet, - WalletAddress, - }, - }, -}; +use crate::error::{handle_generic_error, Error}; +use crate::ibc::token::TaggedTokenRef; +use crate::types::id::{TaggedChannelIdRef, TaggedPortIdRef}; +use crate::types::tagged::*; +use crate::types::wallet::{Wallet, WalletAddress}; pub fn build_transfer_message( port_id: &TaggedPortIdRef<'_, SrcChain, DstChain>, diff --git a/tools/test-framework/src/relayer/tx.rs b/tools/test-framework/src/relayer/tx.rs index 6950c5f88e..90f62a09fb 100644 --- a/tools/test-framework/src/relayer/tx.rs +++ b/tools/test-framework/src/relayer/tx.rs @@ -1,32 +1,21 @@ -use core::{ - str::FromStr, - time::Duration, -}; +use core::str::FromStr; +use core::time::Duration; use http::uri::Uri; + use ibc_proto::cosmos::tx::v1beta1::Fee; -use ibc_relayer::{ - chain::cosmos::{ - gas::calculate_fee, - types::{ - config::TxConfig, - gas::GasConfig, - }, - }, - config::{ - AddressType, - GasPrice, - }, -}; +use ibc_relayer::chain::cosmos::gas::calculate_fee; +use ibc_relayer::chain::cosmos::types::config::TxConfig; +use ibc_relayer::chain::cosmos::types::gas::GasConfig; +use ibc_relayer::config::dynamic_gas::DynamicGasPrice; +use ibc_relayer::config::{AddressType, GasPrice}; use ibc_relayer_types::core::ics24_host::identifier::ChainId; use tendermint_rpc::Url; -use crate::error::{ - handle_generic_error, - Error, -}; +use crate::chain::chain_type::ChainType; +use crate::error::{handle_generic_error, Error}; -pub fn gas_config_for_test(native_token: String) -> GasConfig { +pub fn gas_config_for_test(native_token: String, chain_type: ChainType) -> GasConfig { let max_gas = 3000000; let gas_multiplier = 1.5; @@ -49,6 +38,12 @@ pub fn gas_config_for_test(native_token: String) -> GasConfig { granter: fee_granter.clone(), }; + let dynamic_gas_price = if chain_type.enable_dynamic_fee() { + DynamicGasPrice::unsafe_new(true, 1.3, 5.0) + } else { + DynamicGasPrice::disabled() + }; + GasConfig { default_gas, max_gas, @@ -56,11 +51,13 @@ pub fn gas_config_for_test(native_token: String) -> GasConfig { gas_price, max_fee, fee_granter, + dynamic_gas_price, } } pub fn new_tx_config_for_test( chain_id: ChainId, + chain_type: ChainType, raw_rpc_address: String, raw_grpc_address: String, address_type: AddressType, @@ -68,7 +65,7 @@ pub fn new_tx_config_for_test( ) -> 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(native_token); + let gas_config = gas_config_for_test(native_token, chain_type); 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 bcf87999c8..f195866e17 100644 --- a/tools/test-framework/src/types/binary/chains.rs +++ b/tools/test-framework/src/types/binary/chains.rs @@ -6,22 +6,10 @@ use ibc_relayer::chain::handle::ChainHandle; use tracing::info; use super::foreign_client::ForeignClientPair; -use crate::types::{ - env::{ - prefix_writer, - EnvWriter, - ExportEnv, - }, - id::{ - TaggedChainIdRef, - TaggedClientIdRef, - }, - single::node::{ - FullNode, - TaggedFullNodeExt, - }, - tagged::*, -}; +use crate::types::env::{prefix_writer, EnvWriter, ExportEnv}; +use crate::types::id::{TaggedChainIdRef, TaggedClientIdRef}; +use crate::types::single::node::{FullNode, TaggedFullNodeExt}; +use crate::types::tagged::*; /** Two connected chains including the full node, chain handles, and diff --git a/tools/test-framework/src/types/binary/channel.rs b/tools/test-framework/src/types/binary/channel.rs index 0f4e243c52..99f5bb2e84 100644 --- a/tools/test-framework/src/types/binary/channel.rs +++ b/tools/test-framework/src/types/binary/channel.rs @@ -2,22 +2,12 @@ Type definitions for channel connected between two chains. */ -use ibc_relayer::{ - chain::handle::ChainHandle, - channel::Channel, -}; +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::channel::Channel; use super::connection::ConnectedConnection; -use crate::types::{ - env::{ - EnvWriter, - ExportEnv, - }, - id::{ - TaggedChannelId, - TaggedPortId, - }, -}; +use crate::types::env::{EnvWriter, ExportEnv}; +use crate::types::id::{TaggedChannelId, TaggedPortId}; /** A channel that is connected between two chains with the full handshake diff --git a/tools/test-framework/src/types/binary/client.rs b/tools/test-framework/src/types/binary/client.rs index 933ed4371e..87d5032436 100644 --- a/tools/test-framework/src/types/binary/client.rs +++ b/tools/test-framework/src/types/binary/client.rs @@ -2,13 +2,8 @@ Type definitions for IBC clients connected between two chains. */ -use crate::types::{ - env::{ - EnvWriter, - ExportEnv, - }, - id::TaggedClientId, -}; +use crate::types::env::{EnvWriter, ExportEnv}; +use crate::types::id::TaggedClientId; /** Data type to store the client IDs of two chains that are connected. diff --git a/tools/test-framework/src/types/binary/connection.rs b/tools/test-framework/src/types/binary/connection.rs index a67027735c..34455c3e83 100644 --- a/tools/test-framework/src/types/binary/connection.rs +++ b/tools/test-framework/src/types/binary/connection.rs @@ -2,19 +2,12 @@ Type definitions for connection that is connected between two chains. */ -use ibc_relayer::{ - chain::handle::ChainHandle, - connection::Connection, -}; +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::connection::Connection; use super::client::ClientIdPair; -use crate::types::{ - env::{ - EnvWriter, - ExportEnv, - }, - id::TaggedConnectionId, -}; +use crate::types::env::{EnvWriter, ExportEnv}; +use crate::types::id::TaggedConnectionId; /** A connection that is connected between two chains with the full diff --git a/tools/test-framework/src/types/binary/foreign_client.rs b/tools/test-framework/src/types/binary/foreign_client.rs index 37f1fb8172..e399fd1bfd 100644 --- a/tools/test-framework/src/types/binary/foreign_client.rs +++ b/tools/test-framework/src/types/binary/foreign_client.rs @@ -1,12 +1,7 @@ -use ibc_relayer::{ - chain::handle::ChainHandle, - foreign_client::ForeignClient, -}; - -use crate::{ - relayer::foreign_client::TaggedForeignClientExt, - types::id::TaggedClientIdRef, -}; +use crate::relayer::foreign_client::TaggedForeignClientExt; +use crate::types::id::TaggedClientIdRef; +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::foreign_client::ForeignClient; #[derive(Clone)] pub struct ForeignClientPair { diff --git a/tools/test-framework/src/types/config.rs b/tools/test-framework/src/types/config.rs index ea3944b3f5..a586c46e84 100644 --- a/tools/test-framework/src/types/config.rs +++ b/tools/test-framework/src/types/config.rs @@ -63,3 +63,9 @@ pub struct TestConfig { pub bootstrap_with_random_ids: bool, } + +impl TestConfig { + pub fn native_token(&self, id: usize) -> &String { + &self.native_tokens[id % self.native_tokens.len()] + } +} diff --git a/tools/test-framework/src/types/env.rs b/tools/test-framework/src/types/env.rs index b92fa16cff..7028aa8b32 100644 --- a/tools/test-framework/src/types/env.rs +++ b/tools/test-framework/src/types/env.rs @@ -2,19 +2,13 @@ Types for exporting test setup information into environment variables. */ -use core::convert::AsRef; -use std::{ - collections::BTreeMap, - fs::write, - path::Path, -}; - use itertools::Itertools; +use std::collections::BTreeMap; +use std::fs::write; +use std::path::Path; -use crate::{ - error::Error, - types::tagged::*, -}; +use crate::error::Error; +use crate::types::tagged::*; /** This trait is implemented by data types that can export the contained diff --git a/tools/test-framework/src/types/id.rs b/tools/test-framework/src/types/id.rs index f608141fde..d103a7ab5b 100644 --- a/tools/test-framework/src/types/id.rs +++ b/tools/test-framework/src/types/id.rs @@ -3,9 +3,8 @@ identifier types defined in [`ibc_relayer_types::core::ics24_host::identifier`]. */ -use ibc_relayer_types::core::ics24_host::identifier::*; - use crate::types::tagged::*; +use ibc_relayer_types::core::ics24_host::identifier::*; /** A [`ChainId`] tagged with the chain it belongs to. diff --git a/tools/test-framework/src/types/mod.rs b/tools/test-framework/src/types/mod.rs index a1c1db153d..a107f96d7c 100644 --- a/tools/test-framework/src/types/mod.rs +++ b/tools/test-framework/src/types/mod.rs @@ -16,4 +16,5 @@ pub mod nary; pub mod process; pub mod single; pub mod tagged; +pub mod topology; pub mod wallet; diff --git a/tools/test-framework/src/types/nary/chains.rs b/tools/test-framework/src/types/nary/chains.rs index 1148789f5e..9f727710a5 100644 --- a/tools/test-framework/src/types/nary/chains.rs +++ b/tools/test-framework/src/types/nary/chains.rs @@ -2,41 +2,26 @@ Constructs for N-ary connected chains. */ -use core::convert::{ - From, - TryFrom, -}; - use eyre::eyre; -use ibc_relayer::{ - chain::handle::ChainHandle, - foreign_client::ForeignClient, -}; - -use crate::{ - error::Error, - types::{ - binary::chains::ConnectedChains as BinaryConnectedChains, - env::{ - prefix_writer, - EnvWriter, - ExportEnv, - }, - nary::{ - aliases::*, - foreign_client::*, - }, - single::node::FullNode, - tagged::*, - }, - util::array::try_into_array, -}; +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::foreign_client::ForeignClient; + +use crate::error::Error; +use crate::types::binary::chains::ConnectedChains as BinaryConnectedChains; +use crate::types::env::{prefix_writer, EnvWriter, ExportEnv}; +use crate::types::nary::aliases::*; +use crate::types::nary::foreign_client::*; +use crate::types::single::node::FullNode; +use crate::types::tagged::*; +use crate::util::array::try_into_array; +use crate::util::two_dim_hash_map::TwoDimMap; /** A fixed-size N-ary connected chains as specified by `SIZE`. Contains `SIZE` number of [`ChainHandle`]s, `SIZE` number of - [`FullNode`]s, and `SIZE`x`SIZE` numbers of [`ForeignClient`] pairs. + [`FullNode`]s, and a numbers of [`ForeignClient`] pairs + depending on `SIZE` and the topology. A `ConnectedChains` can be constructed by first constructing a [`DynamicConnectedChains`], and then calling @@ -61,7 +46,7 @@ pub struct NaryConnectedChains { pub struct DynamicConnectedChains { chain_handles: Vec, full_nodes: Vec, - pub foreign_clients: Vec>>, + pub foreign_clients: TwoDimMap>, } /** @@ -199,7 +184,7 @@ impl DynamicConnectedChains { pub fn new( chain_handles: Vec, full_nodes: Vec, - foreign_clients: Vec>>, + foreign_clients: TwoDimMap>, ) -> Self { Self { chain_handles, @@ -216,7 +201,7 @@ impl DynamicConnectedChains { &self.full_nodes } - pub fn foreign_clients(&self) -> &Vec>> { + pub fn foreign_clients(&self) -> &TwoDimMap> { &self.foreign_clients } } diff --git a/tools/test-framework/src/types/nary/channel.rs b/tools/test-framework/src/types/nary/channel.rs index 0a9f252747..097c1579d2 100644 --- a/tools/test-framework/src/types/nary/channel.rs +++ b/tools/test-framework/src/types/nary/channel.rs @@ -1,51 +1,38 @@ /*! Constructs for N-ary connected channels. */ - -use core::convert::TryFrom; - use eyre::eyre; -use ibc_relayer::{ - chain::handle::ChainHandle, - channel::Channel, -}; -use ibc_relayer_types::core::ics24_host::identifier::{ - ChannelId, - PortId, -}; +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::channel::Channel; +use ibc_relayer_types::core::ics24_host::identifier::{ChannelId, PortId}; use super::aliases::NthChainHandle; -use crate::{ - error::Error, - types::{ - binary::channel::ConnectedChannel, - env::{ - EnvWriter, - ExportEnv, - }, - tagged::*, - }, - util::array::try_into_nested_array, -}; +use crate::error::Error; +use crate::types::binary::channel::ConnectedChannel; +use crate::types::env::{EnvWriter, ExportEnv}; +use crate::types::tagged::*; +use crate::util::two_dim_hash_map::TwoDimMap; /** - A fixed-size N-ary connected channels as specified by `SIZE`. + A two dimensional BTreeMap of connected channels as specified by `SIZE` + and topology. - Contains `SIZE`x`SIZE` number of binary [`ConnectedChannel`]s. + The number of binary [`ConnectedChannel`]s depends on the topology. */ #[derive(Debug, Clone)] pub struct ConnectedChannels { - channels: [[ConnectedChannel; SIZE]; SIZE], + pub channels: TwoDimMap>, } /** - A dynamic-sized N-ary connected channels, consist of a nested - vector of binary [`ConnectedChannel`]s which must be of the - same length. + A two dimensional BTreeMap of connected channels as specified by `SIZE` + and topology. + + The number of binary [`ConnectedChannel`]s depends on the topology. */ #[derive(Debug, Clone)] pub struct DynamicConnectedChannels { - channels: Vec>>, + channels: TwoDimMap>, } /** @@ -84,32 +71,31 @@ impl ConnectedChannels { pub fn channel_at( &self, ) -> Result, Error> { - if CHAIN_A >= SIZE || CHAIN_B >= SIZE { - Err(Error::generic(eyre!( - "cannot get channel beyond position {}/{}", - CHAIN_A, - CHAIN_B - ))) - } else { - let raw_channel = self.channels[CHAIN_A][CHAIN_B].clone(); - - let channel = raw_channel.map_chain(MonoTagged::new, MonoTagged::new); - - Ok(channel) - } + let raw_channel = self + .channels + .get((CHAIN_A, CHAIN_B)) + .ok_or_else(|| { + Error::generic(eyre!( + "No channel entry found for chain `{CHAIN_A}` to `{CHAIN_B}`" + )) + })? + .clone(); + let channel = raw_channel.map_chain(MonoTagged::new, MonoTagged::new); + + Ok(channel) } - pub fn channels(&self) -> &[[ConnectedChannel; SIZE]; SIZE] { + pub fn channels(&self) -> &TwoDimMap> { &self.channels } } impl DynamicConnectedChannels { - pub fn new(channels: Vec>>) -> Self { + pub fn new(channels: TwoDimMap>) -> Self { Self { channels } } - pub fn channels(&self) -> &Vec>> { + pub fn channels(&self) -> &TwoDimMap> { &self.channels } } @@ -121,7 +107,7 @@ impl TryFrom) -> Result { Ok(ConnectedChannels { - channels: try_into_nested_array(channels.channels)?, + channels: channels.channels, }) } } @@ -134,38 +120,21 @@ impl From> for NthConnectedCha impl ExportEnv for ConnectedChannels { fn export_env(&self, writer: &mut impl EnvWriter) { - for (i, inner_channels) in self.channels.iter().enumerate() { - for (j, channel_i_to_j) in inner_channels.iter().enumerate() { - writer.write_env( - &format!("CONNECTION_ID_{j}_to_{i}"), - &format!("{}", channel_i_to_j.connection.connection_id_a), - ); - - writer.write_env( - &format!("CONNECTION_ID_{i}_to_{j}"), - &format!("{}", channel_i_to_j.connection.connection_id_b), - ); - - writer.write_env( - &format!("CHANNEL_ID_{j}_to_{i}"), - &format!("{}", channel_i_to_j.channel_id_a), - ); - - writer.write_env( - &format!("PORT_{j}_to_{i}"), - &format!("{}", channel_i_to_j.port_a), - ); - - writer.write_env( - &format!("CHANNEL_ID_{i}_to_{j}"), - &format!("{}", channel_i_to_j.channel_id_b), - ); - - writer.write_env( - &format!("PORT_{i}_to_{j}"), - &format!("{}", channel_i_to_j.port_b), - ); - } + for (src_chain, dst_chain, channel) in self.channels.iter() { + writer.write_env( + &format!("CONNECTION_ID_{}_to_{}", src_chain, dst_chain), + &format!("{}", channel.connection.connection_id_a), + ); + + writer.write_env( + &format!("CHANNEL_ID_{}_to_{}", src_chain, dst_chain), + &format!("{}", channel.channel_id_a), + ); + + writer.write_env( + &format!("PORT_{}_to_{}", src_chain, dst_chain), + &format!("{}", channel.port_a), + ); } } } diff --git a/tools/test-framework/src/types/nary/connection.rs b/tools/test-framework/src/types/nary/connection.rs index a86e458a75..31c5b0e2d8 100644 --- a/tools/test-framework/src/types/nary/connection.rs +++ b/tools/test-framework/src/types/nary/connection.rs @@ -1,48 +1,37 @@ /*! Constructs for N-ary connected connections. */ - -use core::convert::TryFrom; - use eyre::eyre; use ibc_relayer::chain::handle::ChainHandle; use ibc_relayer_types::core::ics24_host::identifier::ConnectionId; use super::aliases::NthChainHandle; -use crate::{ - error::Error, - types::{ - binary::connection::ConnectedConnection, - env::{ - EnvWriter, - ExportEnv, - }, - tagged::*, - }, - util::array::{ - into_nested_vec, - try_into_nested_array, - }, -}; +use crate::error::Error; +use crate::types::binary::connection::ConnectedConnection; +use crate::types::env::{EnvWriter, ExportEnv}; +use crate::types::tagged::*; +use crate::util::two_dim_hash_map::TwoDimMap; /** - A fixed-size N-ary connected connections as specified by `SIZE`. + A two dimensional BTreeMap of connected connections as specified by `SIZE` + and topology. - Contains `SIZE`x`SIZE` number of binary [`ConnectedConnection`]s. + The number of binary [`ConnectedConnection`]s depends on the topology. */ #[derive(Debug, Clone)] pub struct ConnectedConnections { - connections: [[ConnectedConnection; SIZE]; SIZE], + connections: TwoDimMap>, } /** - A dynamic-sized N-ary connected connections, made of a - nested vector of binary [`ConnectedConnection`] which must be - in the same dimension. + A two dimensional BTreeMap of connected connections as specified by `SIZE` + and topology. + + The number of binary [`ConnectedConnection`]s depends on the topology. */ #[derive(Debug, Clone)] pub struct DynamicConnectedConnections { - connections: Vec>>, + connections: TwoDimMap>, } /** @@ -67,32 +56,31 @@ impl ConnectedConnections pub fn connection_at( &self, ) -> Result, Error> { - if CHAIN_A >= SIZE || CHAIN_B >= SIZE { - Err(Error::generic(eyre!( - "cannot get connection beyond position {}/{}", - CHAIN_A, - CHAIN_B - ))) - } else { - let raw_connection = self.connections[CHAIN_A][CHAIN_B].clone(); - - let channel = raw_connection.map_chain(MonoTagged::new, MonoTagged::new); - - Ok(channel) - } + let raw_connection = self + .connections + .get((CHAIN_A, CHAIN_B)) + .ok_or_else(|| { + Error::generic(eyre!( + "No connection entry found for chain `{CHAIN_A}` to `{CHAIN_B}`" + )) + })? + .clone(); + let connection = raw_connection.map_chain(MonoTagged::new, MonoTagged::new); + + Ok(connection) } - pub fn connections(&self) -> &[[ConnectedConnection; SIZE]; SIZE] { + pub fn connections(&self) -> &TwoDimMap> { &self.connections } } impl DynamicConnectedConnections { - pub fn new(connections: Vec>>) -> Self { + pub fn new(connections: TwoDimMap>) -> Self { Self { connections } } - pub fn connections(&self) -> &Vec>> { + pub fn connections(&self) -> &TwoDimMap> { &self.connections } } @@ -102,7 +90,7 @@ impl From) -> Self { DynamicConnectedConnections { - connections: into_nested_vec(connections.connections), + connections: connections.connections, } } } @@ -114,7 +102,7 @@ impl TryFrom) -> Result { Ok(ConnectedConnections { - connections: try_into_nested_array(connections.connections)?, + connections: connections.connections, }) } } @@ -129,18 +117,11 @@ impl From> impl ExportEnv for ConnectedConnections { fn export_env(&self, writer: &mut impl EnvWriter) { - for (i, inner_connections) in self.connections.iter().enumerate() { - for (j, connection_i_to_j) in inner_connections.iter().enumerate() { - writer.write_env( - &format!("CONNECTION_ID_{j}_to_{i}"), - &format!("{}", connection_i_to_j.connection_id_a), - ); - - writer.write_env( - &format!("CONNECTION_ID_{i}_to_{j}"), - &format!("{}", connection_i_to_j.connection_id_b), - ); - } + for (src_chain, dst_chain, connection) in self.connections.iter() { + writer.write_env( + &format!("CONNECTION_ID_{}_to_{}", src_chain, dst_chain), + &format!("{}", connection.connection_id_a), + ); } } } diff --git a/tools/test-framework/src/types/nary/foreign_client.rs b/tools/test-framework/src/types/nary/foreign_client.rs index 409c0c5d75..a9dfd4cd46 100644 --- a/tools/test-framework/src/types/nary/foreign_client.rs +++ b/tools/test-framework/src/types/nary/foreign_client.rs @@ -1,27 +1,13 @@ -use core::convert::TryFrom; - use eyre::eyre; -use ibc_relayer::{ - chain::handle::ChainHandle, - foreign_client::ForeignClient, -}; +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::foreign_client::ForeignClient; use super::aliases::NthChainHandle; -use crate::{ - error::Error, - types::{ - binary::foreign_client::ForeignClientPair, - env::{ - EnvWriter, - ExportEnv, - }, - tagged::*, - }, - util::array::{ - into_nested_vec, - try_into_nested_array, - }, -}; +use crate::error::Error; +use crate::types::binary::foreign_client::ForeignClientPair; +use crate::types::env::{EnvWriter, ExportEnv}; +use crate::types::tagged::*; +use crate::util::two_dim_hash_map::TwoDimMap; /** A [`ForeignClient`] that is tagged by a `Handle: ChainHandle` and @@ -35,7 +21,7 @@ pub type NthForeignClientPair = #[derive(Clone)] pub struct ForeignClientPairs { - foreign_clients: [[ForeignClient; SIZE]; SIZE], + foreign_clients: TwoDimMap>, } impl ForeignClientPairs { @@ -47,19 +33,15 @@ impl ForeignClientPairs { pub fn foreign_client_at( &self, ) -> Result, Error> { - if SRC >= SIZE || DEST >= SIZE { - Err(Error::generic(eyre!( - "cannot get foreign client beyond position {}/{}", - SRC, - DEST - ))) - } else { - let client = self.foreign_clients[SRC][DEST] - .clone() - .map_chain(MonoTagged::new, MonoTagged::new); - - Ok(client) - } + let client = self + .foreign_clients + .get((SRC, DEST)) + .ok_or_else(|| { + Error::generic(eyre!("No client entry found for chain `{SRC}` to `{DEST}`")) + })? + .clone() + .map_chain(MonoTagged::new, MonoTagged::new); + Ok(client) } pub fn foreign_client_pair_at( @@ -71,31 +53,29 @@ impl ForeignClientPairs { Ok(ForeignClientPair::new(client_a_to_b, client_b_to_a)) } - pub fn into_nested_vec(self) -> Vec>> { - into_nested_vec(self.foreign_clients) + pub fn into_nested_vec(self) -> TwoDimMap> { + self.foreign_clients } } -impl TryFrom>>> +impl TryFrom>> for ForeignClientPairs { type Error = Error; - fn try_from(clients: Vec>>) -> Result { - let foreign_clients = try_into_nested_array(clients)?; + fn try_from(clients: TwoDimMap>) -> Result { + let foreign_clients = clients; Ok(Self { foreign_clients }) } } impl ExportEnv for ForeignClientPairs { fn export_env(&self, writer: &mut impl EnvWriter) { - for (source, inner_clients) in self.foreign_clients.iter().enumerate() { - for (destination, client) in inner_clients.iter().enumerate() { - writer.write_env( - &format!("CLIENT_ID_{source}_to_{destination}"), - &format!("{}", client.id()), - ); - } + for (src_chain, dst_chain, client) in self.foreign_clients.iter() { + writer.write_env( + &format!("CLIENT_ID_{}_to_{}", src_chain, dst_chain), + &format!("{}", client.id()), + ); } } } diff --git a/tools/test-framework/src/types/process.rs b/tools/test-framework/src/types/process.rs index fdab93b5b5..1f32e53950 100644 --- a/tools/test-framework/src/types/process.rs +++ b/tools/test-framework/src/types/process.rs @@ -3,9 +3,8 @@ child process when the value is dropped. */ -use std::process::Child; - use eyre::Report as Error; +use std::process::Child; /** A lightweight wrapper around std::process::Child to ensure that the diff --git a/tools/test-framework/src/types/single/node.rs b/tools/test-framework/src/types/single/node.rs index 9e386964af..ae4d0f34bb 100644 --- a/tools/test-framework/src/types/single/node.rs +++ b/tools/test-framework/src/types/single/node.rs @@ -2,52 +2,31 @@ Type definition for a single running full node. */ -use core::{ - str::FromStr, - time::Duration, -}; -use std::sync::{ - Arc, - RwLock, -}; - -use eyre::{ - eyre, - Report as Error, -}; -use ibc_relayer::{ - chain::cosmos::config::CosmosSdkConfig, - config, - config::{ - compat_mode::CompatMode, - gas_multiplier::GasMultiplier, - }, - keyring::Store, -}; +use core::str::FromStr; +use core::time::Duration; +use eyre::eyre; +use eyre::Report as Error; +use ibc_relayer::chain::cosmos::config::CosmosSdkConfig; +use ibc_relayer::config; +use ibc_relayer::config::compat_mode::CompatMode; +use ibc_relayer::config::dynamic_gas::DynamicGasPrice; +use ibc_relayer::config::gas_multiplier::GasMultiplier; +use ibc_relayer::keyring::Store; +use ibc_relayer::util::excluded_sequences::ExcludedSequences; use ibc_relayer_types::core::ics24_host::identifier::ChainId; -use tendermint_rpc::{ - Url, - WebSocketClientUrl, -}; - -use crate::{ - chain::{ - chain_type::ChainType as TestedChainType, - driver::ChainDriver, - }, - ibc::denom::Denom, - prelude::TestConfig, - types::{ - env::{ - prefix_writer, - EnvWriter, - ExportEnv, - }, - process::ChildProcess, - tagged::*, - wallet::TestWallets, - }, -}; +use std::collections::BTreeMap; +use std::sync::{Arc, RwLock}; +use tendermint_rpc::Url; +use tendermint_rpc::WebSocketClientUrl; + +use crate::chain::chain_type::ChainType as TestedChainType; +use crate::chain::driver::ChainDriver; +use crate::ibc::denom::Denom; +use crate::prelude::TestConfig; +use crate::types::env::{prefix_writer, EnvWriter, ExportEnv}; +use crate::types::process::ChildProcess; +use crate::types::tagged::*; +use crate::types::wallet::TestWallets; pub type TaggedFullNode = MonoTagged; @@ -153,7 +132,6 @@ impl FullNode { 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") @@ -168,14 +146,16 @@ impl FullNode { // 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(), - ), + TestedChainType::Provenance => { + config::GasPrice::new(5000.0, test_config.native_token(chain_number).clone()) + } + _ => config::GasPrice::new(0.003, test_config.native_token(chain_number).clone()), + }; + + let dynamic_gas_price = if chain_type.enable_dynamic_fee() { + DynamicGasPrice::unsafe_new(true, 1.3, 5.0) + } else { + DynamicGasPrice::disabled() }; Ok(config::ChainConfig::CosmosSdk(CosmosSdkConfig { @@ -198,6 +178,7 @@ impl FullNode { max_gas: Some(3000000), gas_adjustment: None, gas_multiplier: Some(GasMultiplier::unsafe_new(1.5)), + dynamic_gas_price, fee_granter: None, max_msg_num: Default::default(), max_tx_size: Default::default(), @@ -213,11 +194,14 @@ impl FullNode { packet_filter: Default::default(), address_type: chain_type.address_type(), memo_prefix: Default::default(), + memo_overwrite: None, proof_specs: Default::default(), extension_options: Default::default(), sequential_batch_tx: false, compat_mode, clear_interval: None, + excluded_sequences: ExcludedSequences::new(BTreeMap::new()), + allow_ccq: true, })) } diff --git a/tools/test-framework/src/types/tagged/dual.rs b/tools/test-framework/src/types/tagged/dual.rs index 65912d11b4..605f15820c 100644 --- a/tools/test-framework/src/types/tagged/dual.rs +++ b/tools/test-framework/src/types/tagged/dual.rs @@ -12,25 +12,9 @@ corresponds to a channel connected to a counterparty chain `ChainB`. */ -use core::{ - cmp::{ - Eq, - Ord, - Ordering, - PartialEq, - PartialOrd, - }, - fmt::{ - self, - Debug, - Display, - }, - iter::{ - IntoIterator, - Iterator, - }, - marker::PhantomData, -}; +use core::cmp::Ordering; +use core::fmt::{self, Debug, Display}; +use core::marker::PhantomData; /** Tag a `Value` type with a two type tags `TagA` and `TagB`. diff --git a/tools/test-framework/src/types/tagged/mod.rs b/tools/test-framework/src/types/tagged/mod.rs index 50f75dc6ca..fed89701e2 100644 --- a/tools/test-framework/src/types/tagged/mod.rs +++ b/tools/test-framework/src/types/tagged/mod.rs @@ -70,7 +70,7 @@ a `ChannelId` value that is used on `ChainA` to identify a channel that is connected to `ChainB`. With the tagged identifier, it is more unlikely for us to accidentally use the `ChannelId` coming from - counterparty chain, as it would have the the type + counterparty chain, as it would have the type `DualTagged` and thus result in type error. diff --git a/tools/test-framework/src/types/tagged/mono.rs b/tools/test-framework/src/types/tagged/mono.rs index 24e989f1ed..a1e8a1f448 100644 --- a/tools/test-framework/src/types/tagged/mono.rs +++ b/tools/test-framework/src/types/tagged/mono.rs @@ -17,30 +17,10 @@ */ -use core::{ - cmp::{ - Eq, - Ord, - Ordering, - PartialEq, - PartialOrd, - }, - fmt::{ - self, - Debug, - Display, - }, - iter::{ - IntoIterator, - Iterator, - }, - marker::PhantomData, -}; - -use serde::{ - Serialize, - Serializer, -}; +use core::cmp::Ordering; +use core::fmt::{self, Debug, Display}; +use core::marker::PhantomData; +use serde::{Serialize, Serializer}; use super::dual::Tagged as DualTagged; diff --git a/tools/test-framework/src/types/topology.rs b/tools/test-framework/src/types/topology.rs new file mode 100644 index 0000000000..4fb915a834 --- /dev/null +++ b/tools/test-framework/src/types/topology.rs @@ -0,0 +1,198 @@ +/*! + The Topology defines how chains are interconnected when more than two are used in tests. + This setup is managed by the [`crate::bootstrap::nary::chain::boostrap_chains_with_any_nodes`] + function. + + Connections are established by examining the existing clients, and channels are created based + on these connections. Therefore, to define the topology of the chains, it is sufficient to + create the appropriate set of clients. + + Example: Linear Topology + + For a linear topology between chains A, B, and C, the clients are created as follows: + * Chain A: a client referencing chain B + * Chain B: a client referencing chain B and a client referencing chain C + * Chain C: a client referencing chain B + + This setup ensures that: + + * Chain A is connected to Chain B. + * Chain B is connected to both Chain A and Chain C. + * Chain C is connected to Chain B. + + Example: Fully Connected Topology + + In a fully connected topology, every chain has clients referencing all other chains. + For chains A, B, and C, the clients are created as follows: + + * Chain A: Clients referencing chains B and C + * Chain B: Clients referencing chains A and C + * Chain C: Clients referencing chains A and B + * Each chain will also have a self referencing client + + This setup ensures that every chain is directly connected to every other chain, forming + a complete graph. + + Example: Cyclic Topology + + The cyclic topology is similar to the linear topology with the addition of the first and + last chain being connected as well. + For chains A, B, C and D, the clients are created as follows: + + * Chain A: Clients referencing chains B and D + * Chain B: Clients referencing chains A and C + * Chain C: Clients referencing chains B and D + * Chain D: Clients referencing chains A and C + + By defining the appropriate set of clients, you can establish the desired topology for + your tests, whether it be linear, fully connected, or any other configuration. +*/ + +use eyre::eyre; +use std::str::FromStr; + +use ibc_relayer::chain::handle::ChainHandle; +use ibc_relayer::foreign_client::ForeignClient; + +use crate::bootstrap::binary::chain::bootstrap_foreign_client; +use crate::error::Error; +use crate::util::two_dim_hash_map::TwoDimMap; + +pub enum TopologyType { + Linear, + Full, + Cyclic, +} + +impl FromStr for TopologyType { + type Err = Error; + + fn from_str(s: &str) -> Result { + match s { + "linear" => Ok(Self::Linear), + "full" => Ok(Self::Full), + "cyclic" => Ok(Self::Cyclic), + _ => Err(Error::generic(eyre!("The topology `{s}` does not exist"))), + } + } +} + +pub trait Topology { + fn create_topology( + &self, + chain_handles: &Vec, + ) -> Result>, Error>; +} + +pub struct FullyConnectedTopology; + +impl Topology for FullyConnectedTopology { + fn create_topology( + &self, + chain_handles: &Vec, + ) -> Result>, Error> { + let mut foreign_clients: TwoDimMap> = TwoDimMap::new(); + + for (i, handle_a) in chain_handles.iter().enumerate() { + for (j, handle_b) in chain_handles.iter().enumerate() { + let foreign_client = + bootstrap_foreign_client(handle_a, handle_b, Default::default())?; + + foreign_clients.insert((i, j), foreign_client); + } + } + Ok(foreign_clients) + } +} + +pub struct LinearTopology; + +impl Topology for LinearTopology { + fn create_topology( + &self, + chain_handles: &Vec, + ) -> Result>, Error> { + let mut foreign_clients: TwoDimMap> = TwoDimMap::new(); + + let last_index = chain_handles.len() - 1; + for (i, _) in chain_handles.iter().enumerate() { + if i < last_index { + let client = bootstrap_foreign_client( + &chain_handles[i], + &chain_handles[i + 1], + Default::default(), + )?; + foreign_clients.insert((i, i + 1), client); + } + if i > 0 { + let client = bootstrap_foreign_client( + &chain_handles[i], + &chain_handles[i - 1], + Default::default(), + )?; + foreign_clients.insert((i, i - 1), client); + } + } + Ok(foreign_clients) + } +} + +pub struct CyclicTopology; + +impl Topology for CyclicTopology { + fn create_topology( + &self, + chain_handles: &Vec, + ) -> Result>, Error> { + let mut foreign_clients: TwoDimMap> = TwoDimMap::new(); + + let last_index = chain_handles.len() - 1; + for (i, _) in chain_handles.iter().enumerate() { + // Create client from first chain to last + if i == 0 { + let client = bootstrap_foreign_client( + &chain_handles[0], + &chain_handles[last_index], + Default::default(), + )?; + foreign_clients.insert((i, last_index), client); + } + // Create client from last chain to first + if i == last_index { + let client = bootstrap_foreign_client( + &chain_handles[last_index], + &chain_handles[0], + Default::default(), + )?; + foreign_clients.insert((i, 0), client); + } + if i < last_index { + let client = bootstrap_foreign_client( + &chain_handles[i], + &chain_handles[i + 1], + Default::default(), + )?; + foreign_clients.insert((i, i + 1), client); + } + if i > 0 { + let client = bootstrap_foreign_client( + &chain_handles[i], + &chain_handles[i - 1], + Default::default(), + )?; + foreign_clients.insert((i, i - 1), client); + } + } + Ok(foreign_clients) + } +} + +pub fn bootstrap_topology( + topology: TopologyType, +) -> Box> { + match topology { + TopologyType::Full => Box::new(FullyConnectedTopology), + TopologyType::Linear => Box::new(LinearTopology), + TopologyType::Cyclic => Box::new(CyclicTopology), + } +} diff --git a/tools/test-framework/src/types/wallet.rs b/tools/test-framework/src/types/wallet.rs index 2c8f83a621..9886c19cbe 100644 --- a/tools/test-framework/src/types/wallet.rs +++ b/tools/test-framework/src/types/wallet.rs @@ -2,21 +2,11 @@ Types for information about a chain wallet. */ -use core::fmt::{ - self, - Display, -}; - +use core::fmt::{self, Display}; use ibc_relayer::keyring::Secp256k1KeyPair; -use crate::types::{ - env::{ - prefix_writer, - EnvWriter, - ExportEnv, - }, - tagged::*, -}; +use crate::types::env::{prefix_writer, EnvWriter, ExportEnv}; +use crate::types::tagged::*; /** Newtype wrapper for a wallet ID as identified by the chain and relayer. diff --git a/tools/test-framework/src/util/array.rs b/tools/test-framework/src/util/array.rs index 9bb5ed686e..df02df2a92 100644 --- a/tools/test-framework/src/util/array.rs +++ b/tools/test-framework/src/util/array.rs @@ -2,8 +2,6 @@ Helpers for manipulating fixed-sized arrays. */ -use core::convert::TryInto; - use eyre::eyre; use crate::error::Error; @@ -17,22 +15,6 @@ pub fn try_into_array(list: Vec) -> Result<[T; SIZE], E .map_err(|_| Error::generic(eyre!("vector is not of length {}", SIZE))) } -/** - Converts a dynamic-sized nested vector `Vec>` into a fixed-sized - nested array `[[T; SIZE]; SIZE]`. Fails if the nested vector is not of - `SIZE`x`SIZE` length. -*/ -pub fn try_into_nested_array( - list: Vec>, -) -> Result<[[T; SIZE]; SIZE], Error> { - let list_a = list - .into_iter() - .map(try_into_array) - .collect::, _>>()?; - - try_into_array(list_a) -} - /** Converts a fixed-sized nested array `[[T; SIZE]; SIZE]` into a nested vector `Vec>`. @@ -40,49 +22,3 @@ pub fn try_into_nested_array( pub fn into_nested_vec(array: [[T; SIZE]; SIZE]) -> Vec> { array.map(|array_b| array_b.into()).into() } - -/** - Map the elements in the fixed-sized array `[[T; SIZE]; SIZE]`. -*/ -pub fn map_nested_array( - array: [[T; SIZE]; SIZE], - mapper: impl Fn(T) -> Result, -) -> Result<[[R; SIZE]; SIZE], Error> { - let mapped = into_nested_vec(array) - .into_iter() - .map(|inner| { - inner - .into_iter() - .map(&mapper) - .collect::, _>>() - }) - .collect::, _>>()?; - - try_into_nested_array(mapped) -} - -/** - Asserts that a nested vector `Vec>` has the same dimension - in its inner vectors. -*/ -pub fn assert_same_dimension(size: usize, list: &Vec>) -> Result<(), Error> { - if list.len() != size { - return Err(Error::generic(eyre!( - "expect nested vector to have the dimension {} x {}", - size, - size - ))); - } - - for list_b in list.iter() { - if list_b.len() != size { - return Err(Error::generic(eyre!( - "expect nested vector to have the dimension {} x {}", - size, - size - ))); - } - } - - Ok(()) -} diff --git a/tools/test-framework/src/util/file.rs b/tools/test-framework/src/util/file.rs index 7bb1274c3e..4473c2093b 100644 --- a/tools/test-framework/src/util/file.rs +++ b/tools/test-framework/src/util/file.rs @@ -2,11 +2,9 @@ Filesystem utilities. */ -use std::{ - fs, - io, - thread, -}; +use std::fs; +use std::io; +use std::thread; use crate::error::Error; diff --git a/tools/test-framework/src/util/interchain_security.rs b/tools/test-framework/src/util/interchain_security.rs index c4fcfa0b84..f2bf9fef2c 100644 --- a/tools/test-framework/src/util/interchain_security.rs +++ b/tools/test-framework/src/util/interchain_security.rs @@ -1,9 +1,14 @@ -use ibc_relayer::config::ChainConfig; +use crate::chain::config::set_voting_period; +use crate::prelude::*; -use crate::{ - chain::config::set_voting_period, - prelude::*, -}; +use ibc_relayer::chain::tracking::TrackedMsgs; +use ibc_relayer::config::ChainConfig; +use ibc_relayer::event::IbcEventWithHeight; +use ibc_relayer_types::applications::ics27_ica::msgs::send_tx::MsgSendTx; +use ibc_relayer_types::applications::ics27_ica::packet_data::InterchainAccountPacketData; +use ibc_relayer_types::signer::Signer; +use ibc_relayer_types::timestamp::Timestamp; +use ibc_relayer_types::tx_msg::Msg; pub fn update_genesis_for_consumer_chain(genesis: &mut serde_json::Value) -> Result<(), Error> { // Consumer chain doesn't have a gov key. @@ -24,13 +29,39 @@ pub fn update_relayer_config_for_consumer_chain(config: &mut Config) { // the proposal. for chain_config in config.chains.iter_mut() { match chain_config { - ChainConfig::CosmosSdk(chain_config) | ChainConfig::Astria(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(_) | ChainConfig::Astria(_) => {} + ChainConfig::CosmosSdk(_) => {} + ChainConfig::Astria(_) => {} } } } + +/// Sends a message containing `InterchainAccountPacketData` from the `Signer` +/// to the `Chain`. +pub fn interchain_send_tx( + chain: &ChainA, + from: &Signer, + connection: &ConnectionId, + msg: InterchainAccountPacketData, + relative_timeout: Timestamp, +) -> Result, Error> { + let msg = MsgSendTx { + owner: from.clone(), + connection_id: connection.clone(), + packet_data: msg, + relative_timeout, + }; + + let msg_any = msg.to_any(); + + let tm = TrackedMsgs::new_static(vec![msg_any], "SendTx"); + + chain + .send_messages_and_wait_commit(tm) + .map_err(Error::relayer) +} diff --git a/tools/test-framework/src/util/mod.rs b/tools/test-framework/src/util/mod.rs index 8fcd82a5dc..7db62f867e 100644 --- a/tools/test-framework/src/util/mod.rs +++ b/tools/test-framework/src/util/mod.rs @@ -10,3 +10,4 @@ pub mod proposal_status; pub mod random; pub mod retry; pub mod suspend; +pub mod two_dim_hash_map; diff --git a/tools/test-framework/src/util/proposal_status.rs b/tools/test-framework/src/util/proposal_status.rs index d377e35f25..5c1e63df5e 100644 --- a/tools/test-framework/src/util/proposal_status.rs +++ b/tools/test-framework/src/util/proposal_status.rs @@ -1,6 +1,5 @@ -use std::str::FromStr; - use serde_json::Value; +use std::str::FromStr; use crate::prelude::*; diff --git a/tools/test-framework/src/util/random.rs b/tools/test-framework/src/util/random.rs index 95c08c0b78..8f7d299d25 100644 --- a/tools/test-framework/src/util/random.rs +++ b/tools/test-framework/src/util/random.rs @@ -2,20 +2,15 @@ Utilities for random value generation. */ +use ibc_relayer_types::applications::transfer::amount::Amount; +use once_cell::sync::Lazy; +use rand::Rng; use std::{ collections::HashSet, - net::{ - Ipv4Addr, - SocketAddrV4, - TcpListener, - }, + net::{Ipv4Addr, SocketAddrV4, TcpListener}, sync::Mutex, }; -use ibc_relayer_types::applications::transfer::amount::Amount; -use once_cell::sync::Lazy; -use rand::Rng; - /// Generates a random `u32` value. pub fn random_u32() -> u32 { let mut rng = rand::thread_rng(); diff --git a/tools/test-framework/src/util/retry.rs b/tools/test-framework/src/util/retry.rs index 9867f152cb..2d88feb2b7 100644 --- a/tools/test-framework/src/util/retry.rs +++ b/tools/test-framework/src/util/retry.rs @@ -4,11 +4,7 @@ use core::time::Duration; use std::thread::sleep; - -use tracing::{ - info, - trace, -}; +use tracing::{info, trace}; use crate::error::Error; diff --git a/tools/test-framework/src/util/suspend.rs b/tools/test-framework/src/util/suspend.rs index afaec475ab..edd6adca5e 100644 --- a/tools/test-framework/src/util/suspend.rs +++ b/tools/test-framework/src/util/suspend.rs @@ -3,19 +3,9 @@ */ use core::time::Duration; -use std::{ - panic::{ - catch_unwind, - resume_unwind, - AssertUnwindSafe, - }, - thread::sleep, -}; - -use tracing::{ - error, - warn, -}; +use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe}; +use std::thread::sleep; +use tracing::{error, warn}; use crate::error::Error; diff --git a/tools/test-framework/src/util/two_dim_hash_map.rs b/tools/test-framework/src/util/two_dim_hash_map.rs new file mode 100644 index 0000000000..678961669f --- /dev/null +++ b/tools/test-framework/src/util/two_dim_hash_map.rs @@ -0,0 +1,113 @@ +use std::collections::{btree_map, BTreeMap}; + +#[derive(Clone, Debug)] +pub struct TwoDimMap { + pub map: BTreeMap>, +} + +impl Default for TwoDimMap { + fn default() -> Self { + TwoDimMap { + map: BTreeMap::new(), + } + } +} + +impl TwoDimMap { + pub fn new() -> Self { + Self::default() + } + pub fn get(&self, (x, y): (usize, usize)) -> Option<&T> { + self.map.get(&x).and_then(|inner| inner.get(&y)) + } + + pub fn insert(&mut self, (x, y): (usize, usize), value: T) -> Option { + if let Some(existing_values) = self.map.get_mut(&x) { + existing_values.insert(y, value) + } else { + let mut new_values = BTreeMap::new(); + new_values.insert(y, value); + self.map.insert(x, new_values); + None + } + } + + pub fn iter(&self) -> Iter { + Iter { + outer_iter: self.map.iter(), + inner_iter: None, + outer_key: 0, + } + } +} + +pub struct Iter<'a, T> { + outer_iter: btree_map::Iter<'a, usize, BTreeMap>, + inner_iter: Option>, + outer_key: usize, +} + +impl<'a, T> Iterator for Iter<'a, T> { + type Item = (usize, usize, &'a T); + + fn next(&mut self) -> Option { + loop { + if let Some(inner_iter) = &mut self.inner_iter { + if let Some((inner_key, inner_value)) = inner_iter.next() { + return Some((self.outer_key, *inner_key, inner_value)); + } + } + + if let Some((outer_key, inner_map)) = self.outer_iter.next() { + self.outer_key = *outer_key; + self.inner_iter = Some(inner_map.iter()); + } else { + return None; + } + } + } +} + +impl From>> for TwoDimMap { + fn from(map: BTreeMap>) -> Self { + Self { map } + } +} + +#[cfg(test)] +mod tests { + use std::collections::BTreeMap; + + use super::*; + + #[test] + fn test_two_dim_hash_map_iterator() { + let mut outer_hashmap = BTreeMap::new(); + let mut inner_hashmap1 = BTreeMap::new(); + let mut inner_hashmap2 = BTreeMap::new(); + let mut inner_hashmap3 = BTreeMap::new(); + + inner_hashmap1.insert(1, "a"); + + inner_hashmap2.insert(2, "c"); + inner_hashmap2.insert(0, "b"); + + inner_hashmap3.insert(1, "d"); + + outer_hashmap.insert(0, inner_hashmap1); + outer_hashmap.insert(1, inner_hashmap2); + outer_hashmap.insert(2, inner_hashmap3); + + let two_dim_hash_map = TwoDimMap::from(outer_hashmap); + let mut two_dim_hash_map_iter = two_dim_hash_map.iter(); + + assert_eq!(two_dim_hash_map_iter.next(), Some((0, 1, &"a"))); + + assert_eq!(two_dim_hash_map_iter.next(), Some((1, 0, &"b"))); + assert_eq!(two_dim_hash_map_iter.next(), Some((1, 2, &"c"))); + + assert_eq!(two_dim_hash_map_iter.next(), Some((2, 1, &"d"))); + + assert_eq!(two_dim_hash_map_iter.next(), None); + } +}