• Private: the asset, amount, recipient, and memo of an internal transfer stay encrypted. Public: money moving in or out, the submitting account, its network fee, and timing.
  • Proofs are created on this device. There is no StellarKey backend, operated relay, indexer, or hosted key service; payments submit directly through your selected Stellar RPC.
  • One live Testnet development pool for XLM and USDC, validated by deployment and registry evidence. It is not safe for real value; Mainnet remains blocked.

What it is

Private Payments is a shielded pool for configured XLM and USDC, driven from the wallet you already have. Funds you move into it are held as encrypted notes on this device and can change hands without publishing the amount, the recipient, or the memo; a zero-knowledge proof convinces a contract on the public Stellar ledger that every rule held, without showing it the contents. That one sentence is the whole promise. The rest of this page is the mechanism.

StellarKey 1.0.4 is the current application release, continuing the stable 1.0.0 application baseline. That application version is separate from Private Payments Protocol V2 and its unaudited Testnet-only status. One live, hash-pinned development pool on Testnet has XLM at registry index 0 and USDC at index 1. The pool started from fresh state on September 13, 2026. Only current deployment-bound notes, addresses, proofs and encrypted backups are supported; unsupported records are rejected without being rewritten.

Public reads on September 13, 2026 through SDF and Ankr corroborated the deployed executable hash. A separate synthetic XLM deposit, self-transfer and full-input exit confirmed on Testnet, with canonical archive rescans after each action. This was not a browser-wallet or USDC test, did not saturate the live tree, and is not an independent security audit. The deployment fixture still does not record a deployment transaction hash.

The single-party key passes circuit/Powers-of-Tau compatibility verification, but anyone retaining its setup secret could forge proofs. Mainnet is refused independently. A public multi-party Phase 2 ceremony, independent circuit and contract review, broader payment and recovery evidence, and human/physical-device checks remain required before real-value use. The maintained whitepaper records the artifact identities, dated evidence and remaining limits.

One wallet, two pockets

Your Stellar account is a public pocket: anyone can look up its balance and history, and that openness is what makes the ledger checkable. The private balance is a second pocket beside it. Crossings between the two — deposits in, withdrawals out — are ordinary public transactions by design; only life inside the pocket is encrypted.

Pocket flow: adding funds moves them from the public account into the private balance and is public. Sending and receiving inside the private balance is encrypted. Withdrawing moves funds back out to any Stellar address and is public again.public accountbalances anyone can look upadd · publicamount and source visibleprivate balanceencrypted records on this devicesend privatelyreceive privatelyamount · recipient · memo: encryptedwithdraw · publicamount and recipient visibleany Stellar addressa public payment like any otherpublic by designencrypted

every crossing is public · everything inside is encrypted

What is private, what is public

The whole deal, in one table. If a fact is not marked encrypted here, assume the world can see it.

factwho can read it
asset of a private transferHidden. Internal transfers publish neither the asset contract nor its registry index.
amount of a private transferEncrypted. The sender and the recipient.
recipient of a private transferEncrypted. The sender and the recipient.
private memoEncrypted. Up to 32 bytes; sent-memo recovery depends on the outgoing-recovery choice when the payment was built.
which notes were spentEncrypted. The ledger stores commitments and ciphertext; spend selection stays on the device.
money moving in or outPublic. Deposits and withdrawals reveal the asset, amount, public endpoint and timing.
the transaction source and feePublic. Choosing another wallet account as fee payer changes who pays XLM; it does not hide either account.
timing and activityPublic. When the shared pool was used, and how often, is visible to anyone.
What leaves the device: keys and private-transfer plaintext stay on the device; encrypted recovery records are published. The public ledger sees a contract interaction, the fee account and its fee, timing, deposits and withdrawals with amounts, and an encrypted package it cannot open. The proof is public and verifiable without revealing its private witness.stays on this device· your keys· amounts and recipients· private memos· the proof's inputs· decrypted payment historythe proofcheckable by the contractdoes not reveal the witnessthe public ledger sees· a contract interaction· the transaction source and fee· timing· deposits and withdrawals, with amounts· an encrypted package it cannot open

How a private payment works

The private balance is a set of notes — think unspent banknotes rather than an account balance. A note is a 128-byte record carrying a 63-bit value, its owner, a random seed, and an optional 32-byte memo. The vocabulary, defined once and used throughout:

commitment
A Poseidon2 hash of a note (BN254, width 4, domain-tagged). The ledger stores the hash; the note itself never appears on-chain.
Merkle tree
The pool's ternary depth-64 tree has room for 364 commitments. Positions and archive counters use exact 128-bit integers. Owning a note means being able to prove a private path from its commitment to a recent root, without identifying its leaf.
nullifier
A second domain-tagged Poseidon2 hash, derivable only by a note's owner and revealed exactly once, when the note is spent. The contract keeps every nullifier it has seen; a repeat is a double-spend and is refused. The nullifier cannot be linked back to its commitment by an observer.
Groth16
The proof system: a succinct zero-knowledge proof over the BN254 pairing curve. It proves the statement without revealing its private witness; public inputs and transaction metadata remain visible.
recipient envelope
A 181-byte HPKE ciphertext (RFC 9180: X25519 key agreement, HKDF-SHA256, AES-128-GCM) that carries the new note to its owner. Only the matching viewing key can open it.

Each proof has two input lanes, three output lanes, and a public value leg that is zero for a private transfer. Recipient, change and randomized dummy notes occupy fixed 370-byte output packages. Payments submit directly; there is no peer-fee route. A full-input exit uses the same proof shape without inserting its zero-value dummy outputs.

  1. The wallet selects the notes to spend. The proof anchors to any pool root from the last 1,440 ledgers, roughly the last two hours, so the transaction does not reveal how fresh your notes are.
  2. An isolated worker builds the Groth16 proof on this device: the spent notes sit in the tree under the anchor root, the nullifiers are correctly derived, one private asset is conserved, and all three output commitments are well-formed. The circuit is 40,594 constraints with 11 public inputs, and no private proof witness is uploaded.
  3. You explicitly authorize proof sharing, review the exact transaction and fees, and approve signing. Direct submission uses your own public Stellar account; another software account in this wallet may pay the network fee. The pool checks the nullifiers and records the encrypted packages. A normal private transfer appends three commitments; a full-input exit does not. RPC acceptance and timeout are not ledger confirmation.
  4. The recipient's wallet scans the pool's public record and trial-decrypts each envelope with its incoming viewing key. The one addressed to them opens; the rest are noise. There is no notification service, because a notification service would have to know.
The send pipeline in four steps: the wallet chooses up to two notes to spend and creates three outputs, an isolated worker builds a Groth16 proof over BN254 on the device, the pool contract on Stellar verifies the proof and the nullifiers without learning the contents, and the recipient discovers the payment by trial-decrypting the output envelopes with their viewing key.01 · choosepicks notes to spend · two in, three outthe selection never leaves this device02 · prove — on this devicebuilds a Groth16 proof over BN25440,594 constraints · witness stays local03 · verify — on Stellarthe contract checks proof and nullifiersit never learns amount, recipient, or memo04 · discovertrial-decrypts the output envelopesonly their viewing key opens theirs

Artifact integrity is checked before use. The public manifest pins the files by SHA-256; its retained URL contains v1, but its protocol version is 2. Hash verification detects a mismatched file; it does not replace review of the software, circuit or setup.

Proof systemGroth16 over BN254 · 40,594 constraints · 11 public inputs
HashingPoseidon2 (BN254, t=4) commitments and nullifiers · ternary depth-64 tree
Proving key17,722,398 bytes point-compressed in persistent cache · 26,308,892 bytes expanded in memory
Witness builder261,555-byte WASM witness builder, verified before use

The manifest records a 7,368,646-byte Brotli-compressed proving-key transfer; actual network transfer size depends on the host's content encoding. The application and service worker share the verified compressed artifact cache, retaining up to two completed revisions. One verified public proving key can be reused in memory; it is not an extra persistent copy. A corrupt cached file is discarded or refetched, and a downloaded file that fails verification cannot be used.

Withdrawals and capacity

A full-input exit withdraws the entire value of its selected one or two notes without appending commitments. It can therefore work even when the commitment tree is full. This is not unlimited capacity or guaranteed withdrawal availability: usable roots, unspent notes, live contract/archive data, token backing and authorization, fees, and network availability still matter. A partial withdrawal that creates change still needs unused commitment capacity.

For balances spread across more notes, the wallet reviews a sequence of withdrawals using disjoint groups of one or two available notes. One approval covers at most 64 steps and 15 minutes, with per-step and cumulative fee limits. Each step must confirm on the ledger before the next is prepared. It is not one atomic aggregate withdrawal: interruption can leave a confirmed prefix, and further work needs a new review when the approval expires. Held notes are excluded from ordinary withdrawal selection.

Receiving privately

A deployment-bound shielded address is 128 characters of Base58 — tskpay_… on Testnet — with deployment binding and a four-byte checksum. Wrong-deployment addresses fail; ordinary mistyping is overwhelmingly likely to fail, although a 32-bit checksum is not a guarantee. It never appears as an account on the public ledger, and there is no on-chain registration step.

Addresses are diversified: from one incoming viewing key, the wallet derives many addresses, one per four-byte diversifier, all spendable by the same wallet. Every envelope in one action publishes the same diversifier, so those bytes do not identify recipient, change or dummy roles. Repeated payments to the same address can still link whole actions on-chain. Separate addresses reduce reuse; they do not remove timing or transaction-source correlation.

Sharing happens out of band, over a channel you already trust. Beside the QR code the wallet shows a short verification code derived from the address — the drawn panel below shows one, FC42 C9CF — and the sender's wallet derives the same code from whatever it is about to pay. Matching codes mean the address survived the copy intact.

The receive screen also offers a reusable stealth address (tsm1…): a separate two-key receiving scheme that derives one-time public Stellar accounts. It is not the shielded pool. Payments to those accounts still expose public amounts and activity; the scan key lets the recipient discover the destinations, while timing and funding links can still correlate them.

What it looks like

The surfaces below illustrate the live Testnet development implementation: the setup disclosure, a shielded receive with its verification code, and a private send review. XLM and USDC are available on Testnet; Mainnet remains unavailable.

private // the deal
Stays encryptedThe amountThe recipientThe memo
Stays publicMoney moving in or outThe network feeThe timing
stated before you turn it on — not in the small print
receive // privateShielded
Shielded address QR code
Verification codeFC42 C9CF
the sender sees the same code before paying
tskpay_ … n8d6
send // private review
ToFC42 C9CF ✓
Amount12 XLM · encrypted
Memoencrypted
Network fee0.4847157 XLM · public
Proofbuilt on this device
Confirm Send

the deal, stated before you turn it on · a shielded receive · a private send review

Recovery

Your recovery phrase rederives deployment-bound viewing keys. On a new device the wallet scans the canonical archive, authenticates the transcript and tree, decrypts owned notes and checks nullifiers against the chain. Recovery requires the matching deployment and its authenticated records.

Archived records may require a separately reviewed, fee-bearing restoration transaction. The wallet restores freshly simulated contiguous batches within its limits, then rescans the confirmed records. Chain acceptance or a timeout is not a successful restoration.

When outgoing recovery is enabled for a payment, seed recovery can reconstruct its recipient fingerprint and memo. When outgoing recovery is disabled for future payments, those outgoing records cannot recover the sent recipient fingerprint or memo. Owned balances and incoming payments still recover, and older recovery-enabled records remain readable. Full reusable recipient addresses and other local convenience metadata require the encrypted backup.

An encrypted backup also preserves pending records and exposed-proof reservations. Seed-only recovery cannot reconstruct an unconfirmed shared proof whose local journal was lost. Sharing a spend proof is authorization: rejecting, cancelling or timing out a transaction does not make its inputs safe to spend again. Keep the encrypted backup and do not retry blindly.

An eligible held payment can use an explicitly approved self-transfer of its reserved inputs to a fresh address in the same wallet. This still needs free commitment slots and does not revoke the original proof. The wallet keeps the inputs held until the recovery, original payment or another conflicting spend is canonically confirmed. It is not instant cancellation, and this recovery control is not a full-input exit for held notes.

What you must trust, and what you must not

A privacy claim is a trust claim. Here is exactly where this one rests.

You must trust

  • Your device and browser. An unlocked wallet on a compromised machine has no defense, this feature included.
  • The pool contract on Stellar. Independent review of the contract and circuit is a release gate for exactly this reason.
  • The mathematics and setup. The current Groth16 Phase 2 key is single-party development material. A future reviewed multi-party ceremony must include an honest participant who destroys their secret contribution; publishing a transcript alone does not establish that.

You must not trust

  • A StellarKey custody or transaction backend. The host serves the static application and public proving files and can observe web request metadata. It does not receive private proof witnesses through this design. Payments go through your selected Stellar RPC, which receives proofs and transactions and can observe your IP address and request timing. You still need to trust the application code delivered to your browser.
  • A hosted prover. Proofs are built on your device; anything else would break the claim they make.
  • Obscurity. What stays public — fees, timing, deposits, withdrawals — is written on this page so you can plan around it.

The bar for any non-development release is written down and enforced in code: a proving key verified against its pinned phase-one transcript, reproducible artifacts, a completed trusted-setup ceremony, independent contract and circuit review, immutable deployment evidence, and recovery drills, all tied to the same hashes. The current development key passes circuit and transcript compatibility checks but has no public ceremony or independent audit evidence. The published XLM/USDC pool is therefore a Testnet development deployment only, and Mainnet stays refused.

The awkward questions

Why is my deposit public?

A deposit moves a public asset from your Stellar account into the pool, so its asset, amount, source and timing remain public. The ledger also records commitments and encrypted output packages, but not the note plaintext. Later private transfers still expose transaction sources and timing, which can support correlation.

What does the fee account reveal?

Every private send is submitted by your public Stellar account. The source account, fee payer, fee and timing remain public even when the internal transfer details are encrypted. Choosing another software account in the wallet to pay the fee does not hide either account.

How private is it, really?

Contextual. A transfer among many transfers made by many independent people is hard to single out; the same transfer in a quiet week, between two accounts that always act within the same minute, invites guessing. Correlation through timing, repeated endpoints, address reuse, or a compromised browser remains possible. Privacy grows with more independent activity. It is context, not a guarantee, and we will not sell it as one.

Why testnet first?

Because the evidence is not finished: the proof parameters need a completed public ceremony and the contract and circuit need independent review, and neither is recorded yet. Until both exist, the preview stays on a network where balances have no monetary value. Preview first, promotion after the evidence — that is an order we can defend.

What if I lose this device?

Use the recovery phrase and an encrypted backup where available. Seed recovery depends on the matching deployment and canonical archive; restoration may cost reviewed network fees. The backup preserves local metadata and pending-proof records that seed-only recovery cannot reproduce. Never share the phrase or backup with support.

Can StellarKey see my private balance?

No — the records are encrypted on your device, the proving happens on your device, and requests go directly to the Stellar RPC endpoint you configured. That endpoint's operator can see your IP address and request timing. The RPC also receives the proof and exact transaction for simulation and submission.