SenddySenddy Docs

ZK Circuits

The zero-knowledge circuits that power Senddy's privacy — Shield, Spend, and Association.

Overview

Senddy's zero-knowledge proofs are built with Noir, a domain-specific language for writing ZK circuits. Proofs are generated using the UltraHonk proving system and compiled to WebAssembly for client-side execution.

Universal setup

UltraHonk uses a universal trusted setup, meaning the same setup ceremony works for any circuit. This is a significant advantage:

  • No per-circuit ceremony — Adding new circuits or upgrading existing ones doesn't require a new trusted setup
  • Battle-tested parameters — The universal setup has been used across many production systems
  • Upgradeable — The system can evolve without re-running ceremonies or asking users to trust new setups

Shield Circuit

The shield circuit converts public deposits into private notes.

Purpose: Prove that a deposit was correctly converted into private notes without revealing the note details.

What it proves:

  • Total output value equals the deposit amount (value conservation)
  • Note commitments are correctly computed (Poseidon2 hash of value, owner, randomness)
  • Output notes belong to the depositor

Spend Circuit

The spend circuit transfers or withdraws private notes.

Purpose: Prove that the spender owns the input notes, they exist in the Merkle tree, and the input/output values balance.

What it proves:

  • Each input note exists in the Merkle tree (membership proof via Merkle path)
  • The spender knows the secret key for each input note
  • Nullifiers are correctly derived from the commitment and secret key
  • Total input value equals total output value plus fees and withdrawal (conservation)
  • Supports optional withdrawal to a public Ethereum address
  • Supports optional relayer fee for gasless transactions

Association Circuit

The association circuit enables optional, privacy-preserving compliance. It complements Senddy's deposit screening (which blocks sanctioned addresses) by giving legitimate users a way to prove their funds are clean after they've been in the private pool.

Purpose: Prove that a user's funds trace back to approved deposit sources without revealing their full transaction history.

What it proves:

  • The note's nullifier is correctly derived from the user's secrets
  • The source deposit exists in an Association Set Provider's (ASP) approved set (Merkle membership proof)
  • A valid chain of custody links the deposit to the user's current note

Key properties:

  • Voluntary — Association proofs are never required for basic usage
  • Privacy-preserving — The proof reveals nothing about which specific deposit funded the note, only that it was in the approved set
  • Multi-ASP support — Different ASPs can maintain different compliance standards for different jurisdictions

See Compliance for the full compliance model.

Proof Performance

MetricValue
Proving time (browser)2-5 seconds
Proving time (mobile)3-7 seconds
Proof size~8 KB
Verification (attestor)< 1 second

Proofs are generated client-side using WebAssembly. The UltraHonk proving system is optimized for browser performance.

On this page