Docs/Security/Trusted Setup

Trusted Setup

Details of the trusted setup ceremony

Trusted Setup

ZKMix uses the Groth16 proving system for its zero-knowledge proofs. Groth16 produces the most compact proofs (only 128 bytes for BN254) and has the fastest verification time of any pairing-based SNARK, making it ideal for on-chain verification where compute units and transaction size are constrained. However, Groth16 requires a trusted setup ceremony that must be performed correctly to ensure the security of the entire system.

What Is a Trusted Setup?

A trusted setup is a one-time process that generates the public parameters (proving key and verification key) for a zero-knowledge proof system. These parameters are derived from a random value commonly called "toxic waste" that must be destroyed after the ceremony. If the toxic waste is retained by any participant, it could be used to forge proofs -- creating valid-looking proofs for false statements.

In the context of ZKMix, a forged proof would allow an attacker to:

  • Withdraw funds without having made a corresponding deposit
  • Effectively mint counterfeit tokens from the mixer's vault
  • Drain the entire pool

This is why the trusted setup is arguably the most security-critical component of the protocol.

What the Trusted Setup Produces

The ceremony produces two artifacts:

  1. Proving key (~25 MB) -- Used by clients to generate zero-knowledge proofs. This is a public parameter distributed with the SDK.
  2. Verification key (~1 KB) -- Used by the on-chain Verifier Program to validate proofs. This is stored in a Solana account.

Both keys are derived from the same toxic waste, but the toxic waste itself is not contained in either key. The keys are safe to publish and distribute.

Why Groth16 Needs a Trusted Setup

Not all zero-knowledge proof systems require a trusted setup. Systems like STARKs, Bulletproofs, and PLONK (with universal setup) avoid this requirement. However, they come with tradeoffs:

SystemTrusted SetupProof SizeVerification TimeOn-Chain Cost
Groth16Circuit-specific128 bytes~0.5ms~500K CU
PLONKUniversal~400 bytes~2ms~1.5M CU
STARKsNone~50 KB~5msNot feasible
BulletproofsNone~700 bytes~30msNot feasible

Groth16's compact proof size and fast verification make it the only practical choice for on-chain verification on Solana within a single transaction's compute budget. The tradeoff is the trusted setup requirement, which ZKMix addresses through a multi-party computation ceremony.

The Ceremony Process

Multi-Party Computation (MPC)

The ZKMix trusted setup uses a multi-party computation (MPC) protocol based on the Zcash Powers of Tau ceremony design. The key property of this MPC is that the toxic waste is secure as long as at least one participant acts honestly and destroys their contribution. Even if every other participant is malicious or compromised, the toxic waste cannot be recovered.

The ceremony proceeds in two phases:

Phase 1: Powers of Tau

Phase 1 is circuit-independent and generates generic structured reference string (SRS) parameters that can be reused across different circuits. ZKMix uses the Hermez Network's Phase 1 output, which was contributed to by over 150 participants from the Ethereum community.

The Phase 1 ceremony produces the powers of a secret value tau:

[tau^0]G1, [tau^1]G1, [tau^2]G1, ..., [tau^n]G1
[tau^0]G2, [tau^1]G2

Where [x]G1 denotes the scalar multiplication of x with the G1 generator point, and n is the maximum circuit size supported.

Phase 2: Circuit-Specific

Phase 2 takes the Phase 1 output and specializes it for the ZKMix withdrawal circuit. This phase introduces additional randomness specific to the circuit's constraint structure.

Each participant in Phase 2:

  1. Downloads the current state of the parameters (the output of the previous participant).
  2. Generates a random secret value locally.
  3. Applies their random value to the parameters using elliptic curve operations.
  4. Uploads the updated parameters.
  5. Destroys their random value (the toxic waste).
  6. Publishes an attestation hash that allows anyone to verify their contribution was included.
Participant 1          Participant 2         Participant N
     |                      |                      |
     v                      v                      v
  Generate r1           Generate r2            Generate rN
     |                      |                      |
     v                      v                      v
  Apply r1 to          Apply r2 to            Apply rN to
  initial params       params from P1         params from P(N-1)
     |                      |                      |
     v                      v                      v
  Destroy r1            Destroy r2             Destroy rN
     |                      |                      |
     v                      v                      v
  Output params1        Output params2         Output final params
  + attestation         + attestation          + attestation

The final output is the proving key and verification key used by ZKMix.

ZKMix Ceremony Details

ParameterValue
Phase 1 sourceHermez Network Powers of Tau
Phase 2 participants73 contributors
Ceremony duration3 weeks (open contribution period)
Circuit constraints15,234
Maximum circuit support2^21 constraints
CoordinatorZKMix core team
VerificationPublicly reproducible

Participant Diversity

To maximize the probability that at least one participant is honest, the ceremony sought contributions from a diverse set of participants:

  • Independent developers from the Solana and Ethereum communities
  • Representatives from blockchain security firms
  • Academic researchers in cryptography
  • Anonymous contributors using Tor
  • Participants from multiple geographic jurisdictions

The identities of 58 participants are publicly known (they opted in to identification). The remaining 15 contributed anonymously. The ceremony was open to anyone who wanted to participate -- no permission was required.

How to Verify the Ceremony

The ceremony is fully verifiable. Anyone can independently confirm that:

  1. Each participant's contribution was correctly applied to the parameters.
  2. The final parameters are consistent with the chain of contributions.
  3. The verification key used on-chain matches the ceremony output.

Step 1: Download the Ceremony Transcript

bash
git clone https://github.com/zkmix/trusted-setup-ceremony.git
cd trusted-setup-ceremony

# The transcript includes all intermediate parameters and attestations
ls contributions/
# phase2_0000.params  (initial)
# phase2_0001.params  (after participant 1)
# phase2_0002.params  (after participant 2)
# ...
# phase2_0073.params  (final)
# attestations.json

Step 2: Verify the Contribution Chain

Use snarkjs to verify that each contribution correctly transforms the parameters:

bash
# Install snarkjs
npm install -g snarkjs

# Verify each contribution
for i in $(seq 1 73); do
  prev=$(printf "%04d" $((i - 1)))
  curr=$(printf "%04d" $i)
  echo "Verifying contribution $curr..."
  snarkjs zkey verify \
    circuits/withdrawal.r1cs \
    contributions/phase2_${prev}.params \
    contributions/phase2_${curr}.params
done

echo "All contributions verified."

Step 3: Verify the Final Parameters

Verify that the deployed verification key matches the ceremony output:

bash
# Export the verification key from the final parameters
snarkjs zkey export verificationkey \
  contributions/phase2_0073.params \
  verification_key.json

# Compare with the on-chain verification key
# (fetch from Solana and compare)
solana account ZKMxDevVKey11111111111111111111111111111111 \
  --output json > onchain_vk.json

# The keys should match (after accounting for serialization format differences)
node scripts/compare-vk.js verification_key.json onchain_vk.json

Step 4: Verify Attestations

Each participant published an attestation containing the hash of their contribution. These attestations are signed and can be verified:

bash
# View all attestations
cat attestations.json | jq '.[] | {participant: .name, hash: .contribution_hash}'

# Verify a specific attestation signature
node scripts/verify-attestation.js attestations.json 42

Toxic Waste Destruction

The "toxic waste" is the random secret value that each participant generates during their contribution. If any participant's toxic waste is recovered, and all other participants' toxic waste is also recovered, the complete toxic waste can be reconstructed, enabling proof forgery.

Destruction Methods

Participants were encouraged to use creative and verifiable destruction methods. Some examples from the ceremony:

  • Secure memory wipe: Using mlock to prevent memory from being swapped to disk, then zeroing the memory region and calling munlock.
  • Dedicated hardware: Running the contribution on a freshly provisioned machine that was physically destroyed afterward.
  • Air-gapped computation: Performing the contribution on a machine with no network connection, then destroying the storage media.
  • Multiple entropy sources: Combining hardware random number generators, mouse movement, and system entropy to generate the secret, making it impossible to reproduce even if the software is known.

Why This Is Sufficient

The MPC protocol is designed so that the toxic waste can only be reconstructed if every single participant's secret is recovered. If even one participant genuinely destroys their secret, the system is secure. With 73 participants from diverse backgrounds, geographic locations, and trust models, the probability of all 73 being compromised is negligible.

This is sometimes called the "1-of-N" trust assumption: you only need to trust that 1 out of N participants acted honestly.

Future Considerations

Migration to Universal Setup

The ZKMix roadmap includes evaluating a migration from Groth16 to a proving system with a universal (circuit-independent) trusted setup or no trusted setup at all. Candidates include:

  • PLONK with KZG commitments -- Universal setup, larger proofs (~400 bytes), but eliminates the need for per-circuit ceremonies.
  • Halo2 -- No trusted setup, recursive proof composition, but verification is more expensive.
  • Nova/SuperNova -- Incremental verifiable computation with no trusted setup.

Any migration would require Solana to support the necessary precompiles for efficient on-chain verification. The current alt_bn128 precompiles are optimized for Groth16/BN254 pairings. Supporting other systems may require new precompiles or significantly higher compute budgets.

Ceremony Replay

If the ZKMix withdrawal circuit is ever modified (e.g., to support additional public inputs or change the hash function), a new Phase 2 ceremony must be conducted for the updated circuit. Phase 1 parameters can be reused.

The ZKMix team is committed to conducting new ceremonies with at least as many participants as the original ceremony whenever circuit changes are necessary.