Describe relationships
Append private witnesses and public inputs, then constrain them with arithmetic, range, logic, and elliptic-curve components.
Learn circuits →Zero-knowledge tooling for Rust
Write a circuit once, choose the proving system that fits, and keep the surrounding cryptographic building blocks close at hand.
The mental model
Composer owns circuit semantics. Proof-system crates lower the same structure into their own representation, while gadgets add reusable cryptographic operations.
Append private witnesses and public inputs, then constrain them with arithmetic, range, logic, and elliptic-curve components.
Learn circuits →Compile the same circuit through R1CS for Groth16 or the width-four PLONKish backend for PLONK.
Compare systems →Reach for Poseidon hashing, Merkle openings, and Schnorr verification without rebuilding the cryptography.
Explore gadgets →A proof, end to end
Implement Circuit against a generic ComposerBackend.
Bind the stable circuit shape to Groth16 setup or PLONK public parameters.
Supply private witnesses and receive a proof plus ordered public inputs.
Check the proof in Rust, or generate an EIP-2537 Solidity verifier for a compatible EVM.
The smallest useful circuit
The private values stay in the witness. Only the result is appended as a public input.
impl Circuit for ProductCircuit {
fn circuit<B: ComposerBackend>(
&self,
composer: &mut Composer<B>,
) -> Result<(), CircuitError> {
let left = composer.append_witness(self.left);
let right = composer.append_witness(self.right);
let product = composer.gate_mul(
Constraint::new().mult(1).a(left).b(right),
);
let result = composer.append_public(self.result);
composer.assert_equal(product, result);
Ok(())
}
}