Deposit
Funds enter the pool as a note only you can spend, signed with a hash-based key.
one frame transaction, about 7.5M gas
Three hops, shuffled batches, cover traffic. What leaves cannot be matched to what went in.
A deposit becomes a note only you can open. Spending it proves you own a note, never which one.
Every figure was measured on the testnet.
Funds enter the pool as a note only you can spend, signed with a hash-based key.
one frame transaction, about 7.5M gas
Your wallet proves it owns an unspent note without saying which.
about a second to prove, 450 MB of memory
The proof leaves as identical 8 KB packets through three post-quantum hops.
about a minute on a mobile connection
The exit pairs your spend with another and folds both proofs into one.
12 to 20 minutes on one machine
One transaction verifies the proof and pays both recipients.
16.3M gas
The gateway knows who sent a packet, not where it goes. The exit knows where it goes, not who sent it. Drag the globe.
Most privacy systems are held together by elliptic curves. A quantum computer breaks them: it could forge their proofs, sign for their accounts and unwrap recorded traffic.
Each layer of every packet is sealed with ML-KEM-768, paired with X25519.
Replaces X25519 alone
Accounts and the paymaster sign with leanSPHINCS, which rests on hash functions alone.
Replaces ECDSA
Spends are proven with Spartan-WHIR and checked on chain by a WHIR verifier, with no trusted setup.
Replaces Groth16 on BN254
Five layers between your wallet and the chain, each one post-quantum.
Proves it owns an unspent note with Spartan-WHIR, in about a second, without saying which note.
Rests on hash functions
8 KB KEM-Sphinx packets sealed with X-Wing (ML-KEM-768 and X25519) at each of three hops, mixed in batches with cover traffic.
Rests on lattices
A Binius64 ticket each epoch proves membership anonymously; cheap hash tokens then pay for each packet.
Rests on hash functions
Checks each spend against the chain and folds two proofs into one with leanVM recursion.
Rests on hash functions
One EIP-8141 frame transaction verifies the proof with WHIR; a leanSPHINCS signature authorizes the paymaster.
Rests on hash functions
The pool's validation and settlement are modelled in Lean 4 and these properties are proven, with no unfinished proofs and no axioms beyond Lean's standard two. The model is tested against the live chain, transaction by transaction. What it assumes is written down in the soundness statement.
theorem only_settle_runs_as_pool (pool : Nat) (tx : Tx)
(h : poolPolicy pool tx 0 = .ok ()) :
∃ f2, callsAsSender tx = [f2] ∧ f2.target = pool ∧
f2.selector = SETTLE ∧ f2.value = 0theorem pool_never_pays (pool : Nat) (tx : Tx)
(h : poolPolicy pool tx 0 = .ok ()) :
∃ f0 f1 f2, tx.frames = [f0, f1, f2] ∧ f0.flags = SCOPE_EXECUTION ∧
f1.flags = SCOPE_PAYMENT ∧ f1.target ≠ pooltheorem run_distinct {rootOf : List Nat → Nat} :
∀ (s : State) (txs : List (Bool × Bool × Spend × Spend)),
Distinct s.spent → Distinct (run rootOf s txs).spenttheorem failed_settle_changes_nothing {rootOf : List Nat → Nat}
{s : State} {p q : Bool} {a b : Spend} {e : Err}
(h : settle rootOf s p q a b = .error e) : step rootOf s p q a b = stheorem settle_preserves_inv {rootOf : List Nat → Nat} {s s' : State}
{p q : Bool} {a b : Spend}
(inv : Inv s) (sa : Sound s a) (sb : Sound s b) (fr : Fresh s a b)
(h : settle rootOf s p q a b = .ok s') : Inv s'theorem pq_pool_tx_has_no_ecdsa (d : Deployment) (tx : Tx)
(hpq : d.pqPaymaster = true) (hpp : d.paymaster ≠ d.pool)
(h : valid d tx = true) :
∀ s ∈ tx.sigs, s.scheme = ARBITRARYA TypeScript SDK, a Foundry library, a node binary and a Lean model. Pick a file.
topi
import { PoolReader, RpcClient, loadPoolDeployment } from "@topi/sdk";
const rpc = new RpcClient("https://rpc1.privacy.ethrex.xyz");
const deployment = loadPoolDeployment("deployments/8141/pool.json");
const pool = new PoolReader(rpc, deployment.pool);
// Rebuild the pool's trees from its public events.
const view = await pool.chainView(deployment);
console.log(view.next_leaf, "notes in the pool");// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import { IShieldedPool } from "topi/interfaces/IShieldedPool.sol";
contract Depositor {
IShieldedPool immutable pool;
constructor(IShieldedPool pool_) {
pool = pool_;
}
function deposit(uint256[8] calldata note) external payable {
pool.deposit{ value: msg.value }(note);
}
}cargo build --release
# one key per node, then start the gateway
target/release/topi-node keygen keys/gateway.key
target/release/topi-node run gateway \
--topology topology.json --key keys/gateway.key
# send a ping through all three hops and back
target/release/topi-client ping \
--topology topology.json --identity member.idtheorem run_distinct {rootOf : List Nat → Nat} :
∀ (s : State) (txs : List (Bool × Bool × Spend × Spend)),
Distinct s.spent → Distinct (run rootOf s txs).spent
| _, [], h => h
| s, (p, q, a, b) :: rest, h =>
run_distinct _ rest (step_distinct (a := a) (b := b) (p := p) (q := q) h)One terminal for the whole system: the network on a map, the cloud, the wallet, the prover and the proofs.
leave no trace
■ live
nodes up4/4
packets relayed18,402
batches612
cover packets3,977
Lean14 theorems, all checked
■ a private spend's path
$ cargo install --locked --git https://github.com/Naveen-6087/topi topi-tui topi-mixnet$ topi$ curl -L https://github.com/Naveen-6087/topi/releases/latest/download/topi-aarch64-apple-darwin.tar.gz | tar xz$ ./topi-aarch64-apple-darwin/topi$ curl -L https://github.com/Naveen-6087/topi/releases/latest/download/topi-x86_64-unknown-linux-gnu.tar.gz | tar xz$ ./topi-x86_64-unknown-linux-gnu/topi> iwr https://github.com/Naveen-6087/topi/releases/latest/download/topi-x86_64-pc-windows-msvc.zip -OutFile topi.zip> Expand-Archive topi.zip .> .\topi-x86_64-pc-windows-msvc\topi.exe$ git clone https://github.com/Naveen-6087/topi topi && cd topi$ cargo run --release -p topi-tuiThe console runs from a checkout of the repository: its actions call the scripts and contracts there. Prebuilt binaries come with each tagged release; the node and client binaries are in the same archive.
How the pool, the mixnet and the prover fit together, and how to run each of them.
A gateway, mix, exit or reply relay, on your machine or in an AWS region of your choice.
Encode frame transactions, read the pool and drive a spend from TypeScript.
Build the Lean model, audit its axioms and read what the theorems do and do not cover.