Zero-Knowledge Proofs

A zero-knowledge proof lets one party convince another that a statement is true while revealing nothing beyond its truth. Not a summary, not a redacted version — nothing. You can prove you know a password without transmitting it, that you're over 18 without revealing your birthdate, or that a million transactions executed correctly without anyone re-running them.

The last of those is why the field went from cryptographic curiosity to production infrastructure. Succinct proofs are small and fast to verify regardless of how much computation they attest to, which means a blockchain can verify a proof of a million transactions in milliseconds. That property drives validity rollups, and it's increasingly used outside blockchains entirely — verifiable computation, private identity, and proving that a specific ML model produced a specific output.

TL;DR

Quick Example

A ZK circuit for the classic private membership proof — "I'm in this set, and I haven't claimed before" — written in Circom:

The verifier learns: the prover knows a secret in the tree, and this nullifier is now spent. It learns nothing about which leaf. That's the entire mechanism behind private voting, anonymous airdrops, and privacy pools.

Core Concepts

The three properties

The simulation definition is the rigorous one and worth internalizing: a proof is zero-knowledge if a verifier who doesn't have the secret could produce an identical-looking transcript on their own. If they could have faked it, watching the real one taught them nothing.

The classic intuition

Interactive proofs like this are the foundation. The Fiat-Shamir transform makes them non-interactive by replacing the verifier's random challenges with a hash of the transcript, which is what makes proofs postable to a blockchain.

Arithmetic circuits

A ZK system doesn't prove statements about programs. It proves statements about systems of polynomial constraints, so any computation must first be flattened into one.

This is why writing ZK circuits is unlike ordinary programming:

A common beginner mistake is porting an algorithm directly and producing a circuit with a hundred million constraints that takes hours to prove.

SNARKs vs. STARKs

The families are converging: modern SNARK systems (PLONK, Halo2, Nova) use universal or no trusted setups, and STARK proofs are often wrapped in a SNARK for cheap on-chain verification. The choice is increasingly about proving system maturity and tooling rather than a hard tradeoff.

Trusted setups

Some SNARK systems need a one-time ceremony generating public parameters from secret randomness. That randomness — the toxic waste — must be destroyed. Anyone who retains it can forge proofs of false statements.

Multi-party ceremonies mitigate the risk: many participants each contribute randomness, and the setup is secure if at least one destroyed their contribution. Ethereum's KZG ceremony for EIP-4844 had over 140,000 participants, which makes the assumption about as weak as an assumption gets. Still, "no setup required" is a real advantage of transparent systems, and it's why STARKs are favored where trust minimization is paramount.

What They're Actually Used For

Scaling — the dominant use today

Validity rollups prove that a batch of transactions executed correctly. Ethereum verifies one small proof instead of re-executing thousands of transactions.

Worth stating clearly: this use is about succinctness, not privacy. zkSync and Starknet transactions are fully public. The "zero-knowledge" property is incidental to the reason they're used.

Privacy

The compliance tension is genuine and unresolved: the same primitive that protects legitimate financial privacy also frustrates sanctions enforcement. "Privacy pools" that let honest users prove non-membership in a set of illicit deposits are the leading technical proposal for threading it.

Identity and verifiable credentials

Selective disclosure is the natural fit: an issuer signs a credential once, and the holder proves individual claims from it without revealing the rest, and without the verifier contacting the issuer. This works entirely without a blockchain and is arguably the largest non-crypto application area.

Verifiable computation

Prove that an off-chain computation was performed correctly — a machine learning inference, a data query, a game state transition. zkML proves a specific model produced a specific output, which is a real answer to "did the service actually run the model it claimed?" These are early but no longer theoretical.

Building With ZK

The toolchain

zkVMs are the significant recent shift: instead of hand-writing constraints, you compile normal Rust to a provable virtual machine. The proving overhead is higher than a hand-optimized circuit, and the developer productivity difference is enormous — the same tradeoff as a compiler versus hand-written assembly, and it's likely to resolve the same way.

The proving pipeline

The asymmetry is the entire economic model. Proving is deliberately expensive because it happens once, by one party, off-chain; verification is cheap because it happens everywhere, repeatedly.

Best Practices

Count constraints early and often

Constraint count determines proving time, memory, and cost. Measure it at every stage rather than discovering at the end that your circuit needs 200 GB of RAM. A useful discipline: set a constraint budget before writing the circuit.

Use ZK-friendly primitives

Poseidon instead of SHA-256, Merkle trees instead of iterating a list, and field-native arithmetic instead of emulated bit operations. Switching a hash function alone routinely cuts constraint counts by two orders of magnitude.

Constrain everything — under-constraining is the bug class

A circuit that fails to constrain a signal lets a malicious prover choose it freely, producing valid proofs of false statements. This is the ZK equivalent of missing access control: silent, catastrophic, and the most common serious circuit vulnerability.

Distinguish public from private inputs deliberately

Every public input is revealed to everyone, forever. Every private input must nonetheless be constrained. Mislabeling a signal either leaks data or opens a soundness hole, and reviewing this list explicitly is a cheap, high-value check.

Use nullifiers to prevent replay

Any anonymous action needs a deterministic, unlinkable marker so it can't be repeated. Derive it from the secret so the same secret always yields the same nullifier, and record spent nullifiers publicly.

Don't build the cryptography yourself

Use established proving systems and audited circuit libraries (circomlib and equivalents). Novel constructions require research-level review, and the failure mode — a soundness break — is total and undetectable from outside.

Have circuits audited by ZK specialists

A general smart contract audit will not find under-constrained signals or a soundness gap in a proving system. This is a specialist skill with a small pool of practitioners; budget time accordingly.

Common Mistakes

Assuming ZK means private

Leaving a signal unconstrained

The <-- versus <== distinction in Circom is exactly this trap, and it has produced real vulnerabilities in deployed circuits.

Using a general-purpose hash inside a circuit

Data-dependent control flow

Reusing a nullifier scheme across contexts

Ignoring proving cost in the product design

FAQ

Do I need to understand the math to use ZK?

Not to build applications. Circuit DSLs and zkVMs abstract the cryptography much as a compiler abstracts assembly; you need to understand constraints, public versus private inputs, and proving cost. You do need the math to design a new proving system or audit one — and you need to know enough to recognize that you shouldn't be doing either casually.

How long does proving actually take?

Anywhere from milliseconds to hours, roughly proportional to constraint count. A small membership proof might take under a second in a browser. A zkEVM block proof takes minutes on specialized hardware, which is why proving is a service with dedicated GPU clusters. Assume proving is the bottleneck in any design and measure it early on the hardware users will actually have.

SNARK or STARK?

Whichever your target platform and tooling support, in practice. SNARKs give tiny proofs and cheap on-chain verification, at the cost of a setup ceremony (for older systems) and no post-quantum security. STARKs need no setup and are quantum-resistant, with larger proofs. The distinction is blurring — modern SNARKs have universal or transparent setups, and STARKs are often wrapped in SNARKs for cheap verification.

Is ZK only useful for blockchains?

No, though blockchains funded most of the engineering. Zero-knowledge identity and selective disclosure work entirely off-chain. Verifiable computation lets you outsource work and check the result cheaply. zkML proves a model produced a given output. Private set intersection and private analytics let organizations compute over shared data without pooling it. The blockchain applications are the most visible, not the only ones.

Are ZK proofs quantum-resistant?

STARKs are — they rely only on hash functions. Pairing-based SNARKs (Groth16, PLONK with KZG) are not, since a quantum computer breaking discrete log would break their soundness. Note this affects forging new proofs; it doesn't retroactively reveal information that was never transmitted. Lattice-based and hash-based SNARK constructions are active research.

What is a zkVM and should I use one?

A zkVM proves the execution of a general program — you write Rust or compile to RISC-V and get a proof of correct execution without writing constraints. Use one when developer time matters more than proving cost, which is most applications outside high-volume rollups. Hand-written circuits remain far more efficient and are worth it when the same circuit is proven millions of times.

Related Topics

References