Payer threat model
Spending authority and the reference payer's trust assumptions.
This manual targets 0.1.0-beta.3. Read the source and availability policy before installing. Historical reports retain their original scope.
Security objective
ppops-payer should make one bounded RAILGUN payment requested by a trusted
PPOps merchant without exposing payer spending material or silently changing
the recipient, token, chain, amount, memo or intent.
Gate A is diagnostic. It does not hide the public EVM address that signs and pays gas for submission. Gate B removes that self-signer from submission by using an operator-pinned RAILGUN Waku Broadcaster, but does not provide network-layer anonymity.
Assets
- payer RAILGUN recovery mnemonic and spending authority;
- self-signing EVM private key and its Arbitrum ETH;
- ephemeral shield ownership key when separate funding tooling is used;
- encrypted RAILGUN wallet database and its encryption key;
- payer RAILGUN address, balances, transaction history and private memos;
- merchant signer identity and signed PPOps request;
- Broadcaster fee-signer trust configuration, quote identity and maximum fee;
- reserved transaction nullifiers used to recover an ambiguous submission;
- RPC and PPOI credentials/metadata.
Trust boundaries
local secret files -> payer process -> RAILGUN Wallet SDK/artifacts
-> RPC providers/PPOI nodes
PPOps request URL -> signature verification -> bounded transaction
operator trust file -> Waku fee authorization -> selected Broadcaster
encrypted transaction -> Waku peers/Broadcaster -> Arbitrum
The operator trusts the local host, installed dependency lockfile, independently pinned merchant signer, Arbitrum/RAILGUN contracts and configured external providers. RPC and PPOI services are not assumed confidential or continuously available.
Main threats and controls
| Threat | Control | Residual risk |
|---|---|---|
| Malicious checkout changes recipient or amount | Exact EIP-712 verification against an independently pinned signer; request/descriptor field equality | A compromised trusted merchant signing key can authorize a malicious request |
| Accidental wrong/large/expired payment | Arbitrum/native-USDC pinning, fresh OPEN request, exact intent confirmation, independent maximum atomic amount, and full live-request revalidation after proof generation |
Operator can deliberately confirm the wrong valid intent; mining can still occur after expiry |
| Secret disclosure through arguments/logs | File-only secrets, owner/permission/symlink checks, stable redacted failures, executable privacy check | Compromised host/dependencies can read process memory |
| Incorrect shield-key derivation | Tested fixed-message signature validation followed by keccak256; raw signatures and derived keys are never printed |
Public funding/shielding remains outside the payment harness and links its EVM sender onchain |
| Secret committed to Git | secrets/, config, data and common key extensions ignored |
Manually forcing an ignored file can still publish it |
| Wrong payer wallet imported | Persistent wallet identity plus mandatory expected 0zk address at submission | Operator can copy an already-wrong address instead of checking it out of band |
| Wrong public signer or excessive RPC fee | Mandatory expected EVM address, explicit maximum gas cost and public gas-balance check | A malicious dependency could still alter behavior after checks |
| Malicious/stale Broadcaster quote or excessive token fee | Owner-pinned trusted fee signers, native-USDC quote validation, reliability/lifetime floors, SDK-authorized fee range, explicit atomic fee ceiling and payment + fee balance check; after proof, exact quote is preferred and rotation is accepted only with identical Broadcaster/token/fee rate |
Trusted fee signers, Waku client and selected Broadcaster remain external dependencies; a compatible fee-ID rotation still relies on the Broadcaster retaining that authorized quote |
| Broadcaster redirects the populated call | Local proof/population pins the RAILGUN proxy, zero ETH value, exact recipient/memo/token/amount and pre-transaction PPOI data before encrypted submission | A compromised payer dependency can execute inside the secret-bearing process |
| Scan starts too late and misses funds | Explicit creation block at or before first relevant note | Incorrect operator input can produce an incomplete balance |
| Concurrent payer processes | Owner-only runtime lock spans wallet load, sync, proof generation and submission | A stale lock whose PID was reused can require operator cleanup |
| RPC outage, wrong chain or gas-price outlier | At least two distinct configured origins; 15-second local deadlines; strict healthy majority; upper-median gas selection; explicit fee ceilings; strict identical-receipt quorum | RAILGUN SDK fallback behavior, a high outlier in a two-provider profile and correlated providers remain dependencies |
| PPOI delay/block | Balance buckets are reported; finalize-poi binds proof generation to an exact MINED journal record and requires node acknowledgement; PPOps requires receiver Spendable |
External list policy and node availability are outside the harness; chain mining does not imply PPOI completion |
| Transaction response lost after submission | The raw transaction is signed locally; its hash and nonce are persisted before broadcast, reuse is blocked, and receipt state advances through SUBMITTED, MINED or REVERTED |
RPC/receipt failure still requires resolving the recorded public hash before any new intent is paid |
| Broadcaster lies about, rejects or loses the response after Waku submission | Intent, payer, exact quote, bounded fee and nullifiers are persisted before Waku; the returned hash remains only a report; recovery first derives canonical identity from those nullifiers; a strict RPC majority must agree on receipts. An explicit ambiguity retry must preserve the signed request, payer and complete nullifier set, exclude every attempted Broadcaster identity and stay within a three-retry cap. Any unresolved nullifier is barred from a different intent | The reservation can remain unresolved indefinitely after the cap; distinct 0zk identities need not be independent operators; a compromised full-wallet SDK could misderive identity; the operator must not delete or bypass the journal to force a fresh spend |
| Public sender correlation | Explicit Gate A warning and separate Gate B path | Inherent to Gate A self-signing; Gate B demonstrates submission without a payer EVM self-signer |
| Network metadata correlation | Broadcaster transaction content is encrypted, but RPC, PPOI, artifact, DNS/Waku and Broadcaster connections originate from the payer host | No Tor/mixnet guarantee; timing and IP-layer analysis remain possible |
| Supply-chain compromise | Exact dependency lockfile, build/tests, audit gate | Official RAILGUN tree retains low/moderate legacy transitive findings and downloaded proving artifacts remain trusted inputs |
Explicit non-goals
- protecting secrets on a compromised payer host;
- anonymous network access to RPC, PPOI, artifact or Waku services;
- hiding Gate A’s public self-signing EVM address;
- hiding payer host network metadata or proving resistance to timing analysis;
- key recovery, hardware-wallet custody or multi-user wallet management;
- bypassing RAILGUN PPOI/standby rules;
- guaranteeing merchant fulfillment after PPOps reconciliation.
Operational rules
- Never place payer spending material on the PPOps merchant host.
- Keep runtime config, secrets, LevelDB and evidence outside public artifacts.
- Back up the recovery mnemonic independently; the encrypted local database is a cache, not the sole wallet backup.
- Use a fresh intent and verify the expected signer immediately before payment.
- Treat the self-signed path as Gate A evidence only; a passing Broadcaster payment can support only the narrower claim that the payer self-signer was not used for submission.
- After mining, finalize PPOI from the existing journal record; never resend the
payment merely because the receiver still reports
MissingExternalPOI. - Review Broadcaster signer rotation independently and preserve the local trust fingerprint. Never fetch mutable trust configuration inside a payment.
- Treat
reportedTransactionHashas diagnostic metadata only. Continue recovery untilcanonicalTransactionHashResolvedis true; never inspect the reported hash and infer that payment succeeded. - After an ambiguous Gate B response, run
recover-broadcasterbefore any retry. Useretry-broadcasteronly when the command reports it available; it regenerates a conflicting variant for the exact same nullifiers and excludes identities already attempted. - Never pay a different intent with nullifiers held by a nonterminal Broadcaster journal record. The journal enforces this locally; do not delete or edit it to bypass the check.
- After three retry reservations, stop. There is no timeout after which an unknown external submission becomes safe to ignore; resolve it manually or obtain definitive rejection/reversion evidence before releasing the notes.