Skip to content

Overview — Project 5: Bitcoin Mini-Chain

Project 4 · askr closed Phase 1: you called someone else’s network, streamed untrusted bytes, and made the borrow checker prove they were safe to hold. Phase 2 turns the question inward — instead of trusting a server, you build a system where nobody has to be trusted. Project 5 is a Bitcoin-style mini-chain: a ledger that lets strangers who have never met agree on who owns what, with no bank, no admin, and no central database. By the end you’ll have built — and understood from the inside — the one invention that made digital money possible.

Digital cash sounds easy until you try it. A coin is just data, and data copies for free. So what stops me from spending the same coin twice — sending it to you, then sending the identical bytes to someone else before anyone notices? That’s the double-spend problem, and for decades the only fix was a trusted third party: a bank whose ledger is the single source of truth. Everyone trusts the bank not to lie, not to get hacked, not to freeze your account.

Bitcoin’s 2008 insight was a way to get a single agreed-upon ledger without that trusted party — using cryptography to prove ownership and Proof-of-Work to make rewriting history prohibitively expensive. This project builds the smallest version that still teaches the whole idea:

double-spend without a bank?
├── prove ownership → ECDSA signatures over secp256k1 (day 18)
├── track who owns what → the UTXO set: spend = remove a coin (day 17)
├── one tamper-evident order → blocks chained by hash (day 16)
├── make history costly → Proof-of-Work + the most-work rule (day 19)
└── agree with no server → a P2P node; peers converge (day 20)

A real, runnable crate at rust/btcmini/. It is pure Rust — secp256k1 comes from the k256 crate with no C dependency — and the only concurrency is std threads, exactly like kvlite in Project 2. By Day 20 it mines blocks, moves coins between keypairs, rejects double-spends and forged signatures, and runs a TCP node where two processes sync to the same chain:

$ cargo run -- demo
genesis mined: 000075699d81c057
block 1 mined (nonce 3673); the work is the search for it
alice balance = 50
block 2 mined: alice paid bob 30 (fee 1)
alice balance = 70
bob balance = 30
double-spend rejected: double-spend or unknown output: 7d5a81eb…:0
chain valid: height 3, total work 12288
DayPageYou buildThe Rust / the chain idea it forces
16Blocks & hashingblock headers chained by hashdouble-SHA-256, newtypes, why tampering is detectable
17The UTXO modeltransactions + the UTXO setenums, HashMap, conservation; double-spend = a missing row
18Keys & signatureskeypairs that sign & verifyk256/ECDSA, addresses as pubkey hashes; ownership = a signature
19Proof-of-Workmining + the most-work ruletargets, the mining loop, how strangers agree on one history
20A P2P nodea std::net node + mempoolthread-per-connection, broadcasting, two peers converging

Each day teaches its idea, then has you build that slice into the companion crate. Type the code, run it, and break it on purpose — a rejected double-spend and a failed signature are not errors, they’re the lesson landing.

A blockchain is the rare program where a bug is not an inconvenience but a theft. That raises the stakes on exactly the things Rust is built to protect: an unchecked integer overflow can mint money from nothing (it actually happened to Bitcoin in 2010), a data race in the node can corrupt the ledger, a reused signature nonce can leak a private key. Holding all of that correct at once is what makes the domain such a good forcing function for the language.

This project weaves two questions on every page. The playbook’s recurring one — what does building this force you to understand, and what is Rust’s compiler protecting you from? — meets the chain’s: what problem did Bitcoin actually solve? They turn out to be the same shape of question. Bitcoin replaces trust in a person with trust in rules that are expensive to break; Rust replaces trust in a programmer with rules that are impossible to break (memory safety, data-race freedom), checked at compile time. Both are systems for getting safety without having to trust anyone. Building one in the other is the point.

Begin with Day 16 · Blocks & Hashing →