Architecture
PARANOID has three parts that trust each other as little as possible: the Solana program, the client on your device, and a gateway.
your device gateway (anyone can run one) Solana
----------- ---------------------------- ------
secret, commitment reads recent roots <------------------- Tree account
Merkle path verifies the Groth16 proof Config, Member, vaults
proof per request ---- key ---> checks nullifiers for this epoch
forwards the prompt ---> model
<--- answer --
deposit, exit, withdraw ------------------------------------------------> program instructions
On chain
Accounts, all at program-derived addresses:
| Account | Seeds | Holds |
|---|---|---|
Config | ["config"] | Launch constants (epoch length, rate, limit, max epochs, exit delay, burn shares) and running totals |
Tree | ["tree"] | Poseidon Merkle tree of member leaves, depth 20, with the last 64 roots |
Member | ["member", commitment] | One membership: depositor, leaf index, start and end epoch, next unpaid epoch, balance, status |
| vault | ["vault"] | Every member's |
| burn vault | ["burn_vault"] | |
| bought | ["bought"] | Tokens bought by the crank, burned in the same instruction |
A commitment can be in the tree once: the member PDA is derived from it. The leaf is Poseidon(commitment, end_epoch) with commitment = Poseidon(secret).
Off chain
- Client: makes the secret, keeps it, builds Merkle paths from the tree account, and generates one Groth16 proof per request with snarkjs. The proof is the API key.
- Gateway: stateless apart from the nullifiers it has seen this epoch. It accepts a root only while it is still valid for the request's epoch (each stored root carries a
valid_beforeepoch), so a member that exits or is slashed cannot keep using an old root.
What each party learns
| Party | Learns | Never learns |
|---|---|---|
| Chain | Who deposited, how many epochs, who exited or was slashed | Anything about requests, which are billed by time, not by use |
| Gateway | The prompt, the proof, the epoch, how many slots the proof spends | Which member, which wallet, which other requests are yours |
| Model | The prompt | Anything else; the gateway strips identifying fields |