This step starts two services: the relayer (cosmos/ibc-relayer) and the Proof API. Both need configs which are rendered from templates in this demo. The relayer also needs a funded signing key on both chains and a Postgres database for packet state. Run the following:Documentation Index
Fetch the complete documentation index at: https://docs.cosmos.network/llms.txt
Use this file to discover all available pages before exploring further.
lib/ibc.sh
Relayer
The relayer delivers IBC packets between chains. For each packet, it submits aMsgRecvPacket transaction to the destination chain to deliver it, or a MsgTimeout transaction to the source chain if the packet expires before delivery. It is request-driven: a client submits a source transaction hash, the relayer identifies the packets created by that transaction by reading IBC events from the chain, queries the Proof API for attestation proofs, and submits the relay transaction.
The relayer has three components: a gRPC API server (used to trigger relays and track packet status), a Postgres database (packet state persistence), and a core relay dispatcher (monitors the database and processes relay jobs).
Proof API
The Proof API is a stateless gRPC transaction generation service. The relayer calls it with a source transaction hash and the Proof API:- Queries the source chain for that transaction and parses its IBC events
- Collects attestor signatures and verifies the quorum threshold is met
- Builds the full IBC message (
RecvPacket,AckPacket,Timeout) with the proof embedded - Returns an unsigned transaction payload to the relayer
cosmos_to_eth and eth_to_cosmos. Each module queries the attestor watching its source chain.
What the relayer script does
- Resolve the relayer wallet: reads the relayer’s bech32 address from the Cosmos keyring. This address is used in the Proof API config so the proof API can scope proof queries to this signer.
- Render the relayer config: exports the Cosmos private key and renders
keys.jsonandconfig.ymlfrom templates. - Render the Proof API config: renders
relayer.jsonfrom its template. - Start Postgres and run migrations: waits for the database to be ready, then runs schema migrations.
- Start the relayer and Proof API.
Relayer key setup
The relayer signs transactions on both chains and needs funded accounts on each. In the demo, the relayer uses a dedicatedrelayer key in the Cosmos keyring, pre-funded during chain setup.
For a production deployment, you’ll need to create a dedicated relayer key on each chain and fund it with enough gas to cover relay transactions:
- Cosmos side: the relayer submits
MsgRecvPacket,MsgAcknowledgement, andMsgTimeouttransactions. Fund the account with the chain’s fee denom. - EVM side: the relayer calls
recvPacket,ackPacket, andtimeoutPacketon theICS26Routercontract. Fund the account with the chain’s native token (ETH or equivalent).
Configuration
Relayer
The relayer config is rendered fromibc/relayer-config.yml.tmpl. The signing keys file is rendered from ibc/relayer-keys.json.tmpl. For EVM chains the key is a hex-encoded ECDSA private key; for Cosmos chains it is a hex-encoded secp256k1 private key.
Below is an example of the relayer config for this demo:
Proof API
The Proof API config is rendered fromibc/proof-api.json.tmpl. Each entry in modules is a directional routing unit that handles one transfer direction and knows which attestor to query for that direction’s source chain. The cosmos_to_eth module queries the Cosmos attestor for Cosmos state; eth_to_cosmos queries the EVM attestor for EVM state.
Below is an example of the Proof API config for this demo:
Applying this to your own setup
Relayer key funding
The relayer needs sufficient gas on both chains to submit transactions continuously. The relayer exposes gas balance metrics and supports configurable alert thresholds (signer_gas_alert_thresholds) per chain in config.yml:
Signing
The demo uses local signing viakeys.json. For production, the relayer supports a remote gRPC signing service that keeps private keys isolated from the relayer process. Replace keys_path in the signing block of config.yml with:
grpc_address takes precedence over keys_path if both are set. See the ibc-relayer README for the signer service proto interface.
Finality offset
finality_offset controls when the relayer considers a packet commitment on an EVM source chain to be finalized and safe to relay. If omitted, the relayer uses the chain’s native finalized block tag. If set, the relayer subtracts that many blocks from the latest block to determine finality.
This value should match the finality assumption your attestor is configured with. If the configurations don’t match, the relayer may attempt to generate a proof for a height the attestors do not yet consider finalized.
The demo sets this to 0 because Besu’s single-validator QBFT produces instant finality. Both configs must match:
config.yml
finality_offset in the EVM attestor-config.toml:
counterparty_chains
Theibcv2.counterparty_chains field maps client IDs on a chain to their counterparty chain IDs. The relayer only relays packets for connections listed here: