Node Configuration
Node configs live in config/node/node1.toml, node2.toml, node3.toml. Each file configures one validator.
Full example
# Identity / network
blockchain_name = "clutch-node-test-1"
libp2p_topic_name = "test-net"
# Validator keys (keep secret_key secure — never commit)
author_public_key = "0x9b6e8af0c70..."
author_secret_key = "0x<validator-private-key>"
# All validator public keys — must match across every node
authorities = [
"0x9b6e8af0c70...",
"0x<validator-2-pubkey>",
"0x<validator-3-pubkey>",
]
# Networking
websocket_addr = "0.0.0.0:8081"
listen_addrs = ["/ip4/0.0.0.0/tcp/4001"]
bootstrap_nodes = [] # node1 is the bootstrap; node2/3 set ["..."]
# Consensus parameters — committed to state by the genesis ChainInit transaction.
# Must be byte-for-byte identical across every node (see below).
chain_id = 2077
is_testnet = true
tx_fee = 1000
mint_authority = "0x9b6e8af0c70..."
faucet_address = "0xdeb4cfb63db134698e1879ea24904df074726cc0"
faucet_allocation = 0
ride_request_referrer_fee_bps = 200
ride_offer_referrer_fee_bps = 200
ride_auto_release_secs = 300 # 0 turns the rule off
# mint_cosigners = ["0x...", "0x..."] # optional, for multi-signature minting
# mint_threshold = 2
# Observability
serve_metric_addr = "0.0.0.0:3001"
seq_url = "http://seq:80"
Key settings
| Setting | Description | Example |
|---|---|---|
libp2p_topic_name | Network gossip topic | test-net |
blockchain_name | Chain identifier | clutch-node-test-1 |
author_public_key | Validator public key | 0x9b6e8af... |
author_secret_key | Validator secret (keep secure) | — |
developer_mode | Deletes the on-disk database on every graceful shutdown — see the danger note below | true in clutch-node's own configs; false in every clutch-deploy config |
websocket_addr | WebSocket JSON-RPC bind | 0.0.0.0:8081 |
listen_addrs | libp2p listen addresses | ["/ip4/0.0.0.0/tcp/4001"] |
bootstrap_nodes | Peers to dial on startup | ["/ip4/127.0.0.1/tcp/4001"] (node2/3) |
authorities | Ordered list of validator public keys | Must match across nodes |
block_authoring_enabled | Whether this node runs the block-authoring job (participates as an active validator) | true |
chain_id | Network identifier, signed into every transaction | 2077 |
is_testnet | Gates the genesis faucet allocation, and node startup with one configured | true |
tx_fee | Flat CLT fee per non-exempt transaction, paid to the block author | 1000 (= $0.001) |
mint_authority | The only address permitted to sign a Mint transaction | validator or dedicated treasury key |
faucet_address | Address the genesis faucet allocation is credited to | 0xdeb4cfb6... |
faucet_allocation | CLT credited to faucet_address at genesis, only if is_testnet = true | 0 — genesis pre-mints nothing |
ride_request_referrer_fee_bps | Request referrer fee on each RidePay, in basis points | 200 (2%) |
ride_offer_referrer_fee_bps | Offer referrer fee on each RidePay, in basis points | 200 (2%) |
ride_auto_release_secs | Seconds after a RideAcceptance after which a cancel pays the held fare to the driver instead of refunding the rider. 0 turns the rule off. See Ride Lifecycle | 300 on the testnet, 7200 on the mainnet |
mint_cosigners | Further addresses allowed to sign or approve a Mint, on top of mint_authority | empty: one signer |
mint_threshold | Distinct authority signatures a Mint needs. 0 and 1 both mean one | 0 |
wallet_chain_id | The EIP-155 chain id wallets sign with; with the next setting it turns on wallet transfers. Must equal the Hub API's wallet_chain_id | 20771 on the testnet; unset (off) by default |
wallet_transfers_from_block | The first block that may carry a wallet transfer. Set both or neither: the node refuses to start with one | 0 on the testnet |
sync_enabled | Whether this node runs the peer-sync job (pulls blocks from peers) | true |
serve_metric_enabled | Whether the Prometheus /metrics endpoint is served at all | true |
serve_metric_addr | Prometheus metrics bind | 0.0.0.0:3001 |
log_level | Tracing log verbosity | info |
seq_url | Seq logging URL | http://seq:80 |
developer_mode = true — the value in clutch-node's own configs, including default.toml, and in none of clutch-deploy's — makes the node delete its entire on-disk database on every graceful shutdown (shutdown_blockchain → cleanup_db in blockchain.rs). That's the intended behavior for a scratch chain that starts fresh each run, and catastrophic for one whose data is meant to survive a restart: a month of stage outages were mistakenly blamed on volumes and the deploy script before anyone traced the actual cause to this flag.
The escape hatch is the DB_PATH environment variable: if it's set, the node treats that as a sign the data is meant to outlive the process, logs a warning, and refuses to delete rather than honoring developer_mode. Set DB_PATH (or developer_mode = false) before running against any volume whose contents you care about.
There is no block_reward_amount key anymore, and no CLT is minted per block. Validators are compensated from tx_fee revenue instead — see CLT Economics. A config file left over from before this release that still sets block_reward_amount will simply have that key ignored; the node no longer reads it.
JSON-RPC exposure
websocket_addr binds 0.0.0.0 in every shipped config, and the WebSocket JSON-RPC server performs no authentication and no Origin check: any caller that can reach the port can call send_raw_transaction, every read method, and everything else on the RPC surface with no credential at all. It also never inspects the request path before completing the WebSocket handshake — /ws in this doc and in JSON-RPC Reference is a convention the examples follow, not a route the server enforces; any path completes the same handshake.
That is the right default for a testnet whose entire purpose is letting anyone submit transactions freely. It stops being safe the moment the port is reachable from anywhere untrusted — at that point it needs a reverse proxy or a firewall in front of it, because the node itself enforces nothing at this layer. See Security — Threat model.
Consensus parameters must match across every node
chain_id, is_testnet, tx_fee, mint_authority, mint_cosigners, mint_threshold, faucet_address, faucet_allocation, ride_auto_release_secs, and the two referrer-fee bps rates are not just per-node preferences — they are written into the chain's state by a single ChainInit transaction (RLP tag 9) at block 0, and that transaction's hash feeds the genesis block hash. Peers compare genesis hashes during the p2p handshake: a node whose config produces a different genesis hash is refused outright, not silently allowed to fork.
Practically, this means:
- All three node TOMLs (
node1.toml,node2.toml,node3.toml, and their-dockervariants) must carry identical values for every consensus-parameter key above. - Changing any of these values on an existing chain is equivalent to starting a new chain — the new genesis hash will not match any existing peer's, and no amount of retrying will make them sync.
- This is a deliberate fix: these parameters used to be per-node local config with no cross-node consistency check, which meant two misconfigured nodes could silently diverge instead of failing to connect. Now the failure is loud and immediate — a mismatched node simply never syncs.
Wallet transfers: same rule on every validator, set before its block
wallet_chain_id and wallet_transfers_from_block are not in genesis, so changing them does not start a new chain, but they decide whether a block is valid. A validator without them refuses a block that carries a wallet transfer, so all validators of a chain must carry the same two values before wallet_transfers_from_block is reached. On a running chain with real balances, switch it on as a rolling upgrade: pick a block comfortably ahead of the current height, restart each validator with the new image and the two settings, one at a time, and check all of them carry the setting before that block arrives. On a chain where every validator restarts at once, 0 is enough, because no earlier block can hold a wallet transfer.
Key settings
- Node 1 (bootstrap): leave
bootstrap_nodes = []. It is the seed other nodes dial. - Node 2 / Node 3: point
bootstrap_nodesat node1. The checked-innode2.toml/node3.tomluse["/ip4/127.0.0.1/tcp/4001"]for all three nodes on one host; the container variantsnode2-docker.toml/node3-docker.tomluse["/dns4/node1/tcp/4001"]so Docker DNS resolves the peer. authoritiesmust be identical on every node, in the same order. Aura schedules block authors by position in this list.- Validator keys: generate a secp256k1 keypair per node.
author_public_keygoes inauthoritiesfor every node;author_secret_keystays on the node that authors. mint_authoritydoes not need to be a validator key — a production deployment should use a dedicated treasury key from a proper key ceremony, never a validator'sauthor_secret_key. The checked-in testnet config reuses node1's dev key purely for local convenience.- Genesis: testnet genesis allocates
faucet_allocationCLT tofaucet_address, but only whenis_testnet = true— on any other chain, faucet allocation is forced to zero regardless of whatfaucet_allocationsays, and the node refuses to boot at all ifis_testnet = falsewith a nonzerofaucet_allocationconfigured. This deployment sets it to0anyway, so genesis pre-mints nothing on any chain: see CLT Economics — Testnet notes for why an unbacked genesis balance stopped being acceptable once redemptions went live. Do not changeblockchain_nameon a running chain — it would fork. - Secret management: store
author_secret_keyvia environment or a secret manager in production; never commit it to git.
Multi-node checklist
- Same
authoritieslist (same order) on all nodes - Same
libp2p_topic_nameandblockchain_name - Same
chain_id,is_testnet,tx_fee,mint_authority,mint_cosigners,mint_threshold,faucet_address,faucet_allocation,ride_auto_release_secs, and both referrer-fee bps rates on all nodes — a mismatch here prevents peering entirely - Same
wallet_chain_idandwallet_transfers_from_blockon all validators, or both unset everywhere - Node 1 has empty
bootstrap_nodes; others point to node 1 - Distinct ports per node (8081/8082/8083, 4001/4002/4003, 3001/3002/3003)
- Validator secret keys kept out of source control
Related
- Running Clutch Node
- Overview
- CLT Economics — the peg, fee model, and Mint/Burn
- Transaction Types
- Security — Threat model — the RPC exposure threat and its mitigation