CN-WIRE-08
CN derived enforcedN2N tag-24 CBOR-in-CBOR payload envelopes are constructed and stripped through ONE shared BLUE byte authority in ade_codec (wrap_tag24/unwrap_tag24). Protocol-specific composition lives in ade_network BLUE codecs: a served BlockFetch MsgBlock payload is tag24(bytes([era,block])) (era inside the wrap); a served ChainSync RollForward header is [era_tag, tag24(bytes(header_cbor))] (era_tag outside the wrap). Both compositions are pinned byte-identically against captured cardano-node 11.0.1 wire fixtures, not codec comments. No bare [era,block] may be served over BlockFetch and no bare header over ChainSync RollForward. No hand-rolled tag-24 parse may exist in RED — admission and interop call the shared authority. unwrap_tag24 fails closed (typed error) on non-(0xd8 0x18), wrong inner length, or trailing bytes. The inner bytes are copied verbatim (no re-encode).
- Source
docs/planning/phase4-n-x-invariants.md
- Cluster
- PHASE4-N-X
- Introduced in
- PHASE4-N-X
Enforcement trace
Code
Tests 24
- wrap_then_unwrap_is_identity_across_length_classes
- wrap_emits_canonical_tag24_marker_and_length
- unwrap_returns_zero_copy_borrow_of_input
- unwrap_rejects_missing_tag24_marker
- unwrap_rejects_non_byte_string_payload
- unwrap_rejects_truncated_inner
- unwrap_rejects_trailing_bytes
- inner_bytes_are_verbatim_not_reencoded
- unwrap_rejects_huge_declared_length_without_panic
- read_bytes_rejects_overflowing_declared_length
- read_text_rejects_overflowing_declared_length
- producer_block_fetch_serve_block_payload_is_tag24_wrapped_and_decodes
- producer_block_fetch_serve_block_bytes_equal_accepted_block_as_bytes
- block_body_is_wrapped_cbor_item
- captured_block_era_index_matches_ade_storage_scheme
- chain_sync_wire_era_index_is_consensus_index
- compose_decompose_rollforward_header_round_trips
- decompose_rollforward_header_rejects_non_tag24_inner
- conway_rollforward_header_served_shape_matches_oracle
- producer_chain_sync_serve_roll_forward_header_equals_accepted_block_header_bytes
- session_transcript_served_block_bytes_equal_admitted_accepted_block_bytes
- session_transcript_announced_header_matches_served_body_recipe
- cross_impl_server_pipeline_request_range_returns_decodable_bytes
- cross_impl_server_pipeline_request_range_byte_identical_to_self_accept_input
Cross-references
Attack rationale
Cardano-specific: a producer that serves bare [era,block] or bare headers is rejected by every real peer — block-fetch payloads and chain-sync headers are CBOR-in-CBOR on the wire. Worse, opaque-byte round-trip tests give false confidence (encode(decode(x))==x while the envelope shape is wrong). Binding both surfaces to one fixture-pinned authority makes a wrong-shape serve and a divergent second parser structurally impossible.
Evidence notes
BlockFetch oracle committed: corpus/network/n2n/block_fetch/local_preprod_tip_msg_01_block.cbor = 82 04 d8 18 59 03 ee 82 03 ... (= [4, tag24(bytes([era,block]))]), captured against docker preprod cardano-node 11.0.1, negotiated N2N v15. ChainSync header shape verified in ade_core_interop/src/follow.rs against a real preprod RollForward frame ([era_tag, tag24(header_cbor)], single wrapper); a committed golden header fixture pinning the SERVED shape is a slice-entry obligation for S3 (Q-1).