DC-PROTO-10
DC derived enforcedChain-sync server FindIntersect cursor: after the producer chain-sync server answers IntersectFound(point), its read cursor (last_announced) IS that point -- the next RequestNext serves next_after(point) (the successor the client rolls forward onto), never next_after(None) (the chain start). A non-Origin intersect that left the cursor unset would serve block 0 to a client whose read pointer is its own tip, which the client rejects as UnexpectedBlockNo(tip_block_no + 1)(0). An Origin intersect keeps the cursor None (serve from the chain start, correct).
- Source
docs/clusters/PHASE4-N-AE/slices/AE.E.md; docs/evidence/phase4-n-ae-ce-a5-relay-adoption.md
- Introduced in
- PHASE4-N-AE
Enforcement trace
Tests 1
- producer_chain_sync_serve_find_intersect_sets_cursor_then_rolls_forward_past_it
CI 0
no CI script — gap
Cross-references
Evidence notes
PHASE4-N-AE.E (2026-06-07): the actual CE-A5 closer. Across four prior CE-A5 reruns the real Haskell relay rejected HeaderEnvelopeError (UnexpectedBlockNo (BlockNo N) (BlockNo 0)): the FindIntersect handler resolved the intersect (the relay's own tip) and replied IntersectFound, but never set last_announced, so the next RequestNext served next_after(None) = block 0. ChainDbServedSource::intersect/next_after were verified CORRECT on the live store (intersect([block19@331])==Some((331,6ea841cc)); next_after==block 20); the defect was the SERVER not threading the resolved intersect into the cursor. Fix: state.last_announced = Block->Some((slot,hash)) | Origin->None. Origin-sync clients were unaffected (None is correct for them) -- why earlier producer-serve clusters (N-G) passed. With the fix, venue c2ae18 produced the CE-A5 manifest: a real cardano-node 11.0.1 relay AddedToCurrentChain Ade's forged block 17 (slot 421, hash db3b5675, issuerHash a1ed4e04 == blake2b-224(pool1 cold VK c14343dc); relay node2 forging=0; Ade forge succeeded=1). Evidence: docs/evidence/phase4-n-ae-ce-a5-relay-adoption.{md,jsonl}. Regression: producer_chain_sync_serve_find_intersect_sets_cursor_then_rolls_forward_past_it (FindIntersect at a non-tip block -> cursor set -> next RequestNext RollForwards the successor, not block 0).