Land records in India are, on paper, simple: a state government's sub-registrar office maintains who owns which plot. In practice they are a decades-long source of litigation. A single sub-registrar's database row can be edited, a document can be back-dated, and the same survey number can end up "sold" to two different buyers years apart because the one authority who could catch the conflict never cross-checked it against itself. Several state governments, including Andhra Pradesh and Telangana, have piloted blockchain-based land registries for exactly this reason: not because blockchain is faster or cheaper than a database (it is neither), but because it removes the single point of authority that could quietly rewrite the past. That trade, giving up speed and simplicity to remove a single trusted party, is the entire design story of a blockchain. Everything in this chapter is really one question answered from four angles: how do mutually distrusting parties agree on one shared history, without asking anyone to trust anyone else?
From a ledger to a trust problem
A ledger, in the oldest accounting sense, is an append-only record: you write new entries, you never erase old ones, and the current state is whatever the full history of entries implies. A bank's core database is a ledger. So is a spreadsheet of who owes whom in a chit fund. The problem is not the ledger itself, it is who is allowed to hold the one authoritative copy. If a single party (a sub-registrar, a bank, a clearing house) holds it, that party can rewrite history and no one can prove they did. This is not a hypothetical: back-dated mortgage releases and duplicate land titles are exactly this failure mode.
The fix that a centralized system uses is institutional: audits, courts, regulation. The fix a blockchain uses is architectural: instead of one copy of the ledger, every participating node keeps an identical full copy, and new entries are only accepted once independent nodes agree they are valid and consistent with everything before them. No party edits its own copy in isolation, because every other copy would then disagree with it, and disagreement is detectable by comparing a single number: a cryptographic hash. That is the mechanism this chapter builds, piece by piece: hashing, block-chaining, batching with Merkle trees, and the consensus rule that decides whose copy is "official" when two nodes propose the next entry at the same time.
Cryptographic hashing: from hash tables to tamper-evidence
You already know hash functions from hash tables: a function mapping an arbitrary-size key to a fixed-size bucket index, chosen to spread keys roughly uniformly so lookup stays close to O(1). A cryptographic hash function such as SHA-256 keeps the fixed-output-size and deterministic properties but adds three harder guarantees: given a hash, you cannot feasibly find an input that produces it (pre-image resistance); you cannot feasibly find two different inputs producing the same output (collision resistance); and changing even one bit of the input changes roughly half the output bits unpredictably (the avalanche effect). SHA-256 always outputs 256 bits, conventionally written as 64 hexadecimal characters, regardless of whether you hash one character or one gigabyte.
The avalanche effect is what makes tampering visible, and the worked example later in this chapter shows it directly: editing one transaction's amount inside a block, everything else held fixed, turns that block's hash from 00000f4abf6d836d67f1f736c448e47193203224e355a23eefd5ed6569260184 into ea8428a238e5a8671fad5bbed674c7ccfc2e9c652cf97d4b88326dff79c6e7af. No shared prefix, no visible relationship between old and new hash: exactly what "unpredictable" means here. A hash table's hash function has no such requirement; a cryptographic hash function is judged on it.
Chaining blocks: a worked example
A block groups a batch of ledger entries under a small header. That header stores two things that matter here: the hash of the previous block, and a single fingerprint of everything inside this block (built via a Merkle tree, covered next). The "previous hash" field is the entire "chain" in blockchain: verifying block i means recomputing its hash and checking it matches what block i+1 recorded as "previous hash". If anyone edits block i's contents after the fact, its hash changes (avalanche effect), so it no longer matches the value block i+1 is holding, and the break is detectable by anyone, instantly, without needing to trust the editor.
Here is a minimal but complete implementation, run for real to produce every hash, root and nonce shown in this chapter:
import hashlib
def sha256(s):
return hashlib.sha256(s.encode()).hexdigest()
def merkle_root(tx_list):
layer = [sha256(tx) for tx in tx_list]
if len(layer) == 1:
return layer[0]
while len(layer) > 1:
if len(layer) % 2 == 1:
layer.append(layer[-1]) # duplicate odd one out
layer = [sha256(layer[i] + layer[i+1]) for i in range(0, len(layer), 2)]
return layer[0]
class Block:
def __init__(self, index, timestamp, transactions, previous_hash):
self.index = index
self.timestamp = timestamp
self.transactions = list(transactions)
self.merkle_root = merkle_root(self.transactions)
self.previous_hash = previous_hash
self.nonce = 0
self.hash = self.compute_hash()
def compute_hash(self):
payload = f"{self.index}{self.timestamp}{self.merkle_root}{self.previous_hash}{self.nonce}"
return sha256(payload)
def mine(self, difficulty):
target = "0" * difficulty
while not self.hash.startswith(target):
self.nonce += 1
self.hash = self.compute_hash()
DIFFICULTY = 4
genesis = Block(0, 1000, ["Genesis Block: land parcel registry opens"], "0"*64)
genesis.mine(DIFFICULTY)
txs1 = [
"T1: Ramesh pays Canara Bank 5000000",
"T2: Suresh pays Priya 120000",
"T3: Priya pays Municipal Corp 8000",
"T4: Canara Bank pays RBI clearing 5000000",
]
block1 = Block(1, 1001, txs1, genesis.hash)
block1.mine(DIFFICULTY)
block2 = Block(2, 1002, ["Survey#402/A mortgaged to Canara Bank"], block1.hash)
block2.mine(DIFFICULTY)
Running this produces (SHA-256, difficulty 4, meaning a valid hash must start with four hexadecimal zeros):
Block 0 (genesis)
merkle_root: 3f8f908a8f46bc66c38a7f0c633843f7ab39dc30202f6a47c604f99064f64f6a
nonce: 63856
hash : 0000059af0e983989ca3fac6422b5a47d3730316f48e5ce01f66e47caa0602dc
Block 1
merkle_root: c61b35fc1e93c66710b910add7d89e35fa21204a889c56302f74b5d3db323d1f
nonce: 36225
hash : 00000f4abf6d836d67f1f736c448e47193203224e355a23eefd5ed6569260184
prev : 0000059af0e983989ca3fac6422b5a47d3730316f48e5ce01f66e47caa0602dc
Block 2
merkle_root: 2e2a2c91a74eb05595621aeee7b524b2a31d26e2cd2deb549d1c48483c6e8355
nonce: 24074
hash : 0000a2b3d308addbb31658080a2be9b08ceac8bd693bc12ab646aa5f468c9ad1
prev : 00000f4abf6d836d67f1f736c448e47193203224e355a23eefd5ed6569260184
Notice block 1's prev is exactly block 0's hash, and block 2's prev is exactly block 1's hash: that equality, checked at every link, is what "chained" means. The nonce is the field mine() is free to change while searching for a hash starting with four zero hex digits. Since SHA-256 output is effectively uniform over its 256 bits, the chance any single attempt starts with four hex zeros is 1 in 164 = 1 in 65,536, so the expected number of attempts before success is 65,536 (a geometric distribution with that mean). Our three blocks took 63,856, 36,225, and 24,074 attempts respectively, averaging 41,385, which is well within the normal spread of a geometric distribution around a mean of 65,536 for a sample this small. This searching is "mining": expensive to perform, but trivial to check, since verifying a candidate hash is one hash computation, not tens of thousands.
Now the tamper test. Suppose someone edits transaction T3 inside block 1's batch after the fact, changing an amount from 8,000 to 80,000, and honestly recomputes the merkle root and block hash but does not redo the expensive nonce search:
block1.transactions[2] = "T3: Priya pays Municipal Corp 80000"
block1.merkle_root = merkle_root(block1.transactions) # honest recompute
block1.hash = block1.compute_hash() # honest recompute, no re-mining
print(block1.merkle_root) # bfd60f692ed981c619a083565c877014a39ed69691a0b58363e9927e0305fc6a
print(block1.hash) # ea8428a238e5a8671fad5bbed674c7ccfc2e9c652cf97d4b88326dff79c6e7af
print(block2.previous_hash) # 00000f4abf6d836d67f1f736c448e47193203224e355a23eefd5ed6569260184 (unchanged)
Two things go wrong for the tamperer simultaneously. First, block 1's new hash no longer matches what block 2 recorded as "previous hash" (ea8428a2... versus the expected 00000f4a...), so any verifier walking the chain catches the break at block 2 immediately, an O(1) comparison. Second, the new hash does not start with four zeros, so even taken alone, block 1 no longer satisfies the network's validity rule and would be rejected outright. To hide the edit, the attacker would have to re-mine block 1 (another ~65,536 expected attempts) and then re-mine block 2, because block 2 now needs a matching new "previous hash" and its old nonce almost certainly no longer produces a valid hash for that new payload, and so on for every block published after it. This cascading re-work, not any encryption, is what "immutable" actually rests on; we quantify exactly how solid that rests when we correct a common misconception below.
Batching with Merkle trees: proving membership without reading everything
Real blocks hold thousands of transactions, not one string, so hashing the whole batch as one flat blob would make answering "was transaction T3 included in this block?" expensive: recomputing anything requires the entire transaction list. A Merkle tree fixes this by hashing transactions in a binary tree: leaves are individual transaction hashes, each internal node is the hash of its two children concatenated, and the single root hash is what actually goes into the block header, exactly the merkle_root field computed above. For block 1's four transactions:
H1 = SHA256(T1) = 1337ea4d6ed3... T1: Ramesh pays Canara Bank 5000000
H2 = SHA256(T2) = 5a8019b40102... T2: Suresh pays Priya 120000
H3 = SHA256(T3) = 425850a57d54... T3: Priya pays Municipal Corp 8000
H4 = SHA256(T4) = 27451da7cb78... T4: Canara Bank pays RBI clearing 5000000
H12 = SHA256(H1 + H2) = ce9859135152...
H34 = SHA256(H3 + H4) = 2f983ae7a291...
Root = SHA256(H12 + H34) = c61b35fc1e93c66710b910add7d89e35fa21204a889c56302f74b5d3db323d1f
That root is exactly block 1's merkle_root printed above, computed the identical way by the merkle_root() function. This is the binary tree you already know from DSA, with hashing standing in for comparison keys, height ⌈log₂ n⌉ for n leaves. That height is the whole payoff: to prove T3 was included, you do not need T1, T2, or T4's original data, only the two sibling hashes on the path to the root, H4 and H12. A verifier recomputes SHA256(H3 + H4), checks it equals H34, recomputes SHA256(H12 + H34), and checks it equals the published root. Two hash computations and two supplied sibling hashes prove membership among four transactions; for n transactions it is ⌈log₂ n⌉ sibling hashes, an O(log n) proof instead of an O(n) full scan. A light client, for instance a bank's mobile app, can hold only block headers (index, previous hash, merkle root, nonce) and still verify that a specific transaction is genuinely inside a specific block, without ever downloading the full transaction list. Note also why the tamper test above changed the entire root, not just a "T3 slot": editing T3 changes H3, which changes H34, which changes the root, which changes the whole header hash. A single-leaf edit anywhere in the tree cascades to the top by construction; that is what makes the root a fingerprint of the whole batch rather than of any one transaction.
Consensus: who is allowed to add the next block
Chaining and Merkle trees make tampering with the past detectable. They say nothing about who gets to propose the next block when the network has no central authority. If block creation were free, any node could flood the network with competing histories. Proof of Work, the mechanism inside mine() above, fixes this by making block creation deliberately expensive: you must find a nonce producing a hash below a target (equivalently, starting with enough zero digits), and the difficulty is tuned network-wide so this takes real, costly computation. The rule every node follows is simple: accept the longest valid chain you have seen. Since extending a chain costs real computational work, the longest chain represents the most cumulative work spent, and rewriting history means out-computing everyone else who is honestly extending the real chain, in real time, going forward.
This is where the 51% attack and its economics come from, and it is worth deriving rather than quoting. Model the attacker's deficit, the gap in blocks between the public honest chain and the attacker's secret fork, as a random walk: it grows by one whenever the honest network finds the next block first (probability p) and shrinks by one whenever the attacker finds it first (probability q = 1 − p). Starting at deficit z, this is the classical gambler's ruin problem, and the probability the deficit ever reaches zero (the attacker fully catches up) is exactly (q/p)z when q < p. With an attacker controlling 10% of network hash power (q = 0.1, p = 0.9, ratio q/p = 1/9 ≈ 0.111):
z = 1 confirmation : (1/9)^1 ≈ 0.1111 (11.1% chance the attack still succeeds)
z = 2 confirmations: (1/9)^2 ≈ 0.0123 (1.23%)
z = 6 confirmations: (1/9)^6 ≈ 1.88e-06 (0.00019%)
This is exactly why exchanges and payment processors wait for multiple confirmations before treating a blockchain transaction as final: each additional block the attacker must also out-mine multiplies their success probability down by another factor of q/p. It also shows why the "51%" threshold matters qualitatively, not just quantitatively: once q ≥ p, the ratio q/p ≥ 1, the attacker's success probability no longer shrinks with more confirmations, and given enough time an attacker with a hash-power majority can eventually rewrite any depth of history. Below 50%, the tamperer is fighting a losing race that gets exponentially less winnable the longer they wait; at or above 50%, it becomes only a matter of time and money.
How the pieces fit together
The diagram below is drawn directly from the values computed above: three peer nodes each hold an identical copy of the same three-block chain, and block 1's header commits to both the previous block (via previous_hash) and its own transaction batch (via the merkle_root built from H1 through H4).
The misconception: "immutable" does not mean "impossible to change"
Students consistently read "immutable ledger" as meaning a blockchain physically cannot be altered, the way a fact cannot be un-happened. That is wrong, and the gambler's-ruin derivation above shows exactly why. A block's data can be edited by anyone holding a copy: nothing stops you from changing a byte on disk, as the tamper test literally did. What blockchain immutability actually guarantees is narrower and entirely computational: any edit is (a) instantly detectable, because the hash chain breaks, and (b) astronomically expensive to make undetectable, because hiding it means re-mining that block and every block after it faster than the rest of the network is honestly mining new ones, and doing so before enough confirmations accumulate. "Immutable" is really "tamper-evident, and past a small number of confirmations, tamper-resistant to the point of being economically irrational to attempt", not "tamper-proof". This is precisely why exchanges wait for multiple confirmations on Bitcoin rather than trusting a transaction the instant it appears in one block: at z = 1, we derived an 11.1% success probability for a 10%-hash-power attacker; that number, not some absolute physical guarantee, is what "confirmed" is standing on. It is also why a blockchain controlled by a small number of participants (a "51% attack" is a threshold, not a magic barrier) offers far weaker guarantees than one distributed across thousands of independent, mutually distrusting miners: the whole security argument is economic, not cryptographic in the sense of "unbreakable".
Where this actually earns its cost, and where it doesn't
Proof-of-work consensus is slow and wasteful by design, since making block creation cheap would let an attacker skip the expensive part that secures it. Bitcoin produces one block roughly every 600 seconds; with a few thousand transactions per block, that works out to on the order of a handful of transactions per second, network-wide. UPI, by contrast, is reported to clear tens of thousands of transactions per second at peak, because NPCI is a single trusted clearing authority and does not need every participant to independently re-verify and replicate every transaction before it counts as settled. That is not a flaw in UPI's design, it is the correct engineering choice given that a trusted, regulated, single authority (NPCI, under RBI) already exists and works. Blockchain's overhead only buys something when that condition fails: when no single party is trusted by all participants, and colluding to rewrite the record would otherwise be one institution's unilateral decision. Multiple sub-registrars across state borders who don't fully trust each other's databases; a consortium of banks settling interbank transfers where no bank wants another bank's system to be the sole source of truth; a supply chain spanning several companies that need to jointly agree provenance without any one of them controlling the record: these are the shapes of problem where paying the throughput and energy cost of distributed consensus is worth it. Where a trusted central authority already exists and is doing its job, as UPI demonstrates at national scale, a normal replicated database with an audit trail solves the same problem faster, cheaper, and without inventing a new failure mode of its own (lost private keys, chain forks, majority-hash-power attacks) to replace the one it removed.
Active recall
Attempt these before reading the answers.
- A block's transactions are edited but its stored
hashfield is left unchanged (the attacker doesn't even recompute it). What check catches this, and how expensive is that check? - Why must a Merkle proof for one transaction in a block of n transactions supply exactly ⌈log₂ n⌉ sibling hashes, no more and no fewer, for a perfectly balanced tree?
- Using the gambler's-ruin formula (q/p)z, an attacker controls 25% of network hash power (q = 0.25, p = 0.75). What is their success probability at z = 2 confirmations? Is it larger or smaller than the 10%-attacker, z = 2 case worked in the chapter, and does that match your intuition?
- Explain, precisely, what is wrong with the sentence: "Blockchain data cannot be changed, that's what makes it secure."
- UPI processes vastly more transactions per second than Bitcoin. Is this a defect in blockchain's design that better engineering would fix? Justify your answer using what a trusted central authority buys you.
- Difficulty is raised from 4 hex zeros to 5 hex zeros. By what factor does the expected number of mining attempts change, and why?
Answers.
- Recomputing the block's own hash from its current fields and comparing it to the stored hash catches this immediately: they will no longer match, since the hash is a deterministic function of the block's contents. This is an O(1) check per block (one SHA-256 computation), independent of how much data the block holds, because only the compact header fields feed the hash, not a scan of the ledger's full history.
- Each level of the tree halves the number of hashes needed to reach the root, so proving membership only requires the one sibling at each of the ⌈log₂ n⌉ levels between the leaf and the root; that is precisely the height of a balanced binary tree over n leaves, the same bound as searching a balanced BST. Fewer siblings would leave a gap the verifier cannot bridge to the root; more would be redundant, since only one sibling is needed at each level to compute that level's parent.
- q/p = 0.25/0.75 = 1/3. At z = 2: (1/3)² = 1/9 ≈ 0.111, i.e. 11.1%. This is far larger than the 10%-attacker's z = 2 figure of about 1.23% computed in the chapter. That matches intuition: a stronger attacker (closer to the 50% threshold) closes the gap to the honest chain faster on average, so the same number of confirmations buys much less protection against them.
- The sentence conflates detectability with impossibility. Blockchain data can be changed by anyone holding a copy; what the design guarantees is that an undetected change is astronomically improbable past a few confirmations, because concealing it requires out-mining the honest network's ongoing work, a cost that grows with each additional confirmation via the (q/p)z relationship, not a cryptographic barrier that makes editing impossible outright.
- Not a defect, a different design point. UPI's speed comes from NPCI acting as one already-trusted clearing authority, so a transaction is settled once that single system validates it; no independent global re-verification and replication across thousands of untrusting nodes is needed. Blockchain's slower throughput is the direct cost of removing that single trusted party and replacing it with distributed, redundant, expensive-to-forge consensus. Where the trusted party already exists and is trustworthy, as with NPCI under RBI, paying blockchain's overhead buys nothing extra.
- Each additional hex zero constrains one more hex digit, which multiplies the target space by 16, so the probability of any given attempt succeeding drops by a factor of 16, and the expected number of attempts to succeed rises by the same factor of 16: from an expected 65,536 attempts (164) to an expected 1,048,576 attempts (165).
Think About It
Think about this: How would you explain blockchain: distributed immutable ledger to a friend who has never seen a computer? What real-world analogy would you use? Imagine you had to build a system using these concepts — what would be your first step? Try this: before moving on, write down three things you learned and one question you still have.
Key Takeaways — Summary and Recap
Let us recap what we covered: the core ideas behind blockchain: distributed immutable ledger, how they connect to real-world applications, and why they matter for your journey in computer science. Remember these key points as you move forward. For competitive exam preparation (CBSE, JEE, BITSAT), focus on understanding the WHY behind each concept, not just the WHAT.