What are Zero-Knowledge Proofs?
A zero-knowledge proof (ZKP) is a cryptographic method that allows one party (the prover) to prove to another party (the verifier) that a statement is true, without revealing any information beyond the validity of the statement itself.Example: Cave AnalogyImagine a circular cave with one entrance and a magic door in the middle. Alice wants to prove to Bob that she knows the password to the door without revealing the password.
- Alice enters the cave and goes to either the left or right path (Bob can’t see which)
- Bob then shouts either “left” or “right”
- Alice emerges from the requested side by using the password to open the door if needed
- After many repetitions, Bob is convinced Alice knows the password without ever learning it
Why Zero-Knowledge Proofs?
Privacy Cash uses ZK proofs to enable private transactions while maintaining security guarantees:Privacy
Prove ownership of a commitment without revealing which commitment, maintaining transaction unlinkability.
Security
Ensure all transaction rules are followed (amount conservation, valid signatures, no double-spending) without trust.
Efficiency
Groth16 proofs are small (~256 bytes) and fast to verify (~1ms on Solana), enabling scalable privacy.
No Trusted Party
After trusted setup, no ongoing trust is required. The cryptography is trustless and verifiable.
Groth16 ZK-SNARKs
Privacy Cash uses Groth16, a popular ZK-SNARK (Zero-Knowledge Succinct Non-Interactive Argument of Knowledge) construction.Properties
- Zero-Knowledge
- Succinct
- Non-Interactive
- Argument of Knowledge
The proof reveals nothing about the witness (private inputs) beyond the statement being true.What’s hidden:
- Private keys
- Blinding factors
- Input commitment amounts
- Merkle path (which leaf in tree)
- Proof is valid for some commitment in the tree
- Public inputs (nullifiers, output commitments, amounts)
- Merkle root (tree state)
Circuit Architecture
The Privacy Cash circuit is implemented in Circom and compiles to a rank-1 constraint system (R1CS).Transaction Circuit
Located atcircuits/transaction.circom:22, the main circuit has:
Inputs:
- Keypair validation: Public key = hash(private key)
- Commitment computation: commitment = hash(amount, pubkey, blinding, mint)
- Signature generation: signature = hash(privkey, commitment, merkle_path)
- Nullifier computation: nullifier = hash(commitment, path_indices, signature)
- Merkle proof verification: Prove commitment is in tree with given root
- Amount conservation: sum(inputs) + publicAmount = sum(outputs)
- No duplicate nullifiers: inputNullifier[0] ≠ inputNullifier[1]
The circuit uses Poseidon hash throughout, which is ZK-friendly (requires fewer constraints than SHA-256).
Circuit Parameters
Constraint Count
The circuit compiles to approximately:- Total constraints: ~2,000
- Merkle proof: ~1,500 constraints (26 levels × ~60 per level)
- Poseidon hashes: ~400 constraints
- Other logic: ~100 constraints
Smaller constraint counts mean faster proving and verification. Privacy Cash’s circuit is optimized for efficiency.
Proof Generation
Users generate proofs off-chain using the Privacy Cash SDK or CLI.Generation Process
Generate Witness
Execute the circuit to compute all intermediate signals:This ensures all constraints are satisfied before proving.
Create Proof
Use the proving key to generate a Groth16 proof:Output:
proof.json: The proof (π_a, π_b, π_c)public.json: Public inputs
SDK Integration
The Privacy Cash SDK handles proof generation automatically:Example: Generate Withdraw Proof
Proof Verification
The Solana program verifies proofs on-chain using a hardcoded verifying key.Verification Process
Pairing Check
Verify the proof using bilinear pairings:Groth16 verification equation:Where:
e()is a pairing operation on elliptic curves (BN254)α, β, γ, δare from the verifying keyICis computed from public inputs and verifying key
Verifying Key
The verifying key is hardcoded in the program atutils.rs:16:
Trusted Setup
Groth16 requires a trusted setup ceremony to generate proving and verifying keys.What is Trusted Setup?
Ceremony Details
Ceremony Details
A trusted setup is a multi-party computation (MPC) where participants generate random values called “toxic waste.”Process:
- Multiple participants contribute randomness
- Each contribution is combined cryptographically
- Proving key and verifying key are generated
- Participants destroy their random values (toxic waste)
- As long as one participant is honest and destroys their toxic waste, the setup is secure
- Multiple participants increase confidence (no single point of failure)
- Toxic waste could be used to forge proofs, so destruction is critical
- Conducted by the Privacy Cash team
- Multiple contributors from different organizations
- Setup artifacts are published for transparency
Powers of Tau
Privacy Cash uses a universal trusted setup (Powers of Tau) plus a circuit-specific phase:Phase 1: Powers of Tau
Universal ceremony for all circuits of a certain size:This phase is circuit-independent and can be reused.
Upcoming: PLONK MigrationFuture versions may migrate to PLONK or other proof systems that don’t require trusted setup, providing trustless cryptography end-to-end.
Performance Characteristics
Proving Time
| Hardware | Time |
|---|---|
| MacBook Pro M1 | ~2-3 seconds |
| High-end Desktop | ~1-2 seconds |
| Mobile (iOS/Android) | ~10-15 seconds |
| Server (32 cores) | ~500ms |
Verification Time
| Platform | Time | Compute Units (Solana) |
|---|---|---|
| Solana On-Chain | ~0.4ms | ~20,000 CU |
| Off-Chain (Node.js) | ~1ms | N/A |
| Off-Chain (Browser) | ~2-5ms | N/A |
Resource Usage
Proving:- Memory: ~500 MB (witness generation)
- CPU: 1 core at 100% for 2-3 seconds
- Disk: ~50 MB (proving key)
- Memory: ~10 MB
- CPU: Minimal (< 1ms)
- Disk: ~1 KB (verifying key)
Security Analysis
Soundness
Soundness
Property: A valid proof can only be generated if the statement is true.Groth16 soundness:
- Based on hardness of discrete log on BN254 elliptic curve
- Security level: ~128 bits
- Probability of forging proof: < 2^-128 (negligible)
- Circuit reviewed by Accretion, HashCloak, Zigtur, Kriko
- No soundness vulnerabilities found
Zero-Knowledge
Zero-Knowledge
Property: The proof reveals nothing about private inputs.Groth16 zero-knowledge:
- Proof is computationally indistinguishable from random
- Simulator can generate fake proofs without witness (for analysis only)
- No information leakage even with multiple proofs from same witness
- Never reuse blinding factors
- Use cryptographically secure randomness
- Don’t expose intermediate computation values
Completeness
Completeness
Property: If the statement is true and prover is honest, verification always succeeds.Guarantees:
- Properly formed proofs always verify
- No false rejections
- Deterministic verification
- Extensive unit tests in
anchor/tests/ - Mainnet track record: 100% verification rate for honest proofs
Trusted Setup Security
Trusted Setup Security
Risk: If all setup participants collude and keep toxic waste, they could forge proofs.Mitigation:
- Multiple independent contributors
- Public ceremony with transparency
- Published transcripts
- Future migration to transparent setup (PLONK, STARKs)
- No evidence of setup compromise
- All contributors reported destroying toxic waste
Implementation Reference
Transaction Circuit
Main circuit implementing JoinSplit logiccircuits/transaction.circom
Merkle Proof Circuit
Merkle tree membership proofcircuits/merkleProof.circom
Keypair Circuit
Keypair and signature generationcircuits/keypair.circom
Proof Verification
On-chain Groth16 verificationutils.rs:214
Next Steps
Merkle Trees
Learn how commitments are organized in Merkle trees
Commitments & Nullifiers
Understand the core cryptographic primitives
Build with SDK
Start integrating Privacy Cash into your application
Circuit Audit Reports
Review security audit findings