Skip to main content

Run an IBC Relayer

What is an IBC Relayer?

An IBC relayer is a software component that facilitates communication between two distinct blockchain networks that support the Inter-Blockchain Communication (IBC) protocol. The IBC protocol is a standard for the secure and reliable transfer of digital assets and data across different blockchain networks.

An IBC relayer is responsible for relaying IBC packets, which are used to send messages and data between two different blockchain networks. It receives packets from one chain, verifies their authenticity and validity, and then relays them to the receiving chain.

Minimum Requirements

  • 8 core (4 physical core), x86_64 architecture processor
  • 32 GB RAM (or equivalent swap file set up)
  • 1 TB+ nVME drives

If running many nodes on a single VM, ensure your open files limit is increased.

Prerequisites

Before beginning, ensure you have an Evmos node running in the background of the same machine that you intend to relay on. Follow this guide to set up an Evmos node if you have not already.

In this guide, we will be relaying between Evmos (channel-3) and Cosmos Hub (channel-292). When setting up your Evmos and Cosmos full nodes, be sure to offset the ports being used in both the app.toml and config.toml files of the respective chains (this process will be shown below).

In this example, the default ports for Evmos will be used, and the ports of the Cosmos Hub node will be manually changed.

Evmos Daemon Settings

First, set grpc server on port 9090 in the app.toml file from the $HOME/.evmosd/config directory:

vim $HOME/.evmosd/config/app.toml
[grpc]

# Enable defines if the gRPC server should be enabled.
enable = true

# Address defines the gRPC server address to bind to.
address = "0.0.0.0:9090"

Then, set the pprof_laddr to port 6060, rpc laddr to port 26657, and prp laddr to 26656 in the config.toml file from the $HOME/.evmosd/config directory:

vim $HOME/.evmosd/config/config.toml
# pprof listen address (https://golang.org/pkg/net/http/pprof)
pprof_laddr = "localhost:6060"
[rpc]

# TCP or UNIX socket address for the RPC server to listen on
laddr = "tcp://127.0.0.1:26657"
[p2p]

# Address to listen for incoming connections
laddr = "tcp://0.0.0.0:26656"

Cosmos Daemon Settings

First, set grpc server to port 9090 in the app.toml file from the $HOME/.gaiad/config directory:

vim $HOME/.gaiad/config/app.toml
[grpc]

# Enable defines if the gRPC server should be enabled.
enable = true

# Address defines the gRPC server address to bind to.
address = "0.0.0.0:9092"

Then, set the pprof_laddr to port 6062, rpc laddr to port 26757, and prp laddr to 26756 in the config.toml file from the $HOME/.gaiad/config directory:

vim $HOME/.gaiad/config/app.toml
# pprof listen address (https://golang.org/pkg/net/http/pprof)
pprof_laddr = "localhost:6062"
[rpc]

# TCP or UNIX socket address for the RPC server to listen on
laddr = "tcp://127.0.0.1:26757"
[p2p]

# Address to listen for incoming connections
laddr = "tcp://0.0.0.0:26756"

Install Rust Dependencies

Install the following rust dependencies:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
sudo apt-get install pkg-config libssl-dev
sudo apt install librust-openssl-dev build-essential git

Build & Setup Hermes

Create the directory where the binary will be placed, clone the hermes source repository, and build it using the latest release.

mkdir -p $HOME/hermes
git clone https://github.com/informalsystems/ibc-rs.git hermes
cd hermes
git checkout v0.12.0
cargo install ibc-relayer-cli --bin hermes --locked

Make the hermes config and keys directory, and copy config.toml to the config directory:

mkdir -p $HOME/.hermes
mkdir -p $HOME/.hermes/keys
cp config.toml $HOME/.hermes

Check the hermes version and configuration directory setup:

$ hermes version
INFO ThreadId(01) using default configuration from '/home/relay/.hermes/config.toml'
hermes 0.12.0

Edit the hermes configuration (use ports according the port configuration set above, adding only chains that will be relayed):

vim $HOME/.hermes/config.toml
# In this example, we will set channel-292 on the cosmoshub-4 chain settings and channel-3 on the evmos_9001-2 chain settings:
[[chains]]
id = 'cosmoshub-4'
rpc_addr = 'http://127.0.0.1:26757'
grpc_addr = 'http://127.0.0.1:9092'
websocket_addr = 'ws://127.0.0.1:26757/websocket'
...
[chains.packet_filter]
policy = 'allow'
list = [
['transfer', 'channel-292'], # evmos_9001-2
]

[[chains]]
id = 'evmos_9001-2'
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'
...
address_type = { derivation = 'ethermint', proto_type = { pk_type = '/ethermint.crypto.v1.ethsecp256k1.PubKey' } }
[chains.packet_filter]
policy = 'allow'
list = [
['transfer', 'channel-3'], # cosmoshub-4
]

Add your relayer wallet to Hermes' keyring (located in $HOME/.hermes/keys)

The best practice is to use the same mnemonic over all networks. Do not use your relaying-addresses for anything else, because it will lead to account sequence errors.

hermes keys restore cosmoshub-4 -m "24-word mnemonic seed"
hermes keys restore evmos_9001-2 -m "24-word mnemonic seed"

Ensure this wallet has funds in both EVMOS and ATOM in order to pay the fees required to relay.

Final Checks

Validate your hermes configuration file:

$ hermes config validate
INFO ThreadId(01) using default configuration from '/home/relay/.hermes/config.toml'
Success: "validation passed successfully"

Perform the hermes health-check to see if all connected nodes are up and synced:

$ hermes health-check
INFO ThreadId(01) using default configuration from '/home/relay/.hermes/config.toml'
INFO ThreadId(01) telemetry service running, exposing metrics at http://0.0.0.0:3001/metrics
INFO ThreadId(01) starting REST API server listening at http://127.0.0.1:3000
INFO ThreadId(01) [cosmoshub-4] chain is healthy
INFO ThreadId(01) [evmos_9001-2] chain is healthy

When your nodes are fully synced, you can start the hermes daemon:

hermes start

Watch hermes' output for successfully relayed packets, or any errors. It will try and clear any unrecieved packets after startup has completed.

Helpful Commands

Query hermes for unrecieved packets and acknowledgements (ie. check if channels are "clear") with the following:

hermes query packet unreceived-packets cosmoshub-4 transfer channel-292
hermes query packet unreceived-acks cosmoshub-4 transfer channel-292
hermes query packet unreceived-packets evmos_9001-2 transfer channel-3
hermes query packet unreceived-acks evmos_9001-2 transfer channel-3

Query hermes for packet commitments with the following:

hermes query packet commitments cosmoshub-4 transfer channel-292
hermes query packet commitments evmos_9001-2 transfer channel-3

Clear the channel (only works on hermes v0.12.0 and higher) with the following:

hermes clear packets cosmoshub-4 transfer channel-292
hermes clear packets evmos_9001-2 transfer channel-3

Clear unrecieved packets manually (experimental, will need to stop hermes daemon to prevent confusion with account sequences) with the following:

hermes tx raw packet-recv evmos_9001-2 cosmoshub-4 transfer channel-292
hermes tx raw packet-ack evmos_9001-2 cosmoshub-4 transfer channel-292
hermes tx raw packet-recv cosmoshub-4 evmos_9001-2 transfer channel-3
hermes tx raw packet-ack cosmoshub-4 evmos_9001-2 transfer channel-3