What are Zero-Knowledge Proofs?
A zero-knowledge proof allows a prover to convince a verifier that a statement is true without revealing any information beyond the truth of the statement itself.Properties of SNARKs
SnarkVM uses SNARKs (Succinct Non-interactive Arguments of Knowledge):- Succinct: Proofs are small (~few KB) regardless of computation size
- Non-interactive: No back-and-forth between prover and verifier
- Arguments of Knowledge: Prover must actually know the witness
- Zero-Knowledge: Proof reveals nothing about private inputs
Use Cases in Aleo
- Private Transactions: Transfer tokens without revealing amounts or addresses
- Private Programs: Execute arbitrary logic with hidden inputs
- Proof-Carrying Data: Chain proofs to create complex privacy-preserving applications
- Verifiable Computation: Prove correct execution without re-running
R1CS Constraint Systems
Rank-1 Constraint System
SnarkVM represents circuits as R1CS (Rank-1 Constraint System), the standard representation for SNARK circuits. Each constraint has the form:Variables and Witnesses
Fromalgorithms/src/r1cs/mod.rs:54:
- Public Variables: Known to both prover and verifier (public inputs/outputs)
- Private Variables: Known only to prover (private witness)
- Constants: Fixed values compiled into circuit
Linear Combinations
Fromalgorithms/src/r1cs/linear_combination.rs:
3 + 2·x₁ + 5·x₂ is:
Constraint System Trait
Fromalgorithms/src/r1cs/constraint_system.rs:23:
Circuit Construction
From Operations to Constraints
Consider the computationresult = (a + b) * (c + d):
Step 1: Decompose
Example: Field Multiplication
Fromcircuit/types/field/src/mul.rs:
self * other = output
Cost Model
Proof generation time is roughly linear in constraint count. Minimize multiplications and comparisons to optimize circuit performance.
Varuna SNARK System
SnarkVM uses Varuna, a polynomial-based SNARK system implementing the AHP (Algebraic Holographic Proof) framework.Architecture
Fromalgorithms/src/snark/varuna/mod.rs:16:
Components
1. Structured Reference String (SRS) Universal setup generating public parameters:Proof Generation Flow
Polynomial Commitment Scheme
Varuna uses polynomial commitments to achieve succinctness:- Commit: Prover commits to witness polynomials (few KB)
- Query: Verifier challenges prover at random points
- Open: Prover provides evaluations and opening proofs
- Verify: Verifier checks commitments match opened values
Polynomial commitments compress large witness data into small commitments, enabling succinct proofs.
Program Execution and Proving
Stack and Process
Fromsynthesizer/process/src/stack/mod.rs:211:
Execution Modes
Fromsynthesizer/process/src/stack/mod.rs:103:
Proof Generation Steps
- Evaluation: Run console types to compute output
- Injection: Convert console values to circuit variables
- Synthesis: Execute circuit, generating constraints
- Witness Assignment: Populate all variables with values
- AHP Proving: Convert R1CS to algebraic holographic proof
- Polynomial Commitment: Commit to witness polynomials
- Proof Assembly: Package commitments and evaluations
Proof Verification Steps
- Parse Public Inputs: Extract public variables from proof
- Circuit Verification: Check proof against verifying key
- Polynomial Checks: Verify polynomial commitment openings
- Output Validation: Ensure outputs match public values
Cryptographic Primitives
Elliptic Curves
SnarkVM uses BLS12-377 for pairing-based cryptography:- 128-bit security level
- Efficient pairing computation
- Edwards curve (EdDSA) compatible scalar field
Hash Functions
SnarkVM uses Poseidon hash for circuit-friendly hashing:- Designed for SNARK circuits
- Low constraint count (~150 constraints per hash)
- Collision-resistant and one-way
Performance Characteristics
Typical Proof Times
Proof size is nearly constant (~logarithmic growth), while proving time is linear in constraint count.
Verification Performance
- Verification Time: ~1-10ms (independent of circuit size)
- Verification Cost: Dominated by pairing computations
- Batch Verification: Amortized cost for verifying multiple proofs
Optimization Strategies
Circuit-Level Optimizations
- Minimize Multiplications: Each multiplication = 1 constraint
- Reuse Computations: Cache intermediate results
- Algebraic Tricks: Use field properties (e.g., Fermat’s little theorem for inversion)
- Boolean Packing: Pack multiple booleans into field elements
System-Level Optimizations
- Parallel Proving: Leverage multi-core CPUs
- GPU Acceleration: Use CUDA for MSM and FFT
- Caching: Precompute proving keys for common circuits
- Batch Processing: Generate multiple proofs in parallel
Example: Optimized Range Proof
Naive Approach (O(bits) constraints):Security Considerations
Trusted Setup
Varuna requires a universal trusted setup:- One-time ceremony generating SRS
- Universal parameters for all circuits
- Security relies on at least one honest participant
Soundness
SNARK soundness ensures:- Invalid proofs are rejected with overwhelming probability
- Prover cannot convince verifier of false statements
- Security based on cryptographic assumptions (e.g., discrete log)
Zero-Knowledge
Proofs reveal:- Public Inputs: Intentionally disclosed (e.g., transaction outputs)
- Public Outputs: Computation results
- Nothing Else: Private witnesses remain hidden
Best Practices
For Circuit Design
- Profile First: Measure constraint counts before optimizing
- Test Soundness: Verify invalid inputs are rejected
- Validate Ranges: Ensure integers stay within bounds
- Check Edge Cases: Test zero, max, and boundary values
For Program Development
- Minimize Circuit Operations: Use console types where possible
- Batch Transactions: Amortize proof costs across multiple operations
- Cache Proving Keys: Avoid regenerating keys repeatedly
- Monitor Constraint Growth: Track circuit size as programs evolve
Debugging Circuits
Constraint Counting
Witness Inspection
Constraint Checking
Further Reading
Overview
Return to core concepts overview
Console & Circuit
Understand the dual type system
Quick Start
Build your first program
API Reference
Explore the API documentation