Zero-knowledge tooling for Rust

One API.One circuit.Multiple proof systems.

Write a circuit once, choose the proving system that fits, and keep the surrounding cryptographic building blocks close at hand.

product.circuitshape: stable
privateleft = 6
privateright = 7
constraintleft × right
backend 01R1CS / Groth16
backend 02PLONKish / PLONK
publicresult = 42
01Shared circuitsOne circuit definition, multiple backends
02Two proof systemsGroth16 and PLONK
03ZK-native gadgetsHashing, signatures, and Merkle openings
04Rust + no_stdExplicit feature and backend choices

The mental model

Separate what you want to prove from how you prove it.

Composer owns circuit semantics. Proof-system crates lower the same structure into their own representation, while gadgets add reusable cryptographic operations.

01 / CIRCUITS

Describe relationships

Append private witnesses and public inputs, then constrain them with arithmetic, range, logic, and elliptic-curve components.

Learn circuits
02 / PROVING

Choose a backend

Compile the same circuit through R1CS for Groth16 or the width-four PLONKish backend for PLONK.

Compare systems
03 / GADGETS

Compose useful primitives

Reach for Poseidon hashing, Merkle openings, and Schnorr verification without rebuilding the cryptography.

Explore gadgets

A proof, end to end

Four moves from values to verification.

01

Describe

Implement Circuit against a generic ComposerBackend.

02

Compile

Bind the stable circuit shape to Groth16 setup or PLONK public parameters.

03

Prove

Supply private witnesses and receive a proof plus ordered public inputs.

04

Verify

Check the proof in Rust, or generate an EIP-2537 Solidity verifier for a compatible EVM.

The smallest useful circuit

Prove that two secrets multiply to 42.

The private values stay in the witness. Only the result is appended as a public input.

product.rs
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(())
    }
}
Experimental, compatibility-sensitive softwareThis workspace coordinates evolving cryptographic crates. Review setup assumptions, feature selections, serialization boundaries, and audit status before production use.