Skip to content
Anon Wallet

Private Paymaster Relay

Anon's paymaster relay uses Oblivious HTTP (OHTTP) to separate a wallet's network identity from its paymaster request. The relay receives the browser connection but cannot decrypt the request. The paymaster decrypts and processes the request but receives it from the relay instead of directly from the browser.

The privacy goal is specific: no single operator should be able to connect a user's IP address to the transaction request submitted to the paymaster. OHTTP does not hide information that the resulting transaction publishes on-chain.

Wallet                 Independent relay                 Paymaster
  |                           |                              |
  | HPKE-encrypted request    |                              |
  |-------------------------->| opaque request               |
  |                           |----------------------------->|
  |                           |                    decrypt, validate,
  |                           |                    sponsor, and submit
  |                           |<-----------------------------|
  | encrypted response        |                              |
  |<--------------------------|                              |

sees: request + own IP        sees: client IP + ciphertext  sees: request + relay IP

What a private request contains

The wallet prepares the paymaster operation locally, including its signed transaction data, zero-knowledge proof, fee quote, and selected fee token. It encodes the operation as an inner request and encrypts it to the paymaster's current HPKE public key.

The relay only receives the encrypted OHTTP envelope. It cannot read the transaction, proof, fee token, addresses, or encrypted response. The paymaster opens the envelope because it holds the HPKE private key. On private Railgun operations, the proof still protects the shielded transfer details according to the Railgun protocol; the relay adds transport unlinkability between the browser connection and the paymaster submission.

Request flow

  1. The wallet starts with a relay URL and an independently pinned Ed25519 paymaster signing key. Anon's production values are also published in the well-known discovery document.
  2. The wallet fetches GET /ohttp-configs through the relay and verifies the returned HPKE KeyConfig against the pinned signing key. This prevents a relay from substituting a key it controls.
  3. Public, identity-free reads such as gas quotes and supported fee tokens are fetched through the relay. They are allowlisted and may be cached according to the paymaster's Cache-Control response.
  4. The wallet seals the private execute or status request with HPKE and sends the envelope to POST /gateway as message/ohttp-req.
  5. The relay forwards the opaque envelope to its fixed paymaster target. It does not choose a target from user input and is not an open proxy.
  6. The paymaster decrypts the inner request, validates the proof, signed quote, fee, and transaction, then submits accepted work on-chain.
  7. The paymaster encrypts its response to the wallet. The relay passes back message/ohttp-res without being able to read it.

What each party can observe

Party Can observe Cannot observe by design
Wallet Its request, keys, response, and network connection Other users' activity
Relay Client IP, ciphertext size, timing, and allowlisted public-read paths and queries OHTTP request or response plaintext; paymaster private keys
Paymaster Decrypted request, result, timing, and relay IP Client IP, when the relay and ingress remove client-IP forwarding
Chain observer Data and timing published by the resulting transaction OHTTP plaintext while it is in transit

Security guarantees

  • Content confidentiality at the relay. OHTTP encrypts each private request and response using HPKE. The relay holds no decryption or signing key.
  • Network-identity separation at the paymaster. The paymaster receives a connection from the relay, not the wallet, provided no client-IP header is forwarded.
  • Key-substitution resistance. Clients verify rotating HPKE configurations with an Ed25519 key pinned outside the relay channel. Discovery is convenient, but it is not a replacement for a pinned trust anchor.
  • Ciphertext integrity. Authenticated encryption causes modified ciphertext to fail validation. A relay can still drop, delay, or replay traffic, so the application must remain safe under retries.
  • Constrained forwarding. The implementations use a fixed paymaster target, explicit public-read paths, a 1 MiB request limit in the Go service, and strict OHTTP media types. They are not general-purpose proxies.
  • No browser credentials. Public relay responses use wildcard CORS and no cookies, authorization headers, or browser credentials.

Limits and assumptions

The relay is a split-trust privacy tool, not a full anonymity network.

  • The relay and paymaster must be operated by different, non-colluding parties. If they combine their observations, they can reconnect client IPs with requests.
  • A global observer may correlate request size and timing across the relay and paymaster. OHTTP does not provide mixnet-style traffic-analysis resistance.
  • The relay operator can log client IPs and traffic metadata. Choose an operator whose independence and data-handling policy match your threat model.
  • Direct calls to the paymaster reveal the caller's network address. Clients need to route configuration, public quotes, execute requests, and status requests through the relay.
  • OHTTP does not conceal public blockchain metadata, transaction timing, address reuse, or values that the transaction itself reveals.
  • Availability is not guaranteed. A relay can block, delay, rate-limit, or selectively refuse requests.

Use a public relay

Anon publishes a browser-compatible relay at https://relay.anon.inc. Its current URL and paymaster signing key are discoverable at https://anon.inc/.well-known/anon-paymaster.json.

You can use another public relay when it:

  • targets the paymaster you intend to use;
  • implements the same /ohttp-configs, /gateway, gas-quote, and supported-token routes;
  • permits your client origin or provides compatible browser CORS;
  • is operated independently from the paymaster; and
  • has an acceptable availability, logging, and retention policy.

A public relay cannot be pointed at an arbitrary paymaster by the client. That fixed-target property is intentional: it prevents the service from becoming an open proxy. A relay operator must configure and deploy a compatible instance for each paymaster target.

Run your own relay

The complete Go, Docker, and Cloudflare Worker implementations are public at github.com/anondotinc/paymaster-relay. The repository contains tests, deployment configuration, health checks, and browser preflight verification.

Go and Docker

The Go service provides the strongest client-IP separation because it constructs fresh upstream requests and forwards no client headers. It can run in any container platform, virtual machine, or Kubernetes account:

git clone https://github.com/anondotinc/paymaster-relay.git
cd paymaster-relay
docker build -t anon-ohttp-relay .
docker run --rm -p 8080:8080 \
  -e OHTTP_GATEWAY_URL="https://paymaster.example.com" \
  anon-ohttp-relay

Terminate TLS in front of the container, expose only the relay routes, apply reasonable body and rate limits, and avoid request-body logging.

Cloudflare Worker

The Worker can be deployed from any Cloudflare account with a zone and custom domain you control. Fork the repository, then edit worker/wrangler.toml:

  • choose a unique Worker name;
  • replace the custom-domain routes[].pattern;
  • set TARGET to the intended paymaster's HTTPS OHTTP gateway.

Deploy and verify it from the repository root:

make cloudflare-login
make deploy RELAY_URL=https://relay.example.com

Cloudflare manages the custom-domain DNS record and certificate during deployment.

Cloudflare client-IP caveat: for Worker subrequests to a non-Cloudflare origin, Cloudflare documents that CF-Connecting-IP contains the client address and cannot be altered by the Worker. The paymaster ingress must remove visitor-IP headers before logging or application processing. If you cannot guarantee that, use the Go relay. See Cloudflare's HTTP header reference.

Operator checklist

  • Operate independently from the paymaster organization.
  • Point the relay only at the intended HTTPS paymaster gateway.
  • Forward no browser cookies, authorization values, user agents, or client-IP headers.
  • Disable request and response body logging; minimize metadata retention.
  • Preserve the exact OHTTP request and response media types.
  • Keep the public-read allowlist narrow and honor upstream cache lifetimes.
  • Add rate limits that do not create stable per-user identifiers.
  • Monitor /health and verify the /gateway browser preflight after deployment.
  • Publish the relay URL, operator identity, logging policy, and supported paymaster target.

References