Privara is a privacy-aware payment protocol for SIP-010 assets on Stacks.
The present goal is intentionally narrow: allow someone to receive a payment without exposing their normal Stacks wallet as the onchain settlement destination.
A sender can still pay using the recipient’s normal Stacks address. Privara resolves that recipient’s registered privacy keys and derives a fresh one-time address for the actual payment.
The deployed system is live on Stacks mainnet and currently supports sBTC.
Why Privara?
Suppose Alice regularly pays Bob in sBTC.
Without Privara:
Alice → Bob's known wallet
Alice → Bob's known wallet
Alice → Bob's known wallet
Anyone inspecting the chain can trivially associate those payments with the same recipient.
With Privara:
Alice → fresh address S1
Alice → fresh address S2
Alice → fresh address S3
Bob controls all three addresses, but his normal wallet is never used as the settlement destination.
The sender still knows they are paying Bob. The blockchain still exposes amounts and transaction timing. Privara M2 is specifically about reducing recipient-address linkage at settlement, not providing full transaction anonymity.
How it works
1. The recipient creates a Privara privacy identity
The recipient generates an independent random privacy seed locally.
From that seed, Privara derives two secp256k1 keypairs:
- a spending keypair
p / P - a viewing keypair
v / V
Only the public keys P and V are registered onchain against the recipient’s normal Stacks address.
The privacy seed and private keys never go to the registry, relayer, or indexer.
Privara requires the recipient to export an encrypted backup and successfully verify recovery before enabling registration.
The connected Leather or Xverse wallet authorizes the registration transaction, but the wallet signature is not used as the recovery root for stealth funds.
2. The sender derives a fresh one-time address
When Alice enters Bob’s normal Stacks address, the SDK retrieves Bob’s registered P and V.
Alice generates fresh randomness r and computes:
R = rG
Q = rV
h = HashToScalar(Q)
P' = P + hG
P' corresponds to a fresh Stacks principal S.
Alice can derive S using Bob’s public keys, but only Bob can recover its corresponding private key.
Bob later computes the same shared point using:
Q = vR
p' = p + h mod n
which gives him the one-time private key controlling S.
The implementation tests the core invariant:
address(P + hG) == address((p + h)G)
and verifies that the recovered one-time private key can actually sign a valid Stacks transaction from the derived address.
3. Privara creates an encrypted announcement
The sender also creates an encrypted announcement containing the information Bob needs to identify the payment.
The announcement is encrypted using the stealth key agreement.
Privara then hashes the canonical announcement:
announcement
↓
H(announcement)
↓
announcementHash
That hash is included directly in the payment intent Alice signs.
This is an announcement commitment. It binds Alice’s authorization to the exact encrypted announcement that must accompany settlement.
The relayer cannot replace the announcement or redirect the payment without invalidating what Alice signed.
4. Alice signs a SIP-018 payment intent
The M2 intent contains fields including:
asset
amount
fresh stealth recipient
relayer
relayer fee
random nonce
expiry
announcement hash
The exact router deployment, chain ID, and protocol version are also bound into the SIP-018 domain.
Alice signs the intent through her normal Stacks wallet.
The relayer can submit the signed payment but cannot rewrite its authorized economic fields.
5. The relayer settles onchain
The M2 router:
- validates the asset
- reconstructs the signed intent digest
- checks expiry
- rejects already-settled digests
- validates the encrypted announcement
- verifies its hash against the signed announcement commitment
- recovers the payer from the signature
- debits the payer’s router balance
- transfers the net SIP-010 amount to the fresh stealth address
- emits the announcement
Settlement and announcement publication happen atomically.
Replay protection
Privara uses a random nonce as an intent uniqueness salt, not as an ordered account counter.
The nonce contributes to the signed SIP-018 digest, allowing otherwise-identical payments to produce different authorizations.
After settlement, the router stores the final signed digest in settled-intents.
Submitting the same intent again therefore returns ERR_INTENT_USED.
So M2 replay protection is based on consumed signed digests, not a shielded-note nullifier construction.
How Bob discovers the payment
The public announcement can be indexed because it contains no recipient private material.
Bob’s browser retrieves candidate announcements and scans them locally using his viewing key.
For each candidate, Privara determines whether the announcement produces a one-time address controlled by Bob.
If it does, Bob derives the corresponding one-time spending key locally and the payment appears as a spendable private balance.
The indexer never needs Bob’s:
- privacy seed
- viewing private key
- spending private key
- derived one-time private key
Spending without STX at the stealth address
Receiving privately would be awkward if Bob then had to fund every one-time address with STX before using it.
Privara therefore supports sponsored spending.
Bob’s one-time key signs the origin transaction locally. A sponsor adds the sponsored authorization and pays the Stacks network fee in STX.
Before signing, Privara shows the exact sponsor quote and binds the approved:
destination
asset
amount
fee recipient
sponsor fee
expected sponsor
into the spend flow.
The sponsor can refuse service, but it cannot silently change the transaction Bob approved.
This lets Bob pay someone directly from a one-time balance without first consolidating it into his normal wallet.
What Privara protects
The main M2 privacy property is:
The recipient’s long-term Stacks wallet is not exposed as the settlement destination.
Each payment instead settles to a fresh address controlled by that recipient.
Privara does not currently hide:
- payment amounts
- payer identity from full-chain analysis
- transaction timing
- relayer activity
- balances at one-time addresses
- network or API metadata
- transaction relationships created by later spending
The sender also obviously knows who they intended to pay.
And if a recipient later sends funds directly from a stealth address to a publicly known personal wallet, that action may recreate the link Privara originally avoided.
This is why recipient privacy does not end at receipt. Spending behavior matters too.
Recovery model
Stealth balances are controlled by the Privara privacy seed, not the connected wallet.
That means recovering Leather, Xverse, or a hardware wallet does not automatically recover Privara balances.
The M2 application therefore treats backup as part of account creation rather than an optional afterthought:
create privacy identity
→ export encrypted backup
→ successfully restore/verify backup
→ register P/V
→ enable private receiving
A restored backup deterministically reproduces the same viewing and spending keys, allowing previously received payments to be rediscovered and spent.
DAO and contributor payouts
Privara also supports payout-style use cases.
A treasury can pay multiple registered contributors while giving each contributor a fresh settlement address:
Treasury
├──→ contributor A's fresh address
├──→ contributor B's fresh address
└──→ contributor C's fresh address
The current mainnet acceptance includes a contributor payout flow where two independently authorized payments settled to two separate one-time addresses.
Mainnet status
Privara M2 is live on Stacks mainnet using official sBTC.
The current acceptance evidence includes:
- 25 confirmed end-to-end mainnet intents
- 6 distinct participating mainnet wallets
- 4 non-team wallets
- 1 contributor payout flow
- independently reproduced mainnet usage
- successful sponsored withdrawals from derived one-time addresses
- 151 automated tests across 22 test files
The test surface includes SIP-018 serialization and digest parity, replay protection, stealth derivation, recipient isolation, backup/recovery, malformed-announcement handling, relayer behavior, sponsor-fee approval binding, and sponsored spending.
Architecture
At a high level:
Bob
│
├─ creates independent privacy seed
├─ derives P / V
└─ registers P / V
│
▼
Alice enters Bob's normal address
│
▼
SDK fetches P / V
│
▼
derive fresh stealth address S
│
├─ encrypt announcement
├─ hash announcement
└─ include hash in M2 intent
│
▼
Alice signs SIP-018
│
▼
relayer
│
▼
M2 router settles
│
┌─────────┴──────────┐
▼ ▼
sBTC → S announcement emitted
│
▼
Bob scans locally
│
▼
derives p'
│
▼
sponsored/private spend
What comes next
M2 deliberately focuses on recipient-side privacy rather than claiming to solve every privacy problem at once.
Some directions I’m exploring next include:
Stronger payer-side privacy
The current SIP-018 signature remains publicly recoverable, so M2 does not provide payer anonymity.
A future version may explore commitment/nullifier-based state together with zero-knowledge proofs, where private payment state can be consumed without exposing the same authorization structure used today.
That is a future protocol direction, not part of the deployed M2 architecture.
Better private exits
One important UX problem is what happens after receiving privately.
Sending straight back to a known wallet can recreate an onchain identity link.
I’m exploring safer exit flows such as direct spending, fresh destinations, and sBTC-to-BTC withdrawal paths that could eventually allow users to exit directly to supported Bitcoin wallets or exchanges without first routing funds through their known Stacks wallet.
Payment notifications
Today recipients discover payments by scanning public announcements locally.
A future notification layer could alert users that new Privara activity is available while preserving local ownership detection, so the server does not need access to viewing keys or learn which announcement belongs to which recipient.
Broader wallet and protocol integration
The stealth construction and deterministic interoperability vector are exposed through the TypeScript SDK so other applications and wallets can integrate the same recipient-routing model without reimplementing the cryptography from scratch.
Try Privara
Live app:
https://privara-sbtc.vercel.app/