Circom

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:

  1. Write circuit in .circom file (custom template language)
  2. Compile with circom compiler → generates R1CS constraint file + witness calculator
  3. Trusted setup → generate proving key (.zkey) and verification key
  4. Prove with snarkjs: provide private inputs (witness) → generate proof
  5. 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 powersoftau and snarkjs 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

  1. “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.
  1. “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.
  1. “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.
  1. “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.
  1. “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.