Skip to main content

Decision

All staked nodes form a flat mesh. Node metadata is broadcast over iroh-gossip on regional topics (cdn/region/{cc}/v1) and a global topic (cdn/global/v1). Content discovery uses a Kademlia subset (cdn/dht/v1) with broadcast probe fan-out as bootstrap/emergency fallback.

Gossip economics

NodeAnnounce messages are ~800 bytes with a 60-second default interval. Per-node gossip bandwidth scales linearly:
  • ~3 Kbps at 30 nodes
  • ~111 Kbps at 1,000 nodes
Beyond ~1,000 nodes a structured overlay or gossip partitioning becomes necessary. No content inventories are broadcast — no Bloom filters, no hash lists. Content discovery is on-demand via DHT.

Node selection algorithm

All selection decisions — client→node and node→node — use the same unified score:
score = rate_per_mb × rtt_ms × (1 / max(reputation, 0.1)²)
Lower is better. Rationale:
  • Rate — linear. You pay in proportion to what you consume.
  • Latency — linear. Round-trip cost is symmetric to price in user-perceived delivery time.
  • Reputation — inverse-square. A node with 0.5 reputation is 4× worse than one with 1.0. The max(..., 0.1) floor prevents division blow-up for new or recently-slashed nodes.

On-chain node registry

NodeInfo is part of the StakingRegistry contract:
struct NodeInfo {
    bytes32 nodeId;          // ed25519 public key
    address nodeAddress;     // Ethereum address for slashing + payments
    string[] multiaddrs;     // QUIC multiaddrs
    uint32 firstRegisteredAt;
    uint64 nonce;            // incremented on re-registration
    // ...
}
Registration is atomic and requires two proofs:
  1. EIP-712 binding signature — from the Ethereum address, committing to the NodeId. Makes the node slashable.
  2. ed25519 ownership proof — from the NodeId’s private key, committing to the Ethereum address. Prevents NodeId squatting (an attacker registering someone else’s public key).
bindNodeId() remains available for post-registration key rotation.

Regional topics

Nodes subscribe to cdn/region/{cc}/v1 where {cc} is a two-letter country code plus the global topic. Regional topics reduce gossip noise for latency-sensitive selection: a client in Frankfurt typically prefers DE/NL/AT candidates over US ones, and the regional topic surfaces those preferentially. Clients subscribe but do not publish.

NAT traversal and multiaddrs

iroh handles hole-punching automatically. Nodes update their registered multiaddrs via updateMultiaddrs when the public-facing address changes (cloud region change, new home-ISP lease). When direct P2P fails (~10% of conditions), traffic routes through a relay — a stateless, content-blind QUIC broker. Relays are operated as protocol infrastructure (funded from treasury), not incentivized as a network role — paying relays per byte would create a perverse incentive to prevent direct connections. Source ADR: 001-network.md