IBC Relaying Guide
Celestia uses IBC (Inter-Blockchain Communication protocol) to enable cross-chain transfer of tokens. To support this capability it relies on relayers, processes that can be run by anyone which constantly scan for outbound packets on one chain and submits these packets alongside corresponding proofs on the destination chain. This section describes how one can setup a relayer and create new connections between chains. There are two standard implementations:
- Hermes built in Rust
- Go Relayer built in Go
The following guide explains how to establish IBC connections and relay packets between Celestia's Blockspace Race and Dymension's 35-C networks by using the Hermes relayer.
This guide was adapted from https://medium.com/qubelabs/ibc-connection-and-relaying-celestia-bsr-dymension-35-c-e4423699e856.
Setup
Hermes is an open-source
Rust implementation of an Inter-Blockchain Communication protocol (IBC)
relayer released as part of the ibc-relayer-cli
crate. It includes a
CLI for relaying packets between Cosmos SDK chains, as well as Prometheus
metrics and a REST API.
Install Rust
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 Hermes
Create a new directory and clone the Hermes repository. For the latest available release see Hermes GitHub.
mkdir -p $HOME/hermes
git clone https://github.com/informalsystems/hermes
cd hermes
git checkout v1.5.0
cargo install ibc-relayer-cli --bin hermes --locked
Create a keys
directory and copy the template config.toml
to the .hermes
directory.
mkdir -p $HOME/.hermes
mkdir -p $HOME/.hermes/keys
cp config.toml $HOME/.hermes
Before proceeding, verify that Hermes is installed correctly by running hermes version
.
Hermes Configuration
After you have successfully installed Hermes and created the necessary folders,
you now have to edit config.toml
and add the appropriate configurations for
the chains you want to relay between.
For this tutorial, we will be using the following chains:
Celestia's Blockspace Race
blockspacerace-0
https://docs.celestia.org/nodes/blockspace-race/Dymension's 35-C
35-C
https://docs.dymension.xyz/validate/dymension-hub/build-dymd
If you are running both nodes on the same server where Hermes is running, you can use the local host. Please adjust the ports and IPs depending on your configurations.
nano $HOME/.hermes/config.toml
Please edit the Hermes configurations for your running nodes.
Do not forget to remove the "chains"
section generated by
default with the example at the end of the file.
[[chains]]
id = 'blockspacerace-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 = 'celestia'
key_name = 'hermes-celestia'
store_prefix = 'ibc'
default_gas = 5000000
max_gas = 15000000
gas_price = { price = 0.001, denom = 'utia' }
gas_multiplier = 1.1
max_msg_num = 20
max_tx_size = 209715
clock_drift = '20s'
max_block_time = '30s'
trusting_period = '21days'
trust_threshold = { numerator = '1', denominator = '3' }
memo_prefix = 'Enter your Memo'
address_type = { derivation = 'cosmos' }
[chains.packet_filter]
policy = 'allow'
list = [
[]
]
[[chains]]
id = '35-C'
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 = 'dym'
key_name = 'hermes-dymension'
store_prefix = 'ibc'
default_gas = 100000
max_gas = 15000000
gas_price = { price = 0.025, denom = 'udym' }
gas_multiplier = 1.1
max_msg_num = 30
max_tx_size = 2097152
clock_drift = '5s'
max_block_time = '10s'
trusting_period = '21days'
trust_threshold = { numerator = '1', denominator = '3' }
memo_prefix = 'Enter your memo'
address_type = { derivation = 'cosmos' }
[chains.packet_filter]
policy = 'allow'
list = [
[]
]
Relayer needs chain data for at least 2/3 of the unbonding period,
so make sure to use prunning settings that keep the state for longer
period than the unbonding time. You can configure custom pruning in
app.toml
for each chain.
Add relayer wallets
Now that we have successfully configured our relaying chains, we need to import the wallets that will be used in the process. Please note that both wallets need to be funded with the native tokens of each chain.
You can get faucet tokens in Discord:
- Celestia: https://discord.gg/celestiacommunity
- Dymension: https://discord.gg/dymension
Add your seed phrase to a file and upload it to the server. Do not use wallets for anything else but relaying to avoid running into account sequence errors.
hermes keys add --chain blockspacerace-0 --mnemonic-file <seed-file>
hermes keys add --chain C-35 --mnemonic-file <seed-file>
Verify configuration files
After editing config.toml
and adding wallet keys, it’s time to
test the configurations and ensure the system is healthy. Run the following:
hermes health-check
hermes config validate
If everything was set up correctly, you should be seeing similar outputs:
SUCCESS performed health check for all chains in the config
SUCCESS "configuration is valid"
Create a connection between 2 chains
If you’re attempting to create new connections, please always verify first that the chains in question don’t already have connections and clients in place and use the existing ones if they do. In that case you can skip this step and go to Configure channels in Hermes section.
In this example, we are creating a new connection with new clients between 35-C
and blockspacerace-0
networks.
Open connection over new clients
If a connection already exists, do not create a new one. Most networks already have appropriate relay paths set up!
To create a new connection over new clients, use the following setup
hermes create connection --a-chain 35-C --b-chain blockspacerace-0
You should be seeing a similar output to this:
SUCCESS Connection {
delay_period: 0ns,
a_side: ConnectionSide {
chain: BaseChainHandle {
chain_id: ChainId {
id: "35-C",
version: 0,
},
runtime_sender: Sender { .. },
},
client_id: ClientId(
"07-tendermint-22",
),
connection_id: Some(
ConnectionId(
"connection-15",
),
),
},
b_side: ConnectionSide {
chain: BaseChainHandle {
chain_id: ChainId {
id: "blockspacerace-0",
version: 0,
},
runtime_sender: Sender { .. },
},
client_id: ClientId(
"07-tendermint-0",
),
connection_id: Some(
ConnectionId(
"connection-0",
),
),
},
}
Now that the connection has been established over new clients, we need to create a new channel, by leveraging an existing connection:
hermes create channel --order unordered --a-chain 35-C --a-connection connection-15 --a-port transfer --b-port transfer
You should be seeing a similar output to this:
SUCCESS Channel {
ordering: Unordered,
a_side: ChannelSide {
chain: BaseChainHandle {
chain_id: ChainId {
id: "35-C",
version: 0,
},
runtime_sender: Sender { .. },
},
client_id: ClientId(
"07-tendermint-22",
),
connection_id: ConnectionId(
"connection-15",
),
port_id: PortId(
"transfer",
),
channel_id: Some(
ChannelId(
"channel-14",
),
),
version: None,
},
b_side: ChannelSide {
chain: BaseChainHandle {
chain_id: ChainId {
id: "blockspacerace-0",
version: 0,
},
runtime_sender: Sender { .. },
},
client_id: ClientId(
"07-tendermint-0",
),
connection_id: ConnectionId(
"connection-0",
),
port_id: PortId(
"transfer",
),
channel_id: Some(
ChannelId(
"channel-0",
),
),
version: None,
},
connection_delay: 0ns,
}
You have successfully created a new IBC connection between two networks.
Configure channels in Hermes
Now that we have created new connections and opened channels, we need to
edit config.toml
again and add the newly created channels, or use the
already existing ones.
For 35-C
add:
[chains.packet_filter]
policy = 'allow'
list = [
['transfer', 'channel-14'], # blockspacerace-0
]
For blockspacerace-0
add:
[chains.packet_filter]
policy = 'allow'
list = [
['transfer', 'channel-0'], # 35-C
]
Start the relayer
To start the relayer, we will be using systemd
as a service for
running applications as background processes.
Create Hermes systemd file
sudo tee <<EOF >/dev/null /etc/systemd/system/hermes.service
[Unit]
Description=hermes daemon
After=network-online.target
[Service]
User=$USER
ExecStart=$(which hermes) start
Restart=on-failure
RestartSec=3
LimitNOFILE=4096
[Install]
WantedBy=multi-user.target
EOF
Enable and start the hermes service
sudo systemctl enable hermes
sudo systemctl start hermes
You can follow the logs by using sudo journalctl -u hermes.service -f
.
If the relayer is set up successfully, upon starting, you should be
seeing a similar output:
INFO ThreadId(01) spawn:chain{chain=35-C}: spawning Wallet worker: wallet::35-C
INFO ThreadId(01) spawn:chain{chain=blockspacerace-0}: spawning Wallet worker: wallet::blockspacerace-0
2023-05-12T22:51:03.193852Z INFO ThreadId(01) Hermes has started
Good luck with relaying IBC packets! 🔥