Zero-knowledge proofs

arithmetic circuit

An arithmetic circuit is how you translate "a computation" into a shape a proof system can reason about. Instead of CPU instructions, you express the computation as a graph of gates over a finite field, where every gate is either an addition or a multiplication of its inputs, and wires carry field elements between them. Any program that runs in bounded time can, in principle, be unrolled (flattened) into such a circuit — loops are unrolled, and branches become both sides multiplied by a selector — so proving "I ran this program correctly" becomes proving "I know wire values that make every gate in this circuit consistent."

The reason addition and multiplication suffice is that finite-field arithmetic can simulate Boolean logic and integer math: an AND is a multiplication, a NOT is 1 minus x, and comparisons or hashes decompose into long chains of these gates. The cost model of a circuit is essentially its number of multiplication gates (additions are usually nearly free in SNARKs), and this gate count is what ultimately drives proving time. A SHA-256 hash, for instance, costs tens of thousands of constraints, which is why circuit designers favor "SNARK-friendly" hashes like Poseidon that are cheap in native field arithmetic.

Circuits are the bridge between human-readable statements and the algebra of proofs. Downstream they are flattened into a constraint system (R1CS or a PLONKish layout), then into polynomials, then into a succinct proof. Writing them by hand is painful, so domain-specific languages and compilers — Circom, Halo2, Cairo, Noir — let developers describe the statement at a higher level and emit the gate-level circuit automatically.

A circuit is fixed and data-independent: at proving time it has no real branches or variable-length loops. Every possible execution path must be "baked in," which is why circuit size is bounded by the worst case, not the average case — a major reason proving general computation is expensive.