FABRKNT
P2P Networking Internals — From devp2p to Custom Gossip
P2P Networking
Lesson 1 of 4·CONTENT16 min40 XP

Treat this page as a workbench, not a blog post. The goal is to extract a reusable mental model from the source and carry it into the rest of the Fabrknt stack.

Course
P2P Networking Internals — From devp2p to Custom Gossip
Lesson role
CONTENT
Sequence
1 / 4

Lesson 1 — P2P fundamentals: devp2p, libp2p, and peer discovery

Question

You launch a fresh reth node = zero peers, zero blocks, zero state. Seconds later it is downloading headers from somewhere — where did the peers come from? A node that is not on the network cannot ask the network for peers. This is the bootstrapping problem, and the P2P layer has to solve it before anything else can begin.

Principle (minimum model)

  • Two-layer structure. Discovery (find peers, discv4 / discv5 = Kademlia DHT) + Transport (talk to peers, RLPx = encrypted TCP).
  • Bootstrapping is solved by bootnodes. Well-known IPs hardcoded into the chainspec, connect to one → it gives you more peers → the DHT takes over.
  • devp2p = Ethereum-purpose stack. discv5 (peer discovery) + RLPx (encrypted TCP) + eth/68 (block + tx gossip).
  • Kademlia "closeness" = XOR distance over node IDs. Topological, no geographic meaning. Nodes close in ID space find each other efficiently = O(log N) hops.
  • ENR = Ethereum Node Record. ID + IP + port + capability. Discovery queries return ENRs.
  • RLPx ≈ Ethereum-flavored TLS. ECDH + ECDSA + AES-CTR + RLP framing. peer ID = the public key itself — no central CA, hence the reason to skip TLS.
  • eth/68 announces tx by hash first. Avoids the amplification problem where every node rebroadcasts every tx body to every other node.
  • libp2p = the multi-chain alternative. Discovery / transport / encryption / multiplexing kept as independent layers. Adopted by Polkadot, IPFS, Solana, Lighthouse. Reth uses devp2p for historical reasons.

Worked example + steps

P2P fundamentals — devp2p, libp2p, and peer discovery

You launch a fresh reth node. It has no peers, no blocks, no state. Within seconds it's downloading headers from somewhere — but where did the peers come from? It can't ask the network for peers without already being on the network. That chicken-and-egg is the bootstrapping problem, and it's the first thing the P2P layer has to solve before anything else can happen.

The P2P layer stays invisible until it isn't: sync stalls, gossip drops your tx, peer scoring boots you off the network. When that happens, you need to know what's running underneath. On Ethereum that's devp2p — Ethereum's purpose-built peer-to-peer stack. Other chains use libp2p (a modular, multi-chain alternative) or roll their own.

1. The two layers

Every P2P stack splits the work in two:

LayerJobProtocol on Ethereum
Discovery"Find peers"discv4 / discv5 (Kademlia DHT)
Transport"Talk to peers"RLPx (encrypted TCP)

Discovery is the bootstrapping problem from the opener — peers need peers to find peers. The answer: bootnodes, well-known IP addresses hardcoded into the chainspec. You connect to one, it gives you more, the DHT takes over.

2. devp2p — Ethereum's protocol

devp2p is the protocol Ethereum nodes speak. Ethereum-specific (not multi-chain). It bundles three pieces:

  • discv5: peer discovery via Kademlia DHT (a distributed hash table for finding nodes)
  • RLPx: encrypted, authenticated TCP transport
  • eth/68 (current sub-protocol): block + transaction gossip

When you run a reth node, all of this is happening:

flowchart LR
    Boot["Bootnode"] -->|seed peer list| You["Your Reth node"]
    You -->|discv5 ping| Peer1["Peer 1"]
    You -->|discv5 ping| Peer2["Peer 2"]
    Peer1 -->|RLPx handshake| You
    You -->|eth/68: blocks, txs| Peer1
    You -->|eth/68: blocks, txs| Peer2

3. discv5 — peer discovery via Kademlia

How do you scale "find me peers" from one bootnode to a global network of millions? Kademlia.

Kademlia is a distributed hash table (DHT) — a structure where each node holds a small slice of the directory and routes queries to nodes that hold the rest. Each Ethereum node has a 256-bit ID (derived from its public key). To find peers "close to" some target ID, you query nodes you already know; they return their closest known peers; you query those; repeat. Recursive lookup, O(log N) hops.

For Ethereum:

  • Each peer publishes an ENR (Ethereum Node Record) — its ID, IP, port, capabilities
  • Discovery queries return ENRs
  • Bootnodes are well-known starting points (in the chainspec)

Kademlia's "closeness" is XOR distance over node IDs — purely topological, no geographic meaning. The point: nodes close in ID can find each other efficiently. That's what makes finding any peer in a network of millions tractable.

4. RLPx — the transport layer

Once you have a peer's address, you need an encrypted channel to talk to it. That's RLPx.

  • Handshake: ECDH key exchange + signature verification
  • Encryption: AES-CTR with per-direction keys
  • Framing: RLP-encoded messages with length prefixes (RLP = Recursive Length Prefix, Ethereum's wire encoding)

Think of RLPx as TLS for Ethereum — encrypted, authenticated, ordered byte stream. Why not just use TLS? Pre-2015 history, plus subtle requirements TLS doesn't fit: peer ID is the pubkey, no centralized CA.

5. eth/68 — the sub-protocol

RLPx gives you a secure channel; eth/68 is what flows through it. The current Ethereum sub-protocol. Messages include:

MessagePurpose
StatusHandshake — fork version, chain ID, head
NewBlockAnnounce a new block
BlockBodiesRequest/respond block bodies
NewPooledTransactionHashesAnnounce pending tx (hashes only)
PooledTransactionsRequest full tx bodies
ReceiptsRequest/respond receipts

Note: in eth/68, transactions are announced as hashes first — peers request the full body only if they don't already have it. This kills the "every node re-broadcasts every full tx" amplification.

6. libp2p — the alternative

If devp2p is the bundled Ethereum stack, libp2p is the unbundled multi-chain one. Used by:

  • Polkadot (built on libp2p)
  • IPFS (libp2p's origin)
  • Solana (custom transport but libp2p concepts)
  • Many newer chains

libp2p separates concerns: discovery (separate), transports (TCP/QUIC/WebRTC), encryption (Noise — a key-agreement protocol framework), multiplexing (yamux/mplex — running many logical streams over one connection). You compose what you need.

Why Ethereum doesn't use libp2p: history. devp2p existed first; switching is hard. Some newer Ethereum tools (Lighthouse, a consensus client) use libp2p anyway; reth sticks with devp2p to match the execution-layer protocol.

7. For Reth-based chains

A new chain built on Reth has a choice:

  • Use devp2p (default, what reth provides) — works out of the box
  • Customize devp2p — add custom sub-protocols (e.g., tempo/1 for payment-specific messages)
  • Add libp2p sidecar — for cases where you need different networking semantics

For Tempo: likely devp2p with custom sub-protocol for payment-specific gossip (e.g., merchant identity attestations, payment finality hints).

For Hyperliquid: their custom transport (HyperBFT communication) is separate from execution-layer P2P — they layered their own network on top of devp2p for consensus.

8. Practice

  1. Open discv5 spec and identify the 4 message types
  2. Browse reth's crates/net/network — find the entry point
  3. Identify: how would you add a custom sub-protocol for payment-specific gossip?

Final check: in one sentence, what's the bootstrapping problem solved by bootnodes? If your answer doesn't reference "peers need peers to find peers," re-read §1.

🛣️ The road not taken (Solana): Solana's block propagation is Turbine — a tree-based broadcast protocol, not gossip. The leader splits each block into shreds (small packets) and propagates them via a deterministic peer tree: each shred reaches every validator in roughly O(log N) hops, vs devp2p's O(N) gossip flooding. The result: dramatically lower bandwidth waste per block, but the design assumes every validator has near-symmetric high-bandwidth connectivity. devp2p's gossip wastes bandwidth (every validator receives each tx multiple times) but tolerates wildly heterogeneous network conditions and adversarial peers gracefully. Turbine optimizes for throughput-at-scale with good peers; devp2p optimizes for survivability with bad peers. Both are valid network-layer choices; the choice tracks what kind of validator network the chain is willing to require.

Pass criteria

  • State the two-layer split (Discovery vs Transport) and which protocols staff each role on Ethereum.
  • Explain bootstrapping via bootnodes in one sentence — and why DNS-based discovery is a sibling, not a replacement.
  • Define Kademlia XOR distance and the O(log N) lookup property.
  • Name the three pieces inside devp2p (discv5 / RLPx / eth/68) and what each does.
  • Explain why peer ID is the public key (no central CA) and why that excludes plain TLS.
  • Summarize the eth/68 hash-first announcement and what amplification problem it avoids.
  • Contrast devp2p vs libp2p in a sentence — and explain why Reth uses devp2p.

Summary (3 lines)

  • P2P two-layer split (Discovery = discv5 / Kademlia DHT + Transport = RLPx). Bootstrapping is solved by bootnodes hardcoded in the chainspec.
  • devp2p bundles three pieces (discv5 + RLPx + eth/68); ENRs are the records returned by lookup. Peer ID = the public key, so RLPx ships its own crypto rather than TLS.
  • libp2p is the modular multi-chain sibling; Reth speaks devp2p for historical reasons. Next lesson reads the actual reth crate that implements all of this.