Files
consensus/engine
zeekayandHanzo Dev e4e70c888b fix(engine/chain): advance the durable sign floor from Quasar only, never Nova
The vote guard's finalizedThrough — a validator's PERMANENT, fsync'd
sign-refusal floor — was fed from Nova (bare-majority) acceptance through
four separate paths. Nova acceptance is reorgable by construction: at n=5,
its quorum intersection is 2a-n = 1, which is NOT > f=1, so a Nova height
may never become certified. Welding an irreversible refusal to it stranded
each validator at whatever it happened to accept first, and no restart,
resync, or peer could clear the refusal because it was already on disk.

That is mainnet 96369 at 1098192 and testnet 96368 at 11367: a valid block
was built, verified, and gossiped to every peer, but was unsignable, so no
certificate could ever assemble. Zero errors logged. It also made rolling
upgrades impossible, because a restarted node came back refusing exactly
the heights the fleet still needed it to sign.

Quasar is the only tier whose intersection exceeds f (strict 2/3 of 5 gives
2a-n = 3 > 1), so a Quasar height is agreed by every honest peer and may be
closed forever. Nova keeps everything it legitimately owns — the ledger,
VM.Accept, preference, catch-up, rejoin — and simply stops closing heights.

The four paths, all cut:
  - acceptWithCertCore no longer prunes/advances the guard on Nova accept
  - ingestAttestation advances it after PromoteQuasar reports advanced,
    fsync'd BEFORE the export frontier is published (so a crash cannot
    leave vm.LastQuasarHeight ahead of the compaction), fail-closed with
    an in-memory rollback and the observer withheld on write failure
  - SyncState (RLP import / state sync / snapshot clone) is a recovery
    hint again; block data is not a certificate, and an import happens
    precisely when a fleet is below quorum
  - the Start boot seed from vm.LastAccepted is gone; the boot floor comes
    from the guard file and the export frontier the chain manager re-seeds
    from vm.LastQuasarHeight. A node with none of the three is genuinely
    memoryless and now says so loudly instead of inventing a floor

Compacting at the Quasar height RETAINS every binding in (Quasar, Nova].
Those heights stay guarded individually — one signature each, enforced by
memory of the actual vote — rather than closed by a blunt permanent floor.
That window is where a rolling upgrade lives: a restarted node can re-issue
its outstanding vote so the certificate can finally form.

Renames, so the tiers cannot be re-braided by a later edit:
  GetDecidedFloor          -> GetNovaAcceptedFloor  (build/catch-up only)
  pruneCommittedSlotsBelow -> compactVoteGuardThroughQuasar
  new: GetQuasarSigningFloor — the only source for a permanent refusal

Deliberately NOT a tier gate at cert intake. An earlier attempt to refuse
Nova certs in HandleIncomingCert broke three heal/rejoin tests, because
Nova certs ARE the recovery transport; nova_quasar_matrix_test.go:319
requires a healed fleet to re-converge on Nova. All three stay green here.

No ava/snow imports added.

Tests: engine/chain full suite ok 211s. Negative control — re-introducing
the Nova weld fails 4 tests with the exact halt signatures. New
quasar_signing_floor_test.go covers: Nova accept leaves both frontier and
durable floor untouched; Quasar promotion advances floor + compaction in
one atomic write; guard write failure rolls back and withholds the export
frontier; RLP import above the floor stays signable; restart keeps the
floor at Quasar while every uncertified height stays individually bound and
idempotently re-signable. Two existing tests re-sourced from vm.LastAccepted
to the export frontier, each gaining the inverse assertion that the
Nova-only window stays signable.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-30 07:03:57 -07:00
..
2025-12-19 08:49:11 -08:00