DC-NODE-32
DC derived enforcedRecovered-anchor rollback boundary on the single-producer live-follow path (PHASE4-N-AK AK-S2). After recovery to a bare bootstrap anchor, the single-producer follow path (run_node_sync) accepts a peer RollBackward whose target binds EXACTLY (slot AND hash) to the persisted recovered anchor point (DC-NODE-31 / BootstrapState.tip) as an IDEMPOTENT NO-OP boundary rewind: no WAL, no ChainDb mutation, no ledger mutation, no cursor. The anchor is a recovery snapshot boundary, NOT a stored servable block, and is NEVER synthesized into one (ChainDb::tip()/last_block_bytes/serve never return it). RollBackward(Origin) still fails closed (AI-S4a unchanged); every non-anchor, non-Origin rollback fails closed; the accepted point must bind to the PERSISTED anchor on slot AND hash, never peer-supplied alone. The anchor point consumed by run_node_sync is the single authority (BootstrapState.tip), threaded in -- NEVER re-read from the store inside the loop. The first forward block after the anchor admits through the EXISTING sole pump_block path (its prev_hash binds the recovered chain_dep) -- AK-S2 adds NO forward-link code (verified live by the OQ-AK-S2-2 probe: blocks 9-13 admitted via local_chaindb_tip, caught up to the relay tip, 0 errors). Recover->follow on the single-producer path is replay-equivalent (extends T-REC-05/DC-NODE-31 to the follow): same store + same ordered peer feed => byte-identical post-state and admit sequence. SCOPE: does NOT add general stored-block rollback-follow on the single-producer path (out of scope), and does NOT touch the participant path (run_participant_sync @ node_lifecycle.rs -- a separate follow-on obligation).
- Source
docs/planning/phase4-n-ak-s2-recovered-anchor-boundary-invariants.md + docs/clusters/PHASE4-N-AK/cluster.md
- Introduced in
- PHASE4-N-AK
Enforcement trace
Code
Tests 7
- crates/ade_node/tests/live_fork_choice_ai_s4bii.rs::ak_s2_rollback_to_recovered_anchor_is_idempotent_noop
- crates/ade_node/tests/live_fork_choice_ai_s4bii.rs::ak_s2_rollback_to_origin_fails_closed_even_with_anchor
- crates/ade_node/tests/live_fork_choice_ai_s4bii.rs::ak_s2_non_anchor_rollback_fails_closed_slot_and_hash_bound
- crates/ade_node/tests/live_fork_choice_ai_s4bii.rs::ak_s2_no_recovered_anchor_still_fails_closed
- crates/ade_node/tests/live_fork_choice_ai_s4bii.rs::ak_s2_after_anchor_noop_forward_block_reaches_pump_block_validation_holds
- crates/ade_node/src/node_sync.rs::ak_s2_valid_forward_block_admits_after_recovered_anchor_noop
- crates/ade_node/tests/live_fork_choice_ai_s4bii.rs::singleproducer_rollback_refused_by_run_node_sync
CI 0
no CI script — gap