Skip to content

Security and Trust ​

Veilix separates things you must trust from things the proof checks. This page is that split, as the program works today.

You do not trust a custodian with the spending key ​

The treasury can pay out only when a proof verifies. The proof requires the spending key inside the note. The team, a relayer, and the indexer cannot produce that proof from public data.

A relayer who submits your proof cannot change the recipient or the fee. Those fields are hashed into the public inputs, and the program rebuilds the hash from the instruction.

A nullifier can be stored once. The same note cannot be withdrawn twice.

You do trust the software that builds the proof ​

The circuit, the proving key, and the client are what bind your secret to the recipient you chose. A malicious client can build an honest-looking proof that pays someone else, or can upload the note. Review the client you run, and prefer builds that check the circuit artifacts before proving.

In the browser, the SDK checks the proving artifacts against a pinned SHA-256 hash before proving, and falls back to the pinned CDN if another URL does not match. In Node, the process reads the circuit files from the package (or from the paths you set) without that browser check.

You do trust the chain and the program ​

The program is the verifier and the treasury. If the program is wrong, the proof system does not save you. The configuration authority on network state can:

  • replace the platform-fee wallets and their basis points
  • change the per-tree maximum deposit

That authority cannot spend a note. It can change what a future withdrawal must pay, and how large a new deposit may be. Fee wallets are public configuration. Read them before you withdraw if the fee matters.

The program is not described here as immutable. An upgrade authority, if one still exists on the deployed buffer, is a further trust assumption that lives outside this book. Check the program account on Solana before you rely on it.

You do not need the indexer to be honest for correctness ​

A withdrawal verifies against an on-chain root. An indexer that invents leaves cannot make a false proof pass. An indexer that hides your leaf can delay you, or can serve a stale view. If a spend fails because the leaf is missing, wait and retry. Do not conclude that the note is gone until the nullifier exists on-chain.

Side channels are still real ​

The visibility page lists them. The important one for this design is amount. Variable amounts are a feature. They are also a correlation channel when the public numbers are unique. Waiting, and not withdrawing the same unusual number you deposited, is part of using the system as intended.

Screening is a client gate ​

Flagged recipients are refused by the SDK before a proof is built. That protects the default path. It is not, in the current instruction layout, an oracle account on the withdrawal. See Address Screening.

What to verify yourself ​

ItemWhere
Program idHbatG5gpfs2g3N4gc2Qkfmmeu4zaBEVxzrDdYtWNLyyA
Relayer registry mintGAFN64LvtCBoc5BHncVn3JEJGpq42rUzQjPmvMK2UhZH
Tree, cap, recent rootThe tree account for that asset
Fee walletsNetwork state, seed config
Whether a note is spentThe nullifier account, or the indexer’s nullifier check