Skip to content

fix(mpc): pin the canonical production circuit at init - #13

Merged
mellowcroc merged 1 commit into
mainfrom
fix/pin-canonical-production-circuit
Aug 20, 2026
Merged

fix(mpc): pin the canonical production circuit at init#13
mellowcroc merged 1 commit into
mainfrom
fix/pin-canonical-production-circuit

Conversation

@mellowcroc

Copy link
Copy Markdown
Collaborator

A build made without the patched vendor tree resolves upstream gnark from the module cache and compiles a slightly different destination-v2 circuit (observed: 1,791,413 constraints instead of the canonical 1,789,750 — the reviewed vendor patches such as uints-constant-fold change the constraint system). Nothing fails on its own: init signs the wrong circuit into the ceremony definition, and every later stage coherently verifies against it. The fork surfaces only when the transcript is compared against the canonical circuit — hours later, if at all. (Found by making exactly this mistake during the 2026-08-20 production-mode Relay test.)

Change: pin the reviewed R1CS identity (sha256, blake2b256, size, constraint count) in internal/mpcceremony/canonical.go and reject a mismatch at production init with an error that names scripts/bootstrap-vendor.sh. Rehearsal mode and the rehearsal circuit are deliberately not pinned. Unit-tested with the observed unvendored fork as the negative case.

Also extends docs/mpc-ceremony-parallel-optimizations.md with the measured exact-K=21 numbers from the same test: contribution 56m54s → 7m02s (16 vCPU) / 8m01s (8 vCPU via relay participate), candidate verification 50m27s → 5m46s.

The pinned digests come from the canonical vendored build's signed ceremony definition; the existing reproducible-build CI compiles the same circuit, so any intentional circuit change will fail this check loudly and require updating the constants alongside the vendor patches.

A build made without the patched vendor tree resolves upstream gnark from
the module cache and compiles a slightly different destination-v2 circuit
(observed: 1,791,413 constraints instead of the canonical 1,789,750),
because reviewed vendor patches such as the uints constant folding change
the constraint system. Nothing fails on its own: init signs the wrong
circuit into the ceremony definition and every later stage coherently
verifies against it, so the fork is only discovered when the transcript is
compared against the canonical circuit hours later, if at all.

Pin the reviewed R1CS identity (sha256, blake2b256, size, constraint count)
and reject it at production init with an error that names
scripts/bootstrap-vendor.sh. Rehearsal mode and the rehearsal circuit are
deliberately not pinned.

Also record the measured exact-K=21 contribution and verification timings
from the 2026-08-20 Relay-driven production-mode first-head test in the
parallel-optimizations note.
@mellowcroc
mellowcroc force-pushed the fix/pin-canonical-production-circuit branch from 965ca90 to 619660c Compare August 20, 2026 17:09
@mellowcroc
mellowcroc merged commit a508eef into main Aug 20, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant