Reading — step 1 of 5
Read
Double-Spend Defense
Digital cash has one hard problem, and it isn't cryptography — it's copying. A coin that's just data can be paid to two merchants at once:
I own UTXO u.
Tx_A: u -> merchant_A Tx_B: u -> merchant_B
broadcast both simultaneously. Which one is money?
Signatures don't help — both are validly signed, by me. Before Bitcoin, the only known fix was a central server deciding order. Nakamoto's insight: let the chain decide. Whichever transaction lands in the canonical chain wins; the other becomes invalid automatically, because its input is already consumed. Double-spend defense is the consensus problem — ordering, not secrecy.
Confirmations
Temporary forks complicate this. Two miners can find blocks at the same height — one containing Tx_A, the other Tx_B. Both are valid chains for a while. The fork resolves when the next block extends one side; the other side's block is orphaned and its transactions return to the mempool (where Tx_B now bounces off the spent input).
So "in a block" is not "final." Finality is probabilistic and deepens with confirmations: a transaction at height H with the tip at height T has T − H + 1 confirmations — the block containing it counts as the first. Each additional confirmation is another block an attacker would have to out-mine. The whitepaper's own math: an attacker's catch-up chance shrinks exponentially with depth as long as they hold under half the hashrate (at ~10% of hashrate, six blocks deep is already worse than 1-in-1000); over half, and they eventually win no matter the depth — confirmations only buy time against a majority. Hence the folklore policies:
| Payment | Wait | Rationale |
|---|---|---|
| Coffee | 0-conf | loss < attack cost; RBF makes even this risky |
| E-commerce | 1 conf (~10 min) | survives simple races |
| Large transfer | 6 conf (~1 hour) | the classic "final enough" |
| Exchange deposit | up to 100 | paranoia scales with amount |
Faster chains (Litecoin 2.5 min, Solana sub-second) shrink the wait but not the principle: fewer independent extensions of history = weaker guarantee per confirmation. Lightning moves small payments off-chain entirely and settles disputes on-chain.
Reorgs, concretely
When the canonical tip switches branches, blocks above the fork point are disconnected. Any transaction that only existed in a disconnected block loses all its confirmations at once — it's unconfirmed again, pending re-mining. This is why exchanges track confirmations continuously rather than flagging "confirmed" once: the count can go down.
Your exercise
Build the tracker: BLOCK <height> <txs>, TX_CONFIRMATIONS <tx>, TIP_HEIGHT, and REORG <h> — which, despite the name reading like a rewind to h, keeps blocks at heights ≤ h and removes every block above h (that's what the tests encode: after REORG 1, a tx in block 1 still prints 1). Two graded mistakes: the off-by-one — a tx in block 1 with tip 3 has 3 confirmations (3−1+1), and printing 2 fails the very first test — and reorg direction: after blocks at 5, 6, 7 and REORG 6, the tx in block 7 prints UNCONFIRMED while the one in block 6 prints 1. Unknown transactions and reorged-out transactions both print exactly UNCONFIRMED; empty chain prints tip 0.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…