Networking

Torsten implements the full Ouroboros network protocol stack, supporting both Node-to-Node (N2N) and Node-to-Client (N2C) communication.

Protocol Stack

flowchart TB
    subgraph N2N ["Node-to-Node (TCP)"]
        HS[Handshake V14/V15]
        CSP[ChainSync<br/>Headers]
        BFP[BlockFetch<br/>Block Bodies]
        TX[TxSubmission2<br/>Transactions]
        KA[KeepAlive<br/>Liveness]
    end

    subgraph N2C ["Node-to-Client (Unix Socket)"]
        HSC[Handshake]
        LCS[LocalChainSync<br/>Block Delivery]
        LSQ[LocalStateQuery<br/>Ledger Queries]
        LTS[LocalTxSubmission<br/>Submit Transactions]
        LTM[LocalTxMonitor<br/>Mempool Queries]
    end

    MUX[Multiplexer] --> N2N
    MUX --> N2C

Relay Node Architecture

flowchart TB
    subgraph Inbound ["Inbound Connections"]
        IN1[Peer A] -->|N2N| MUX_IN[Multiplexer]
        IN2[Peer B] -->|N2N| MUX_IN
        IN3[Wallet] -->|N2C| MUX_N2C[N2C Server]
    end

    subgraph Outbound ["Outbound Connections"]
        MUX_OUT[Multiplexer] -->|ChainSync| PEER1[Bootstrap Peer]
        MUX_OUT -->|BlockFetch| PEER1
        MUX_OUT -->|TxSubmission| PEER1
    end

    subgraph Core ["Node Core"]
        PM[Peer Manager<br/>Cold→Warm→Hot]
        MP[Mempool<br/>Tx Validation]
        CDB[(ChainDB)]
        LS[Ledger State]
        CONS[Consensus<br/>Ouroboros Praos]
    end

    MUX_IN -->|ChainSync| CDB
    MUX_IN -->|BlockFetch| CDB
    MUX_IN -->|TxSubmission| MP
    MUX_N2C -->|LocalStateQuery| LS
    MUX_N2C -->|LocalTxSubmission| MP
    MUX_N2C -->|LocalTxMonitor| MP

    PEER1 -->|blocks| CDB
    CDB --> LS
    LS --> CONS
    PM -->|manage| MUX_OUT
    PM -->|manage| MUX_IN

Node-to-Node (N2N) Protocol

N2N connections use TCP and carry multiple mini-protocols over a multiplexed connection.

Handshake (V14/V15)

The N2N handshake negotiates the protocol version and network parameters:

  • Protocol version V14 (Plomin HF) and V15 (SRV DNS support)
  • Network magic number
  • Diffusion mode: InitiatorOnly or InitiatorAndResponder
  • Peer sharing flags

ChainSync

The ChainSync mini-protocol synchronizes block headers between peers:

  • Client mode: Requests headers sequentially from a peer to track the chain
  • Server mode: Serves headers to connected peers, with per-peer cursor tracking

Key messages:

  • MsgFindIntersect -- Find a common chain point
  • MsgRequestNext -- Request the next header
  • MsgRollForward -- Header delivered
  • MsgRollBackward -- Chain reorganization
  • MsgAwaitReply -- Peer has no new headers (at tip)

BlockFetch

The BlockFetch mini-protocol retrieves block bodies by hash:

  • Client mode: Requests ranges of blocks from peers
  • Server mode: Serves blocks to peers, validates block existence before serving

Key messages:

  • MsgRequestRange -- Request blocks in a slot range
  • MsgBlock -- Block delivered
  • MsgNoBlocks -- Requested blocks not available
  • MsgBatchDone -- End of batch

TxSubmission2

The TxSubmission2 mini-protocol propagates transactions between peers:

  • Bidirectional handshake (MsgInit)
  • Flow-controlled transaction exchange with ack/req counts
  • Inflight tracking per peer
  • Mempool integration for serving transaction IDs and bodies

KeepAlive

The KeepAlive mini-protocol maintains connection liveness with periodic heartbeat messages.

PeerSharing

The PeerSharing mini-protocol enables gossip-based peer discovery. Peers exchange addresses of other known peers to help the network self-organize.

Node-to-Client (N2C) Protocol

N2C connections use Unix domain sockets and serve local clients (wallets, CLI tools). The N2C handshake supports versions V16-V17 (Conway era) with automatic detection of the Haskell bit-15 version encoding used by cardano-cli.

LocalStateQuery

Supports a wide range of ledger queries:

QueryTagDescription
Chain tip0Current slot, hash, block number
Current epoch1Active epoch number
Current era--Active era (Byron through Conway)
Block number--Current chain height
System start--Network genesis time
Protocol parameters2Live protocol parameters
Proposed PP updates4Proposed parameter updates (empty in Conway)
Stake distribution5Pool stake and pledge
UTxO by address6UTxO set filtered by address
Stake address info10Delegation and rewards
Genesis config11System start, epoch length, slot length, security param
UTxO by TxIn15UTxO set filtered by transaction inputs
Stake pools16Set of registered pool key hashes
Pool parameters17Registered pool parameters
Pool state19Pool state (same as pool parameters)
Stake snapshots20Mark/set/go snapshots
Pool distribution21Pool stake distribution with VRF keys
Stake deleg deposits22Deposit amounts per registered stake credential
Constitution23Constitution anchor and guardrail script
Governance state24Active proposals, committee, and voting state
DRep state25Registered DReps with delegators
DRep stake distr26Total delegated stake per DRep
Committee state27Constitutional committee members
Vote delegatees28Vote delegation map per credential
Account state29Treasury and reserves
Non-myopic rewards6*Estimated rewards per pool for given stake amounts

The query protocol uses an acquire/query/release pattern:

  1. MsgAcquire -- Lock the ledger state at the current tip
  2. MsgQuery -- Execute queries against the locked state
  3. MsgRelease -- Release the lock

LocalTxSubmission

Submits transactions from local clients to the node's mempool:

MessageDescription
MsgSubmitTxSubmit a transaction (era ID + CBOR bytes)
MsgAcceptTxTransaction accepted into mempool
MsgRejectTxTransaction rejected with reason

Submitted transactions undergo both Phase-1 (structural) and Phase-2 (Plutus script) validation before mempool admission.

LocalTxMonitor

Monitors the transaction mempool:

MessageDescription
MsgAcquireAcquire a mempool snapshot
MsgHasTxCheck if a transaction is in the mempool
MsgNextTxGet the next transaction from the mempool
MsgGetSizesGet mempool capacity, size, and transaction count

Peer Manager

The peer manager classifies peers into three categories following the cardano-node model:

  • Cold -- Known but not connected
  • Warm -- Connected but not actively syncing
  • Hot -- Actively syncing (ChainSync + BlockFetch)

Peer Lifecycle

Cold --> Warm (TCP connection established)
Warm --> Hot  (Mini-protocols activated)
Hot  --> Warm (Demotion for poor performance)
Warm --> Cold (Disconnection)

Failure Handling

  • Exponential backoff on connection failures
  • Latency-based ranking and reputation scoring (EWMA metrics)
  • Adaptive peer selection preferring low-latency, reliable peers

Inbound Connections

  • Per-IP token bucket rate limiting for DoS protection
  • N2N server handles handshake, ChainSync, BlockFetch, KeepAlive, and TxSubmission2
  • Bidirectional diffusion mode supports both initiator and responder roles

Peer Discovery

Peers are discovered through multiple channels:

  1. Topology file -- Bootstrap peers, local roots, and public roots
  2. PeerSharing protocol -- Gossip-based discovery from connected peers
  3. Ledger-based discovery -- SPO relay addresses extracted from pool registration certificates (enabled after useLedgerAfterSlot)

Multiplexer

All mini-protocols run over a single TCP connection (N2N) or Unix socket (N2C), multiplexed by protocol ID:

Protocol IDMini-Protocol
0Handshake
2ChainSync (N2N)
3BlockFetch (N2N)
4TxSubmission2 (N2N)
8KeepAlive (N2N)
10PeerSharing (N2N)
5LocalChainSync (N2C)
6LocalTxSubmission (N2C)
7LocalStateQuery (N2C)
9LocalTxMonitor (N2C)

The multiplexer uses length-prefixed frames with protocol ID headers, matching the Ouroboros specification.