diff --git a/CHANGELOG.md b/CHANGELOG.md index d614e1e6b4..a2cfb9e427 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,22 @@ # Changelog ## Unreleased Changes +This release includes initial support for relaying over multiple paths from a single `hermes` instance. +Adds support for relayer restart, where pending packets are cleared. +Includes support for ordered channels, packet delay, misbehaviour detection and evidence submission, client upgrade after counterparty chain upgrades. -> [TODO: high level summary] +This release brings improvements to the relayer UX by providing new and updated commands for keys, client, +connection and channel management. +In addition, it simplifies the configuration of and integration with the light client. + +This release also finalizes initial implementation for all of ICS 004 handlers. ### FEATURES - Update to `tendermint-rs` v0.19.0 ([#798]) - [ibc] - - Added handler(s) for sending packets ([#695]) and for recv. and ack. packets ([#736]) + - Added handler(s) for sending packets ([#695]), recv. and ack. packets ([#736]), and timeouts ([#362]) - [ibc-relayer] - Support for relayer restart ([#561]) @@ -77,6 +84,7 @@ [#352]: https://github.com/informalsystems/ibc-rs/issues/352 +[#362]: https://github.com/informalsystems/ibc-rs/issues/362 [#357]: https://github.com/informalsystems/ibc-rs/issues/357 [#416]: https://github.com/informalsystems/ibc-rs/issues/416 [#561]: https://github.com/informalsystems/ibc-rs/issues/561 diff --git a/Cargo.lock b/Cargo.lock index 860d397633..17a4f8d872 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1055,9 +1055,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7245cd7449cc792608c3c8a9eaf69bd4eabbabf802713748fd739c98b82f0747" +checksum = "527e8c9ac747e28542699a951517aa9a6945af506cd1f2e1b53a576c17b6cc11" dependencies = [ "bytes", "fnv", @@ -1077,9 +1077,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.3.5" +version = "1.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "615caabe2c3160b313d52ccc905335f4ed5f10881dd63dc5699d47e90be85691" +checksum = "bc35c995b9d93ec174cf9a27d425c7892722101e14993cd227fdb51d70cf9589" [[package]] name = "httpdate" @@ -2099,9 +2099,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "sct" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" +checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" dependencies = [ "ring", "untrusted", @@ -2422,9 +2422,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ce15dd3ed8aa2f8eeac4716d6ef5ab58b6b9256db41d7e1a0224c2788e8fd87" +checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb" dependencies = [ "proc-macro2", "quote", @@ -2675,9 +2675,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134af885d758d645f0f0505c9a8b3f9bf8a348fd822e112ab5248138348f1722" +checksum = "83f0c8e7c0addab50b663055baf787d0af7f413a46e6e7fb9559a4e4db7137a5" dependencies = [ "autocfg", "bytes", @@ -2738,9 +2738,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5143d049e85af7fbc36f5454d990e62c2df705b3589f123b71f441b6b59f443f" +checksum = "940a12c99365c31ea8dd9ba04ec1be183ffe4920102bb7122c2f515437601e8e" dependencies = [ "bytes", "futures-core", diff --git a/e2e/e2e/packet.py b/e2e/e2e/packet.py index 1f7c34686e..640dc2ef9c 100644 --- a/e2e/e2e/packet.py +++ b/e2e/e2e/packet.py @@ -23,13 +23,13 @@ class TxPacketSendRes: @cmd("tx raw ft-transfer") @dataclass class TxPacketSend(Cmd[TxPacketSendRes]): - src_chain_id: ChainId dst_chain_id: ChainId + src_chain_id: ChainId src_port: PortId src_channel: ChannelId def args(self) -> List[str]: - return [self.src_chain_id, self.dst_chain_id, self.src_port, self.src_channel, "9999", "1000"] + return [self.dst_chain_id, self.src_chain_id, self.src_port, self.src_channel, "9999", "1000"] def process(self, result: Any) -> TxPacketSendRes: entry = find_entry(result, 'SendPacket') @@ -90,7 +90,7 @@ def process(self, result: Any) -> TxPacketAckRes: def packet_send(c: Config, src: ChainId, dst: ChainId, src_port: PortId, src_channel: ChannelId) -> Packet: - cmd = TxPacketSend(src_chain_id=src, dst_chain_id=dst, + cmd = TxPacketSend(dst_chain_id=dst, src_chain_id=src, src_port=src_port, src_channel=src_channel) res = cmd.run(c).success() diff --git a/guide/book.toml b/guide/book.toml index 71b1e8bc1d..c11547b50c 100644 --- a/guide/book.toml +++ b/guide/book.toml @@ -14,3 +14,6 @@ renderer = ["html"] [output.html] additional-js = ["mermaid.min.js", "mermaid-init.js"] + +# Uncomment to trigger the link check +# [output.linkcheck] diff --git a/guide/src/SUMMARY.md b/guide/src/SUMMARY.md index cb11408c5d..94a85b0cb9 100644 --- a/guide/src/SUMMARY.md +++ b/guide/src/SUMMARY.md @@ -6,41 +6,49 @@ - [Introduction](./index.md) - [What is Hermes?](./relayer.md) - [Features](./features.md) - - [Feature matrix](./feature_matrix.md) + - [Feature matrix](./features/matrix.md) - [Getting Started](./getting_started.md) - [Pre-requisites](./pre_requisites.md) - [Installation](./installation.md) - [Configuration](./config.md) -- [Tutorials](./tutorials.md) - - [Two local chains](./two_chains.md) - - [Install Gaia](./gaia.md) - - [Start the local chains](./local_chains.md) - - [Connect the chains using raw transactions](./tutorial_raw.md) - - [Configure clients](./tutorial_client_raw.md) - - [Connection handshake](./tutorial_conn_raw.md) - - [Channel handshake](./tutorial_chan_open_raw.md) - - [Relay packets](./tutorial_packet_raw.md) - - [Connect the chains using relay paths](./tutorial_relay_paths.md) - - [New path](./tutorial_set_new_path.md) - - [Packet relaying on existing path](./tutorial_relay_existing_path.md) - - [Packet relaying on new path](./tutorial_relay_new_path.md) - - [Concurrent packet relaying on multiple paths](./tutorial_relay_two_paths.md) -- [Commands Reference](./commands.md) - - [Keys](./keys.md) - - [Light clients](./light_clients.md) - - [Path setup and streaming](./relayer_loop.md) - - [Raw transactions](./transactions.md) - - [Client](./tx_client.md) - - [Connection](./tx_connection.md) - - [Channel Open](./tx_channel_open.md) - - [Channel Close](./tx_channel_close.md) - - [Packet](./tx_packet.md) - - [Queries](./queries.md) - - [Client](./query_client.md) - - [Connection](./query_connection.md) - - [Channel](./query_channel.md) - - [Packet](./query_packet.md) - - [Listen mode](./listen.md) -- [Help](help.md) +- [Tutorials](./tutorials/index.md) + - [Local chains](./tutorials/local-chains/index.md) + - [Install Gaia](./tutorials/local-chains/gaia.md) + - [Start the local chains](./tutorials/local-chains/start.md) + - [Identifiers](./tutorials/local-chains/identifiers.md) + - [Connect the chains using relay paths](./tutorials/local-chains/relay-paths/index.md) + - [Create a new path](./tutorials/local-chains/relay-paths/create-new-path.md) + - [Packet relaying on existing path](./tutorials/local-chains/relay-paths/existing-path.md) + - [Packet relaying on new path](./tutorials/local-chains/relay-paths/new-path.md) + - [Concurrent packet relaying on multiple paths](./tutorials/local-chains/relay-paths/multiple-paths.md) + - [Connect the chains using raw transactions](./tutorials/local-chains/raw/index.md) + - [Configure clients](./tutorials/local-chains/raw/client.md) + - [Connection handshake](./tutorials/local-chains/raw/connection.md) + - [Channel handshake](./tutorials/local-chains/raw/channel.md) + - [Relay packets](./tutorials/local-chains/raw/packet.md) +- [Commands Reference](./commands/index.md) + - [Global options and JSON output](./commands/global.md) + - [Keys](./commands/keys/index.md) + - [Path setup and streaming](./commands/setup-and-relaying/index.md) + - [Clients](./commands/setup-and-relaying/clients.md) + - [Connections](./commands/setup-and-relaying/connections.md) + - [Channels](./commands/setup-and-relaying/channels.md) + - [Packet relaying](./commands/setup-and-relaying/packets.md) + - [Listen mode](./commands/listen/index.md) + - [Client upgrade](./commands/upgrade/index.md) + - [Testing client upgrade](./commands/upgrade/test.md) + - [Misbehaviour](./commands/misbehaviour/index.md) + - [Queries](./commands/queries/index.md) + - [Client](./commands/queries/client.md) + - [Connection](./commands/queries/connection.md) + - [Channel](./commands/queries/channel.md) + - [Packet](./commands/queries/packet.md) + - [Raw transactions](./commands/raw/index.md) + - [Client](./commands/raw/client.md) + - [Connection](./commands/raw/connection.md) + - [Channel Open](./commands/raw/channel-open.md) + - [Channel Close](./commands/raw/channel-close.md) + - [Packet](./commands/raw/packet.md) +- [Help](./help.md) - [Glossary](./glossary.md) --- diff --git a/guide/src/commands.md b/guide/src/commands.md deleted file mode 100644 index a6486b1654..0000000000 --- a/guide/src/commands.md +++ /dev/null @@ -1,29 +0,0 @@ -# Commands - -The `Commands` section presents the commands current available in Hermes - -## Sections - -**[Keys](./keys.md)** - -Commands to manage keys (private keys) for each chain. - -**[Light Clients](./light_clients.md)** - -Commands to manage light client configuration. Allows adding and removing light client peers. - -**[Path Setup and Streaming](./relayer_loop.md)** - -Commands to manage channels - -**[Raw Transactions](./transactions.md)** - -Command to submit transactions to configured chains - -**[Queries](./queries.md)** - -Commands to execute queries on configured chains - -**[Listen Mode](./listen.md)** - -Commands to listen for IBC events \ No newline at end of file diff --git a/guide/src/commands/global.md b/guide/src/commands/global.md new file mode 100644 index 0000000000..21af754e7c --- /dev/null +++ b/guide/src/commands/global.md @@ -0,0 +1,113 @@ +# Global options + +The Hermes accepts global options which affect all commands. + +```shell +hermes 0.1.1 +Informal Systems +Implementation of `hermes`, an IBC Relayer developed in Rust. + +FLAGS: + -c, --config CONFIG path to configuration file + -h, --help print help message + -j, --json enable JSON output +``` + +The flags must be specified right after the `hermes` command and before any subcommand. + +__Example__ + +To start the relayer using the configuration file at `/home/my_chain.toml` and enable JSON output: + +```shell +hermes -c /home/my_chain.toml --json start ibc-0 ibc-1 +``` + +## JSON output + +If the `--json` option is supplied, all relayer commands will output single-line JSON values instead of plain text. + +Intermediate log messages will be written to `stderr`, while the final result will be written to `stdout`. +This allows processing only the final output using [`jq`](https://stedolan.github.io/jq/). +To process all the output using `jq`, one can redirect `stderr` to `stdout` with `hermes --json COMMAND 2>&1 | jq`. + +__Example__ + +```shell +hermes -c /home/my_chain.toml --json create client ibc-0 ibc-1 +``` + +```json +{"timestamp":"Apr 13 20:46:31.921","level":"INFO","fields":{"message":"Using default configuration from: '.hermes/config.toml'"},"target":"ibc_relayer_cli::commands"} +{"timestamp":"Apr 13 20:46:31.961","level":"INFO","fields":{"message":"running listener","chain.id":"ibc-1"},"target":"ibc_relayer::event::monitor"} +{"timestamp":"Apr 13 20:46:31.989","level":"INFO","fields":{"message":"running listener","chain.id":"ibc-0"},"target":"ibc_relayer::event::monitor"} +{"result":{"CreateClient":{"client_id":"07-tendermint-1","client_type":"Tendermint","consensus_height":{"revision_height":10060,"revision_number":1},"height":{"revision_height":10072,"revision_number":0}}},"status":"success"} +``` + +The first three lines are printed to `stderr`, while the last line with a `"result"` key is printed to `stdout`. + +__Example__ + +To improve the readability, pipe all of the output to `jq`: + +``` +hermes -c /home/my_chain.toml --json create client ibc-0 ibc-1 2>&1 | jq +``` + +```json +{ + "timestamp": "Apr 13 20:52:26.060", + "level": "INFO", + "fields": { + "message": "Using default configuration from: '.hermes/config.toml'" + }, + "target": "ibc_relayer_cli::commands" +} +{ + "timestamp": "Apr 13 20:52:26.082", + "level": "INFO", + "fields": { + "message": "running listener", + "chain.id": "ibc-1" + }, + "target": "ibc_relayer::event::monitor" +} +{ + "timestamp": "Apr 13 20:52:26.088", + "level": "INFO", + "fields": { + "message": "running listener", + "chain.id": "ibc-0" + }, + "target": "ibc_relayer::event::monitor" +} +{ + "result": { + "CreateClient": { + "client_id": "07-tendermint-5", + "client_type": "Tendermint", + "consensus_height": { + "revision_height": 10364, + "revision_number": 1 + }, + "height": { + "revision_height": 10375, + "revision_number": 0 + } + } + }, + "status": "success" +} +``` + +__Example__ + +To extract the identifer of the newly created client above: + +``` +hermes -c /home/my_chain.toml --json create client ibc-0 ibc-1 | jq '.result.CreateClient.client_id' +``` + +``` +"07-tendermint-2" +``` diff --git a/guide/src/commands/index.md b/guide/src/commands/index.md new file mode 100644 index 0000000000..2262554f9b --- /dev/null +++ b/guide/src/commands/index.md @@ -0,0 +1,33 @@ +# Commands + +The `Commands` section presents the commands current available in Hermes + +## Sections + +**[Keys](./keys/index.md)** + +Commands to manage keys (private keys) for each chain. + +**[Path Setup and Streaming](./setup-and-relaying/index.md)** + +Commands to manage clients, connections, channels and performing packet relaying + +**[Listen Mode](./listen/index.md)** + +Commands to listen for IBC events + +**[Upgrade](./upgrade/index.md)** + +Commands to perform client upgrade + +**[Monitor](./misbehaviour/index.md)** + +Commands to monitor clients and submit evidence of misbehaviour + +**[Queries](./queries/index.md)** + +Commands to execute queries on configured chains + +**[Raw Transactions](./raw/index.md)** + +Commands to submit individual transactions to configured chains diff --git a/guide/src/keys.md b/guide/src/commands/keys/index.md similarity index 60% rename from guide/src/keys.md rename to guide/src/commands/keys/index.md index 85f31da966..c4efb5a5e9 100644 --- a/guide/src/keys.md +++ b/guide/src/commands/keys/index.md @@ -1,5 +1,15 @@ # Adding Keys to the Relayer +> __WARNING__: Currently the relayer does NOT support a `keyring` store to securely +> store the private key file. The key file will be stored on the local file system +> in the user __$HOME__ folder under `$HOME/.rrly` + +> __BREAKING__: As of Hermes v0.2.0, the format of the keys stored on disk has changed, and +> keys which had been previously configured must now be re-imported using either the `keys add` +> or the `keys restore` commands. + +--- + Using the `keys` command you can add and list keys. #### Show usage @@ -35,7 +45,7 @@ The private key file can be obtained by using the `keys add` on a Cosmos chain, gaiad keys add ... ``` -The command outputs a JSON similar to the one below. You can save this file (e.g. key_seed.json) and use it to add to the relayer +The command outputs a JSON similar to the one below. You can save this file (e.g. `key_seed.json`) and use it to add to the relayer ```json { @@ -47,12 +57,9 @@ The command outputs a JSON similar to the one below. You can save this file (e.g } ``` -> __WARNING__: Currently the relayer does NOT support a `keyring` store to securely store the private key file. The key file will be stored on the local file system in the user __$HOME__ folder under `$HOME/.rrly` - - ### Adding Keys -In order to add a key to a chain use the `keys add` command: +#### Add a private key to a chain from a key file ```shell USAGE: @@ -63,22 +70,50 @@ DESCRIPTION: POSITIONAL ARGUMENTS: chain_id identifier of the chain - file the key path and filename +FLAGS: + -f, --file FILE the path to the key file (conflicts with --mnemonic) ``` -#### Add a private key to a chain - To add a private key file to a chain: ```shell -hermes -c config keys add [CHAIN_ID] [PRIVATE_KEY_FILE] +hermes -c config keys add [CHAIN_ID] -f [PRIVATE_KEY_FILE] +``` + +If the command is successful a message similar to the one below will be displayed: + +```json +Success: Added key testkey ([ADDRESS]) on [CHAIN ID] chain +``` + +#### Restore a private key to a chain from a mnemonic + +```shell +USAGE: + hermes keys restore + +DESCRIPTION: + restore a key to a configured chain using a mnemonic + +POSITIONAL ARGUMENTS: + chain_id identifier of the chain + +FLAGS: + -n, --name NAME key name + -m, --mnemonic MNEMONIC mnemonic to restore the key from +``` + +To restore a key from its mnemonic: + +```shell +hermes -c config keys restore [CHAIN_ID] -m "[MNEMONIC]" ``` If the command is successful a message similar to the one below will be displayed: ```json -{"status":"success","result":["Added key testkey ([ADDRESS]) on [CHAIN ID] chain"]} +Success: Restore key testkey ([ADDRESS]) on [CHAIN ID] chain ``` ### List keys @@ -107,5 +142,5 @@ hermes -c config keys list [CHAIN_ID] If the command is successful a message similar to the one below will be displayed: ```json -{"status":"success","result":["chain: [CHAIN_ID] -> testkey ([ADDRESS])"]} +[CHAIN_ID] -> [KEY_NAME] ([ADDRESS]) ``` diff --git a/guide/src/listen.md b/guide/src/commands/listen/index.md similarity index 70% rename from guide/src/listen.md rename to guide/src/commands/listen/index.md index 3dc9d92d7c..ff9a8dddf7 100644 --- a/guide/src/listen.md +++ b/guide/src/commands/listen/index.md @@ -1,26 +1,31 @@ # Relayer Listen Mode -The relayer can be started in `listen` mode to display the events emitted by a given chain. `NewBlock` and IBC events are shown. +The relayer can be started in `listen` mode to display the events emitted by a given chain. `NewBlock` and `Tx` IBC events are shown. ```shell USAGE: hermes listen DESCRIPTION: - Listen to IBC events + Listen to and display IBC events emitted by a chain POSITIONAL ARGUMENTS: - chain_id + chain_id Identifier of the chain to listen for events from + +FLAGS: + -e, --event EVENT Add an event type to listen for, can be repeated. Listen for all events by default (available: Tx, NewBlock) ``` __Example__ -Start the relayer in listen mode for `ibc-0` events and observe the output: +Start the relayer in listen mode for all `ibc-0` events and observe the output: ```shell hermes listen ibc-0 +``` -[relayer-cli/src/commands/listen.rs:45] event_batch = EventBatch { +```rust +EventBatch { chain_id: ChainId { id: "ibc-0", version: 0, @@ -34,7 +39,7 @@ hermes listen ibc-0 ), ], } -[relayer-cli/src/commands/listen.rs:45] event_batch = EventBatch { +EventBatch { chain_id: ChainId { id: "ibc-0", version: 0, @@ -61,8 +66,10 @@ hermes listen ibc-0 ), ), ], + ... -[relayer-cli/src/commands/listen.rs:45] event_batch = EventBatch { + +EventBatch { chain_id: ChainId { id: "ibc-0", version: 0, @@ -78,16 +85,18 @@ hermes listen ibc-0 ), client_type: Tendermint, consensus_height: Height { - revision_number: 1, - revision_height: 10907, + revision: 1, + height: 10907, }, }, ), ), ], } + ... -[relayer-cli/src/commands/listen.rs:45] event_batch = EventBatch { + +EventBatch { chain_id: ChainId { id: "ibc-0", version: 0, @@ -103,8 +112,8 @@ hermes listen ibc-0 ), client_type: Tendermint, consensus_height: Height { - revision_number: 1, - revision_height: 10912, + revision: 1, + height: 10912, }, }, ), @@ -135,3 +144,19 @@ hermes listen ibc-0 ], } ``` + +## Filter events + +The `listen` command accepts an `--event` flag to specify which event types to listen for. + +At the moment, two event types are available: +- `NewBlock` +- `Tx` + +The `--event` flag can be repeated to specify more than one event type. + +- To listen for only `NewBlock` events on `ibc-0`, invoke `hermes listen ibc-0 --event NewBlock` +- To listen for only `Tx` events on `ibc-0`, invoke `hermes listen ibc-0 --event Tx` +- To listen for both `NewBlock` and `Tx` events on `ibc-0`, invoke `hermes listen ibc-0 --e NewBlock --event Tx` + +If the `--event` flag is omitted, the relayer will subscribe to all event types. diff --git a/guide/src/commands/misbehaviour/index.md b/guide/src/commands/misbehaviour/index.md new file mode 100644 index 0000000000..2aa4e3b722 --- /dev/null +++ b/guide/src/commands/misbehaviour/index.md @@ -0,0 +1,127 @@ +# Misbehaviour + +## Table of Contents + + +## Monitoring Misbehaviour and Evidence Submission +Use the `mishbehaviour` command to monitor the updates for a given client, detect certain types of misbehaviour and +submit evidence to the chain. If the evidence passes the on-chain validation, the client is frozen. Further packets +cannot be relayed using the frozen client. + +```shell +USAGE: + hermes misbehaviour + +DESCRIPTION: + Listen to client update IBC events and handles misbehaviour + +POSITIONAL ARGUMENTS: + chain_id identifier of the chain where client updates are monitored for misbehaviour + client_id identifier of the client to be monitored for misbehaviour +``` + +The misbehaviour monitor starts by analyzing all headers used in prior client updates. +Once finished it registers for update client events and checks any new headers for misbehaviour. +If it detects evidence of misbehaviour, it submits a transaction with the evidence to the chain. +If the chain validates the transaction then the monitor exits. + +> This is an experimental feature. + +The following types of misbehaviour are handled: +1. **Fork** + + Assumes at least one consensus state before the fork point exists. + Let existing consensus states on chain B be: `[Sn,.., Sf, Sf-1, S0]` with `Sf-1` being + the most recent state before the fork. + Chain A is queried for a header `Hf'` at `Sf.height` and if it is different than the `Hf` + in the event for the client update (the one that has generated `Sf` on chain), then the two + headers are included in the evidence and submitted. + Note that in this case the headers are different but have the same height. + +2. **BFT time violation for an unavailable header** + + Some header with a height that is higher than the latest + height on chain `A` has been accepted and a consensus state was created on `B`. Note that this implies + that the timestamp of this header must be within the `clock_drift` of the client. + Assume the client on `B` has been updated with `h2`(not present on/ produced by chain `A`) + and it has a timestamp of `t2` that is at most `clock_drift` in the future. + Then the latest header from `A` is fetched, let it be `h1`, with a timestamp of `t1`. + If `t1 >= t2` then evidence of misbehavior is submitted to A. + +__Example__ + +The `hermes misbehaviour` outputs an error message displaying `MISBEHAVIOUR DETECTED`: + +```shell +hermes misbehaviour ibc-0 07-tendermint-0 +``` + +```rust +Apr 13 20:04:03.347 INFO ibc_relayer::foreign_client: checking misbehaviour for consensus state heights [Height { revision: 1, height: 195 }, Height { revision: 1, height: 85 }, Height { revision: 1, height: 28 }] +Apr 13 20:04:04.425 ERROR ibc_relayer::foreign_client: MISBEHAVIOUR DETECTED ClientId("07-tendermint-0") h1: Height { revision: 1, height: 195 }-Height { revision: 1, height: 85 } h2: Height { revision: 1, height: 195 }-Height { revision: 1, height: 85 }, sending evidence +Apr 13 20:04:05.070 INFO ibc_relayer_cli::commands::misbehaviour: evidence submission result [ClientMisbehaviour(ClientMisbehaviour(Attributes { height: Height { revision: 0, height: 1521 }, client_id: ClientId("07-tendermint-0"), client_type: Tendermint, consensus_height: Height { revision: 1, height: 195 } }))] + +Success: Some( + ClientMisbehaviour( + ClientMisbehaviour( + Attributes { + height: Height { + revision: 0, + height: 1521, + }, + client_id: ClientId( + "07-tendermint-0", + ), + client_type: Tendermint, + consensus_height: Height { + revision: 1, + height: 195, + }, + }, + ), + ), +) +``` + +Querying client state from this point will show the client is in frozen state, with `frozen_height` indicating the height at which the client was frozen: +```shell +hermes query client state ibc-0 07-tendermint-0 | jq +``` +```json +{ + "result": { + "allow_update_after_expiry": false, + "allow_update_after_misbehaviour": false, + "chain_id": "ibc-1", + "frozen_height": { + "revision_height": 16, + "revision_number": 1 + }, + "latest_height": { + "revision_height": 16, + "revision_number": 1 + }, + "max_clock_drift": { + "nanos": 0, + "secs": 3 + }, + "trust_level": { + "denominator": "3", + "numerator": "1" + }, + "trusting_period": { + "nanos": 0, + "secs": 1209600 + }, + "unbonding_period": { + "nanos": 0, + "secs": 1814400 + }, + "upgrade_path": [ + "upgrade", + "upgradedIBCState" + ] + }, + "status": "success" +} +``` diff --git a/guide/src/query_channel.md b/guide/src/commands/queries/channel.md similarity index 62% rename from guide/src/query_channel.md rename to guide/src/commands/queries/channel.md index aba649e00c..f9777ee67e 100644 --- a/guide/src/query_channel.md +++ b/guide/src/commands/queries/channel.md @@ -11,7 +11,7 @@ USAGE: hermes query channels DESCRIPTION: - Query the identifiers of all channels on a chain + Query the identifiers of all channels on a given chain POSITIONAL ARGUMENTS: chain_id identifier of the chain to query @@ -22,19 +22,18 @@ __Example__ Query all channels on `ibc-1`: ```shell -hermes query channels ibc-1 | jq +hermes query channels ibc-1 ``` -```json -{ - "status": "success", - "result": [ - "channel-0", - "channel-1", - "channel-2", - "channel-3" - ] -} +```rust +Success: [ + ChannelId( + "channel-0", + ), + ChannelId( + "channel-1", + ), +] ``` # Query Channel Data @@ -74,27 +73,32 @@ FLAGS: __Example__ -Query the channel end of channel `channel-1` on `ibc-1`: +Query the channel end of channel `channel-1` on port `transfer` on `ibc-1`: ```shell -hermes query channel end ibc-1 channel-1 | jq +hermes query channel end ibc-1 channel-1 ``` -```json -{ - "status": "success", - "result": { - "connection_hops": [ - "connection-1" - ], - "ordering": "Unordered", - "remote": { - "channel_id": "channel-0", - "port_id": "transfer" +```rust +Success: ChannelEnd { + state: Open, + ordering: Unordered, + remote: Counterparty { + port_id: PortId( + "transfer", + ), + channel_id: Some( + ChannelId( + "channel-0", + ), + ), }, - "state": "Open", - "version": "ics20-1" - } + connection_hops: [ + ConnectionId( + "connection-1", + ), + ], + version: "ics20-1", } ``` diff --git a/guide/src/commands/queries/client.md b/guide/src/commands/queries/client.md new file mode 100644 index 0000000000..94700fc801 --- /dev/null +++ b/guide/src/commands/queries/client.md @@ -0,0 +1,272 @@ + +# Table of Contents + + + +# Query Clients + +Use the `query clients` command to query the identifiers of all clients on a given chain. + +```shell +USAGE: + hermes query clients + +DESCRIPTION: + Query clients + +POSITIONAL ARGUMENTS: + chain_id identifier of the chain to query +``` + +__Example__ + +Query all clients on `ibc-1`: + +```shell +hermes query clients ibc-1 +``` + +```rust +Success: [ + ClientId("07-tendermint-0"), + ClientId("07-tendermint-1"), +] +``` + +# Query Client Data + +Use the `query client` command to query the information about a specific client. + +```shell +USAGE: + hermes query client + +DESCRIPTION: + Query information about clients + +SUBCOMMANDS: + state query client full state + consensus query client consensus + connections query client connections +``` + +## Query the client state + +Use the `query client state` command to query the client state of a client: + +```shell +USAGE: + hermes query client state + +DESCRIPTION: + Query client full state + +POSITIONAL ARGUMENTS: + chain_id identifier of the chain to query + client_id identifier of the client to query + +FLAGS: + -h, --height HEIGHT the chain height which this query should reflect +``` + +__Example__ + +Query the state of client `07-tendermint-2` on `ibc-1`: + +```shell +hermes query client state ibc-1 07-tendermint-1 +``` + +```rust +Success: ClientState { + chain_id: ChainId { + id: "ibc-2", + version: 2, + }, + trust_level: TrustThresholdFraction { + numerator: 1, + denominator: 3, + }, + trusting_period: 1209600s, + unbonding_period: 1814400s, + max_clock_drift: 3s, + frozen_height: Height { + revision: 0, + height: 0, + }, + latest_height: Height { + revision: 2, + height: 3069, + }, + upgrade_path: [ + "upgrade", + "upgradedIBCState", + ], + allow_update_after_expiry: false, + allow_update_after_misbehaviour: false, +} +``` + +## Query the client consensus state + +Use the `query client consensus` command to query the consensus states of a given client, or the state at a specified height: + +```shell +USAGE: + hermes query client consensus + +DESCRIPTION: + Query client consensus state + +POSITIONAL ARGUMENTS: + chain_id identifier of the chain to query + client_id identifier of the client to query + +FLAGS: + -c, --consensus-height CONSENSUS-HEIGHT + -s, --heights-only show only consensus heights + -h, --height HEIGHT the chain height context to be used, applicable only to a specific height +``` + +__Example__ + +Query the states of client `07-tendermint-0` on `ibc-0`: + +```shell +hermes query client consensus ibc-0 07-tendermint-0 --heights-only +``` + +```json +Success: [ + Height { + revision: 1, + height: 3049, + }, + Height { + revision: 1, + height: 2888, + }, + Height { + revision: 1, + height: 2736, + }, + Height { + revision: 1, + height: 2729, + }, + Height { + revision: 1, + height: 2724, + }, + Height { + revision: 1, + height: 2717, + }, +] +``` + +Query `ibc-0` at height `2800` for the consensus state for height `2724`: + +```shell +hermes query client consensus ibc-0 07-tendermint-0 -c 2724 -h 2800 +``` + +```json +Success: ConsensusState { + timestamp: Time( + 2021-04-13T14:11:20.969154Z + ), + root: CommitmentRoot( + "371DD19003221B60162D42C78FD86ABF95A572F3D9497084584B75F97B05B70C" + ), + next_validators_hash: Hash::Sha256( + 740950668B6705A136D041914FC219045B1D0AD1C6A284C626BF5116005A98A7 + ), +} +``` + +## Query the identifiers of all connections associated with a given client + +Use the `query client connections` command to query the connections associated with a given client: + +```shell +USAGE: + hermes query client connections + +DESCRIPTION: + Query client connections + +POSITIONAL ARGUMENTS: + chain_id identifier of the chain to query + client_id identifier of the client to query + +FLAGS: + -h, --height HEIGHT the chain height which this query should reflect +``` + +__Example__ + +Query the connections of client `07-tendermint-0` on `ibc-0`: + +```shell +hermes query client connections ibc-0 07-tendermint-0 +``` + +```rust +Success: [ + ConnectionId("connection-0"), + ConnectionId("connection-1"), +] +``` + +## Query for the header used in a client update at a certain height + +``` +USAGE: + hermes query client header + +DESCRIPTION: + Query for the header used in a client update at a certain height + +POSITIONAL ARGUMENTS: + chain_id identifier of the chain to query + client_id identifier of the client to query + consensus_height height of header to query + +FLAGS: + -h, --height HEIGHT the chain height context for the query +``` + +__Example__ + +Query for the header used in the `07-tendermint-0` client update at height 2724 on `ibc-0`: + +```shell +hermes query client header ibc-0 07-tendermint-0 2724 +``` + +```rust +Success: [ + UpdateClient( + UpdateClient { + common: Attributes { + height: Height { + revision: 0, + height: 0, + }, + client_id: ClientId( + "07-tendermint-0", + ), + client_type: Tendermint, + consensus_height: Height { + revision: 1, + height: 2724, + }, + }, + header: Some( + Tendermint(...), + ), + }, + ), +] +``` diff --git a/guide/src/query_connection.md b/guide/src/commands/queries/connection.md similarity index 67% rename from guide/src/query_connection.md rename to guide/src/commands/queries/connection.md index 1adc26e2f3..1327de73e2 100644 --- a/guide/src/query_connection.md +++ b/guide/src/commands/queries/connection.md @@ -22,19 +22,18 @@ __Example__ Query all connections on `ibc-1`: ```shell -hermes query connections ibc-1 | jq +hermes query connections ibc-1 ``` -```json -{ - "status": "success", - "result": [ - "connection-0", - "connection-1", - "connection-2", - "connection-3" - ] -} +```rust +Success: [ + ConnectionId( + "connection-0", + ), + ConnectionId( + "connection-1", + ), +] ``` # Query Connection Data @@ -77,31 +76,36 @@ __Example__ Query the connection end of connection `connection-1` on `ibc-1`: ```shell -hermes query connection end ibc-1 connection-1 | jq +hermes query connection end ibc-1 connection-1 ``` -```json -{ - "status": "success", - "result": { - "client_id": "07-tendermint-2", - "counterparty": { - "client_id": "07-tendermint-1", - "connection_id": "connection-0", - "prefix": "ibc" +```rust +Success: ConnectionEnd { + state: Open, + client_id: ClientId( + "07-tendermint-1", + ), + counterparty: Counterparty { + client_id: ClientId( + "07-tendermint-0", + ), + connection_id: Some( + ConnectionId( + "connection-0", + ), + ), + prefix: ibc, }, - "delay_period": 0, - "state": "Open", - "versions": [ - { - "features": [ - "ORDER_ORDERED", - "ORDER_UNORDERED" - ], - "identifier": "1" - } - ] - } + versions: [ + Version { + identifier: "1", + features: [ + "ORDER_ORDERED", + "ORDER_UNORDERED", + ], + }, + ], + delay_period: 0ns, } ``` @@ -126,15 +130,14 @@ __Example__ Query the channels associated with connection `connection-1` on `ibc-1`: ```shell -hermes query connection channels ibc-1 connection-1 | jq +hermes query connection channels ibc-1 connection-1 ``` -```json -{ - "status": "success", - "result": [ - "channel-1" - ] -} +```rust +Success: [ + ChannelId( + "channel-1", + ), +] ``` diff --git a/guide/src/queries.md b/guide/src/commands/queries/index.md similarity index 69% rename from guide/src/queries.md rename to guide/src/commands/queries/index.md index cfcccdc763..e31d157181 100644 --- a/guide/src/queries.md +++ b/guide/src/commands/queries/index.md @@ -6,13 +6,13 @@ The `query` command provides the following sub-commands: | CLI name | Description | | ---------------------- | ------------------------------------------------------------------------------ | -| `client` | [Query information about clients](./query_client.html) | -| `clients` | [Query all clients](./query_client.html) | -| `connection` | [Query information about connections](./query_connection.html) | -| `connections` | [Query the identifiers of all connections on a chain](./query_connection.html) | -| `channel` | [Query information about channels](./query_channel.html) | -| `channels` | [Query the identifiers of all channels on a given chain](./query_channel.html) | -| `packet` | [Query information about packets](./query_packet.html) | +| `client` | [Query information about clients](./client.md) | +| `clients` | [Query all clients](./client.md) | +| `connection` | [Query information about connections](./connection.md) | +| `connections` | [Query the identifiers of all connections on a chain](./connection.md) | +| `channel` | [Query information about channels](./channel.md) | +| `channels` | [Query the identifiers of all channels on a given chain](./channel.md) | +| `packet` | [Query information about packets](./packet.md) | ## Usage diff --git a/guide/src/query_packet.md b/guide/src/commands/queries/packet.md similarity index 80% rename from guide/src/query_packet.md rename to guide/src/commands/queries/packet.md index 91191fcbc8..3b07d50738 100644 --- a/guide/src/query_packet.md +++ b/guide/src/commands/queries/packet.md @@ -12,12 +12,12 @@ DESCRIPTION: Query information about packets SUBCOMMANDS: - commitments query packet commitments - commitment query packet commitment - acks query packet acknowledgments - ack query packet acknowledgment - unreceived-packets query unreceived packets - unreceived-acks query unreceived acknowledgments + commitments Query packet commitments + commitment Query packet commitment + acks Query packet acknowledgments + ack Query packet acknowledgment + unreceived-packets Query unreceived packets + unreceived-acks Query unreceived acknowledgments ``` ## Table of Contents @@ -47,23 +47,20 @@ __Example__ Query `ibc-0` for the sequence numbers of packets that still have commitments on `ibc-0` and that were sent on `transfer` port and `channel-0`: ```shell -hermes query packet commitments ibc-0 transfer channel-0 | jq +hermes query packet commitments ibc-0 transfer channel-0 ``` -```json -{ - "status": "success", - "result": { - "height": { - "revision_height": 139, - "revision_number": 0 +```rust +Success: PacketSeqs { + height: Height { + revision: 0, + height: 9154, }, - "seqs": [ - 1, - 2, - 3 - ] - } + seqs: [ + 1, + 2, + 3 + ], } ``` @@ -93,14 +90,11 @@ __Example__ Query `ibc-0` for the commitment of packet with sequence `3` sent on `transfer` port and `channel-0`: ```shell -hermes query packet commitment ibc-0 transfer channel-0 3 | jq +hermes query packet commitment ibc-0 transfer channel-0 3 ``` -```json -{ - "status": "success", - "result": "F9458DC7EBEBCD6D18E983FCAB5BD752CC2A74532BBD50B812DB229997739EFC" -} +```rust +Success: "F9458DC7EBEBCD6D18E983FCAB5BD752CC2A74532BBD50B812DB229997739EFC" ``` ## Packet Acknowledgments @@ -125,23 +119,20 @@ __Example__ Query `ibc-1` for the sequence numbers of packets acknowledged that were received on `transfer` port and `channel-1`: ```shell -hermes query packet acks ibc-1 transfer channel-1 | jq +hermes query packet acks ibc-1 transfer channel-1 ``` -```json -{ - "status": "success", - "result": { - "height": { - "revision_height": 397, - "revision_number": 1 +```rust +Success: PacketSeqs { + height: Height { + revision: 1, + height: 9547, }, - "seqs": [ - 1, - 2, - 3 - ] - } + seqs: [ + 1, + 2, + 3 + ], } ``` @@ -171,14 +162,11 @@ __Example__ Query `ibc-1` for the acknowledgment of packet with sequence `2` received on `transfer` port and `channel-1`: ```shell -hermes query packet ack ibc-1 transfer channel-1 2 | jq +hermes query packet ack ibc-1 transfer channel-1 2 ``` -```json -{ - "status": "success", - "result": "08F7557ED51826FE18D84512BF24EC75001EDBAF2123A477DF72A0A9F3640A7C" -} +```rust +Success: "08F7557ED51826FE18D84512BF24EC75001EDBAF2123A477DF72A0A9F3640A7C" ``` ## Unreceived Packets @@ -204,18 +192,15 @@ __Example__ Query `ibc-1` for the sequence numbers of packets sent on `ibc-0` on `transfer` port and `channel-0` but not yet received: ```shell -hermes query packet unreceived-packets ibc-1 ibc-0 transfer channel-0 | jq +hermes query packet unreceived-packets ibc-1 ibc-0 transfer channel-0 ``` ```json -{ - "status": "success", - "result": [ +Success: [ 1, 2, 3 - ] -} +] ``` ## Unreceived Acknowledgments @@ -241,16 +226,13 @@ __Example__ Query `ibc-0` for the sequence numbers of packets received on `ibc-1` on `transfer` port and `channel-1` but not yet acknowledged on `ibc-0`: ```shell -hermes query packet unreceived-acks ibc-0 ibc-1 transfer channel-1 | jq +hermes query packet unreceived-acks ibc-0 ibc-1 transfer channel-1 ``` ```json -{ - "status": "success", - "result": [ +Success: [ 1, 2, 3 - ] -} +] ``` diff --git a/guide/src/tx_channel_close.md b/guide/src/commands/raw/channel-close.md similarity index 50% rename from guide/src/tx_channel_close.md rename to guide/src/commands/raw/channel-close.md index 24abc12267..4e2e4b257d 100644 --- a/guide/src/tx_channel_close.md +++ b/guide/src/commands/raw/channel-close.md @@ -32,23 +32,39 @@ FLAGS: __Example__ ```shell -hermes tx raw chan-close-init ibc-0 ibc-1 connection-0 transfer transfer -d channel-0 -s channel-1 | jq +hermes tx raw chan-close-init ibc-0 ibc-1 connection-0 transfer transfer -d channel-0 -s channel-1 ``` -```json -{ - "status": "success", - "result": { - "CloseInitChannel": { - "channel_id": "channel-0", - "connection_id": "connection-0", - "counterparty_channel_id": "channel-1", - "counterparty_port_id": "transfer", - "height": "1", - "port_id": "transfer" - } - } -} +```rust +Success: CloseInitChannel( + CloseInit( + Attributes { + height: Height { + revision: 0, + height: 77, + }, + port_id: PortId( + "transfer", + ), + channel_id: Some( + ChannelId( + "channel-0", + ), + ), + connection_id: ConnectionId( + "connection-0", + ), + counterparty_port_id: PortId( + "transfer", + ), + counterparty_channel_id: Some( + ChannelId( + "channel-1", + ), + ), + }, + ), +) ``` ## Channel Close Confirm @@ -77,26 +93,42 @@ FLAGS: __Example__ ```shell -hermes tx raw chan-close-confirm ibc-1 ibc-0 connection-1 transfer transfer -d channel-1 -s channel-0 | jq +hermes tx raw chan-close-confirm ibc-1 ibc-0 connection-1 transfer transfer -d channel-1 -s channel-0 ``` -```json -{ - "status": "success", - "result": { - "CloseConfirmChannel": { - "channel_id": "channel-1", - "connection_id": "connection-1", - "counterparty_channel_id": "channel-0", - "counterparty_port_id": "transfer", - "height": "1", - "port_id": "transfer" - } - } -} +```rust +Success: CloseConfirmChannel( + CloseConfirm( + Attributes { + height: Height { + revision: 1, + height: 551, + }, + port_id: PortId( + "transfer", + ), + channel_id: Some( + ChannelId( + "channel-1", + ), + ), + connection_id: ConnectionId( + "connection-1", + ), + counterparty_port_id: PortId( + "transfer", + ), + counterparty_channel_id: Some( + ChannelId( + "channel-0", + ), + ), + }, + ), +) ``` -__NOTE__: The cosmos-sdk implementation does not allow the relayer to initiate the closing of channels. -Therefore, when using the Gaia release image, the `chan-close-init` command will -fail as the `cosmos-sdk` transfer module will reject the `MsgChannelCloseInit` message included in the transaction. -To be able to test channel closure, you will need to [patch](./help.html#patching-gaia) your gaia deployments. +__NOTE__: The `cosmos-sdk` transfer module implementation does not allow the user (`hermes` in this case) to initiate the closing of channels. +Therefore, when using the Gaia release image, the `chan-close-init` command +fails as the `MsgChannelCloseInit` message included in the transaction is rejected. +To be able to test channel closure, you need to [patch](../../help.md#patching-gaia) your gaia deployments. diff --git a/guide/src/tx_channel_open.md b/guide/src/commands/raw/channel-open.md similarity index 62% rename from guide/src/tx_channel_open.md rename to guide/src/commands/raw/channel-open.md index 26999e1e3f..6657f703b1 100644 --- a/guide/src/tx_channel_open.md +++ b/guide/src/commands/raw/channel-open.md @@ -48,7 +48,7 @@ POSITIONAL ARGUMENTS: src_port_id identifier of the source port FLAGS: - -o, --ordering ORDERING the channel order: `UNORDERED` or `ORDERED`, default `UNORDERED` + -o, --order ORDER the channel ordering, valid options 'unordered' (default) and 'ordered' ``` __Example__ @@ -56,23 +56,35 @@ __Example__ First, let's initialize the channel on `ibc-0` using an existing connection identified by `connection-0`: ```shell -hermes tx raw chan-open-init ibc-0 ibc-1 connection-0 transfer transfer | jq +hermes tx raw chan-open-init ibc-0 ibc-1 connection-0 transfer transfer ``` -```json -{ - "status": "success", - "result": { - "OpenInitChannel": { - "channel_id": "channel-0", - "connection_id": "connection-0", - "counterparty_channel_id": null, - "counterparty_port_id": "transfer", - "height": "1", - "port_id": "transfer" - } - } -} +```rust +Success: OpenInitChannel( + OpenInit( + Attributes { + height: Height { + revision: 0, + height: 3091 + }, + port_id: PortId( + "transfer", + ), + channel_id: Some( + ChannelId( + "channel-0", + ), + ), + connection_id: ConnectionId( + "connection-0", + ), + counterparty_port_id: PortId( + "transfer", + ), + counterparty_channel_id: None, + }, + ), +) ``` A new channel has been initialized on `ibc-1` with identifier `channel-0`. @@ -107,23 +119,39 @@ __Example__ Let's now create the counterparty to `channel-0` on chain `ibc-1`: ```shell -hermes tx raw chan-open-try ibc-1 ibc-0 connection-1 transfer transfer -s channel-0 | jq +hermes tx raw chan-open-try ibc-1 ibc-0 connection-1 transfer transfer -s channel-0 ``` -```json -{ - "status": "success", - "result": { - "OpenTryChannel": { - "channel_id": "channel-1", - "connection_id": "connection-1", - "counterparty_channel_id": "channel-0", - "counterparty_port_id": "transfer", - "height": "1", - "port_id": "transfer" - } - } -} +```rust +Success: OpenTryChannel( + OpenTry( + Attributes { + height: Height { + revision: 1, + height: 3213 + }, + port_id: PortId( + "transfer", + ), + channel_id: Some( + ChannelId( + "channel-1", + ), + ), + connection_id: ConnectionId( + "connection-1", + ), + counterparty_port_id: PortId( + "transfer", + ), + counterparty_channel_id: Some( + ChannelId( + "channel-0", + ), + ), + }, + ), +) ``` A new channel has been created on `ibc-1` with identifier `channel-1`. @@ -159,23 +187,39 @@ __Example__ We can now acknowledge on `ibc-0` that `ibc-1` has accepted the opening of the channel: ```shell -hermes tx raw chan-open-ack ibc-0 ibc-1 connection-0 transfer transfer -d channel-0 -s channel-1 | jq +hermes tx raw chan-open-ack ibc-0 ibc-1 connection-0 transfer transfer -d channel-0 -s channel-1 ``` -```json -{ - "status": "success", - "result": { - "OpenAckChannel": { - "channel_id": "channel-0", - "connection_id": "connection-0", - "counterparty_channel_id": "channel-1", - "counterparty_port_id": "transfer", - "height": "1", - "port_id": "transfer" - } - } -} +```rust +Success: OpenAckChannel( + OpenAck( + Attributes { + height: Height { + revision: 0, + height: 3301 + }, + port_id: PortId( + "transfer", + ), + channel_id: Some( + ChannelId( + "channel-0", + ), + ), + connection_id: ConnectionId( + "connection-0", + ), + counterparty_port_id: PortId( + "transfer", + ), + counterparty_channel_id: Some( + ChannelId( + "channel-1", + ), + ), + }, + ), +) ``` > Note that the field `counterparty_channel_id` now points to the channel on `ibc-1`. @@ -211,23 +255,38 @@ Confirm on `ibc-1` that `ibc-0` has accepted the opening of the channel, after which the channel is open on both chains. ```shell -hermes tx raw chan-open-confirm ibc-1 ibc-0 connection-1 transfer transfer channel-1 channel-0 | jq +hermes tx raw chan-open-confirm ibc-1 ibc-0 connection-1 transfer transfer -d channel-1 -s channel-0 ``` -```json -{ - "status": "success", - "result": { - "OpenConfirmChannel": { - "channel_id": "channel-1", - "connection_id": "connection-1", - "counterparty_channel_id": "channel-0", - "counterparty_port_id": "transfer", - "height": "1", - "port_id": "transfer" - } - } -} +```rust + OpenConfirm( + Attributes { + height: Height { + revision: 1, + height: 3483 + }, + port_id: PortId( + "transfer", + ), + channel_id: Some( + ChannelId( + "channel-1", + ), + ), + connection_id: ConnectionId( + "connection-1", + ), + counterparty_port_id: PortId( + "transfer", + ), + counterparty_channel_id: Some( + ChannelId( + "channel-0", + ), + ), + }, + ), +) ``` We have now successfully opened a channel over an existing connection between the two chains. diff --git a/guide/src/tx_client.md b/guide/src/commands/raw/client.md similarity index 55% rename from guide/src/tx_client.md rename to guide/src/commands/raw/client.md index bf1ec43b0d..58f27481e7 100644 --- a/guide/src/tx_client.md +++ b/guide/src/commands/raw/client.md @@ -25,23 +25,23 @@ __Example__ Create a new client of `ibc-1` on `ibc-0`: ```shell -hermes tx raw create-client ibc-0 ibc-1 | jq +hermes tx raw create-client ibc-0 ibc-1 ``` -```json +```rust { - "status": "success", - "result": { - "CreateClient": { - "client_id": "07-tendermint-0", - "client_type": "Tendermint", - "consensus_height": { - "revision_height": 18, - "revision_number": 1 - }, - "height": "1" - } - } + Success: CreateClient( + CreateClient( + Attributes { + height: Height { revision: 0, height: 43 }, + client_id: ClientId( + "07-tendermint-0", + ), + client_type: Tendermint, + consensus_height: Height { revision: 1, height: 32 }, + }, + ), + ) } ``` @@ -49,6 +49,7 @@ A new client is created with identifier `07-tendermint-0` ## Update Client Use the `update-client` command to update an existing client with a new consensus state. +Specific update and trusted heights can be specified. ```shell USAGE: @@ -59,8 +60,11 @@ DESCRIPTION: POSITIONAL ARGUMENTS: dst_chain_id identifier of the destination chain - src_chain_id identifier of the source chain dst_client_id identifier of the client to be updated on destination chain + +FLAGS: + -h, --target-height TARGET-HEIGHT + -t, --trusted-height TRUSTED-HEIGHT ``` __Example__ @@ -68,24 +72,25 @@ __Example__ Update the client on `ibc-0` with latest header of `ibc-1` ```shell -hermes tx raw update-client ibc-0 ibc-1 07-tendermint-0 | jq +hermes tx raw update-client ibc-0 07-tendermint-0 ``` ```json -{ - "status": "success", - "result": { - "UpdateClient": { - "client_id": "07-tendermint-0", - "client_type": "Tendermint", - "consensus_height": { - "revision_height": 273, - "revision_number": 1 - }, - "height": "1" - } - } -} +Success: UpdateClient( + UpdateClient { + common: Attributes { + height: Height { revision: 0, height: 110 }, + client_id: ClientId( + "07-tendermint-0", + ), + client_type: Tendermint, + consensus_height: Height { revision: 1, height: 109 }, + }, + header: Some( + Tendermint(...), + ), + }, +) ``` The client with identifier `07-tendermint-0` has been updated with the consensus state at height `1-273`. diff --git a/guide/src/tx_connection.md b/guide/src/commands/raw/connection.md similarity index 63% rename from guide/src/tx_connection.md rename to guide/src/commands/raw/connection.md index f799cdc740..80d656e1b7 100644 --- a/guide/src/tx_connection.md +++ b/guide/src/commands/raw/connection.md @@ -58,19 +58,29 @@ First, let's initialize the connection on `ibc-0`: hermes tx raw conn-init ibc-0 ibc-1 07-tendermint-0 07-tendermint-1 ``` -```json -{ - "status": "success", - "result": { - "OpenInitConnection": { - "client_id": "07-tendermint-0", - "connection_id": "connection-0", - "counterparty_client_id": "07-tendermint-1", - "counterparty_connection_id": null, - "height": "1" - } - } -} +```rust +Success: OpenInitConnection( + OpenInit( + Attributes { + height: Height { + revision: 0, + height: 73, + }, + connection_id: Some( + ConnectionId( + "connection-0", + ), + ), + client_id: ClientId( + "07-tendermint-0", + ), + counterparty_connection_id: None, + counterparty_client_id: ClientId( + "07-tendermint-1", + ), + }, + ), +) ``` A new connection has been initialized on `ibc-0` with identifier `connection-0`. @@ -104,22 +114,36 @@ __Example__ Let's now create the counterparty to `connection-0` on chain `ibc-1`: ```shell -hermes tx raw conn-try ibc-1 ibc-0 07-tendermint-1 07-tendermint-0 -s connection-0 | jq +hermes tx raw conn-try ibc-1 ibc-0 07-tendermint-1 07-tendermint-0 -s connection-0 ``` -```json -{ - "status": "success", - "result": { - "OpenTryConnection": { - "client_id": "07-tendermint-1", - "connection_id": "connection-1", - "counterparty_client_id": "07-tendermint-0", - "counterparty_connection_id": "connection-0", - "height": "1" - } - } -} +```rust +Success: OpenTryConnection( + OpenTry( + Attributes { + height: Height { + revision: 1, + height: 88, + }, + connection_id: Some( + ConnectionId( + "connection-1", + ), + ), + client_id: ClientId( + "07-tendermint-1", + ), + counterparty_connection_id: Some( + ConnectionId( + "connection-0", + ), + ), + counterparty_client_id: ClientId( + "07-tendermint-0", + ), + }, + ), +) ``` A new connection has been created on `ibc-1` with identifier `connection-1`. @@ -154,22 +178,36 @@ __Example__ We can now acknowledge on `ibc-0` that `ibc-1` has accepted the connection attempt: ```shell -hermes tx raw conn-ack ibc-0 ibc-1 07-tendermint-0 07-tendermint-1 -d connection-0 -s connection-1 | jq +hermes tx raw conn-ack ibc-0 ibc-1 07-tendermint-0 07-tendermint-1 -d connection-0 -s connection-1 ``` -```json -{ - "status": "success", - "result": { - "OpenAckConnection": { - "client_id": "07-tendermint-0", - "connection_id": "connection-0", - "counterparty_client_id": "07-tendermint-1", - "counterparty_connection_id": "connection-1", - "height": "1" - } - } -} +```rust +Success: OpenAckConnection( + OpenAck( + Attributes { + height: Height { + revision: 0, + height: 206, + }, + connection_id: Some( + ConnectionId( + "connection-0", + ), + ), + client_id: ClientId( + "07-tendermint-0", + ), + counterparty_connection_id: Some( + ConnectionId( + "connection-1", + ), + ), + counterparty_client_id: ClientId( + "07-tendermint-1", + ), + }, + ), +) ``` > Note that the field `counterparty_connection_id` now points to the connection on `ibc-1`. @@ -203,22 +241,36 @@ __Example__ Confirm on `ibc-1` that `ibc-0` has accepted the connection attempt. ```shell -hermes tx raw conn-confirm ibc-1 ibc-0 07-tendermint-1 07-tendermint-0 -d connection-1 -s connection-0 | jq +hermes tx raw conn-confirm ibc-1 ibc-0 07-tendermint-1 07-tendermint-0 -d connection-1 -s connection-0 ``` -```json -{ - "status": "success", - "result": { - "OpenConfirmConnection": { - "client_id": "07-tendermint-1", - "connection_id": "connection-1", - "counterparty_client_id": "07-tendermint-0", - "counterparty_connection_id": "connection-0", - "height": "1" - } - } -} +```rust +Success: OpenConfirmConnection( + OpenConfirm( + Attributes { + height: Height { + revision: 1, + height: 239, + }, + connection_id: Some( + ConnectionId( + "connection-1", + ), + ), + client_id: ClientId( + "07-tendermint-1", + ), + counterparty_connection_id: Some( + ConnectionId( + "connection-0", + ), + ), + counterparty_client_id: ClientId( + "07-tendermint-0", + ), + }, + ), +) ``` We have now successfully established a connection between the two chains. diff --git a/guide/src/transactions.md b/guide/src/commands/raw/index.md similarity index 76% rename from guide/src/transactions.md rename to guide/src/commands/raw/index.md index 94b3c032d0..c4c4093015 100644 --- a/guide/src/transactions.md +++ b/guide/src/commands/raw/index.md @@ -6,21 +6,21 @@ The `tx raw` command provides the following sub-commands: | CLI name | Description | | ---------------------- | --------------------------------------------------------------------------------------------------------------- | -| `create-client` | [Create a client for source chain on destination chain](./tx_client.html#create-client) | -| `update-client` | [Update the specified client on destination chain](./tx_client.html#update-client) | -| `conn-init` | [Initialize a connection (ConnectionOpenInit)](./tx_connection.html#connection-init) | -| `conn-try` | [Relay the connection attempt (ConnectionOpenTry)](./tx_connection.html#connection-try) | -| `conn-ack` | [Relay acknowledgment of a connection attempt (ConnectionOpenAck)](./tx_connection.html#connection-ack) | -| `conn-confirm` | [Confirm opening of a connection (ConnectionOpenConfirm)](./tx_connection.html#connection-confirm) | -| `chan-open-init` | [Initialize a channel (ChannelOpenInit)](./tx_channel_open.html#channel-open-init) | -| `chan-open-try` | [Relay the channel attempt (ChannelOpenTry)](./tx_channel_open.html#channel-open-try) | -| `chan-open-ack` | [Relay acknowledgment of a channel attempt (ChannelOpenAck)](./tx_channel_open.html#channel-open-ack) | -| `chan-open-close` | [Confirm opening of a channel (ChannelOpenConfirm)](./tx_channel_open.html#channel-open-close) | -| `chan-close-init` | [Initiate the closing of a channel (ChannelCloseInit)](./tx_channel_close.html#channel-close-init) | -| `chan-close-confirm` | [Confirm the closing of a channel (ChannelCloseConfirm)](./tx_channel_close.html#channel-close-confirm) | -| `ft-transfer` | [Send a fungible token transfer test transaction (ICS20 MsgTransfer)](./tx_packet.html#fungible-token-transfer) | -| `packet-recv` | [Relay receive or timeout packets](./tx_packet.html#relay-receive-and-timeout-packets) | -| `packet-ack` | [Relay acknowledgment packets](./tx_packet.html#relay-acknowledgment-packets) | +| `create-client` | [Create a client for source chain on destination chain](./client.md#create-client) | +| `update-client` | [Update the specified client on destination chain](./client.md#update-client) | +| `conn-init` | [Initialize a connection (ConnectionOpenInit)](./connection.md#connection-init) | +| `conn-try` | [Relay the connection attempt (ConnectionOpenTry)](./connection.md#connection-try) | +| `conn-ack` | [Relay acknowledgment of a connection attempt (ConnectionOpenAck)](./connection.md#connection-ack) | +| `conn-confirm` | [Confirm opening of a connection (ConnectionOpenConfirm)](./connection.md#connection-confirm) | +| `chan-open-init` | [Initialize a channel (ChannelOpenInit)](./channel-open.md#channel-open-init) | +| `chan-open-try` | [Relay the channel attempt (ChannelOpenTry)](./channel-open.md#channel-open-try) | +| `chan-open-ack` | [Relay acknowledgment of a channel attempt (ChannelOpenAck)](./channel-open.md#channel-open-ack) | +| `chan-open-close` | [Confirm opening of a channel (ChannelOpenConfirm)](./channel-open.md#channel-open-close) | +| `chan-close-init` | [Initiate the closing of a channel (ChannelCloseInit)](./channel-close.md#channel-close-init) | +| `chan-close-confirm` | [Confirm the closing of a channel (ChannelCloseConfirm)](./channel-close.md#channel-close-confirm) | +| `ft-transfer` | [Send a fungible token transfer test transaction (ICS20 MsgTransfer](./packet.md#fungible-token-transfer) | +| `packet-recv` | [Relay receive or timeout packets](./packet.md#relay-receive-and-timeout-packets) | +| `packet-ack` | [Relay acknowledgment packets](./packet.md#relay-acknowledgment-packets) | The main purpose of these commands is to support development and testing, and continuous integration. These CLIs take quite a few parameters and they are explained in the individual sub-sections. @@ -50,15 +50,15 @@ In the command template above: - `src-obj-id` - the identifier of an object on the source chain, required by the datagram, e.d. the `client-id` of the connection on source chain. - More details about the `tx raw` commands can be found in the following sections: - - [Client](./tx_client.md) - - [Connection](./tx_connection.md) - - [Channel Open](./tx_channel_open.md) - - [Channel Close](./tx_channel_close.md) - - [Packet](./tx_packet.md) + - [Client](./client.md) + - [Connection](./connection.md) + - [Channel Open](./channel-open.md) + - [Channel Close](./channel-close.md) + - [Packet](./packet.md) ## Usage -```shell script +```shell USAGE: hermes tx raw diff --git a/guide/src/commands/raw/packet.md b/guide/src/commands/raw/packet.md new file mode 100644 index 0000000000..6cfbb6b079 --- /dev/null +++ b/guide/src/commands/raw/packet.md @@ -0,0 +1,270 @@ +# Packet Tx Commands + +## Table of Contents + + + +## Fungible token transfer + +Use the `tx raw ft-transfer` command to send ICS-20 fungible token transfer packets. +__NOTE:__ This command is mainly used for testing the packet features of the relayer. + +```shell +USAGE: + hermes tx raw ft-transfer + +DESCRIPTION: + Send a fungible token transfer test transaction (ICS20 MsgTransfer) + +POSITIONAL ARGUMENTS: + dst_chain_id identifier of the destination chain + src_chain_id identifier of the source chain + src_port_id identifier of the source port + src_channel_id identifier of the source channel + amount amount of coins (samoleans, by default) to send (e.g. `100000`) + height_offset timeout in number of blocks since current + +FLAGS: + -r, --receiver RECEIVER receiving account address on the destination chain + -d, --denom DENOM denomination of the coins to send (default: samoleans) + -n, --number-msgs NUMBER-MSGS +``` + +__Example__ + +Send two transfer packets from the `transfer` module and `channel-0` of `ibc-0` to `ibc-1`. Each transfer if for `9999` samoleans (default denomination) and a timeout offset of `10` blocks. The transfer fee is paid by the relayer account on `ibc-1`. + +```shell +hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-0 9999 1000 -n 2 +``` + +```rust +Success: [ + SendPacket( + SendPacket { + height: Height { + revision: 0, + height: 431, + }, + packet: PortId("transfer") ChannelId("channel-0") Sequence(4), + }, + ), + SendPacket( + SendPacket { + height: Height { + revision: 0, + height: 431, + }, + packet: PortId("transfer") ChannelId("channel-0") Sequence(5), + }, + ), +] +``` + +The transfer packets are stored on `ibc-0` and can be relayed. + +> To send transfer packets with a custom receiver address use the `--receiver | -r` flag. + +```shell +hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-0 9999 1000 -n 1 -r board:1938586739 +``` + +```rust +Success: [ + SendPacket( + SendPacket { + height: Height { + revision: 0, + height: 546, + }, + packet: PortId("transfer") ChannelId("channel-0") Sequence(7), + }, + ), +] +``` + +## Relay receive and timeout packets + +Use the `tx raw packet-recv` command to relay the packets sent but not yet received. If the sent packets have timed out then a timeout packet is sent to the source chain. + +```shell +USAGE: + hermes tx raw packet-recv + +DESCRIPTION: + Relay receive or timeout packets + +POSITIONAL ARGUMENTS: + dst_chain_id identifier of the destination chain + src_chain_id identifier of the source chain + src_port_id identifier of the source port + src_channel_id identifier of the source channel +``` + +__Example__ + +Send the two transfer packets to the `ibc-1` module bound to the `transfer` port and the `channel-0`'s counterparty. + +__NOTE__: The relayer prepends a client update message before the receive messages. + +```shell +hermes tx raw packet-recv ibc-1 ibc-0 transfer channel-0 +``` + +```rust +Success: [ + UpdateClient( + UpdateClient { + common: Attributes { + height: Height { + revision: 1, + height: 439, + }, + client_id: ClientId( + "07-tendermint-1", + ), + client_type: Tendermint, + consensus_height: Height { + revision: 0, + height: 449, + }, + }, + header: Some( + Tendermint(...), + ), + }, + ), + WriteAcknowledgement( + WriteAcknowledgement { + height: Height { + revision: 1, + height: 439, + }, + packet: PortId("transfer") ChannelId("channel-0") Sequence(4), + ack: [ + 123, + 34, + 114, + 101, + 115, + 117, + 108, + 116, + 34, + 58, + 34, + 65, + 81, + 61, + 61, + 34, + 125, + ], + }, + ), + WriteAcknowledgement( + WriteAcknowledgement { + height: Height { + revision: 1, + height: 439, + }, + packet: PortId("transfer") ChannelId("channel-0") Sequence(5), + ack: [ + 123, + 34, + 114, + 101, + 115, + 117, + 108, + 116, + 34, + 58, + 34, + 65, + 81, + 61, + 61, + 34, + 125, + ], + }, + ), +] +``` + +Both packets have been relayed to `ibc-1` and acknowledged. + +## Relay acknowledgment packets + +Use the `tx raw packet-ack` command to relay acknowledgments to the original source of the packets. + +```shell +USAGE: + hermes tx raw packet-ack + +DESCRIPTION: + Relay acknowledgment packets + +POSITIONAL ARGUMENTS: + dst_chain_id identifier of the destination chain + src_chain_id identifier of the source chain + src_port_id identifier of the source port + src_channel_id identifier of the source channel +``` + +__Example__ + +Send the acknowledgments to the `ibc-0` module bound to the `transfer` port and the `channel-1`'s counterparty. + +__NOTE__: The relayer prepends a client update message before the acknowledgments. + +```shell +hermes tx raw packet-ack ibc-0 ibc-1 transfer channel-1 +``` + +```rust +Success: [ + UpdateClient( + UpdateClient { + common: Attributes { + height: Height { + revision: 0, + height: 495, + }, + client_id: ClientId( + "07-tendermint-0", + ), + client_type: Tendermint, + consensus_height: Height { + revision: 1, + height: 483, + }, + }, + header: Some( + Tendermint(...), + ), + }, + ), + AcknowledgePacket( + AcknowledgePacket { + height: Height { + revision: 0, + height: 495, + }, + packet: PortId("transfer") ChannelId("channel-0") Sequence(4), + }, + ), + AcknowledgePacket( + AcknowledgePacket { + height: Height { + revision: 0, + height: 495, + }, + packet: PortId("transfer") ChannelId("channel-0") Sequence(5), + }, + ), +] +``` + +Both acknowledgments have been received on `ibc-0`. diff --git a/guide/src/commands/setup-and-relaying/channels.md b/guide/src/commands/setup-and-relaying/channels.md new file mode 100644 index 0000000000..29562bdf86 --- /dev/null +++ b/guide/src/commands/setup-and-relaying/channels.md @@ -0,0 +1,476 @@ +# Channel + +## Table of Contents + + + +## Establish Channel + +Use the `create channel` command to establish a new channel. + +```shell +USAGE: + hermes create channel + +DESCRIPTION: + Create a new channel between two chains + +POSITIONAL ARGUMENTS: + chain_a_id identifier of the side `a` chain for the new channel + chain_b_id identifier of the side `b` chain for the new channel (optional) + +FLAGS: + -c, --connection-a CONNECTION-A + --port-a PORT-A identifier of the side `a` port for the new channel + --port-b PORT-B identifier of the side `b` port for the new channel + -o, --order ORDER the channel ordering, valid options 'unordered' (default) and 'ordered' + -v, --version VERSION the version for the new channel +``` + +## Examples + +### New channel over a new connection + +Create a new unordered channel between `ibc-0` and `ibc-1` over a new connection, using +port name `transfer` on both sides: + +```shell +hermes create channel ibc-0 ibc-1 --port-a transfer --port-b transfer -o unordered +``` + +```rust +🥂 ibc-0 => OpenInitConnection( + OpenInit( + Attributes { + height: Height { revision: 0, height: 66 }, + connection_id: Some( + ConnectionId( + "connection-0", + ), + ), + client_id: ClientId( + "07-tendermint-0", + ), + counterparty_connection_id: None, + counterparty_client_id: ClientId( + "07-tendermint-0", + ), + }, + ), +) + +🥂 ibc-1 => OpenTryConnection( + OpenTry( + Attributes { + height: Height { revision: 1, height: 64 }, + connection_id: Some( + ConnectionId( + "connection-0", + ), + ), + client_id: ClientId( + "07-tendermint-0", + ), + counterparty_connection_id: Some( + ConnectionId( + "connection-0", + ), + ), + counterparty_client_id: ClientId( + "07-tendermint-0", + ), + }, + ), +) + +🥂 ibc-0 => OpenAckConnection( + OpenAck( + Attributes { + height: Height { revision: 0, height: 76 }, + connection_id: Some( + ConnectionId( + "connection-0", + ), + ), + client_id: ClientId( + "07-tendermint-0", + ), + counterparty_connection_id: Some( + ConnectionId( + "connection-0", + ), + ), + counterparty_client_id: ClientId( + "07-tendermint-0", + ), + }, + ), +) + +🥂 ibc-1 => OpenConfirmConnection( + OpenConfirm( + Attributes { + height: Height { revision: 1, height: 68 }, + connection_id: Some( + ConnectionId( + "connection-0", + ), + ), + client_id: ClientId( + "07-tendermint-0", + ), + counterparty_connection_id: Some( + ConnectionId( + "connection-0", + ), + ), + counterparty_client_id: ClientId( + "07-tendermint-0", + ), + }, + ), +) + +🥂🥂🥂 Connection handshake finished for [Connection { + delay_period: 0ns, + a_side: ConnectionSide { + chain: ProdChainHandle { + chain_id: ChainId { + id: "ibc-0", + version: 0, + }, + runtime_sender: Sender { .. }, + }, + client_id: ClientId( + "07-tendermint-0", + ), + connection_id: ConnectionId( + "connection-0", + ), + }, + b_side: ConnectionSide { + chain: ProdChainHandle { + chain_id: ChainId { + id: "ibc-1", + version: 1, + }, + runtime_sender: Sender { .. }, + }, + client_id: ClientId( + "07-tendermint-0", + ), + connection_id: ConnectionId( + "connection-0", + ), + }, +}] + +🥳 ibc-0 => OpenInitChannel( + OpenInit( + Attributes { + height: Height { revision: 0, height: 78 }, + port_id: PortId("transfer"), + channel_id: Some(ChannelId("channel-0")), + connection_id: ConnectionId("connection-0"), + counterparty_port_id: PortId("transfer"), + counterparty_channel_id: None + } + ) +) + +🥳 ibc-1 => OpenTryChannel( + OpenTry( + Attributes { + height: Height { revision: 1, height: 70 }, + port_id: PortId("transfer"), + channel_id: Some(ChannelId("channel-0")), + connection_id: ConnectionId("connection-0"), + counterparty_port_id: PortId("transfer"), + counterparty_channel_id: Some(ChannelId("channel-0")) + } + ) +) + +🥳 ibc-0 => OpenAckChannel( + OpenAck( + Attributes { + height: Height { revision: 0, height: 81 }, + port_id: PortId("transfer"), + channel_id: Some(ChannelId("channel-0")), + connection_id: ConnectionId("connection-0"), + counterparty_port_id: PortId("transfer"), + counterparty_channel_id: Some(ChannelId("channel-0")) + } + ) +) + +🥳 ibc-1 => OpenConfirmChannel + OpenConfirm + Attributes { + height: Height { revision: 1, height: 73 }, + port_id: PortId("transfer"), + channel_id: Some(ChannelId("channel-0")), + connection_id: ConnectionId("connection-0"), + counterparty_port_id: PortId("transfer"), + counterparty_channel_id: Some(ChannelId("channel-0")) + } + ) +) + +🥳 🥳 🥳 Channel handshake finished for Channel { + ordering: Unordered, + a_side: ChannelSide { + chain: ProdChainHandle { + chain_id: ChainId { + id: "ibc-0", + version: 0, + }, + runtime_sender: Sender { .. }, + }, + client_id: ClientId( + "07-tendermint-0", + ), + connection_id: ConnectionId( + "connection-0", + ), + port_id: PortId( + "transfer", + ), + channel_id: ChannelId( + "channel-0", + ), + }, + b_side: ChannelSide { + chain: ProdChainHandle { + chain_id: ChainId { + id: "ibc-1", + version: 1, + }, + runtime_sender: Sender { .. }, + }, + client_id: ClientId( + "07-tendermint-0", + ), + connection_id: ConnectionId( + "connection-0", + ), + port_id: PortId( + "transfer", + ), + channel_id: ChannelId( + "channel-0", + ), + }, + connection_delay: 0ns, +} + +Success: Channel { + ordering: Unordered, + a_side: ChannelSide { + chain: ProdChainHandle { + chain_id: ChainId { + id: "ibc-0", + version: 0, + }, + runtime_sender: Sender { .. }, + }, + client_id: ClientId( + "07-tendermint-0", + ), + connection_id: ConnectionId( + "connection-0", + ), + port_id: PortId( + "transfer", + ), + channel_id: ChannelId( + "channel-0", + ), + }, + b_side: ChannelSide { + chain: ProdChainHandle { + chain_id: ChainId { + id: "ibc-1", + version: 1, + }, + runtime_sender: Sender { .. }, + }, + client_id: ClientId( + "07-tendermint-0", + ), + connection_id: ConnectionId( + "connection-0", + ), + port_id: PortId( + "transfer", + ), + channel_id: ChannelId( + "channel-0", + ), + }, + connection_delay: 0ns, +} +``` + +A new channel with identifier `channel-0` on both sides has been established on +a new connection with identifier `connection-0` on both sides. + +### New channel over an existing connection + +Create a new unordered channel between `ibc-0` and `ibc-1` over an existing connection, +specifically the one we just created in the example above, with port name `transfer` on both sides: + +```shell +hermes create channel ibc-0 --connection-a connection-0 --port-a transfer --port-b transfer -o unordered +``` + +Notice that one can omit the destination chain parameter, as Hermes will automatically +figure it out by looking up the given connection on `ibc-0`. + +```rust +🥳 ibc-0 => OpenInitChannel( + OpenInit( + Attributes { + height: Height { revision: 0, height: 129 }, + port_id: PortId("transfer"), + channel_id: Some(ChannelId("channel-1")), + connection_id: ConnectionId("connection-0"), + counterparty_port_id: PortId("transfer"), + counterparty_channel_id: None + } + ) +) + +🥳 ibc-1 => OpenTryChannel( + OpenTry( + Attributes { + height: Height { revision: 1, height: 126 }, + port_id: PortId("transfer"), + channel_id: Some(ChannelId("channel-1")), + connection_id: ConnectionId("connection-0"), + counterparty_port_id: PortId("transfer"), + counterparty_channel_id: Some(ChannelId("channel-1")) + } + ) +) + +🥳 ibc-0 => OpenAckChannel( + OpenAck( + Attributes { + height: Height { revision: 0, height: 137 }, + port_id: PortId("transfer"), + channel_id: Some(ChannelId("channel-1")), + connection_id: ConnectionId("connection-0"), + counterparty_port_id: PortId("transfer"), + counterparty_channel_id: Some(ChannelId("channel-1")) + } + ) +) + +🥳 ibc-1 => OpenConfirmChannel( + OpenConfirm( + Attributes { + height: Height { revision: 1, height: 129 }, + port_id: PortId("transfer"), + channel_id: Some(ChannelId("channel-1")), + connection_id: ConnectionId("connection-0"), + counterparty_port_id: PortId("transfer"), + counterparty_channel_id: Some(ChannelId("channel-1")) + } + ) +) + +🥳 🥳 🥳 Channel handshake finished for Channel { + ordering: Unordered, + a_side: ChannelSide { + chain: ProdChainHandle { + chain_id: ChainId { + id: "ibc-0", + version: 0, + }, + runtime_sender: Sender { .. }, + }, + client_id: ClientId( + "07-tendermint-0", + ), + connection_id: ConnectionId( + "connection-0", + ), + port_id: PortId( + "transfer", + ), + channel_id: ChannelId( + "channel-1", + ), + }, + b_side: ChannelSide { + chain: ProdChainHandle { + chain_id: ChainId { + id: "ibc-1", + version: 1, + }, + runtime_sender: Sender { .. }, + }, + client_id: ClientId( + "07-tendermint-0", + ), + connection_id: ConnectionId( + "connection-0", + ), + port_id: PortId( + "transfer", + ), + channel_id: ChannelId( + "channel-1", + ), + }, + connection_delay: 0ns, +} + +Success: Channel { + ordering: Unordered, + a_side: ChannelSide { + chain: ProdChainHandle { + chain_id: ChainId { + id: "ibc-0", + version: 0, + }, + runtime_sender: Sender { .. }, + }, + client_id: ClientId( + "07-tendermint-0", + ), + connection_id: ConnectionId( + "connection-0", + ), + port_id: PortId( + "transfer", + ), + channel_id: ChannelId( + "channel-1", + ), + }, + b_side: ChannelSide { + chain: ProdChainHandle { + chain_id: ChainId { + id: "ibc-1", + version: 1, + }, + runtime_sender: Sender { .. }, + }, + client_id: ClientId( + "07-tendermint-0", + ), + connection_id: ConnectionId( + "connection-0", + ), + port_id: PortId( + "transfer", + ), + channel_id: ChannelId( + "channel-1", + ), + }, + connection_delay: 0ns, +} +``` diff --git a/guide/src/commands/setup-and-relaying/clients.md b/guide/src/commands/setup-and-relaying/clients.md new file mode 100644 index 0000000000..03e9a06438 --- /dev/null +++ b/guide/src/commands/setup-and-relaying/clients.md @@ -0,0 +1,121 @@ +# Client + +## Table of Contents + + + +## Create Client + +Use the `create client` command to create a new client. + +```shell +USAGE: + hermes create client + +DESCRIPTION: + Create a new IBC client + +POSITIONAL ARGUMENTS: + dst_chain_id identifier of the destination chain + src_chain_id identifier of the source chain +``` + +__Example__ + +Create a new client of `ibc-1` on `ibc-0`: + +```shell +hermes create client ibc-0 ibc-1 +``` + +```rust +Success: CreateClient( + CreateClient( + Attributes { + height: Height { revision: 0, height: 264 }, + client_id: ClientId( + "07-tendermint-1", + ), + client_type: Tendermint, + consensus_height: Height { revision: 1, height: 253 }, + }, + ), +) +``` + +A new client is created with identifier `07-tendermint-1` + +## Update Client + +Use the `update client` command to update an existing client with a new consensus state. +Specific update and trusted heights can be specified. + +```shell +USAGE: + hermes update client + +DESCRIPTION: + Update an IBC client + +POSITIONAL ARGUMENTS: + dst_chain_id identifier of the destination chain + dst_client_id identifier of the client to be updated on destination chain + +FLAGS: + -h, --target-height TARGET-HEIGHT + -t, --trusted-height TRUSTED-HEIGHT +``` + +__Update client with latest header__ + +the client on `ibc-0` with latest header of `ibc-1`: + +```shell +hermes update client ibc-0 07-tendermint-9 +``` + +```rust +Success: UpdateClient( + UpdateClient { + common: Attributes { + height: Height { revision: 0, height: 303 }, + client_id: ClientId( + "07-tendermint-1", + ), + client_type: Tendermint, + consensus_height: Height { revision: 1, height: 293 }, + }, + header: Some( + Tendermint(...), + ), + }, +) +``` + +The client with identifier `07-tendermint-1` has been updated with the consensus state at height `1-293`. + +__Update a client to a specific target height__ + +```shell +hermes update client ibc-0 07-tendermint-1 --target-height 320 --trusted-height 293 +``` + +```rust +Success: UpdateClient( + UpdateClient { + common: Attributes { + height: Height { revision: 0, height: 555 }, + client_id: ClientId( + "07-tendermint-1", + ), + client_type: Tendermint, + consensus_height: Height { revision: 1, height: 320 }, + }, + header: Some( + Tendermint(...), + ), + }, +) +``` + +The client with identifier `07-tendermint-1` has been updated with the consensus state at height `1-320`, as specified. diff --git a/guide/src/commands/setup-and-relaying/connections.md b/guide/src/commands/setup-and-relaying/connections.md new file mode 100644 index 0000000000..14e688066b --- /dev/null +++ b/guide/src/commands/setup-and-relaying/connections.md @@ -0,0 +1,197 @@ +# Connection + +## Table of Contents + + + +## Establish Connection +Use the `create connection` command to create a new connection. + +```shell +USAGE: + hermes create connection + +DESCRIPTION: + Create a new connection between two chains + +POSITIONAL ARGUMENTS: + chain_a_id identifier of the side `a` chain for the new connection + chain_b_id identifier of the side `b` chain for the new connection + +FLAGS: + --client-a CLIENT-A identifier of client hosted on chain `a`; default: None (creates a new client) + --client-b CLIENT-B identifier of client hosted on chain `b`; default: None (creates a new client) + +``` + +__Example__ + +```shell +hermes create connection ibc-0 ibc-1 +``` + +```rust +🥂 ibc-0 => OpenInitConnection( + OpenInit( + Attributes { + height: Height { revision: 0, height: 4073 }, + connection_id: Some( + ConnectionId( + "connection-8", + ), + ), + client_id: ClientId( + "07-tendermint-8", + ), + counterparty_connection_id: None, + counterparty_client_id: ClientId( + "07-tendermint-8", + ), + }, + ), +) + +🥂 ibc-1 => OpenTryConnection( + OpenTry( + Attributes { + height: Height { revision: 1, height: 4069 }, + connection_id: Some( + ConnectionId( + "connection-8", + ), + ), + client_id: ClientId( + "07-tendermint-8", + ), + counterparty_connection_id: Some( + ConnectionId( + "connection-8", + ), + ), + counterparty_client_id: ClientId( + "07-tendermint-8", + ), + }, + ), +) + +🥂 ibc-0 => OpenAckConnection( + OpenAck( + Attributes { + height: Height { revision: 0, height: 4081 }, + connection_id: Some( + ConnectionId( + "connection-8", + ), + ), + client_id: ClientId( + "07-tendermint-8", + ), + counterparty_connection_id: Some( + ConnectionId( + "connection-8", + ), + ), + counterparty_client_id: ClientId( + "07-tendermint-8", + ), + }, + ), +) + +🥂 ibc-1 => OpenConfirmConnection( + OpenConfirm( + Attributes { + height: Height { revision: 1, height: 4073 }, + connection_id: Some( + ConnectionId( + "connection-8", + ), + ), + client_id: ClientId( + "07-tendermint-8", + ), + counterparty_connection_id: Some( + ConnectionId( + "connection-8", + ), + ), + counterparty_client_id: ClientId( + "07-tendermint-8", + ), + }, + ), +) + +🥂🥂🥂 Connection handshake finished for [Connection { + delay_period: 0ns, + a_side: ConnectionSide { + chain: ProdChainHandle { + chain_id: ChainId { + id: "ibc-0", + version: 0, + }, + runtime_sender: Sender { .. }, + }, + client_id: ClientId( + "07-tendermint-8", + ), + connection_id: ConnectionId( + "connection-8", + ), + }, + b_side: ConnectionSide { + chain: ProdChainHandle { + chain_id: ChainId { + id: "ibc-1", + version: 1, + }, + runtime_sender: Sender { .. }, + }, + client_id: ClientId( + "07-tendermint-8", + ), + connection_id: ConnectionId( + "connection-8", + ), + }, +}] + +Success: Connection { + delay_period: 0ns, + a_side: ConnectionSide { + chain: ProdChainHandle { + chain_id: ChainId { + id: "ibc-0", + version: 0, + }, + runtime_sender: Sender { .. }, + }, + client_id: ClientId( + "07-tendermint-8", + ), + connection_id: ConnectionId( + "connection-8", + ), + }, + b_side: ConnectionSide { + chain: ProdChainHandle { + chain_id: ChainId { + id: "ibc-1", + version: 1, + }, + runtime_sender: Sender { .. }, + }, + client_id: ClientId( + "07-tendermint-8", + ), + connection_id: ConnectionId( + "connection-8", + ), + }, +} +``` + +## Non-zero Delay Connection + +A connection can be created with a delay period parameter. This parameter specifies a period of time that must elpase after a successful client state update and before a packet with proofs using its commitment root can pe processed on chain. For more information see [how packet delay works](./packets.md#packet-delay) and the [connection delay specification](https://github.com/cosmos/ibc/tree/master/spec/core/ics-003-connection-semantics). diff --git a/guide/src/commands/setup-and-relaying/index.md b/guide/src/commands/setup-and-relaying/index.md new file mode 100644 index 0000000000..fa62c13030 --- /dev/null +++ b/guide/src/commands/setup-and-relaying/index.md @@ -0,0 +1,48 @@ +# Path Setup and Relay Commands + +This section describes a number of commands that can be used to manage clients, connections, channels and relay over new or existing paths. + +| CLI name | Description | +| ---------------------- | --------------------------------------------------------------------------------------------------------------- | +| `create client` | [Create a client for source chain on destination chain](./clients.md#create-client) | +| `update client` | [Update the specified client on destination chain](./clients.md#md-client) | +| `create connection` | [Establish a connection using existing or new clients](./connections.md#establish-connection) | +| `create channel` | [Establish a channel using existing or new connection](./channels.md#establish-channel) | +| `start` | [Relay packets over a new or exsiting channel](./packets.md#start) | + + +## Create +Use the `create` commands to create a new clients, connections and channels. + +```shell +USAGE: + hermes create + +DESCRIPTION: + Create objects (client, connection, or channel) on chains + +SUBCOMMANDS: + help Get usage information + client Create a new IBC client + connection Create a new connection between two chains + channel Create a new channel between two chains +``` + +## Relay +Use the `start` commands to start relaying packets over one path. + +```shell +USAGE: + hermes start + +DESCRIPTION: + Start the relayer + +POSITIONAL ARGUMENTS: + src_chain_id identifier of the source chain + dst_chain_id identifier of the destination chain + +FLAGS: + -p, --src-port-id SRC-PORT-ID + -c, --src-channel-id SRC-CHANNEL-ID +``` diff --git a/guide/src/relayer_loop.md b/guide/src/commands/setup-and-relaying/packets.md similarity index 72% rename from guide/src/relayer_loop.md rename to guide/src/commands/setup-and-relaying/packets.md index 7286da1570..653013ad12 100644 --- a/guide/src/relayer_loop.md +++ b/guide/src/commands/setup-and-relaying/packets.md @@ -1,8 +1,15 @@ -# Relay Path Setup and Packet Streaming +# Packet Relaying + +## Table of Contents + + + +## Start + The `start` command can be used to send packet transactions triggered by IBC packet events that occur for a given channel. This is also referred to packet streaming. A new channel can be established or an existing one can be specified. -```shell script +```shell USAGE: hermes start @@ -24,9 +31,9 @@ Use the `start` command without flags to create new clients on `source` and `des > Reusing existing clients or connection is not possible with the current version. The port used by the channel is obtained from and must be specified in the configuration file. -### Example +__Example__ -```shell script +```shell hermes start ibc-0 ibc-1 ``` @@ -36,9 +43,9 @@ The relayer creates a new client on each chain and then established a new connec Use the `start` command and specify the source port and channel identifier of a channel that is already created and in open state on both chains. -### Example +__Example__ -```shell script +```shell hermes start ibc-0 ibc-1 -p transfer -c channel-0 ``` @@ -56,31 +63,9 @@ Current events and actions are: - `MsgTimeoutOnClose`, sent to the `source` chain if the channel is in closed state on the `destination` chain. - `write_acknowledgement`: the relayer builds a `MsgAcknowledgement` packet that is sent to the `destination` chain. -## Relay Path Setup - -The `channel handshake` command can be used to establish a new channel that uses a new connection and new clients. There is no requirement for the ports to be configured in the configuration file (i.e. its `connections` section may be missing). - -> Reuse of existing clients and/or connections is not supported in the current version. - -```shell script -USAGE: - hermes channel handshake - -DESCRIPTION: - tx raw +## Packet Delay -POSITIONAL ARGUMENTS: - dst_chain_id identifier of the destination chain - src_chain_id identifier of the source chain - dst_port_id identifier of the destination port - src_port_id identifier of the source port - -FLAGS: - -o, --ordering ORDERING the channel order -``` - -## Example - -```shell script -hermes channel handshake ibc-0 ibc-1 transfer transfer -``` +If the relay path is using a non-zero delay connection, then `hermes` will delay all packet transactions. The delay is +relative to the submission time for the client update at the height required by the packet proof. +The delay is used to prevent light client attacks and ensures that misbehavior detection finalizes before the transaction is submitted. +For more information on the misbehavior detector see [the misbehaviour section](../misbehaviour/index.md#monitoring-misbehaviour-and-evidence-submission). diff --git a/guide/src/commands/upgrade/index.md b/guide/src/commands/upgrade/index.md new file mode 100644 index 0000000000..135d9c137e --- /dev/null +++ b/guide/src/commands/upgrade/index.md @@ -0,0 +1,21 @@ +# Client Upgrade + +## Client Upgrade Command + +Use the `upgrade client` command to upgrade a client after a chain upgrade. + +```shell +USAGE: + hermes upgrade client + +DESCRIPTION: + Upgrade an IBC client + +POSITIONAL ARGUMENTS: + dst_chain_id identifier of the destination chain + dst_client_id identifier of the client to be upgraded on destination chain +``` + +__Example__ + +Here is [an example](./test.md) of a chain upgrade proposal submission and client upgrade. diff --git a/guide/src/commands/upgrade/test.md b/guide/src/commands/upgrade/test.md new file mode 100644 index 0000000000..3a43d8f62c --- /dev/null +++ b/guide/src/commands/upgrade/test.md @@ -0,0 +1,220 @@ +# Testing Client Upgrade + +## Prerequisites + +- gaiad `(v4.2.*)`, for example: + +```shell +$ gaiad version --log_level error --long | head -n4 +name: gaia +server_name: gaiad +version: v4.2.0 +commit: 535be14a8bdbfeb0d950914b5baa2dc72c6b081c +``` + +## Testing procedure + +1. Start two gaia instances and initialize hermes: + + ```shell + $ ./scripts/dev-env ~/.hermes/config.toml ibc-0 ibc-1 + ``` + The `one-chain` script is invoked for each chain and modifies the `genesis.json` file to use a short window for governance proposals (`200s` for `max_deposit_period` and `voting_period`). Therefore, an upgrade proposal can be submitted, voted on and accepted within a short time. + +2. Create one client on `ibc-1` for `ibc-0`: + + ```shell + $ hermes create client ibc-1 ibc-0 + + Success: CreateClient( + CreateClient( + Attributes { + height: Height { revision: 1, height: 9 }, + client_id: ClientId( + "07-tendermint-0", + ), + client_type: Tendermint, + consensus_height: Height { revision: 0, height: 18 }, + }, + ), + ) + ``` + +3. Create and submit an upgrade plan for chain `ibc-0`: + + Use the hermes test command to make an upgrade proposal. In the example below a software upgrade proposal is made for `ibc-0`, for the height `300` blocks from latest height. `10000000stake` is deposited. + The proposal includes the upgraded client state constructed from the state of `07-tendermint-0` client on `ibc-1` that was created in the previous step. In addition, the `unbonding_period` of the client is set to some new value (`400h`) + + ```shell + $ hermes tx raw upgrade-chain ibc-0 ibc-1 07-tendermint-0 10000000 300 + Success: [] + ``` + + Note that the height offset should be picked such that the proposal plan height is reached after the `200s` voting period. + + 4. Verify that the proposal was accepted: + + Query the upgrade plan to check that it was submitted correctly. Note the `height` at which the proposal will take effect (chain halts). Also `status: PROPOSAL_STATUS_VOTING_PERIOD`. + + ```shell + gaiad query gov proposal 1 --home data/ibc-0/ + ``` + ``` + content: + '@type': /cosmos.upgrade.v1beta1.SoftwareUpgradeProposal + description: upgrade the chain software and unbonding period + plan: + height: "332" + info: upgrade the chain software and unbonding period + name: test + time: "0001-01-01T00:00:00Z" + upgraded_client_state: + '@type': /ibc.lightclients.tendermint.v1.ClientState + allow_update_after_expiry: false + allow_update_after_misbehaviour: false + chain_id: ibc-0 + frozen_height: + revision_height: "0" + revision_number: "0" + latest_height: + revision_height: "333" + revision_number: "0" + max_clock_drift: 0s + proof_specs: + - inner_spec: + child_order: + - 0 + - 1 + child_size: 33 + empty_child: null + hash: SHA256 + max_prefix_length: 12 + min_prefix_length: 4 + leaf_spec: + hash: SHA256 + length: VAR_PROTO + prefix: AA== + prehash_key: NO_HASH + prehash_value: SHA256 + max_depth: 0 + min_depth: 0 + - inner_spec: + child_order: + - 0 + - 1 + child_size: 32 + empty_child: null + hash: SHA256 + max_prefix_length: 1 + min_prefix_length: 1 + leaf_spec: + hash: SHA256 + length: VAR_PROTO + prefix: AA== + prehash_key: NO_HASH + prehash_value: SHA256 + max_depth: 0 + min_depth: 0 + trust_level: + denominator: "0" + numerator: "0" + trusting_period: 0s + unbonding_period: 1440000s + upgrade_path: + - upgrade + - upgradedIBCState + title: upgrade_ibc_clients + deposit_end_time: "2021-04-12T16:33:37.187389Z" + final_tally_result: + abstain: "0" + "no": "0" + no_with_veto: "0" + "yes": "0" + proposal_id: "1" + status: PROPOSAL_STATUS_VOTING_PERIOD + submit_time: "2021-04-12T16:30:17.187389Z" + total_deposit: + - amount: "10000000" + denom: stake + voting_end_time: "2021-04-12T16:33:37.187389Z" + voting_start_time: "2021-04-12T16:30:17.187389Z" + ``` + + 5. Vote on the proposal + + The parameter `1` should match the `proposal_id:` from the upgrade proposal submitted at step 3. + This command must be issued while the proposal status is `PROPOSAL_STATUS_VOTING_PERIOD`. Confirm transaction when prompted. + + ```shell + $ gaiad tx gov vote 1 yes --home data/ibc-0/data/ --keyring-backend test --keyring-dir data/ibc-0/ --chain-id ibc-0 --from validator + confirm transaction before signing and broadcasting [y/N]: y + + {"height":"85","txhash":"AC24D80B1BFE0832769DECFDD3B3DF999A363D5E4390B0B673344FFDED9150B2","codespace":"","code":0,"data":"0A060A04766F7465","raw_log":"[{\"events\":[{\"type\":\"message\",\"attributes\":[{\"key\":\"action\",\"value\":\"vote\"},{\"key\":\"module\",\"value\":\"governance\"},{\"key\":\"sender\",\"value\":\"cosmos1srfzw0jkyyn7wf0ps4zy0tuvdaclfj2ufgp6w3\"}]},{\"type\":\"proposal_vote\",\"attributes\":[{\"key\":\"option\",\"value\":\"VOTE_OPTION_YES\"},{\"key\":\"proposal_id\",\"value\":\"1\"}]}]}]","logs":[{"msg_index":0,"log":"","events":[{"type":"message","attributes":[{"key":"action","value":"vote"},{"key":"module","value":"governance"},{"key":"sender","value":"cosmos1srfzw0jkyyn7wf0ps4zy0tuvdaclfj2ufgp6w3"}]},{"type":"proposal_vote","attributes":[{"key":"option","value":"VOTE_OPTION_YES"},{"key":"proposal_id","value":"1"}]}]}],"info":"","gas_wanted":"200000","gas_used":"43716","tx":null,"timestamp":""} + ``` + + 6. Wait approximately 200 seconds until the proposal changes status to `PROPOSAL_STATUS_PASSED`. + Note the `final tally_result` that includes the vote submitted in the previous step. + + ```shell + gaiad query gov proposal 1 --home data/ibc-0/ + ``` + + ``` + content: + '@type': /cosmos.upgrade.v1beta1.SoftwareUpgradeProposal + description: upgrade the chain software and unbonding period + ... + final_tally_result: + abstain: "0" + "no": "0" + no_with_veto: "0" + "yes": "100000000000" + proposal_id: "1" + status: PROPOSAL_STATUS_PASSED + submit_time: "2021-04-12T16:30:17.187389Z" + total_deposit: + - amount: "10000000" + denom: stake + voting_end_time: "2021-04-12T16:33:37.187389Z" + voting_start_time: "2021-04-12T16:30:17.187389Z" + ``` + +6. Test the `upgrade client` CLI + + The following command performs the upgrade for client `07-tendermint-0`. It outputs two events, one for the updated client state, + and another for the upgraded state. + + ```shell + $ hermes upgrade client ibc-1 07-tendermint-0 + ``` + ```rust + Success: [ + UpdateClient( + UpdateClient { + common: Attributes { + height: Height { revision: 1, height: 438 }, + client_id: ClientId( + "07-tendermint-0", + ), + client_type: Tendermint, + consensus_height: Height { revision: 0, height: 440 }, + }, + header: Some( + Tendermint(..) + ), + }, + ), + UpgradeClient( + UpgradeClient( + Attributes { + height: Height { revision: 1, height: 438 }, + client_id: ClientId( + "07-tendermint-0", + ), + client_type: Tendermint, + consensus_height: Height { revision: 0, height: 441 }, + }, + ), + ), + ] + ``` diff --git a/guide/src/config.md b/guide/src/config.md index dc29f150fd..ad32e7c2cf 100644 --- a/guide/src/config.md +++ b/guide/src/config.md @@ -9,7 +9,7 @@ By default, Hermes expects the configuration file to be located at `$HOME/.herme This can be overridden by supplying the `-c` flag when invoking `hermes`, before the name of the command to run, eg. `hermes -c my_config.toml query connection channels ibc-1 connection-1`. -> With the exception of the light client configuration, current relayer does not support managing the configuration file programmatically. +> The current version of Hermes does not support managing the configuration file programmatically. > You will need to use a text editor to create the file and add content to it. ```bash @@ -26,8 +26,6 @@ The global section has parameters that apply globally to the relayer operation. #### Parameters -* __timeout__: Specify the maximum amount of time (duration) that the operations should take before timing out. Default value is `10s` (10 seconds). - * __strategy__: Specify the strategy to be used by the relayer. Currently only `naive` is supported. * __log_level__: Specify the verbosity for the relayer logging output. Valid options are 'error', 'warn', 'info', 'debug', 'trace'. Default value is `info`. @@ -38,22 +36,25 @@ Here is an example for the `global` section: ```toml [global] -timeout = '10s' strategy = 'naive' log_level = 'info' ``` ### `[[chains]]` -A `chains` section includes parameters related to a chain and the full node to which the relayer can send transactions and queries. It also has parameters related to the light client peers configured for the chain. +A `chains` section includes parameters related to a chain and the full node to which the relayer can send transactions and queries. #### Parameters * __id__: Specify the chain ID. For example `ibc-0` -* __rpc_addr__: Specify the RPC address and port where the chain RPC server listens on. For example `tcp://localhost:26657` +* __rpc_addr__: Specify the RPC address and port where the chain RPC server listens on. For example `http://localhost:26657` + +* __grpc_addr__: Specify the GRPC address and port where the chain GRPC server listens on. For example `http://localhost:9090` -* __grpc_addr__: Specify the GRPC address and port where the chain GRPC server listens on. For example `tcp://localhost:9090` +* __websocket_addr__: Specify the WebSocket address and port where the chain WebSocket server listens on. For example `ws://localhost:26657/websocket` + +* __rpc_timeout__: Specify the maximum amount of time (duration) that the RPC requests should take before timing out. Default value is `10s` (10 seconds). * __account_prefix__: Specify the prefix used by the chain. For example `cosmos` @@ -78,29 +79,28 @@ For example if you want to add a configuration for a chain named `ibc-0`: id = 'ibc-0' rpc_addr = 'http://127.0.0.1:26657' grpc_addr = 'http://127.0.0.1:9090' +websocket_addr = 'ws://localhost:26657/websocket' +rpc_timeout = '10s' account_prefix = 'cosmos' key_name = 'testkey' store_prefix = 'ibc' gas = 200000 +fee_denom = 'stake' +fee_amount = 10 clock_drift = '5s' trusting_period = '14days' ``` -### Light clients - -The configuration file stores information about the light client peers. This configuration can be added to the configuration file when running the `relayer light add` command. Please see the [Light Clients](./light_clients.md) section to learn how to configure them. - ### Adding Private Keys -For each chain configured you need to add a private key for that chain in order to submit [transactions](./transactions.md), please refer to the [Keys](./keys.md) sections in order to learn how to add the private keys that are used by the relayer. +For each chain configured you need to add a private key for that chain in order to submit [transactions](./commands/raw/index.md), please refer to the [Keys](./commands/keys/index.md) sections in order to learn how to add the private keys that are used by the relayer. ### Example configuration file -Here is a full example of a configuration file with two chains configured and light client peers added: +Here is a full example of a configuration file with two chains configured: ```toml [global] -timeout = '10s' strategy = 'naive' log_level = 'error' @@ -108,6 +108,8 @@ log_level = 'error' id = 'ibc-0' rpc_addr = 'http://127.0.0.1:26657' grpc_addr = 'http://127.0.0.1:9090' +websocket_addr = 'ws://localhost:26657/websocket' +rpc_timeout = '10s' account_prefix = 'cosmos' key_name = 'testkey' store_prefix = 'ibc' @@ -121,35 +123,12 @@ trusting_period = '14days' numerator = '1' denominator = '3' -[chains.peers] -primary = '66E3B7083DF9DD1FC57A611929BF4C505E34AA88' - -[[chains.peers.light_clients]] -peer_id = '66E3B7083DF9DD1FC57A611929BF4C505E34AA88' -address = 'http://127.0.0.1:26657' -timeout = '10s' -trusted_header_hash = 'A24F654188BC3FC9EFE589FB33D513CE9AC86BFA48B063BDBF1D769750713E09' -trusted_height = '15' - -[chains.peers.light_clients.store] -type = 'disk' -path = '/ibc-rs/data/ibc-0/data/66E3B7083DF9DD1FC57A611929BF4C505E34AA88' - -[[chains.peers.light_clients]] -peer_id = '2427F8D914A6862279B3326FA64F76E3BC06DB2E' -address = 'http://127.0.0.1:26657' -timeout = '10s' -trusted_header_hash = '44E7C90BFA53256AD72B84286BFDA70FE87BBC7C0D80A1DB199C72A4FBE88FB6' -trusted_height = '16' - -[chains.peers.light_clients.store] -type = 'disk' -path = '/ibc-rs/data/ibc-0/data/2427F8D914A6862279B3326FA64F76E3BC06DB2E' - [[chains]] id = 'ibc-1' rpc_addr = 'http://127.0.0.1:26557' grpc_addr = 'http://127.0.0.1:9091' +websocket_addr = 'ws://localhost:26557/websocket' +rpc_timeout = '10s' account_prefix = 'cosmos' key_name = 'testkey' store_prefix = 'ibc' @@ -162,35 +141,10 @@ trusting_period = '14days' [chains.trust_threshold] numerator = '1' denominator = '3' - -[chains.peers] -primary = '28ED8856CBACA85DA866AB99F50DB22A58DA35F4' - -[[chains.peers.light_clients]] -peer_id = '28ED8856CBACA85DA866AB99F50DB22A58DA35F4' -address = 'http://127.0.0.1:26557' -timeout = '10s' -trusted_header_hash = '66BD0E5ED1FA2022A036782F7D8444DB98DC0326B379BCA6BA75864295D1C910' -trusted_height = '4' - -[chains.peers.light_clients.store] -type = 'disk' -path = '/ibc-rs/data/ibc-1/data/28ED8856CBACA85DA866AB99F50DB22A58DA35F4' - -[[chains.peers.light_clients]] -peer_id = 'A885BB3D3DFF6101188B462466AE926E7A6CD51E' -address = 'http://127.0.0.1:26557' -timeout = '10s' -trusted_header_hash = '0325BFAA36407D1F11966AEC57D34131CB27B370D3698F284F09152ADE3423C4' -trusted_height = '5' - -[chains.peers.light_clients.store] -type = 'disk' -path = '/ibc-rs/data/ibc-1/data/A885BB3D3DFF6101188B462466AE926E7A6CD51E' ``` ### Next Steps -Now that you learned how to build the relayer and how to create a configuration file, you can go to the [`Two Chains`](./two_chains.md) tutorial to learn how to perform some local testing connecting the relayer to two local chains. +Now that you learned how to build the relayer and how to create a configuration file, you can go to the [`Two Chains`](./tutorials/local-chains/index.md) tutorial to learn how to perform some local testing connecting the relayer to two local chains. [log-level]: ./help.html#parametrizing-the-log-output-level diff --git a/guide/src/features.md b/guide/src/features.md index 1e17f833e4..1c09c1c60a 100644 --- a/guide/src/features.md +++ b/guide/src/features.md @@ -1,43 +1,53 @@ # Features This section includes a summary of the supported and planned features. -More details and feature comparison between the Rust and Go relayer implementations can be found in the [Feature Matrix](./feature_matrix.md) +A feature matrix and comparison between the Rust and Go relayer implementations can be found in the [Feature Matrix](./features/matrix.md) ## Supported Features -- Establish a new relaying path (new clients, connection and unordered channel handshake) -- Relay from packet events on a newly created, or an existing relaying path - - __Limitations:__ - - Supports only one path per relayer instance - - Relayer restart is not supported, i.e. pending packets (previously sent packets and acknowledgments) are not cleared on startup - - Only unordered channels are supported - -- individual commands that build and send transactions for: - - Creating and updating IBC Tendermint light clients - - Sending connection open handshake datagrams - - Sending channel open handshake datagrams - - Sending channel closing handshake datagrams - - Initiating a cross chain transfer (mainly for testing) - - Relaying sent packets, acknowledgments and timeouts +- Basic features + - create and update clients + - establish connections with new or existing clients + - establish channels with new or existing connection + - channel closing handshake + - relay packets, acknowledgments, timeout and timeout-on-close packets, with zero or non-zero delay. + - queries for all objects +- Packet relaying over: + - new path + - single specified path + - multiple paths configured in `config.toml` +- Restart support + - clear packets on relayer restart when started for a single path + > clear packets in multi-path mode not fully supported yet +- Client upgrade + - upgrading clients after a counterparty chain has performed an upgrade for IBC breaking changes +- Packet delay: + - establish path over non-zero delay connection + - relay all packets with the specified delay +- Monitor and submit misbehaviour for clients + - monitor client updates for misbehaviour (fork and BFT time violation) + - submit misbehaviour evidence to the on-chain IBC client. + > misbehaviour submission to full node not yet supported +- Individual commands that build and send transactions for: + - creating and updating IBC Tendermint light clients + - aending connection open handshake datagrams + - sending channel open handshake datagrams + - sending channel closing handshake datagrams + - initiating a cross chain transfer (mainly for testing) + - relaying sent packets, acknowledgments and timeouts + - client upgrade ## Upcoming / Unsupported Features Planned features: -- Support for client upgrade and unfreezing -- Connection handshake using existing clients and/or existing connection that is not in `Open` state -- Channel handshake using existing clients, opened connection, and/ or existing channel that is not in `Open` state -- Passive mode: relay from all IBC events -- Support for relayer restart -- Support for multiple paths -- Close-to-0 configuration relayer +- Connection handshake for existing connection that is not in `Open` state +- Channel handshake for existing channel that is not in `Open` state +- Clear pending packets in multi path mode +- Full Passive mode: relay from all IBC events - Relayer support for management application (add RPC server) Not planned: - Relayer management application - Create clients with user chosen parameters (such as UpgradePath) -- Monitor and submit misbehaviour for clients - Use IBC light clients other than Tendermint such as Solo Machine - Support non cosmos-SDK chains -- Sending an UpgradePlan proposal for an IBC breaking upgrade -- Upgrading clients after a counterparty chain has performed an upgrade for IBC breaking changes diff --git a/guide/src/feature_matrix.md b/guide/src/features/matrix.md similarity index 68% rename from guide/src/feature_matrix.md rename to guide/src/features/matrix.md index 3fa831c176..6e0f43ac19 100644 --- a/guide/src/feature_matrix.md +++ b/guide/src/features/matrix.md @@ -20,39 +20,28 @@ __Feature comparison between Hermes and the Go relayer__ | Features \ Status | Hermes | Cosmos Go | Feature Details | | ---------------------- | :---: | :----: |:-------| -| Restart | ❌ | ✅ | replays any IBC events that happened before restart -| Multiple_Paths | ❌ | ✅ | relays on multiple paths concurrently +| Restart | ✅ | ✅ | replays any IBC events that happened before restart +| Multiple_Paths | ✅ | ✅ | relays on multiple paths concurrently +| | | | +| Connection Delay | ✅ | ❌ | +| Cl_Misbehavior | ✅ | ❌ | monitors and submits IBC client misbehavior +| Packet Delay | ✅ | ❌ | +| | | | | Chan_Unordered | ✅ | ✅ | -| Chan_Ordered | ❌ | ❓ | +| Chan_Ordered | ✅ | ❓ | | | | | | Cl_Tendermint_Create | ✅ | ✅ | tendermint light client creation | Cl_Tendermint_Update | ✅ | ✅ | tendermint light client update -| Cl_Tendermint_Upgrade | ❌ | ✅ | tendermint light client upgrade +| Cl_Tendermint_Upgrade | ✅ | ✅ | tendermint light client upgrade | | | | -| Conn_Handshake_A | ✅ | ✅ | -| Conn_Handshake_P | ❌ | ❌ | -| Chan_Handshake_A | ✅ | ✅ | -| Chan_Handshake_P | ❌ | ❌ | +| Conn_Open_Handshake_A | ✅ | ✅ | +| Conn_Open_Handshake_P | ❌ | ❌ | | | | | -| Conn_Open_Init | ✅ | ✅ | -| Conn_Open_Try_A | ✅ | ✅ | -| Conn_Open_Try_P | ❌ | ❌ | -| Conn_Open_Ack_A | ✅ | ✅ | -| Conn_Open_Ack_P | ❌ | ❌ | -| Conn_Open_Confirm_A | ✅ | ✅ | -| Conn_Open_Confirm_P | ❌ | ❌ | +| Chan_Open_Handshake_A | ✅ | ✅ | +| Chan_Open_Handshake_P | ❌ | ❌ | | | | | -| Chan_Open_Init | ✅ | ✅ | -| Chan_Open_Try_A | ✅ | ✅ | -| Chan_Open_Try_P | ❌ | ❌ | -| Chan_Open_Ack_A | ✅ | ✅ | -| Chan_Open_Ack_P | ❌ | ❌ | -| Chan_Open_Confirm_A | ✅ | ✅ | -| Chan_Open_Confirm_P | ❌ | ❌ | -| | | | -| Chan_Close_Init | ✅ | ✅ | -| Chan_Close_Confirm_A | ✅ | ✅ | -| Chan_Close_Confirm_P | ❌ | ❌ | +| Chan_Close_Handshake_P | ✅ | ✅ | +| Chan_Close_Handshake_A | ✅ | ❌ | | | | | | FT_Transfer | ✅ | ✅ | can submit an ICS-20 fungible token transfer message | Packet_Recv_A | ✅ | ✅ | @@ -62,10 +51,6 @@ __Feature comparison between Hermes and the Go relayer__ | Packet_TimeoutClose_A | ✅ | ❓ | | Packet_TimeoutClose_P | ✅ | ❓ | | | | | -| Upgrade_Plan_Proposal | ❌ | ✅ | submit `UpgradePlan` proposals for IBC breaking upgrades -| Cl_Unfreeze_Proposal | ❌ | ❌ | submit IBC client unfreezing proposals -| Cl_Misbehavior | ❌ | ❌ | monitors and submits IBC client misbehavior -| | | | | Cl_Non_Tendermint | ❌ | ❌ | supports non tendermint IBC light clients | Chain_Non_Cosmos | ❌ | ❌ | supports non cosmos-SDK chains | | | | diff --git a/guide/src/help.md b/guide/src/help.md index 152069200d..5a93f4685c 100644 --- a/guide/src/help.md +++ b/guide/src/help.md @@ -32,14 +32,14 @@ To enable it, one must compile the `relayer-cli` crate with the `--features=prof a) One way is to build the `relayer` binary and update the `hermes` alias to point to the executable: -```shell script +```shell cd relayer-cli/ cargo build --features=profiling ``` b) Alternatively, one can use the `cargo run` command and update the alias accordingly: -```shell script +```shell alias hermes='cargo run --features=profiling --manifest-path=relayer-cli/Cargo.toml --' ``` @@ -82,27 +82,68 @@ and it's often not clear which of these are the culprit for low performance. With profiling enabled, `hermes` will output timing information for individual methods involved in a command. -__NOTE__: To be able to see the profiling output, the -[log level][log-level] should be `info` -level or lower. +__NOTE__: To be able to see the profiling output, the realyer needs to be compiled with +the `profiling` feature and the [log level][log-level] should be `info` level or lower. #### Example output for `tx raw conn-init` command - ``` hermes -c config_example.toml tx raw conn-init ibc-0 ibc-1 07-tendermint-0 07-tendermint-0 -{"timestamp":"Feb 03 14:46:55.282","level":"INFO","fields":{"message":"⏳ init_light_client - start"},"target":"ibc_relayer::macros::profiling"} -{"timestamp":"Feb 03 14:46:55.361","level":"INFO","fields":{"message":"⏳ init_light_client - elapsed: 75ms"},"target":"ibc_relayer::macros::profiling"} -{"timestamp":"Feb 03 14:46:55.361","level":"INFO","fields":{"message":"⏳ init_event_monitor - start"},"target":"ibc_relayer::macros::profiling"} -{"timestamp":"Feb 03 14:46:55.374","level":"INFO","fields":{"message":"⏳ init_event_monitor - elapsed: 12ms"},"target":"ibc_relayer::macros::profiling"} -{"timestamp":"Feb 03 14:46:55.374","level":"INFO","fields":{"message":"running listener","chain.id":"ibc-1"},"target":"ibc_relayer::event::monitor"} -{"timestamp":"Feb 03 14:46:55.375","level":"INFO","fields":{"message":"⏳ init_light_client - start"},"target":"ibc_relayer::macros::profiling"} -{"timestamp":"Feb 03 14:46:55.405","level":"INFO","fields":{"message":"⏳ init_light_client - elapsed: 29ms"},"target":"ibc_relayer::macros::profiling"} -{"timestamp":"Feb 03 14:46:55.405","level":"INFO","fields":{"message":"⏳ init_event_monitor - start"},"target":"ibc_relayer::macros::profiling"} -{"timestamp":"Feb 03 14:46:55.408","level":"INFO","fields":{"message":"⏳ init_event_monitor - elapsed: 3ms"},"target":"ibc_relayer::macros::profiling"} -{"timestamp":"Feb 03 14:46:55.408","level":"INFO","fields":{"message":"running listener","chain.id":"ibc-0"},"target":"ibc_relayer::event::monitor"} -{"timestamp":"Feb 03 14:46:55.410","level":"INFO","fields":{"message":"Message ConnOpenInit: Connection { a_side: ConnectionSide { chain: ProdChainHandle { chain_id: ChainId { id: \"ibc-1\", version: 1 }, runtime_sender: Sender { .. } }, client_id: ClientId(\"07-tendermint-0\"), connection_id: ConnectionId(\"defaultConnection\") }, b_side: ConnectionSide { chain: ProdChainHandle { chain_id: ChainId { id: \"ibc-0\", version: 0 }, runtime_sender: Sender { .. } }, client_id: ClientId(\"07-tendermint-0\"), connection_id: ConnectionId(\"defaultConnection\") } }"},"target":"ibc_relayer_cli::commands::tx::connection"} +``` +``` +Apr 13 20:58:21.225 INFO ibc_relayer::macros::profiling: ⏳ init_light_client - start +Apr 13 20:58:21.230 INFO ibc_relayer::macros::profiling: ⏳ init_light_client - elapsed: 4ms +Apr 13 20:58:21.230 INFO ibc_relayer::macros::profiling: ⏳ init_event_monitor - start +Apr 13 20:58:21.235 INFO ibc_relayer::macros::profiling: ⏳ init_event_monitor - elapsed: 5ms +Apr 13 20:58:21.235 INFO ibc_relayer::event::monitor: running listener chain.id=ibc-1 +Apr 13 20:58:21.236 INFO ibc_relayer::macros::profiling: ⏳ init_light_client - start +Apr 13 20:58:21.239 INFO ibc_relayer::macros::profiling: ⏳ init_light_client - elapsed: 2ms +Apr 13 20:58:21.239 INFO ibc_relayer::macros::profiling: ⏳ init_event_monitor - start +Apr 13 20:58:21.244 INFO ibc_relayer::macros::profiling: ⏳ init_event_monitor - elapsed: 4ms +Apr 13 20:58:21.244 INFO ibc_relayer::event::monitor: running listener chain.id=ibc-0 +Apr 13 20:58:21.244 INFO ibc_relayer::macros::profiling: ⏳ get_signer - start +Apr 13 20:58:21.246 INFO ibc_relayer::macros::profiling: ⏳ get_signer - elapsed: 1ms +Apr 13 20:58:21.246 INFO ibc_relayer::macros::profiling: ⏳ query_latest_height - start +Apr 13 20:58:21.246 INFO ibc_relayer::macros::profiling: ⏳ block_on - start +Apr 13 20:58:21.248 INFO ibc_relayer::macros::profiling: ⏳ block_on - elapsed: 1ms +Apr 13 20:58:21.249 INFO ibc_relayer::macros::profiling: ⏳ query_latest_height - elapsed: 3ms +Apr 13 20:58:21.250 INFO ibc_relayer::macros::profiling: ⏳ unbonding_period - start +Apr 13 20:58:21.250 INFO ibc_relayer::macros::profiling: ⏳ block_on - start +Apr 13 20:58:21.251 INFO ibc_relayer::macros::profiling: ⏳ block_on - elapsed: 0ms +Apr 13 20:58:21.270 INFO ibc_relayer::macros::profiling: ⏳ block_on - start +Apr 13 20:58:21.273 INFO ibc_relayer::macros::profiling: ⏳ block_on - elapsed: 2ms +Apr 13 20:58:21.273 INFO ibc_relayer::macros::profiling: ⏳ unbonding_period - elapsed: 23ms +Apr 13 20:58:21.279 INFO ibc_relayer::macros::profiling: ⏳ build_consensus_state - start +Apr 13 20:58:21.280 INFO ibc_relayer::macros::profiling: ⏳ build_consensus_state - elapsed: 0ms +Apr 13 20:58:21.280 INFO ibc_relayer::macros::profiling: ⏳ send_msgs - start +Apr 13 20:58:21.280 INFO ibc_relayer::macros::profiling: ⏳ send_tx - start +Apr 13 20:58:21.282 INFO ibc_relayer::macros::profiling: ⏳ PK "03f17d2c094ee68cfcedb2c2f2b7dec6cd82ea158ac1c32d3de0ca8b288a3c8bfa" - start +Apr 13 20:58:21.282 INFO ibc_relayer::macros::profiling: ⏳ block_on - start +Apr 13 20:58:21.285 INFO ibc_relayer::macros::profiling: ⏳ block_on - elapsed: 3ms +Apr 13 20:58:21.296 INFO ibc_relayer::macros::profiling: ⏳ block_on - start +Apr 13 20:58:22.664 INFO ibc_relayer::macros::profiling: ⏳ block_on - elapsed: 1367ms +Apr 13 20:58:22.664 INFO ibc_relayer::macros::profiling: ⏳ PK "03f17d2c094ee68cfcedb2c2f2b7dec6cd82ea158ac1c32d3de0ca8b288a3c8bfa" - elapsed: 1382ms +Apr 13 20:58:22.664 INFO ibc_relayer::macros::profiling: ⏳ send_tx - elapsed: 1384ms +Apr 13 20:58:22.664 INFO ibc_relayer::macros::profiling: ⏳ send_msgs - elapsed: 1384ms +Success: CreateClient( + CreateClient( + Attributes { + height: Height { + revision: 0, + height: 10675, + }, + client_id: ClientId( + "07-tendermint-7", + ), + client_type: Tendermint, + consensus_height: Height { + revision: 1, + height: 10663, + }, + }, + ), +) ``` ## Parametrizing the log output level @@ -115,22 +156,20 @@ Relevant snippet: ```toml [global] -timeout = '10s' strategy = 'naive' log_level = 'error' ``` Valid options for `log_level` are: 'error', 'warn', 'info', 'debug', 'trace'. -These levels correspond to the tracing sub-component of the relayer-cli, [see -here](https://docs.rs/tracing-core/0.1.17/tracing_core/struct.Level.html). +These levels correspond to the tracing sub-component of the relayer-cli, +[see here](https://docs.rs/tracing-core/0.1.17/tracing_core/struct.Level.html). The relayer will _always_ print a last line summarizing the result of its operation for queries of transactions. In addition to this last line, arbitrary debug, info, or other outputs may be produced. Example, with -`log_level = 'debug'`: +`log_level = 'debug'` and JSON output: ```bash -Running `target/debug/relayer query client consensus ibc-0 07-tendermint-X 0 1` {"timestamp":"Jan 20 19:21:52.070","level":"DEBUG","fields":{"message":"registered component: abscissa_core::terminal::component::Terminal (v0.5.2)"},"target":"abscissa_core::component::registry"} {"timestamp":"Jan 20 19:21:52.071","level":"DEBUG","fields":{"message":"registered component: relayer_cli::components::Tracing (v0.0.6)"},"target":"abscissa_core::component::registry"} {"timestamp":"Jan 20 19:21:52.078","level":"INFO","fields":{"message":"Options QueryClientConsensusOptions { client_id: ClientId(\"07-tendermint-X\"), revision_number: 0, revision_height: 1, height: 0, proof: true }"},"target":"relayer_cli::commands::query::client"} @@ -144,21 +183,19 @@ For the same command, with `log_level = 'error'`, just the last line will be produced: ```bash - Running `target/debug/relayer query client consensus ibc-0 07-tendermint-X 0 1` {"status":"error","result":["query error: RPC error to endpoint tcp://localhost:26657: error trying to connect: tcp connect error: Connection refused (os error 61) (code: 0)"]} ``` ## Patching `gaia` The guide below refers specifically to patching your gaia chain so that the -relayer can initiate the closing of channels by submitting a [`chan-close-init` -transaction][chan-close]. +relayer can initiate the closing of channels by submitting a [`chan-close-init` transaction][chan-close]. Without this modification, the transaction will be rejected. We also describe how to test the channel closing feature. - Clone the Cosmos SDK - ```shell script + ```shell git clone https://github.com/cosmos/cosmos-sdk.git ~/go/src/github.com/cosmos/cosmos-sdk cd ~/go/src/github.com/cosmos/cosmos-sdk ``` @@ -193,32 +230,32 @@ In order to test the correct operation during the channel close, perform the ste Make sure you're not relaying this packet (the relayer should not be running on this path). - ```shell script - hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-1 5555 1000 -n 1 -d samoleans + ```shell + hermes tx raw ft-transfer ibc-0 ibc-1 transfer channel-1 5555 1000 -n 1 -d samoleans ``` - now do the first step of channel closing: the channel will transition to close-open: - ```shell script + ```shell hermes -c config.toml tx raw chan-close-init ibc-0 ibc-1 connection-0 transfer transfer channel-0 channel-1 ``` - trigger timeout on close to ibc-1 - ```shell script + ```shell hermes -c config.toml tx raw packet-recv ibc-0 ibc-1 transfer channel-1 ``` - close-close - ```shell script + ```shell hermes -c config.toml tx raw chan-close-confirm ibc-1 ibc-0 connection-1 transfer transfer channel-1 channel-0 ``` - verify that the two ends are in Close state: - ```shell script + ```shell hermes -c config.toml query channel end ibc-0 transfer channel-0 hermes -c config.toml query channel end ibc-1 transfer channel-1 ``` @@ -236,9 +273,9 @@ issue template. [twitter]: https://twitter.com/informalinc [twitter-image]: https://abs.twimg.com/errors/logo23x19.png [website]: https://informal.systems -[log-level]: ./help.html#parametrizing-the-log-output-level +[log-level]: ./help.md#parametrizing-the-log-output-level [issues]: https://github.com/informalsystems/ibc-rs/issues [profiling]: ./help.md#profiling -[feature]: ./help.html#new-feature-request -[patching]: ./help.html#patching-gaia -[chan-close]: ./tx_channel_close.html#channel-close-init +[feature]: ./help.md#new-feature-request +[patching]: ./help.md#patching-gaia +[chan-close]: ./commands/raw/channel-close.md#channel-close-init diff --git a/guide/src/index.md b/guide/src/index.md index 8f9b16b256..34d571841d 100644 --- a/guide/src/index.md +++ b/guide/src/index.md @@ -9,7 +9,7 @@ packets between two IBC enabled chains. - Explains what Hermes is about. -**[Features](./features.html)** +**[Features](./features.md)** - This section discusses what features to expect from Hermes, as well as a comparison between the Cosmos Go relayer and Hermes. @@ -18,11 +18,11 @@ packets between two IBC enabled chains. - The getting started section can help you setup, configure, and run Hermes. -**[Tutorials](./tutorials.md)** +**[Tutorials](./tutorials/index.md)** - This section provides some tutorials on how to operate and test Hermes. -**[Commands Reference](./commands.md)** +**[Commands Reference](./commands/index.md)** - The commands let you interact with Hermes using its command line interface. diff --git a/guide/src/installation.md b/guide/src/installation.md index 4297a3c3ee..05bc7b82d7 100644 --- a/guide/src/installation.md +++ b/guide/src/installation.md @@ -150,7 +150,6 @@ USAGE: SUBCOMMANDS: help Get usage information keys Manage keys in the relayer for each chain - light Basic functionality for managing the light clients start Start the relayer channel Channel functionality for managing channels query Query state from chain diff --git a/guide/src/light_clients.md b/guide/src/light_clients.md deleted file mode 100644 index ec5cf1a5c8..0000000000 --- a/guide/src/light_clients.md +++ /dev/null @@ -1,100 +0,0 @@ -# Light Clients - -Using the `light` command you can add and remove light client peer information to the chain configuration. - -#### Show usage - -To see the available sub-commands for the `light` command run: - -```shell -hermes help light -``` - -There are two sub-commands supported `add` and `rm`: - -```shell -USAGE: - hermes light - -DESCRIPTION: - Basic functionality for managing the lite clients - -SUBCOMMANDS: - add add a light client peer for a given chain - rm remove a light client peer for a given chain - -``` - -### Adding Light Client Peers - -In order to add the light client peers use the `add` command: - -```shell -USAGE: - hermes light add - -DESCRIPTION: - Add a light client peer for a given chain - -POSITIONAL ARGUMENTS: - address RPC network address (required) - -FLAGS: - -c, --chain-id CHAIN-ID identifier of the chain (required) - -s, --store STORE path to light client store for this peer (required) - -p, --primary whether this is the primary peer - -f, --force allow overriding an existing peer - -y, --yes skip confirmation - --peer-id PEER-ID override peer id (optional) - --height HEIGHT override height (optional) - --hash HASH override hash (optional) -``` - - -#### Set the Primary Light Client Peer for a Chain - -In order to add a light client primary peer for a given chain execute the following command: - -```shell -hermes -c [CONFIG_FILE] light add tcp://[RPC_NETWORK_ADDRESS] -c [CHAIN_ID] -s [CHAIN_STORE] -p -y -f -``` - -#### Set the Secondary Light Client Peer for a Chain - -In order to add a light client secondary peer for a given chain execute the following command: - -```shell -hermes -c [CONFIG_FILE] light add tcp://[RPC_NETWORK_ADDRESS] -c [CHAIN_ID] -s [CHAIN_STORE] --peer-id 17D46D8C1576A79203A6733F63B2C9B7235DD559 -y -``` - -> The `peer-id` above can be any valid value for a peer id. Currently, the relayer does not validate if this secondary peer exists. - -### Removing Light Client Peers - -In order to remove a light client peer use the `rm` command: - -```shell -USAGE: - hermes light rm - -DESCRIPTION: - Remove a light client peer for a given chain - -POSITIONAL ARGUMENTS: - peer_id identifiers of peers to remove - -FLAGS: - -c, --chain-id CHAIN-ID identifier of the chain to remove peers from - -f, --force force removal of primary peer - --all remove all peers, implies --force - -y, --yes skip confirmation - -``` - -#### Removing all light client peers from a chain - -In order to remove all light peers for a chain from the configuration execute the following command: - -```shell -hermes -c [CONFIG_FILE] light rm -c [CHAIN_ID] -y --all -``` diff --git a/guide/src/pre_requisites.md b/guide/src/pre_requisites.md index d83d386d5f..e90640d015 100644 --- a/guide/src/pre_requisites.md +++ b/guide/src/pre_requisites.md @@ -2,7 +2,7 @@ ## 1. Rust -The IBC Relayer is developed with the [Rust]() programming language. In order to build and run the relayer you need to install and configure `Rust` on your machine. +The IBC Relayer is developed with the [Rust](https://www.rust-lang.org) programming language. In order to build and run the relayer you need to install and configure `Rust` on your machine. ### Fresh Rust installation @@ -34,11 +34,10 @@ This should display the `cargo` version and confirm the proper installation. ## 2. Golang -You will also need the __Go__ programming language installed and configured on your machine. This is a requirement for the the section [Installing Gaia](./gaia.md) in the [Two Local Chains](./two_chains.md) tutorial. +You will also need the __Go__ programming language installed and configured on your machine. This is a requirement for the the section [Installing Gaia](./tutorials/local-chains/gaia.md) in the [Two Local Chains](./tutorials/local-chains/index.md) tutorial. -To install and configure Golang on your machine please follow the [Golang official documentation](https://golang.org/doc/install) +To install and configure Golang on your machine please follow the [Golang official documentation](https://golang.org/doc/install). ## Next Steps -Next, go to the [Installation](./installation.md) section to learn how to build -Hermes. \ No newline at end of file +Next, go to the [Installation](./installation.md) section to learn how to build Hermes. diff --git a/guide/src/query_client.md b/guide/src/query_client.md deleted file mode 100644 index 4b8cfb3d90..0000000000 --- a/guide/src/query_client.md +++ /dev/null @@ -1,193 +0,0 @@ - -# Table of Contents - - - -# Query Clients -Use the `query clients` command to query the identifiers of all clients on a given chain. - -```shell -USAGE: - hermes query clients - -DESCRIPTION: - Query clients - -POSITIONAL ARGUMENTS: - chain_id identifier of the chain to query -``` - -__Example__ - -Query all clients on `ibc-1`: - -```shell -hermes query clients ibc-1 | jq -``` - -```json -{ - "status": "success", - "result": [ - "07-tendermint-0", - "07-tendermint-1", - "07-tendermint-2", - "07-tendermint-3" - ] -} -``` - -# Query Client Data -Use the `query client` command to query the information about a specific client. - -```shell -USAGE: - hermes query client - -DESCRIPTION: - Query information about clients - -SUBCOMMANDS: - state query client full state - consensus query client consensus - connections query client connections -``` - -## Query the client state -Use the `query client state` command to query the client state of a client: - -```shell -USAGE: - hermes query client state - -DESCRIPTION: - Query client full state - -POSITIONAL ARGUMENTS: - chain_id identifier of the chain to query - client_id identifier of the client to query - -FLAGS: - -h, --height HEIGHT the chain height which this query should reflect -``` - -__Example__ - -Query the state of client `07-tendermint-2` on `ibc-1`: - -```shell -hermes query client state ibc-1 07-tendermint-2 | jq -``` - -```json -{ - "status": "success", - "result": { - "type": "Tendermint", - "allow_update_after_expiry": false, - "allow_update_after_misbehaviour": false, - "chain_id": "ibc-0", - "frozen_height": { - "revision_height": 0, - "revision_number": 0 - }, - "latest_height": { - "revision_height": 948, - "revision_number": 0 - }, - "max_clock_drift": { - "nanos": 0, - "secs": 3 - }, - "trust_level": { - "denominator": "3", - "numerator": "1" - }, - "trusting_period": { - "nanos": 0, - "secs": 1209600 - }, - "unbonding_period": { - "nanos": 0, - "secs": 1814400 - }, - "upgrade_path": [ - "upgrade", - "upgradedIBCState" - ] - } -} -``` - -## Query the client consensus state -Use the `query client consensus` command to query the consensus state for a given client and consensus height: - -```shell -USAGE: - hermes query client consensus - -DESCRIPTION: - Query client consensus state - -POSITIONAL ARGUMENTS: - chain_id identifier of the chain to query - client_id identifier of the client to query - consensus_epoch epoch of the client's consensus state to query - consensus_height height of the client's consensus state to query - -FLAGS: - -h, --height HEIGHT the chain height which this query should reflect -``` - -__Example__ - -Query the state of client `07-tendermint-2` on `ibc-1`: - -```shell -hermes query client consensus ibc-1 07-tendermint-2 0 948 | jq -``` - -```json -{ - "status": "success", - "result": { - "type": "Tendermint", - "next_validators_hash": "61B504627364047439A253FFBDD5D384B31D29611BD4B2ABA2636C232ABADA33", - "root": "82EFC9F24C8B595BDADBFE1576B473648DD8EBC76F30DC21201539FCCE15A9F8", - "timestamp": "2021-02-01T13:42:30.30536Z" - } -} -``` - -## Query the identifiers of all connections associated with a given client -Use the `query client connections` command to query the connections associated with a given client: - -```shell -USAGE: - hermes query client connections - -DESCRIPTION: - Query client connections - -POSITIONAL ARGUMENTS: - chain_id identifier of the chain to query - client_id identifier of the client to query - -FLAGS: - -h, --height HEIGHT the chain height which this query should reflect -``` - -__Example__ - -Query the connections of client `07-tendermint-0` on `ibc-0`: - -```shell -hermes query client connections ibc-0 07-terndermint-0 -{ - "status": "success", - "result": [ - "connection-0", - "connection-1", - "connection-2" - ] -}``` diff --git a/guide/src/setup.md b/guide/src/setup.md deleted file mode 100644 index feae8cb576..0000000000 --- a/guide/src/setup.md +++ /dev/null @@ -1 +0,0 @@ -# Setup diff --git a/guide/src/tutorial_client_raw.md b/guide/src/tutorial_client_raw.md deleted file mode 100644 index 061d4e2481..0000000000 --- a/guide/src/tutorial_client_raw.md +++ /dev/null @@ -1,125 +0,0 @@ -# 1. Configuring clients - -### 1.1. `create client` - -First you will need to create a client for each chain: - -This command submits a transaction to a destination chain (`ibc-0`) with a request to create a client for a source chain (`ibc-1`): - -```shell -hermes tx raw create-client ibc-0 ibc-1 -``` - -if the command is successful a message similar to the one below will be displayed `status:success`: - -```json -{ - "status": "success", - "result": [ - { - "CreateClient": { - "client_id": "07-tendermint-0", - "client_type": "Tendermint", - "consensus_height": { - "revision_height": 9082, - "revision_number": 1 - }, - "height": "1" - } - } - ] -} -``` - -> Please note the `client_id` value returned. You will need that for other commands. - -You can also execute a __query__ to view the client state on destination chain `ibc-0` by specifying the `client_id` value `07-tendermint-0`: - -```shell -hermes query client state ibc-0 07-tendermint-0 -``` - -which show a message similar to the one below: - -```json -{ - "status": "success", - "result": { - "type": "Tendermint", - "allow_update_after_expiry": false, - "allow_update_after_misbehaviour": false, - "chain_id": "ibc-1", - "frozen_height": { - "revision_height": 0, - "revision_number": 0 - }, - "latest_height": { - "revision_height": 9082, - "revision_number": 1 - }, - "max_clock_drift": { - "nanos": 0, - "secs": 3 - }, - "trust_level": { - "denominator": "3", - "numerator": "1" - }, - "trusting_period": { - "nanos": 0, - "secs": 1209600 - }, - "unbonding_period": { - "nanos": 0, - "secs": 1814400 - }, - "upgrade_path": [ - "upgrade", - "upgradedIBCState" - ] - } -} -``` - -Now let's do the same for `ibc-1` as the destination chain: - -```shell -hermes tx raw create-client ibc-1 ibc-0 -``` - -Take note of the `client_id` allocated for this client. In the examples we assume is `07-tendermint-1`. - -As before, if the command is successful a message with `status:success` is displayed: - -```json -{ - "status": "success", - "result": { - "CreateClient": { - "client_id": "07-tendermint-1", - "client_type": "Tendermint", - "consensus_height": { - "revision_height": 9505, - "revision_number": 0 - }, - "height": "1" - } - } -} -``` - -### 1.2 `update-client` - -Client states can be updated by sending an `update-client` transaction: - -```shell -hermes tx raw update-client ibc-0 ibc-1 07-tendermint-0 -``` - -```shell -hermes tx raw update-client ibc-1 ibc-0 07-tendermint-1 -``` - -## Next Steps - -In the next section, we'll establish the [Connection Handshake](./tutorial_conn_raw.md) diff --git a/guide/src/tutorial_raw.md b/guide/src/tutorial_raw.md deleted file mode 100644 index 62ff3aa35f..0000000000 --- a/guide/src/tutorial_raw.md +++ /dev/null @@ -1,90 +0,0 @@ -# Connecting the chains - -In the rest of this section we will show how to create the clients, establish a connection and a channel between the two chains, and relay packets over the channel. But first, a note on identifiers. - -## Identifiers -A chain allocates identifiers when it creates clients, connections and channels. These identifiers can subsequently be used to refer to existing clients, connections and channels. - -Chains allocate identifiers using a chain specific allocation scheme. -Currently, cosmos-SDK implementation uses: - - `07-tendermint-` for tendermint clients - - For example `07-tendermin-0` is assigned to the first client created on `ibc-1`: - ```shell - hermes tx raw create-client ibc-1 ibc-0 | jq - ``` - ```json - { - "status": "success", - "result": { - "CreateClient": { - "client_id": "07-tendermint-0", - "client_type": "Tendermint", - "consensus_height": { - "revision_height": 44895, - "revision_number": 0 - }, - "height": "1" - } - } - } - ``` - We will create a second client on `ibc-1` with identifier `07-tendermint-1` in the client tutorial. - - - `connection-` for connections - - For example `connection-0` is assigned to the first connection created on `ibc-1`: - ```shell - hermes tx raw conn-init ibc-1 ibc-0 07-tendermint-0 07-tendermint-0 | jq - ``` - ```json - { - "status": "success", - "result": { - "OpenInitConnection": { - "client_id": "07-tendermint-0", - "connection_id": "connection-0", - "counterparty_client_id": "07-tendermint-0", - "counterparty_connection_id": null, - "height": "1" - } - } - } - ``` - We will create a second connection on `ibc-1` with identifier `connection-1` in the connection tutorial. - - - `channel-` for channels - - For example `channel-0` is assigned to the first channel created on `ibc-1`: - ```shell - hermes tx raw chan-open-init ibc-1 ibc-0 connection-0 transfer transfer | jq - ``` - ```json - { - "status": "success", - "result": { - "OpenInitChannel": { - "channel_id": "channel-2", - "connection_id": "connection-0", - "counterparty_channel_id": null, - "counterparty_port_id": "transfer", - "height": "1", - "port_id": "transfer" - } - } - } - ``` - We will create a second channel on `ibc-1` with identifier `channel-1` in the channel tutorial. - -In the following tutorials the `ibc-0` and `ibc-1` chains are setup and configured. For clarity, the tutorials run on a setup where the identifiers allocated to the client, connection and channel on `ibc-0` are `07-tendermint-0`, `connection-0` and `channel-0` respectively. Identifiers allocated to the client, connection and channel on `ibc-1` are `07-tendermint-1`, `connection-1` and `channel-1` respectively. - -If you want to ensure you get the same identifiers while following the tutorial, run the above three commands once on `ibc-1` before going over the next sections. - -## Steps to start relaying packets between the two local chains - -In order to start relaying packets please follow the steps below: - -* [Configure Clients](./tutorial_client_raw.md) - -* [Connection Handshake](./tutorial_conn_raw.md) - -* [Open the Channel](./tutorial_chan_open_raw.md) - -* [Relay Packets](tutorial_packet_raw.md) diff --git a/guide/src/tutorial_relay_existing_path.md b/guide/src/tutorial_relay_existing_path.md deleted file mode 100644 index f599a0af1c..0000000000 --- a/guide/src/tutorial_relay_existing_path.md +++ /dev/null @@ -1,45 +0,0 @@ -# Packet relaying on existing path - -Hermes can listen to IBC packet events over a specified path and relay receive packets, acknowledgments and timeouts. - -1. From one terminal start hermes using the `start` command and specify the port and a previously established channel: - - ```shell script - hermes start ibc-0 ibc-1 transfer channel-0 - ``` - - > In this example, the channel identifier on `ibc-0`is `channel-0` while the identifier on`ibc-1` is `channel-1` - -2. In a separate terminal, use the transfer command to send 2 packets to `ibc0` chain: - - ```shell script - hermes tx raw ft-transfer ibc-0 ibc-1 transfer channel-0 9999 1000 -n 2 - ``` - -3. Use the CLI to send 2 packets to `ibc1` chain: - - ```shell script - hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-1 9999 1000 -n 2 - ``` - -4. Observe the output on the relayer terminal, verify that the send events are processed, and the `recv_packet` -s are sent out. - -5. Query the unreceived packets on `ibc0` and `ibc1` from a different terminal - - ```shell script - hermes query packet unreceived-packets ibc-1 ibc-0 transfer channel-0 - hermes query packet unreceived-acks ibc-0 ibc-1 transfer channel-1 - hermes query packet unreceived-packets ibc-0 ibc-1 transfer channel-1 - hermes query packet unreceived-acks ibc-1 ibc-0 transfer channel-0 - ``` - - There should be no unreceived packets and acks: - - ```json - { - "status": "success", - "result": [] - } - ``` - - > It may also show packets that have been sent before the relayer loop was started (Hermes currently does not flush those). diff --git a/guide/src/tutorial_relay_two_paths.md b/guide/src/tutorial_relay_two_paths.md deleted file mode 100644 index ede9f0c5a3..0000000000 --- a/guide/src/tutorial_relay_two_paths.md +++ /dev/null @@ -1,223 +0,0 @@ -# Concurrent packet relaying on multiple paths - -At the moment, one Hermes instance relays packets over a single channel. -To relay packets over multiple channels, one needs to spawn multiple instances. - -> Due to a current limitation, an instance needs its own configuration file -and its own `data` folder. The steps below describe the process for setting things -up properly for two hermes instances. - -1. From the `ibc-rs` repository folder run the following script with the parameters below to start the chains (`ibc-0` and `ibc-1`): - - ```bash - ./scripts/setup-chains ibc-0 ibc-1 - ``` - - > __NOTE__: If the script above prompts you to delete the data folder just answer __'yes'__ - - The script configures and starts two __`gaiad`__ instances, one named __`ibc-0`__ and the other __`ibc-1`__ - -2. From the root of the working copy of `ibc-rs`, create a folder for the first instance: - - ```shell - mkdir relay_a && cd relay_a - ``` - -3. Paste the following configuration in a file named `config.toml` in the `relay_a` directory: - - ```toml - [global] - timeout = '10s' - strategy = 'naive' - log_level = 'error' - - [[chains]] - id = 'ibc-0' - rpc_addr = 'tcp://localhost:26657' - grpc_addr = 'tcp://localhost:9090' - account_prefix = 'cosmos' - key_name = 'testkey' - store_prefix = 'ibc' - gas = 200000 - clock_drift = '5s' - trusting_period = '14days' - - [chains.trust_threshold] - numerator = '1' - denominator = '3' - - [[chains]] - id = 'ibc-1' - rpc_addr = 'tcp://localhost:26557' - grpc_addr = 'tcp://localhost:9091' - account_prefix = 'cosmos' - key_name = 'testkey' - store_prefix = 'ibc' - gas = 200000 - clock_drift = '5s' - trusting_period = '14days' - - [chains.trust_threshold] - numerator = '1' - denominator = '3' - - [[connections]] - a_chain = "ibc-1" - b_chain = "ibc-0" - - [[connections.paths]] - a_port = 'transfer' - b_port = 'transfer' - ``` - -4. Create the data folders for both chains: - - ```shell - mkdir -p data/ibc-0/data - mkdir -p data/ibc-1/data - ``` - -5. Copy the keys over from the chains `data` directory: - - ```shell - cp ../data/ibc-0/key_seed.json data/ibc-0/ - cp ../data/ibc-1/key_seed.json data/ibc-1/ - ``` -6. Initialize the light clients: - - ```shell - ../scripts/init-clients config.toml ibc-0 ibc-1 - ``` - -7. Let's proceed similarly for the second instance, but pay attention to the commands - and the configuration, as both are slightly different from the steps above. - - From the root of the working copy of `ibc-rs`, create a folder for the second instance: - - ```shell - mkdir relay_b && cd relay_b - ``` - -8. Paste the following configuration in a file named `config.toml` in the `relay_b` directory: - - ```toml - [global] - timeout = '10s' - strategy = 'naive' - log_level = 'error' - - [[chains]] - id = 'ibc-0' - rpc_addr = 'tcp://localhost:26657' - grpc_addr = 'tcp://localhost:9090' - account_prefix = 'cosmos' - key_name = 'testkey' - store_prefix = 'ibc' - gas = 200000 - clock_drift = '5s' - trusting_period = '14days' - - [chains.trust_threshold] - numerator = '1' - denominator = '3' - - [[chains]] - id = 'ibc-1' - rpc_addr = 'tcp://localhost:26557' - grpc_addr = 'tcp://localhost:9091' - account_prefix = 'cosmos' - key_name = 'testkey' - store_prefix = 'ibc' - gas = 200000 - clock_drift = '5s' - trusting_period = '14days' - - [chains.trust_threshold] - numerator = '1' - denominator = '3' - - [[connections]] - a_chain = "ibc-0" - b_chain = "ibc-1" - - [[connections.paths]] - a_port = 'transfer' - b_port = 'transfer' - ``` - -9. Create the data folders for both chains: - - ```shell - mkdir -p data/ibc-0/data - mkdir -p data/ibc-1/data - ``` - -10. Copy the keys over from the chains `data` directory: - - ```shell - cp ../data/ibc-0/key_seed.json data/ibc-0/ - cp ../data/ibc-1/key_seed.json data/ibc-1/ - ``` -11. Initialize the light clients: - - ```shell - ../scripts/init-clients config.toml ibc-0 ibc-1 - ``` - -12. Start the first relayer in the `relay_a` directory: - - ```shell - hermes -c config.toml start ibc-0 ibc-1 - ``` - Take note of the identifier of this first channel created between the two chains, e.g. `channel-0` - -13. In another terminal, start the second relayer from the `relay_b` directory: - - ```shell - hermes -c config.toml start ibc-0 ibc-1 - ``` - -14. In yet another terminal, From the either the `relay_a` or `relay_b` directory, use the `tx raw ft-transfer` command to send 2 packets to the `ibc0` chain: - - ```shell - hermes -c config.toml tx raw ft-transfer ibc-0 ibc-1 transfer channel-0 9999 1000 -n 2 - ``` - Take note of the identifier of the second channel created between the two chains, e.g. `channel-1` - -14. In yet another terminal: - Use the `tx raw ft-transfer` command to send packets on the two channels: - - ```shell - hermes -c relay_a/config.toml tx raw ft-transfer ibc-0 ibc-1 transfer channel-0 9999 1000 -n 2 - hermes -c relay_b/config.toml tx raw ft-transfer ibc-0 ibc-1 transfer channel-1 9999 1000 -n 2 - ``` - -16. Observe the output on both relayer terminals, verify that the send events are processed, and the `recv_packet` -s are sent out. - -17. Query the unreceived packets on `ibc-0` and `ibc-1` for both channels: - - ```shell - # verify that there are no pending packets on channe-0 in either direction - hermes -c relay_a/config.toml query packet unreceived-packets ibc-1 ibc-0 transfer channel-0 - hermes -c relay_a/config.toml query packet unreceived-acks ibc-0 ibc-1 transfer channel-0 - hermes -c relay_a/config.toml query packet unreceived-packets ibc-0 ibc-1 transfer channel-0 - hermes -c relay_a/config.toml query packet unreceived-acks ibc-1 ibc-0 transfer channel-0 - # verify that there are no pending packets on channe-1 in either direction - hermes -c relay_b/config.toml query packet unreceived-packets ibc-1 ibc-0 transfer channel-1 - hermes -c relay_b/config.toml query packet unreceived-acks ibc-0 ibc-1 transfer channel-1 - hermes -c relay_b/config.toml query packet unreceived-packets ibc-0 ibc-1 transfer channel-1 - hermes -c relay_b/config.toml query packet unreceived-acks ibc-1 ibc-0 transfer channel-1 - ``` - - There should be no unreceived packets and acks on both channels: - - ```json - { - "status": "success", - "result": [] - } - ``` - - > The above commands may show some packets if any have been sent before the instances were started (Hermes currently does not flush those). - - diff --git a/guide/src/tutorial_set_new_path.md b/guide/src/tutorial_set_new_path.md deleted file mode 100644 index dc574f08e3..0000000000 --- a/guide/src/tutorial_set_new_path.md +++ /dev/null @@ -1,29 +0,0 @@ -# Create a new path - -Perform client creation, connection and channel handshake to establish a new path between the `transfer` ports on `ibc-0` and `ibc-1` chains. - -```shell script -hermes channel handshake ibc-0 ibc-1 transfer transfer -``` - -```json -{ - "status": "success", - "result": { - "a_side": { - "chain": "ibc-1", - "channel_id": "channel-3", - "client_id": "07-tendermint-3", - "connection_id": "connection-2", - "port_id": "transfer"}, - "b_side": { - "chain": "ibc-0", - "channel_id": "channel-1", - "client_id": "07-tendermint-1", - "connection_id": "connection-3", - "port_id": "transfer" - }, - "ordering":"Unordered" - } -} -``` diff --git a/guide/src/tutorials.md b/guide/src/tutorials/index.md similarity index 74% rename from guide/src/tutorials.md rename to guide/src/tutorials/index.md index e5b6dab581..8eee017999 100644 --- a/guide/src/tutorials.md +++ b/guide/src/tutorials/index.md @@ -1,9 +1,9 @@ # Tutorials -This section includes tutorials for some common relayer uses cases and commands. You can also refer to the [Commands Reference](./commands.md) section to learn more about individual commands. +This section includes tutorials for some common relayer uses cases and commands. You can also refer to the [Commands Reference](../commands/index.md) section to learn more about individual commands. ## Basic tutorials -**[Two Local Chains](./two_chains.md)** +**[Two Local Chains](./local-chains/index.md)** In this tutorial you will learn how to start two local [`Cosmos Gaia`](https://github.com/cosmos/gaia) chains that support the `IBC` protocol and start relaying packets between them. diff --git a/guide/src/gaia.md b/guide/src/tutorials/local-chains/gaia.md similarity index 73% rename from guide/src/gaia.md rename to guide/src/tutorials/local-chains/gaia.md index 78baf6c1d6..147daa6dfd 100644 --- a/guide/src/gaia.md +++ b/guide/src/tutorials/local-chains/gaia.md @@ -4,7 +4,7 @@ The script to start the chains requires gaia to be installed. > __NOTE__: This assumes you have `Golang` programming language installed on > your machine. If not, please ensure you install before proceeding. See -> more details in the [Pre-requisites](pre_requisites.html#2-golang) section. +> more details in the [Pre-requisites](../../pre_requisites.md#2-golang) section. #### Clone gaia @@ -20,16 +20,20 @@ Run the `make` command to build and install `gaiad` ```shell cd ~/go/src/github.com/cosmos/gaia -git checkout v4.0.0 +git checkout v4.2.0 make install ``` If the command above is successful you can run the following command to ensure it was properly installed: ```shell -gaiad version +$ gaiad version --log_level error --long | head -n4 +name: gaia +server_name: gaiad +version: v4.2.0 +commit: 535be14a8bdbfeb0d950914b5baa2dc72c6b081c ``` ## Next Steps -In the next section you will learn how to [start two local chains](./local_chains.md) \ No newline at end of file +In the next section you will learn how to [start two local chains](./start.md) diff --git a/guide/src/tutorials/local-chains/identifiers.md b/guide/src/tutorials/local-chains/identifiers.md new file mode 100644 index 0000000000..092fc3b25e --- /dev/null +++ b/guide/src/tutorials/local-chains/identifiers.md @@ -0,0 +1,130 @@ +# Identifiers + + +A chain allocates identifiers when it creates clients, connections and channels. These identifiers can subsequently be used to refer to existing clients, connections and channels. + +> NOTE: If you want to ensure you get the same identifiers while following the tutorials, run the each of the three commands below __once__ on `ibc-1`. This will ensure that when going through the tutorial, a second channel on `ibc-1` with identifier `channel-1` will created. + +Chains allocate identifiers using a chain specific allocation scheme. Currently, *cosmos-sdk* implementation uses the follow identifiers: + +### 1. Client Identifiers + +__`07-tendermint-`__ for tendermint clients + +For example `07-tendermint-0` is assigned to the first client created on `ibc-1`: + + ```shell +hermes tx raw create-client ibc-1 ibc-0 + ``` + + ```rust +Success: CreateClient( + CreateClient( + Attributes { + height: Height { + revision: 1, + height: 103, + }, + client_id: ClientId( + "07-tendermint-0", + ), + client_type: Tendermint, + consensus_height: Height { + revision: 0, + height: 112, + }, + }, + ), +) + ``` + +We will create a second client on `ibc-1` with identifier `07-tendermint-1` in the client tutorial. + +### 2. Connection Identifiers + +__`connection-`__ for connections + +For example `connection-0` is assigned to the first connection created on `ibc-1`: + +```shell +hermes tx raw conn-init ibc-1 ibc-0 07-tendermint-0 07-tendermint-0 +``` + +```rust +Success: OpenInitConnection( + OpenInit( + Attributes { + height: Height { + revision: 1, + height: 119, + }, + connection_id: Some( + ConnectionId( + "connection-0", + ), + ), + client_id: ClientId( + "07-tendermint-0", + ), + counterparty_connection_id: None, + counterparty_client_id: ClientId( + "07-tendermint-0", + ), + }, + ), +) +``` +We will create a second connection on `ibc-1` with identifier `connection-1` in the connection tutorial. + +### 3. Channel Identifiers + +`channel-` for channels + +For example `channel-0` is assigned to the first channel created on `ibc-1`: + +```shell +hermes tx raw chan-open-init ibc-1 ibc-0 connection-0 transfer transfer +``` + +```rust +Success: OpenInitChannel( + OpenInit( + Attributes { + height: Height { + revision: 1, + height: 225, + }, + port_id: PortId( + "transfer", + ), + channel_id: Some( + ChannelId( + "channel-0", + ), + ), + connection_id: ConnectionId( + "connection-0", + ), + counterparty_port_id: PortId( + "transfer", + ), + counterparty_channel_id: None, + }, + ), +) +``` + +In the following tutorials the __`ibc-0`__ and __`ibc-1`__ chains are setup and configured. + +For clarity, the tutorials run on a setup where the identifiers allocated to the client, connection and channel on __`ibc-0`__ are __`07-tendermint-0`__, __`connection-0`__ and __`channel-0`__ respectively. Identifiers allocated to the client, connection and channel on __`ibc-1`__ are __`07-tendermint-1`__, __`connection-1`__ and __`channel-1`__ respectively. + +Before going over the next sections, please ensure the commands above are executed. + +### Next Steps + +The following sections describe the commands to connect and relay packets between two chains. You can: + +1. use a [simplified approach](./relay-paths/index.md) for managing relaying paths, or +2. use [individual (raw) transactions](./raw/index.md) to create + all the necessary chain objects (clients, connections, channels) and relay packets. + diff --git a/guide/src/two_chains.md b/guide/src/tutorials/local-chains/index.md similarity index 90% rename from guide/src/two_chains.md rename to guide/src/tutorials/local-chains/index.md index 209606b360..4ffdfa025f 100644 --- a/guide/src/two_chains.md +++ b/guide/src/tutorials/local-chains/index.md @@ -4,4 +4,4 @@ In this tutorial we will show how you can test the relayer against two chains, w The script starts two [`gaia`](https://github.com/cosmos/gaia) chains that support the `IBC` protocol. -Follow the steps in this tutorial section starting with the [Install Gaia](./gaia.md) section. +Follow the steps in this tutorial section starting with the [Install Gaia](./gaia.md) section.# Local chains diff --git a/guide/src/tutorial_chan_open_raw.md b/guide/src/tutorials/local-chains/raw/channel.md similarity index 82% rename from guide/src/tutorial_chan_open_raw.md rename to guide/src/tutorials/local-chains/raw/channel.md index 9e7f9bb3eb..6902d98ae4 100644 --- a/guide/src/tutorial_chan_open_raw.md +++ b/guide/src/tutorials/local-chains/raw/channel.md @@ -1,13 +1,13 @@ # 3. Channel Handshake -### 3.1 chan-open-init +## 3.1 `chan-open-init` Initialize a new unordered channel on `ibc-0`: ```shell hermes tx raw chan-open-init ibc-0 ibc-1 connection-0 transfer transfer -o UNORDERED ``` -### 3.2 chan-open-try +## 3.2 `chan-open-try` Send a channel open try to `ibc-1`: ```shell @@ -16,21 +16,21 @@ hermes tx raw chan-open-try ibc-1 ibc-0 connection-1 transfer transfer -s channe Take note of the ID allocated by the chain, e.g. `channel-1` on `ibc-1`. Use in the `chan-open-ack` CLI -### 3.3 chan-open-ack +## 3.3 `chan-open-ack` Send a channel open acknowledgment to `ibc-0`: ```shell hermes tx raw chan-open-ack ibc-0 ibc-1 connection-0 transfer transfer -d channel-0 -s channel-1 ``` -### 3.4 chan-open-confirm +## 3.4 `chan-open-confirm` Send the open confirmation to `ibc-1`: ```shell hermes tx raw chan-open-confirm ibc-1 ibc-0 connection-1 transfer transfer -d channel-1 -s channel-0 ``` -### 3.5 query channel +## 3.5 `query channel` To verify that the two ends are in `Open` state: ```shell @@ -43,4 +43,4 @@ hermes query channel end ibc-1 transfer channel-1 ## Next Steps -In the next section, we'll start to [relay packets](./tutorial_packet_raw.md) \ No newline at end of file +In the next section, we'll start to [relay packets](./packet.md) diff --git a/guide/src/tutorials/local-chains/raw/client.md b/guide/src/tutorials/local-chains/raw/client.md new file mode 100644 index 0000000000..ce72268d03 --- /dev/null +++ b/guide/src/tutorials/local-chains/raw/client.md @@ -0,0 +1,117 @@ +# 1. Configuring clients + +### 1.1. `create client` + +First you will need to create a client for each chain: + +This command submits a transaction to a destination chain (`ibc-0`) with a request to create a client for a source chain (`ibc-1`): + +```shell +hermes tx raw create-client ibc-0 ibc-1 +``` + +if the command is successful a message similar to the one below will be displayed `status:success`: + +```rust +{ + Success: CreateClient( + CreateClient( + Attributes { + height: Height { revision: 0, height: 43 }, + client_id: ClientId( + "07-tendermint-0", + ), + client_type: Tendermint, + consensus_height: Height { revision: 1, height: 32 }, + }, + ), + ) +} +``` + +> Please note the `client_id` value returned. You will need that for other commands. + +You can also execute a __query__ to view the client state on destination chain `ibc-0` by specifying the `client_id` value `07-tendermint-0`: + +```shell +hermes query client state ibc-0 07-tendermint-0 +``` + +which show a message similar to the one below: + +```json +Success: ClientState { + chain_id: ChainId { + id: "ibc-1", + version: 1, + }, + trust_level: TrustThresholdFraction { + numerator: 1, + denominator: 3, + }, + trusting_period: 1209600s, + unbonding_period: 1814400s, + max_clock_drift: 3s, + frozen_height: Height { + revision: 0, + height: 0, + }, + latest_height: Height { + revision: 1, + height: 38, + }, + upgrade_path: [ + "upgrade", + "upgradedIBCState", + ], + allow_update_after_expiry: false, + allow_update_after_misbehaviour: false, +} +``` + +Now let's do the same for `ibc-1` as the destination chain: + +```shell +hermes tx raw create-client ibc-1 ibc-0 +``` + +Take note of the `client_id` allocated for this client. In the examples we assume is `07-tendermint-1` (this client identity is obtained by creating two clients on ibc-1 for ibc-0). + +As before, if the command is successful a message with `status:success` is displayed: + +```json +Success: CreateClient( + CreateClient( + Attributes { + height: Height { + revision: 1, + height: 135, + }, + client_id: ClientId( + "07-tendermint-1", + ), + client_type: Tendermint, + consensus_height: Height { + revision: 0, + height: 145, + }, + }, + ), +) +``` + +### 1.2 `update-client` + +Client states can be updated by sending an `update-client` transaction: + +```shell +hermes tx raw update-client ibc-0 07-tendermint-0 +``` + +```shell +hermes tx raw update-client ibc-1 07-tendermint-1 +``` + +## Next Steps + +In the next section, we'll establish the [Connection Handshake](./connection.md) diff --git a/guide/src/tutorial_conn_raw.md b/guide/src/tutorials/local-chains/raw/connection.md similarity index 77% rename from guide/src/tutorial_conn_raw.md rename to guide/src/tutorials/local-chains/raw/connection.md index 82527e9ecc..f93c35e074 100644 --- a/guide/src/tutorial_conn_raw.md +++ b/guide/src/tutorials/local-chains/raw/connection.md @@ -1,6 +1,6 @@ # 2. Connection Handshake -### 2.1 `conn-init` +## 2.1 `conn-init` Initialize a new connection on `ibc-0`: ```shell @@ -9,41 +9,42 @@ hermes tx raw conn-init ibc-0 ibc-1 07-tendermint-0 07-tendermint-1 Take note of the ID allocated by the chain, e.g. `connection-0` on `ibc-0` in order to use it in the `conn-try` command below. -### 2.2 `conn-try` +## 2.2 `conn-try` Send a connection try to `ibc-1`: ```shell -hermes tx raw conn-try ibc-1 ibc-0 07-tendermint-0 07-tendermint-1 -s connection-0 +hermes tx raw conn-try ibc-1 ibc-0 07-tendermint-1 07-tendermint-0 -s connection-0 ``` Take note of the ID allocated by the chain, e.g. `connection-1` on `ibc-1`. Use in the `conn-ack` CLI -### 2.3 conn-ack +## 2.3 `conn-ack` Send a connection open acknowledgment to `ibc-0`: ```shell hermes tx raw conn-ack ibc-0 ibc-1 07-tendermint-0 07-tendermint-1 -d connection-0 -s connection-1 ``` -### 2.4 conn-confirm +## 2.4 `conn-confirm` Send the open confirmation to `ibc-1`: ```shell hermes tx raw conn-confirm ibc-1 ibc-0 07-tendermint-1 07-tendermint-0 -d connection-1 -s connection-0 ``` -### 2.5 query connection +## 2.5 `query connection` To verify that the two ends are in `Open` state: ```shell -hermes query connection end ibc-1 connection-1 +hermes query connection end ibc-0 connection-0 ``` ```shell -hermes query connection end ibc-0 connection-0 +hermes query connection end ibc-1 connection-1 ``` + ## Next Steps -In the next section, we'll [establish a new channel](./tutorial_chan_open_raw.md) \ No newline at end of file +In the next section, we'll [establish a new channel](./channel.md) diff --git a/guide/src/tutorials/local-chains/raw/index.md b/guide/src/tutorials/local-chains/raw/index.md new file mode 100644 index 0000000000..bc0fbeebaa --- /dev/null +++ b/guide/src/tutorials/local-chains/raw/index.md @@ -0,0 +1,12 @@ +# Connecting the chains + +In the rest of this section we will show how to create the clients, establish a connection and a channel between the two chains, and relay packets over the channel. But first, make sure you followed the steps in the [start the local chains](../start.md) and [Identifiers section](../identifiers.md) + +## Steps to start relaying packets between the two local chains + +In order to start relaying packets please follow the steps below: + +* [Configure Clients](./client.md) +* [Connection Handshake](./connection.md) +* [Open the Channel](./channel.md) +* [Relay Packets](./packet.md) diff --git a/guide/src/tutorial_packet_raw.md b/guide/src/tutorials/local-chains/raw/packet.md similarity index 64% rename from guide/src/tutorial_packet_raw.md rename to guide/src/tutorials/local-chains/raw/packet.md index edb6b00c31..4cfd6ad37e 100644 --- a/guide/src/tutorial_packet_raw.md +++ b/guide/src/tutorials/local-chains/raw/packet.md @@ -1,79 +1,79 @@ # 4. Relay Packets -### 4.1 Query balances: +### 4.1 Query balances - balance at ibc-0 - ```shell script + ```shell gaiad --node tcp://localhost:26657 query bank balances $(gaiad --home data/ibc-0 keys --keyring-backend="test" show user -a) ``` - balance at ibc-1 - ```shell script + ```shell gaiad --node tcp://localhost:26557 query bank balances $(gaiad --home data/ibc-1 keys --keyring-backend="test" show user -a) ``` > Note that the addresses used in the two commands above are configured in `dev-env`. -### 4.2 Packet relaying: +### 4.2 Packet relaying First, we'll send `9999` `samoleans` from `ibc-0` to `ibc-1`. - start the transfer of 9999 samoleans from `ibc-0` to `ibc-1`. This sends a `MsgTransfer` in a transaction to `ibc-0` - ```shell script - hermes tx raw ft-transfer ibc-0 ibc-1 transfer channel-0 9999 1000 -n 1 -d samoleans + ```shell + hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-0 9999 1000 -n 1 -d samoleans ``` - query packet commitments on `ibc-0` - ```shell script + ```shell hermes query packet commitments ibc-0 transfer channel-0 ``` - query unreceived packets on `ibc-1` - ```shell script + ```shell hermes query packet unreceived-packets ibc-1 ibc-0 transfer channel-0 ``` -- send recv_packet to `ibc-1` +- send `recv_packet` to `ibc-1` - ```shell script + ```shell hermes tx raw packet-recv ibc-1 ibc-0 transfer channel-0 ``` - query unreceived acks on `ibc-0` - ```shell script + ```shell hermes query packet unreceived-acks ibc-0 ibc-1 transfer channel-1 ``` - send acknowledgement to `ibc-0` - ```shell script - hermes tx raw packet-ack ibc-0 ibc-1 transfer channel-1 + ```shell + hermes tx raw packet-ack ibc-0 ibc-1 transfer channel-1 ``` - send 1 packet with low timeout height offset to ibc-0 - ```shell script - hermes tx raw ft-transfer ibc-0 ibc-1 transfer channel-0 9999 2 -n 1 + ```shell + hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-0 9999 2 -n 1 ``` - send timeout to `ibc-0` - ```shell script + ```shell hermes tx raw packet-recv ibc-1 ibc-0 transfer channel-0 ``` -Send those samoleans back, from `ibc-1` to `ibc-1`. +Send those samoleans back, from `ibc-1` to `ibc-0`. -```shell script -hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-0 9999 1000 -n 1 -d ibc/C1840BD16FCFA8F421DAA0DAAB08B9C323FC7685D0D7951DC37B3F9ECB08A199 +```shell +hermes tx raw ft-transfer ibc-0 ibc-1 transfer channel-1 9999 1000 -n 1 -d ibc/49D321B40FCF56B0370E5673CF090389C8E9CD185209FBE1BEE5D94E58E69BDC hermes tx raw packet-recv ibc-0 ibc-1 transfer channel-1 hermes tx raw packet-ack ibc-1 ibc-0 transfer channel-0 ``` -The `ibc/C1840BD16FCFA8F421DAA0DAAB08B9C323FC7685D0D7951DC37B3F9ECB08A199` denominator above can be obtained by querying the balance at `ibc-1` after the transfer from `ibc-0` to `ibc-1` is concluded. +The `ibc/49D321B40FCF56B0370E5673CF090389C8E9CD185209FBE1BEE5D94E58E69BDC` denominator above can be obtained by querying the balance at `ibc-1` after the transfer from `ibc-0` to `ibc-1` is concluded. diff --git a/guide/src/tutorials/local-chains/relay-paths/create-new-path.md b/guide/src/tutorials/local-chains/relay-paths/create-new-path.md new file mode 100644 index 0000000000..ff55e6ea45 --- /dev/null +++ b/guide/src/tutorials/local-chains/relay-paths/create-new-path.md @@ -0,0 +1,64 @@ +# Create a new path + +Perform client creation, connection and channel handshake to establish a new path between the `transfer` ports on `ibc-0` and `ibc-1` chains. + +```shell +hermes create channel ibc-0 ibc-1 --port-a transfer --port-b transfer +``` + +If all the handshakes are performed successfully you should see a message similar to the one below: + +```json +Success: Channel { + ordering: Unordered, + a_side: ChannelSide { + chain: ProdChainHandle { + chain_id: ChainId { + id: "ibc-0", + version: 0, + }, + runtime_sender: Sender { .. }, + }, + client_id: ClientId( + "07-tendermint-0", + ), + connection_id: ConnectionId( + "connection-0", + ), + port_id: PortId( + "transfer", + ), + channel_id: ChannelId( + "channel-0", + ), + }, + b_side: ChannelSide { + chain: ProdChainHandle { + chain_id: ChainId { + id: "ibc-1", + version: 1, + }, + runtime_sender: Sender { .. }, + }, + client_id: ClientId( + "07-tendermint-1", + ), + connection_id: ConnectionId( + "connection-1", + ), + port_id: PortId( + "transfer", + ), + channel_id: ChannelId( + "channel-1", + ), + }, + connection_delay: 0ns, + version: Some( + "ics20-1", + ), +} + +``` + +Note that for each side, *a_side* (__ibc-0__) and *b_side* (__ibc-1__) there are a __client_id__, __connection_id__, __channel_id__ and __port_id__. With all these established, you have [a path that you can relay packets](./existing-path.md) diff --git a/guide/src/tutorials/local-chains/relay-paths/existing-path.md b/guide/src/tutorials/local-chains/relay-paths/existing-path.md new file mode 100644 index 0000000000..1b49c09367 --- /dev/null +++ b/guide/src/tutorials/local-chains/relay-paths/existing-path.md @@ -0,0 +1,96 @@ +# Packet relaying on existing path + +Hermes can listen to IBC packet events over a specified path and relay receive packets, acknowledgments and timeouts. + +1. From one terminal start Hermes using the `start` command and specify the port and a previously established channel: + + ```shell + hermes start ibc-0 ibc-1 -p transfer -c channel-0 + ``` + + > In this example, the channel identifier on `ibc-0`is `channel-0` while the identifier on`ibc-1` is `channel-1` + + +2. In a separate terminal, use the transfer command to send 2 packets to `ibc-0` chain: + + ```shell + hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-0 9999 1000 -n 2 + ``` + + You should see a result similar to the one below: + + ```json + Success: [ + SendPacket( + SendPacket { + height: Height { + revision: 0, + height: 842, + }, + packet: PortId("transfer") ChannelId("channel-0") Sequence(1), + }, + ), + SendPacket( + SendPacket { + height: Height { + revision: 0, + height: 842, + }, + packet: PortId("transfer") ChannelId("channel-0") Sequence(2), + }, + ), + ] + ``` + +3. Use the CLI to send 2 packets to `ibc-1` chain: + + ```shell + hermes tx raw ft-transfer ibc-0 ibc-1 transfer channel-1 9999 1000 -n 2 + ``` + + You should see a result similar to the one below: + + ```json + Success: [ + SendPacket( + SendPacket { + height: Height { + revision: 1, + height: 963, + }, + packet: PortId("transfer") ChannelId("channel-1") Sequence(1), + }, + ), + SendPacket( + SendPacket { + height: Height { + revision: 1, + height: 963, + }, + packet: PortId("transfer") ChannelId("channel-1") Sequence(2), + }, + ), + ] + ``` + +4. Observe the output on the relayer terminal, verify that the send events are processed, and that the `recv_packet`s are sent out. + +5. Query the unreceived packets on `ibc-0` and `ibc-1` from a different terminal + + ```shell + hermes query packet unreceived-packets ibc-1 ibc-0 transfer channel-0 + hermes query packet unreceived-acks ibc-0 ibc-1 transfer channel-1 + hermes query packet unreceived-packets ibc-0 ibc-1 transfer channel-1 + hermes query packet unreceived-acks ibc-1 ibc-0 transfer channel-0 + ``` + + There should be no unreceived packets and acks: + + ```json + { + "status": "success", + "result": [] + } + ``` + + > It may also show packets that have been sent before the relayer loop was started (Hermes currently does not flush those). diff --git a/guide/src/tutorial_relay_paths.md b/guide/src/tutorials/local-chains/relay-paths/index.md similarity index 51% rename from guide/src/tutorial_relay_paths.md rename to guide/src/tutorials/local-chains/relay-paths/index.md index 548aeead04..5563df676a 100644 --- a/guide/src/tutorial_relay_paths.md +++ b/guide/src/tutorials/local-chains/relay-paths/index.md @@ -2,8 +2,11 @@ # Connect the chains using relay paths A relay path refers to a specific channel used to interconnect two chains and over which packets are being sent. + Hermes can be started to listen for packet events on the two ends of a path and relay packets. This can be done over a new or existing path. - - [Create a new path](./tutorial_set_new_path.md) - - [Packet relaying on existing path](./tutorial_relay_existing_path.md) - - [Packet relaying on new path](./tutorial_relay_new_path.md) +- [Create a new path](./create-new-path.md) +- [Packet relaying on existing path](./existing-path.md) +- [Packet relaying on new path](./new-path.md) + +Before proceeding to the sections above, please first, make sure you followed the steps in the [Identifiers section](../identifiers.md) \ No newline at end of file diff --git a/guide/src/tutorials/local-chains/relay-paths/multiple-paths.md b/guide/src/tutorials/local-chains/relay-paths/multiple-paths.md new file mode 100644 index 0000000000..6889cb4bec --- /dev/null +++ b/guide/src/tutorials/local-chains/relay-paths/multiple-paths.md @@ -0,0 +1,327 @@ +# Concurrent packet relaying on multiple paths + +At the moment, the `start` command relays packets over a single channel. +To relay packets over multiple channels concurrently, one can instead use +the `start-multi` command. + +> __WARNING__: Relaying packets concurrently over multiple channels with the +> `start-multi` command is currently __experimental__. Use at your own risk. + +> __Caveat__: At the moment, `start-multi` does not clear pending packets +> when starting. It is therefore advised to only use it for channels which +> do not have pending packets. + +1. Paste the following configuration in a file named __`multi-config.toml`__: + + ```toml + [global] + strategy = 'naive' + log_level = 'info' + + [[chains]] + id = 'ibc-0' + rpc_addr = 'http://127.0.0.1:26657' + grpc_addr = 'http://127.0.0.1:9090' + websocket_addr = 'ws://127.0.0.1:26657/websocket' + rpc_timeout = '10s' + account_prefix = 'cosmos' + key_name = 'testkey' + store_prefix = 'ibc' + gas = 200000 + fee_denom = 'stake' + fee_amount = 10 + clock_drift = '5s' + trusting_period = '14days' + + [chains.trust_threshold] + numerator = '1' + denominator = '3' + + [[chains]] + id = 'ibc-1' + rpc_addr = 'http://127.0.0.1:26557' + grpc_addr = 'http://127.0.0.1:9091' + websocket_addr = 'ws://127.0.0.1:26557/websocket' + rpc_timeout = '10s' + account_prefix = 'cosmos' + key_name = 'testkey' + store_prefix = 'ibc' + gas = 200000 + fee_denom = 'stake' + fee_amount = 10 + clock_drift = '5s' + trusting_period = '14days' + + [[chains]] + id = 'ibc-2' + rpc_addr = 'http://127.0.0.1:26457' + grpc_addr = 'http://127.0.0.1:9092' + websocket_addr = 'ws://127.0.0.1:26457/websocket' + rpc_timeout = '10s' + account_prefix = 'cosmos' + key_name = 'testkey' + store_prefix = 'ibc' + gas = 200000 + fee_denom = 'stake' + fee_amount = 10 + clock_drift = '5s' + trusting_period = '14days' + + [chains.trust_threshold] + numerator = '1' + denominator = '3' + + [[connections]] + a_chain = 'ibc-0' + b_chain = 'ibc-1' + + [[connections.paths]] + a_port = 'transfer' + b_port = 'transfer' + + [[connections]] + a_chain = 'ibc-1' + b_chain = 'ibc-2' + + [[connections.paths]] + a_port = 'transfer' + b_port = 'transfer' + ``` + + This configuration three chains `ibc-0`, `ibc-1` and `ibc-2` as well + as two connections: one between `ibc-0` and `ibc-1`, and another + between `ibc-1` and `ibc-2`, both using the `transfer` ports. + +2. Run the `dev-env` script with the parameters below to start three chains: + + ```bash + ./scripts/dev-env multi-config.toml ibc-0 ibc-1 ibc-2 + ``` + + > __NOTE__: If the script above prompts you to delete the data folder, answer __'yes'__. + + The script configures and starts three __`gaiad`__ instances, named __`ibc-0`__, and __`ibc-1`__, and __`ibc-2`__. + + +3. Create a channel between `ibc-0` and `ibc-1`: + + ```shell + hermes -c multi-config.toml create channel ibc-0 ibc-1 --port-a transfer --port-b transfer -o unordered + ``` + + ```rust + (...) + + Success: Channel { + ordering: Unordered, + a_side: ChannelSide { + chain: ProdChainHandle { + chain_id: ChainId { + id: "ibc-0", + version: 0, + }, + runtime_sender: Sender { .. }, + }, + client_id: ClientId( + "07-tendermint-0", + ), + connection_id: ConnectionId( + "connection-0", + ), + port_id: PortId( + "transfer", + ), + channel_id: ChannelId( + "channel-0", + ), + }, + b_side: ChannelSide { + chain: ProdChainHandle { + chain_id: ChainId { + id: "ibc-1", + version: 1, + }, + runtime_sender: Sender { .. }, + }, + client_id: ClientId( + "07-tendermint-0", + ), + connection_id: ConnectionId( + "connection-0", + ), + port_id: PortId( + "transfer", + ), + channel_id: ChannelId( + "channel-0", + ), + }, + connection_delay: 0ns, + version: Some( + "ics20-1", + ), + } + ``` + + Note that the channel identifier on both `ibc-0` and `ibc-1` is `channel-0`. + +5. Create a channel between `ibc-1` and `ibc-2`: + + ```shell + hermes -c multi-config.toml create channel ibc-1 ibc-2 --port-a transfer --port-b transfer -o unordered + ``` + + ```rust + (...) + + Success: Channel { + ordering: Unordered, + a_side: ChannelSide { + chain: ProdChainHandle { + chain_id: ChainId { + id: "ibc-1", + version: 1, + }, + runtime_sender: Sender { .. }, + }, + client_id: ClientId( + "07-tendermint-1", + ), + connection_id: ConnectionId( + "connection-1", + ), + port_id: PortId( + "transfer", + ), + channel_id: ChannelId( + "channel-1", + ), + }, + b_side: ChannelSide { + chain: ProdChainHandle { + chain_id: ChainId { + id: "ibc-2", + version: 2, + }, + runtime_sender: Sender { .. }, + }, + client_id: ClientId( + "07-tendermint-0", + ), + connection_id: ConnectionId( + "connection-0", + ), + port_id: PortId( + "transfer", + ), + channel_id: ChannelId( + "channel-0", + ), + }, + connection_delay: 0ns, + version: Some( + "ics20-1", + ), + } + ``` + + Note that the channel identifier on `ibc-1` is `channel-1`, and on `ibc-2` it is `channel-0`. + +3. From a terminal, start Hermes using the `start-multi` command: + + ```shell + hermes -c multi-config.toml start-multi + ``` + +4. In a separate terminal, use the `ft-transfer` command to send: + + - two packets from `ibc-0` to `ibc-1` from source channel `channel-0` + + ```shell + hermes -c multi-config.toml tx raw ft-transfer ibc-1 ibc-0 transfer channel-0 9999 1000 -n 2 + ``` + + ```rust + Success: [ + SendPacket( + SendPacket { + height: revision: 0, height: 3056, + packet: PortId("transfer") ChannelId("channel-0") Sequence(3), + }, + ), + SendPacket( + SendPacket { + height: revision: 0, height: 3056, + packet: PortId("transfer") ChannelId("channel-0") Sequence(4), + }, + ), + ] + ``` + + - two packets from `ibc-1` to `ibc-2` from source channel `channel-1` + + ```shell + hermes -c multi-config.toml tx raw ft-transfer ibc-2 ibc-1 transfer channel-1 9999 1000 -n 2 + ``` + + ```rust + Success: [ + SendPacket( + SendPacket { + height: revision: 1, height: 3076, + packet: PortId("transfer") ChannelId("channel-1") Sequence(3), + }, + ), + SendPacket( + SendPacket { + height: revision: 1, height: 3076, + packet: PortId("transfer") ChannelId("channel-1") Sequence(4), + }, + ), + ] + ``` + +5. Observe the output on the relayer terminal, verify that the send events are processed, and that the `recv_packets` are sent out. + + ``` + (...) + + INFO ibc_relayer::link: [ibc-0 -> ibc-1] result events: + UpdateClientEv(ev_h:1-3048, 07-tendermint-0(0-3057), ) + WriteAcknowledgementEv(h:1-3048, seq:3, path:channel-0/transfer->channel-0/transfer, toh:1-4045, tos:0)) + WriteAcknowledgementEv(h:1-3048, seq:4, path:channel-0/transfer->channel-0/transfer, toh:1-4045, tos:0)) + INFO ibc_relayer::link: [ibc-0 -> ibc-1] success + + (...) + + INFO ibc_relayer::link: [ibc-1 -> ibc-0] clearing old packets + INFO ibc_relayer::link: [ibc-1 -> ibc-0] received from query_txs [] + INFO ibc_relayer::link: [ibc-1 -> ibc-0] finished clearing pending packets + INFO ibc_relayer::link: [ibc-1 -> ibc-0] generate messages from batch with 2 events + INFO ibc_relayer::link: [ibc-1 -> ibc-0] scheduling op. data with 2 msg(s) for Destination chain (height 1-3049) + INFO ibc_relayer::link: [ibc-1 -> ibc-0] relay op. data to Destination, proofs height 1-3048, (delayed by: 2.154603ms) [try 1/10] + INFO ibc_relayer::link: [ibc-1 -> ibc-0] prepending Destination client update @ height 1-3049 + INFO ibc_relayer::link: [ibc-1 -> ibc-0] assembled batch of 3 message(s) + INFO ibc_relayer::link: [ibc-1 -> ibc-0] result events: + UpdateClientEv(ev_h:0-3059, 07-tendermint-0(1-3049), ) + AcknowledgePacketEv(h:0-3059, seq:3, path:channel-0/transfer->channel-0/transfer, toh:1-4045, tos:0)) + AcknowledgePacketEv(h:0-3059, seq:4, path:channel-0/transfer->channel-0/transfer, toh:1-4045, tos:0)) + INFO ibc_relayer::link: [ibc-1 -> ibc-0] success + + (...) + ``` + +5. Query the unreceived packets and acknowledgments on `ibc-1` and `ibc-2` from a different terminal: + + ```shell + hermes -c multi-config.toml query packet unreceived-packets ibc-0 ibc-1 transfer channel-0 + hermes -c multi-config.toml query packet unreceived-acks ibc-1 ibc-0 transfer channel-0 + hermes -c multi-config.toml query packet unreceived-packets ibc-2 ibc-1 transfer channel-1 + hermes -c multi-config.toml query packet unreceived-acks ibc-1 ibc-2 transfer channel-0 + ``` + + If everything went well, each of these commands should result in: + + ``` + Success: [] + ``` diff --git a/guide/src/tutorial_relay_new_path.md b/guide/src/tutorials/local-chains/relay-paths/new-path.md similarity index 63% rename from guide/src/tutorial_relay_new_path.md rename to guide/src/tutorials/local-chains/relay-paths/new-path.md index 3b17851e8b..56d16a6dd2 100644 --- a/guide/src/tutorial_relay_new_path.md +++ b/guide/src/tutorials/local-chains/relay-paths/new-path.md @@ -1,4 +1,4 @@ -## Packet relaying on new path +# Packet relaying on new path Hermes packet relaying can be done over a newly established path. It performs client creation, connection and channel handshake if a relay path is present in the configuration file. @@ -6,8 +6,8 @@ Hermes packet relaying can be done over a newly established path. It performs cl ```toml [[connections]] - a_chain = "ibc1" - b_chain = "ibc0" + a_chain = 'ibc-1' + b_chain = 'ibc-0' [[connections.paths]] a_port = 'transfer' @@ -16,7 +16,7 @@ Hermes packet relaying can be done over a newly established path. It performs cl 2. From one terminal start hermes over this path: - ```shell script + ```shell hermes start ibc-0 ibc-1 ``` @@ -24,26 +24,26 @@ Hermes packet relaying can be done over a newly established path. It performs cl Once the path is established the relayer waits listening for IBC packet events. -3. in a separate terminal, use the transfer command to send 2 packets to `ibc0` chain: +3. in a separate terminal, use the transfer command to send 2 packets to `ibc-0` chain: - ```shell script - hermes tx raw ft-transfer ibc-0 ibc-1 transfer channel-0 9999 1000 -n 2 + ```shell + hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-0 9999 1000 -n 2 ``` -4. use the CLI to send 2 packets to `ibc1` chain: +4. use the CLI to send 2 packets to `ibc-1` chain: - ```shell script - hermes tx raw ft-transfer ibc-1 ibc-0 transfer channel-1 9999 1000 -n 2 + ```shell + hermes tx raw ft-transfer ibc-0 ibc-1 transfer channel-1 9999 1000 -n 2 ``` 5. Observe the output on the relayer terminal, verify that the send events are processed, and the `recv_packet` -s are sent out. -6. Query the unreceived packets on `ibc0` and `ibc1` from a different terminal +6. Query the unreceived packets on `ibc-0` and `ibc-1` from a different terminal - ```shell script - hermes query packet unreceived-packets ibc-1 ibc-0 transfer channel-0 - hermes query packet unreceived-acks ibc-0 ibc-1 transfer channel-1 - hermes query packet unreceived-packets ibc-0 ibc-1 transfer channel-1 - hermes query packet unreceived-acks ibc-1 ibc-0 transfer channel-0 + ```shell + hermes query packet unreceived-packets ibc-1 ibc-0 transfer channel-0 + hermes query packet unreceived-acks ibc-0 ibc-1 transfer channel-1 + hermes query packet unreceived-packets ibc-0 ibc-1 transfer channel-1 + hermes query packet unreceived-acks ibc-1 ibc-0 transfer channel-0 ``` There should be no unreceived packets and acks: diff --git a/guide/src/local_chains.md b/guide/src/tutorials/local-chains/start.md similarity index 70% rename from guide/src/local_chains.md rename to guide/src/tutorials/local-chains/start.md index 14e16e0d3a..06d8d59010 100644 --- a/guide/src/local_chains.md +++ b/guide/src/tutorials/local-chains/start.md @@ -18,51 +18,14 @@ killall gaiad ### Configuration file -In order to run the script, you will need a `TOML` configuration file to be passed as a parameter. Please check the [`Configuration`](./config.md) section for more information about the relayer configuration file. +In order to run the script, you will need a `TOML` configuration file to be passed as a parameter. Please check the [`Configuration`](../../config.md) section for more information about the relayer configuration file. The following configuration file in the `ibc-rs` repository folder can be used for running the local chains: __config.toml__ ```toml -[global] -timeout = '10s' -strategy = 'naive' -log_level = 'error' - -[[chains]] -id = 'ibc-0' -rpc_addr = 'tcp://localhost:26657' -grpc_addr = 'tcp://localhost:9090' -account_prefix = 'cosmos' -key_name = 'testkey' -store_prefix = 'ibc' -gas = 3000000 -fee_denom = 'stake' -fee_amount = 10 -clock_drift = '5s' -trusting_period = '14days' - -[chains.trust_threshold] -numerator = '1' -denominator = '3' - -[[chains]] -id = 'ibc-1' -rpc_addr = 'tcp://localhost:26557' -grpc_addr = 'tcp://localhost:9091' -account_prefix = 'cosmos' -key_name = 'testkey' -store_prefix = 'ibc' -gas = 3000000 -fee_denom = 'stake' -fee_amount = 10 -clock_drift = '5s' -trusting_period = '14days' - -[chains.trust_threshold] -numerator = '1' -denominator = '3' +{{#include ../../../../config.toml}} ``` #### Saving the configuration file @@ -85,7 +48,8 @@ Then just __`copy`__ the content for `config.toml` above and __`paste`__ into th ### Running the script to start the chains -From the `ibc-rs` repository folder run the following script with the parameters below to start the chains (`ibc-0` and `ibc-1`) and configure the light client peers: +From the `ibc-rs` repository folder run the following script with the parameters below to start the chains (`ibc-0` and `ibc-1`) +and import the signing keys into the keyring: ```bash ./scripts/dev-env ~/.hermes/config.toml ibc-0 ibc-1 @@ -105,16 +69,19 @@ graph TD If the script runs successfully you should see a message similar to the one below in the terminal: ```shell -GAIA VERSION INFO: 4.0.0 +GAIA VERSION INFO: v4.2.0 Generating gaia configurations... Creating gaiad instance: home=./data | chain-id=ibc-0 | p2p=:26656 | rpc=:26657 | profiling=:6060 | grpc=:9090 | samoleans=:100000000000 Change settings in config.toml file... +Start gaia on grpc port: 9090... +Balances for validator 'cosmos1kx8dmaav2k3gjyqr80f6ddaf94v5yujpefu8j6' @ 'tcp://localhost:26657' balances: - amount: "0" denom: stake pagination: next_key: null total: "0" +Balances for user 'cosmos1n33qt980aml6q8e2ky85g3dn98eh6fghg7cn6y' @ 'tcp://localhost:26657' balances: - amount: "100000000000" denom: samoleans @@ -125,12 +92,15 @@ pagination: total: "0" Creating gaiad instance: home=./data | chain-id=ibc-1 | p2p=:26556 | rpc=:26557 | profiling=:6061 | grpc=:9091 | samoleans=:100000000000 Change settings in config.toml file... +Start gaia on grpc port: 9091... +Balances for validator 'cosmos188qk2p3qr7rjkequjjmpx0frcc65p6dltmml0x' @ 'tcp://localhost:26557' balances: - amount: "0" denom: stake pagination: next_key: null total: "0" +Balances for user 'cosmos1xkvpgw8dng3zr2au3n86u8e3h249355vg7jaef' @ 'tcp://localhost:26557' balances: - amount: "100000000000" denom: samoleans @@ -139,13 +109,12 @@ balances: pagination: next_key: null total: "0" -ibc-0 initialized. Watch file /dev/github.com/informalsystems/ibc-rs/data/ibc-0.log to see its execution. -ibc-1 initialized. Watch file /dev/github.com/informalsystems/ibc-rs/data/ibc-1.log to see its execution. +ibc-0 initialized. Watch file /Users/ancaz/rust/ibc-rs/data/ibc-0.log to see its execution. +ibc-1 initialized. Watch file /Users/ancaz/rust/ibc-rs/data/ibc-1.log to see its execution. Building the Rust relayer... -Removing light client peers from configuration... -Adding primary peers to light client configuration... -Adding secondary peers to light client configuration... Importing keys... +Success: Added key testkey (cosmos1n33qt980aml6q8e2ky85g3dn98eh6fghg7cn6y) on ibc-0 chain +Success: Added key testkey (cosmos1xkvpgw8dng3zr2au3n86u8e3h249355vg7jaef) on ibc-1 chain Done! ``` @@ -173,11 +142,13 @@ data ``` +> __Tip__: You can use the command `tree ./data/ -L 2` to view the folder structure above: + ### $HOME/.hermes directory -By the default `hermes` expects the configuration file to be in the __`$HOME/.hermes`__ folder. +By the default `hermes` expects the configuration file to be in the __`$HOME/.hermes`__ folder. -It also stores the private keys for each chain in this folder as outlined in the [Keys](./keys.md) section. +It also stores the private keys for each chain in this folder as outlined in the [Keys](../../commands/keys/index.md) section. After executing the __`dev-env`__ script, this is how the folder should look like: @@ -195,9 +166,6 @@ $HOME/.hermes/ #### Next Steps -We now offer two options with regard to connecting the two chains: - -1. you can use [individual (raw) transactions](./tutorial_raw.html) to create - all the necessary chain objects (clients, connections, channels), or -2. you can perform this step using a - [simplified approach](./tutorial_relay_paths.html). \ No newline at end of file +[The next section](./identifiers.md) describes how identifers for clients, connections and channels +are allocated, and will walk you through how to pre-allocate some identifers +to help matching them with their corresponding chains for the purpose of this tutorial. diff --git a/guide/src/tx_packet.md b/guide/src/tx_packet.md deleted file mode 100644 index 3e08b99a48..0000000000 --- a/guide/src/tx_packet.md +++ /dev/null @@ -1,256 +0,0 @@ -# Packet Tx Commands - -## Table of Contents - - - -## Fungible token transfer - -Use the `tx raw ft-transfer` command to send ICS-20 fungible token transfer packets. -__NOTE:__ This command is mainly used for testing the packet features of the relayer. - -```shell -USAGE: - hermes tx raw ft-transfer - -DESCRIPTION: - Send a fungible token transfer test transaction (ICS20 MsgTransfer) - -POSITIONAL ARGUMENTS: - src_chain_id identifier of the source chain - dest_chain_id identifier of the destination chain - src_port_id identifier of the source port - src_channel_id identifier of the source channel - amount amount of coins (samoleans, by default) to send (e.g. `100000`) - height_offset timeout in number of blocks since current - -FLAGS: - -d, --denom DENOM denomination of the coins to send - -n, --number-msgs NUMBER-MSGS -``` - -__Example__ - -Send two transfer packets from the `transfer` module and `channel-0` of `ibc-0` to `ibc-1`. Each transfer if for `9999` samoleans (default denomination) and a timeout offset of `10` blocks. The transfer fee is paid by the relayer account on `ibc-1`. - -```shell -hermes tx raw ft-transfer ibc-0 ibc-1 transfer channel-0 9999 10 -n 2 | jq -``` - -```json -{ - "status": "success", - "result": [ - { - "SendPacketChannel": { - "height": "1", - "packet": { - "data": "7B22616...", - "destination_channel": "channel-1", - "destination_port": "transfer", - "sequence": 7, - "source_channel": "channel-0", - "source_port": "transfer", - "timeout_height": { - "revision_height": 25041, - "revision_number": 1 - }, - "timeout_timestamp": 0 - } - } - }, - { - "SendPacketChannel": { - "height": "1", - "packet": { - "data": "7B22616...", - "destination_channel": "channel-1", - "destination_port": "transfer", - "sequence": 8, - "source_channel": "channel-0", - "source_port": "transfer", - "timeout_height": { - "revision_height": 25041, - "revision_number": 1 - }, - "timeout_timestamp": 0 - } - } - } - ] -} -``` - -The transfer packets are stored on `ibc-0` and can be relayed. - -## Relay receive and timeout packets - -Use the `tx raw packet-recv` command to relay the packets sent but not yet received. If the sent packets have timed out then a timeout packet is sent to the source chain. - -```shell -USAGE: - hermes tx raw packet-recv - -DESCRIPTION: - Relay receive or timeout packets - -POSITIONAL ARGUMENTS: - dst_chain_id identifier of the destination chain - src_chain_id identifier of the source chain - src_port_id identifier of the source port - src_channel_id identifier of the source channel -``` - -__Example__ - -Send the two transfer packets to the `ibc-1` module bound to the `transfer` port and the `channel-0`'s counterparty. - -__NOTE__: The relayer prepends a client update message before the receive messages. - -```shell -hermes tx raw packet-recv ibc-1 ibc-0 transfer channel-0 | jq -``` - -```json -{ - "status": "success", - "result": [ - { - "UpdateClient": { - "client_id": "07-tendermint-1", - "client_type": "Tendermint", - "consensus_height": { - "revision_height": 25049, - "revision_number": 0 - }, - "height": "1" - } - }, - { - "WriteAcknowledgementChannel": { - "ack": "7B22726573756C74223A2241513D3D227D", - "height": "1", - "packet": { - "data": "7B22616...", - "destination_channel": "channel-1", - "destination_port": "transfer", - "sequence": 7, - "source_channel": "channel-0", - "source_port": "transfer", - "timeout_height": { - "revision_height": 25041, - "revision_number": 1 - }, - "timeout_timestamp": 0 - } - } - }, - { - "WriteAcknowledgementChannel": { - "ack": "7B22726573756C74223A2241513D3D227D", - "height": "1", - "packet": { - "data": "7B22616...", - "destination_channel": "channel-1", - "destination_port": "transfer", - "sequence": 8, - "source_channel": "channel-0", - "source_port": "transfer", - "timeout_height": { - "revision_height": 25041, - "revision_number": 1 - }, - "timeout_timestamp": 0 - } - } - } - ] -} -``` - -Both packets have been relayed to `ibc-1` and acknowledged. - -## Relay acknowledgment packets - -Use the `tx raw packet-ack` command to relay acknowledgments to the original source of the packets. - -```shell -USAGE: - hermes tx raw packet-recv - -DESCRIPTION: - Relay receive or timeout packets - -POSITIONAL ARGUMENTS: - dst_chain_id identifier of the destination chain - src_chain_id identifier of the source chain - src_port_id identifier of the source port - src_channel_id identifier of the source channel -``` - -__Example__ - -Send the acknowledgments to the `ibc-0` module bound to the `transfer` port and the `channel-1`'s counterparty. - -__NOTE__: The relayer prepends a client update message before the acknowledgments. - -```shell -hermes tx raw packet-ack ibc-0 ibc-1 transfer channel-1 | jq -``` - -```json -{ - "status": "success", - "result": [ - { - "UpdateClient": { - "client_id": "07-tendermint-0", - "client_type": "Tendermint", - "consensus_height": { - "revision_height": 25673, - "revision_number": 1 - }, - "height": "1" - } - }, - { - "AcknowledgePacketChannel": { - "height": "1", - "packet": { - "data": "", - "destination_channel": "channel-1", - "destination_port": "transfer", - "sequence": 7, - "source_channel": "channel-0", - "source_port": "transfer", - "timeout_height": { - "revision_height": 25041, - "revision_number": 1 - }, - "timeout_timestamp": 0 - } - } - }, - { - "AcknowledgePacketChannel": { - "height": "1", - "packet": { - "data": "", - "destination_channel": "channel-1", - "destination_port": "transfer", - "sequence": 8, - "source_channel": "channel-0", - "source_port": "transfer", - "timeout_height": { - "revision_height": 25041, - "revision_number": 1 - }, - "timeout_timestamp": 0 - } - } - } - ] -} -``` - -Both acknowledgments have been received on `ibc-0`. diff --git a/guide/src/upgrade_test.md b/guide/src/upgrade_test.md deleted file mode 100644 index aaf06fbb50..0000000000 --- a/guide/src/upgrade_test.md +++ /dev/null @@ -1,166 +0,0 @@ -## Prerequisites - -- gaiad `(v4.1.*)`, for example: - -```shell -$ gaiad version --long | head -n4 -name: gaia -server_name: gaiad -version: 4.1.2 -commit: 95b07e641d1f69ee12dd911e92b1679f2c64d385 -``` - -## Testing procedure - -1. Start two gaia instances and initialize hermes: - - ```shell - $ ./scripts/dev-env ~/.hermes/config.toml ibc-0 ibc-1 - ``` - The `one-chain` script is invoked for each chain and modifies the `genesis.json` file to use a short window for governance proposals (`200s` for `max_deposit_period` and `voting_period`). Therefore, an upgrade proposal can be submitted, voted on and accepted within a short time. - -2. Create one client on `ibc-1` for `ibc-0`: - - ```shell - $ hermes tx raw create-client ibc-1 ibc-0 - ``` - -3. Create and submit an upgrade plan for chain `ibc-0`: - - Use the hermes test command to make an upgrade proposal. In the example below a software upgrade proposal is made for `ibc-0`, for the height `300` blocks from latest height. `10000000stake` is deposited. - The proposal includes the upgraded client state constructed from the state of `07-tendermint-0` client on `ibc-1` that was created in the previous step. In addition, the `unbonding_period` of the client is set to some new value (`400h`) - - ```shell - $ hermes tx raw upgrade-chain ibc-0 ibc-1 07-tendermint-0 10000000 300 - ``` - - Note that the height offset should be picked such that the proposal plan height is reached after the `200s` voting period. - - 4. Verify that the proposal was accepted: - - Query the upgrade plan to check that it was submitted correctly. Note the `height` at which the proposal will take effect (chain halts). Also `status: PROPOSAL_STATUS_VOTING_PERIOD`. - - ```shell - $ gaiad query gov proposal 1 --home data/ibc-0/ - - content: - '@type': /cosmos.upgrade.v1beta1.SoftwareUpgradeProposal - description: upgrade the chain software and unbonding period - plan: - height: "382" - info: upgrade the chain software and unbonding period - name: test - time: "0001-01-01T00:00:00Z" - upgraded_client_state: - '@type': /ibc.lightclients.tendermint.v1.ClientState - allow_update_after_expiry: false - allow_update_after_misbehaviour: false - chain_id: ibc-0 - frozen_height: - revision_height: "0" - revision_number: "0" - latest_height: - revision_height: "383" - revision_number: "0" - max_clock_drift: 0s - proof_specs: - ... - trust_level: - denominator: "0" - numerator: "0" - trusting_period: 0s - unbonding_period: 1440000s - upgrade_path: - - upgrade - - upgradedIBCState - title: upgrade_ibc_clients - deposit_end_time: "2021-03-23T17:25:42.543572Z" - final_tally_result: - abstain: "0" - "no": "0" - no_with_veto: "0" - "yes": "0" - proposal_id: "1" - status: PROPOSAL_STATUS_VOTING_PERIOD - submit_time: "2021-03-23T17:22:22.543572Z" - total_deposit: - - amount: "10000000" - denom: stake - voting_end_time: "2021-03-23T17:25:42.543572Z" - voting_start_time: "2021-03-23T17:22:22.543572Z" - ``` - - 5. Vote on the proposal - - The parameter `1` should match the `proposal_id:` from the upgrade proposal submitted at step 3. This command must be issued while the proposal status is `PROPOSAL_STATUS_VOTING_PERIOD`. - - ```shell - gaiad tx gov vote 1 yes --home data/ibc-0/data/ --keyring-backend test --keyring-dir data/ibc-0/ --chain-id ibc-0 --from validator - ``` - - Wait approximately 200 seconds until the proposal changes status to `PROPOSAL_STATUS_PASSED`. Note the `final tally_result` that includes the vote submitted in previous step. - - ```shell - $ gaiad query gov proposal 1 --home data/ibc-0/ - - content: - '@type': /cosmos.upgrade.v1beta1.SoftwareUpgradeProposal - description: upgrade the chain software and unbonding period - plan: - ... - final_tally_result: - abstain: "0" - "no": "0" - no_with_veto: "0" - "yes": "100000000000" - proposal_id: "1" - status: PROPOSAL_STATUS_PASSED - submit_time: "2021-03-23T17:22:22.543572Z" - total_deposit: - - amount: "10000000" - denom: stake - voting_end_time: "2021-03-23T17:25:42.543572Z" - voting_start_time: "2021-03-23T17:22:22.543572Z" - ``` - -6. Test the `upgrade-client` CLI - - The following command performs the upgrade for client `07-tendermint-0`. It outputs two events, one for the updated client state, and another for the upgraded state. - - ```shell - $ hermes tx raw upgrade-client ibc-1 ibc-0 07-tendermint-0 - - { - "status": "success", - "result": [ - { - "UpdateClient": { - "client_id": "07-tendermint-0", - "client_type": "Tendermint", - "consensus_height": { - "revision_height": 332, - "revision_number": 0 - }, - "height": { - "revision_height": 404, - "revision_number": 1 - } - } - }, - { - "UpgradeClient": { - "client_id": "07-tendermint-0", - "client_type": "Tendermint", - "consensus_height": { - "revision_height": 333, - "revision_number": 0 - }, - "height": { - "revision_height": 404, - "revision_number": 1 - } - } - } - ] - } - ``` diff --git a/modules/README.md b/modules/README.md index 2d5251b182..bb33b19c07 100644 --- a/modules/README.md +++ b/modules/README.md @@ -1,16 +1,33 @@ +# IBC module + [![Crate][crate-image]][crate-link] [![Docs][docs-image]][docs-link] +[![Build Status][build-image]][build-link] +[![End to End testing][e2e-image]][e2e-link] +[![Apache 2.0 Licensed][license-image]][license-link] +![Rust Stable][rustc-image] +![Rust 1.49+][rustc-version] + -See the [ibc-rs] repo root for more detailed information on this crate can be used. +See the [ibc-rs] repo root for more detailed information on how this crate can be used. -# ibc -Implementation of the Inter-Blockchain Communication Protocol ([IBC]). +Implementation of the Inter-Blockchain Communication Protocol ([IBC]) module. ## Documentation See documentation on [docs.rs][docs-link]. +## License + +Copyright © 2021 Informal Systems Inc. and ibc-rs authors. + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use the files in this repository except in compliance with the License. You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + [//]: # (badges) [crate-image]: https://img.shields.io/crates/v/ibc.svg @@ -18,7 +35,17 @@ See documentation on [docs.rs][docs-link]. [docs-image]: https://docs.rs/ibc/badge.svg [docs-link]: https://docs.rs/ibc/ +[build-image]: https://github.com/informalsystems/ibc-rs/workflows/Rust/badge.svg +[build-link]: https://github.com/informalsystems/ibc-rs/actions?query=workflow%3ARust +[e2e-image]: https://github.com/informalsystems/ibc-rs/workflows/End%20to%20End%20testing/badge.svg +[e2e-link]: https://github.com/informalsystems/ibc-rs/actions?query=workflow%3A%22End+to+End+testing%22 + +[license-image]: https://img.shields.io/badge/license-Apache2.0-blue.svg +[license-link]: https://github.com/informalsystems/ibc-rs/blob/master/LICENSE +[rustc-image]: https://img.shields.io/badge/rustc-stable-blue.svg +[rustc-version]: https://img.shields.io/badge/rustc-1.49+-blue.svg + [//]: # (general links) [ibc-rs]: https://github.com/informalsystems/ibc-rs -[IBC]: https://github.com/cosmos/ics +[IBC]: https://github.com/cosmos/ibc diff --git a/modules/src/ics02_client/height.rs b/modules/src/ics02_client/height.rs index dee2bd477c..e2b2af2fc7 100644 --- a/modules/src/ics02_client/height.rs +++ b/modules/src/ics02_client/height.rs @@ -125,11 +125,10 @@ impl From for RawHeight { impl std::fmt::Debug for Height { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { - write!( - f, - "revision: {}, height: {}", - self.revision_number, self.revision_height - ) + f.debug_struct("Height") + .field("revision", &self.revision_number) + .field("height", &self.revision_height) + .finish() } } diff --git a/modules/src/ics04_channel/channel.rs b/modules/src/ics04_channel/channel.rs index 5adae9651d..6b51f4d8ec 100644 --- a/modules/src/ics04_channel/channel.rs +++ b/modules/src/ics04_channel/channel.rs @@ -1,4 +1,5 @@ use std::convert::{TryFrom, TryInto}; +use std::fmt; use std::str::FromStr; use anomaly::fail; @@ -262,9 +263,15 @@ impl Default for Order { } } +impl fmt::Display for Order { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.as_str()) + } +} + impl Order { /// Yields the Order as a string - pub fn as_string(&self) -> &'static str { + pub fn as_str(&self) -> &'static str { match self { Self::None => "UNINITIALIZED", Self::Unordered => "ORDER_UNORDERED", diff --git a/modules/src/ics04_channel/handler/chan_open_init.rs b/modules/src/ics04_channel/handler/chan_open_init.rs index 3320226516..3d2e815a1e 100644 --- a/modules/src/ics04_channel/handler/chan_open_init.rs +++ b/modules/src/ics04_channel/handler/chan_open_init.rs @@ -37,7 +37,7 @@ pub(crate) fn process( _ => return Err(Kind::InvalidVersionLengthConnection.into()), }; - let channel_feature = msg.channel().ordering().as_string().to_string(); + let channel_feature = msg.channel().ordering().to_string(); if !version.is_supported_feature(channel_feature) { return Err(Kind::ChannelFeatureNotSuportedByConnection.into()); } diff --git a/modules/src/ics04_channel/handler/chan_open_try.rs b/modules/src/ics04_channel/handler/chan_open_try.rs index f9f123061d..1d91f10f18 100644 --- a/modules/src/ics04_channel/handler/chan_open_try.rs +++ b/modules/src/ics04_channel/handler/chan_open_try.rs @@ -94,7 +94,7 @@ pub(crate) fn process( _ => return Err(Kind::InvalidVersionLengthConnection.into()), }; - let channel_feature = msg.channel().ordering().as_string().to_string(); + let channel_feature = msg.channel().ordering().to_string(); if !version.is_supported_feature(channel_feature) { return Err(Kind::ChannelFeatureNotSuportedByConnection.into()); } diff --git a/modules/src/ics23_commitment/commitment.rs b/modules/src/ics23_commitment/commitment.rs index bee6f3d75f..d0658ab232 100644 --- a/modules/src/ics23_commitment/commitment.rs +++ b/modules/src/ics23_commitment/commitment.rs @@ -2,18 +2,26 @@ use std::convert::TryFrom; use std::fmt; use serde::{Deserialize, Serialize}; +use subtle_encoding::{Encoding, Hex}; use ibc_proto::ibc::core::commitment::v1::MerkleProof as RawMerkleProof; use crate::ics23_commitment::error::{Error, Kind}; -#[derive(Clone, Debug, PartialEq, Eq, Serialize)] +#[derive(Clone, PartialEq, Eq, Serialize)] #[serde(transparent)] pub struct CommitmentRoot { #[serde(serialize_with = "crate::serializers::ser_hex_upper")] bytes: Vec, } +impl fmt::Debug for CommitmentRoot { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let hex = Hex::upper_case().encode_to_string(&self.bytes).unwrap(); + f.debug_tuple("CommitmentRoot").field(&hex).finish() + } +} + impl CommitmentRoot { pub fn from_bytes(bytes: &[u8]) -> Self { Self { diff --git a/proto/Cargo.toml b/proto/Cargo.toml index 6563477de2..87fa8d8d2b 100644 --- a/proto/Cargo.toml +++ b/proto/Cargo.toml @@ -11,7 +11,7 @@ keywords = ["blockchain", "cosmos", "tendermint", "ibc", "proto"] exclude = ["definitions"] description = """ - ibc-proto is a the Rust implementation of the Cosmos SDK proto structs. + ibc-proto is a Rust implementation of the Cosmos SDK & IBC proto structs. """ [lib] diff --git a/proto/README.md b/proto/README.md index 1c82fd23a4..1078f44fad 100644 --- a/proto/README.md +++ b/proto/README.md @@ -1,11 +1,12 @@ -## ibc-proto +# ibc-proto [![Crate][crate-image]][crate-link] [![Docs][docs-image]][docs-link] [![Build Status][build-image]][build-link] -[![Audit Status][audit-image]][audit-link] +[![End to End testing][e2e-image]][e2e-link] [![Apache 2.0 Licensed][license-image]][license-link] -![Rust 1.39+][rustc-image] +![Rust Stable][rustc-image] +![Rust 1.49+][rustc-version] Rust crate for interacting with Cosmos SDK [IBC structs](https://github.com/cosmos/cosmos-sdk/tree/master/proto/ibc). @@ -14,13 +15,13 @@ Rust crate for interacting with Cosmos SDK ## Requirements -- Rust 1.39+ -- make, curl +- Rust 1.49+ +- `make`, `curl` - Cosmos SDK (downloaded automatically if you are using `make`) ## License -Copyright © 2020 Informal Systems +Copyright © 2021 Informal Systems Licensed under the Apache License, Version 2.0 (the "License"); you may not use the files in this repository except in compliance with the License. @@ -40,13 +41,16 @@ limitations under the License. [crate-link]: https://crates.io/crates/ibc-proto [docs-image]: https://docs.rs/ibc-proto/badge.svg [docs-link]: https://docs.rs/ibc-proto/ + [build-image]: https://github.com/informalsystems/ibc-rs/workflows/Rust/badge.svg [build-link]: https://github.com/informalsystems/ibc-rs/actions?query=workflow%3ARust -[audit-image]: https://github.com/informalsystems/ibc-rs/workflows/Audit-Check/badge.svg -[audit-link]: https://github.com/informalsystems/ibc-rs/actions?query=workflow%3AAudit-Check +[e2e-image]: https://github.com/informalsystems/ibc-rs/workflows/End%20to%20End%20testing/badge.svg +[e2e-link]: https://github.com/informalsystems/ibc-rs/actions?query=workflow%3A%22End+to+End+testing%22 + [license-image]: https://img.shields.io/badge/license-Apache2.0-blue.svg [license-link]: https://github.com/informalsystems/ibc-rs/blob/master/LICENSE -[rustc-image]: https://img.shields.io/badge/rustc-1.39+-blue.svg +[rustc-image]: https://img.shields.io/badge/rustc-stable-blue.svg +[rustc-version]: https://img.shields.io/badge/rustc-1.49+-blue.svg [//]: # (general links) diff --git a/relayer-cli/README.md b/relayer-cli/README.md index 172c8f043d..974086a314 100644 --- a/relayer-cli/README.md +++ b/relayer-cli/README.md @@ -1,7 +1,43 @@ # Hermes: IBC Relayer CLI +[![Crate][crate-image]][crate-link] +[![Docs][docs-image]][docs-link] +[![Build Status][build-image]][build-link] +[![End to End testing][e2e-image]][e2e-link] +[![Apache 2.0 Licensed][license-image]][license-link] +![Rust Stable][rustc-image] +![Rust 1.49+][rustc-version] + This is the repository for the CLI of the IBC Relayer built in Rust, called `hermes`. For any information about the relayer binary, please read the comprehensive guide available at [hermes.informal.systems](https://hermes.informal.systems). + + +## License + +Copyright © 2021 Informal Systems Inc. and ibc-rs authors. + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use the files in this repository except in compliance with the License. You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + +[//]: # (badges) + +[crate-image]: https://img.shields.io/crates/v/ibc-relayer-cli.svg +[crate-link]: https://crates.io/crates/ibc-relayer-cli +[docs-image]: https://docs.rs/ibc-relayer-cli/badge.svg +[docs-link]: https://docs.rs/ibc-relayer-cli/ + +[build-image]: https://github.com/informalsystems/ibc-rs/workflows/Rust/badge.svg +[build-link]: https://github.com/informalsystems/ibc-rs/actions?query=workflow%3ARust +[e2e-image]: https://github.com/informalsystems/ibc-rs/workflows/End%20to%20End%20testing/badge.svg +[e2e-link]: https://github.com/informalsystems/ibc-rs/actions?query=workflow%3A%22End+to+End+testing%22 + +[license-image]: https://img.shields.io/badge/license-Apache2.0-blue.svg +[license-link]: https://github.com/informalsystems/ibc-rs/blob/master/LICENSE +[rustc-image]: https://img.shields.io/badge/rustc-stable-blue.svg +[rustc-version]: https://img.shields.io/badge/rustc-1.49+-blue.svg \ No newline at end of file diff --git a/relayer-cli/src/commands.rs b/relayer-cli/src/commands.rs index b48d3f84b8..0636b2fb11 100644 --- a/relayer-cli/src/commands.rs +++ b/relayer-cli/src/commands.rs @@ -11,10 +11,12 @@ use abscissa_core::{Command, Configurable, FrameworkError, Help, Options, Runnab use tracing::info; use crate::config::Config; +use crate::DEFAULT_CONFIG_PATH; use self::{ create::CreateCmds, keys::KeysCmd, listen::ListenCmd, query::QueryCmd, start::StartCmd, - start_multi::StartMultiCmd, tx::TxCmd, update::UpdateCmds, version::VersionCmd, + start_multi::StartMultiCmd, tx::TxCmd, update::UpdateCmds, upgrade::UpgradeCmds, + version::VersionCmd, }; use crate::commands::misbehaviour::MisbehaviourCmd; @@ -28,12 +30,13 @@ mod start; mod start_multi; mod tx; mod update; +mod upgrade; mod version; /// Default configuration file path pub fn default_config_file() -> Option { info!("Using default configuration from: '.hermes/config.toml'"); - dirs_next::home_dir().map(|home| home.join(".hermes/config.toml")) + dirs_next::home_dir().map(|home| home.join(DEFAULT_CONFIG_PATH)) } // TODO: Re-add the `config` subcommand @@ -62,6 +65,12 @@ pub enum CliCmd { )] Update(UpdateCmds), + /// The `upgrade` subcommand + #[options( + help = "Upgrade objects after chain upgrade. Currently this sub-commands serves only to upgrade clients" + )] + Upgrade(UpgradeCmds), + /// The `start` subcommand #[options(help = "Start the relayer")] Start(StartCmd), diff --git a/relayer-cli/src/commands/create/channel.rs b/relayer-cli/src/commands/create/channel.rs index df69aabb41..fc5df65204 100644 --- a/relayer-cli/src/commands/create/channel.rs +++ b/relayer-cli/src/commands/create/channel.rs @@ -48,11 +48,11 @@ pub struct CreateChannelCommand { )] port_b: PortId, - #[options(help = "the channel ordering, valid options 'unordered' and 'ordered'")] + #[options(help = "the channel ordering, valid options 'unordered' (default) and 'ordered'")] order: Order, #[options(help = "the version for the new channel")] - version: String, + version: Option, } impl Runnable for CreateChannelCommand { @@ -80,9 +80,11 @@ impl CreateChannelCommand { let chains = ChainHandlePair::spawn(&config, &self.chain_a_id, chain_b_id) .unwrap_or_else(exit_with_unrecoverable_error); + // let version = self.chain_a_id.version(); + info!( - "Creating new clients, new connection, and a new channel with order {:?} and version {}", - self.order, self.version + "Creating new clients, new connection, and a new channel with order {}", + self.order ); let client_a = ForeignClient::new(chains.src.clone(), chains.dst.clone()) @@ -95,8 +97,14 @@ impl CreateChannelCommand { .unwrap_or_else(exit_with_unrecoverable_error); // Finally create the channel. - let channel = Channel::new(con, self.order, self.port_a.clone(), self.port_b.clone()) - .unwrap_or_else(exit_with_unrecoverable_error); + let channel = Channel::new( + con, + self.order, + self.port_a.clone(), + self.port_b.clone(), + self.version.clone(), + ) + .unwrap_or_else(exit_with_unrecoverable_error); Output::success(channel).exit(); } @@ -152,6 +160,7 @@ impl CreateChannelCommand { self.order, self.port_a.clone(), self.port_b.clone(), + self.version.clone(), ) .unwrap_or_else(exit_with_unrecoverable_error); diff --git a/relayer-cli/src/commands/create/connection.rs b/relayer-cli/src/commands/create/connection.rs index af767466e8..5e7b596f00 100644 --- a/relayer-cli/src/commands/create/connection.rs +++ b/relayer-cli/src/commands/create/connection.rs @@ -37,10 +37,11 @@ pub struct CreateConnectionCommand { client_b: Option, #[options( - help = "delay period parameter for the new connection (seconds); default: `0`", + help = "delay period parameter for the new connection (seconds)", + default = "0", no_short )] - delay: Option, + delay: u64, } // cargo run --bin hermes -- create connection ibc-0 ibc-1 @@ -88,9 +89,9 @@ impl CreateConnectionCommand { .unwrap_or_else(exit_with_unrecoverable_error); // Finally, execute the connection handshake. - let delay = Duration::from_secs(self.delay.unwrap_or_default()); + let delay = Duration::from_secs(self.delay); match Connection::new(client_a, client_b, delay) { - Ok(con) => Output::success(format!("{:?}", con)).exit(), + Ok(conn) => Output::success(conn).exit(), Err(e) => Output::error(format!("{}", e)).exit(), } } @@ -158,9 +159,9 @@ impl CreateConnectionCommand { .unwrap_or_else(exit_with_unrecoverable_error); // All verification passed. Create the Connection object & do the handshake. - let delay = Duration::from_secs(self.delay.unwrap_or_default()); + let delay = Duration::from_secs(self.delay); match Connection::new(client_a, client_b, delay) { - Ok(con) => Output::success(format!("{:?}", con)).exit(), + Ok(conn) => Output::success(conn).exit(), Err(e) => Output::error(format!("{}", e)).exit(), } } diff --git a/relayer-cli/src/commands/keys/add.rs b/relayer-cli/src/commands/keys/add.rs index a68da47795..8de82c58af 100644 --- a/relayer-cli/src/commands/keys/add.rs +++ b/relayer-cli/src/commands/keys/add.rs @@ -69,7 +69,7 @@ impl Runnable for KeysAddCmd { } pub fn add_key(config: ChainConfig, file: &Path) -> Result { - let mut keyring = KeyRing::new(Store::Disk, config)?; + let mut keyring = KeyRing::new(Store::Test, config)?; let key_contents = fs::read_to_string(file).map_err(|_| "error reading the key file")?; let key = keyring.key_from_seed_file(&key_contents)?; diff --git a/relayer-cli/src/commands/keys/list.rs b/relayer-cli/src/commands/keys/list.rs index e4f624cb09..53d997f85f 100644 --- a/relayer-cli/src/commands/keys/list.rs +++ b/relayer-cli/src/commands/keys/list.rs @@ -57,7 +57,7 @@ pub struct KeysListOptions { } pub fn list_keys(config: ChainConfig) -> Result { - let keyring = KeyRing::new(Store::Disk, config)?; + let keyring = KeyRing::new(Store::Test, config)?; let key_entry = keyring.get_key()?; Ok(key_entry) } diff --git a/relayer-cli/src/commands/keys/restore.rs b/relayer-cli/src/commands/keys/restore.rs index 5ee02e9071..ef05629983 100644 --- a/relayer-cli/src/commands/keys/restore.rs +++ b/relayer-cli/src/commands/keys/restore.rs @@ -63,7 +63,7 @@ impl Runnable for KeyRestoreCmd { } pub fn restore_key(mnemonic: &str, config: ChainConfig) -> Result { - let mut keyring = KeyRing::new(Store::Disk, config)?; + let mut keyring = KeyRing::new(Store::Test, config)?; let key_entry = keyring.key_from_mnemonic(mnemonic)?; keyring.add_key(key_entry.clone())?; diff --git a/relayer-cli/src/commands/listen.rs b/relayer-cli/src/commands/listen.rs index 96400f0e8b..d7aa193d47 100644 --- a/relayer-cli/src/commands/listen.rs +++ b/relayer-cli/src/commands/listen.rs @@ -63,7 +63,7 @@ pub fn listen(config: &ChainConfig, events: &[EventType]) -> Result<(), BoxError thread::spawn(|| event_monitor.run()); while let Ok(event_batch) = rx.recv() { - dbg!(event_batch); + println!("{:#?}", event_batch); } Ok(()) diff --git a/relayer-cli/src/commands/misbehaviour.rs b/relayer-cli/src/commands/misbehaviour.rs index f31d79102e..49f6e659cf 100644 --- a/relayer-cli/src/commands/misbehaviour.rs +++ b/relayer-cli/src/commands/misbehaviour.rs @@ -35,7 +35,7 @@ impl Runnable for MisbehaviourCmd { let res = monitor_misbehaviour(&self.chain_id, &self.client_id, &config); match res { - Ok(()) => Output::success(()).exit(), + Ok(some_event) => Output::success(some_event).exit(), Err(e) => Output::error(format!("{}", e)).exit(), } } @@ -45,9 +45,9 @@ pub fn monitor_misbehaviour( chain_id: &ChainId, client_id: &ClientId, config: &config::Reader, -) -> Result<(), BoxError> { +) -> Result, BoxError> { let chain = spawn_chain_runtime(&config, chain_id) - .map_err(|e| format!("could not spawn the chain runtime for {}", chain_id))?; + .map_err(|e| format!("could not spawn the chain runtime for {}: {}", chain_id, e))?; let subscription = chain.subscribe()?; @@ -68,12 +68,13 @@ pub fn monitor_misbehaviour( )?; } - IbcEvent::CreateClient(create) => { + IbcEvent::CreateClient(_create) => { // TODO - get header from full node, consensus state from chain, compare } - IbcEvent::ClientMisbehaviour(misbehaviour) => { + IbcEvent::ClientMisbehaviour(_misbehaviour) => { // TODO - submit misbehaviour to the witnesses (our full node) + return Ok(Some(event.clone())); } _ => {} @@ -81,7 +82,7 @@ pub fn monitor_misbehaviour( } } - Ok(()) + Ok(None) } fn misbehaviour_handling( @@ -92,17 +93,18 @@ fn misbehaviour_handling( ) -> Result<(), BoxError> { let client_state = chain .query_client_state(client_id, Height::zero()) - .map_err(|e| format!("could not query client state for {}", client_id))?; + .map_err(|e| format!("could not query client state for {}: {}", client_id, e))?; if client_state.is_frozen() { - // nothing to do - return Ok(()); + return Err(format!("client {} is already frozen", client_id).into()); } + let counterparty_chain = spawn_chain_runtime(&config, &client_state.chain_id()).map_err(|e| { format!( - "could not spawn the chain runtime for {}", - client_state.chain_id() + "could not spawn the chain runtime for {}: {}", + client_state.chain_id(), + e ) })?; diff --git a/relayer-cli/src/commands/query.rs b/relayer-cli/src/commands/query.rs index 8df32359ea..f32c01b654 100644 --- a/relayer-cli/src/commands/query.rs +++ b/relayer-cli/src/commands/query.rs @@ -46,19 +46,19 @@ pub enum QueryCmd { #[derive(Command, Debug, Options, Runnable)] pub enum QueryClientCmds { /// The `query client state` subcommand - #[options(help = "Query client full state")] + #[options(help = "Query the client full state")] State(client::QueryClientStateCmd), /// The `query client consensus` subcommand - #[options(help = "Query client consensus state")] + #[options(help = "Query the client consensus state")] Consensus(client::QueryClientConsensusCmd), /// The `query client header` subcommand - #[options(help = "Query client header")] + #[options(help = "Query for the header used in a client update at a certain height")] Header(client::QueryClientHeaderCmd), /// The `query client connections` subcommand - #[options(help = "Query client connections")] + #[options(help = "Query the client connections")] Connections(client::QueryClientConnectionsCmd), } diff --git a/relayer-cli/src/commands/query/channel.rs b/relayer-cli/src/commands/query/channel.rs index e548ec7f9f..cf6a667207 100644 --- a/relayer-cli/src/commands/query/channel.rs +++ b/relayer-cli/src/commands/query/channel.rs @@ -40,7 +40,7 @@ impl Runnable for QueryChannelEndCmd { Some(chain_config) => chain_config, }; - info!("Options {:?}", self); + debug!("Options: {:?}", self); let rt = Arc::new(TokioRuntime::new().unwrap()); let chain = CosmosSdkChain::bootstrap(chain_config.clone(), rt).unwrap(); diff --git a/relayer-cli/src/commands/query/channels.rs b/relayer-cli/src/commands/query/channels.rs index ec407022d2..222d61dcf7 100644 --- a/relayer-cli/src/commands/query/channels.rs +++ b/relayer-cli/src/commands/query/channels.rs @@ -32,7 +32,7 @@ impl Runnable for QueryChannelsCmd { Some(chain_config) => chain_config, }; - info!("Options {:?}", self); + debug!("Options: {:?}", self); let rt = Arc::new(TokioRuntime::new().unwrap()); let chain = CosmosSdkChain::bootstrap(chain_config.clone(), rt).unwrap(); diff --git a/relayer-cli/src/commands/query/client.rs b/relayer-cli/src/commands/query/client.rs index 4344390b26..6bb8e333b6 100644 --- a/relayer-cli/src/commands/query/client.rs +++ b/relayer-cli/src/commands/query/client.rs @@ -2,7 +2,6 @@ use std::sync::Arc; use abscissa_core::{Command, Options, Runnable}; use tokio::runtime::Runtime as TokioRuntime; -use tracing::info; use ibc::events::IbcEventType; use ibc::ics02_client::client_consensus::QueryClientEventRequest; @@ -99,7 +98,7 @@ impl Runnable for QueryClientConsensusCmd { Some(chain_config) => chain_config, }; - info!("Options {:?}", self); + debug!("Options: {:?}", self); let rt = Arc::new(TokioRuntime::new().unwrap()); let chain = CosmosSdkChain::bootstrap(chain_config.clone(), rt).unwrap(); @@ -147,7 +146,6 @@ impl Runnable for QueryClientConsensusCmd { } } -/// Query client header command #[derive(Clone, Command, Debug, Options)] pub struct QueryClientHeaderCmd { #[options(free, required, help = "identifier of the chain to query")] @@ -180,7 +178,7 @@ impl Runnable for QueryClientHeaderCmd { Some(chain_config) => chain_config, }; - info!("Options {:?}", self); + debug!("Options: {:?}", self); let rt = Arc::new(TokioRuntime::new().unwrap()); let chain = CosmosSdkChain::bootstrap(chain_config.clone(), rt).unwrap(); @@ -243,7 +241,7 @@ impl Runnable for QueryClientConnectionsCmd { Some(chain_config) => chain_config, }; - info!("Options {:?}", self); + debug!("Options: {:?}", self); let rt = Arc::new(TokioRuntime::new().unwrap()); let chain = CosmosSdkChain::bootstrap(chain_config.clone(), rt).unwrap(); diff --git a/relayer-cli/src/commands/query/clients.rs b/relayer-cli/src/commands/query/clients.rs index 39aaf949d9..8e37b4d964 100644 --- a/relayer-cli/src/commands/query/clients.rs +++ b/relayer-cli/src/commands/query/clients.rs @@ -35,7 +35,7 @@ impl Runnable for QueryAllClientsCmd { Some(chain_config) => chain_config, }; - info!("Options {:?}", self); + debug!("Options: {:?}", self); let rt = Arc::new(TokioRuntime::new().unwrap()); let chain = CosmosSdkChain::bootstrap(chain_config.clone(), rt).unwrap(); diff --git a/relayer-cli/src/commands/query/connection.rs b/relayer-cli/src/commands/query/connection.rs index 74905e4975..8956d7a59b 100644 --- a/relayer-cli/src/commands/query/connection.rs +++ b/relayer-cli/src/commands/query/connection.rs @@ -41,7 +41,7 @@ impl Runnable for QueryConnectionEndCmd { Some(chain_config) => chain_config, }; - info!("Options {:?}", self); + debug!("Options: {:?}", self); let rt = Arc::new(TokioRuntime::new().unwrap()); let chain = CosmosSdkChain::bootstrap(chain_config.clone(), rt).unwrap(); @@ -86,7 +86,7 @@ impl Runnable for QueryConnectionChannelsCmd { Some(chain_config) => chain_config, }; - info!("Options {:?}", self); + debug!("Options: {:?}", self); let rt = Arc::new(TokioRuntime::new().unwrap()); let chain = CosmosSdkChain::bootstrap(chain_config.clone(), rt).unwrap(); diff --git a/relayer-cli/src/commands/query/connections.rs b/relayer-cli/src/commands/query/connections.rs index e9a8e71e8a..d31a149342 100644 --- a/relayer-cli/src/commands/query/connections.rs +++ b/relayer-cli/src/commands/query/connections.rs @@ -32,7 +32,8 @@ impl Runnable for QueryConnectionsCmd { Some(chain_config) => chain_config, }; - info!("Options {:?}", self); + debug!("Options: {:?}", self); + let rt = Arc::new(TokioRuntime::new().unwrap()); let chain = CosmosSdkChain::bootstrap(chain_config.clone(), rt).unwrap(); diff --git a/relayer-cli/src/commands/query/packet.rs b/relayer-cli/src/commands/query/packet.rs index 2342e1d538..0d63b83bb4 100644 --- a/relayer-cli/src/commands/query/packet.rs +++ b/relayer-cli/src/commands/query/packet.rs @@ -1,10 +1,9 @@ use std::sync::Arc; use abscissa_core::{Command, Options, Runnable}; -use serde_json::json; +use serde::Serialize; use subtle_encoding::{Encoding, Hex}; use tokio::runtime::Runtime as TokioRuntime; -use tracing::info; use ibc::ics04_channel::packet::{PacketMsgType, Sequence}; use ibc::ics24_host::identifier::{ChainId, ChannelId, PortId}; @@ -20,6 +19,12 @@ use crate::conclude::Output; use crate::error::{Error, Kind}; use crate::prelude::*; +#[derive(Serialize, Debug)] +struct PacketSeqs { + height: Height, + seqs: Vec, +} + #[derive(Clone, Command, Debug, Options)] pub struct QueryPacketCommitmentsCmd { #[options(free, required, help = "identifier of the chain to query")] @@ -60,7 +65,8 @@ impl Runnable for QueryPacketCommitmentsCmd { Err(err) => return Output::error(err).exit(), Ok(result) => result, }; - info!("Options {:?}", opts); + + debug!("Options: {:?}", opts); let rt = Arc::new(TokioRuntime::new().unwrap()); let chain = CosmosSdkChain::bootstrap(chain_config, rt).unwrap(); @@ -79,11 +85,7 @@ impl Runnable for QueryPacketCommitmentsCmd { Ok((packet_states, height)) => { // Transform the raw packet commitm. state into the list of sequence numbers let seqs: Vec = packet_states.iter().map(|ps| ps.sequence).collect(); - Output::success(json!({ - "seqs": seqs, - "height": height - })) - .exit(); + Output::success(PacketSeqs { height, seqs }).exit(); } Err(e) => Output::error(format!("{}", e)).exit(), } @@ -135,7 +137,8 @@ impl Runnable for QueryPacketCommitmentCmd { Err(err) => return Output::error(err).exit(), Ok(result) => result, }; - info!("Options {:?}", opts); + + debug!("Options: {:?}", opts); // cargo run --bin hermes -- query packet commitment ibc-0 transfer ibconexfer 3 --height 3 let rt = Arc::new(TokioRuntime::new().unwrap()); @@ -150,6 +153,7 @@ impl Runnable for QueryPacketCommitmentCmd { ); match res { + Ok((bytes, _proofs)) if bytes.is_empty() => Output::success_msg("None").exit(), Ok((bytes, _proofs)) => { let hex = Hex::upper_case().encode_to_string(bytes).unwrap(); Output::success(hex).exit() @@ -231,7 +235,8 @@ impl Runnable for QueryUnreceivedPacketsCmd { Err(err) => return Output::error(err).exit(), Ok(result) => result, }; - info!("Options {:?}", opts); + + debug!("Options: {:?}", opts); let rt = Arc::new(TokioRuntime::new().unwrap()); let src_chain = CosmosSdkChain::bootstrap(src_chain_config, rt.clone()).unwrap(); @@ -355,7 +360,8 @@ impl Runnable for QueryPacketAcknowledgementsCmd { Err(err) => return Output::error(err).exit(), Ok(result) => result, }; - info!("Options {:?}", opts); + + debug!("Options: {:?}", opts); let rt = Arc::new(TokioRuntime::new().unwrap()); let chain = CosmosSdkChain::bootstrap(chain_config, rt).unwrap(); @@ -374,11 +380,7 @@ impl Runnable for QueryPacketAcknowledgementsCmd { Ok((packet_state, height)) => { // Transform the raw packet state into the list of sequence numbers let seqs: Vec = packet_state.iter().map(|ps| ps.sequence).collect(); - Output::success(json!({ - "height": height, - "seqs": seqs - })) - .exit(); + Output::success(PacketSeqs { height, seqs }).exit(); } Err(e) => Output::error(format!("{}", e)).exit(), } @@ -430,7 +432,8 @@ impl Runnable for QueryPacketAcknowledgmentCmd { Err(err) => return Output::error(err).exit(), Ok(result) => result, }; - info!("Options {:?}", opts); + + debug!("Options: {:?}", opts); // cargo run --bin hermes -- query packet acknowledgment ibc-0 transfer ibconexfer --height 3 let rt = Arc::new(TokioRuntime::new().unwrap()); @@ -526,7 +529,8 @@ impl Runnable for QueryUnreceivedAcknowledgementCmd { Err(err) => return Output::error(err).exit(), Ok(result) => result, }; - info!("Options {:?}", opts); + + debug!("Options: {:?}", opts); let rt = Arc::new(TokioRuntime::new().unwrap()); let src_chain = CosmosSdkChain::bootstrap(src_chain_config, rt.clone()).unwrap(); diff --git a/relayer-cli/src/commands/tx/channel.rs b/relayer-cli/src/commands/tx/channel.rs index f874eb929a..7a3d60fe1d 100644 --- a/relayer-cli/src/commands/tx/channel.rs +++ b/relayer-cli/src/commands/tx/channel.rs @@ -61,11 +61,8 @@ pub struct TxRawChanOpenInitCmd { #[options(free, required, help = "identifier of the source port")] src_port_id: PortId, - #[options( - help = "the channel order: `UNORDERED` or `ORDERED`, default `UNORDERED`", - short = "o" - )] - ordering: Order, + #[options(help = "the channel ordering, valid options 'unordered' (default) and 'ordered'")] + order: Order, } impl Runnable for TxRawChanOpenInitCmd { @@ -77,7 +74,7 @@ impl Runnable for TxRawChanOpenInitCmd { |chains: ChainHandlePair, dst_connection: ConnectionEnd| { Channel { connection_delay: Default::default(), - ordering: self.ordering, + ordering: self.order, a_side: ChannelSide::new( chains.src, ClientId::default(), @@ -86,12 +83,13 @@ impl Runnable for TxRawChanOpenInitCmd { ChannelId::default(), ), b_side: ChannelSide::new( - chains.dst, + chains.dst.clone(), dst_connection.client_id().clone(), self.dst_conn_id.clone(), self.dst_port_id.clone(), ChannelId::default(), ), + version: None, } } ); @@ -142,12 +140,13 @@ impl Runnable for TxRawChanOpenTryCmd { self.src_chan_id.clone(), ), b_side: ChannelSide::new( - chains.dst, + chains.dst.clone(), dst_connection.client_id().clone(), self.dst_conn_id.clone(), self.dst_port_id.clone(), ChannelId::default(), ), + version: None, } } ); @@ -206,12 +205,13 @@ impl Runnable for TxRawChanOpenAckCmd { self.src_chan_id.clone(), ), b_side: ChannelSide::new( - chains.dst, + chains.dst.clone(), dst_connection.client_id().clone(), self.dst_conn_id.clone(), self.dst_port_id.clone(), self.dst_chan_id.clone(), ), + version: None, } } ); @@ -270,12 +270,13 @@ impl Runnable for TxRawChanOpenConfirmCmd { self.src_chan_id.clone(), ), b_side: ChannelSide::new( - chains.dst, + chains.dst.clone(), dst_connection.client_id().clone(), self.dst_conn_id.clone(), self.dst_port_id.clone(), self.dst_chan_id.clone(), ), + version: None, } } ); @@ -334,12 +335,13 @@ impl Runnable for TxRawChanCloseInitCmd { self.src_chan_id.clone(), ), b_side: ChannelSide::new( - chains.dst, + chains.dst.clone(), dst_connection.client_id().clone(), self.dst_conn_id.clone(), self.dst_port_id.clone(), self.dst_chan_id.clone(), ), + version: None, } } ); @@ -398,12 +400,13 @@ impl Runnable for TxRawChanCloseConfirmCmd { self.src_chan_id.clone(), ), b_side: ChannelSide::new( - chains.dst, + chains.dst.clone(), dst_connection.client_id().clone(), self.dst_conn_id.clone(), self.dst_port_id.clone(), self.dst_chan_id.clone(), ), + version: None, } } ); diff --git a/relayer-cli/src/commands/tx/client.rs b/relayer-cli/src/commands/tx/client.rs index c3de8d402f..da212a0796 100644 --- a/relayer-cli/src/commands/tx/client.rs +++ b/relayer-cli/src/commands/tx/client.rs @@ -1,5 +1,4 @@ use abscissa_core::{Command, Options, Runnable}; -use tracing::info; use ibc::events::IbcEvent; use ibc::ics02_client::client_state::ClientState; @@ -103,11 +102,8 @@ impl Runnable for TxUpdateClientCmd { None => ibc::Height::zero(), }; - let client = ForeignClient { - dst_chain, - src_chain, - id: self.dst_client_id.clone(), - }; + let client = ForeignClient::find(src_chain, dst_chain, &self.dst_client_id) + .unwrap_or_else(exit_with_unrecoverable_error); let res: Result = client .build_update_client_and_send(height, trusted_height) @@ -122,36 +118,40 @@ impl Runnable for TxUpdateClientCmd { #[derive(Clone, Command, Debug, Options)] pub struct TxUpgradeClientCmd { - #[options(free, required, help = "identifier of the destination chain")] - dst_chain_id: ChainId, + #[options(free, required, help = "identifier of the chain that hosts the client")] + chain_id: ChainId, - #[options( - free, - required, - help = "identifier of the chain which underwent upgrade (source chain)" - )] - src_chain_id: ChainId, - - #[options( - free, - required, - help = "identifier of the client to be upgraded on destination chain" - )] - dst_client_id: ClientId, + #[options(free, required, help = "identifier of the client to be upgraded")] + client_id: ClientId, } impl Runnable for TxUpgradeClientCmd { fn run(&self) { let config = app_config(); - let chains = ChainHandlePair::spawn(&config, &self.src_chain_id, &self.dst_chain_id) - .unwrap_or_else(exit_with_unrecoverable_error); + let dst_chain = match spawn_chain_runtime(&config, &self.chain_id) { + Ok(handle) => handle, + Err(e) => return Output::error(format!("{}", e)).exit(), + }; - info!("Started the chain runtimes"); + let src_chain_id = match dst_chain.query_client_state(&self.client_id, ibc::Height::zero()) + { + Ok(cs) => cs.chain_id(), + Err(e) => { + return Output::error(format!( + "Query of client '{}' on chain '{}' failed with error: {}", + self.client_id, self.chain_id, e + )) + .exit() + } + }; + + let src_chain = match spawn_chain_runtime(&config, &src_chain_id) { + Ok(handle) => handle, + Err(e) => return Output::error(format!("{}", e)).exit(), + }; - // Instantiate the client hosted on the destination chain, which is targeting headers for - // the source chain. - let client = ForeignClient::find(chains.src, chains.dst, &self.dst_client_id) + let client = ForeignClient::find(src_chain, dst_chain, &self.client_id) .unwrap_or_else(exit_with_unrecoverable_error); let outcome = client.upgrade(); diff --git a/relayer-cli/src/commands/tx/connection.rs b/relayer-cli/src/commands/tx/connection.rs index 02f1d75da9..16983f3cdf 100644 --- a/relayer-cli/src/commands/tx/connection.rs +++ b/relayer-cli/src/commands/tx/connection.rs @@ -23,7 +23,7 @@ macro_rules! conn_open_cmd { let connection = $conn(chains); - info!("Message {}: {:?}", $dbg_string, connection); + debug!("Message {}: {:?}", $dbg_string, connection); let res: Result = connection.$func().map_err(|e| Kind::Tx.context(e).into()); diff --git a/relayer-cli/src/commands/tx/transfer.rs b/relayer-cli/src/commands/tx/transfer.rs index 88adef5779..3ac285e2ca 100644 --- a/relayer-cli/src/commands/tx/transfer.rs +++ b/relayer-cli/src/commands/tx/transfer.rs @@ -1,6 +1,7 @@ use std::sync::Arc; use abscissa_core::{Command, Options, Runnable}; +use anomaly::BoxError; use tokio::runtime::Runtime as TokioRuntime; use ibc::events::IbcEvent; @@ -17,12 +18,12 @@ use crate::prelude::*; #[derive(Clone, Command, Debug, Options)] pub struct TxIcs20MsgTransferCmd { + #[options(free, required, help = "identifier of the destination chain")] + dst_chain_id: ChainId, + #[options(free, required, help = "identifier of the source chain")] src_chain_id: ChainId, - #[options(free, required, help = "identifier of the destination chain")] - dest_chain_id: ChainId, - #[options(free, required, help = "identifier of the source port")] src_port_id: PortId, @@ -45,31 +46,34 @@ pub struct TxIcs20MsgTransferCmd { )] receiver: Option, - #[options(help = "denomination of the coins to send", short = "d")] - denom: Option, + #[options( + help = "denomination of the coins to send", + short = "d", + default = "samoleans" + )] + denom: String, #[options(help = "number of messages to send", short = "n")] number_msgs: Option, } impl TxIcs20MsgTransferCmd { - fn validate_options(&self, config: &Config) -> Result { + fn validate_options(&self, config: &Config) -> Result { let src_chain_config = config .find_chain(&self.src_chain_id) - .ok_or_else(|| "missing src chain configuration".to_string())?; + .ok_or("missing src chain configuration")?; let dest_chain_config = config - .find_chain(&self.dest_chain_id) - .ok_or_else(|| "missing destination chain configuration".to_string())?; + .find_chain(&self.dst_chain_id) + .ok_or("missing destination chain configuration")?; + + let denom = self.denom.clone(); - let denom = self - .denom - .clone() - .unwrap_or_else(|| "samoleans".to_string()); let number_msgs = self.number_msgs.unwrap_or(1); if number_msgs == 0 { - return Err("number of messages should be bigger than zero".to_string()); + return Err("number of messages should be greater than zero".into()); } + let opts = TransferOptions { packet_src_chain_config: src_chain_config.clone(), packet_dst_chain_config: dest_chain_config.clone(), @@ -94,13 +98,15 @@ impl Runnable for TxIcs20MsgTransferCmd { Err(err) => return Output::error(err).exit(), Ok(result) => result, }; - info!("Message {:?}", opts); + + debug!("Message: {:?}", opts); let rt = Arc::new(TokioRuntime::new().unwrap()); let src_chain_res = CosmosSdkChain::bootstrap(opts.packet_src_chain_config.clone(), rt.clone()) .map_err(|e| Kind::Runtime.context(e)); + let src_chain = match src_chain_res { Ok(chain) => chain, Err(e) => return Output::error(format!("{}", e)).exit(), @@ -108,6 +114,7 @@ impl Runnable for TxIcs20MsgTransferCmd { let dst_chain_res = CosmosSdkChain::bootstrap(opts.packet_dst_chain_config.clone(), rt) .map_err(|e| Kind::Runtime.context(e)); + let dst_chain = match dst_chain_res { Ok(chain) => chain, Err(e) => return Output::error(format!("{}", e)).exit(), diff --git a/relayer-cli/src/commands/upgrade.rs b/relayer-cli/src/commands/upgrade.rs new file mode 100644 index 0000000000..f27d413514 --- /dev/null +++ b/relayer-cli/src/commands/upgrade.rs @@ -0,0 +1,16 @@ +//! `upgrade` subcommand + +use abscissa_core::{Command, Help, Options, Runnable}; + +use crate::commands::tx::client::TxUpgradeClientCmd; + +#[derive(Command, Debug, Options, Runnable)] +pub enum UpgradeCmds { + /// Generic `help` + #[options(help = "Get usage information")] + Help(Help), + + /// Subcommand for upgrading a `client` + #[options(help = "Upgrade an IBC client")] + Client(TxUpgradeClientCmd), +} diff --git a/relayer-cli/src/lib.rs b/relayer-cli/src/lib.rs index 56019b8671..c63f8f619d 100644 --- a/relayer-cli/src/lib.rs +++ b/relayer-cli/src/lib.rs @@ -1,8 +1,14 @@ -//! Cli for the IBC Relayer +//! Hermes: IBC Relayer CLI built in Rust //! -//! Application based on the [Abscissa] framework. +//! The Hermes binary is a wrapper over the [ibc-relayer] library. This binary builds on +//! the [Abscissa] framework. //! +//! For a comprehensive guide to using Hermes, the authoritative resource is +//! at [hermes.informal.systems]. +//! +//! [ibc-relayer]: https://docs.rs/ibc-relayer/0.1.1/ //! [Abscissa]: https://github.com/iqlusioninc/abscissa +//! [hermes.informal.systems]: https://hermes.informal.systems // Tip: Deny warnings with `RUSTFLAGS="-D warnings"` environment variable in CI @@ -14,7 +20,6 @@ unused_lifetimes, unused_qualifications )] -#![allow(unused_variables)] pub mod application; pub mod commands; @@ -27,3 +32,6 @@ pub(crate) mod cli_utils; pub(crate) mod components; pub(crate) mod conclude; pub(crate) mod entry; + +/// The path to the default configuration file. +pub const DEFAULT_CONFIG_PATH: &str = ".hermes/config.toml"; diff --git a/relayer/README.md b/relayer/README.md index a63c85aa36..60032b4580 100644 --- a/relayer/README.md +++ b/relayer/README.md @@ -1,3 +1,40 @@ -# IBC Relayer +# IBC Relayer (library) -This is the repository for the IBC Relayer built in Rust. \ No newline at end of file +[![Crate][crate-image]][crate-link] +[![Docs][docs-image]][docs-link] +[![Build Status][build-image]][build-link] +[![End to End testing][e2e-image]][e2e-link] +[![Apache 2.0 Licensed][license-image]][license-link] +![Rust Stable][rustc-image] +![Rust 1.49+][rustc-version] + +This is the repository for the IBC Relayer built in Rust, as a library. + + +## License + +Copyright © 2021 Informal Systems Inc. and ibc-rs authors. + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use the files in this repository except in compliance with the License. You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + + +[//]: # (badges) + +[crate-image]: https://img.shields.io/crates/v/ibc-relayer.svg +[crate-link]: https://crates.io/crates/ibc-relayer +[docs-image]: https://docs.rs/ibc-relayer/badge.svg +[docs-link]: https://docs.rs/ibc-relayer/ + +[build-image]: https://github.com/informalsystems/ibc-rs/workflows/Rust/badge.svg +[build-link]: https://github.com/informalsystems/ibc-rs/actions?query=workflow%3ARust +[e2e-image]: https://github.com/informalsystems/ibc-rs/workflows/End%20to%20End%20testing/badge.svg +[e2e-link]: https://github.com/informalsystems/ibc-rs/actions?query=workflow%3A%22End+to+End+testing%22 + +[license-image]: https://img.shields.io/badge/license-Apache2.0-blue.svg +[license-link]: https://github.com/informalsystems/ibc-rs/blob/master/LICENSE +[rustc-image]: https://img.shields.io/badge/rustc-stable-blue.svg +[rustc-version]: https://img.shields.io/badge/rustc-1.49+-blue.svg \ No newline at end of file diff --git a/relayer/src/chain/cosmos.rs b/relayer/src/chain/cosmos.rs index 888292a675..74cc46e34a 100644 --- a/relayer/src/chain/cosmos.rs +++ b/relayer/src/chain/cosmos.rs @@ -327,7 +327,7 @@ impl Chain for CosmosSdkChain { // Initialize key store and load key let keybase = - KeyRing::new(Store::Disk, config.clone()).map_err(|e| Kind::KeyBase.context(e))?; + KeyRing::new(Store::Test, config.clone()).map_err(|e| Kind::KeyBase.context(e))?; let grpc_addr = Uri::from_str(&config.grpc_addr.to_string()).map_err(|e| Kind::Grpc.context(e))?; diff --git a/relayer/src/channel.rs b/relayer/src/channel.rs index 0a48706a42..31ceb05cd1 100644 --- a/relayer/src/channel.rs +++ b/relayer/src/channel.rs @@ -92,6 +92,7 @@ pub struct Channel { pub a_side: ChannelSide, pub b_side: ChannelSide, pub connection_delay: Duration, + pub version: Option, } impl Channel { @@ -102,7 +103,15 @@ impl Channel { ordering: Order, a_port: PortId, b_port: PortId, + version: Option, ) -> Result { + let b_side_chain = connection.dst_chain().clone(); + let version = version.unwrap_or( + b_side_chain + .module_version(&a_port) + .map_err(|e| ChannelError::QueryError(b_side_chain.id(), e))?, + ); + let mut channel = Self { ordering, a_side: ChannelSide::new( @@ -120,6 +129,7 @@ impl Channel { Default::default(), ), connection_delay: connection.delay_period, + version: Some(version), }; channel.handshake()?; @@ -173,12 +183,13 @@ impl Channel { a_side: self.b_side.clone(), b_side: self.a_side.clone(), connection_delay: self.connection_delay, + version: self.version.clone(), } } /// Executes the channel handshake protocol (ICS004) fn handshake(&mut self) -> Result<(), ChannelError> { - let done = '\u{1F973}'; + let done = '🥳'; let a_chain = self.src_chain(); let b_chain = self.dst_chain(); @@ -195,7 +206,7 @@ impl Channel { } Ok(event) => { self.a_side.channel_id = extract_channel_id(&event)?.clone(); - println!("{} {} => {:?}\n", done, a_chain.id(), event); + println!("{} {} => {:#?}\n", done, a_chain.id(), event); init_success = true; break; } @@ -222,7 +233,7 @@ impl Channel { } Ok(event) => { self.b_side.channel_id = extract_channel_id(&event)?.clone(); - println!("{} {} => {:?}\n", done, b_chain.id(), event); + println!("{} {} => {:#?}\n", done, b_chain.id(), event); try_success = true; break; } @@ -260,21 +271,21 @@ impl Channel { // Ack to a_chain match self.flipped().build_chan_open_ack_and_send() { Err(e) => error!("Failed ChanAck {:?}: {}", self.a_side, e), - Ok(event) => println!("{} {} => {:?}\n", done, a_chain.id(), event), + Ok(event) => println!("{} {} => {:#?}\n", done, a_chain.id(), event), } } (State::Open, State::TryOpen) => { // Confirm to b_chain match self.build_chan_open_confirm_and_send() { Err(e) => error!("Failed ChanConfirm {:?}: {}", self.b_side, e), - Ok(event) => println!("{} {} => {:?}\n", done, b_chain.id(), event), + Ok(event) => println!("{} {} => {:#?}\n", done, b_chain.id(), event), } } (State::TryOpen, State::Open) => { // Confirm to a_chain match self.flipped().build_chan_open_confirm_and_send() { Err(e) => error!("Failed ChanConfirm {:?}: {}", self.a_side, e), - Ok(event) => println!("{} {} => {:?}\n", done, a_chain.id(), event), + Ok(event) => println!("{} {} => {:#?}\n", done, a_chain.id(), event), } } (State::Open, State::Open) => { @@ -306,6 +317,44 @@ impl Channel { }) } + /// Returns the channel version if already set, otherwise it queries the destination chain + /// for the destination port's version. + /// Note: This query is currently not available and it is hardcoded in the `module_version()` + /// to be `ics20-1` for `transfer` port. + pub fn dst_version(&self) -> Result { + Ok(self.version.clone() + .unwrap_or( + self + .dst_chain() + .module_version(self.dst_port_id()) + .map_err(|e| { + ChannelError::Failed(format!( + "failed while getting the module version from dst chain ({}) with error: {}", + self.dst_chain().id(), + e + )) + })? + )) + } + + /// Returns the channel version if already set, otherwise it queries the source chain + /// for the source port's version. + pub fn src_version(&self) -> Result { + Ok(self.version.clone() + .unwrap_or( + self + .src_chain() + .module_version(self.src_port_id()) + .map_err(|e| { + ChannelError::Failed(format!( + "failed while getting the module version from src chain ({}) with error: {}", + self.src_chain().id(), + e + )) + })? + )) + } + pub fn build_chan_open_init(&self) -> Result, ChannelError> { let signer = self.dst_chain().get_signer().map_err(|e| { ChannelError::Failed(format!( @@ -317,23 +366,12 @@ impl Channel { let counterparty = Counterparty::new(self.src_port_id().clone(), None); - let chan_version = self - .dst_chain() - .module_version(self.dst_port_id()) - .map_err(|e| { - ChannelError::Failed(format!( - "failed while getting the module version from dst chain ({}) with error: {}", - self.dst_chain().id(), - e - )) - })?; - let channel = ChannelEnd::new( State::Init, self.ordering, counterparty, vec![self.dst_connection_id().clone()], - chan_version, + self.dst_version()?, ); // Build the domain type message @@ -395,23 +433,12 @@ impl Channel { _ => State::Uninitialized, }; - let chan_version = self - .dst_chain() - .module_version(self.dst_port_id()) - .map_err(|e| { - ChannelError::Failed(format!( - "failed while getting the module version from dst chain ({}) with error: {}", - self.dst_chain().id(), - e - )) - })?; - let dst_expected_channel = ChannelEnd::new( highest_state, self.ordering, counterparty, vec![self.dst_connection_id().clone()], - chan_version, + self.dst_version()?, ); // Retrieve existing channel if any @@ -467,17 +494,12 @@ impl Channel { Some(self.src_channel_id().clone()), ); - let v_dst = self - .dst_chain() - .module_version(self.dst_port_id()) - .map_err(|e| ChannelError::QueryError(self.dst_chain().id(), e))?; - let channel = ChannelEnd::new( State::TryOpen, *src_channel.ordering(), counterparty, vec![self.dst_connection_id().clone()], - v_dst, + self.dst_version()?, ); // Get signer @@ -489,17 +511,11 @@ impl Channel { )) })?; - // Get source-chain version - let v_src = self - .src_chain() - .module_version(self.src_port_id()) - .map_err(|e| ChannelError::QueryError(self.src_chain().id(), e))?; - // Build the domain type message let new_msg = MsgChannelOpenTry { port_id: self.dst_port_id().clone(), previous_channel_id: src_channel.counterparty().channel_id.clone(), - counterparty_version: v_src, + counterparty_version: self.src_version()?, channel, proofs, signer, @@ -579,17 +595,12 @@ impl Channel { )) })?; - let v_src = self - .src_chain() - .module_version(self.src_port_id()) - .map_err(|e| ChannelError::QueryError(self.src_chain().id(), e))?; - // Build the domain type message let new_msg = MsgChannelOpenAck { port_id: self.dst_port_id().clone(), channel_id: self.dst_channel_id().clone(), counterparty_channel_id: self.src_channel_id().clone(), - counterparty_version: v_src, + counterparty_version: self.src_version()?, proofs, signer, }; diff --git a/relayer/src/connection.rs b/relayer/src/connection.rs index f0a39f22c3..fcf2a111ae 100644 --- a/relayer/src/connection.rs +++ b/relayer/src/connection.rs @@ -1,6 +1,7 @@ use std::time::Duration; use prost_types::Any; +use serde::Serialize; use thiserror::Error; use tracing::{error, warn}; @@ -57,7 +58,7 @@ impl ConnectionSide { chain: Box, client_id: ClientId, connection_id: ConnectionId, - ) -> ConnectionSide { + ) -> Self { Self { chain, client_id, @@ -66,7 +67,27 @@ impl ConnectionSide { } } -#[derive(Clone, Debug)] +impl Serialize for ConnectionSide { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + #[derive(Debug, Serialize)] + struct ConnectionSide<'a> { + client_id: &'a ClientId, + connection_id: &'a ConnectionId, + } + + let value = ConnectionSide { + client_id: &self.client_id, + connection_id: &self.connection_id, + }; + + value.serialize(serializer) + } +} + +#[derive(Clone, Debug, Serialize)] pub struct Connection { pub delay_period: Duration, pub a_side: ConnectionSide, @@ -223,7 +244,7 @@ impl Connection { /// Executes a connection handshake protocol (ICS 003) for this connection object fn handshake(&mut self) -> Result<(), ConnectionError> { - let done = '\u{1F942}'; // surprise emoji + let done = '🥂'; let a_chain = self.a_side.chain.clone(); let b_chain = self.b_side.chain.clone(); @@ -239,7 +260,7 @@ impl Connection { } Ok(result) => { self.a_side.connection_id = extract_connection_id(&result)?.clone(); - println!("{} {} => {:?}\n", done, self.a_side.chain.id(), result); + println!("🥂 {} => {:#?}\n", self.a_side.chain.id(), result); break; } } @@ -256,7 +277,7 @@ impl Connection { } Ok(result) => { self.b_side.connection_id = extract_connection_id(&result)?.clone(); - println!("{} {} => {:?}\n", done, self.b_side.chain.id(), result); + println!("{} {} => {:#?}\n", done, self.b_side.chain.id(), result); break; } } @@ -283,11 +304,9 @@ impl Connection { (State::Init, State::TryOpen) | (State::TryOpen, State::TryOpen) => { // Ack to a_chain match self.flipped().build_conn_ack_and_send() { - Err(e) => { - error!("Failed ConnAck {:?}: {}", self.a_side, e); - } + Err(e) => error!("Failed ConnAck {:?}: {}", self.a_side, e), Ok(event) => { - println!("{} {} => {:?}\n", done, self.a_side.chain.id(), event) + println!("{} {} => {:#?}\n", done, self.a_side.chain.id(), event) } } } @@ -296,7 +315,7 @@ impl Connection { match self.build_conn_confirm_and_send() { Err(e) => error!("Failed ConnConfirm {:?}: {}", self.b_side, e), Ok(event) => { - println!("{} {} => {:?}\n", done, self.b_side.chain.id(), event) + println!("{} {} => {:#?}\n", done, self.b_side.chain.id(), event) } } } @@ -305,14 +324,14 @@ impl Connection { match self.flipped().build_conn_confirm_and_send() { Err(e) => error!("Failed ConnConfirm {:?}: {}", self.a_side, e), Ok(event) => { - println!("{} {} => {:?}\n", done, self.a_side.chain.id(), event) + println!("{} {} => {:#?}\n", done, self.a_side.chain.id(), event) } } } (State::Open, State::Open) => { println!( - "{} {} {} Connection handshake finished for [{:#?}]\n", - done, done, done, self + "{0}{0}{0} Connection handshake finished for [{1:#?}]\n", + done, self ); return Ok(()); } diff --git a/relayer/src/event/rpc.rs b/relayer/src/event/rpc.rs index 6f50ba5f7c..7d3e8ca8fe 100644 --- a/relayer/src/event/rpc.rs +++ b/relayer/src/event/rpc.rs @@ -128,7 +128,7 @@ pub fn build_event(mut object: RawObject) -> Result { )) } - _ => Err("Incorrect Event Type".into()), + event_type => Err(format!("Incorrect event type: '{}'", event_type).into()), } } diff --git a/relayer/src/foreign_client.rs b/relayer/src/foreign_client.rs index dd23da8f4c..c83f353a97 100644 --- a/relayer/src/foreign_client.rs +++ b/relayer/src/foreign_client.rs @@ -301,8 +301,6 @@ impl ForeignClient { /// Sends the client creation transaction & subsequently sets the id of this ForeignClient fn create(&mut self) -> Result<(), ForeignClientError> { - let done = '\u{1F36D}'; - match self.build_create_client_and_send() { Err(e) => { error!("Failed CreateClient {:?}: {}", self.dst_chain.id(), e); @@ -313,7 +311,7 @@ impl ForeignClient { } Ok(event) => { self.id = extract_client_id(&event)?.clone(); - println!("{} {} => {:?}\n", done, self.dst_chain.id(), event); + info!("🍭 {} => {:#?}\n", self.dst_chain.id(), event); } } Ok(()) diff --git a/relayer/src/keyring.rs b/relayer/src/keyring.rs index b654148489..b7a9192201 100644 --- a/relayer/src/keyring.rs +++ b/relayer/src/keyring.rs @@ -131,13 +131,13 @@ impl KeyStore for Memory { } #[derive(Clone, Debug, Serialize, Deserialize)] -pub struct Disk { +pub struct Test { key_name: String, account_prefix: String, store: PathBuf, } -impl Disk { +impl Test { pub fn new(key_name: String, account_prefix: String, store: PathBuf) -> Self { Self { key_name, @@ -147,7 +147,7 @@ impl Disk { } } -impl KeyStore for Disk { +impl KeyStore for Test { fn get_key(&self) -> Result { let mut filename = self.store.join(&self.key_name); filename.set_extension(KEYSTORE_FILE_EXTENSION); @@ -182,13 +182,13 @@ impl KeyStore for Disk { #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum Store { Memory, - Disk, + Test, } #[derive(Clone, Debug, Serialize, Deserialize)] pub enum KeyRing { Memory(Memory), - Disk(Disk), + Test(Test), } impl KeyRing { @@ -196,17 +196,17 @@ impl KeyRing { match store { Store::Memory => Ok(Self::Memory(Memory::new(chain_config.account_prefix, None))), - Store::Disk => { + Store::Test => { let keys_folder = disk_store_path(chain_config.id.as_str()).map_err(|e| { Kind::KeyStore.context(format!("failed to compute keys folder path: {:?}", e)) })?; // Create keys folder if it does not exist - fs::create_dir_all(keys_folder.clone()).map_err(|e| { + fs::create_dir_all(&keys_folder).map_err(|e| { Kind::KeyStore.context(format!("failed to create keys folder: {:?}", e)) })?; - Ok(Self::Disk(Disk::new( + Ok(Self::Test(Test::new( chain_config.key_name, chain_config.account_prefix, keys_folder, @@ -218,14 +218,14 @@ impl KeyRing { pub fn get_key(&self) -> Result { match self { KeyRing::Memory(m) => m.get_key(), - KeyRing::Disk(d) => d.get_key(), + KeyRing::Test(d) => d.get_key(), } } pub fn add_key(&mut self, key_entry: KeyEntry) -> Result<(), Error> { match self { KeyRing::Memory(m) => m.add_key(key_entry), - KeyRing::Disk(d) => d.add_key(key_entry), + KeyRing::Test(d) => d.add_key(key_entry), } } @@ -276,7 +276,7 @@ impl KeyRing { pub fn account_prefix(&self) -> &str { match self { KeyRing::Memory(m) => &m.account_prefix, - KeyRing::Disk(d) => &d.account_prefix, + KeyRing::Test(d) => &d.account_prefix, } } } diff --git a/relayer/src/lib.rs b/relayer/src/lib.rs index 192cd78686..1474f380dd 100644 --- a/relayer/src/lib.rs +++ b/relayer/src/lib.rs @@ -1,7 +1,5 @@ #![forbid(unsafe_code)] #![deny( - // warnings, - // missing_docs, trivial_casts, trivial_numeric_casts, unused_import_braces, @@ -9,7 +7,11 @@ rust_2018_idioms )] -//! IBC Relayer implementation +//! IBC Relayer implementation as a library. +//! +//! For the IBC relayer binary, please see [Hermes] (`ibc-relayer-cli` crate). +//! +//! [Hermes]: https://docs.rs/ibc-relayer-cli/0.1.1/ pub mod chain; pub mod channel; diff --git a/relayer/src/link.rs b/relayer/src/link.rs index af47d4db1f..f1158f48b8 100644 --- a/relayer/src/link.rs +++ b/relayer/src/link.rs @@ -1226,7 +1226,7 @@ impl RelayPath { /// Checks if there are any operational data items ready, and if so performs the relaying /// of corresponding packets to the target chain. - fn execute_schedule(&mut self) -> Result<(), LinkError> { + pub fn execute_schedule(&mut self) -> Result<(), LinkError> { let (src_ods, dst_ods) = self.try_fetch_scheduled_operational_data(); for od in src_ods { self.relay_from_operational_data(od)?; @@ -1242,7 +1242,7 @@ impl RelayPath { /// Refreshes the scheduled batches. /// Verifies if any sendPacket messages timed-out. If so, moves them from destination op. data /// to source operational data, and adjusts the events and messages accordingly. - fn refresh_schedule(&mut self) -> Result<(), LinkError> { + pub fn refresh_schedule(&mut self) -> Result<(), LinkError> { let dst_current_height = self.dst_latest_height()?; // Intermediary data struct to help better manage the transfer from dst. operational data @@ -1467,7 +1467,7 @@ impl Link { loop { if self.is_closed()? { - println!("channel is closed, exiting"); + warn!("channel is closed, exiting"); return Ok(()); } @@ -1492,7 +1492,7 @@ impl Link { } } - fn is_closed(&self) -> Result { + pub fn is_closed(&self) -> Result { let a_channel = self .a_to_b .src_chain() @@ -1607,6 +1607,7 @@ impl Link { b_channel_id, ), connection_delay: a_connection.delay_period(), + version: None, }; Ok(Link::new(channel)) diff --git a/relayer/src/relay.rs b/relayer/src/relay.rs index 7ce996e9cf..ac2ca17c75 100644 --- a/relayer/src/relay.rs +++ b/relayer/src/relay.rs @@ -66,5 +66,6 @@ pub fn connect_with_new_channel( ordering, path.a_port, path.b_port, + None, )?) } diff --git a/relayer/src/supervisor.rs b/relayer/src/supervisor.rs index e1dd5cbd01..c86df8e03b 100644 --- a/relayer/src/supervisor.rs +++ b/relayer/src/supervisor.rs @@ -18,7 +18,7 @@ use ibc::{ ics24_host::identifier::{ChainId, ChannelId, PortId}, Height, }; -use tracing::info; +use tracing::{info, warn}; use crate::{ chain::handle::ChainHandle, @@ -161,7 +161,7 @@ impl Supervisor { continue; } - println!("[{}] events: {:?}", chain_id, events); + println!("[{}] events: {:#?}", chain_id, events); if let Some(worker) = self.worker_for_object(object, direction) { worker.send_packet_events(height, events, chain_id.clone())?; @@ -231,6 +231,12 @@ impl Worker { pub fn spawn(chains: ChainHandlePair, object: Object) -> WorkerHandle { let (tx, rx) = crossbeam_channel::unbounded(); + println!( + "[{}] Spawned worker for object {:#?}", + object.short_name(), + object + ); + let worker = Self { chains, rx }; let thread_handle = std::thread::spawn(move || worker.run(object)); @@ -250,8 +256,6 @@ impl Worker { /// Run the event loop for events associated with a [`UnidirectionalChannelPath`]. fn run_uni_chan_path(self, path: UnidirectionalChannelPath) -> Result<(), BoxError> { - println!("running worker for object {:?}", path); - let mut link = Link::new_from_opts( self.chains.a.clone(), self.chains.b.clone(), @@ -261,17 +265,31 @@ impl Worker { }, )?; - while let Ok(cmd) = self.rx.recv() { - match cmd { - WorkerCmd::PacketEvents { batch } => link.a_to_b.update_schedule(batch)?, - WorkerCmd::NewBlocks { - height, - new_blocks: _, - } => link.a_to_b.clear_packets(height)?, - } + if link.is_closed()? { + warn!("channel is closed, exiting"); + return Ok(()); } - Ok(()) + loop { + if let Ok(cmd) = self.rx.try_recv() { + match cmd { + WorkerCmd::PacketEvents { batch } => { + link.a_to_b.update_schedule(batch)?; + // Refresh the scheduled batches and execute any outstanding ones. + } + WorkerCmd::NewBlocks { + height, + new_blocks: _, + } => link.a_to_b.clear_packets(height)?, + } + } + + // Refresh the scheduled batches and execute any outstanding ones. + link.a_to_b.refresh_schedule()?; + link.a_to_b.execute_schedule()?; + + thread::sleep(Duration::from_millis(100)) + } } } @@ -280,14 +298,26 @@ impl Worker { pub struct UnidirectionalChannelPath { /// Destination chain identifier. pub dst_chain_id: ChainId, + /// Source chain identifier. pub src_chain_id: ChainId, + /// Source channel identiier. pub src_channel_id: ChannelId, + /// Source port identiier. pub src_port_id: PortId, } +impl UnidirectionalChannelPath { + pub fn short_name(&self) -> String { + format!( + "{}->{}@{}:{}", + self.src_chain_id, self.dst_chain_id, self.src_channel_id, self.src_port_id + ) + } +} + /// An object determines the amount of parallelism that can /// be exercised when processing [`IbcEvent`] between /// two chains. For each [`Object`], a corresponding @@ -319,6 +349,12 @@ impl Object { } } + pub fn short_name(&self) -> String { + match self { + Self::UnidirectionalChannelPath(ref path) => path.short_name(), + } + } + /// Build the object associated with the given [`SendPacket`] event. pub fn for_send_packet(e: &SendPacket, src_chain: &dyn ChainHandle) -> Result { let dst_chain_id = diff --git a/scripts/setup-chains b/scripts/setup-chains index ecaa2506f2..c031ea99b8 100755 --- a/scripts/setup-chains +++ b/scripts/setup-chains @@ -35,7 +35,7 @@ GAIA_DATA="$(pwd)/data" # Ensure user understands what will be deleted if [[ -d $GAIA_DATA ]] && [[ ! "$3" == "skip" ]]; then - echo "$0 will delete $(pwd)/data folder." + echo "WARNING: $0 will DELETE the '$(pwd)/data' folder." read -p "> Do you wish to continue? (y/n): " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then @@ -68,15 +68,19 @@ CHAIN_0_RPC_PORT=26657 CHAIN_1_RPC_PORT=26557 CHAIN_2_RPC_PORT=26457 +CHAIN_0_GRPC_PORT=9090 +CHAIN_1_GRPC_PORT=9091 +CHAIN_2_GRPC_PORT=9092 + CHAIN_0_SAMOLEANS=100000000000 CHAIN_1_SAMOLEANS=100000000000 CHAIN_2_SAMOLEANS=100000000000 -"$ONE_CHAIN" gaiad "$CHAIN_0_ID" ./data $CHAIN_0_RPC_PORT 26656 6060 9090 $CHAIN_0_SAMOLEANS -"$ONE_CHAIN" gaiad "$CHAIN_1_ID" ./data $CHAIN_1_RPC_PORT 26556 6061 9091 $CHAIN_1_SAMOLEANS +"$ONE_CHAIN" gaiad "$CHAIN_0_ID" ./data $CHAIN_0_RPC_PORT 26656 6060 $CHAIN_0_GRPC_PORT $CHAIN_0_SAMOLEANS +"$ONE_CHAIN" gaiad "$CHAIN_1_ID" ./data $CHAIN_1_RPC_PORT 26556 6061 $CHAIN_1_GRPC_PORT $CHAIN_1_SAMOLEANS if [ -n "$CHAIN_2_ID" ]; then - "$ONE_CHAIN" gaiad "$CHAIN_2_ID" ./data $CHAIN_2_RPC_PORT 26456 6062 9092 $CHAIN_2_SAMOLEANS + "$ONE_CHAIN" gaiad "$CHAIN_2_ID" ./data $CHAIN_2_RPC_PORT 26456 6062 $CHAIN_2_GRPC_PORT $CHAIN_2_SAMOLEANS fi [ -f "$GAIA_DATA/$CHAIN_0_ID.log" ] && echo "$CHAIN_0_ID initialized. Watch file $GAIA_DATA/$CHAIN_0_ID.log to see its execution."