Build the topology

At this point in the tutorial, you should have four chains running and Hermes correctly configured. You can perform a health-check with the command :

hermes health-check

If the command runs successfully, it should output something similar to:

2022-08-23T15:54:58.150005Z INFO ThreadId(01) using default configuration from '$HOME/.hermes/config.toml' 2022-08-23T15:54:58.150179Z INFO ThreadId(01) [ibc-0] performing health check... 2022-08-23T15:54:58.163298Z INFO ThreadId(01) chain is healthy chain=ibc-0 2022-08-23T15:54:58.163323Z INFO ThreadId(01) [ibc-1] performing health check... 2022-08-23T15:54:58.169132Z INFO ThreadId(01) chain is healthy chain=ibc-1 2022-08-23T15:54:58.169154Z INFO ThreadId(01) [ibc-2] performing health check... 2022-08-23T15:54:58.178418Z INFO ThreadId(01) chain is healthy chain=ibc-2 2022-08-23T15:54:58.178445Z INFO ThreadId(01) [ibc-3] performing health check... 2022-08-23T15:54:58.184615Z INFO ThreadId(01) chain is healthy chain=ibc-3 SUCCESS performed health check for all chains in the config

In the following tutorial, we will connect all of these chains in a full mesh topology, then use Packet filters to simulate the topology given at the beginning of the previous section.

NOTE: It is also possible to only create the channels that you want. However, in production, anyone can open channels and recreate a fully-connected topology.


Connect all the chains

Execute the following command:

gm hermes cc

If this command runs successfully, it should output the following:

"$HOME/hermes/target/release/hermes" create channel --a-chain ibc-0 --b-chain ibc-1 --a-port transfer --b-port transfer --new-client-connection "$HOME/hermes/target/release/hermes" create channel --a-chain ibc-0 --b-chain ibc-2 --a-port transfer --b-port transfer --new-client-connection "$HOME/hermes/target/release/hermes" create channel --a-chain ibc-0 --b-chain ibc-3 --a-port transfer --b-port transfer --new-client-connection "$HOME/hermes/target/release/hermes" create channel --a-chain ibc-1 --b-chain ibc-2 --a-port transfer --b-port transfer --new-client-connection "$HOME/hermes/target/release/hermes" create channel --a-chain ibc-1 --b-chain ibc-3 --a-port transfer --b-port transfer --new-client-connection "$HOME/hermes/target/release/hermes" create channel --a-chain ibc-2 --b-chain ibc-3 --a-port transfer --b-port transfer --new-client-connection

Executing these commands will:

  • For every pair of chains, create a client on both chain tracking the state of the counterparty chain.
  • Create a connection between these two clients.
  • Create a transfer channel over this connection.

Use the flag --exec flag to execute these commands:

gm hermes cc --exec

At this point, your network should be fully connected. It is now time to filter channels. The following chart shows the current state of the network. The channels that we want to filter out are filled in red while the channels we want to relay on are filled in green:

Network topology

ibc-0
channel-0
channel-1
channel-2
ibc-1
channel-0
channel-1
channel-2
ibc-2
channel-0
channel-1
channel-2
ibc-3
channel-0
channel-1
channel-2

You can verify that everything is correct with the commands:

hermes query channels --show-counterparty --chain ibc-0 hermes query channels --show-counterparty --chain ibc-1 hermes query channels --show-counterparty --chain ibc-2 hermes query channels --show-counterparty --chain ibc-3

Which should normally output:

ibc-0: transfer/channel-0 --- ibc-1: transfer/channel-0 ibc-0: transfer/channel-1 --- ibc-2: transfer/channel-0 ibc-0: transfer/channel-2 --- ibc-3: transfer/channel-0 ibc-1: transfer/channel-0 --- ibc-0: transfer/channel-0 ibc-1: transfer/channel-1 --- ibc-2: transfer/channel-1 ibc-1: transfer/channel-2 --- ibc-3: transfer/channel-1 ibc-2: transfer/channel-0 --- ibc-0: transfer/channel-1 ibc-2: transfer/channel-1 --- ibc-1: transfer/channel-1 ibc-2: transfer/channel-2 --- ibc-3: transfer/channel-2 ibc-3: transfer/channel-0 --- ibc-0: transfer/channel-2 ibc-3: transfer/channel-1 --- ibc-1: transfer/channel-2 ibc-3: transfer/channel-2 --- ibc-2: transfer/channel-2

Add packet filters

Let's use packet filters to relay only on the green paths specified in the chart. In order to add filters, open your default configuration file $HOME/.hermes/config.toml and add:

  • Under ibc-0's config:
    [chains.packet_filter] policy = 'allow' list = [ ['transfer', 'channel-0'], ['transfer', 'channel-2'], ]
  • Under ibc-1's config:
    [chains.packet_filter] policy = 'allow' list = [ ['transfer', 'channel-0'], ['transfer', 'channel-1'], ]
  • Under ibc-2's config:
    [chains.packet_filter] policy = 'allow' list = [ ['transfer', 'channel-1'], ['transfer', 'channel-2'], ]
  • Under ibc-3's config:
    [chains.packet_filter] policy = 'allow' list = [ ['transfer', 'channel-0'], ['transfer', 'channel-2'], ]

NOTE: It is also possible to use a deny policy to filter out the channels you do not want to relay on. However, if other channels exist or are created, Hermes will also relay on them.

At this point, your config file should look like this:

config.toml
[global] log_level = 'info' [mode] [mode.clients] enabled = true refresh = true misbehaviour = true [mode.connections] enabled = true [mode.channels] enabled = true [mode.packets] enabled = true clear_interval = 100 clear_on_start = true tx_confirmation = true [telemetry] enabled = true host = '127.0.0.1' port = 3001 [[chains]] id = 'ibc-0' type = 'CosmosSdk' rpc_addr = 'http://localhost:27050' grpc_addr = 'http://localhost:27052' event_source = { mode = 'push', url = 'ws://localhost:27050/websocket', batch_delay = '200ms' } rpc_timeout = '15s' trusted_node = true account_prefix = 'cosmos' key_name = 'wallet' store_prefix = 'ibc' gas_price = { price = 0.001, denom = 'stake' } gas_multiplier = 1.2 default_gas = 1000000 max_gas = 10000000 max_msg_num = 30 max_tx_size = 2097152 clock_drift = '5s' max_block_time = '30s' trusting_period = '14days' trust_threshold = { numerator = '2', denominator = '3' } [chains.packet_filter] policy = 'allow' list = [ ['transfer', 'channel-0'], ['transfer', 'channel-2'], ] [[chains]] id = 'ibc-1' type = 'CosmosSdk' rpc_addr = 'http://localhost:27060' grpc_addr = 'http://localhost:27062' event_source = { mode = 'push', url = 'ws://localhost:27060/websocket', batch_delay = '200ms' } rpc_timeout = '15s' trusted_node = true account_prefix = 'cosmos' key_name = 'wallet' store_prefix = 'ibc' gas_price = { price = 0.001, denom = 'stake' } gas_multiplier = 1.2 default_gas = 1000000 max_gas = 10000000 max_msg_num = 30 max_tx_size = 2097152 clock_drift = '5s' max_block_time = '30s' trusting_period = '14days' trust_threshold = { numerator = '2', denominator = '3' } [chains.packet_filter] policy = 'allow' list = [ ['transfer', 'channel-0'], ['transfer', 'channel-1'], ] [[chains]] id = 'ibc-2' type = 'CosmosSdk' rpc_addr = 'http://localhost:27070' grpc_addr = 'http://localhost:27072' event_source = { mode = 'push', url = 'ws://localhost:27070/websocket', batch_delay = '200ms' } rpc_timeout = '15s' trusted_node = true account_prefix = 'cosmos' key_name = 'wallet' store_prefix = 'ibc' gas_price = { price = 0.001, denom = 'stake' } gas_multiplier = 1.2 default_gas = 1000000 max_gas = 10000000 max_msg_num = 30 max_tx_size = 2097152 clock_drift = '5s' max_block_time = '30s' trusting_period = '14days' trust_threshold = { numerator = '2', denominator = '3' } [chains.packet_filter] policy = 'allow' list = [ ['transfer', 'channel-1'], ['transfer', 'channel-2'], ] [[chains]] id = 'ibc-3' type = 'CosmosSdk' rpc_addr = 'http://localhost:27080' grpc_addr = 'http://localhost:27082' event_source = { mode = 'push', url = 'ws://localhost:27080/websocket', batch_delay = '200ms' } rpc_timeout = '15s' trusted_node = true account_prefix = 'cosmos' key_name = 'wallet' store_prefix = 'ibc' gas_price = { price = 0.001, denom = 'stake' } gas_multiplier = 1.2 default_gas = 1000000 max_gas = 10000000 max_msg_num = 30 max_tx_size = 2097152 clock_drift = '5s' max_block_time = '30s' trusting_period = '14days' trust_threshold = { numerator = '2', denominator = '3' } [chains.packet_filter] policy = 'allow' list = [ ['transfer', 'channel-0'], ['transfer', 'channel-2'], ]

It is also possible to check that the configuration file is valid with the command:

hermes config validate

If the command runs successfully, the output should be:

SUCCESS "configuration is valid"

Next Steps

The following section describes how to relay packets between any chain with this topology.