Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Part IV · Surviving the long run This chapter detours back into cryptography — one of only two in eighteen.

Recall what has been done to hashing so far:

  • Chapter 1: a hash is a fixed-length fingerprint, a pure function, and it avalanches

  • Chapter 4: hashes linked end to end into a chain

  • This chapter: hashes combined upward in pairs into a tree

Same brick, third way of laying it.


11.1 The problem

A block may hold thousands of transactions. Your phone wants to confirm that its payment made it in. Must it download the entire block and scan every entry?

In real Bitcoin the full block data is several hundred gigabytes. A phone cannot do that, and should not have to.

The Merkle tree’s answer: one short path of hashes is enough — even among a million transactions.

warm-up: the same hash as always.
c4d09eac2af12725 ...

11.2 Combine transactions upward in pairs

The rule: hash each transaction into a leaf; then concatenate adjacent pairs and hash again to get the level above; repeat until one hash remains — the Merkle root.

(If a level has an odd count, duplicate the last entry to make it even. That detail becomes a real vulnerability in 11.6.)

4 transactions -> Merkle root: a765893c3938e60b31bc ...

First be clear what level is: a list of strings, and each pass through the loop halves its length.

level, pass 0: ['h(A)', 'h(B)', 'h(C)', 'h(D)']     4 items
level, pass 1: ['h(AB)', 'h(CD)']                    2 items
level, pass 2: ['h(ABCD)']                           1 item -> loop ends, this is the root

Drawn out:

                 ROOT
                /    \
          H(AB)        H(CD)
          /   \        /   \
      H(A)   H(B)   H(C)   H(D)
       |      |      |      |
      txA    txB    txC    txD

Four transactions collapse in two levels. A million takes about twenty.

Because every level halves. That is log₂ — chapter 2’s complexity intuition, this time working for you instead of against you.


11.3 The proof path

To prove “transaction C is in this tree” you do not need all the transactions.

You need only the sibling hashes along C’s path to the root — follow them and you can recompute the root yourself.

proof path for 'Carol pays Dave':
  sibling hash fdc627173c15...  on the right
  sibling hash 18a400e83a3f...  on the left

4 transactions, 2-step proof.

proof is a list, and each entry is “one hash, and which side of me it sits on”:

[('h(D)...', 'right'), ('h(AB)...', 'left')]

Meaning: “combine with the h(D) on your right, then combine with the h(AB) on your left, and you’re at the root.”

That idx //= 2 is worth a glance too: if you are item 2 on this level, you are item 1 on the level above — because every two items merge into one. That integer division is “climb one level.”


11.4 Verification: a phone needs only the root and the path

The verifier holds only the Merkle root (32 bytes, stored in the block header) and the proof path.

is 'Carol pays Dave' in the block: True
forged 'Carol pays Dave a million': False

Four lines, and it is a for loop that hashes repeatedly.

Change one word and the recomputed root no longer matches — avalanche again (chapter 1). To forge, an attacker would need different transaction content hashing to the same value: a collision attack, which nobody can perform against SHA-256.

That is the basis of a light (SPV) wallet: no block download, just a block header and a path.


11.5 A callback to chapter 4 — now it’s the root that moves

In chapter 4, editing an old block broke the hash of every block after it.

Here, editing any transaction changes the Merkle root → changes the block header → changes the block’s hash.

root before the edit: a765893c3938e60b ...
root after the edit : 66db0d01764f31b9 ...
did the root change: True

Two threads now join:

  • Chapters 4 and 7: the block header holds prev_hash, which commits to all prior history

  • This chapter: the block header also holds the Merkle root, which commits to every transaction in this block

So a block header — 80 bytes in real Bitcoin — simultaneously commits to “the entire history behind me” and “every transaction inside me.”

Eighty bytes, committing to everything. It is the most elegant single piece of Bitcoin’s design, and it is why a phone can verify a ledger of several hundred gigabytes.


11.6 Scale, and one real bug

The power of a Merkle tree only shows at scale.

transaction count: 1000
proof path length: 10 steps   (log2(1000) = 10.0)
is tx500 in the block: True

Without a Merkle tree you would download all 1000 and check them one by one.
With one, you need 10 hashes.

A thousand transactions, a ten-step proof. Double the transactions and the proof grows by one step.

A million → 20 steps. A billion → 30.

That “duplicate the last one” detail

Now back to the detail planted in 11.2: when a level has an odd number of leaves, we duplicate the last one.

In real Bitcoin this caused a vulnerability, CVE-2012-2459.

Think about it. A tree with 5 leaves duplicates the fifth: [1,2,3,4,5,5]. Now what about a tree with 6 leaves, where the 5th and 6th happen to be identical? Also [1,2,3,4,5,5].

Two different transaction lists produce exactly the same Merkle root.

An attacker could take a valid block, duplicate some transactions inside it, and produce a block with the same Merkle root but different contents. A node computing the root sees it match, while the block’s contents have changed. This could be used to make nodes wrongly mark a valid block invalid and reject it permanently.

Bitcoin patched this in 2012 by rejecting blocks containing duplicate transactions.

What is worth remembering is not the bug itself, but where it lived. The mathematics was right. The hashing was right. The tree structure was right. It went wrong in a padding detail — in the kind of place nobody bothers to write down in the specification.

Section 3.6’s reused k is the same class of error. You will meet it a third time in chapter 13, and a fourth in chapter 18.

YOUR TURN

using tx500's path to verify tx999: False

Please actually do question 3. Watching two different lists produce one identical root is worth more than ten paragraphs of explanation.


11.7 The ledger

What you wroteField
merkle_root() — collapse pairs upward into one rootCryptography (composed hashing)
merkle_proof() — the sibling pathCryptography
verify_proof() — light verificationCryptography
“80 bytes committing to everything”Systems design
CVE-2012-2459Engineering safety — not mathematics

This chapter’s ledger tips back to the left, for the first time since chapter 3.

But note what it is in service of: letting weak devices verify — which is a systems-level requirement.

A Merkle tree is pure hash composition with no new mathematics in it. It matters not because it is deep, but because it makes “anyone can verify independently” hold true on a device with limited bandwidth and a battery.

Chapter 1’s “anyone can check the arithmetic” only truly reaches a phone in this chapter.


Next

Mempool, fee market, and confirmations.

Chapter 10 had you write pick_txs from the miner’s side. The next chapter switches to the user’s side:

After you broadcast a transaction, and before it makes it into a block — where is it?

In a place called the mempool. Chapter 7 already gave you the sentence: the mempool is “I heard about this”; the blockchain is “the network finally accepted this.”

The next chapter is about the blurry region between those two: why transactions get stuck, how to unstick one, and why “wait for 6 confirmations” is a probability judgment rather than a promise.