A technical primer on how these systems work — not on any coin, market or product, none of which appear here. One idea explains most of the rest: a blockchain is a public database that many independent machines keep identical copies of, and nearly every surprising property is the price of removing the operator you would otherwise trust to hold it. That single trade produces the publicness, the permanence, the cost per operation and the finality rules. Read it as engineering and it stops looking like magic: it is a set of expensive trade-offs, most of which an ordinary database wins.
Each chapter opens with the short version. Tap one to read the detail.
A database with no owner, and the bill for that
~2 min
A blockchain is a public database shared across many computers and appended to rather than edited. It buys agreement without an operator anyone must trust, and charges privacy, speed, and the ability to fix a mistake.
It is a public database, updated and shared across many computers, organized into blocks that each reference their parent. Every node must agree on each new block and on the chain as a whole, and none takes another's word for it — each re-executes the work and computes the result itself.
Three consequences follow, and beginners are surprised by all three. First, publicness. The design requires transactions to be announced publicly; the founding proposal for this kind of system says so, offering exactly one privacy measure — keeping the keys anonymous. This is not a private store with public parts. It is a public store, and the moment one address is tied to a person, everything that address ever did is tied to them too.
Second, redundancy costs throughput: every verifying machine repeats every transaction, so whatever computation you allow per block becomes the hardware bill for everyone who checks. Third, "decentralised" is a spectrum rather than a badge — the useful question is how many independent parties would have to collude, which has a specific answer per system.
Rule: use a chain only when the requirement is that no single party may be trusted with the record; if you can name the party everyone already trusts, a database is cheaper, faster, private by default, and correctable.
Why tampering shows, and what "immutable" really claims
~2 min
Hashing is not encryption: there is nothing to decrypt and no key. It is a one-way fingerprint, and linking each block to its parent's fingerprint is the whole tamper-evidence mechanism. It makes an edit detectable, never impossible.
A hash function turns any input into a fixed-size digest, deterministically and irreversibly. Build on that twice and you have a chain. First, a block's transactions are hashed into a Merkle tree and only the root goes in the header, so one small value commits to the whole set and membership can be proven with the hashes along a single path, not the entire block. Ethereum uses a keyed variant for its state, where the only way to produce the state root is to compute it from every piece of state.
Second, each header names its parent's digest — the timestamping trick the founding design describes: each entry includes the previous inside its own hash, so every later block reinforces the ones before it.
Now the misconception. Immutable does not mean physically unwritable — these are ordinary files on ordinary disks. It means an edit is visible and expensive. Change one byte of one old transaction and its leaf hash changes, so the Merkle root changes, so the header changes, so every descendant's parent reference is wrong. Detecting the forgery is a hash comparison, not an audit; redoing everything after it is the cost that stops anyone bothering.
Rule: read "immutable" as tamper-evident rather than tamper-proof — and remember the same property makes your own mistakes permanent.
Possession of a key is the entire security model
~2 min
No account, no password, no reset: an address is computed from a key you generated and registered with nobody. A lost key is final, a copied key total, and a wallet stores the key rather than the assets.
An externally-owned account is controlled by whoever holds its private key. The public key is derived from the private one by an elliptic-curve signature algorithm, and the address is the last 20 bytes of the Keccak-256 hash of that public key. Nothing is registered anywhere: creating an account costs nothing because there is no registrar to pay — you pick a number, and the address falls out of it.
Hence the binary model — with the key you can do anything the rules allow, without it nothing — and the two beliefs it breaks. The first is that a lost key can be recovered: newcomers assume an owner of last resort — a support desk, a reset link, an issuer who can freeze and reissue — and there is none. The second is the word "wallet". Wallet software holds no funds, only a window onto the ledger and tools for signing, so the recovery phrase it makes you write down is the entire wallet to anyone else who reads it.
Concretely: save that phrase into a synced notes app and every device on that account can regenerate every key. Assets move, no error is raised, nothing reversible. Contract accounts change this: their own code decides what counts as valid authorization, allowing spending limits, shared control and recovery paths.
Rule: treat the recovery phrase as the asset itself; if you would not hand someone the balance, do not let them read the phrase.
Two ways to record who owns what
~2 min
Ownership is not stored the same way everywhere. One family tracks discrete unspent outputs consumed whole; the other stores a balance per account plus a counter that keeps order. The difference explains change outputs, stuck transactions and irreversibility.
In the older design a coin is a chain of signatures: each owner transfers it by signing over the previous transaction and the next owner's public key. Transactions take inputs and produce outputs, normally at most two — the payment and the change returned to the sender. That is the detail newcomers misread: spend 3 units from a 10-unit output and the whole output is consumed, with 7 coming back to you explicitly. In an explorer it looks as though 10 left.
The account design stores a number instead. An account's state is a nonce, a balance, a code hash and a storage root, where the nonce counts transactions sent. Transactions execute in nonce order, which produces the other classic confusion: submit nonce 8 with a fee too low to attract a proposer and nonces 9 and 10 sit behind it indefinitely, however valid they are. The queue is per account and strictly sequential.
Either way the lifecycle is the same: sign locally, broadcast to the network, wait in the pool of pending transactions, get included by a proposer, and only then reach finality. There is no recall step in that list.
Rule: before debugging a "missing" or "stuck" transfer, work out which ledger shape you are on — one explains it with a change output, the other with a nonce.
Consensus buys ordering, not validity
~2 min
Consensus does not decide whether a transaction is valid — every node checks that alone. It decides which of several valid histories everyone keeps, and that ordering is paid for with electricity or with destructible capital. The two offer different guarantees.
Because validity is settled independently by every node, agreement is only ever about order — which kills the commonest misconception here. A majority attacker is imagined as a thief able to drain any account or mint at will. It cannot: it reorders, censors, and can undo its own recent spends, because every node still validates and a signature it does not hold cannot be forged.
Proof of work pays with electricity. Miners vary a nonce until the block's hash falls below a target set by the difficulty; there is no shortcut, only more guesses; the average work rises exponentially with the leading zero bits demanded, while verification is a single hash. Difficulty follows a moving average, holding the block rate steady however much hardware joins. When two valid blocks appear at once, nodes keep both and the tie breaks when one branch accumulates more work — so transactions on the loser may end up nowhere, and "confirmed" is a probability. The founding analysis quantifies it: against an attacker holding a tenth of the hash power, 5 blocks put the risk under 0.1%; against three tenths, the same confidence needs 24.
Proof of stake pays with capital that can be destroyed. Time is cut into 12-second slots, 32 to an epoch, with a randomly chosen proposer and committee; participating means a fixed deposit, 32 ether on Ethereum. A checkpoint carrying votes from two-thirds of all staked value becomes justified, and once a later checkpoint is justified above it, the earlier is finalized. That is not a deeper block, it is a different claim: a competing finalized chain needs two-thirds of the stake, or at least a third of it destroyed. Equivocation — two blocks in one slot, or contradictory attestations — is slashed, up to a validator's whole stake when many offend together; and if too many go offline, an inactivity leak drains the absent until those left are two-thirds again.
Rule: ask what reversing a block would cost, never how many blocks sit on top — under work that cost decays as a probability, under stake it is capital somebody must forfeit.
Who actually enforces the rules
~2 min
No foundation and no vote of holders enforces anything. The rules are whatever independently run software accepts, which makes verification something you either do yourself or delegate, and rule changes something client teams coordinate rather than announce.
A node is an instance of client software talking to others running the same. Running one lets you check every block and transaction against the consensus rules yourself, trusting no other node. Node types trade storage against trust: a full node keeps recent state, an archive node everything back to genesis, a light node only headers — cheap, and it reintroduces an assumption. Since the move to proof of stake a node is two paired programs: an execution client running transactions and holding state, and a consensus client implementing the agreement protocol.
The trap is calling an application trustless while it reads the chain through one hosted endpoint. You then have that provider's guarantees, not the network's, because everything a chain promises concerns what a verifying node checks. Client diversity is the same argument at network scale: several independent implementations exist so no one codebase is a single point of failure.
Rule changes work the same way. An Ethereum Improvement Proposal (EIP) moves through Draft, Review, Last Call and Final; editors check soundness and formatting but explicitly do not pass judgment, and core changes need rough consensus among those who write and run the clients. Holding a coin is not a vote.
Rule: you inherit a chain's guarantees only as far as something you control actually verifies them.
A machine every node re-runs, metered by the step
~2 min
Contract code runs on every verifying node and must give identical results everywhere, so no clock, no randomness and no network call exists inside it. Since nobody can know in advance whether a program halts, it is charged per step.
One distributed state machine: old state plus transactions gives exactly one new state, and every node computes the same answer. Ethereum's virtual machine is a stack machine at most 1,024 items deep working in 256-bit words, a width chosen to suit the hashing and elliptic-curve arithmetic it has to do. Determinism is not a preference here — if contracts could pull outside data directly, two nodes would compute different values and consensus would break.
Metering follows from the same constraint. Nobody can decide in advance whether an arbitrary program terminates, so instead of proving it the protocol charges per step and halts when the budget is exhausted, which also makes spamming expensive. A plain transfer costs 21,000 units, and prices differ enormously by operation, so writing persistent storage dominates real contract design.
The misconception worth killing: a failed transaction is not a free transaction. Run out of gas midway and every state change is rolled back, but the gas consumed is gone. You pay a protocol-computed base fee — it moves by at most 12.5% per block with how full the last one was, and is burned rather than paid to anyone — plus a tip. Setting a high ceiling is not paying it; the difference is refunded.
Rule: you are buying execution steps, not outcomes, and you pay for the work that ran even when its result is discarded.
Contracts: what code can see, and why it cannot be patched
~2 min
Deployed bytecode cannot be edited at its address, so every upgrade is indirection rather than a patch. And visibility keywords say who may call a function, never who may read data — the ledger is public whatever you mark private.
A contract is state plus functions. Visibility governs calls: public is reachable inside and out, external only from outside, internal from the contract and those deriving from it, private only from the contract itself. Note what that is not — it restricts which code may reach a value, never who may see it. The database is public and every node stores the state, so reading private as "secret" is a mistake with real consequences. view promises not to modify state, pure not even to read it, and no contract can read back an event it emitted. Nothing runs on its own: every function needs an incoming transaction.
Compiling produces two artifacts. The chain stores only bytecode; the description of the functions — the application binary interface (ABI) — lives off-chain, which is why a caller needs it to encode anything.
Because bytecode is fixed at its address, upgradeability is architecture rather than editing. The usual shape is a proxy holding the storage and forwarding calls with delegatecall, which runs the target's code in the caller's context: the proxy's storage and balance, sender preserved. Upgrading means pointing at a different implementation — which is where reading "immutable" as "unchangeable" gets it backwards. The contract you audited can stay byte-for-byte identical while its behavior changes completely, so what users trust is whoever may swap it.
Rule: read a contract's trust story before its logic — who may replace the implementation is a bigger fact than anything in the current version.
Every caller is adversarial, and every bug is permanent
~2 min
Contract code sits where anyone can call it, in any order, from another contract you did not write. Combine that with immutability and a bug's consequences change in kind: no patch, no rollback, and the attacker never touches your interface.
The defining hazard is reentrancy: an external call transfers control to the callee, which can call straight back in before the first invocation has finished. The fix is ordering rather than cleverness — checks first, then state changes, then any interaction with another contract or account. Write the balance down before you send, and the callback finds nothing left to take.
The rest of the classic list has the same flavor. Arithmetic wrapped silently before Solidity 0.8.0, which now rejects overflowing operations by default. A function marked public or external is callable by any account or contract, so an unprotected privileged function is unprotected whatever the front end exposes. A low-level call reports failure in a return value instead of reverting, so ignoring it continues as though the call had worked.
Tokens make permanence concrete. A token is a contract keeping balances in its own storage, and moving one is that contract editing two numbers. To let another contract spend for you, approve records an allowance and allowance returns what remains — a number sitting in storage until spent down or overwritten. A bug found in that spender months later still reaches a wallet that has done nothing since, because a standing approval does not expire.
Rule: order every function checks, then effects, then interactions — and treat any approval you have granted as live until you revoke it.
Moving execution elsewhere, and where the trust goes
~2 min
A rollup executes transactions off the main chain and posts the data plus a state commitment back, which is what keeps it checkable. Bridging is different in kind: nothing crosses. Something is locked here and a claim is minted there.
Rollups run execution outside layer 1 and post the data back to it, where consensus happens. That posting is the whole security argument: without the data nobody can recompute the state or dispute it. Optimistic designs assume a batch is valid and only run the computation when someone challenges, which is why a native withdrawal waits out a dispute window of roughly seven days. Validity-proof designs verify a proof up front, so the wait is proof generation instead. A sidechain is a different animal: an independent chain with its own rules and its own security, inherited from nowhere.
Two things regularly surprise people. A sequencer's instant receipt is a promise from one operator — the transaction settles when its batch is accepted on layer 1 and any challenge period expires. And rollups hide nothing: a proof compresses verification, it does not add privacy.
Bridging concentrates the risk. Lock-and-mint and burn-and-mint move nothing: they immobilize an asset on one chain and issue a representation on another, which is a claim against whatever holds the original. A bridge attested by an external set of signers is a different risk model from one verifying proofs, and this category has produced some of the largest recorded exploits.
Rule: for anything cross-chain, ask what holds the original and who can move it — that, not the destination chain, is the security you actually have.
The chain cannot see out, and cannot hide the queue
~2 min
Determinism forbids a contract from fetching anything: outside facts arrive only as transactions someone sends, so a contract fed by one reporter trusts it completely. Publicness runs the other way — whoever orders a block reads your pending transaction first.
Because every node must reach the same result from the same inputs, a contract cannot call out to the world — if it could, nodes would fetch different values and consensus would break. External data arrives the only way anything arrives: some party submits a transaction writing it into a contract's storage. That relocates the trust problem rather than solving it, defeating a widespread assumption: that a trustless contract implies trustworthy data. It does not — a contract reading one reporter's feed is exactly as trustworthy as that reporter. The defense is many independent reporters agreeing before the value lands; the failure is a value that can be pushed around cheaply, which is what makes deriving a figure from on-chain trading activity exploitable.
The mirror image surprises people just as often: ordering. Whoever assembles a block chooses what to include, exclude and how to sequence it, and that choice carries value independent of fees — the term of art is maximal extractable value (MEV). A pending transaction is not private while it waits; it is visible to everyone before it executes, so a large one can be surrounded by transactions placed immediately before and after. One partial mitigation separates whoever builds a block from whoever proposes it, so a proposer is trusted with less.
Rule: a contract is only as trustworthy as its weakest input, and anything you broadcast is readable by whoever picks the order.
Written by Keentune. We are not affiliated with or endorsed by the organizations whose documentation informs this guide, and any linked sources belong to their respective owners.
All exam, test, and product names and trademarks are the property of their respective owners and are used here for identification and reference only. Keentune is independent study practice — not affiliated with, authorized, or endorsed by any of these organizations.