Privacy design

Profile B — Privacy Pool & Association Sets

The compliance-compatible value model: a fixed-denomination pool, two Merkle trees (state + association), and a withdraw circuit that proves a deposit both exists and is ASP-approved — without revealing which deposit.

A Privacy Pool is parameterised by a single denomination (e.g. 0.1 ETH). Every deposit is for exactly that amount, which concentrates the anonymity set. Withdrawals prove membership in two trees at once.

Secrets & public values

NameTypeWhere
nullifierrandom F_psecret
secretrandom F_psecret
commitmentH(nullifier, secret)public on deposit, hidden on withdraw
nullifierHashH(nullifier)public on withdraw

Two trees

State tree (stateRoot)
Every deposited commitment, in insertion order.
Association tree (associationRoot)
The subset of commitments the ASP marks compliant. Same leaf value, so one secret proves membership in both.

The withdraw circuit

pool/poolWithdraw.circom. Public signals, in order:

text
[ stateRoot, associationRoot, nullifierHash, recipient, relayer, fee, refund ]

Private inputs: nullifier, secret, statePathElements[LEVELS], statePathIndices, assocPathElements[LEVELS], assocPathIndices.

Constraints

  1. commitment = H(nullifier, secret).
  2. nullifierHash === H(nullifier).
  3. MerkleProof(commitment, statePathElements, statePathIndices) === stateRoot — it exists.
  4. MerkleProof(commitment, assocPathElements, assocPathIndices) === associationRoot — it's approved.
  5. recipient, relayer, fee, refund are bound (squared) so the proof can't be reused with different withdrawal parameters.

What the contract does

The contract checks nullifierHash is unused, marks it spent, verifies the proof against the current stateRoot (or a recent historical root) and the ASP's published associationRoot, then pays denomination − fee to recipient and fee to relayer.

Unlockable / compliance

The ASP learns no more than the public deposit set; it only chooses a subset to endorse. Build these proofs with the SDK — see SDK: Privacy Pool — and submit them gaslessly via the relayer.