Key Question
How do you find a file in a peer-to-peer network where no one knows where everything is?
Deep Dive
A Distributed Hash Table (DHT) is a decentralized key-value store spread across many nodes. You PUT a value under a key, and anyone who knows the key can GET the value back β no central server required.
Before DHTs, P2P lookedups were broken in two ways:
Napster (1999): Gnutella (2000): DHT (2001+):
βββββββ ββββ ββββ ββββ ββββ ββββ ββββ
βIndexβ βA βββB βββC β βA βββB βββC β
ββββ¬βββ ββββ ββββ ββββ ββββ ββββ ββββ
β βββ βββ βββ βββ βββ βββ
ββββββ΄βββββ ββββ ββββ ββββ ββββ ββββ ββββ
βΌ βΌ βD βββE βββF β βD βββE βββF β
ββββ ββββ ββββ ββββ ββββ ββββ ββββ ββββ
βA β βB β
ββββ ββββ Each query floods to Each node knows
every neighbor (O(n)) a few "routes"
Central index = SPOF
- Napster: Central index server. Fast, but a single point of failure (and a lawsuit magnet).
- Gnutella: Flood queries to all neighbors.
TTLfield limits spread, but still O(n) messages per query β doesnβt scale. - DHT: Each node stores a small slice of the key space. Queries route through O(log n) hops. No central coordination.
Core operations are dirt simple:
PUT("song.mp3", 192.168.1.5) β stored on responsible node(s)
GET("song.mp3") β returns 192.168.1.5
This looks like consistent hashing, and it is β but with a twist. Consistent hashing assumes you know the full ring of nodes. In a P2P network, you join, you leave, you crash. You donβt have a directory. You know maybe 5-10 nodes. DHTs answer: how do you route to the right node when you only know a handful of peers?
The answer depends on the DHT protocol. Chord uses a finger table and clockwise distance. Kademlia uses XOR. Pastry uses prefix matching. They all achieve O(log n) lookups with only O(log n) routing state per node.
Check Your Understanding
- What are the scaling properties of Napster, Gnutella, and a DHT (in terms of messages per lookup)?
- Why canβt you just use consistent hashing directly in a P2P network?
- Draw the communication pattern of each system from memory.
The βSo What?β
DHTs are the routing layer of every major decentralized system today β BitTorrent, IPFS, Ethereumβs discovery protocol. Without them, P2P networks either centralize or drown in flooded traffic. Theyβre the reason βfind this dataβ scales to millions of nodes.
βοΈ Exercises
Exercises: DHTs & Kademlia
Exercise 1
In Kademlia with 8-bit IDs, what is the XOR distance between node IDs 11001010 and 11011010?
Exercise 2
Why does Kademlia use parallel queries (Ξ± > 1) instead of sequential queries (Ξ± = 1)? Whatβs the trade-off?
Exercise 3
What problem does S/Kademliaβs disjoint path routing solve, and how does it protect against an attacker who controls ~30% of the network?
Exercise 4 (Challenge)
In a Kademlia network with N = 100,000 nodes and k = 20, assume each node has a fully populated routing table. How many distinct nodes can a single node know about (maximum)? How many hops should a lookup take in the worst case?
ποΈ View Solutions
Solutions: DHTs & Kademlia
Exercise 1
XOR distance between 11001010 and 11011010.
11001010
β 11011010
ββββββββββ
00010000 = 16
The distance is 16.
Exercise 2
Parallel queries (Ξ± > 1) vs sequential.
Parallel queries (Ξ±=3) reduce lookup latency by sending requests simultaneously. If one node is slow or offline, the other Ξ±-1 requests proceed independently. The trade-off is bandwidth: each hop sends 3x as many messages. In practice this is a good trade because:
- It masks network latency (RTT matters less)
- It provides fault tolerance (dead nodes donβt stall the lookup)
- The XOR topology means responses fill routing tables faster
Exercise 3
S/Kademliaβs disjoint path routing.
Vanilla Kademlia routes all queries toward the same k closest nodes. If an attacker controls those nodes (via a Sybil or Eclipse attack), they can return false results. S/Kademlia sends lookups along d independent paths to different sets of nodes. If the attacker controls ~30% of the network, the probability of them controlling all d paths is (0.3)^d. With d=3, the attacker has only a 2.7% chance of controlling every path, greatly reducing attack success.
Exercise 4 (Challenge)
Routing table capacity and lookup hops.
Each node has 160 k-buckets, each holding up to k=20 contacts. Maximum nodes known per node: 160 Γ 20 = 3,200.
In practice, many buckets will be sparsely populated (especially high-distance ranges), so a node typically knows far fewer.
Lookup hops (worst case): logβ(N) = logβ(100,000) β 16.6. So 17 hops maximum.
In practice, with Ξ±=3 parallelism and well-populated routing tables, lookups converge in ~10-12 hops.