FABRKNT
Consensus Engineering — Building L1 Consensus on Reth
Consensus Fundamentals
Lesson 3 of 12·CONTENT18 min45 XP

Treat this page as a workbench, not a blog post. The goal is to extract a reusable mental model from the source and carry it into the rest of the Fabrknt stack.

Course
Consensus Engineering — Building L1 Consensus on Reth
Lesson role
CONTENT
Sequence
3 / 12

Lesson 3 — Ethereum's PoS — Casper FFG + LMD-GHOST

Question

Ethereum PoS is the canonical production deployment of a hybrid consensus design. Casper FFG provides finality; LMD-GHOST provides fork choice. They are two separate protocols composed. Read how they cooperate.

Principle (minimum model)

  • Casper FFG = the finality gadget. Validators attest to block pairs (source + target); 2/3 of stake-weighted attestations finalize. Two finalized checkpoints = the chain is finalized between them.
  • LMD-GHOST = the fork-choice rule. Latest Message Driven Greedy Heaviest Observed Sub-Tree. Picks the heaviest sub-tree based on the latest attestation from each validator. Continuous; doesn't wait for finality.
  • Together = finality + fork choice. LMD-GHOST tells you the canonical head right now; Casper FFG eventually finalizes it. Reorgs are possible within the finality window; impossible after.
  • Slot + epoch structure. A slot = 12 seconds; an epoch = 32 slots = 6.4 minutes. Casper attests once per epoch; finalization usually within 2 epochs (≈12 minutes).
  • Validator duties. Propose (one per slot) + attest (once per epoch) + sync-committee duty (rotating). Missing duties = small inactivity penalty; equivocating = slashing.
  • Three finality levels. latest (unconfirmed) / safe (~32 blocks back, likely finalized) / finalized (~12 minutes, irreversible). Applications pick the right level.
  • Inactivity leak. When > 1/3 are offline, finality stalls → every epoch the offline stake loses a small amount → eventually the chain self-heals back to > 2/3 online.

Worked example + steps

Ethereum's PoS — Casper FFG + LMD-GHOST

Ethereum doesn't run one consensus protocol. It runs two, stacked. LMD-GHOST decides which block is "the head right now"; Casper FFG decides "what's actually final and can never be reorged." Why two? Because at ~1 million validators, you can't do BFT-style instant finality without melting the network — but you also can't ship a chain where nothing ever truly settles. The hybrid is the compromise.

This lesson takes the hybrid apart so you can read the spec and know what each half is doing.

12 seconds × 32 slots × 2 epochs = 12.8 minutes. The next 4 sections explain why this number.

1. The two protocols

ProtocolRoleCadenceOutput
LMD-GHOSTFork choice — "what's the head?"Every slot (12s)Probabilistic head
Casper FFGFinality gadget — "what's final?"Every epoch (~6.4 min)Finalized checkpoint

LMD-GHOST runs continuously, picks the tip. Casper FFG runs at epoch boundaries, finalizes older blocks. Both rely on the same validator set — the ~1M ETH stakers.

2. LMD-GHOST in 60 seconds

Latest Message Driven, Greedy Heaviest Observed Sub-Tree. (The mouthful unpacks below.)

Each slot, validators do two things:

  1. Propose (if it's your slot) — broadcast a block
  2. Attest — vote on which block you think is the head (an attestation is a signed message naming a block)

The fork choice rule: for each block, count attestations in its subtree (weighted by stake). Pick the subtree with most weight.

Block A (proposed slot N)
├── Block B (slot N+1)        ← 60% of attestations in subtree
│   └── Block D (slot N+2)
└── Block C (slot N+1, conflicting fork)    ← 40% of attestations

The chain picks B as canonical. C is orphaned.

Key properties:

  • "Latest Message": only count each validator's most recent attestation (prevents long-range bribery via old votes)
  • "Heaviest Sub-Tree": count the subtree's weight, not just the immediate child (this is the GHOST part — gives weight to uncle confirmations)

The defense: selfish mining. Longest-chain lets a miner with 30% hashpower secretly build a chain and reveal it to orphan others. Heaviest-subtree forces stake-weighted attestations to make this much harder.

3. Casper FFG in 60 seconds

Friendly Finality Gadget.

Every 32 slots (one epoch ~ 6.4 min), the protocol picks the start of that epoch as a checkpoint. Validators vote on which checkpoint they justify.

The rule:

  1. Justification: 2/3+ of validators (by stake) vote to justify a checkpoint
  2. Finalization: a justified checkpoint is finalized when the next checkpoint is also justified

So finality takes 2 epochs minimum. After finalization:

  • Cannot be reorged — finalized blocks are permanent
  • Cannot be slashed away — even Byzantine validators can't undo finality

This is the BFT half of the hybrid. The 2/3+ rule is exactly the 3f+1 quorum from Lesson 1.

This is surround voting or double voting — both are slashable. Penalty depends on correlated slashing (how many other validators were slashed in the same window). Minimum: 1 ETH. Maximum: full stake (32 ETH) if many validators were slashed together.

4. Slashing conditions

Two slashable offenses:

OffenseWhat it looks likeWhy it's bad
Double votingSign two votes for the same epoch but different checkpointsCould split-finalize two conflicting checkpoints
Surround votingSign vote A then sign vote B that "surrounds" ACan't both be valid without forks

The math: if no validator double-votes or surround-votes, you can prove safety. So slashing makes attacks economically irrational — attempt = guaranteed loss of stake.

Slashing is cryptographically detectable. Anyone can submit a slashing proof to the chain; the validator's stake gets burned automatically. No trusted oracle needed.

Because an attacker needs to acquire stake (millions of ETH) and then lose it to attack. The cost of attack > value extractable. Stake is the security collateral.

5. The Engine API — where consensus talks to execution

Ethereum splits the node into two processes: a consensus client (CL — Lighthouse, Prysm, etc.) that runs the voting protocol, and an execution client (EL — Reth, Geth, etc.) that runs the EVM and stores state. They communicate over the Engine API — a JSON-RPC interface defined by the Ethereum spec, spoken locally between the two processes on the same machine.

sequenceDiagram
    participant CL as Consensus Client (Lighthouse)
    participant EL as Execution Client (Reth)

    Note over CL: Slot N — I'm the proposer
    CL->>EL: engine_forkchoiceUpdated(head, finalized, safe)
    CL->>EL: engine_getPayloadV4(payloadId)
    EL-->>CL: ExecutionPayload (built block)
    Note over CL: Sign + broadcast block
    CL->>EL: engine_newPayloadV4(payload)
    EL-->>CL: PayloadStatus { VALID }

Three methods do the work:

  • engine_forkchoiceUpdated — CL tells EL "the chain head is X, finalized is Y, prepare a block on top of X"
  • engine_getPayload — CL asks EL "give me the block you prepared"
  • engine_newPayload — CL tells EL "validate this block I received from another proposer"

Reth implements the EL side of this. That's where consensus integration happens.

🔍 Find in repo. Open reth's engine crate and find the engine_newPayload handler. Trace what happens when it returns VALID — what does the EL commit to disk before responding?

6. Why this matters for your L1

If you're building Tempo-class L1:

  • Probably not running Ethereum's CL — you have your own validator set, different slot times, different finality cadence
  • Probably using a Reth-compatible Engine API — so you can swap in different consensus clients
  • Definitely need slashing semantics — but customized for your validator set size

The two halves of Ethereum's hybrid (LMD-GHOST + Casper FFG) are the mental model for any new PoS chain. You'll likely simplify (no 1M validators = no need for the gadget split), but the slashing + 2/3+ quorum structure ports directly.

7. Reading list

8. Practice

Sketch on paper:

  1. Two competing checkpoints — when does the gadget finalize one over the other?
  2. A slashing proof — what data is in it? Why is that data sufficient?
  3. The handshake from CL to EL when a new block arrives from the network

Final check: in two sentences, why is "Ethereum finality takes 13 minutes" not a bug — what does the 13 minutes buy us that 1-second BFT finality wouldn't? If your answer doesn't include "validator decentralization at scale," re-read §1 of this lesson and §3 of last.

🛣️ The road not taken (Solana): Solana's consensus is Tower BFT + Proof-of-History (PoH) — a fundamentally different bet from Gasper. Tower BFT is a PBFT variant where validator votes anchor to a verifiable clock (PoH — a SHA256 hash-chain that serves as a deterministic timeline). Validators don't agree on time first and then vote; PoH is the time, and votes reference points along it. The result: ~400ms finality vs Ethereum's ~13 minutes, at the cost of much higher validator hardware requirements and a single-leader-per-slot model (no per-slot committees, no ~1M validator pool). Gasper trades latency for permissionless validator participation at scale; Tower BFT trades validator-pool size for end-user latency. Both are valid BFT answers; the choice tracks what the chain optimizes for — open participation vs sub-second finality.

Summary (3 lines)

  • Ethereum PoS = Casper FFG (finality, 2/3 stake-weighted attestations) + LMD-GHOST (fork choice, heaviest sub-tree). Two protocols composed.
  • Slot 12 s + epoch 32 slots; finalization within ~12 minutes. Validator duties: propose + attest + sync committee.
  • Three finality levels (latest / safe / finalized) for applications. Inactivity leak self-heals offline-validator scenarios. Next: HotStuff and HyperBFT.