On this page
Start from the constraints
Teams often pick a proof system by name, usually the one their first tutorial used. It works better the other way round. Four questions decide most of it:
- Where is the proof verified? On Ethereum, every byte and every operation costs gas. On a server, verification is close to free.
- How big is the computation? A credential check and a full virtual machine trace differ by orders of magnitude.
- How often will the circuit change? Some systems tie their setup to one exact circuit.
- What may you assume? A trusted setup ceremony, or long-lived security against quantum adversaries.
Groth16
Groth16 has the smallest proofs and the cheapest verification of anything in common use. A proof is three elliptic-curve points; on the BN254 curve that is 128 bytes compressed. Verification is a constant number of pairings plus a little work per public input, which is why it has long been the default for verifying on Ethereum, where BN254 pairings are available as precompiles.
The price is the setup. Groth16 needs a structured reference string specific to each circuit. The first phase of the ceremony (the "powers of tau") is universal and reusable; the second phase is per circuit, so changing the circuit means running phase two again. Circuits are expressed as R1CS, which makes some operations, such as range checks and bit manipulation, comparatively expensive.
Typical tooling: Circom with snarkjs, gnark, arkworks.
PLONK and its descendants
PLONK keeps proofs small and changes the setup story. Its reference string is universal and updatable: one ceremony supports any circuit up to a maximum size, so you can change the circuit without a new ceremony.
With KZG polynomial commitments, proofs are still well under a kilobyte and verification is constant, though somewhat more expensive than Groth16 on-chain. The bigger win is the arithmetisation. PLONK-style systems support custom gates and lookup arguments, which make the operations R1CS struggles with (range checks, bitwise logic, many hash functions) much cheaper.
The family is large, and the commitment scheme is a choice in its own right:
- KZG gives small proofs and needs a trusted setup.
- Inner-product arguments, as in the original Halo2, need no trusted setup and give larger proofs with slower verification.
- FRI, a hash-based commitment, moves PLONK-style systems toward STARK territory.
Halo2 and Noir both sit in this family. Noir compiles to an intermediate representation that a proving backend consumes; its default backend, Barretenberg, uses a PLONK-family system.
STARKs
STARKs are transparent: there is no trusted setup at all. Security rests on collision-resistant hash functions, used to build Merkle trees and a low-degree test called FRI. Because no discrete-logarithm or pairing assumption is involved, STARKs are generally considered plausibly secure against quantum adversaries.
Provers scale well to very large computations and work over small fields that are fast on ordinary CPUs. The cost is proof size, tens to hundreds of kilobytes, and verification that grows (slowly, polylogarithmically) with the computation. Posting that on-chain directly is expensive.
The common answer is to wrap it: prove the large computation with a STARK, then prove the STARK verifier inside a Groth16 or PLONK circuit and post that small proof. Many zkVMs work this way. You keep fast proving and get cheap verification, and you inherit the wrapper's setup and assumptions for the final step.
Side by side
| Groth16 | PLONK (KZG) | STARK | |
|---|---|---|---|
| Setup | Trusted, per circuit | Trusted, universal and updatable | None |
| Proof size | Smallest (128 bytes on BN254, compressed) | Small (under a kilobyte) | Large (tens to hundreds of KB) |
| Verification | Constant, cheapest on-chain | Constant, a little more | Polylogarithmic, costly on-chain |
| Change the circuit | New phase-two ceremony | Same setup | Nothing to redo |
| Custom gates, lookups | No (R1CS) | Yes | Yes (AIR) |
| Quantum adversaries | Not secure | Not secure | Plausibly secure |
A way to decide
- Verifying on Ethereum, a stable circuit, and a ceremony you can run or trust: Groth16.
- Circuits still changing, several circuits, or heavy on hashing and range checks: a PLONK-family system such as Halo2 or Noir with Barretenberg.
- Very large computations, general programs, no trusted setup, or assurances meant to last against quantum adversaries: a STARK, wrapped if it has to be verified on-chain.
In practice the language often decides first. Circom leads to Groth16 or PLONK through snarkjs; Noir leads to its backend; Halo2 is its own stack. That is fine, as long as the choice is made on purpose.
The circuit usually matters more
Switching proof systems rarely saves as much as changing what the circuit does. SHA-256 or RSA verified inside a circuit can cost far more than any difference between Groth16 and PLONK. Where you control the primitives, use ones designed for circuits, such as Poseidon. Where you don't, for instance when verifying a government's signature, as in Anon-Aadhaar, budget for it from the start.
Then measure: constraint count, proving time and memory on the device that will actually prove, and verification cost where it will actually verify. A table like the one above narrows the choice; only numbers from your own circuit finish it.
