Technical docs
Privacy
Privacy payments
Operational vs cryptographic privacy, current PoolManager stack, Nethermind reference, and migration plan for opt-in ZK settlement.
Overview
Hypertron ships an opt-in private settlement path for B2B payment links. Merchants can offer checkout where the payer’s wallet is hidden from the business, and funds are tracked via commitments and nullifiers on a Soroban PoolManager contract. This page explains what that gives you today, what real cryptographic privacy looks like on Stellar, and how we plan to migrate from our Phase 1 stack to a full zero-knowledge pool.
NEXT_PUBLIC_POOLMANAGER_CONTRACT_ID is set (or NEXT_PUBLIC_ENABLE_PRIVATE_SETTLEMENT=true). It targets Stellar testnet only and is not audited.Real vs operational privacy
Not all “private payments” are equal. Hypertron Phase 1 and a full ZK privacy pool solve different problems.
| Guarantee | Phase 1 (Hypertron today) | ZK pool (Nethermind target) |
|---|---|---|
| Hide payer from merchant | Yes — relayer + hash memo + UI | Yes — shielded UTXO inside pool |
| Hide payer from chain analyst | No — payer → relayer → pool is traceable | Yes — ZK proofs break on-chain links |
| Hide amount | No — visible on Horizon payment | Yes — inside pool |
| Unlinkable withdrawal | No — direct pool → recipient payout | Yes — nullifier spend via ZK proof |
| Server cannot spend user funds | No — server derives secrets, signs commits | Yes — client holds note keys |
| Trust model | Trust Hypertron backend + pool operator | Trustless on-chain verification |
Operational privacy (Phase 1) is appropriate for “the merchant shouldn’t see who paid.” Cryptographic privacy (Phase 2) is required for unlinkable, trustless settlement — the standard set by Nethermind’s reference implementation.
- Phase 1 solves a real merchant problem.
- Phase 2 adds cryptographic privacy via Nethermind’s stack.
Nethermind reference implementation
The Stellar Privacy Engineering team at Nethermind maintains the canonical open-source privacy pool for Soroban. It is the intended upgrade path for Hypertron’s ZK layer and is explicitly referenced in our PoolManager source.
- Repository: github.com/NethermindEth/stellar-private-payments ↗
- Live demo: nethermindeth.github.io/stellar-private-payments ↗
- Stack: Circom circuits, Groth16 proofs (browser WASM), Pool + CircomGroth16Verifier + ASP Membership + ASP Non-Membership Soroban contracts
- Model: 2-in / 2-out UTXO transactions — deposit, private transfer, and withdraw inside the pool with balance conservation proved in zero knowledge
- Compliance: Association Set Provider (ASP) membership and non-membership Merkle proofs enforced inside the circuit
- Status: Work in progress, not audited — same caution as Hypertron testnet beta
Current architecture (Phase 1)
Phase 1 splits settlement across classic Horizon payments (fund custody) and a Soroban commitment registry (double-spend bookkeeping). Privacy is achieved at the application layer, not inside a shielded pool.
POST prepare-pay → SHA-256 memo hash
PendingPaymentMemo in DB
Yes
Payer → relayer (hash memo)
Relayer → pool G-address (same memo)
No
Payer → pool / vault (hash memo)
Horizon match + attribution
status poll / relayer inbox
Server derives secret + nullifier
hashToScalar(payer, businessId, amount)
PoolManager.commit (Soroban)
Poseidon leaf + nullifier reg
Virtual balance updated (Prisma)
Key components in the repo:
| Layer | Files / contracts | Role |
|---|---|---|
| Checkout UX | pay/[id], privacy-features.ts | Opt-in toggle, prepare-pay, Freighter signing |
| Hash memo | prepare-pay | One-time opaque memo; no link id on chain |
| Relayer | relayer.ts | Hide payer from pool observer; forward to pool |
| Attribution | status/route.ts | Horizon match → commit → update PaymentLink |
| Soroban client | soroban-commit-server.ts, soroban-poolmanager.ts | Server-side commit / withdraw invocations |
| PoolManager (PoC) | contracts/poolmanager | Poseidon leaf, nullifier registry, ASP approve/block, stub ZK verifier |
| Virtual balance | virtual-balance.ts | Off-chain ledger of unspent nullifiers per business |
| Withdrawal | /api/withdraw, payout-server.ts | Mark nullifiers on Soroban + Horizon payout from pool account |
depositor and amount on chain, uses a rolling Poseidon accumulator (not a Merkle tree), and verify_proof_stub accepts any non-empty proof. These are intentional PoC shortcuts — not production privacy guarantees.Where we are today
Opt-in private settlement on payment links (testnet beta)
Hash-memo dark pool (prepare-pay + PendingPaymentMemo)
Relayer: payer hidden from merchant / pool memo match
Fee sponsorship (CAP-40) on private checkout
PoolManager commit + nullifier registry on Soroban testnet
PoC contract; SDK call shape may lag contract ABI
Virtual balance + /api/withdraw treasury flow
Groth16 on-chain proof verification
Client-side WASM prover (Circom)
Merkle commitment tree + membership proofs
Single shielded pool custody (no split Horizon + Soroban)
Privacy relay (multi-hop ephemeral wallets)
Described in README; not implemented — superseded by ZK path for real unlinkability
Security audit before mainnet
Target architecture (Phase 2)
Phase 2 keeps Hypertron as the product layer and swaps the settlement engine for Nethermind’s shielded pool when the customer opts in. Standard checkout (direct vault payment) stays unchanged.
Browser loads WASM prover
Nethermind circuit artifacts
Client generates deposit proof + note
User holds secrets
Pool.transact(proof, ext_data)
Tokens locked in pool contract
Hypertron indexes pool events
Update merchant virtual balance
Nethermind contracts to deploy alongside (or instead of) stub PoolManager:
| Contract | Purpose |
|---|---|
| Pool | Merkle UTXO pool — transact (deposit / transfer / withdraw) |
| CircomGroth16Verifier | On-chain Groth16 proof verification (BN254) |
| ASPMembership | Merkle tree of approved note public keys |
| ASPNonMembership | Sparse Merkle exclusion list |
What Hypertron keeps vs replaces:
| Keep (Hypertron) | Replace / embed (Nethermind) |
|---|---|
| Payment links, /pay checkout, fee sponsorship | PoolManager stub → Pool + Verifier |
| Business vaults, treasury UX, virtual balance display | Server hashToScalar secrets → client UTXO notes |
| Relayer (optional pre-pool obfuscation) | Horizon-only custody → in-contract token lock |
| KYB / compliance dashboard | Inline approve/block maps → ASP Merkle + circuit proofs |
| Prisma attribution (link id ↔ payment) | Event sync from pool NewCommitment / NewNullifier events |
Migration plan
Migration is phased so merchants can ship confidential checkout now while ZK settlement is integrated without breaking standard payments.
Phase 1 — Shipped (operational privacy)
- Hash-memo + relayer + PoolManager PoC commits
- Market honestly as “payer hidden from merchant” — not ZK-shielded
- Fix contract ↔ SDK ABI alignment if continuing PoC commits on testnet
Phase 2 — Nethermind integration (real privacy)
- Deploy Nethermind contracts to testnet using their
deployments/scripts/deploy.sh(pool levels, ASP levels, verification key) - Bundle Circom WASM prover + circuit keys in the private checkout path only
- Replace executeCommit with client-side Pool.transact() deposit flow
- Replace sendPayout + stub withdraw with ZK withdraw transact from pool
- Sync virtual balances from pool contract events (replace server-derived nullifier tracking where possible)
- Wire KYB-approved businesses into ASP membership tree (admin UI or CLI)
Phase 3 — Production hardening
- Joint or independent security audit (Hypertron BFF + Nethermind pool path)
- Trusted setup / verification key governance documented for deployers
- Mainnet deploy only after Protocol 25 X-Ray verifier is stable on public network
- Deprecate stub PoolManager; migrate open nullifiers or sunset testnet pool
- 1Pay pagePay page
User chooses Standard vs Private (ZK)
- 2Pay pagePhase 1 path
Standard → Horizon payment to vault/pool G-address
- 3Pay pageNethermind Pool
Private (ZK) → WASM proof + transact deposit
- 4Phase 1 pathHypertron API
Memo match + optional commit
- 5Nethermind PoolHypertron API
Pool events → virtual balance
- 6Hypertron APIMerchant
Dashboard: Paid ✓
Opt-in dual-mode checkout
The product goal is a single payment link with two modes — defaulting to standard (simple, auditable) and offering private settlement as an explicit opt-in:
| Mode | User experience | Privacy level | Backend |
|---|---|---|---|
| Standard | Pay vault / pool directly; text or fixed memo | Public on-chain payment | Current Hypertron Horizon flow |
| Confidential (Phase 1) | Hash memo; optional relayer; payer hidden from merchant | Operational | relayer.ts + PoolManager PoC + virtual balance |
| Private / ZK (Phase 2) | Freighter signs ZK deposit; note stored client-side | Cryptographic | Nethermind Pool + WASM prover + ASP |
Environment flags today: NEXT_PUBLIC_ENABLE_PRIVATE_SETTLEMENT, NEXT_PUBLIC_POOLMANAGER_CONTRACT_ID, NEXT_PUBLIC_RELAYER_PUBLIC_KEY / RELAYER_SECRET_KEY, SOROBAN_COMMIT_SOURCE_SECRET. Phase 2 adds Nethermind contract IDs, circuit key paths, and prover bundle config (TBD).