web3.path

PHASE 13 ZK · ~5 hours

Zero-Knowledge Proofs

"I can prove I know x without revealing x." That sentence became a multi-billion-dollar industry. Here's the engineer's view — enough to build, without the PhD.

Goal — build a Circom circuit, generate and verify a zk-SNARK, and know when to reach for one in production.

1. What ZK actually gives you

Analogy — a hash lets you prove you know a preimage by revealing it. A ZK proof lets you prove you know a preimage without revealing it. That's the leap.

2. Classic Ali Baba's cave intuition

Cave with two paths (A, B) meeting at a magic door. Peggy knows the password. Victor doesn't. Victor waits outside. Peggy enters a random path. Victor shouts "come out via A!" (random). If Peggy knows password → she can always comply (p=1). If she doesn't → she's right 50% of the time; after 20 rounds → 1 in 10⁶. Victor is convinced without ever learning the password.

3. SNARK vs STARK

SNARK (Groth16, PLONK)STARK
Proof size~200 bytes~100 KB
VerifierConstant, very fastLarger, still fast
Trusted setup?Yes (Groth16) / universal (PLONK)No
Post-quantum?No (pairing-based)Yes (hash-based)
Used byzkSync, Polygon zkEVMStarknet

4. The pipeline

1. Write a circuit (Circom, Noir, Halo2) 2. Compile → R1CS / arithmetic circuit 3. Trusted setup (or universal SRS) → proving key, verifying key 4. Prover: inputs + witness → proof 5. Verifier: proof + public inputs → true/false 6. On-chain: the verifier is a Solidity contract auto-generated from vkey

5. A tiny Circom circuit — prove you know a preimage

// preimage.circom
pragma circom 2.1.6;
include "circomlib/poseidon.circom";

template Preimage() {
    signal input secret;        // private
    signal input hash;          // public
    signal output ok;

    component h = Poseidon(1);
    h.inputs[0] <== secret;
    hash === h.out;             // constraint: provided hash must match
    ok <== 1;
}

component main { public [hash] } = Preimage();
# toolchain
npm i -g circom snarkjs

circom preimage.circom --r1cs --wasm --sym
# trusted setup (Powers-of-Tau, one-time, shared)
snarkjs powersoftau new bn128 12 pot12_0000.ptau
snarkjs powersoftau contribute pot12_0000.ptau pot12.ptau --name="me"
snarkjs powersoftau prepare phase2 pot12.ptau pot12_final.ptau
# circuit-specific
snarkjs groth16 setup preimage.r1cs pot12_final.ptau pre_0000.zkey
snarkjs zkey contribute pre_0000.zkey pre_final.zkey --name="me"
snarkjs zkey export verificationkey pre_final.zkey vkey.json

# prove
node generate_witness.js preimage_js/preimage.wasm input.json witness.wtns
snarkjs groth16 prove pre_final.zkey witness.wtns proof.json public.json

# verify (off-chain)
snarkjs groth16 verify vkey.json public.json proof.json
# export Solidity verifier for on-chain
snarkjs zkey export solidityverifier pre_final.zkey Verifier.sol

6. What "trusted setup" means

Groth16 needs a one-time ceremony where participants contribute randomness; as long as one participant is honest and destroys their secret, the setup is safe. Ethereum's KZG ceremony for EIP-4844 had ~140k contributors.

7. Real-world ZK use cases

8. The cost model

Heuristic — if your computation is "the same 10 lines over 10,000 inputs", ZK is a win. If it's "1000 lines of branching business logic", it isn't yet.

9. Alternatives to learn alongside

10. Project

Deliverable — build a private airdrop: a Merkle tree of eligible addresses. Eligible users submit a zk-proof of "I know a leaf and a Merkle path to this public root" to claim, without revealing which address. Circom + Solidity verifier + a React claim UI.

Quiz

Q. You have a legitimate preimage x, and want to prove hash = H(x) to a contract cheaply. Is ZK the right tool?
ZK is about privacy/compression of computation, not a default. If the input is already public, a plain hash check is trivially cheaper.
← Phase 12Phase 14: Cross-chain →