Part V — Blockchain & Trustless Consensus · Chapter 8

Build a toy blockchain with proof-of-work mining

Hook

Every piece is already built: a way to commit a batch of transactions to one hash, and a way to make proposing a block expensive to compute but cheap to check. What does it look like to actually chain real blocks together using both at once?

Intuition
genesishash: 33
Block 1prevHash: 33merkleRoot: 577nonce: 600hash: 43
Block 2prevHash: 43merkleRoot: 506nonce: 900hash: 19

This is the same genesis hash from the proof-of-work chapter, and the same Merkle root from the cryptographic-primitives chapter — nothing new is being invented here. Block 1 commits 4 transactions to a root, mines a nonce against that root, and block 2 repeats the process chained onto block 1's hash.

Formalize
  1. Commit transactions to a Merkle root — reused, not reimplemented

    merkleRoot(txs)\text{merkleRoot}(\text{txs}) is exactly the function from the cryptographic-primitives chapter. Every block runs its own transaction set through it once.

  2. A block's hash folds in the previous hash and this root

    blockHash(prevHash,root,nonce)=toyHash(prevHashrootnonce)\text{blockHash}(\text{prevHash}, \text{root}, \text{nonce}) = \text{toyHash}(\text{prevHash} \mathbin\Vert \text{root} \mathbin\Vert \text{nonce}) — the same shape as the mining chapter's blockHash, with the Merkle root standing in for the raw data string.

  3. Mining is the same brute-force nonce search

    Try nonce=0,1,2,\text{nonce} = 0, 1, 2, \ldots until blockHash()<T\text{blockHash}(\ldots) < T. Same difficulty target T=50T=50, same search, same asymmetry: expensive to find, one hash to check.

  4. A chain is blocks whose prevHash fields actually link up

    Block ii's prevHash must equal block i1i-1's mined hash. Change anything upstream — a transaction, a root, a nonce — and every downstream prevHash reference stops matching, breaking the chain from that point forward.

  • root — this block's Merkle root, committing all of its transactions to one hash.
  • prevHash — the previous block's mined hash; the literal link in "blockchain."
Play
genesishash: 33
Block 1prevHash: 33merkleRoot: 577nonce: 600hash: 43
Block 2prevHash: 43merkleRoot: 506nonce: 900hash: 19

Both blocks are exactly as mined — every hash matches, and every link points at the block before it.

Tamper with block 1's first transaction and watch the damage cascade: a different Merkle root produces a different block hash, that new hash no longer meets the difficulty target (it was only mined to work for the original root), and block 2's stored prevHash no longer points at anything real. One tampered transaction breaks two blocks.

Worked example

Genesis hash 33 (mined in the proof-of-work chapter). Block 1 reuses the crypto-primitives chapter's exact 4 transactions.

  1. Block 1's Merkle root

    merkleRoot(txs)=577\text{merkleRoot}(\text{txs}) = 577 — identical to the cryptographic-primitives chapter's worked example, because it's the same 4 transactions.

  2. Mining block 1

    Searching nonces against (prevHash=33,root=577)(\text{prevHash}=33, \text{root}=577): blockHash(33,577,0)=981\text{blockHash}(33,577,0)=981, then 982,983,984,985,982, 983, 984, 985, \ldots for nonces 11 through 55 — every one of them lands in the 980980s, well past the target. Nonce 600600 is the first to succeed: blockHash(33,577,600)=43<50\text{blockHash}(33, 577, 600) = 43 < 50.

  3. Mining block 2

    A second batch of 4 transactions gives root 506506. Chained onto block 1's hash 4343, the same search against (prevHash=43,root=506)(\text{prevHash}=43, \text{root}=506) starts at blockHash(43,506,0)=594\text{blockHash}(43,506,0)=594, climbing through the 590590s for the first several nonces, until nonce 900900 is the first to succeed, giving hash 1919.

  4. Tampering with block 1

    Change transaction 0 to "alice pays bob 9": the Merkle root becomes 301301 instead of 577577, so blockHash(33,301,600)=498\text{blockHash}(33, 301, 600) = 498 — nowhere near under 5050. The nonce that worked for the original root doesn't work for the tampered one; block 1 is no longer validly mined, and block 2's prevHash = 43 no longer matches block 1's real (recomputed) hash.

Checkpoint

Block 3 commits its 4 transactions to Merkle root 617 and chains onto block 2's hash (19). Find a nonce whose hash drops under the difficulty target of 50.

Slide to search for a winning nonce
Summary
blockHash(prevHash,merkleRoot(txs),nonce)<T\text{blockHash}(\text{prevHash}, \text{merkleRoot}(\text{txs}), \text{nonce}) < T

A blockchain is nothing more than these two ideas, chained: commit a batch of transactions to one hash (Merkle root), then spend real, unfakeable work proving you found a nonce that makes the resulting block hash small enough — with each block's proof depending on the exact hash of the one before it. Every later chapter in this Part — stake instead of work, forks and finality, sharding, Sybil resistance — is a variation on making that same chain harder to fake or cheaper to run.