ONE PROOF
TO RULE THEM ALL.
Send XLM through a private pool on Stellar. We bundle many withdrawals into one transaction at a fixed cost, so the on-chain fee stays flat as the pool grows. The chart on the right is the proof: measured on testnet, today.
Measured at N = 4 on Stellar testnet (dots above). The recursive line is structurally flat: one outer UltraHonk verify regardless of how many inner proofs it aggregates. The naive line is linear: every proof is its own transaction. Drag the slider — the chain doesn't care how many proofs are inside.
yellow climbs linearly · every proof is its own transaction. blue stays flat · one aggregated proof, one transaction, any N.
the problem
Verifying one zero-knowledge proof on Stellar is cheap. Verifying a thousand of them costs a thousand times more. On-chain cost grows in lockstep with usage, and that's what stops privacy apps from scaling past tiny user counts.
Every private operation, a transfer, a vote, a trade, needs its own proof verified on-chain. One proof, one transaction, one fee. If a thousand users transact privately, the chain does the same verification work a thousand times. The fee bill grows in lockstep.
Stellar's recent protocol upgrades made each individual proof cheap to verify, fast pairing math, batched scalar multiplication, optimized verifier code. That's real progress. But none of it changes the slope. A cheaper line that still goes up is still a line that goes up.
Aggregation flattens the line. We take N proofs, prove their validity off-chain inside one outer proof, and the chain only verifies that single outer proof. The on-chain cost is the same whether N is 4 or 4,000. That's the entire OneProof claim, in one sentence.
what the proof proves
Before we can fold many proofs into one, each individual proof has to prove something. A short tour of what each transfer's proof guarantees to the chain — without revealing any of the user's private data.
Every private transfer in OneProof runs through the same small program. That program proves three things about the user's secret data, without revealing the data itself. The aggregator then takes many of these proofs and folds them into one.
a commitment
A commitment is a one-way fingerprint. The user combines their secret values into a short hash cthat nobody can reverse to recover the originals. Only c goes public; the inputs stay with the user.
a membership proof
All published commitments are stored in a shared list (a Merkle tree). When the user later spends, the proof shows that their commitment is somewhere in that list, without revealing which entry. Anyone can verify it; nobody can tell who spent.
a nullifier
A nullifier is a one-time burn marker. It's derived from the same secret that built the commitment, but in a way that doesn't reveal which commitment it came from. Once published, the nullifier prevents the user from spending the same commitment twice.
Where the aggregator fits in.
Each transfer produces one of these proofs. Without aggregation, the chain would have to check every single one. The aggregator is a special proof about other proofs: it confirms that four inner proofs all hold, and produces one new proof that the chain can check in a single transaction. Chain a few aggregators together and you can collapse thousands of transfers into one on-chain verification.
How four proofs become one.
Four user proofs are generated in parallel. They flow into an aggregator that proves all four are valid and produces a single new proof. That one proof is then sent to a Stellar smart contract, which verifies it in a single transaction. The hash at the end is a real testnet receipt anyone can look up.
what's novel here
The cryptography isn't new. The application of it to Stellar is. Three things that, to our knowledge, didn't exist before this build.
first Soroban privacy pool with batch settlement
Privacy pools on EVM chains settle one withdrawal per transaction (Tornado Cash, Privacy Pools). Our oneproof_pool contract verifies an aggregated proof AND dispatches N transfers atomically in one Soroban invocation — only possible because Soroban can hold native assets and run arbitrary verifier logic in the same execution context. EVM would need a verifier call followed by a separate multicall.
deposit + batch-withdraw on testnet →first recursive UltraHonk on Stellar
Recursive proof aggregation has shipped on Ethereum (Aztec, Polygon Hermez). It hadn't been deployed on Stellar before this — the BN254 host functions Stellar shipped in Protocol 25/26 made it possible, and we're the first project to actually use them for recursive Honk verification. The K=4 aggregator contract is at the address above; the bytes match the proof we generated locally.
first measured constant-cost ZK primitive on a Stellar mainnet candidate
Plenty of papers project constant-cost ZK. We measured it: 136K stroops per tx, flat as N grows from 4 to (projected) 1024. All numbers linkable to stellar.expert pages, all contract IDs pinned in bench/results.json, all proofs reproducible from the committed circuits.
what this unlocks
We built #1 already — the privacy pool you just used. The same primitive enables the next five. Fixed on-chain cost changes what's actually buildable: things that were too expensive on a per-user basis become viable the moment the chain's bill stops growing with the user count.
private payments at scale
Today's privacy pools (think Tornado Cash on Ethereum) settle one withdrawal per transaction. With aggregation, a thousand private withdrawals can be bundled and settled in one. Lower fees per user, much larger anonymity sets.
← we built this, deposit + withdraw on testnetlayer-2 patterns on Stellar
Collect hundreds of off-chain state changes, prove the whole batch was valid off-chain, settle the result in one Stellar transaction. Stellar gets an 'L2' pattern (the same trick Ethereum rollups use) without any change to the underlying protocol.
anonymous voting + governance
Thousands of ballots, all private, all verified in one on-chain step. Each voter proves their ballot is valid without revealing how they voted. The aggregator combines everyone's proofs; the chain just checks the one result. Auditable, censorship-resistant, single-tx settlement.
batch-matched DEX
Instead of matching trades one at a time on-chain (which is slow, expensive, and easy to front-run), match a batch of orders off-chain and settle the whole batch in one verified transaction. Cheaper per trade and harder for bots to manipulate.
combining proofs across apps
The aggregator doesn't care which app generated each input proof. A private payment proof, a DEX trade proof, and a governance vote proof can all be bundled and settled together. One transaction, multiple unrelated privacy operations.
any app paying the verification tax
If your bottleneck is 'I have to verify too many proofs on-chain for this to be affordable,' aggregation is the fix. The on-chain cost stops scaling with how many proofs are inside the batch — it's a fixed cost set by the size of the aggregator's own proof.
the numbers
Measured on Stellar testnet. Real transaction hashes, real fees, every value linkable to a stellar.expert page.
what this is, and isn't
Plain about what we built and what we didn't. The point of a demo is to show what works, not to overpromise.
- Real zero-knowledge proofs (UltraHonk + Groth16) over a working privacy-transfer circuit.
- Real on-chain measurements on Stellar testnet, every transaction hash linkable to stellar.expert.
- Recursive aggregation: many proofs collapsed into one, and the on-chain cost stays flat as you scale up.
- Built on audited cryptography libraries (Aztec's Barretenberg, snarkjs). Standard, no homebrew crypto.
- A production-ready privacy app. The demo cohort is small; a real anonymity set needs thousands of users.
- A new cryptographic scheme. We combine well-known, peer-reviewed components.
- On Stellar mainnet yet. Testnet only.
- "Free." Generating proofs off-chain still costs CPU time. What we flatten is the on-chain fee, not the total work.
run it
Five commands, testnet end to end. Run the same proofs we ran, deploy the same contracts, see the same numbers.
git clone <repo> && cd oneproof ./scripts/build.sh ./scripts/deploy.sh ./scripts/bench.sh cd web && pnpm dev
- git clone …download the source · pulls in two pinned helper libraries with it
- build.shcompile the zero-knowledge programs and the on-chain contracts
- deploy.shdeploy both verifier contracts to Stellar testnet · prints the new contract IDs
- bench.shrun the measurement sweep (4 proofs, batched + recursive) · writes the numbers shown above
- pnpm devserve this exact page locally at http://localhost:3000