Skip to content
Bitcoin Block Header
step 1/5

Reading — step 1 of 5

Read

~2 min readCryptography Foundations

Bitcoin Block Header

Time to stop simplifying. In this lesson your code reproduces the actual hash of the actual Bitcoin genesis block — the value 000000000019d668... that every full node on Earth agrees on. If a single byte of your serialization is off, you'll know immediately.

The header is exactly 80 bytes:

 4 bytes  version      little-endian integer
32 bytes  prev_block   byte-REVERSED from the displayed hex
32 bytes  merkle_root  byte-REVERSED from the displayed hex
 4 bytes  timestamp    little-endian (unix seconds)
 4 bytes  bits         little-endian (compact difficulty target)
 4 bytes  nonce        little-endian

Block hash = SHA-256(SHA-256(header)), then reverse the 32-byte digest for display. Double-SHA was Satoshi's belt-and-suspenders choice in 2008 (length-extension paranoia); Ethereum uses a single Keccak-256.

The endianness trap — the whole lesson in one sentence

Bitcoin serializes integers and hashes little-endian internally, but every explorer, RPC response, and human displays hashes big-endian — so you must byte-reverse the two hashes going in, and byte-reverse the digest coming out. Forget any one of the three reversals and you get a well-formed, useless hash. That bits field, for the curious, is a compact float-ish target encoding: 0x1d00ffff means 0x00ffff × 256^(0x1d − 3) ≈ 2^224 — the easiest target Bitcoin ever allowed, and the genesis hash's ten leading hex zeros are the proof-of-work sitting below it.

Genesis, for real

version   = 1
prev      = 0000...0000  (no parent)
merkle    = 4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
timestamp = 1231006505   (2009-01-03 18:15:05 UTC)
bits      = 486604799    (0x1d00ffff)
nonce     = 2083236893
hash      = 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f

Its coinbase embeds "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks."

The idiom

python

Note .digest() on the inner hash, not .hexdigest(): the second SHA-256 must eat the raw 32 bytes. Hashing the 64-character hex string of the first digest is the single most common bug in this exercise — it types-checks, runs, and produces garbage.

Your exercise

Each line gives <version>|<prev_hex>|<merkle_hex>|<timestamp>|<bits>|<nonce> (hashes in display order); print the display-order block hash. Test 0 is the genesis block above and must print exactly 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f; tests 1–2 are real Bitcoin blocks 1 and 2. The grader catches, in descending order of popularity: double-hashing the hex string instead of raw bytes, skipping the [::-1] on prev/merkle (the leading zeros vanish), and forgetting the final digest reversal (your zeros come out trailing). Get all three reversals and both raw-byte hashes right, and three real mainnet hashes fall out of your code — enjoy that moment.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…