Circuits describe statements
A circuit does not describe a particular proof. It describes the relationship that every acceptable witness must satisfy. In Composer, those relationships are emitted as constraints through a backend-neutral API.
The same Circuit implementation can be lowered into R1CS equations or width-four PLONKish gates because it is generic over ComposerBackend.
Witnesses are private; inputs are public
A witness is a value known to the prover and hidden from the verifier. A public input is part of the statement the verifier checks. Their ordering is part of the protocol, not presentation detail.
let secret = composer.append_witness(self.secret);
let expected = composer.append_public(self.expected);
composer.assert_equal(secret, expected);For finalized R1CS assignments, the order is: constant one, public inputs in emission order, Composer witnesses, then lowering auxiliaries. Groth16 returns the public-input prefix without the constant-one entry.
Shape must be stable
Compilation binds the topology of a circuit: variable counts, constraint order, indexes, coefficients, and public-input count. Witness values may change between proofs; the emitted structure may not.
Shape binding catches mismatches
Groth16 setup records a canonical R1CS shape digest. A proof attempt is rejected if rebuilding the supplied circuit produces another shape. PLONK compilation similarly binds a circuit description and transcript context.
Backends lower shared semantics
Composer deliberately does not depend on a proving system. Instead, proof systems select a constraint representation:
- R1CS lowers arithmetic, range, logic, and elliptic-curve identities into sparse rank-1 equations for Groth16.
- PLONKish emits the width-four gates, selectors, and identities consumed by PLONK.
This direction of dependency keeps reusable circuit semantics independent from setup, commitment schemes, transcripts, and proof serialization.
Setup is part of the security model
Groth16
The current implementation uses circuit-specific, single-party setup. Its randomness is toxic waste and must be generated securely and destroyed. The repository does not currently implement multi-party contributions or ceremony verification.
PLONK
PLONK compiles circuits against reusable KZG public parameters. Their maximum supported degree must cover the compiled circuit domain. Transcript labels should be deliberate and stable.
Setup convenience does not remove operational responsibility: parameter provenance, storage, versioning, and circuit binding still matter.
Serialization defines compatibility
Serialized proofs and keys cross process, release, and backend boundaries. Treat their formats as protocol surfaces.
- Groth16 proofs use a fixed 192-byte canonical compressed encoding.
- Groth16 proving and verification keys use versioned, length-checked encodings.
- EIP-2537 Solidity verification uses a separate 512-byte uncompressed proof transport; it does not replace the canonical proof format.
- Archived curve representations produced with rkyv-impl can be backend-specific.
- Malformed points, identity parameters, wrong public-input order, or incompatible versions must be rejected rather than guessed.