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.

1 · DEPOSIT

Payer escrows the whitelisted SIP-010 asset in the router.

2 · INTENT

SDK creates the payment tuple with nonce and expiry.

3 · SIGN

Wallet signs a router- and chain-bound SIP-018 digest.

4 · RELAY

Relayer broadcasts the signed settlement call.

5 · VERIFY

Router recovers signer, checks replay, expiry, and balance.

6 · MOVE

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.

\operatorname{digest}=\operatorname{SHA256}\!\left(\text{\"SIP018\"}\;\Vert\;\operatorname{domainHash}\;\Vert\;\operatorname{intentHash}\right)
domainHash binds name, version, chain-id, and router principal; intentHash binds the payment terms.
The signed economic fieldsclarity
{
  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.

Recover-based authorizationclarity
(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

06 · Asset safety

A relayer should not imply unlimited contract authority

Each router deployment whitelists one asset. Deposits reject anything else so a user cannot accidentally trap an unsupported token. During settlement, the contract updates replay and balance state before external transfers, then enters an as-contract? block with a with-ft allowance bounded to that asset and the exact total amount.

The recipient and relayer are caller-provided arguments, but they are also covered by the signed intent. The relayer cannot replace either address or change the fee without invalidating signer recovery against the rebuilt digest.

The allowance contains the blast radius of a contract-initiated transfer. Even if the surrounding execution path is wrong, it cannot move another token or more than the authorized amount through that guarded block.

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.