Invariants / DC-CINPUT-07

DC-CINPUT-07

DC true declared

Conway deposit-parameter bootstrap authority. The Conway-only deposit params (drep_deposit / gov_action_deposit / drep_activity) are DECODED from the certified Mithril snapshot's Conway curPParams (the verified positions 27 govActionDeposit / 28 dRepDeposit / 29 dRepActivity) by the SINGLE canonical BLUE decoder (read_conway_pparams / decode_native_nonutxo_state), NEVER defaulted, guessed, fixture-derived, or read via a parallel parser. They are carried as a REQUIRED (non-Option) field on NativeSnapshotNonUtxoState, threaded by the native Mithril assembly into the assembled LedgerState.conway_deposit_params = Some(..) (never None on the Conway path), and copied by EpochAccumulator::seed_from_bootstrap_ledger into the accumulator — so a governance-active epoch boundary reaches drep_activity through LedgerState::gov_cert_env (GovCertEnv) and no longer fail-closes CertApply(ValidationEnvironment(MissingDRepActivityParam)). Tamper-evidence is dual: the three fields fold into the pparams component of fingerprint() (so the native bootstrap seed_hash / initial_ledger_fingerprint covers a substituted deposit param) AND into the v12 native-nonutxo-state S1a commitment. Durable fail-closed: EPOCH_ACCUMULATOR_SCHEMA_VERSION is bumped 1->2; a pre-fix v1 store fails closed at decode (UnknownVersion{ expected:2, found:1}) and a v2 Conway accumulator decoded with conway_deposit_params == None fails closed with the structured EpochAccumulatorCodecError::MissingConwayDepositParams — migration is an EXPLICIT re-bootstrap, never a silent reinterpretation as a defaulted set. Missing (curPParams arity < 31) or malformed (wrong CBOR type at the deposit positions) curPParams is TERMINAL (ProtocolParamsMissing / MalformedCbor), never a default substitution. NO fallback in the governance-cert environment: a missing param stays terminal (MissingDRepActivityParam), never patched to a default activity period.

Source

docs/active (CONWAY-DEPOSIT-PARAMS-BOOTSTRAP slice); native-bootstrap continuous-operation blocker: a preview re-follow bootstrapped at epoch 1338 stalled the accumulator at the 1339->1340 boundary with CertApply(ValidationEnvironment(MissingDRepActivityParam)) because assemble_native_mithril_seed hardcoded conway_deposit_params = None; user directive 2026-07-06 (import from the certified curPParams via the ONE canonical decoder; never default drep_activity; versioned durable fail-closed; no GovCertValidationEnv fallback).

Introduced in
CONWAY-DEPOSIT-PARAMS-BOOTSTRAP-S1

Enforcement trace

Tests 13

  • ade_ledger tests/ledgerdb_nonutxo_hermetic.rs::happy_minimal_state_decodes_all_fields (conway_deposit_params decoded from curPParams idx 27/28/29)
  • ade_ledger tests/ledgerdb_nonutxo_hermetic.rs::malformed_drep_activity_type_is_terminal (wrong CBOR type at idx 29 -> MalformedCbor)
  • ade_ledger tests/ledgerdb_nonutxo_hermetic.rs::malformed_pparams_arity_is_terminal (curPParams arity < 31 -> ProtocolParamsMissing)
  • ade_ledger tests/ledgerdb_nonutxo_hermetic.rs::wrong_era_is_terminal (pre-Conway native state -> UnsupportedEra)
  • ade_ledger::ledgerdb_state::tip_tests::v6_commitment_is_deterministic_and_binds_gov (v12 binds conway_deposit_params.drep_activity)
  • ade_ledger::fingerprint::tests::tampered_drep_activity_flips_pparams_fingerprint
  • ade_ledger::fingerprint::tests::pparams_fingerprint_includes_conway_deposits_when_present
  • ade_ledger::epoch_accumulator::tests::codec_v2_conway_without_deposit_params_fails_closed (v2 + None -> MissingConwayDepositParams)
  • ade_ledger::epoch_accumulator::tests::codec_rejects_unknown_version (v1 store -> UnknownVersion{expected:3, found:1}; expected bumped 2->3 by CE3D-BOOTSTRAP-FEE-BUFFER-S1)
  • ade_ledger::epoch_accumulator::tests::imported_deposit_params_cross_governance_boundary_and_reach_gov_cert_env (boundary regression: env reached unchanged, DRep cert applies, cross carries the params)
  • ade_runtime::mithril_native_assembly::tests::native_assembly_maps_each_field_from_its_source (conway_deposit_params imported from s1a, never None)
  • ade_runtime::chaindb::epoch_accumulator_store::tests::seal_advance_reset_round_trip_is_exact (v2 store round-trip carries Some)
  • ade_testkit tests/conway_deposit_params_single_decoder.rs::harness_and_blue_decoder_agree_on_conway_deposit_params (one-decoder proof: harness == BLUE on the same bytes)

Cross-references

Strengthened in

Attack rationale

Without a decoded source, drep_activity would have to be defaulted (e.g. a fabricated Some(20)) to cross a governance-active boundary — a silent authoritative substitution: a wrong DRep-expiry epoch (current_epoch + activity) mis-times DRep ratification denominators, and a defaulted deposit could mis-account a gov-action refund. The blocker made native bootstrap STRUCTURALLY unable to cross the boundary (fail-closed), so the tempting 'fix' is a None->Some(20) patch — exactly what this rule forbids. Decoding from the certified curPParams via the one canonical decoder + binding into the fingerprint/commitment makes the value manifest-bound and tamper-evident; the v1->v2 schema bump + MissingConwayDepositParams fail-close prevent a pre-fix store from being loaded as a defaulted set (it must re-bootstrap); the no-fallback GovCertValidationEnv keeps a genuinely-missing param terminal rather than papered over.

Evidence notes

Introduced at CONWAY-DEPOSIT-PARAMS-BOOTSTRAP-S1 (2026-07-06). The decoder already carried the verified curPParams field map (27 govActionDeposit / 28 dRepDeposit / 29 dRepActivity) in its doc comment and read 22/23/26; this slice reads 27/28/29 into the pre-existing ConwayOnlyDepositParams type and threads it: NativeSnapshotNonUtxoState gains a REQUIRED conway_deposit_params field; mithril_native_assembly flips the hardcoded None to Some(s1a.conway_deposit_params.clone()); the accumulator schema bumps 1->2 with a MissingConwayDepositParams fail-close. The one-decoder proof (harness parse_conway_gov_params vs BLUE decode_native_nonutxo_state on the same synthetic bytes) guards against the harness drifting into a parallel parser. Construction sites that build a None Conway accumulator and round-trip it (the empty-ctor test fixtures fresh_conway_acc / acc_bootstrap / acc_advanced / the node + advance sealed_store_at_epoch_500 helpers) were updated to carry Some, matching the production seed path (seed_from_bootstrap_ledger copies the now-populated ledger value). ade_ledger + ade_runtime + ade_node + ade_testkit green; ci/ci_check_conway_deposit_params_bootstrap.sh green. The byte-exact live boundary crossing is the pending acceptance gate (open_obligation).

Open obligation