oneproof→ console
Private payments on Stellar · testnet · live

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.

on-chain cost · stroops
N = 64
272.0 K544.0 K816.1 K1.09 M1642565121024N · NUMBER OF PRIVATE OPERATIONS
↔ drag to change NN = 64
naive · N txs
1.96 M
batched · 1 tx
482.4 K
recursive · 1 tx
136.0 K

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.

scroll for the wall · the proof · the pipeline · the receipts
01

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.

naive · cost vs N · stellar testnet30,556 stroops × N
N = 130.6 K stroops · 1 tx
N = 4122.2 K stroops · 4 tx
N = 641.96 M stroops · 64 tx
N = 1,02431.29 M stroops · 1024 tx
off the chart →
Every proof is its own transaction. Past N = 64 you've burned ~2 million stroops just on verification — and you've sent 64 separate transactions to do it. Aggregation collapses all of them into one.
02

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.

i

a commitment

c = hash(secret, amount, blinding)

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.

ii

a membership proof

prove c is one of the published commitments

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.

iii

a nullifier

nf = hash(secret, leafIndex)

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.

example values · from our demo proof
secret7
private · the user's seed
amount1000
private · what they're transferring
blinding42
private · random padding to prevent guessing
c0x1cdce02c…22cbf
commitment · the one-way hash of the three above
root0x1cdce02c…22cbf
public · the shared list stored on-chain
nf0x1e95b928…29d3
public · the one-time burn marker
Only root and nf are visible to the chain. Secret, amount, and blinding never leave the user's machine; the proof attests they were used correctly without ever exposing them.

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.

03 · pipeline · twelve seconds, scroll to scrub

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.

pipeline · loading composition…
04

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.

i

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 →
ii

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.

iii

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.

05

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.

i

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 testnet
≈ 136,009 stroops
for a 1024-user batch · vs ~31M naive
ii

layer-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.

N updates · 1 verify
cost amortized across the batch
iii

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.

1 tx · N voters
proof of valid tally · votes stay private
iv

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.

1 tx · any N orders
batch-priced, front-running resistant
v

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.

K apps · 1 verify
cross-application composition
vi

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.

flat in N
that's the whole product
06

the numbers

Measured on Stellar testnet. Real transaction hashes, real fees, every value linkable to a stellar.expert page.

crossover N
≈ 5
where recursive beats naive
recursive · 1 tx
136,009
stroops, flat in N
naive · 4 txs
122,224
stroops, linear in N
savings at scale · projected from measured per-tx costrecursive · flat at 136,009 stroops
N = 1single proof30.6 K stroops · 1 txloses by 4.5×
N = 4measured today122.2 K stroops · 4 txloses by 1.1×
N = 16small batch · K=16 projected488.9 K stroops · 16 tx3.5× cheaper
N = 64moderate · linearly projected1.96 M stroops · 64 tx14.1× cheaper
N = 256high-throughput · projected7.82 M stroops · 256 tx56.5× cheaper
N = 1,024rollup-scale · projected31.29 M stroops · 1024 tx226× cheaper
contacting
connecting to stellar.expert…
07

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.

what it is
  • 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.
what it isn't
  • 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.
08

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
oneproof · stellar hackathon · testnetv0.1 · 2026