Concepts

The two privacy profiles

One core, two postures. Profile A makes shielded notes the default. Profile B keeps the L3 transparent and adds an opt-in, compliance-compatible Privacy Pool. A single config flag selects between them.

shh deliberately ships two profiles so that the same cryptography can serve both a privacy-maximal chain and a regulator-legible one. They share circuits, the Merkle tree, and verifiers — they differ only in which contract is the default value path and what the genesis sets.

Profile A — Full privacy chain

The ShieldedPool is the canonical value layer. Balances live as UTXO note commitments in a Poseidon Merkle tree, and transfers are join-split proofs. There are no transparent transfers in the default UX — value moves by spending input notes and creating output notes, all behind a proof.

  • Arbitrary amounts (UTXO model, after Tornado Nova).
  • A 2-in / 2-out transaction circuit covers deposit, private transfer, and withdraw via a signed publicAmount.
  • Strongest unlinkability: there is no public balance to correlate against.

Profile B — Open L3 + Privacy Pool

A normal, transparent EVM L3. Privacy is opt-in through the fixed-denomination PrivacyPool. Crucially, withdrawals require an Association Set membership proof, so an ASP (Association Set Provider) can scope which deposits may exit privately — unlockable, i.e. compliance-compatible, privacy.

  • Fixed denomination per pool (e.g. 0.1 ETH) concentrates the anonymity set.
  • Withdrawals prove membership in both the state tree and an ASP-published association tree.
  • Excluding a tainted deposit from the association root leaves it deposited but non-withdrawable through the private path.

Side by side

Profile A — ShieldedProfile B — Privacy Pool
Default value pathShieldedPool (notes)Transparent EVM + opt-in pool
AmountsArbitrary (UTXO)Fixed denomination
Core circuittransaction (2-in/2-out)poolWithdraw
Compliance hookAssociation Set (ASP)
Best forPrivacy-maximal appsRegulator-legible deployments

Selecting a profile

The profile is chosen by a single environment flag, recorded in the deployment manifest and surfaced over the backend's /api/config:

bash
SHH_PROFILE=full-privacy   # Profile A
SHH_PROFILE=open-pool      # Profile B (default)

Read the cryptographic detail in Profile A — Shielded UTXO pool and Profile B — Privacy Pool.