Run a node
Install, configure and start an SCL node, then confirm it is in sync with the rest of the network. You do not need a local Bitcoin node.
#Install
- Install Rust and Cargo.
- Clone scl-node (opens in a new tab) and build the release binary with
cargo build --release. The binary lands attarget/release/scl-node. - Keep it alongside a writable data directory for state and logs.
You do not need a local Bitcoin node: chain data is read from an Esplora (opens in a new tab) endpoint over HTTP.
#Configure
Configuration comes from a config.toml next to the binary, from environment variables, or both; environment variables override the file. All fields have working defaults.
Example config.toml:
node_id = "my-node"
rest_address = "0.0.0.0:8080" # client-facing REST API
bind_address = "0.0.0.0:50051" # gRPC: peer sync and gossip
url = "http://my-node.example:50051" # public gRPC URL advertised to peers
peers = ["http://node1.example:50051", "http://node2.example:50051"]
esplora = "https://blockstream.info/api"
db_path = "./data/scl-node"
data_dir = "./data"
peer_limit = 10
# Optional: stable Ed25519 identity for signing gossip (64 hex chars).
# Omit for an ephemeral identity.
gossip_private_key = ""
# Optional: bearer token protecting private endpoints
# (confirmed-call log, admin operations). Omit to leave them locked.
api_token = ""The equivalent environment variables:
| Variable | Default | Purpose |
|---|---|---|
SCL_NODE_ID | scl-node-1 | Node identifier |
SCL_REST_ADDRESS | 0.0.0.0:8080 | REST API bind |
SCL_BIND_ADDRESS | 0.0.0.0:50051 | gRPC bind |
SCL_PUBLIC_URL | http://localhost:50051 | Public gRPC URL advertised to peers |
SCL_PEERS | empty | Comma-separated peer gRPC URLs |
SCL_PEER_LIMIT | 10 | Max peers for gossip forwarding |
SCL_ESPLORA_URL | https://blockstream.info/api | Esplora API base (set a testnet URL for testnet) |
SCL_DB_PATH | data/scl-node | Database path |
SCL_GOSSIP_PRIVATE_KEY | empty | Ed25519 seed for a stable gossip identity |
SCL_API_TOKEN | empty | Bearer token for private endpoints |
RUST_LOG | info | Log filter |
#Start
./scl-nodeThere are no subcommands; configuration fully determines behavior. A docker-compose.yml in the repository runs a single node with persistent data if you prefer containers.
On startup your node:
- Initializes local storage.
- Fetches the current Bitcoin height from Esplora and anchors its block journal.
- Reloads the contract registry.
- Syncs with peers using Merkle-based diffing.
- Then serves requests, gossips payloads, and watches Bitcoin for new blocks (checking every 60 seconds, with a full peer sync every 5 minutes).
Health check:
curl -i http://localhost:8080/health
# Expect: HTTP/1.1 200 OK
curl http://localhost:8080/node_status#Verify you're in sync
Compare state roots with another node; matching roots at the same height prove matching state:
curl http://localhost:8080/v2/state_rootFor the full REST and gRPC surface, see the Node API reference. Treat the REST surface as current implementation, not a stable public API.
#Validator seats
Anyone can run a node and replay the network. Validator seats on the canonical ledger, which co-sign state roots and earn from the emission pool, are accredited: they are admitted by governance and carry obligations to replay, publish state roots and operate network infrastructure. See Validators and the canonical ledger and XRB and network economics.