DEEP DIVE: MERKLE TREES

Merkle Trees: Merkle Tree, Patricia Trie, and Search Tree

Blockchains, BitTorrent, and Git all root their integrity in "trees of hashes." From the basic Merkle tree, through the Merkle Patricia Trie that underpins Ethereum's state, to the Merkle Search Tree for P2P replica synchronization: here is how a tree of hashes lets you verify a mountain of data with a single number.

Merkle tree basics: binding a mountain of data into one hash

The Merkle tree was invented by Ralph Merkle, filed as a patent in 1979 and published in a 1987 paper. Leaves are the hashes of individual data chunks; each internal node is the hash of its children's hashes concatenated together; and the single hash at the top is the Merkle root. A root of roughly 32 bytes ends up acting as a commitment to the entire dataset beneath it. Change one bit anywhere in the leaves, and the root changes.

A Merkle proof (inclusion proof) lets you prove a given chunk belongs to the tree without holding the whole dataset: you only need the sibling hashes along the path from that leaf to the root, which is log₂(n) of them. For a dataset of a million items that is only around 20 hashes, a few hundred bytes, and the verifier needs nothing but the root to check it.

  • Tamper-evidence: flip a single bit anywhere in the leaves and the root hash changes, so any modification is immediately detectable.
  • O(log n) proof size: inclusion proofs stay tiny even as the dataset grows into the millions, which is what makes lightweight verification practical.
  • Partial verification and parallel downloads: each chunk can be checked against the root as soon as it arrives, so pieces can be fetched from many peers at once and verified independently, exactly what BitTorrent and IPFS rely on.
  • The second-preimage pitfall: a naive tree lets an attacker construct a different tree with the same root by reinterpreting an internal node's hash as a leaf. RFC 6962 (Certificate Transparency) closes this by domain-separating leaf and internal nodes with 0x00/0x01 prefixes before hashing.
SystemWhat gets MerkleizedPurpose
BitcoinBlock transactions → Merkle root in the block headerLightweight SPV verification without downloading the full block
BitTorrent v2 (BEP 52)Per-file piece-hash treeVerify pieces as they arrive, independent of one another
IPFSMerkle DAG and CIDsContent addressing and deduplication
Certificate TransparencyRFC 6962 certificate logsInclusion and consistency proofs for an append-only log
GitCommit → tree → blob hash chainHistory integrity

The plain Merkle tree is perfect for verifying a fixed, static list, but the moment you need a key-addressable index, frequent updates, or a way to diff two replicas efficiently, it runs out of steam. That is where the two descendants below come in.

Merkle Patricia Trie: a verifiable key-value store (Ethereum)

Blockchain "state" (account balances, contract storage) is a key-value map that is updated constantly. Rebuilding an entire Merkle tree on every single update is a non-starter; what is needed is a structure that recomputes only the nodes along the updated key's path, and whose shape is determined purely by the set of keys it holds. The Merkle Patricia Trie (MPT) is Ethereum's answer.

Structurally, it is a radix trie with path compression (Patricia). Ethereum walks each key one hex nibble (4 bits) at a time, giving a 16-way branching structure at every level.

Branch node
Has 16 child slots, one per possible nibble value, plus a value slot for a key that terminates exactly at this node.
Extension node
Compresses a shared run of nibbles that has no branching into a single node, avoiding a long chain of single-child branch nodes.
Leaf node
Stores the remaining key path plus the value itself. A hex-prefix (HP) encoding distinguishes leaf from extension nodes and odd- from even-length paths in the same nibble stream.

In practice, an Ethereum block header carries the stateRoot (the root of the world-state trie) alongside separate transaction-trie and receipt-trie roots, and every contract additionally has its own storage trie. A light client can verify a single account's balance with nothing more than a Merkle proof against stateRoot. To prevent an adversary from crafting keys that create pathologically deep paths (a DoS vector), Ethereum uses a "secure trie" that hashes each key with keccak256(address) before insertion.

  • I/O amplification: nodes are RLP-encoded and stored hash→node in a key-value database such as LevelDB, so a single logical read of "this account's balance" fans out into multiple underlying database lookups along the trie path.
  • State bloat: as accounts and contract storage grow, the trie (and the disk space and I/O it demands) grows with it, a persistent operational headache for node operators.
  • Successors under discussion: in the stateless-Ethereum research track, Verkle trees (built on vector commitments for dramatically smaller proofs) and a flat binary trie are both being explored as replacements for the hex MPT.

Merkle Search Tree: a convergent tree independent of insertion order (2019)

In P2P replica synchronization (anti-entropy), two nodes want to answer "do we hold the same set of data, and if not, exactly where do we differ?" The efficient approach is to compare roots first and descend only into subtrees whose hashes disagree, giving O(log n) diff discovery. The trouble is that ordinary B-trees and balanced binary trees change internal shape depending on the order items were inserted, so two nodes holding the identical set of data can end up with different tree shapes and, therefore, different root hashes, which breaks the comparison entirely.

The Merkle Search Tree (MST), introduced by Auvolat and Taïani in 2019, solves this by assigning each key a layer equal to the number of leading zeros in its hash, counted in some base B. Keys with a higher layer number become the upper nodes of the tree, so the tree's shape is uniquely determined by the set of keys it holds (determinism), independent of the order they were inserted in. The resulting shape resembles a B-tree and is probabilistically balanced.

  • Uniqueness: the same set of keys always produces the same tree shape and therefore the same root hash, regardless of insertion history.
  • Expected O(log n) depth: the layer-assignment scheme keeps the tree balanced in expectation without any explicit rebalancing logic.
  • Diff sync: two replicas compare root hashes first, then recursively descend and fetch only the subtrees whose hashes disagree, with no need to transfer or compare data that already matches.
  • Pairs beautifully with state-based CRDTs (Conflict-free Replicated Data Types) and [gossip protocols](/gossip), since both are built around the same idea of periodically reconciling state without a central coordinator.

One of the clearest production deployments is Bluesky's AT Protocol, where each user's repository of records lives in an MST. Commits sign the current root, which lets any party generate an existence proof for a single record and lets relays replicate repositories efficiently by exchanging only the differing subtrees.

Choosing between the three

AspectMerkle TreeMerkle Patricia TrieMerkle Search Tree
Data modelStatic list or setContinuously updated key-value mapOrdered set or map
Structural determinismDepends on construction orderUnique, determined by the key setUnique, determined by the key set
StrengthsInclusion proofs and bulk verificationUpdates plus proofs togetherReplica diffing
Proof and sync costO(log n) proofsProof length tracks path length, with fairly large per-node dataSync transfers only the diff between replicas
Flagship deploymentsBitcoin SPV, Certificate Transparency, BitTorrent v2Ethereum stateAT Protocol (Bluesky)

The choice comes down to what you actually need to verify: proving inclusion in a fixed dataset calls for a plain Merkle tree; proving and updating a piece of evolving state calls for an MPT-like structure; and confirming, and efficiently repairing, equality between two replicas calls for a Merkle Search Tree.

Common misconceptions and caveats

  • "The root hash lets you recover the data" is wrong: a Merkle tree proves integrity, not availability. It does not guarantee anyone actually holds and will serve the underlying data. This is the data-availability problem, and it sits at the center of rollup design.
  • "A valid Merkle proof means the data is authentic" is also incomplete: a proof only shows the data is consistent with a given root. The root itself must be legitimized by something else (consensus, a signature, a trusted timestamp) before the proof means anything.
  • "MPT is a strict upgrade over a plain Merkle tree" is not quite right: it costs you larger proofs and a meaningfully more complex implementation. For genuinely static data, a plain Merkle tree remains the simpler and cheaper choice.
  • Everything here rests on hash collision resistance: the whole edifice of tamper-evidence depends on the underlying hash function being collision-resistant, a lesson underscored by the real-world SHA-1 collisions that forced changes in both Git and Certificate Transparency.

Related pages

Merkle trees show up throughout this site's other deep dives: DHTs use hash trees for content addressing, BitTorrent verifies pieces with BEP 52's per-file hash tree, gossip protocols pair naturally with Merkle Search Trees for anti-entropy, distributed consensus is what legitimizes a root hash in the first place, smart contracts run atop the EVM's stateRoot, and attacks and defenses covers what happens when any of these assumptions break.

Back to top page