Proof of work: making the next block cost effort
How does a network agree on the next block without a boss? Proof of work makes adding a block cost effort: you must find a hash with a rare pattern, and the only way is to guess, over and over.
The big idea
Proof of work requires finding an input whose hash meets a hard target (like leading zeros), which takes many guesses — making blocks expensive to produce and cheap to verify.
See it in code
Mining means hunting for a hash that hits a target pattern. Start with the simplest check: hash the block with one guess number (a nonce) and see whether the hash happens to start with a 0:
import hashlib
def sha(text):
return hashlib.sha256(text.encode()).hexdigest()
data = "block-data"
print(sha(f"{data}0"))
print("Starts with 0?", sha(f"{data}0").startswith("0"))4e81a49fcb5399c75df93f8b0ab4795b9ccc07efcc314d34fc80a662d09dde81 Starts with 0? False
This hash starts with 4, not 0 — a miss. There's no way to design a hash that begins with a zero; all you can do is try another nonce and check again.
So loop: keep bumping the nonce until the hash finally starts with a 0. This is real mining, just at the easiest possible difficulty of one leading zero:
import hashlib
def sha(text):
return hashlib.sha256(text.encode()).hexdigest()
data = "block-data"
nonce = 0
while not sha(f"{data}{nonce}").startswith("0"):
nonce += 1
print("Found nonce:", nonce)
print("Hash:", sha(f"{data}{nonce}"))Found nonce: 6 Hash: 0befb6c4df919ea999974ed7968b56f32c4f1cae1c4781beea88419550d07cd1
Nonce 6 did it — just six tries for one leading zero. Now demand four zeros in a row and the search gets dramatically longer.
Now the real target: four leading zeros. Same loop — increment and re-hash until you get lucky — but the winning nonce is far rarer. Verifying the answer, though, is still a single hash:
import hashlib
def sha(text):
return hashlib.sha256(text.encode()).hexdigest()
data = "block-data"
nonce = 0
while not sha(f"{data}{nonce}").startswith("0000"):
nonce += 1
print("Found nonce:", nonce)
print("Hash:", sha(f"{data}{nonce}"))Found nonce: 7704 Hash: 000062c4209894b19658c5274f213acfa4ee56f67b189cbb4a26a337670879ab
It took 7,704 guesses to land a hash starting with 0000 — versus six for one zero above. Anyone can check that answer in one hash, but finding it took real work — that asymmetry is the point. Demanding more zeros makes mining exponentially harder, which is how networks tune difficulty.
The 'hard to produce, easy to verify' pattern appears elsewhere: CAPTCHAs, rate-limiting puzzles, and anti-spam systems that make sending bulk messages costly. Proof of work turns raw computation into a cost that secures the network — though its energy use is why newer systems explore alternatives like proof of stake.
Try it yourself
Change "0000" to "000" and watch the nonce (and time) drop dramatically; try "00000" to see it climb. Then change data and confirm you get a completely different winning nonce.
The common mistake
Assuming difficulty scales linearly. Each extra leading zero makes the target roughly 16 times rarer, so mining time grows exponentially, not gradually. That steep curve is exactly what keeps the network secure — and expensive to attack.
What it unlocks
Proof of work secures blocks and chains and what a blockchain is, and builds directly on hashing and while loops.