Part III · The house: building a chain This chapter contains no cryptography from beginning to end. It is the heart of the book, and it is Satoshi’s actual invention.
Last chapter left a hole: the ledger lives on one machine. Alice goes to another machine, spends the same coin against another ledger, and both ledgers insist they are correct.
Which do you believe?
7.0 First, dismantle a common belief¶
Before the answer, one misconception has to go — nearly everybody has it:
WRONG. “Bitcoin makes every computer in the world see the same ledger, always.”
It does not. Networks have latency. Right now, two nodes on opposite sides of the planet very likely see different transactions, different blocks, different local ledgers. That is normal, not a malfunction.
The accurate statement is:
RIGHT. Everyone runs the same rules, starts from possibly different local views, and eventually converges on one history.
This is not pedantry. It determines how you understand everything downstream — why forks happen, why you wait for confirmations, why a chain reorganization is part of the design rather than an accident.
A shared ledger is not the starting point. It is the result of convergence.
7.1 A block you can mine¶
Fuse chapter 4 and chapter 5:
A block = a batch of transactions + the previous block’s hash (chapter 4’s chain)
a mined nonce (chapter 5’s work)
import hashlib
def H(s): return hashlib.sha256(s.encode()).hexdigest()
class Block:
def __init__(self, txs, prev_hash, difficulty=3):
self.txs = txs # this block's transactions (simplified to strings)
self.prev_hash = prev_hash # chapter 4: pointer to the previous block
self.difficulty = difficulty # chapter 5: mining difficulty
self.nonce = None
def content(self):
return f"{self.txs}|{self.prev_hash}|{self.nonce}"
def mine(self):
'''Chapter 5's mining.'''
target = "0" * self.difficulty
n = 0
while not H(f"{self.txs}|{self.prev_hash}|{n}").startswith(target):
n += 1
self.nonce = n
return self
def hash(self):
return H(self.content())
genesis = Block(["genesis"], "0"*64).mine()
print("genesis mined. nonce =", genesis.nonce, " hash =", genesis.hash()[:12], "...")
print("genesis fields:", genesis.__dict__)
print("genesis content:", genesis.content())
genesis mined. nonce = 3661 hash = 0008f013f7ef ...
genesis fields: {'txs': ['genesis'], 'prev_hash': '0000000000000000000000000000000000000000000000000000000000000000', 'difficulty': 3, 'nonce': 3661}
genesis content: ['genesis']|0000000000000000000000000000000000000000000000000000000000000000|3661
Again, do not let chain become an abstract noun. It is a Python list:
[block0, block1, block2]Every block carries a prev_hash pointing at the one before it, which is what strings the
objects together.
Those last two print lines are worth reading when it runs: genesis.__dict__ shows the
block is four fields, and genesis.content() shows you exactly which string is hashed.
Nothing here is new — chapter 4’s chain plus chapter 5’s mining, and not one novel concept.
7.2 A chain, and its “work”¶
def extend(chain, txs):
'''Mine a new block onto the chain.'''
b = Block(txs, chain[-1].hash())
b.mine()
return chain + [b]
def work(chain):
'''Accumulated work (simplified: sum of difficulties).'''
return sum(b.difficulty for b in chain)
def valid(chain):
'''Is this chain valid? Every block must link up AND have really been mined.'''
for i in range(1, len(chain)):
if chain[i].prev_hash != chain[i-1].hash(): # ch4: does it link?
return False
if not chain[i].hash().startswith("0"*chain[i].difficulty): # ch5: was it mined?
return False
return True
# The honest chain: Alice pays Bob, Bob pays Carol.
honest = [genesis]
honest = extend(honest, ["Alice pays Bob 10"])
honest = extend(honest, ["Bob pays Carol 10"])
print("honest chain: length", len(honest), " work", work(honest), " valid?", valid(honest))
for i, b in enumerate(honest):
print(f"block{i}: txs={b.txs}, prev={b.prev_hash[:10]}..., nonce={b.nonce}, hash={b.hash()[:10]}...")
honest chain: length 3 work 9 valid? True
block0: txs=['genesis'], prev=0000000000..., nonce=3661, hash=0008f013f7...
block1: txs=['Alice pays Bob 10'], prev=0008f013f7..., nonce=6795, hash=0007c2b94c...
block2: txs=['Bob pays Carol 10'], prev=0007c2b94c..., nonce=6430, hash=000650c2ef...
Two things to look for in that output:
honestis a list holding threeBlockobjects in orderblock 1’s
prev_hashequals block 0’s hash; block 2’sprev_hashequals block 1’s hash
So “chain” is not a magic word. It means: each block writes the previous block’s hash into its own body.
Of the three functions, work is the new one, and it is suspiciously simple —
it adds up the difficulties.
The question it answers is: “how much electricity did building this chain consume?”
(Real Bitcoin computes accumulated work more precisely, but it means exactly this: a chain’s weight is the total hashpower required to produce it.)
7.3 Alice double-spends, this time across machines¶
Now open up last chapter’s hole.
On another machine, Alice forks from the same genesis block and spends the coin — already given to Bob — again, to Dave.
# Alice's attack chain: forks from the same genesis, double-spends to Dave.
attacker = [genesis]
attacker = extend(attacker, ["Alice pays Dave 10"]) # a conflicting transaction!
print("honest : length", len(honest), " work", work(honest), " valid?", valid(honest))
print("attacker: length", len(attacker), " work", work(attacker), " valid?", valid(attacker))
print()
print("Both chains are valid, and they disagree about who got the coin.")
honest : length 3 work 9 valid? True
attacker: length 2 work 6 valid? True
Both chains are valid, and they disagree about who got the coin.
Both chains pass valid.
Signatures fine, proof-of-work fine, links fine. You cannot write a checking function that rules either one out — because neither one is invalid.
Cryptography is no help at all here. It can prove Alice signed both transactions. It cannot say which chain is the real history.
Seeing something first locally does not mean it happened first. Final order is decided by whichever chain wins.
7.4 The rule¶
Satoshi’s rule is this:
Among all valid chains, take the one with the most accumulated work.
No voting, no identities, no adjudication of who is right — only who spent more effort.
def choose(*chains):
'''Longest-chain rule: among valid chains, most work wins.'''
return max((c for c in chains if valid(c)), key=work)
winner = choose(honest, attacker)
print("honest work:", work(honest), " attacker work:", work(attacker))
print("winner:", "honest" if winner is honest else "attacker")
print()
print("Alice->Bob stands. Alice->Dave (the double-spend) is discarded.")
honest work: 9 attacker work: 6
winner: honest
Alice->Bob stands. Alice->Dave (the double-spend) is discarded.
That is the whole thing.
max((c for c in chains if valid(c)), key=work)This is Bitcoin’s heart. Thirty years of an unsolved problem, and the answer is a max.
Notice carefully what it does not do:
It does not ask who the good guy is
It does not ask which transaction happened first (it has no way to know)
It has no authority, no roster, no weighted votes
It does not even care which chain is “correct”
It does one thing: among valid chains, pick the one that burned the most electricity.
And that is sufficient. Because everyone runs the same max, everyone picks the same chain.
Disagreement does not need to be prevented; the same rule dissolves it automatically.
The mempool is “I heard about this.” The blockchain is “the network finally accepted this.”
7.5 So can Alice still win?¶
Yes. If her hashpower exceeds every honest miner combined.
# Alice races to catch up: keeps mining on the attack chain until it overtakes.
attacker2 = extend(attacker, ["Dave pays Eve 10"])
attacker2 = extend(attacker2, ["Eve pays Frank 10"])
print("honest work:", work(honest), " attacker after catching up:", work(attacker2))
winner = choose(honest, attacker2)
print("who wins now?:", "honest" if winner is honest else "attacker -- 51% attack succeeded!")
honest work: 9 attacker after catching up: 12
who wins now?: attacker -- 51% attack succeeded!
The attacker wins.
That is the 51% attack, and you just performed one successfully. It genuinely works.
Which exposes the truth about Bitcoin’s security, and it deserves saying bluntly:
Bitcoin is not “impossible to attack.” It is “not worth attacking.”
You would need more than half the hashpower on Earth. The hardware and electricity cost more than you could steal.
Bitcoin’s security is not absolute. It is computational and economic.
That should make you slightly uncomfortable. Chapter 1’s hash and chapter 3’s signature gave you the feeling of a mathematical guarantee. This gives you we ran the numbers and it doesn’t pay.
But that discomfort is exactly what this book wants you to see. Mathematics can guarantee that a signature cannot be forged without the key. Mathematics can never guarantee that a crowd of strangers will agree on an ordering — that is a social problem, a game-theoretic problem. Satoshi’s contribution was converting that social problem into a cost problem.
One more thing works in the honest chain’s favour: honest miners do not stop and wait. They keep extending, and the gap the attacker must close keeps widening. Time is on the honest chain’s side.
YOUR TURN¶
# YOUR TURN:
# 1) Confirmations: how many blocks are stacked on top of a transaction.
def confirmations(chain, tx_str):
for i, blk in enumerate(chain):
if tx_str in blk.txs:
return len(chain) - 1 - i
return None
print("confirmations for Alice pays Bob:", confirmations(honest, "Alice pays Bob 10"))
# Think: why does more confirmations mean more safety?
# 2) Challenge: lower the attacker's difficulty to 2. Can it now win by having MORE blocks?
# You'll discover that "longest" compares WORK, not block count.
confirmations for Alice pays Bob: 1
Question 2 exposes the most misleading thing in this chapter. “Longest chain” is a bad name.
If block count were the measure, an attacker could set difficulty to 1 and stack a hundred
blocks in seconds. What actually gets compared is work — accumulated work.
The honest name would be “heaviest chain.”
(In Bitcoin the rule is formally most-cumulative-work. “Longest chain” is a historical nickname, because when difficulty is equal, longest and heaviest coincide.)
7.6 The ledger¶
This chapter’s ledger is the most important table in the book:
| What you wrote | Field |
|---|---|
class Block — transactions + previous hash + nonce | Systems design |
work(chain) — accumulated work | Systems design |
valid(chain) — does it link, was it mined | Systems design |
choose(*chains) — the longest-chain rule | A game rule |
| The 51% attack | Economics |
confirmations() | Probability |
Now count: how many lines of cryptography are in this chapter?
Zero.
H() appears, but its jobs are “did this meet the mining target” and “does this block link to
that one” — those are integrity checks, not cryptography in the sense of secrecy or
authentication. There is not one private key, not one signature, not one verification in the
entire chapter.
And what this chapter solved is precisely the thing thirty years of cryptographers could not.
This is the prologue’s claim, fully cashed:
Signatures and hashes are bricks, and they were somebody else’s (chapters 1–5). “Use accumulated work to make mutually distrustful strangers converge on one history” — that house is Satoshi’s, and it lies entirely outside cryptography.
Chapter 1 promised you: “by chapter 7 you will write an entire chapter of code and find not one line of cryptography in it.”
Delivered.
Next¶
Incentives and issuance.
You have a machine that resists forgery, resists double-spending, and reaches consensus. One question remains, and it is fatal:
Why would any miner burn electricity?
If nobody mines, this entire chapter is waste paper — with no work, choose has nothing
to compare.
The next chapter is the whitepaper’s cleverest move, and the first time in this book that economics takes the lead role.