Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Conformance

Conformance behavior is pinned by two packs in crates/conformance, because the same category of question has to be asked of two different systems and the answer means something different in each case.

PackIDsJudged byAsserts
conformanceCT-CONF-001..005the in-memory double + fixture proverthe double’s vocabulary: public balances, fixture commitment ids, ct_* event codes
conformance-realCT-CONF-R01..R05the real crucible-simulator flow engineonly facts the engine publishes: op.<id>.accepted, its own event codes, its public state counts

Which harness judges which pack

A contract’s tag decides, never a heuristic. Every conformance-real scenario carries the real-engine tag, MockHarness::run_real_simulator judges it, and the CLI enforces the pairing:

crucible-scenarios run --tag real-engine --real-engine   # the engine judges these
crucible-scenarios run --category conformance            # skips them, with a note
crucible-scenarios report                                # runs each pack on its own harness

run refuses to judge a double-backed contract with the real engine (that contract’s vocabulary does not exist there, so a “failure” would say nothing about the engine) and refuses a real-engine-only selection without the flag. A test asserts the packs are not interchangeable: the real-engine contracts are not all satisfiable by the double, so the distinction is real rather than nominal.

Honest scope

Simulate: real. The conformance-real pack is judged by the actual crucible-simulator flow engine, compiled from the simulator repository at a pinned revision. A pass there is evidence about that engine.

Prove: mock. Both packs run against crucible-prover’s hermetic mock backend. Nothing here is yet a cryptographic conformance check; real UltraHonk/bb proving is heavyweight and opt-in in the prover repository. That is the remaining gap, and it is gated on the same external audit the prover repository needs — not on work in this one.

Anti-circular oracle design

The pack avoids the “simulator says X → ask the simulator → confirm X” trap. Expected outcomes are derived independently:

  • balances are computed from the declared deposit/transfer/withdraw amounts against the fixture starting ledger, by plain arithmetic in the scenario,
  • ownership is derived from the transfer’s sender/recipient,
  • proof validity expectations come from the pinned circuit version and the statement, not from the verifier’s own verdict,
  • every scenario also runs with all seven built-in invariants attached, so the pack judges global properties (conservation, ownership, commitment consistency) across whole runs, not just per-step effects.

What is covered (CT-CONF-001..005)

  • Register, deposit, merge, transfer, withdraw as independent conformance checks, each asserting events, balance deltas, ownership, and state effects.
  • A full-lifecycle conformance run (register → fund → merge → prove-and-transfer → withdraw) judged with every invariant attached.

What the engine pack covers (CT-CONF-R01..R05)

The expected counts are derived from the operation sequence alone, so they are an independent oracle rather than a restatement of the engine’s answers:

IDContractExpected from the sequence
R01a 40-unit depositexactly 1 live commitment, 2 accounts, 1 token, 2 transactions
R02two deposits then a mergethe two commitments consolidate to exactly 1
R03a funded 30-unit confidential transferthe spent commitment is consumed and two are created (live: 1 → 2), and no per-holder public balance is published
R04a 30-unit withdrawalcompletes under the engine’s withdrawal_completed event
R05the full lifecycleall five lifecycle event codes across seven steps, no rejection

Boundary

Conformance scenarios implement no state or proof logic. They compose the adapter services and assert on observed effects against independently computed expectations.