Invariants / DC-EPOCH-12

DC-EPOCH-12

DC derived enforced

The promoted-epoch PoolDistrView is derived EXCLUSIVELY from the sealed EpochConsensusView + the bound-commitment- checked consensus profile (ECA-0b). EpochConsensusView::to_pool_distr_view(genesis_hash, protocol_params_hash, asc) -> Result<PoolDistrView, ProjectionError>: it FIRST verifies consensus_profile_commitment(genesis_hash, protocol_params_hash, asc) == self.protocol_params_commitment (else ParamsCommitmentMismatch, FAIL-CLOSED -- no unbound protocol-parameter is ever read into leadership), THEN requires is_leadership_complete() (else NotLeadershipComplete), THEN builds PoolDistrView{epoch, total_active_stake, asc, pools: per kept pool PoolEntry{active_stake: stake_by_pool[p], vrf_keyhash: pool_vrf_keyhashes[p]}}. NO live CertState read, NO re-aggregation, NO unbound param: the next-epoch leadership distribution is a pure projection of the frozen view. A rebind that combined the sealed stake/VRF with a live cert-state join or an unbound ASC is structurally impossible. Pure, total, deterministic.

Source

docs/clusters/EPOCH-CONSENSUS-VIEW/SLICE-ECA-0b-leadership-complete-view.md; user directive 2026-06-21 (no live CertState read at rebind; no unbound protocol-parameter read; ASC reaches the projection ONLY through the bound commitment)

Introduced in
EPOCH-CONTINUITY-ACTIVATION-ECA-0b

Enforcement trace

Tests 2

  • to_pool_distr_view_builds_from_bound_profile_and_rejects_wrong_params
  • projection_rejects_wrong_profile_through_the_real_derive_path

Cross-references

Attack rationale

The projection is the seam where a wrong leadership distribution could enter at rebind. The risks are closed: (a) a live CertState join -- to_pool_distr_view reads ONLY self (the sealed view), so the design's bound-activation prohibition (never combine a correct distribution with the wrong fork/epoch/cert-state) holds structurally; (b) an unbound protocol parameter -- the ASC (and the genesis/protocol-params identity) must match the bound commitment or the projection fails closed (to_pool_distr_view_builds_from_bound_profile_and_rejects_wrong_params + projection_rejects_wrong_profile_through_the_real_derive_path prove a wrong genesis/ASC -> ParamsCommitmentMismatch), so leadership never consumes a param the view did not commit to; (c) an incomplete distribution -- NotLeadershipComplete fails closed if any pool lacks stake or VRF. The wrong-profile rejection is proven THROUGH the real derive path (derive_candidate computes+binds the commitment, the projection rejects a different profile), not just a hand-built view.

Evidence notes

Introduced at EPOCH-CONTINUITY-ACTIVATION ECA-0b (2026-06-21). The CONSUMER of the leadership-complete view (DC-EVIEW-12): the next-epoch PoolDistrView is a pure projection of the sealed view + the commitment-checked profile. The mechanical encoding of the user directive 'PoolDistrView derives EXCLUSIVELY from the promoted view; no live cert-state join at rebind; no unbound protocol-parameter read'. ade_ledger 639 + ade_node 366 green. OBSERVE-ONLY: the projection is not yet consulted by live leader election (that is the activation slice, with EVIEW_ACTIVATION_ARMED=false until the live proofs); no live-path change. The rebind that calls this at a real boundary, the first unattended crossing, and the Model-A continuity test are ECA-1..5 -- still ahead.