Skip to main content

Security and Privacy

TEST deployments

The proving keys of the C4 and C5 instances were generated with public TEST entropy, so anyone could in principle rebuild the setup secrets and forge proofs. Neither the contracts, the circuits nor the wallet library have been independently audited. Do not use them for funds of value.

What the pool hides​

  • The owner of every note.
  • The amounts of assignments inside the pool.
  • Which note a transaction spends. A nullifier cannot be linked to its commitment without the owner's key.
  • The recipients of an assignment.
  • The link between the receiving addresses of one wallet, since each address has independent keys.

What stays public​

ItemWhat an observer sees
DepositsThe amount and the funding coin, with its address and history
WithdrawalsThe amount and the destination address. A withdrawal always takes a whole note
FeesThe sponsor coin and its address. The change returns to the same script, so every operation paid from that address is linked
FormThe verification key reveals the operation and, for assignments, how many notes were created. A T1 shows that a whole note went to one recipient without change
ReserveThe total XNA in the pool after every transaction
TimingThe block and the order of every operation
Network metadataThe RPC node sees the client's IP address, the coins it checks and the transactions it publishes. The server of the proving files sees which form's files are downloaded, and when

Linking risks​

Zero-knowledge proofs hide the private ledger, not the public facts around it. With few users, amounts and timing alone can link operations. If the only activity is deposit 1,000 → assign 400 to Bob → Bob withdraws 400, an observer sees 1,000 XNA enter, an assignment, and 400 XNA leave to Bob's address, and can guess the relationship.

Ways to reduce linking, none of which guarantees anonymity:

  • Pay fees from coins that are not linked to the deposit or withdrawal addresses, and do not reuse one sponsor address for unrelated operations.
  • Avoid withdrawing exactly the amount that was deposited, and avoid unique amounts.
  • Leave time between a deposit and later operations.
  • Use your own node, so that no third-party RPC operator sees your queries.

Keeping funds in the pool hides who owns them now, but the original deposit stays visible. A small testnet pool has a small anonymity set even when the cryptography is correct.

Trust assumptions​

ComponentWhat the wallet checksWhat it trusts
Node (RPC)The genesis, that every transition matches the pinned contract and that every block used is still in the active chainThat the node validates consensus, including the proofs of past transactions, and does not hide confirmed transactions. A lying node can show a stale or incomplete view, and transactions built on it fail at publication
ManifestLeaves, control blocks, verification keys, guard, domain and context. The commitment must match an independent pinThat the pinned contract actually implements safe custody
Proving filesSize and SHA-256 of every fileNothing else: a wrong file is rejected. The server can still refuse to serve them
snarkjsEvery proof is verified locally before useThe injected module runs inside the worker and sees the private witness
Application codeNothingThe worker keeps secrets away from page code, but it cannot stop malicious code in the same application, such as a compromised dependency
RandomnessFails if crypto.getRandomValues is missingThe platform's secure random generator for rho, ephemeral keys and nonces

Where secrets live​

DataLives inLeaves the worker
Account key, spend secrets, view seeds, nullifier keysWorkerNever
Note plaintexts and circuit witnessesWorkerOnly inside the encrypted checkpoint
Scan checkpointWorker and pageYes, encrypted and authenticated
Balance, own commitments and amounts, receiving addressesWorker and pageYes
Proof and unsigned transactionWorker and pageYes. They become public anyway

The page learns the balance and which commitments belong to the wallet. That link is private and must never be sent to analytics or a server. RPC requests never contain wallet words, passphrases, spend secrets, note plaintexts or witnesses. Wiping keys in JavaScript is best effort: the engine may keep copies that cannot be erased.

Not implemented yet​

  • Selective disclosure. There are no receipts or viewing capabilities that prove where a payment came from. Exporting spend secrets is not a substitute, and a withdrawal alone does not prove a particular source.
  • Note merging. A transaction consumes one note.
  • Asset pools in wallets. Ordinary assets were tested at node level. Restricted assets, qualifiers and DePIN permissions keep their own consensus rules, and a privacy proof does not override them.
  • Forced exit. The current eight-leaf contract has no separate exit or congestion protocol.

Before funds of value​

At least these parts need independent review:

  • note ownership and nullifier constraints in the circuits;
  • bounded amounts and conservation of the reserve;
  • the HPKE record construction and data availability;
  • the TXHASH anchor and the Script introspection that checks it;
  • the commitments from verification keys to contract leaves;
  • wallet secret storage, exact amount parsing and recovery after reorganizations;
  • a trusted setup ceremony with independent contributions to replace the TEST proving keys.

Replacing verification keys changes the contract leaves and the pool commitment. That is a new deployment, with new pins and a migration plan, not a silent parameter update.