01 · Threat model
Begin by narrowing the privacy claim
A normal SIP-010 transfer places a direct, sender-submitted payment edge on-chain. Privara changes the execution shape: the payer deposits into a router, signs an instruction off-chain, and a relayer submits the settlement. This separates authorization from transaction submission and removes the long-term wallet from the settlement transaction's tx-sender field.
That is metadata reduction, not transaction secrecy. The initial deposit links the payer to the router. The settlement exposes amount, recipient, relayer, fee, expiry, and the recoverable signature. Because the contract itself recovers the payer from that signature, an observer can perform the same recovery. Timing and amounts can also correlate deposits with settlements.
The protocol can still be useful for payment hygiene and fresh-address workflows, but only if those limits are part of the product. Calling this fully private would be technically false and would lead integrators to make unsafe assumptions.
02 · Architecture
Authorization happens off-chain; enforcement happens in Clarity
The user first deposits the router's whitelisted SIP-010 asset. They then construct an intent containing the asset, amount, recipient, relayer, relayer fee, random nonce, and expiry. The SDK serializes that tuple using Stacks consensus encoding and signs the SIP-018 digest.
The relayer submits those fields and the 65-byte RSV signature. The router rebuilds the digest, rejects expired or previously consumed intents, recovers the signer's principal, checks the recovered user's deposit, debits internal accounting, and moves the exact authorized amount.
Payer escrows the whitelisted SIP-010 asset in the router.
SDK creates the payment tuple with nonce and expiry.
Wallet signs a router- and chain-bound SIP-018 digest.
Relayer broadcasts the signed settlement call.
Router recovers signer, checks replay, expiry, and balance.
Scoped contract authority pays recipient and optional fee.
03 · Domain separation
The signature is bound to the chain and exact router deployment
The structured data hash covers every economic field. The SIP-018 domain covers the protocol name, version, chain ID, and router principal. Including chain ID blocks testnet-to-mainnet replay. Including the full router principal blocks reuse against a different deployer or a replacement router with the same contract name.
The SDK and contract each implement the digest independently. A parity test compares hashIntent, domainHash, and messageDigest byte for byte. That test is essential: a different tuple order or serialization rule does not produce a slightly different signature - it produces a signature the contract can never authorize.
{
asset: asset,
amount: amount,
recipient: recipient,
relayer: relayer,
relayer-fee: relayer-fee,
nonce: nonce,
expiry: expiry
}04 · Authorization
Recover the payer instead of trusting a supplied public key
A Stacks principal is derived from a public-key hash, so a relayer cannot derive the public key from the address alone. Asking the caller to provide both a principal and a public key creates an extra consistency check and an opportunity for integration mistakes. Privara uses secp256k1-recover? followed by principal-of? to recover the authorizing principal directly from the signed digest.
The recovered principal becomes the key for deposit and settlement accounting. The user address is absent from the settlement arguments, but it is not secret: anyone with the public signature and digest can recover it. This is an authorization simplification, not a privacy primitive.
A malformed signature can recover a well-formed stranger principal. The contract distinguishes that case with ERR_NO_DEPOSIT, while a known depositor with insufficient funds receives ERR_INSUFFICIENT_FUNDS. That separation improves debugging without weakening the authorization rule.
(let (
(pubkey (unwrap! (secp256k1-recover? digest user-sig) ERR_INVALID_SIG))
(user (unwrap! (principal-of? pubkey) ERR_INVALID_SIG))
(balance (get-deposit user asset-contract))
)
(asserts! (> balance u0) ERR_NO_DEPOSIT)
(asserts! (>= balance amount) ERR_INSUFFICIENT_FUNDS)
;; settle from recovered user's deposit
)05 · State machine
Random nonces remove head-of-line blocking - but retries become dangerous
Privara uses an unordered random 64-bit nonce as a uniqueness salt. Replay protection is keyed by the full digest, not a monotonically increasing user counter. This lets independent intents settle in any order and avoids an old, delayed intent blocking every later payment.
The trade-off appears when a payment is retried. Reissuing with a new nonce creates a second valid authorization; it does not revoke the first. If both remain funded, either - or both - can settle. The safe sequence is to cancel the original, wait until cancellation confirms as successful, and only then issue the replacement.
Cancellation itself is best-effort. A relayer can race the cancel transaction and settle first. Short expiries and withdrawal are therefore stronger safety tools than assuming a broadcast cancellation has already taken effect.
- Random nonce: no chain read and no sequential queue
- Per-digest replay map: one digest can settle or cancel once
- Reissue: creates another live intent until the original is confirmed cancelled
- Cancellation: a transaction race, not an off-chain revocation guarantee
07 · Status
What exists now, and what stronger privacy would require
The current core has 41 passing Clarinet/Vitest tests across five clean contracts. Contract and SDK digest parity is tested, and the complete mock-token flow has run on testnet: relayer registration, mint, deposit, settlement, replay rejection, and expiry rejection. Real sBTC and USDC execution still depends on funded test assets.
Stronger privacy needs a different cryptographic construction: private membership proofs, nullifiers, hidden-note commitments, or another mechanism that proves authorization without publishing a recoverable link to the depositor. That is closer to a shielded pool than an intent router and should not be smuggled into the v1 claim.
The next protocol work should bind wallet UX to the exact structured fields, model relayer observation explicitly, test adversarial cancellation races, and decide whether the deposit-to-signer link is acceptable for each proposed integration. The honest threat model is not a disclaimer attached after the design; it determines whether the design solves the user's actual problem.