DC-NODE-33
DC derived enforcedParticipant-path recovered-anchor rollback boundary (PHASE4-N-AL) -- the participant MIRROR of DC-NODE-32. On the participant live-follow path (run_participant_sync), a peer RollBackward whose target binds EXACTLY (slot AND hash) to the persisted recovered anchor point (DC-NODE-31 / BootstrapState.tip, carried in ForwardSyncState.recovered_anchor) is accepted as an IDEMPOTENT NO-OP boundary rewind: no commit_rollback, no WalEntry::RollBack, no ChainDb / ledger / chain_dep mutation, no cursor, no pending_reselection. The anchor is a recovery snapshot boundary, NOT a stored servable block, and is NEVER synthesized into one (ChainDb::tip()/serve never return it). The anchor branch is evaluated BEFORE the existing DC-NODE-29 stored-block resolution: RollBackward(Origin) still fails closed (AI-S4a unchanged); every non-anchor, non-Origin rollback still resolves through the EXISTING DC-NODE-29 authority (get_block_by_hash + stored slot/hash binding -> apply_chain_event or fail closed) UNCHANGED; the accepted anchor point binds to the PERSISTED anchor on slot AND hash, never peer-supplied alone. The anchor consumed by run_participant_sync is the single authority (state.recovered_anchor, set once in the forge-ON arm at node_lifecycle.rs:563 and threaded via run_relay_loop_with_sched -- never re-read from the store inside the loop). The first forward block after the anchor no-op admits through the EXISTING sole pump_block path (its prev_hash binds the recovered chain_dep) -- AL adds NO forward-link code. Recover->follow on the participant path is replay-equivalent (extends T-REC-05 / DC-NODE-31 / DC-NODE-32 to the participant follow): same store + same ordered peer feed => byte-identical post-state and admit sequence. DC-NODE-32 stays scoped to run_node_sync (NOT broadened; this is a distinct sibling rule). SCOPE: the recovered-anchor rollback-to-intersection case ONLY; does NOT add general multi-candidate fork-choice, does NOT change N-AJ evidence emission (DC-NODE-30), does NOT flip CN-CONS-03.
- Source
docs/planning/phase4-n-al-participant-recovered-anchor-boundary-invariants.md + docs/clusters/PHASE4-N-AL/cluster.md
- Introduced in
- PHASE4-N-AL
Enforcement trace
Code
Tests 5
- crates/ade_node/tests/live_fork_choice_ai_s4bii.rs::participant_rollback_to_recovered_anchor_is_noop
- crates/ade_node/tests/live_fork_choice_ai_s4bii.rs::participant_rollback_origin_fails_closed
- crates/ade_node/tests/live_fork_choice_ai_s4bii.rs::participant_rollback_non_anchor_fails_closed
- crates/ade_node/tests/live_fork_choice_ai_s4bii.rs::participant_first_forward_after_anchor_noop_admits_via_pump_block
- crates/ade_node/tests/live_fork_choice_ai_s4bii.rs::participant_stored_block_rollback_still_applies
CI 0
no CI script — gap