Where session 2 sits in the ten
The practitioner track works through one engine in a fixed order: the primitive, the structure, the attack, the cost of the attack, then the things built on top, and finally a bench where all of it runs at once. Session 2 is the structure. Everything from session 3 onwards attacks it, prices it, or extends it, so a shaky picture here shows up four times later.
★ What you walk out with tonight. The six fields of a block, in order, and which five of them are hashed. The reason the genesis block's previous hash is a row of zeros rather than a computed value. And the Harbourgate register assembled in front of you, with the same six hashes any correct run produces.
Self-studyThe words that will keep coming back4 min▶
- Block. One record:
index,timestamp,data,prev,nonce,hash. - prev. The field holding the previous block's hash, all 64 characters of it.
- Genesis block. Block 0, whose
previs 64 zero characters by convention. - Block hash. The digest of the whole assembled block. Not the digest of the entry text.
- Nonce. A field that can change without changing what the block says. Idle at difficulty 0, and the subject of session 4.
- Difficulty. How many leading zeros a block hash must have. Zero for the Harbourgate register.
- Reproducible. Rebuilt from the same entries, the register gives the same six hashes, because the timestamps are fixed.
- verify. Recompute every hash and check every link. Returns ok on the untampered register, and session 3 breaks it.
Six fields, five of them hashed
12 min liveA block is an ordinary record. The interesting part is not any one field but the fact that the digest is taken over all five of the stored fields joined together, in a fixed order, rather than over the entry text on its own. The sixth field, the hash itself, is the output and cannot be an input.
...
LiveWhy the position and the timestamp are inside the digest4 min▶
If only the entry text were hashed, two identical entries would produce identical digests and could be swapped, duplicated or reordered without leaving a mark. Putting the index in the digest fixes the block to a position. Putting the timestamp in fixes it to a moment. Putting the previous hash in fixes it to a history.
So a block hash is a statement about five things at once, and any claim you make from a matching hash inherits all five. That is stronger than people expect and still narrower than the word immutable suggests.
LiveThe nonce is doing nothing, on purpose3 min▶
Every block in the register carries a nonce of 0, and at difficulty 0 nothing ever changes it. It is in the record because a block needs one field that can be varied freely without altering what the block says, so that a hash can be searched for rather than merely computed.
Press the nonce button in the box above and watch the digest move completely for a change from 0 to 1 that alters nothing anybody would read. Session 4 turns that uselessness into the entire cost model of mining.
Self-studyField order is part of the format3 min▶
The five fields are joined in a fixed order with a separator before they are hashed. Any other order, or any other separator, produces different digests for the same register, which would still be perfectly self consistent and would disagree with every other implementation.
That is the unglamorous reason serialisation formats get specified to the byte in real systems. A verifier and a writer that disagree about field order do not fail loudly. They just never agree on a hash, and the register looks permanently tampered with.
The first block has nothing to point at
7 min liveEvery block's previous hash field holds a computed value: the hash of the block above it, all 64 characters. Block 0 has no block above it, so the field is filled with 64 zero characters. That value was not computed by anything. It is a convention, and knowing that it is a convention is the point.
LiveWhy not hash something real into block 04 min▶
Some registers do exactly that. They put a newspaper headline, a court filing reference or a published document digest into the first block, so the start of the register can be dated from outside the system. It is a genuinely useful trick, and it does not change the structure at all, because that value still enters the block as data rather than as a verified link.
The zeros are the honest default. They announce that nothing precedes this block and make no claim at all about when it was written or by whom, which keeps the unanswered question visible instead of dressing it up.
LiveWhat a verifier does with the zeros3 min▶
Verification walks the register recomputing each block's hash from its own fields, and comparing each block's prev field against the hash of the block above. Block 0 has no block above it, so the link check simply does not run there, and only the hash check applies.
That asymmetry is worth holding on to. Block 0 is the one block whose position in history rests on nothing inside the register, which is why an attacker who can replace the whole register from block 0 onwards is a different threat from the one in session 3, and a much harder one to reason about.
Self-studyWhere the disagreement really is4 min▶
One camp holds that batching entries into blocks is an accident of network economics. If every entry simply carried the hash of the entry before it, you would get the same tamper evidence with less machinery, no block assembly, no batching delay, and a structure a reader can hold in their head. On this view the block is an optimisation that leaked into the conceptual model and then got taught as though it were the idea.
The other camp holds that the block is the unit of agreement, and that without it there is nothing to agree on. A batch is what participants vote on, what work is attached to, and what gets accepted or rejected as a whole. Remove the block and the tamper evidence survives but the mechanism for many parties converging on one history does not.
Both are right about different things, which is why the argument survives. Notice that a single organisation keeping one register has no need of the second camp's answer, and that is the shape most internal projects actually have.
makeChain, and the six blocks it produces
9 min liveAssembly is a loop with one carried variable. Start with the previous hash set to 64 zeros, build a block from the next entry, hash it, store the hash, and carry that hash forward as the next block's previous hash. Six entries in, six blocks out, and the hashes below are what any correct run produces.
...
LiveWhy the register is reproducible, and why that is artificial4 min▶
The timestamps are set by the loop, starting at 1758000000 and advancing 600 seconds per block, so rebuilding the register from the same six entries produces the same six hashes every time. That is what lets a number in a diagram be checked against a number on your screen, and it is the only reason these pages can quote hashes at all.
A real register reads a clock, so two runs never agree, and the hashes are unique to the moment. Take the reproducibility here as a property of the teaching model. Everything else on this page survives the switch to a real clock. That one does not.
LiveThe loop is four lines, and one of them is the whole idea3 min▶
Build a block from the entry. Set its prev to the carried value. Hash it. Carry that hash forward. The third and fourth lines are ordinary; the second is the structure. Everything sessions 3 and 5 do is an attempt to survive that one assignment being wrong for a single block.
Notice also what the loop does not do. It does not check the entry, it does not ask who submitted it, and it does not compare it with anything. Those are sessions 7 and beyond, and none of them are supplied by the arrangement you are looking at.
Self-studyDifficulty 0 is a deliberate choice here3 min▶
Assembly takes a difficulty option, and the register uses 0, meaning each block's hash is computed once and accepted. Every structural property on this page holds exactly as it would at any difficulty: the fields, the link, the genesis convention, the reproducibility.
Raising the difficulty changes one thing only, which is how much a block costs to produce and therefore to redo. It is worth seeing the structure work with no cost attached at all, so that when session 4 attaches one you can say precisely what it bought.
Assemble it yourself
17 min hands onConsole open on this page. The same six entries, the same engine, and the hashes in the table above are what you should get back.
Check the hash before you read the chain
Run CHAIN.selfTest().ok first, as in session 1. Then build the chain and compare the six truncated hashes with the table above. If the first one is not 608eba0870199b95, stop and find out why before going further.
Look at block 0's prev
Print chain[0].prev and count the characters. Then say, out loud, which part of the engine decided that value and what would happen if a second register used a different convention.
Rehash a block and compare
CHAIN.hashBlock(chain[2]) === chain[2].hash should be true. That single comparison is what verification does six times, and it is the whole of tamper detection before an attacker gets clever.
Prove the entry digest is not the block hash
Compare CHAIN.sha256(chain[2].data) with chain[2].hash. Two different values for the same entry. Write one sentence explaining why, using the word fields, and keep it for session 3.
Move the clock by one second
Copy block 4, add 1 to its timestamp, and rehash it. Count how many of the 64 characters moved for a change nobody in a cold store would notice. Then say what that implies for any register whose timestamps come from more than one machine.
Break a link on purpose
Set chain[3].prev to block 1's hash instead of block 2's and run CHAIN.verify(chain). Read what comes back, including which index it names. Session 3 starts from exactly this output, with an attacker who is trying to make it go away.
The habit to keep. When you are handed a register, recompute one block's hash from its own fields before you believe anything else about it. If that single check fails, no argument about consensus, mining or governance is worth having yet.
Three questions
What is a block's hash taken over?
Five stored fields go in and the hash comes out, which is why the sixth field cannot be one of the inputs. It also explains why the digest of "Consignment 41 inspected, seal intact" is not block 2's hash: the entry is one of five things in the digest, not the only thing.
The genesis block's prev field holds 64 zero characters. Where did that value come from?
The hash of the empty string is e3b0c442 and so on, and it is not what sits in block 0. The zeros are written there because the field has to hold something and there is nothing to put in it. That makes block 0 identifiable as the start, and supplies no confidence in block 0 itself.
Rebuilding the Harbourgate register from the same six entries gives the same six hashes every time. Why, and what should you conclude about real registers?
Timestamps start at 1758000000 and advance 600 seconds per block, which is what lets a printed hash be checked against your screen. It is a property of the teaching model. Every other property on this page survives a real clock; this one does not.
Homework
Twenty five minutes, writing a register of your own rather than reading one.
Build a register from your own records
Take six real rows from a log or audit trail you work with and assemble them the way the loop does: fixed timestamps, prev carried forward, 64 zeros in the first block. Confirm your own verification passes on the result.
Decide what your fields are
Write down which fields you chose to hash and which you left out, and why. Bring the list to session 3, which attacks it. Anything you left out of the digest is something an attacker can change for free, and that is the sentence worth arriving with.
What this session covers
Cheat sheet
index, timestamp, data, prev, nonce, hash.