Warning
The code is a work in progress and not production ready yet. Breaking changes may occur in the code updates as well as backward compatibility is not guaranteed. Use with caution.
The Symbiotic Relay operates as a distributed middleware layer that facilitates:
- Validator Set Management: Derives and maintains validator sets across different epochs based on on-chain state
- Signature Aggregation: Collects individual validator signatures and aggregates them using BLS signatures or zero-knowledge proofs
- Cross-Chain Coordination: Manages validator sets across multiple EVM-compatible blockchains
The relay consists of several key components:
- P2P Layer: Uses libp2p with GossipSub for decentralized communication
- Signer Nodes: Sign messages using BLS/ECDSA keys
- Aggregator Nodes: Collect and aggregate signatures with configurable policies
- Committer Nodes: Submit aggregated proofs to settlement chains
- API Server: Exposes gRPC API for external clients
For detailed architecture information, see DEVELOPMENT.md.
- Development Guide - Comprehensive guide for developers including testing, API changes, and code generation
- Relay Docs - Official documentation
- CLI Documentation - Command-line interface reference for relay_sidecar and relay_utils
- Contributing - Contribution guidelines and workflow
For a complete end-to-end example application using the relay, see:
Symbiotic Super Sum - A task-based network example demonstrating relay integration
The relay exposes both gRPC and HTTP/JSON REST APIs for interacting with the network:
- API Documentation: docs/api/v1/doc.md
- Proto Definitions: api/proto/v1/api.proto
- Go Client: api/client/v1/
- Client Examples: api/client/examples/
The relay includes an optional HTTP/JSON REST API gateway that translates HTTP requests to gRPC:
- Swagger File: docs/v1/api.swagger.json
- OpenAPI/Swagger Spec: Available at
/docs/api.swagger.jsonwhen enabled - Endpoints: All gRPC methods accessible via RESTful HTTP at
/api/v1/*
Enable via configuration:
api:
http-gateway: trueOr via command-line flag:
./relay_sidecar --api.http-gateway=true- Go: Included in this repository at
github.com/symbioticfi/relay/api/client/v1 - TypeScript: relay-client-ts
- Rust: relay-client-rs
- HTTP/cURL: Use the HTTP gateway for language-agnostic access
Instead of building from source, you can download pre-built binaries from GitHub releases:
# Download the latest release for your platform
# Linux AMD64
wget https://github.com/symbioticfi/relay/releases/latest/download/relay_sidecar_linux_amd64
wget https://github.com/symbioticfi/relay/releases/latest/download/relay_utils_linux_amd64
chmod +x relay_sidecar_linux_amd64 relay_utils_linux_amd64
# macOS ARM64
wget https://github.com/symbioticfi/relay/releases/latest/download/relay_sidecar_darwin_arm64
wget https://github.com/symbioticfi/relay/releases/latest/download/relay_utils_darwin_arm64
chmod +x relay_sidecar_darwin_arm64 relay_utils_darwin_arm64
# Run the binaries
./relay_sidecar_linux_amd64 --config config.yamlBrowse all releases at: https://github.com/symbioticfi/relay/releases
Pre-built Docker images are available from Docker Hub:
# Pull the latest image
docker pull symbioticfi/relay:latest
# Or pull a specific version
docker pull symbioticfi/relay:<tag>
# Run the relay sidecar
docker run -v $(pwd)/config.yaml:/config.yaml \
symbioticfi/relay:latest \
--config /config.yamlDocker Hub: https://hub.docker.com/r/symbioticfi/relay
- Go 1.24.3+
- Docker & Docker Compose (for local setup and E2E tests)
- Node.js & Foundry (for contract compilation in E2E)
Build the relay sidecar and utils binaries:
# For Linux
make build-relay-sidecar OS=linux ARCH=amd64
make build-relay-utils OS=linux ARCH=amd64
# For macOS ARM
make build-relay-sidecar OS=darwin ARCH=arm64
make build-relay-utils OS=darwin ARCH=arm64make image TAG=devSet up a complete local relay network with blockchain nodes and multiple relay sidecars:
make local-setupThis command:
- Builds the relay Docker image
- Sets up local blockchain nodes (Anvil)
- Deploys contracts
- Generates sidecar configurations
- Starts relay nodes in Docker
Customize the network using environment variables (see DEVELOPMENT.md for details):
OPERATORS=6 COMMITERS=2 AGGREGATORS=1 make local-setupNote: For a complete reference of all configuration options and command-line flags, see the relay_sidecar CLI documentation.
Create a config.yaml file with the following structure:
# Logging
log:
level: "debug" # Options: debug, info, warn, error
mode: "pretty" # Options: json, text, pretty
# Storage
storage-dir: ".data" # Directory for persistent data
circuits-dir: "" # Path to ZK circuits (optional, empty disables ZK proofs)
# API Server
api:
listen: ":8080" # API server address
verbose-logging: false # Enable verbose API logging
# Metrics (optional)
metrics:
listen: ":9090" # Metrics endpoint address
pprof: false # Enable pprof debug endpoints
# Driver Contract
driver:
chain-id: 31337 # Chain ID where driver contract is deployed
address: "0x..." # Driver contract address
# Secret Keys
secret-keys:
- namespace: "symb" # Namespace for the key
key-type: 0 # 0=BLS-BN254, 1=ECDSA
key-id: 15 # Key identifier
secret: "0x..." # Private key hex
- namespace: "evm"
key-type: 1
key-id: 31337
secret: "0x..."
- namespace: "p2p"
key-type: 1
key-id: 1
secret: "0x..."
# Alternatively, use keystore
# keystore:
# path: "/path/to/keystore.json"
# password: "your-password"
# Signal Configuration, used for internal messages and event queues
signal:
worker-count: 10 # Number of signal workers
buffer-size: 20 # Signal buffer size
# Cache Configuration, used for in memorylookups for db queries
cache:
network-config-size: 10 # Network config cache size
validator-set-size: 10 # Validator set cache size
# Sync Configuration, sync signatures and proofs over p2p to recover missing information
sync:
enabled: true # Enable P2P sync
period: 5s # Sync period
timeout: 1m # Sync timeout
epochs: 5 # Number of epochs to sync
# Key Cache, used for fast public key lookups
key-cache:
size: 100 # Key cache size
enabled: true # Enable key caching
# P2P Configuration
p2p:
listen: "/ip4/0.0.0.0/tcp/8880" # P2P listen address
bootnodes: # List of bootstrap nodes (optional)
- /dns4/node1/tcp/8880/p2p/...
dht-mode: "server" # Options: auto, server, client, disabled, default: server (ideally should not change)
mdns: true # Enable mDNS local discovery (useful for local networks)
# EVM Configuration
evm:
chains: # List of settlement chain RPC endpoints
- "http://localhost:8545"
- "http://localhost:8546"
max-calls: 30 # Max calls in multicall batches
# Aggregation Policy
aggregation-policy-max-unsigners: 50 # Max unsigners for low-cost policy
# Data Retention (optional)
# Controls how much historical data to keep on this node
retention:
valset-epochs: 0 # Number of historical epochs to retain on fresh node startup
# 0 = unlimited (sync from genesis)
# N > 0 = sync only last N epochs (for fresh nodes only)Control historical data sync for new nodes:
--retention.valset-epochs=20 # Keep only last 20 validator set epochs on fresh node startupImportant Notes:
- Only affects fresh nodes (no existing epoch data)
- Set to match your planned pruning retention period
- Must be >=
--sync.epochsif both are set - Does not backfill gaps if increased on existing node
You can override config file values with command-line flags:
./relay_sidecar \
--config config.yaml \
--log.level debug \
--storage-dir /var/lib/relay \
--api.listen ":8080" \
--p2p.listen "/ip4/0.0.0.0/tcp/8880" \
--driver.chain-id 1 \
--driver.address "0x..." \
--secret-keys "symb/0/15/0x...,evm/1/31337/0x..." \
--evm.chains "http://localhost:8545"Environment variables use the SYMB_ prefix with underscores instead of dashes and dots:
export SYMB_LOG_LEVEL=debug
export SYMB_LOG_MODE=pretty
export SYMB_STORAGE_DIR=/var/lib/relay
export SYMB_API_LISTEN=":8080"
export SYMB_P2P_LISTEN="/ip4/0.0.0.0/tcp/8880"
export SYMB_DRIVER_CHAIN_ID=1
export SYMB_DRIVER_ADDRESS="0x..."
./relay_sidecar --config config.yamlConfiguration is loaded in the following order (highest priority first):
- Command-line flags
- Environment variables (with
SYMB_prefix) - Configuration file (specified by
--config)
For reference, see how configurations are generated in the E2E setup:
# See the template in e2e/scripts/sidecar-start.sh (lines 11-27)
cat e2e/scripts/sidecar-start.shTo customize the local setup configuration, modify the template in e2e/scripts/sidecar-start.sh and run:
make local-setupOnce you have your configuration file ready:
./relay_sidecar --config config.yamlOr with Docker:
docker run -v $(pwd)/config.yaml:/config.yaml symbioticfi/relay:latest --config /config.yamlWe welcome contributions! Please read CONTRIBUTING.md for:
- Branching strategy and PR process
- Code style and linting requirements
- Testing requirements
For development workflows, API changes, and testing procedures, see DEVELOPMENT.md.