Merkle Mountain Range Multi Proofs
Merkle mountain ranges are an improvement over conventional merkle trees for growing, potentially unbounded lists. Where conventional merkle tree constructions over growing lists prove very inefficient to compute, as all nodes in the tree must be recomputed. Merkle mountain ranges amortise this cost by growing subtrees incrementally and merging subtrees at the same height, rather than growing the full tree.
Merkle mountain ranges, true to their name, are a type of merkle tree composed of perfectly balanced binary subtrees (each subtree has leaves for some ) arranged in decreasing height — forming a mountain range silhouette. This construction provides two key benefits over conventional merkle trees:
- Efficient appends. Inserting a leaf into a conventional merkle tree requires recomputing nodes (every node on the path from the new leaf to the root, plus the root changes position). In an MMR, appending a leaf is amortized — only the rightmost subtrees may need merging.
- Compact proofs over large sets. A proof for a single leaf requires at most nodes for the subtree proof (where is the subtree’s height) plus at most peak hashes for bagging — still total.
Capacity
An MMR where the tallest subtree has height can hold subtrees of every smaller height as well. When all heights from down to are present, the total leaf count is:
A conventional merkle tree of height holds exactly leaves. So an MMR with the same maximum proof depth holds nearly twice as many leaves:
| Height | Max leaves | Max proof size | |
|---|---|---|---|
| Merkle tree | |||
| MMR | (subtree + peaks) |
The MMR proof is at most twice as large, but this is a constant factor — both are .
MMR Multi Proofs
Our approach to verifying mmr multi proofs is to decompose the MMR into its constituent subtrees and verify each one independently using the position-based indexing model defined in my previous article.
An MMR with leaves decomposes into subtrees whose sizes are the powers of 2 in the binary representation of :
The number of subtrees (peaks) equals .
Each subtree is treated as a standalone merkle tree with 1-based position indexing. Within a subtree, leaf indices are converted to tree positions and siblings are paired bottom-up, consuming proof nodes as needed for missing siblings.
Proof Schema
The MMR proof uses a minimal format. The proof is a flat array of hashes, and each leaf carries its 0-based index across the entire MMR. Positions within subtrees are inferred from leafCount.
Verification Algorithm
The algorithm proceeds in three phases:
Phase 1: Decompose into subtrees. Walk through the binary representation of , peeling off the largest power-of-2 subtree at each step. Partition the leaves into each subtree by their index.
Phase 2: Compute subtree roots. For each subtree, convert leaf indices to 1-based tree positions and walk up level by level. At each level, check if the next node is a sibling (). If both siblings are known, hash them together; otherwise, consume a proof element as the missing sibling.
Phase 3: Bag the peaks. Combine the subtree roots right-to-left: .
Subtree Root Calculation
Each subtree is a perfect binary tree verified independently by converting leaf indices to tree positions and walking up:
Algorithm 1 Subtree Root Calculation
Require: leaves , proof hashes , position offset
Ensure: peak root hash
1:for each do
2:
3:end for
4:repeat
5:
6:for each node do
7:if next node is sibling () then
8:
9:skip
10:else
11:
12:
13:end if
14:end for
15:
16:until
17:return
orders the hash inputs by position — even positions are left children, odd are right:
MMR Verification
With SubtreeRoot defined, we can now describe the full MMR verification:
Algorithm 2 MMR Multi Proof Verification
Require: proof hashes , leaves with 0-based indices, leaf count
Ensure: root hash of the MMR
1:
2:,
3:while do
4:
5:
6:
7:
8: leaves with index
9:if then
10:
11:else if and then
12:
13:else
14:
15:end if
16:end while
17:if then
18:reject // contains indices
19:end if // bag peaks right-to-left
20:while do
21:,
22:
23:end while
24:return
Reference Implementation
A production Solidity implementation of this algorithm is available at polytope-labs/solidity-merkle-trees.
References
P. Todd. Merkle Mountain Ranges. GitHub, 2012. https://opentimestamps.org.