Choosing the right ZK proving system significantly impacts your application. Groth16 and PLONK are the two most popular systems, each with distinct trade-offs — and both play a role in enabling computation on encrypted data. This guide helps you decide.
Overview
Groth16
A pairing-based SNARK from 2016, known for minimal proof size and verification time.
PLONK
A universal SNARK from 2019, known for flexibility and universal trusted setup.
Key Differences
At a Glance
Groth16: Smallest proofs (~200 bytes), fastest verification, circuit-specific setup
PLONK: Larger proofs (~400+ bytes), universal setup, more flexible
Trusted Setup
Groth16
- Requires per-circuit trusted setup ceremony
- Changing the circuit requires new setup
- Setup must be done securely—toxic waste must be destroyed
PLONK
- Universal setup: one ceremony for all circuits up to a size limit
- Update circuits without new setup
- More practical for evolving applications
What Is Toxic Waste?
In a trusted setup ceremony, participants generate random secret values (the "toxic waste") that are used to derive the public parameters. If any single participant in the multi-party computation honestly destroys their contribution, the resulting parameters are secure. The risk arises only if every participant colludes or is compromised. Groth16 ceremonies such as Zcash's Powers of Tau involved hundreds of independent participants to minimize this risk. PLONK's universal setup reduces the operational burden because the ceremony only needs to happen once, regardless of how many different circuits you deploy.
Proof Size and Verification
| Property | Groth16 | PLONK |
|---|---|---|
| Proof size | ~192 bytes (constant) | ~400–800 bytes (varies by variant) |
| Verification ops | 3 pairings | ~15–20 group operations + 1 pairing |
| On-chain gas cost | ~230K gas (Ethereum) | ~300–400K gas |
| Proof generation | 1 multi-exp per wire | FFTs + multi-exp over quotient polynomial |
Groth16's constant 192-byte proof and 3-pairing verification make it the gold standard for on-chain use cases where every byte and every gas unit counts. PLONK's verification involves more elliptic curve operations, but the absolute cost is still practical for most L1 and L2 deployments.
Proving Time
Both have similar proving complexity, though:
- Groth16 requires FFTs over the full circuit
- PLONK has slightly different proving structure
- Actual performance depends on implementation
In practice, proving time is dominated by the number of constraints (Groth16) or number of gates (PLONK) in the circuit. For equivalently sized circuits, Groth16 provers tend to be marginally faster because the prover computes fewer polynomial commitments. However, PLONK's custom gates can reduce total gate count for specific operations—making the effective proving time comparable or even faster for well-optimized circuits.
In H33's production pipeline, ZKP verification via in-process DashMap lookup completes in 0.085 microseconds—proof system choice matters far less than cache architecture at this scale.
Flexibility
Groth16
- Fixed circuit at setup time
- Any change requires new trusted setup
- Rigid but optimal for known, stable circuits
PLONK
- Universal setup supports any circuit within size bounds
- Custom gates can optimize specific operations
- Variants (TurboPLONK, UltraPLONK) add features
Custom Gates and Lookup Arguments
PLONK's extensibility is its strongest architectural advantage. Custom gates let you define specialized constraints—range checks, hash evaluations, or signature verification—as single gate operations instead of decomposing them into basic addition and multiplication gates. Lookup arguments (such as Plookup, integrated into UltraPLONK) further reduce circuit size by replacing expensive constraint trees with table lookups. A SHA-256 hash that requires ~25,000 R1CS constraints in Groth16 can be expressed in ~3,000–5,000 PLONK gates with lookup tables. This gate reduction directly translates to faster proving times for hash-heavy workloads.
Quantum Resistance: Neither Is Enough
Both Groth16 and PLONK rely on elliptic curve pairings vulnerable to Shor's algorithm. Neither system is post-quantum secure. A sufficiently powerful quantum computer would break the discrete log and pairing assumptions underlying both protocols.
For applications requiring long-term security guarantees, hash-based proof systems like STARKs offer quantum resistance by relying only on collision-resistant hash functions (such as SHA3-256). The trade-off is significantly larger proof sizes (tens to hundreds of kilobytes). H33 addresses this by using SHA3-256 as the hash backbone in its ZKP layer, combined with Dilithium signatures for post-quantum attestation—achieving both zero-knowledge verification and quantum resilience in a single API call at ~42 microseconds per authentication.
Ecosystem and Tooling
Groth16
- Mature ecosystem (snarkjs, bellman, gnark)
- Well-understood security properties
- Widely deployed in production
PLONK
- Growing ecosystem (halo2, plonky2, Noir)
- Active development and optimization
- Increasingly adopted
When to Choose Each
Choose Groth16 when:
- Proof size is critical (blockchain, on-chain verification)
- Circuit is stable and won't change
- You can coordinate trusted setup
- Verification cost is paramount
Choose PLONK when:
- Circuit may evolve over time
- Universal setup is more practical
- You want custom gate flexibility
- Slightly larger proofs are acceptable
H33's Approach
We use Groth16 for our production ZK proofs because:
- Our identity verification circuit is stable
- Minimal proof size matters for blockchain attestation
- Fastest verification for real-time authentication
But the ZKP layer is only one component of the full pipeline. H33's production stack pairs BFV fully homomorphic encryption with a ZKP cache backed by an in-process DashMap (0.085 microsecond lookups) and Dilithium post-quantum attestation. The result: 2,172,518 authentications per second on a single Graviton4 instance—~42 microseconds per auth, end to end. The proving system contributes negligible latency compared to the FHE inner product, which is where the real computational work happens.
// H33 production pipeline — single API call
let ct = bfv.batch_encrypt(&biometric, &pk); // FHE encrypt (32 users)
let score = bfv.inner_product_ntt(&ct, &enrolled); // ~1,109 µs
let zkp_ok = dashmap.get(&proof_key); // 0.085 µs (cached)
let attestation = dilithium.sign(&digest); // ~244 µs (batch of 32)
// Total: ~1,356 µs for 32 users → ~42 µs per auth
Both systems are excellent choices. Your decision should be driven by your specific requirements around flexibility, proof size, and operational constraints.
Ready to Go Quantum-Secure?
Start protecting your users with post-quantum authentication today. 1,000 free auths, no credit card required.
Get Free API Key →