CN-STORE-07
CN release enforcedSingle materialize authority for rolled-back state: the function that materializes (LedgerState, PraosChainDepState) at a target point uses ONLY one SnapshotStore lookup + ChainDb::iter_from_slot
- apply_block_with_verdicts (+ apply_epoch_boundary when crossing). No bypass; no parallel rolled-back-state computation path. Mirror of CN-CONS-08 (admission gate) for the rollback path. Single- public-function discipline; type-level + CI grep enforcement.
- Source
docs/planning/ledger-snapshot-rollback-invariants.md §1 (I-5)
- Cluster
- PHASE4-N-I
- Authority surface
- rollback materialization
Enforcement trace
Tests 5
- materialize_returns_rollback_too_deep_when_no_snapshot
- materialize_with_snapshot_at_target_returns_snapshot_state
- materialize_with_snapshot_below_target_replays_forward
- materialize_fails_closed_on_invalid_block
- materialize_replay_forward_equals_direct_apply
Cross-references
Strengthened in
Attack rationale
A parallel materializer can produce a rolled-back state inconsistent with what block_validity would compute, allowing peer-controlled state divergence.
Evidence notes
Enforcement is type-level: materialize_rolled_back_state is the sole pub fn returning the rolled-back state tuple. The function takes narrow read-only traits (SnapshotReader, BlockSource), not concrete chain stores — test-side and production-side go through the same single composition.
Evidence
ci_check_rollback_materialize_closure.sh enforces single-authority via grep: no other pub fn in rollback/* returns (LedgerState, PraosChainDepState). The driver composes one SnapshotReader::nearest_le + BlockSource::blocks_in_range + per-block block_validity (positive grep for block_validity call site).
The function takes narrow read-only traits (SnapshotReader, BlockSource), not concrete chain stores — production impls in ade_runtime (S4) go through the same single composition path.
N-J: the second production SnapshotReader impl (PersistentSnapshotCache) goes through the SAME single materialize composition — cross-impl equivalence with InMemorySnapshotCache proven via persistent_cache_matches_in_memory_cache_semantics. CN-STORE-08 (the snapshot-encoder counterpart to CN-STORE-07) also lands.
PHASE4-N-K strengthening: bootstrap warm-start branch routes directly through materialize_rolled_back_state (see ade_runtime::bootstrap), and ade_node binary calls bootstrap_initial_state exactly once (ci/ci_check_node_binary_uses_single_bootstrap.sh). bootstrap_warm_start_equals_direct_materialize proves bootstrap-warm-start = direct-materialize equivalence.