Skip to content
Blockchain Association of Cameroon
BAC-L0-FOUND-1103 h

Anatomy of a blockchain

Assembling the earlier building blocks: blocks, headers, state roots, mempool, propagation. Where the foundations become a system.

  • Break down a real block header field by field
  • Follow a transaction from mempool to finalised block
  • Explain the role of the state root

The earlier workshops gave you building blocks: hashes, signatures, Merkle trees, consensus. Here you assemble them into a system. You will open a real block header byte by byte, follow a transaction from the network's waiting queue to a finalised block, and understand the role of the state root, the single hash that summarises every account. You will also learn, which matters for security, what a header alone lets you verify and what still requires the block body.

Lessons 1/4 · 20 min

A block header, byte by byte

An identity card of 80 bytes

A block is made of a header (small, fixed size in Bitcoin) and a body (the list of transactions). The header summarises the block and links it to the chain. Let us start with Bitcoin, whose format is the simplest: the header is exactly 80 bytes.

BytesSizeFieldRole
0–34versionRule set the miner announces following
4–3532previous block hashLink to the parent (workshop 104)
36–6732Merkle rootSummary of all transactions (workshop 106)
68–714timestampSeconds since 1 January 1970 UTC, claimed by the miner
72–754bitsDifficulty target in compact form
76–794nonceCounter changed by the miner (workshop 109)

The 4-byte integers are little-endian: the least significant byte comes first. The block hash is SHA-256 applied twice to those 80 bytes. In Bitcoin, explorers display this result with the bytes in reversed order; the "internal" order is the one used in the computation.

Reading fields by hand

Version: the bytes 00 00 00 20 read little-endian give the integer 0x20000000, which is 536,870,912 in decimal.

Timestamp: the bytes 00 3c 9a 65 give 0x659a3c00 = 1,704,606,720 seconds, that is 7 January 2024 at 05:52:00 UTC. (An example value chosen for the exercise, unrelated to any specific block.)

Nonce: the bytes 2a 00 00 00 give 0x2a = 42.

The bytes tool below does these readings for you: paste hexadecimal, slice ranges, read little- or big-endian, reverse the order.

The "bits" field: the target in compact form

The 4 bytes ff ff 00 1d read 0x1d00ffff. The most significant byte, 0x1d = 29, is the exponent; the next three, 0x00ffff, are the mantissa. The target is mantissa × 256^(exponent − 3), here 0xffff × 256^26. A block hash, read as a big number, must be less than or equal to the target. A smaller target requires more leading zeros in the displayed hash: that is the difficulty.

And elsewhere?

Not every network has this header. An Ethereum header contains, among others, the parent hash, a state root, a transactions root, a receipts root, a block number, a timestamp and fee-related fields. A CometBFT header contains, among others, the previous block's identifier, the hash of the validator set and an app_hash field that commits to the application state. Names and sizes change; the idea stays the same: a small object that commits to everything else.

What this does NOT guarantee

  • The timestamp is claimed by the miner: it is constrained by tolerance rules, but it is not an exact clock.
  • The version field does not prove a miner really applies the rules it announces.
  • A low block hash proves work was done, not that the body's transactions are valid.

Recap

The header is a commitment of 80 bytes (in Bitcoin): parent, summary of the transactions, difficulty, nonce. Its double SHA-256 is the block's identity.

Interactive tool

Byte inspector

Paste hex, cut out a slice and read it as a little-endian or big-endian integer.

Length: 14 bytes

0000020000000a006c1f
00084d5e1d00ffff

Slice as hex

02000000

Little-endian unsigned integer

2

Little-endian signed integer (two's complement)

2

Big-endian unsigned integer

33,554,432

Big-endian signed integer (two's complement)

33,554,432

Bytes reversed (hex)

00000002

UTC date of the slice (little-endian): 1970-01-01T00:00:02Z

For example a block header timestamp. It can be read from the slice above.

2009-01-03T18:15:05Z

Interactive tool

SHA-256 of hex bytes

Paste bytes as hex: the hash covers the bytes, not the text of the digits. A second field is concatenated after the first.

Digest

…

Spaces, newlines and 0x prefixes are ignored.

Lessons 2/4 · 20 min

From mempool to finalised block

Where does a transaction go after "Send"?

Awa sends 50 units to Bineta from her phone. Nothing is "sent" to Bineta: the signed transaction is broadcast across a peer-to-peer network. Let us follow it.

  1. Creation and signing. The wallet builds the transaction (recipient, amount, fee, nonce) and signs it with Awa's private key (workshop 105).
  2. Broadcast. The wallet hands it to a node, which relays it to its peers by gossip: each one forwards it to its neighbours.
  3. Local validation. Each node checks, according to its network's rules, the signature, the format, the balance or inputs, the nonce (in account models) and the fee before keeping or relaying it. An invalid transaction is dropped.
  4. Mempool. Valid but unconfirmed transactions wait in the node's mempool ("memory pool", the waiting queue). There is no global mempool: every node has its own, which may differ slightly from its neighbour's depending on what it received and its own rules.
  5. Selection. The next block's proposer picks transactions from its mempool, usually the ones paying best per unit of space, within the block size limit.
  6. Block and propagation. It builds the block, computes the Merkle root of the transactions, fills in the header, does what its consensus requires (hash lottery or vote), then broadcasts the block.
  7. Block validation. Every full node replays the block: valid header, known parent, every transaction valid.
  8. Confirmation then finality. The block becomes the chain's tip; afterwards, depending on the family (workshop 109), it gains confirmations or is finalised.

Worked example

A block has room for 4 transactions (made-up figure). A proposer's mempool holds: T1 fee 2, T2 fee 9, T3 fee 5, T4 fee 1, T5 fee 7, T6 fee 4. It fills the block by decreasing fee: T2 (9), T5 (7), T3 (5), T6 (4). T1 and T4 wait for the next block. If Awa had set a fee of 1, her transaction could wait a long time: fees are the price of access to a scarce resource (workshop 111).

And if the block is abandoned?

If a reorganisation replaces the block, its transactions go back into the mempool, unless the winning branch already contains them. A transaction may then move to another block, or even, if it conflicts with another transaction already confirmed on the winning branch, become invalid.

What this does NOT guarantee

  • Being in a mempool does not guarantee inclusion: a node may evict transactions when its queue is full.
  • Seeing your transaction in your node does not mean others see it.
  • No node is obliged to include a particular transaction: a proposer can censor it, and the network relies on proposer rotation.
  • "Included in a block" is not "finalised": see workshop 109.

Recap

Sign, broadcast, validate, wait in each node's mempool, be picked, be put in a block, see that block validated by everyone, then gain finality. Each stage has its own guarantee, and none implies the next.

Interactive tool

Blockchain explorer (toy)

Five blocks linked by their digests. Edit a block's data: its digest changes, the next block's link breaks, and every later block becomes invalid.

Building the chain (mining 5 blocks)…

This is a toy. A block's hash is SHA-256 of "index|previous hash|data|nonce"; difficulty is only two leading hex zeros (about 256 attempts). A real chain requires astronomically more work and a network of nodes that each verify the chain.

Lessons 3/4 · 20 min

The state root: summarising every account

Two things not to confuse: transactions and state

Transactions are events ("Awa pays 50 to Bineta"). The state is the result of all events since genesis: who owns what now. In an account model (workshop 111), the state is, for example, the table of balances and nonces. A node that replays all the transactions rebuilds the state. But how do two nodes quickly check that they agree on that state?

The idea: a fingerprint of the state

Arrange the state in a Merkle tree (workshop 106) whose leaves are the accounts. The root of that tree is the state root. A header that contains the state root commits to the state of every account after that block.

Toy example: four accounts, leaf = "name:balance:nonce".

AccountLeaf before the blockLeaf after the block
AwaAwa:200:7Awa:149:8
BinetaBineta:30:2Bineta:80:2
KofiKofi:500:0Kofi:500:0
DayoDayo:10:1Dayo:11:1

Awa paid 50 plus a fee of 1 to a proposer (here the proposer holds the Dayo account, which receives 1): Awa's balance goes from 200 to 149, her nonce from 7 to 8, Bineta gains 50, Dayo gains 1. Those three leaves change, so the root changes. If two nodes compute the same root after the same block, they have the same state; if they get two different roots, at least one executed the block differently. Try it in merkle-explorer: edit a leaf and watch the root change.

What is the state root for?

  1. Fast agreement: comparing 32 bytes is enough to check that two nodes hold the same state.
  2. Proofs for light clients: a client that keeps only headers can receive a balance with a Merkle proof and verify it against the header's root.
  3. Synchronisation: a new node can check a state snapshot against a root.

Not every network has the same one

  • In Bitcoin, the header contains no state root: it contains the Merkle root of the transactions. To know what is still unspent, full nodes maintain the set of unspent outputs (UTXO set) locally, without the header committing to it.
  • In Ethereum, the header contains a state root, plus a transactions root and a receipts root. The state is organised in a more elaborate tree than a binary Merkle tree (a Merkle-Patricia trie), but the commitment principle is the same.
  • In CometBFT (Cosmos), the header contains an app_hash field, computed by the application, that commits to the application state. It is computed with a delay: a block's app_hash reflects the state after executing the previous block.

What this does NOT guarantee

  • A state root in a header does not prove it is correct: only executing the transactions checks it. A malicious miner or validator can propose a false root; full nodes reject it by replaying the block.
  • A light client verifying a proof against a root assumes the header itself is valid (consensus).
  • The state root does not say why the state changed: you need the transactions for history.

Recap

Transactions = events, state = consequences, state root = a single fingerprint of the consequences. It lets nodes agree and lets light clients verify a balance.

Interactive tool

Merkle tree explorer (toy)

One leaf per line (2 to 8). Pick a leaf to see its inclusion proof; edit a text to see which nodes change.

5 leaves

Nodes changed since the last valid input are underlined and marked "changed". Nodes on the chosen leaf's path are outlined. Last node of an odd level: it is duplicated as its own sibling.

Convention: leaf = SHA-256(UTF-8 text); parent = SHA-256(left ‖ right, raw bytes); odd node duplicated. Toy tree: Bitcoin double-hashes and serialises differently.

Lessons 4/4 · 15 min

What a header proves alone, and what it does not

The client that downloads only headers

A phone on a metered connection cannot download hundreds of gigabytes of blocks. The simplified payment verification section of Nakamoto's paper (Bitcoin: A Peer-to-Peer Electronic Cash System) describes a client that keeps only the longest chain's headers (in practice, the one with the most cumulative work) and asks for a Merkle branch for a transaction it cares about. What can it actually conclude?

What a header lets you verify alone

  • The link to the parent: the parent's hash is in the header, so a chain of headers is verified step by step.
  • The work (proof of work): is the header's hash below the target, and is that target the one the difficulty-adjustment rules require at that height? A header that declares a very easy target itself proves almost nothing: the bits field must also be compared with that of the previous blocks. The computation to redo is still a double SHA-256 of 80 bytes.
  • A transaction's inclusion, with a Merkle proof: is the transaction under the header's root? (workshop 106)
  • A balance, in a network that has a state root, with a proof against that root.

What still requires the body (and execution)

  • The validity of the transactions: correct signatures, no double spend, sufficient balances. A header can commit to invalid transactions.
  • The correctness of the state root: only executing the transactions checks it.
  • Data availability: the header does not prove the body was published.
  • The absence of a transaction: an inclusion proof shows an item is present, not that another is absent (except with particular structures: workshop 106).
  • Being on the right chain: a light client sees the headers its peers show it; if they are all malicious, or if it is eclipsed (workshop 107), it may follow a chain the rest of the world has abandoned.

Example: a proof that fails

The client receives a transaction T, its proof (the siblings at each level) and the root announced by the header. It recomputes: hash of T, then combines with each sibling, from the bottom up. If the final result equals the root, T is in the block; otherwise either the transaction was modified, or the proof is wrong, or the server is lying. A single changed byte of T changes the result (avalanche, workshop 104). You will do this in the security exercise.

What this does NOT guarantee

  • A valid Merkle proof says nothing about the block's depth or finality: you must also know where the header sits in the chain.
  • It does not say the transaction succeeded: in contract chains, an included transaction may have failed during execution (the receipt says so).
  • Light clients trust consensus: if the majority of power (or more than one third of validators) is malicious, an invalid header can look valid.

Recap

A header proves the link, work that matches the required target, or the consensus signature, and (with a proof) inclusion. It proves neither the validity of the transactions, nor the correctness of the state, nor data availability.

Interactive tool

Merkle tree explorer (toy)

One leaf per line (2 to 8). Pick a leaf to see its inclusion proof; edit a text to see which nodes change.

5 leaves

Nodes changed since the last valid input are underlined and marked "changed". Nodes on the chosen leaf's path are outlined. Last node of an odd level: it is duplicated as its own sibling.

Convention: leaf = SHA-256(UTF-8 text); parent = SHA-256(left ‖ right, raw bytes); odd node duplicated. Toy tree: Bitcoin double-hashes and serialises differently.

Interactive tool

SHA-256 of hex bytes

Paste bytes as hex: the hash covers the bytes, not the text of the digits. A second field is concatenated after the first.

Digest

…

Spaces, newlines and 0x prefixes are ignored.

Guided lab

The browser does not contact a real node over JSON-RPC: the headers below are generated for you, in Bitcoin's real 80-byte format, with fictitious values. You decode, recompute the double SHA-256, then reason about a transaction's journey. Decoding a header fetched from a real network is in the independent lab.

A browser is no substitute for a real terminal: this lab trains reading and reasoning; the real hands-on practice is in the independent lab.

A certified account is required

Graded activities record results in your name and are the basis for a credential. They therefore need a complete certified file and a current consent. Filling in the file does not verify your identity; the Secretariat can verify it afterwards ("Verified" badge).

  1. 1.Read the simple fields

    In the 160-hex-character header, locate the byte ranges from the table in lesson 1. With the bytes tool, read the version, timestamp and nonce little-endian, then give the UTC date (YYYY-MM-DD) matching the timestamp.

    Interactive tool

    Byte inspector

    Paste hex, cut out a slice and read it as a little-endian or big-endian integer.

    Length: 14 bytes

    0000020000000a006c1f
    00084d5e1d00ffff

    Slice as hex

    02000000

    Little-endian unsigned integer

    2

    Little-endian signed integer (two's complement)

    2

    Big-endian unsigned integer

    33,554,432

    Big-endian signed integer (two's complement)

    33,554,432

    Bytes reversed (hex)

    00000002

    UTC date of the slice (little-endian): 1970-01-01T00:00:02Z

    For example a block header timestamp. It can be read from the slice above.

    2009-01-03T18:15:05Z
  2. 2.Parent hash, difficulty and block hash

    On a new header, give the previous block hash as explorers display it (bytes reversed), the exponent of the bits field in decimal, and the block hash: double SHA-256 of the 80 bytes with the hexhash tool ("twice" option), then reversed order with the bytes tool.

    Interactive tool

    Byte inspector

    Paste hex, cut out a slice and read it as a little-endian or big-endian integer.

    Length: 14 bytes

    0000020000000a006c1f
    00084d5e1d00ffff

    Slice as hex

    02000000

    Little-endian unsigned integer

    2

    Little-endian signed integer (two's complement)

    2

    Big-endian unsigned integer

    33,554,432

    Big-endian signed integer (two's complement)

    33,554,432

    Bytes reversed (hex)

    00000002

    UTC date of the slice (little-endian): 1970-01-01T00:00:02Z

    For example a block header timestamp. It can be read from the slice above.

    2009-01-03T18:15:05Z

    Interactive tool

    SHA-256 of hex bytes

    Paste bytes as hex: the hash covers the bytes, not the text of the digits. A second field is concatenated after the first.

    Digest

    …

    Spaces, newlines and 0x prefixes are ignored.

  3. 3.Follow a transaction

    Answer the multiple-choice question: at which precise stage of the journey does a transaction gain which guarantee? Rely on the eight stages of lesson 2 (signing, broadcast, local validation, mempool, selection, block, block validation, finality) and locate the moment described in the question.

  4. 4.The state root's role

    Answer the multiple-choice question about two nodes that obtain different state roots after the same block. Use the merkle-explorer tool if you want to review how a modified leaf changes the root, then deduce what this reveals about their execution.

    Interactive tool

    Merkle tree explorer (toy)

    One leaf per line (2 to 8). Pick a leaf to see its inclusion proof; edit a text to see which nodes change.

    5 leaves

    Nodes changed since the last valid input are underlined and marked "changed". Nodes on the chosen leaf's path are outlined. Last node of an odd level: it is duplicated as its own sibling.

    Convention: leaf = SHA-256(UTF-8 text); parent = SHA-256(left ‖ right, raw bytes); odd node duplicated. Toy tree: Bitcoin double-hashes and serialises differently.

Security exercise — A light client facing a doctored proof

You are building the light wallet of a traders' cooperative. It keeps only headers. A "helper" server sends you, for a payment that is supposed to have been received, a leaf (the transaction text, hashed), a list of siblings, and the root announced by the block's header. The server claims the payment is in the block.

The exercise below generates such a proof with 8 transactions. It is sometimes authentic and sometimes doctored: the server changed the leaf or one of the siblings. Your wallet must credit the trader only if the recomputation reproduces the header's root exactly.

Recompute the root, compare it with the announced root, and say whether the proof is valid.

Workshop quiz

Eight questions drawn from a larger pool, 70% to pass. It opens once every lab checkpoint is passed. You can retake it: the draw changes.

A certified account is required

Graded activities record results in your name and are the basis for a credential. They therefore need a complete certified file and a current consent. Filling in the file does not verify your identity; the Secretariat can verify it afterwards ("Verified" badge).

Independent lab (outside the site)

Not graded online: do it on your own machine and publish it to your Git repository.

To do on your own machine, outside the site

Write, in Python, a header decoder for two different networks (for example Bitcoin and Ethereum, or Bitcoin and a Cosmos network), then compare their design choices.

  1. Fetch a header over JSON-RPC from a public node or from a test node you run. Use the method names from the network's documentation; do not guess them.
  2. For Bitcoin, decode the 80 bytes by hand (the struct module), recompute the double SHA-256 and check it is below the target given by the bits field, then compare that field with the previous block's: a target that changes for no reason is suspect.
  3. For the other network, list every header field and say what it commits to (parent, transactions, state, validators, timestamp).
  4. Produce a mapping table: field, role, size, present in the other network (yes/no), remark.

Any field you cannot find in the official specification must be marked "unverified". Use only test networks or public data: never put a real key in your scripts.

Takeaways

  • A Bitcoin header is 80 bytes: version, parent hash, Merkle root, timestamp, bits, nonce; the block hash is the double SHA-256 of those bytes.
  • A transaction goes through signing, broadcast, local validation, each node's mempool, selection, the block, block validation, then finality.
  • The state root commits to the state of all accounts after a block; Bitcoin has none in its header, Ethereum and CometBFT have an equivalent field.
  • A header proves the link, work that matches the required target or consensus and, with a Merkle proof, inclusion; it proves neither the transactions' validity nor the state's correctness.
  • A mempool is local to a node: there is no global waiting queue.

Common misconceptions

  • Misconception : The mempool is a single waiting queue that the whole network shares.

    In fact : Each node has its own mempool, filled by what it received and filtered by its own rules. Two nodes may hold different contents.

  • Misconception : A block contains every account's balance.

    In fact : A block contains transactions. The state (balances) results from them; the header may commit to it through a state root without containing the balances themselves.

  • Misconception : If the header is valid, all the block's transactions are valid.

    In fact : A header proves only its own link, its work or its consensus signature. Only nodes that replay the block body verify the transactions.

  • Misconception : A block's hash is stored inside the block itself.

    In fact : A block's hash is computed from its header. It appears in the *next* block's header (the "parent" field), not in its own.

Glossary

Block header
A small object summarising a block: link to the parent, commitment to the transactions (and sometimes the state), consensus elements.
Mempool
A node's local waiting queue: valid transactions not yet included in a block.
State root
Root of a Merkle tree (or equivalent structure) over the state of all accounts; the header thereby commits to that state.
Little-endian
Byte order of an integer where the least significant byte comes first. Bitcoin header integers are written this way.
Bits (compact target)
A 4-byte field encoding the target: one exponent byte then three mantissa bytes; target = mantissa × 256^(exponent − 3).
Light client
A client that keeps only headers and verifies specific items through Merkle proofs, without replaying blocks.