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

Reproducibility

What it means for a proof to be reproducible in this repository, and every pin that makes it so. Reproducibility is not just determinism of one artifact — it is a chain: same sources + same toolchains + same inputs ⇒ same bytecode, same manifest, same fixtures.

The pins

PinWhereEnforced by
Rust toolchain 1.98rust-toolchain.tomlrustup
nargo 1.0.0-beta.26TESTED_NARGO_VERSION in crates/noir/src/lib.rs, scripts/setup-noir.sh, CIversion gate in crucible-noir, CI install
bb 6.0.0-nightly.20260903TESTED_BB_VERSION in crates/ultrahonk/src/lib.rs, CIversion gate in crucible-ultrahonk, CI install
nargo × bb pairing + circuit versionsBACKEND_COMPAT in crates/ultrahonk/src/backend.rsprovider supports/check_supported
Canonical value encodingFieldValue/SecretValue canonical lowercase hex (no 0x, no leading zeros)constructors reject non-canonical forms
Envelope format v1 + deterministic JSONcrates/proof-typesserialization is field-ordered; parsing rejects future versions

Deterministic artifacts

Compiled bytecode is pinned with byte-for-byte reproducibility:

  1. Artifacts are generated by a deterministic path: per-package nargo execute (see scripts/generate-test-vectors.sh) — a whole-workspace nargo compile produces different debug-metadata ordering, so the generate path matters as much as the compiler version.
  2. crucible-prover artifacts generate writes bytecode + a canonical manifest.json (sorted file list, ordered JSON); identical bytecode reproduces byte-identical manifests.
  3. CI runs the fresh-compile determinism gate: generate to a fresh root and diff -r against the committed artifacts/circuits/ — a circuit change that forgets to re-pin, or a toolchain drift that changes bytecode, fails CI.
  4. The strict loader rejects any committed artifact that no longer matches its manifest (docs/artifacts.md).

Deterministic fixtures

  • Catalog vectors: expected public outputs are captured from real nargo execute runs, and the circuit tier re-checks them on every test run (docs/test-vectors.md).
  • Mock proofs are deterministic (same vector + same mock key ⇒ same bytes), so proofs/fixtures/ regenerate as a no-op diff unless the envelope format or a vector changed; scripts/generate-proof-fixtures.sh reproduces them exactly.

What is not claimed reproducible

Real UltraHonk proof bytes are produced by bb and are treated as opaque backend output; reproducibility guarantees apply to the context around them (artifact checksums, verification-key ids, public outputs, state binding), not to byte-identity of proofs across backend versions — which is precisely why backend version identity is pinned and carried on every envelope.

Regen workflow

MaterialCommand
Circuit vectorsbash scripts/generate-test-vectors.sh
Pinned artifactscargo run -q -p crucible-cli -- artifacts generate
Proof fixturesbash scripts/generate-proof-fixtures.sh

Each produces a no-op git diff when nothing changed — drift is loud by design.