Skip to main content

Groth16 Proof Verification

Privacy Cash uses Groth16 zero-knowledge proofs for transaction privacy. The Groth16 verifier runs entirely on-chain in Solana programs, leveraging the BN254 elliptic curve precompiled functions.

Groth16 Overview

Groth16 is a zero-knowledge SNARK (Succinct Non-interactive Argument of Knowledge) that provides:
  • Small proof size: 256 bytes (2 G1 points + 1 G2 point)
  • Fast verification: Single pairing check
  • Trusted setup: Requires ceremony for each circuit
The proof consists of three elliptic curve points:
  • proof_a: G1 point (64 bytes)
  • proof_b: G2 point (128 bytes)
  • proof_c: G1 point (64 bytes)

Verification Key Structure

The verifying key is generated during the trusted setup and contains:
Key components:
  • Alpha, Beta, Gamma, Delta: Cryptographic parameters from trusted setup
  • IC coefficients: vk_ic[0] is the constant term, vk_ic[1..n+1] are coefficients for each public input
  • The length of vk_ic must equal nr_pubinputs + 1

Verifier Implementation

The verifier is implemented in src/groth16.rs and provides a safe, efficient verification interface:

Verification Process

1. Initialization

The new function performs validation:

2. Preparing Public Inputs

The core of Groth16 verification involves computing a linear combination of IC coefficients:
Algorithm:
  1. Start with vk_ic[0] (constant term)
  2. For each public input x[i]:
    • Multiply vk_ic[i+1] by scalar x[i] (G1 multiplication)
    • Add result to running sum (G1 addition)
  3. Result: vk_ic[0] + x[0]*vk_ic[1] + x[1]*vk_ic[2] + ... + x[n-1]*vk_ic[n]
This computed value represents the public input component of the proof. Optional field size check: When CHECK = true, each public input is verified to be less than the BN254 field modulus:

3. Pairing Check

The final verification performs a bilinear pairing check:
Pairing equation: The verifier checks:
Where:
  • A = proof_a
  • B = proof_b
  • C = proof_c
  • L = prepared_public_inputs
  • α = vk_alpha_g1
  • β = vk_beta_g2
  • γ = vk_gamma_g2
  • δ = vk_delta_g2
The pairing function takes 4 pairs of points (8 total) and computes:
If the result equals 1 (checked via pairing_res[31] != 1), the proof is valid.

Verification API

Two verification methods are provided:

Checked Verification

Validates that all public inputs are within the BN254 field size. Use this by default for security.

Unchecked Verification

Skips field size validation for a small gas optimization. Only use if inputs are pre-validated.

Solana BN254 Precompiles

The verifier uses Solana’s native BN254 precompiled functions for efficient elliptic curve operations:

alt_bn128_multiplication

Computes scalar multiplication: point * scalar on the BN254 curve. Cost: ~2,100 compute units

alt_bn128_addition

Computes point addition: point1 + point2 on the BN254 curve. Cost: ~540 compute units

alt_bn128_pairing

Computes a pairing check over 4 pairs of G1 and G2 points. Cost: ~25,000 compute units

Usage Example

Error Handling

The verifier defines comprehensive error types:

Performance Characteristics

Total compute units: ~30,000-35,000 CU Breakdown:
  • Input preparation: ~2,100 CU per public input (scalar mul) + ~540 CU per addition
  • Pairing check: ~25,000 CU
  • Overhead: ~1,000 CU
For Privacy Cash with 7 public inputs:
  • 7 × 2,100 = 14,700 CU (multiplications)
  • 7 × 540 = 3,780 CU (additions)
  • 25,000 CU (pairing)
  • Total: ~44,000 CU
This fits comfortably within Solana’s 200,000 CU default limit for instructions.

Security Considerations

Trusted Setup

Groth16 requires a circuit-specific trusted setup. If the setup’s “toxic waste” is not destroyed, proofs can be forged. Privacy Cash uses:
  • Multi-party computation (MPC) ceremonies
  • Multiple independent participants
  • Public verification transcripts

Proof Malleability

Groth16 proofs are non-malleable. An attacker cannot modify a valid proof without breaking the pairing equation.

Field Overflow

Public inputs must be validated to be less than the BN254 field modulus. The verify() method enforces this, preventing field overflow attacks.

Side-Channel Resistance

The verifier operates on public data only (proof and public inputs), so it is not vulnerable to timing attacks.

Implementation Source

The Groth16 verifier is adapted from Light Protocol’s implementation, which provides a battle-tested, gas-optimized verifier for Solana.