zPredictdocs
App
Menu

Privacy

View .md

Who can learn what, through which data flow, the open caveats of the hosted demo, and how to check each claim yourself.

This page summarises PRIVACY.md, the result of an adversarial audit (#15, 2026-10-23) where every claim names its evidence.

Summary. Order privacy is 3-of-3 (all three relayers must collude); funds are 2-of-3 (FROST). Nothing transparent touches the product.

Read the hosted demo as "one party can see everything". Cloudflare terminates TLS for all three relayers, so it sees every share in clear plus client IPs (#88, open). And all three relayers, and the key ceremony, run on one VM, whose operator could read every share. The protocol's guarantees assume three independent operators with TLS ending at each relayer.

Who learns what

PartyLearnsNever learns
Chain observerThat shielded Ironwood transactions happen; ZIP 317 feesDepositors, bets, sides, sizes, winners, payout recipients
Anyone (public API)Markets, outcomes and signatures, one clearing price per market per crossing batch; a digest per share received (how many orders arrive, and when); batch number and peer healthAny share, orderId, account id, balance or fill
Network observerThat your IP talks to *.zpredict.site; sizes and timingContents (TLS); with Tor, your IP
Cloudflare (as deployed)Everything the relayers receive, in clear, and client IPs (#88)—
Demo VM operatorEverything—
One relayerEach deposit's amount, time and account id; each withdrawal's amount, address and time; its own share of everything; the public priceOrders, sides, prices, sizes, positions, balances, any tag, whose withdrawal it is (except via #90 and #91)
Two relayersAs one, and they can move escrow fundsOrders and tags
All three relayersEverything—
CounterpartyIts own fill at the midpoint; if a single pair crossed, the midpoint and its own limit give yoursWho you are
lightwalletd operators (zec.rocks, testnet.zec.rocks)The relayer VM's IP syncing and broadcastingUsers
PolymarketThe relayer VM's IP fetching public records for the mirrored markets, about every 5 minUsers, orders. The browser never contacts Polymarket

Leak checklist

ItemEvidence
✅No transparent address in any product pathpayout.rs re-encodes payees Ironwood-only; verify.rs refuses transparent, Sapling or Orchard parts; the e2e scripts assert transparent in+out 0
✅Fixed deposit denominations; order size never on chainDENOMINATIONS; orders exist only as XOR shares
⚠️Withdrawals don't link to depositsShielded on chain; relayers see amount, address and time (#91)
✅Memos carry no order data and never the tagmemo-vectors.json
✅Each order share goes only to its own relayersubmitOrder + distinct() in packages/sdk
✅Public feeds can't be recombined/view publishes BLAKE2b-128 digests, no shares, no orderIds
✅One relayer can't collect fill sharesPer-relayer read token (orders.rs)
✅One relayer can't read balances or act as an account?key=sᵢ gate; the circuit checks the 128-bit key (a_relayer_cannot_act_as_an_account)
⚠️TLS ends at each relayerCloudflare terminates TLS for all three (#88)
✅No third-party requests from the frontendsSelf-only CSP; build gates; these docs too (below)
⚠️No analyticsWe ship none; Cloudflare injects a beacon (blocked by CSP) and NEL headers (#89)
✅No IP logsnginx access_log off, error_log /dev/null, client-IP headers stripped; Caddy and the relayers log no addresses
⚠️Request metadata doesn't link actions to an accountPoll jitter, no balance read on fill; connection-level linkage open (#90)
✅Viewing keys and key shares never leave the relayers or appear in logsSealed at rest (Settlement & FROST)
✅No secrets in gittrufflehog git file://. --no-verification over all history

Accepted limitations

  • Single-VM demo and Cloudflare (above).
  • Demo counterparty. "Take the other side (demo)" sends a judge's order and its exact opposite together from the same account, so a relayer can guess they came from one browser. It still can't read either.
  • Relayers see deposit and withdrawal amounts, addresses and times, and the account id behind each deposit.
  • Key-burn DoS. A dishonest relayer can pre-register shares for an id it learned and burn that row: funds locked, never stolen.
  • Public price per market per crossing batch, and order arrival counts through /view.
  • Two relayers can move escrow funds, while order privacy needs all three.
  • Not quantum-recoverable escrow notes (ZIP 2005; see Threat model).
  • Mirrored markets trust Polymarket (Markets).

These docs

docs.zpredict.site makes no third-party requests: the font (JetBrains Mono) and every image are self-hosted, search runs on this server, and there are no analytics or cookies. Each page carries a CSP with a per-request script nonce and default-src 'none', no remote origin anywhere. pnpm build fails if the client bundle references a third-party host, and the smoke test fails if a rendered page would fetch one (apps/docs). Links to GitHub and elsewhere are plain links; nothing loads until you click.

Verify it yourself

# Public views hold digests only: nothing to XOR.
for i in 0 1 2; do curl -s "https://r$i.zpredict.site/view?after=0" | head -c 300; echo; done
# Fill shares need the browser's token.
curl -s https://r0.zpredict.site/orders/00000000000000000000000000000000
# CSP of the app: self-only, connect-src = the three relayers.
curl -sI https://app.zpredict.site | grep -i 'content-security-policy\|referrer'
# Is TLS still at Cloudflare (#88)? "server: cloudflare" means yes.
curl -sI https://r1.zpredict.site/health | grep -i 'server\|cf-ray'
# Code: one relayer can't act as an account; the full flow pays to Ironwood only.
cargo test -p zpredict-circuit a_relayer_cannot_act_as_an_account
scripts/relayer-e2e.sh