Getting Started
TraceZero is a privacy-preserving transaction protocol for Solana. It breaks the on-chain transaction graph so that an observer cannot link who funded a transfer to who received it — using RSA blind signatures, zero-knowledge proofs, stealth addresses, and Tor routing.
The four-phase flow
| Phase | What happens | What breaks the link |
|---|---|---|
| 1 — Credit | Buy credits with an RSA-2048 blind signature (RFC 9474). | The blinding factor makes the payment unlinkable to redemption. |
| 2 — Deposit | Deposit over Tor with a Poseidon commitment, from a separate wallet. | Wallet separation + encrypted, Tor-routed request = on-chain dead end. |
| 3 — Withdraw | Prove Merkle membership with a Groth16 ZK-SNARK. | Zero-knowledge: the proof reveals nothing about which deposit is yours. |
| 4 — Claim | Funds land at a one-time X25519 stealth address; sweep to your destination. | The stealth address has no on-chain link to the deposit. |
See Architecture for the full sequence and Mathematical Foundation for the cryptography.
Repository layout
TraceZero/
├── app/ TanStack Start + Vite dApp (the in-browser client)
├── crates/ Rust: relayer, tor-gateway, network, privacy-proxy-sdk, tracer
├── circuits/ Circom ZK circuits
├── programs/ Solana Anchor program (privacy_proxy)
├── docs/ Engineering docs (rendered into this site)
├── sdk/ @tracezero/sdk — TypeScript client + authenticated telemetry
├── counter/ Cloudflare Worker + D1 — the authenticated live usage counter
└── site/ This landing + docs site (Astro)
Run the relayer
The relayer is the HTTP API the SDK talks to (crates/relayer, default port 8080):
# from the repo root, with the Rust toolchain installed
cargo run -p relayer
Configuration is via environment variables (RPC_URL, KEYPAIR_PATH,
TREASURY_KEYPAIR_PATH, PROGRAM_ID, FEE_BPS, HOST, PORT). See
crates/relayer/src/config.rs.
Use the SDK
npm install @tracezero/sdk
import { TraceZeroClient } from "@tracezero/sdk";
const client = new TraceZeroClient({ relayerUrl: "http://localhost:8080" });
const info = await client.getInfo();
console.log(info.buckets); // the 7 fixed-denomination pools
Full reference: SDK Reference.
Run the live counter locally
cd counter
npm install
npm run db:init # local D1 tables
npm run dev # http://127.0.0.1:8787
Then point the SDK (and this site’s PUBLIC_COUNTER_URL) at it to see the
authenticated counter tick up as the SDK is used.