Run an IBC Relayer
What is an IBC Relayer?
It is possible to communicate between two different blockchain networks that accept the Inter-Blockchain Communication (IBC) protocol using an IBC relayer, which is a software component. IBC protocol is a standard for the safe and reliable movement of digital assets and data between various blockchain networks.
IBC packets are used to transport messages and data between two distinct blockchain networks, and an IBC relayer is in charge of relaying these packets. After confirming their validity and authenticity, it sends the packets to the receiving chain after receiving them from one chain.
In this guide, we will be relaying between Humans (channel-4) and Osmosis (channel-20082). When setting up your Humans and Osmosis full nodes, be sure to offset the ports being used in both the app.toml
and config.toml
files of the respective chains.
Steps can be also found in the validator guide created by Huggin Tech.
Minimum Requirements
- 8 core (4 physical core), x86_64 architecture processor
- 32 GB RAM (or equivalent swap file set up)
- 1 TB+ nVME drives
- Tested in Ubuntu Server 22.04 / Rocky Linux 8 x64
When using a single VM to run several nodes, ensure your open files limit is increased.
Prerequisites
Humans Daemon Settings
First, set grpc server
on port 9090
in the app.toml
file from the $HOME/.humansd/config
directory:
nano $HOME/.humansd/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/.humansd/config
directory:
nano $HOME/.humansd/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"
Osmosis Daemon Settings
First, set grpc server
to port 9092
in the app.toml
file from the $HOME/.osmosisd/config
directory:
nano $HOME/.osmosisd/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/.osmosisd/config
directory:
nano $HOME/.osmosisd/config/config.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"
Make the updates and install the necessary packages
sudo apt update && sudo apt upgrade
Install 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
Install Hermes via Cargo
The official Hermes (IBC Relayer CLI) Documentation can be found here.
cargo install ibc-relayer-cli --bin hermes --locked
export PATH="$HOME/.cargo/bin:$PATH"
# Check hermes version
hermes version
hermes v1.7.4
Make the hermes directory
, keys
and create config.toml
and save this config:
mkdir -p $HOME/.hermes
mkdir -p $HOME/.hermes/keys
cd .hermes
nano config.toml
[global]
log_level = "info"
[mode.clients]
enabled = true
refresh = true
misbehaviour = false
[mode.connections]
enabled = false
[mode.channels]
enabled = false
[mode.packets]
enabled = true
clear_interval = 200
clear_on_start = true
tx_confirmation = true
auto_register_counterparty_payee = false
[rest]
enabled = false
host = "127.0.0.1"
port = 3000
[telemetry]
enabled = false
host = "127.0.0.1"
port = 3001
[telemetry.buckets.latency_submitted]
start = 500
end = 20000
buckets = 10
[telemetry.buckets.latency_confirmed]
start = 1000
end = 30000
buckets = 10
[[chains]]
id = "osmosis-1"
type = "CosmosSdk"
rpc_addr = "http://127.0.0.1:26757"
grpc_addr = "http://127.0.0.1:9092"
rpc_timeout = "10s"
trusted_node = false
account_prefix = "osmo"
key_name = "osmosis"
key_store_type = "Test"
store_prefix = "ibc"
default_gas = 500000
max_gas = 120000000
gas_multiplier = 1.4
max_msg_num = 30
max_tx_size = 180000
max_grpc_decoding_size = 33554432
clock_drift = "15s"
max_block_time = "30s"
ccv_consumer_chain = false
memo_prefix = "Relayed by Huginn | https://huginn.tech"
sequential_batch_tx = false
[chains.event_source]
mode = "push"
url = "wss://127.0.0.1:26757/websocket"
batch_delay = "500ms"
[chains.trust_threshold]
numerator = "1"
denominator = "3"
[chains.gas_price]
price = 0.0050
denom = "uosmo"
[chains.packet_filter]
policy = "allow"
list = [
['transfer', 'channel-20082'], # humans
]
[chains.packet_filter.min_fees]
[chains.address_type]
derivation = "cosmos"
[[chains]]
id = "humans_1089-1"
type = "CosmosSdk"
rpc_addr = "http://127.0.0.1:26657"
grpc_addr = "http://127.0.0.1:9090"
rpc_timeout = "10s"
trusted_node = false
account_prefix = "human"
key_name = "human"
key_store_type = "Test"
store_prefix = "ibc"
default_gas = 200000
max_gas = 10000000
gas_multiplier = 1.3
max_msg_num = 30
max_tx_size = 2097152
max_grpc_decoding_size = 33554432
clock_drift = "25s"
max_block_time = "30s"
ccv_consumer_chain = false
memo_prefix = "Relayed by validator name | validator.website"
sequential_batch_tx = false
[chains.event_source]
mode = "push"
url = "wss://127.0.0.1:26657/websocket"
batch_delay = "500ms"
[chains.trust_threshold]
numerator = "1"
denominator = "3"
[chains.gas_price]
price = 100000000000
denom = "aheart"
[chains.packet_filter]
policy = "allow"
list = [
['transfer', 'channel-4'], # osmosis
]
[chains.packet_filter.min_fees]
[chains.address_type]
derivation = "ethermint"
proto_type = { pk_type = '/ethermint.crypto.v1.ethsecp256k1.PubKey' }
Edit the hermes configuration (use ports according the port configuration set above, adding only chains that will be relayed) and save the file.
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.
MNEMONIC_B='24-word mnemonic seed'
CHAIN_ID_B='humans_1089-1'
sudo tee $HOME/.hermes/${CHAIN_ID_A}.mnemonic > /dev/null <<EOF
${MNEMONIC_A}
EOF
hermes keys add --chain ${CHAIN_ID_A} --mnemonic-file $HOME/.hermes/${CHAIN_ID_A}.mnemonic
MNEMONIC_B='24-word mnemonic seed'
CHAIN_ID_B='osmosis-1'
sudo tee $HOME/.hermes/${CHAIN_ID_B}.mnemonic > /dev/null <<EOF
${MNEMONIC_A}
EOF
hermes keys add --chain ${CHAIN_ID_B} --mnemonic-file $HOME/.hermes/${CHAIN_ID_B}.mnemonic
Ensure this wallet has funds in both HEART
and OSMO
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 '/root/.hermes/config.toml'
INFO ThreadId(01) running Hermes v1.7.4
SUCCESS "configuration is valid"
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 '/root/.hermes/config.toml'
INFO ThreadId(01) running Hermes v1.7.4
INFO ThreadId(01) health_check{chain=osmosis-1}: performing health check...
WARN ThreadId(06) health_check{chain=osmosis-1}: Will use fallback value for max_block_time: `30s`. Error: response error: Internal error: genesis response is large, please use the genesis_chunked API instead (code: -32603)
INFO ThreadId(01) health_check{chain=osmosis-1}: chain is healthy
INFO ThreadId(01) health_check{chain=humans_1089-1}: performing health check...
INFO ThreadId(11) health_check{chain=humans_1089-1}: Updated `max_block_time` using /genesis endpoint. Old value: `30s`, new value: `30s`
INFO ThreadId(01) health_check{chain=humans_1089-1}: chain is healthy
SUCCES performed health check for all chains in the config
When your nodes are fully synced, you can start the hermes daemon:
sudo tee /etc/systemd/system/hermesd.service > /dev/null <<EOF
[Unit]
Description=Hermes
After=network.target
[Service]
User=root
Type=simple
ExecStart=/root/.cargo/bin/hermes start
Restart=on-failure
LimitNOFILE=4096
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable hermesd
systemctl start hermesd
Watch hermes's output for successfully relayed packets, or any errors. It will try and clear any unreceived packets after startup has completed.
journalctl -u hermesd -fo cat