Skip to content
VOUCHVOUCHDocs

Architecture

System architecture

Vouch is a file format and the small set of programs that write it, check it and act on it. This page maps every component, what it depends on, what it talks to, and where it runs.

On this page

#Components

System overview: chain data, the holder, verifiers and SolanaZcash networkZcash chainIronwood poollightwalletdcompact blocksAnchor publisher · anyone can run itpof-anchorrebuilds the note treeand the nullifier IMT.vsnp snapshotevery commitmentand nullifierAnchor tableheight · nc_root · nf_root/api/anchorsrootsHolder's machineWallet seedread locallypof-provefinds notes,proves, signs.pof≈ 11.9 KBpublic dataAnyone can verifyBrowserpof-wasmpof-verifyCLIAttestorpof-attest.poftrusted rootsRelying partiesRail · exchange · deskchecks an exit certificate,matches the depositLender · counterpartyreads proof of funds,sees reuse in its periodValid · or why notSolanapof-gatereceiptspof-creditcredit linespof-reservereserves feedEd25519 verdict
Public chain data becomes trusted roots; the holder proves against them on their own machine; anyone verifies the .pof file; an attestor carries the verdict to Solana.
ComponentRoleRuns whereNetwork
pof-anchorRebuilds the note tree and nullifier IMT from compact blocks; writes snapshots; publishes anchors.Whoever publishes anchorslightwalletd (gRPC)
pof-proveFinds the holder’s notes in a snapshot, proves the claim, signs it, writes the .pof.The holder’s machinenone (library); revoke only
pof-verifyThe verifier library and CLI: six checks, typed verdicts.Anywherenone
pof-wasmpof-verify compiled to WebAssembly with the verifying key embedded.The browser, in a Web Workernone
pof-attestHTTP service: verify, sign attestations for Solana, the rail API, reserves attestations.Render (hosted), or anyoneSolana RPC, revocation list, lightwalletd
pof-gateSolana program: attestations in, receipts out.Solana devnet—
pof-creditSolana program: credit lines against receipts.Solana devnet—
pof-reserveSolana program: reserves feed and Secure Mint.Solana devnet—
The siteNext.js: verifier, request builder, prover console, rail console, reserves, the live demo, these docs, and a thin API.Vercelthe attestor, Solana RPC, Redis

#The Rust workspace

The Rust crates and what each depends onpof-wasmthe browser buildpof-attestHTTP servicepof-proveholder library + CLIpof-verifyverifier + CLIpof-anchorsnapshots · lightwalletdpof-zkcircuit glue · embedded VKpof-corethe .pof formatvoting-circuitsvendored · Valar Groupdemo holderNetwork: pof-anchor (lightwalletd gRPC) · pof-attest (Solana RPC, revocation list, lightwalletd for rails)
Arrows point from a crate to what it uses. Every crate also uses pof-core, the format. Only pof-anchor and the attestor talk to a network; pof-prove's library links no network client, and a test enforces it.
CrateKey entry pointsNotes
pof-coreencode · decode · statement_hash · signing_message · audience_hash · revocation_tag · subject_hashThe format. Decoding is injective: canonical varints, checked lengths, timestamps ≤ 2⁵³ − 1.
pof-zkVerifier::new · verify_holding · instance_for · round_id · NoteTree · prove_holding (feature prove)Embedded params and verifying keys; refuses repeated tags before Halo2.
pof-verifyverify(bytes, &Context) → VerificationResult · verify_batch · exit_matchesThe single source of verdicts.
pof-proveselect_notes · envelope_for · prove · wallet::find_notes · DemoWorld · historyA test fails the build if the library links a network client.
pof-anchorSnapshot::{read, write, anchor} · Lightwalletd::scan · publishThe only crate with a gRPC client.
pof-attestattest · verify_only · rail::{submit, match_deposit, batch} · demo::proveAxum; per-core semaphore; 64 KiB body limit (2 MiB for batches).
pof-wasmwarm · verify · versionwasm-bindgen, about 4.6 MB, committed so CI tests exactly what ships.

The vendored crates are in backend/vendor/; every Vouch change is listed in THIRD-PARTY.md and in each crate’s VOUCH-MODIFICATIONS.md. The Solana programs are a separate Anchor workspace in backend/solana/.

#Repository layout

PathWhat it is
frontend/The site (Next.js 15): pages, the API routes, the committed WASM verifier, these docs.
backend/crates/The seven Rust crates above.
backend/vendor/voting-circuits and its dependencies, with marked Vouch modifications.
backend/solana/pof-gate, pof-credit, pof-reserve (Anchor) and the LiteSVM tests.
fixtures/Real proofs with their expected verdicts, anchor tables, the demo ledger, request vectors.
scripts/WASM build, fixture sync, the WASM parity check, end-to-end test, local stack, devnet deploy.
.github/workflows/CI (every test but e2e), release builds of the CLIs, the attestor keepalive.

#Data flows

FlowFrom → toCarriesNever carries
Anchorslightwalletd → pof-anchor → anchor table → every verifierheights, roots, block hashes—
Requestverifier → holder (a link)claim, audience id, expiry, period, policyanything about the holder
Proofholder → verifier (a file or link)the statement and the evidencebalance, notes, addresses, keys
Verify linkholder → anyonethe proof after the #nothing reaches a server log
Attestationattestor → Solana139 signed bytesproof bytes
Rail API storeattestor ↔ railids, tags, revealed nullifiers, verdicts, timesproof bytes
Revocationholder → list → verifiersa 32-byte secretwhich proof it was, to anyone else

#The hosted deployment

The hosted deploymentVisitor's browserpages + WASM verifierproofs stay localVercelNext.js sitepages · docs · /proofs · /wasmSite API/api/anchors · revocations · status/api/attest · relay · reserveUpstash Redisrevocations · used demo proofsrate limits · budgetsRender · free planpof-attestverify · attest · rail APIEd25519 key from the environmentSolana devnetProgramspof-gatepof-creditpof-reserveZcash testnetlightwalletdtestnet.zec.rocksdeposit lookupsHTTPSstate/v1/attest · /v1/batchrelayer txsrevocation listslotGetTransaction
The site and its API run on Vercel with Upstash Redis for shared state; the attestor runs on Render; the programs are on Solana devnet; deposit lookups go to a public testnet lightwalletd.
PieceWhereNotes
Site and APIVercelDeployed from frontend/. Upstash Redis holds revocations, used demo proofs, rate limits and hourly relayer budgets.
AttestorRender, free planrender.yaml builds pof-attest without the demo prover (one proof takes about 2 minutes on 0.1 CPU); /demo uses 120 pre-made single-use proofs instead.
ProgramsSolana devnetFixed program ids; the admin keeps the upgrade authority, which initialize requires.
CLIsGitHub ReleasesBuilt for Linux, macOS (arm64) and Windows from each v* tag.

Free Render instances sleep after 15 minutes idle. The site’s /api/status reports a sleeping attestor as waking, and /demo waits for it rather than falling back to the simulated chain.

#Design principles

  • The proof is a file, not an API call. Offline verification, a testable boundary, a format that outlives any implementation.
  • One verifier. The CLI, the browser and the attestor run the same code; CI proves they agree.
  • The verifier never trusts a field it can derive. Roots, round id, domain and threshold are recomputed or looked up.
  • Keys stay put. The prover links no network client; nothing is broadcast.
  • Boring, plural attestors. Stateless, re-runnable, allowlisted, k-of-n.
  • Honest labels. Demo, testnet and simulated are said wherever they apply.