Files
consensus/engine
zeekayandHanzo Dev 1dc9470996 chain: catch-up aims at what the VM applied, and replays what it missed
A validator keeps two records of the chain: the ledger, which holds what a quorum
decided, and the VM, which holds what this node executed. Finalization can fold the
ledger across a block the VM never applied, so the ledger legitimately runs ahead of
the applied head.

Catch-up read only the ledger. Every block in the gap is at or below it, so a node
that asked for the blocks it was missing threw all of them away as already-decided —
and counted a full batch accepted while applying none of it. Nothing retried, because
nothing recorded a failure, and the descent that exists to steer the window down is
suppressed by exactly that counter. A node in this state stops at a gap of any size.
It was found on a five-validator fleet stalled at gaps of 58, 65 and 1,836 blocks.

Two changes follow from one idea — a height is behind us only if we both agreed to it
and ran it:

settledHeight takes the lower of the two heads. A VM naming no accepted block reports
nothing about what it applied, and an absent reading is not a reading of zero, so the
floor drops only for a VM that names a block below the ledger.

replayFinalized executes the blocks between the two heads. These are not a finality
question — the network settled them long ago, and asking for a cert here asks it to
decide again, which the height guard correctly refuses. What is missing is execution.
The ledger names which block belongs at each height (IsFinalizedAt, matching canonical
or envelope, since a differing envelope over one canonical id is an alias); anything
else is refused, as is a height the ledger cannot speak for. Replay moves the applied
head and nothing else: no vote, no cert consumed, no ledger movement. A lying peer
earns a rejection.

Tests drive the live shape — ledger at N+k, VM at N — and assert VM.Accept, since the
finalized height is already N+k before a block is served and proves nothing. Both fail
under the ledger-only reading. The safety half covers an impostor at a known height
and any block at a height the ledger cannot vouch for; neither reaches the VM.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-14 19:18:51 -07:00
..
2025-12-19 08:49:11 -08:00