Engineer. Investor. Writer.
Meeting the Neighbors
How blockchain nodes find each other with no directory, the two ways peers exchange data, and how a Base node runs two separate p2p networks at once, one for execution and one for consensus.
A new node has no peers. It knows its own key and the chain it wants to join. It does not know a single other node. There is no directory of who is online. There is no server to query and no name to trust. Nodes never register anywhere. Yet within a minute the node is connected to dozens of peers and syncing the chain.
This post explains how. It covers the protocols that let nodes find each other, the two ways peers exchange data once they have, and the two separate networks a Base node runs at once. It assumes no p2p background.
Every node ships with a small hardcoded list of bootnodes. A bootnode is a stable machine that stays online. It is not trusted and not authoritative. It is only a place to start. The node connects to a bootnode and asks which other nodes it knows. It connects to those and asks the same question. Each round widens its view. After a few rounds it knows far more peers than it needs.
A new node knows almost nothing — just one bootnode. It bootstraps by asking that node who else is out there, then asking those peers for more, until it has a healthy view of the network.
This only works if each node's contact list has structure. A random set of contacts would force a random walk to find any specific peer. discv4 gives the list structure. It is a Kademlia distributed hash table. Each node has a 256-bit ID derived from its public key. The distance between two IDs is their bitwise XOR, read as a number. It has nothing to do with latency or geography. IDs that differ in their low bits are close. IDs that differ in their high bits are far. Every node computes distance the same way, so all nodes agree on which of two IDs is nearer a target.
Each node sorts its contacts into buckets by distance. It keeps a few peers close to itself, a few further out, and a few further still. Each bucket holds up to 16. The table is dense near the node and sparse far away.
discv4 gives every node a 256-bit ID and measures 'distance' between IDs with XOR. Each node keeps a table of buckets grouped by distance, holding a few peers in each — so from anywhere it can always route toward any target ID in a handful of hops.
That shape makes lookups cheap. To find the nodes nearest a target ID, a node asks its closest known peers for their closest known peers. Each hop lands measurably nearer. Any target is a handful of hops away, even in a network of hundreds of thousands.
discv4 runs over UDP and uses four messages. PING and PONG check that a peer is alive. They also enforce an endpoint proof. Before a node answers your queries, it pings the address you claimed and waits for your reply from it. That proves you control the IP and port. FINDNODE asks for the nodes closest to a target. NEIGHBORS returns up to 16 of them. A node's address is an enode URL, written enode://<pubkey>@<ip>:<port>. It is flat and unsigned.
That flatness is discv4's main weakness. An enode URL carries an address and nothing more. It is unsigned. Every packet is plaintext, so anyone on the path can read who is looking for whom. discv5 keeps the Kademlia core and fixes all three problems.
The core change is the Ethereum Node Record, or ENR. An ENR is a signed record of key/value pairs. It holds the node's identity scheme, its secp256k1 public key, its IP, and its ports. It can hold any other keys the node wants to publish. It also carries a sequence number. To change your address, you bump the sequence and re-sign. Your identity stays the same. An ENR is capped at 300 bytes, small enough to fit in a DNS TXT record.
discv5 replaces discv4's flat enode:// URL with a signed, versioned Ethereum Node Record, and wraps every exchange in an encrypted session. Same idea — find peers — with real cryptographic identity and privacy.
discv5 also encrypts the wire. Peers run a handshake and derive session keys, then encrypt every message. Discovery traffic is no longer observable. FINDNODE now asks for nodes at a specific XOR distance and gets a NODES reply. A generic TALKREQ and TALKRESP channel lets other protocols ride on top of discovery.
Discovery only produces addresses. Exchanging data is a separate protocol. It takes one of two shapes. The first shape is point-to-point, and execution clients use it. Two peers complete an encrypted, authenticated handshake. In Ethereum's stack that handshake is RLPx. They open a direct channel and run request and response over it. One peer asks another for a range of block headers and gets them back. One peer announces a new transaction hash. You always talk to a specific peer.
The second shape is publish and subscribe, and consensus clients use it. A node subscribes to a topic. To send a message, it hands the message to a mesh of peers. They forward it to their mesh, which forwards it again. The message reaches every subscriber in a second or two. This is gossipsub, part of libp2p. It fits data that everyone needs at once, like a new block.
Once peers have found each other, they talk in one of two shapes. Execution clients open direct, encrypted request/response channels (RLPx). Consensus clients flood a single message to every peer subscribed to a topic (gossipsub).
RLPx / devp2p — point to point
libp2p gossipsub — topic broadcast
Two networks at once
A Base node uses both shapes at the same time. It is really two programs. One is an execution client and one is a consensus client. Each runs its own p2p network.
The execution client is reth. It connects over RLPx and speaks the eth wire protocol. It gossips transactions and syncs state, exactly like an Ethereum execution node. It discovers peers with discv5, and discv4 is off by default. Base runs that discovery under a custom network identity called basev0, mixed into the handshake. This has a concrete effect. A generic discv5 crawler cannot see Base's execution nodes. Its session keys come from the default identity, so the handshake never completes. Base nodes recognize each other. A crawler speaking stock discv5 gets no reply. RLPx listens on port 30303 and discv5 on 30304.
A single Base node speaks on two independent p2p networks at the same time. Its execution client gossips transactions and syncs state over Ethereum's devp2p stack; its consensus client discovers peers with discv5 and receives the sequencer's signed unsafe blocks over libp2p gossipsub, then hands them down to execution over the local Engine API.
The consensus client is base-consensus. It discovers peers with discv5 and distributes blocks over libp2p gossipsub. Its one job is speed. It gets each new block to every node as fast as possible.
The unsafe-block path ties the two clients together. The sequencer produces a block and signs its execution payload. It publishes the block to a gossipsub topic. Every consensus client receives it and checks the signature against the current unsafe_block_signer address. If the signature matches, the client hands the block to its local execution client over the Engine API. The Engine API is a JWT-authenticated link on localhost, not a p2p connection. The signature is what makes a block from an anonymous relay safe to accept. The messenger is untrusted. The signature is not forgeable. Nodes read the signer address from Ethereum L1, so the sequencer's key can rotate without a release.
"Unsafe" means the block has not yet been derived from L1. The block is valid and executable. It has just not been confirmed through the canonical path that rebuilds it from L1 data. Gossip delivers it in a few hundred milliseconds. L1 derivation is the source of truth, and it follows behind. The two layers keep separate discovery networks and separate bootnodes. Mainnet has five consensus bootnodes and ten execution bootnodes.
Base does not have its own networking stack. It runs Ethereum's stack twice. Same discovery protocols. Same RLPx transport. Same gossipsub. Same secp256k1 identities. Same split into an execution network and a consensus network, bridged locally by the Engine API.
Base reuses Ethereum's exact peer-to-peer machinery on both layers — same discovery, same transports, same gossip. What differs is who's talking and what they're saying: one sequencer signing unsafe blocks, instead of thousands of validators.
What differs is the traffic. Ethereum's consensus network carries beacon blocks, attestations, and blobs from hundreds of thousands of validators. Its gossip layer is where consensus happens. Base's consensus network carries execution blocks from a single sequencer, signed by a single key. Nothing votes on it. The gossip only distributes the sequencer's output, and L1 remains the arbiter of truth.
Everything else is the same. Identities are points in XOR space. Nodes route between them in a few hops, then sign, version, and encrypt what they exchange. Data moves as direct request and response, or as topic flooding. A Base node runs that whole stack twice, once for execution and once for consensus. The one real difference from Ethereum is a single signing sequencer where Ethereum has a voting crowd.
✎ Test Yourself
14 questions · each scores the instant you answer.
No central directory
Q1
A brand-new node has no peer list and no directory to query. What is the one thing it starts with?
discv4
Q2
In discv4's Kademlia design, what does the 'distance' between two node IDs mean?
Q3
Why does each k-bucket hold only a handful of peers, with near buckets sparse and far buckets full?
Q4
What is the 'endpoint proof' enforced by discv4's PING/PONG?
discv5
Q5
What does discv5's ENR (Ethereum Node Record) provide that a discv4 enode URL does not?
Q6
Beyond the ENR, what does discv5 change about the discovery traffic itself?
Q7
How does a discv5 FINDNODE query differ from discv4's?
Wire vs gossip
Q8
What shape of communication do execution clients use over RLPx / devp2p?
Q9
Why is libp2p gossipsub the right tool for propagating a freshly produced block?
Base's two networks
Q10
In what sense does a single Base node run two peer-to-peer networks?
Q11
What makes it safe for a node to accept an unsafe block that arrived from an anonymous peer several hops away?
Q12
Where does a Base node get the unsafe_block_signer address it checks blocks against?
Q13
Why can a generic Ethereum discv5 crawler fail to see Base's execution nodes?
Base vs Ethereum
Q14
What is actually different about Base's networking compared to Ethereum's, versus what's the same?