| title | Run a standalone attestor |
|---|---|
| description | Run an attestor in its own process, separate from any relayer, so a relayer can query it and count its signatures toward a light client's quorum. |
This guide runs an attestor as its own process, serving one chain. A relayer can then query it and count its signatures toward a light client's quorum.
In order to run a standalone attestor, your signing address must already be in the light client's attestation set, which is fixed when the client is deployed and read from the chain.
You need:
- A chain with IBC deployed, and a light client tracking it. This guide continues from the tutorial.
- Your signing address already in that client's attestation set.
- Your signing key.
- The chain's RPC endpoint and its router address. Configuration validation treats the router address as optional, but the process cannot start without it.
- Go 1.26.4 or later and a build of the binary.
The commands below continue from the tutorial. They move the attestor keys it generated into processes of their own, reading values from your own deployment rather than asking you to copy one.
Warning: Stop the tutorial's relayer before you start, with
Ctrl+Cin its terminal. It hosts both attestors inside its own process, and this guide gives those same attestors processes of their own.
Create a second configuration file alongside the tutorial's:
./bin/ibc config new --config ibc-attestor-41002.ymlIt shares the tutorial's keystore, so the attestor key generated there is already available. That key's address matches the one in the client's attestation set.
Warning: An attestor address must never appear in more than one client's attestation set. The signed attestation carries no domain separation, so a signature made for one client can be replayed against another.
Write the attestor's configuration file, reading the router address and your own signing address from the deployment:
cat > ~/.ibc/ibc-attestor-41002.yml <<EOF
server:
listenAddr: 0.0.0.0:3001
chains:
- chainId: "41002"
evm:
rpc: http://localhost:8745
ics26Router: "$(./bin/ibc deploy show 41002 | jq -r '.core.router')"
attestors:
- name: attestor-41002
type: local
chainId: "41002"
signer: attestor-41002
finalityOffset: 1
signers:
- alias: attestor-41002
type: local
file: attestor-41002
EOFAn attestor's name is attestor-<chain it watches>.
Warning: The attestor's name has to match the name the relayer uses for it. A relayer sends that name in every query, and the process serves its attestors by name, so a mismatch makes every lookup fail.
A finality offset of 1 signs one block behind the chain head. Zero waits for the chain's own finalized block instead.
- Validate the configuration:
./bin/ibc config validate --config ibc-attestor-41002.yml --strict{
"status": "valid"
}- Start the process in a new terminal, and leave it running:
./bin/ibc attestor run --config ibc-attestor-41002.ymllevel=INFO msg="Starting attestor" module=bootstrap
level=INFO msg=Readiness module=bootstrap readiness="{Event:ready HTTP:[::]:3001}"
That readiness line names the address it bound.
- Back in your first terminal, ask the process what its address is:
./bin/ibc attestor info attestor-41002 --host 127.0.0.1:3001{
"chainId": "41002",
"address": "0xc7f148Da846781a9a1D9d22F699A7A88c592CCee"
}This should be the address of the attestor.
- Ask how far it can attest:
./bin/ibc attestor latest-height attestor-41002 --host 127.0.0.1:3001{
"height": "25509"
}This shows the attestor's latest height.
The tutorial this guide follows generated one attestor per chain. The following steps repeat the process to create an attestor for chain 41001, in its own configuration file on port 3003. Port 3002 is left free for the relayer in the next guide.
- Create a third configuration file:
./bin/ibc config new --config ibc-attestor-41001.yml- Write its configuration:
cat > ~/.ibc/ibc-attestor-41001.yml <<EOF
server:
listenAddr: 0.0.0.0:3003
chains:
- chainId: "41001"
evm:
rpc: http://localhost:8545
ics26Router: "$(./bin/ibc deploy show 41001 | jq -r '.core.router')"
attestors:
- name: attestor-41001
type: local
chainId: "41001"
signer: attestor-41001
finalityOffset: 1
signers:
- alias: attestor-41001
type: local
file: attestor-41001
EOF- Start it in another terminal:
./bin/ibc attestor run --config ibc-attestor-41001.ymllevel=INFO msg="Starting attestor" module=bootstrap
level=INFO msg=Readiness module=bootstrap readiness="{Event:ready HTTP:[::]:3003}"
Both attestors now run in processes of their own, and no relayer is running.
A relayer references your attestor by name and network address:
attestors:
- name: attestor-41002
type: remote
grpc: 127.0.0.1:3001- Run a standalone relayer brings up a relayer that queries these attestors instead of hosting its own.