Invariants / DC-EPOCH-16

DC-EPOCH-16

DC true enforced drift

Rolling Praos chain-dep nonce evolution on the live follow path. Each validated followed header drives ONE indivisible BLUE nonce transition over {slot, prev_block_hash, vrf_nonce_output, next_epoch_freeze_boundary}: evolving' = evolving (X) nonceValue(vrf_nonce_output); lab' = prevHashToNonce(prev_block_hash); candidate' = evolving' WHILE slot < freeze_boundary ELSE candidate (frozen), with freeze_boundary = firstSlotNextEpoch - RSW and RSW = ceil(4*k / f). The epoch tick computes epoch_nonce' = candidate (X) last_epoch_block_nonce, previous_epoch_nonce' = epoch_nonce, last_epoch_block_nonce' = lab, with evolving AND candidate carried UNCHANGED across the boundary (NO reset). (a) (X) = Nonce(blake2b256(a || b)), NeutralNonce identity; the Praos boundary combine carries NO extraEntropy operand (unlike TPraos TICKN). (b) EXPLICIT OPERAND PRESENCE: last_epoch_block_nonce is an explicit optional; the boundary combine FAILS CLOSED (MissingLastEpochBlockNonce) on an absent operand unless supplied by a valid bootstrap bridge (ECA-5) or a freshly-seeded B1 chain-dep -- a nonce is NEVER fabricated. (c) BACKWARD-COMPATIBLE DURABLE FORMAT: the chain-dep snapshot encoder ALWAYS writes the array(10) form (10th field null|bytes(32) = last_epoch_block_nonce); decode accepts EXACTLY arity 10 (full B1 state) OR the legacy arity 9 (last_epoch_block_nonce = explicit None, preserving the store's already-promised within-epoch operation and barred from the rolling cross-boundary combine). (d) BRIDGE EQUIVALENCE (hermetic, mandatory): the B1 epoch tick over the seeded seed-epoch snapshot nonces reproduces the live-proven ECA-5 bridge eta0(seed+1) byte-identically. (e) LIVE GROUND TRUTH: Ade's self-evolved eta0(seed+2) equals the live Cardano node's epochNonce(seed+2). CandidateFreeze as a separable transition is retired -- the per-header transition is indivisible.

Source

docs/clusters/EPOCH-CONSENSUS-VIEW/SLICE-ECA-B1-rolling-praos-nonce-follow.md; user directive 2026-06-25 (fold the live per-header Praos update into ONE HeaderContribution and retire the dead CandidateFreeze split; backward-compatible array(10)/legacy-array(9) chain-dep format; an explicit no-last_epoch_block_nonce form for legacy stores that fails closed before the rolling cross-boundary path -- never a fabricated nonce; the seeded-snapshot -> B1-tick -> eta0(seed+1) == ECA-5 bridge cross-check is a mandatory hermetic assertion; the live gate stays self-evolved eta0(seed+2) == cardano-node epochNonce(seed+2)). Pinned canonical rule from ouroboros-consensus Praos.hs (reupdateChainDepState + epoch tick), cross-checked vs cardano-ledger @ cb57dc730 (Updn/Tickn, BaseTypes, StabilityWindow). Praos boundary combine drops extraEntropy and uses last_epoch_block_nonce (the lab of the last block of E-1), diverging from TPraos TICKN. Operational detail (venues, slots, timing, commands, capture) is kept in an untracked competition-secret runbook.

Introduced in
EPOCH-CONTINUITY-ACTIVATION-ECA-B1

Enforcement trace

Tests 12

  • bridge_equivalence_seeded_snapshot_tick_reproduces_eca5_eta0 not on disk
  • header_contribution_advances_evolving_lab_candidate not on disk
  • candidate_freezes_at_freeze_boundary not on disk
  • epoch_tick_combines_candidate_with_last_epoch_block_nonce_no_reset not on disk
  • epoch_tick_rotates_last_epoch_block_nonce_from_lab not on disk
  • epoch_tick_fails_closed_on_absent_operand not on disk
  • chain_dep_array10_round_trip_some_and_none not on disk
  • chain_dep_legacy_array9_decodes_to_none
  • chain_dep_always_writes_array10 not on disk
  • b1_store_round_trip_reproduces_next_boundary_eta0 not on disk
  • seed_cinput_v6_persists_k_for_durable_candidate_freeze_window
  • sidecar_freeze_rsw_derives_from_store_and_cross_checks_the_cli

Cross-references

Strengthened in