A swarm of GPUs on Robinhood Chain. Read the docs
Privacy model

What the network knows about you.

Two mechanisms, and an honest account of what neither of them does. Anonymous access hides which holder is asking. Sealed prompts stop the orchestrator reading the text it routes. Everything below is backed by code in this repository; anything that is not built says so.

Anonymous access
Checking…

Reading the gate…

What leaked before

The network already stripped identity before a job reached a worker, and kept no prompt text. Then the $ZKMOSQ access gate arrived, and every request started carrying a wallet signature. The orchestrator could tie a wallet to every prompt it served. The token gate created exactly the linkage the privacy claim was about, and closing it is what this work is.

Anonymous access

You register once. A signature binds a Semaphore commitment to your wallet, the orchestrator reads your on-chain $ZKMOSQ balance and files the commitment under a tier. That step is public on purpose: it is the only place a balance can be checked.

After that, each request carries a membership proof instead of a wallet. The proof says “some member of this tier”, is bound to that exact request, and burns a single-use nullifier. One nullifier per slot per identity is what enforces the tier’s daily cap, cryptographically, without anyone keeping a per-wallet counter. Your browser builds the whole member set locally and proves against it, because asking the server for one member’s Merkle path would tell it which member is about to send a request.

The circuits are Semaphore v4, existing audited work. We write none of our own. Proving runs in your browser and costs about half a second:

Build a 1,000-member group (depth 10)225 ms
Generate a proof527 ms
Verify a proof0 to 14 ms
Proof sizeabout 884 bytes

Measured on a 6-core laptop under Node 20. Verifying is the orchestrator’s cost, and it is a rounding error next to running a model.

Sealed prompts

This one is not ZK, and we will not describe it as ZK. It is ordinary public-key encryption, and it closes the other half of the leak: without it the orchestrator can read prompt text in memory while routing it.

Every worker publishes an X25519 public key for its session. Your browser reserves a worker, derives a shared key against that key (ECDH, then HKDF-SHA256 salted with the job id) and encrypts the payload with AES-256-GCM. The worker decrypts, runs the model, and encrypts each token frame on the way back. The orchestrator relays opaque frames and becomes a blind relay. Token counts still travel in clear, so billing and settlement are untouched.

What each party learns

The orchestrator gets metadata without content. The worker gets content without identity. Registration gets identity, and stops there. No party holds both halves, which is the whole design.

Registration

Once per wallet. Public on purpose, and this is where it stops.
wallet, commitment, signature, issuedAt
Learns
  • That this wallet joined this tier
  • Its on-chain $ZKMOSQ balance
Never sees
  • Anything you ask later
  • Which request is yours

Nothing crosses this line. A request carries a proof that some member of the tier sent it, and a single-use nullifier that spends one of the day's slots. Neither can be traced back to the wallet above.

Your browser

Holds everything. Nothing below it does.
prompt
identity secret
wallet
Learns
  • The prompt
  • Which wallet you are
  • Your identity secret

The orchestrator

Routes and bills. Relays ciphertext it cannot read.
X-ZK-Proof: root, nullifier, scope, points
jobId, clientPublicKey, nonce, ciphertext
Learns
  • That some member of a tier asked
  • Which model, and the token counts
  • When the request happened
  • Your IP address
Never sees
  • Which wallet asked
  • The prompt text
  • The answer text

The GPU worker

Runs the model. Gets the text, never the person.
model, params, decrypted prompt
Learns
  • The prompt text
  • The answer it generates
  • Which model and parameters
Never sees
  • Which wallet asked
  • Your account or billing
  • Your IP address
  • Your tier

What this does not do

Privacy claims are worth what their limits are worth. These are the limits, and they are not footnotes.

It does not prove the model ran

Nothing here proves a worker ran the model you asked for, or ran it correctly. That is the state of the field, not a shortcut: the high-water mark for zkML is a full proof of GPT-2, and proving LLaMA-2-7B costs roughly 2,646 seconds per token. One sentence would take weeks. Verifiable execution is a later phase and would use TEE attestation or sampled re-execution, not ZK.

It does not hide that you asked

A sealed, anonymous request still tells the orchestrator that a request happened, which model it used, how many tokens went in and out, and when. Billing and routing run on exactly that.

It does not hide your IP

You connect over the network, so the orchestrator sees your address. We don’t log IPs and they are stripped before a job reaches a worker, but “we don’t log it” is a policy, not a proof. If the operator is in your threat model, use a VPN or Tor. That is your call, not something the protocol makes for you.

It is only as good as the set size

A proof hides you inside the registered holders of your tier and nothing more. In a set of three, the set identifies you. The panel above reports the live size of every tier so you can judge it before relying on it.

Registration itself is public

Registering binds a wallet to a commitment through an on-chain balance check, and that record is not hidden. Anyone can see a wallet joined a tier. What nobody can see is which member sent any particular request.

The request path, the endpoint shapes and the worker-side rules are in the privacy docs, and the console shows per request which of these protections actually applied.