mirror of
https://github.com/luxfi/consensus.git
synced 2026-09-24 00:26:58 +00:00
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]>