Circom is the most widely adopted dedicated zero-knowledge circuit programming language, created by the iden3 team (Jorge Izquierdo, Jordi Baylina, and collaborators) and used to build arithmetic circuits that can be proven with zkSNARK proof systems. A “circuit” in ZK terms is a mathematical representation of a computation — specifically an arithmetic circuit over a finite field — where the circuit’s constraints define what constitutes a valid proof. Circom provides a domain-specific language that compiles to R1CS (Rank-1 Constraint System), the constraint format consumed by snarkjs and other proving backends. The Circom ecosystem is central to the ZK developer toolkit: most public ZK applications (Tornado Cash’s original mixer circuit, Semaphore’s anonymous voting circuit, many zkRollup components) were written in Circom. The tradeoff vs. higher-level ZK languages like Noir or Cairo is that Circom gives developers direct control over constraints — powerful but requiring careful attention to potential under-constrained bugs that could break soundness.
How Circom Works
Development Flow:
- Write circuit in
.circomfile (custom template language) - Compile with
circomcompiler → generates R1CS constraint file + witness calculator - Trusted setup → generate proving key (
.zkey) and verification key - Prove with snarkjs: provide private inputs (witness) → generate proof
- Verify on-chain or off-chain: submit proof + public inputs to verifier contract
Key Concepts:
- Signals: Variables in a circuit (can be input, output, or intermediate)
- Constraints: Equations that must hold for the proof to be valid (
===) - Templates: Reusable circuit components (like functions)
- Components: Instantiated templates in a circuit
- Witness: The set of all signal values satisfying all constraints
Signal Types and Constraints
“`circom
// Example: Simple multiply circuit
template Multiply() {
signal input a; // private input
signal input b; // private input
signal output c; // public output
c <== a b; // constrains: c = ab (both assign AND constrain)
}
“`
The Critical Bug Pattern:
“`circom
// BAD — assigns but does NOT constrain (soundness vulnerability!)
c <– a * b;
// GOOD — assigns and constrains (both are enforced)
c <== a * b;
“`
snarkjs Integration
Circom pairs with snarkjs (JavaScript/Node.js library):
- Setup:
snarkjs powersoftauandsnarkjs groth16 setup - Prove:
snarkjs groth16 prove(1 line, given witness + proving key) - Verify:
snarkjs groth16 verify(off-chain) - Export verifier:
snarkjs zkey export solidityverifier→ Solidity contract for on-chain verification
Notable Circom Circuits
| Circuit | Application | Usage |
|---|---|---|
| Tornado Cash | Privacy mixer | Nullifier/commitment scheme |
| Semaphore | Anonymous identity | Group membership proofs |
| Hermez rollup | zkRollup | Transaction validity |
| MACI | Voting | Anti-bribery voting scheme |
| zkEmail | Email proof | Prove email ownership |
Related Terms
Sources
- “Circom: A Circuit Description Language” — iden3 Team / circom.io (2020). Official documentation and specification of the Circom language — covering signal types, templates, constraint generation, and the compilation pipeline from Circom source to R1CS.
- “Under-Constrained Circom Circuits: A Security Taxonomy” — Trail of Bits (2022). Security analysis of Circom circuit vulnerabilities — documenting the under-constrained circuit bug class, real-world examples, and detection methodology.
- “snarkjs: zkSNARK Proofs in JavaScript” — iden3 (2020). Documentation for snarkjs — the JavaScript library that pairs with Circom to enable zkSNARK proving and verification, Solidity verifier generation, and trusted setup ceremonies.
- “circomlib: Standard Library of Reusable ZK Circuit Templates” — iden3 (2021). Documentation of circomlib — the standard library of Circom templates covering hash functions (Pedersen, MiMC, Poseidon), elliptic curve operations (EdDSA, BabyJubJub), Merkle trees, and common arithmetic components.
- “Halo2: An Updated, Production-Grade ZK Proving System” — Zcash (Electric Coin Co.) / PSE (2022). Introduction to Halo2 — an improved ZK proving system that replaces snarkjs/Groth16 in performance-critical applications, featuring UltraPlonk arithmetic with Lookup arguments, recursive proofs via inner product arguments, and no trusted setup.