Invariants / DC-NODE-11

DC-NODE-11

DC derived enforced

Once --mode node has self-accepted and SERVED a genesis-successor block at block_no 0, it MUST NOT add/replace the served view (ServedChainView) with another block_no-0 block during the same recovered NO-TIP episode (durable ChainDb tip + recovered tip both None). The node-level serve gate admits a self-accepted forge handoff to the ServedChainView ONLY when its block_no STRICTLY EXCEEDS the highest already-served block_no (serve_gate_admits) -- so the FIRST block 0 wins the served view and the hermetic forge's subsequent block-0 re-forges (DC-NODE-05, no own-tip advance) are NOT re-served; a follower then sees a STABLE block 0 to fetch + adopt. NARROW: no durable own-tip advance (the own-tip-adoption path is a separate cluster); no forged block 1+ claim; no synthetic numbering; the served block is still self-accepted (no bypass of self_accept, no serve of unvalidated bytes); the forge + served_chain_admit + durable tip are UNCHANGED (DC-NODE-05 intact). PHASE4-N-U (DC-NODE-13) SUPERSEDES the serve_gate_admits MECHANISM with serve-as-projection: own-forged blocks are now durably admitted (DC-NODE-12) and the durable chain is extend-only (DC-CONS-23), so it holds exactly one block 0 by construction; the served view PROJECTS the durable ChainDb (ChainDbServedSource), serving that stable, coherent chain WITHOUT a monotone gate. The invariant (a follower sees a STABLE block 0, no block-0-replaces-block-0 churn) is PRESERVED and strengthened -- it now also survives restart (the durable ChainDb is recovered by T-REC-05; the accumulator was not).

Source

docs/clusters/PHASE4-N-F-G-R/cluster.md; docs/clusters/PHASE4-N-U/S3-serve-as-durable-chain-projection.md

Cluster
PHASE4-N-F-G-R
Introduced in
PHASE4-N-F-G-R

Enforcement trace

Cross-references

Strengthened in

Evidence notes

PHASE4-N-F-G-R S1 (2026-06-04). Capture-first (code + clean-follower live run): after G-Q + the follower RESET to genesis, Ade serves the right block_no (block 0) but the follower does NOT adopt -- 0 adoptions, 48x UnexpectedBlockNo(BlockNo 1)(BlockNo 0). CAUSE: the hermetic forge (DC-NODE-05) re-mints a genesis-successor block 0 each winning slot (7x, slots 120465/120537/...), and ServedChainSnapshot.blocks is an append-only BTreeMap<(slot,hash), AcceptedBlock> (served_chain.rs:40) whose served_chain_admit inserts each block with no block_no dedup -- so the served view accumulated multiple block_no-0 blocks; the follower downloaded one, expected block 1, got another block 0. FIX: the node-level serve sibling gates by serve_gate_admits (push to the ServedChainView only when block_no strictly exceeds the highest served) -- the first block 0 wins, re-forges skipped. serve_gate_admits_first_block_zero_then_skips_reforged_block_zero pins the gate decision (None->0 admit; Some(0)->0 skip; Some(0)->1 admit; lower/equal skip); serve_gate_keeps_first_block_zero_skips_reforge forges two distinct block 0s and proves the served view holds EXACTLY ONE. No forge/durable-tip/self_accept/served_chain_admit change (DC-NODE-05 intact). CE-G-R-2 LIVE-CONFIRMED 2026-06-04: a C1 rerun (follower reset to genesis) showed the follower ValidCandidate + AddedToCurrentChain Ade-forged genesis-successor block 0 (56a29ac4...c868f26f, slot 122520; cardano-cli query tip = that hash / block 0 / slot 122520; UnexpectedBlockNo churn gone). Bound the project's way: the follower-tip peer-accept event through ba02_evidence::correlate -> Agreed (forged == matched == 56a29ac4, peer_accept_source = chain_tip) -> PrivateRehearsalManifest at docs/evidence/c1-genesis-rehearsal-manifest.toml (is_rehearsal=true, not_bounty_evidence=true, venue=private-testnet-c1), with docs/evidence/c1-genesis-rehearsal-{peer-accept.jsonl,follower.log} as the correlate input + the raw cardano-node proof. NARROW CLAIM: C1 private rehearsal success ONLY -- NOT preprod, NOT bounty BA-02, NO RO-LIVE flip. OQ-R1 (separate cluster): full producer own-tip advance (forge -> adopt own block -> build block 1+). OQ-R2: served-chain completeness after a feed ingest. PHASE4-N-U S3 SUPERSESSION (2026-06-05): OQ-R1 + OQ-R2 are now closed by N-U. serve_gate_admits, ci_check_served_chain_stability.sh, and the serve_gate_* tests (serve_gate_admits_first_block_zero_then_skips_reforged_block_zero, serve_gate_keeps_first_block_zero_skips_reforge) are RETIRED (mechanism superseded -- justified test/CI removal). The stability property they enforced is now a structural consequence of serve-as-projection over the extend-only durable chain (DC-NODE-13): own-forged blocks are durably admitted (DC-NODE-12), a re-mint block 0 fails closed at the extend-only admit (DC-CONS-23), so the durable chain holds exactly one block 0 and the projection serves it stably -- proven by served_view_projects_durable_chain + served_view_retires_accumulator + ci/ci_check_served_chain_projection.sh, and now ALSO surviving restart (T-REC-05). The rule is preserved + strengthened, not weakened.