Skip to content
VOUCHVOUCHDocs

Getting started

Core concepts

The vocabulary of the rest of the docs: what a note is, where its truth lives on chain, and the handful of fields that make a proof single-purpose.

On this page

#Notes and the Ironwood pool

Shielded ZEC is held as notes: encrypted records of a value addressed to a key. A wallet’s balance is the sum of its unspent notes. Since July 2026 the active shielded pool is Ironwood, which replaced Orchard after the Orchard counterfeiting flaw; Ironwood activated at mainnet block 3,428,143 and testnet block 4,134,000. Vouch proves facts about Ironwood notes.

The chain never shows a note. It shows two things about each one: a note commitment (cmx) when the note is created, and a nullifier when it is spent.

#The note-commitment tree and the spent set

Every note commitment ever created is a leaf of an append-only Merkle tree; its root at a height is nc_root. Every nullifier ever revealed is in the spent set, which Vouch arranges as an indexed Merkle tree (IMT) of sorted ranges; its root is nf_root.

Membership in the note tree, non-membership in the spent setnc_rootsiblingpath··pathsiblingcm0cm1cm2cm3cm4cm5cm6cm7your noteNote-commitment tree at nc_heightthe tree only grows: a leaf at H₀ is a leaf for ever0pyour nfIMT leaf (low, next)low < nf < nextnf_roothashes up to● a revealed (spent) nullifierSpent-nullifier IMT at heightspending a note reveals its nullifier, for ever
Left: a Merkle path shows the note is a leaf of the tree whose root is nc_root. Right: an IMT leaf (low, next) with low < nf < next shows the note's nullifier was never revealed, so the note is unspent. Neither the note nor the nullifier is shown to the verifier.

A proof shows, for each of up to five notes, a Merkle path to nc_root (the note exists) and an IMT range that excludes its nullifier (the note is unspent), without revealing the note, the path or the nullifier.

#Anchors

An anchor is a finalised height and the two roots at it. A verifier accepts a proof only if both of its roots appear in the verifier’s anchor table. Vouch’s pof-anchor rebuilds the roots from public compact blocks and checks the tree root against lightwalletd’s own; anyone can re-derive every entry. See Anchors and chain data.

#The claim and its units

Each proof carries exactly one claim. Today that is HoldsAtLeast { zatoshi }: the notes together hold at least that much. The circuit counts value in units of 0.125 ZEC (12,500,000 zatoshi), so thresholds are whole multiples of 0.125 ZEC. The sum itself is committed inside the proof and never revealed. “Exactly X” is deliberately not offered: a threshold reveals less.

ThresholdZatoshiUnits
1 ZEC (or TAZ)1000000008
500 ZEC500000000004,000
4,018.125 ZEC40181250000032,145

#The fields that make a proof single-purpose

FieldWhat it does
AudienceThe verifier the proof is for, stored as blake2b("pof-audience:" ‖ id). Only that verifier, matching its own identifier, accepts it; nobody else learns who it was for.
ExpiryAn absolute time. From that second on, every verifier answers Expired.
BindingWho may use the proof: all zero (anyone holding the file), a Solana public key (only that wallet can act on the receipt), or a deposit intent for an exit certificate.
Revocation tag16 bytes of blake2b of a secret only the holder has. Publishing the secret revokes the proof everywhere the list is checked.
Two heightsnc_height (the tree) and height (the spent set). When the first is earlier, the proof says “unmoved since nc_height”.
EpochThe verifier’s period, chosen in its request. With the circuit and audience it forms the scope.

#Scopes and tags

Each note in a proof produces a tag (the circuit calls it a governance nullifier). In format version 2 tags are derived from the scope: the circuit, the audience and the epoch. The same note always gives the same tag in one scope, and unrelated tags in different scopes.

Scopes: reuse is visible to one verifier, linkable by nobody elseYour notereal nullifier nfkey nkScope A, 1st proofcircuit 1 · rail:x · OctScope A, 2nd proofcircuit 1 · rail:x · OctScope Bcircuit 1 · lender:y · Octtag 7f3a…tag 7f3a…tag c91e…AlreadyUsedrail:x sees the same coinspledged twice this monthUnrelatedlender:y and rail:x cannotlink their two proofs
tag = Poseidon(nk, dom, nf), with dom derived from the scope (circuit, audience, period). The tag is deterministic per note and scope, and reveals nothing about nf or nk.

So a verifier that records tags sees when the same coins are pledged to it twice in a period (AlreadyUsed), and two verifiers can never link their proofs to each other. A proof made without an epoch gets a fresh scope of its own and links to nothing.

#Unmoved since block H

Because the two roots are separate inputs, a proof can take the tree at an earlier block H₀ and the spent set at a later block H₁. It then says the notes were already in the chain at H₀ and have not moved since. The verifier chooses H₀ in its policy, for example a block before a known incident. See How it works.

#Exit certificates

An exit certificate is a proof made with the second circuit, which also reveals the certified notes’ real nullifiers. When the deposit lands, the rail reads the nullifiers the deposit transaction reveals and checks they are all certified. See Exit certificates.

#Attestations, receipts and feeds

TermMeaning
AttestationA 139-byte message (POF-ATTEST-v1) signed with Ed25519 by an attestor that ran the verifier and got Valid.
ReceiptA pof-gate account created from an attestation, one per proof id, bound to the holder’s wallet. Consumer programs read it.
ConsumedA receipt a consumer program has used, through a CPI only that program’s PDA can sign. A receipt is consumed once.
FeedA pof-reserve account holding an attested reserves total, with a heartbeat after which it reads as stale.

#Demo, testnet and mainnet

NetworkWhat it isWhere it appears
demoA published synthetic ledger with real keys and real proofs. Lets anyone see a real proof without ZEC.The /demo credit flow, most /verify presets, reserves demo
testnetZcash testnet: real chain, real wallet, TAZ with no monetary value.The real dormancy proof, the real exit, the first real proof
mainnetZcash mainnet. The anchor at 3,493,000 is rebuilt and checked; no mainnet proof has been made.The anchor table