Veilify uses two kinds of nullifier.

Note nullifier

  • Published when a note is spent. Recorded in noteNullifiers.
  • Deterministic, so the same note always yields the same nullifier → no double-spend.
  • Needs nk, so nobody else can link a nullifier to its commitment.
Each operation carries six nullifier slots. Unused slots are zero, and the contract skips them.
nullifiersHash is bound into every output note commitment.

Transaction nullifier

  • One per signed transaction. Recorded in txNullifiers.
  • Built from the signed nonce and chain ID, so a signature can execute at most once on this deployment → no replay.
  • Keyed by the sender’s inbox-key hash. This is why a registered inbox key can never be replaced: after a rotation, one signed transaction could be proven once per key.

Contract checks

Spent note nullifiers are announced with NoteSpent(noteNullifier).