Bootstrap sequence
Identity lifecycle
- iroh NodeId — ephemeral per session. Clients rotate NodeIds on session boundaries to break linkability across subscriptions (privacy).
- Ethereum address — persistent. Identifies channel ownership and settlement.
- Ephemeral NodeId↔Ethereum binding — per-connection, with
nonce=0as a sentinel indicating ephemeral (not slashable) binding.
StakingRegistry. There’s no on-chain identity for clients.
Registry query with retry
Primary source: the on-chainStakingRegistry via your configured RPC provider. Query paginated to keep gas/bandwidth bounded.
Retry policy: exponential backoff with jitter. After N retries, fall back to the bundled peers.json.
peers.json fallback
A bundled static list of known-good peers. Used only if the registry is unreachable — once you have any working peer, they can gossip-announce others and the peer table fills in.
Multi-source bootstrap
The client queries three independent sources:- On-chain registry (primary).
- DNS seed list (
_decdn._tcp.seeds.decdn.net) returning a handful of entry points. - Operator-provided static list (optional, configured by advanced users).
Gossip subscription
Three topics:cdn/global/v1— globalNodeAnnounce,RateChange,WatchtowerAnnounce.cdn/region/{cc}/v1— regionalNodeAnnouncefor the region you configured.cdn/reputation/v1— reputation reports.
Periodic refresh
The client re-queries the registry periodically (default: every 10 minutes) to pick up:- Newly registered nodes.
- Newly deregistered nodes (removed from selection).
- Multiaddr updates (nodes that rebooted on new IPs).
NodeAnnounce messages are received in near-real-time.
Peer table
The peer table holds:- NodeInfo — from registry (ed25519 NodeId, multiaddrs, Ethereum address, region).
- Rate — from most recent
NodeAnnounceorRateChange. - Local reputation — observed from direct interactions.
- Gossip reputation — aggregated from
cdn/reputation/v1. - Load hint — from recent
NodeAnnounceorProbeResponse.
Eclipse attack posture
| Threat | Mitigation |
|---|---|
| RPC provider returns fabricated nodes | Multi-source bootstrap — 2-of-3 agreement required |
| Gossip-only view of an attacker’s island | Minimum peer-operator diversity + multi-source bootstrap |
| NodeId squatting | On-chain ed25519 ownership proof enforced at registration |
Observability
Clients expose a small set of metrics:decdn_client_peer_table_sizedecdn_client_registry_refresh_secondsdecdn_client_bootstrap_fallback_total— incremented wheneverpeers.jsonfallback is hit (a signal your RPC is flaky)decdn_client_channels_open,decdn_client_vouchers_signed_totaldecdn_client_bytes_received_total,decdn_client_verification_failures_total
decdn_client_verification_failures_total > 0 indicates a node sent bytes that didn’t match the BLAKE3 hash. The stream is cancelled automatically, but an elevated rate may indicate a targeted attack or a buggy peer.