DC-SERVEMEM-01
DC derived enforcedPeer-driven serve range work is bounded. The --mode node serve path must not materialize an unbounded chain range, perform per-block full-index scans, or read more than MAX_SERVE_RANGE_BLOCKS blocks for a single peer request. Oversized ranges fail closed before unbounded storage/CPU work. The cap is a defensive implementation bound, not a Cardano semantic parameter, and cannot be disabled at runtime.
- Source
docs/clusters/PHASE4-N-AA/cluster.md; PHASE4-N-U cross-slice security review (MEDIUM finding)
- Introduced in
- PHASE4-N-AA
Enforcement trace
Code
Tests 12
- range_bytes_capped_returns_at_most_max
- range_bytes_capped_within_cap_not_truncated
- range_bytes_capped_respects_bounds
- range_bytes_capped_bytes_byte_identical
- range_bytes_capped_inverted_range_is_empty
- last_block_bytes_returns_highest_slot
- serve_range_over_cap_fails_closed
- serve_range_empty_window_is_empty_not_capexceeded
- serve_range_undecodable_in_range_fails_closed
- serve_range_inverted_range_fails_closed
- served_view_projects_durable_chain
- follower_fetches_coherent_history_incl_ingested_predecessor
Cross-references
Strengthened in
Evidence notes
Declared at cluster scoping (2026-06-05, user-confirmed). ENFORCED at the PHASE4-N-AA S2 close. Pre-RO-LIVE hardening item 1; closes the PHASE4-N-U cross-slice security review MEDIUM finding (peer-driven serve resource amplification). The serve-side analog of DC-LIVEMEM-01 (receive-side bounded memory). MAX_SERVE_RANGE_BLOCKS = 256 (symmetric with MAX_WIRE_PUMP_LOOKAHEAD; fixed/closed/non-configurable). No schema change: S1 added bounded hash-free slot-ordered ChainDb read primitives (range_bytes_capped + last_block_bytes; 5 contract tests run against BOTH PersistentChainDb + InMemoryChainDb). S2 switched ChainDbServedSource range_bytes/next_after/tip to those primitives, applied the cap (CapExceeded -> empty -> reducer NoBlocks), and derives each block's hash from its bytes via the single BLUE decode_block authority (no HASH_BY_SLOT index, no second hash authority). A closed ServeRangeOutcome enum distinguishes Served/Empty/CapExceeded/ReadError internally (all non-Served -> wire NoBlocks). Gate ci_check_serve_range_bounded.sh is non-vacuous: pre-S2 HEAD had 2 iter_from_slot + 1 chaindb.tip() serve calls (Guards 2/3 would fire); S2 has 0. Within-cap real-bytes serving (Served, byte-identical, derived hash == stored) is covered by the ade_node serve integration tests (real forged blocks). The trusted recovery/rollback iter_from_slot internals are OUT OF SCOPE (doc-fenced, not peer-driven).