Trap rows and slashing
Every AI buyer's view carries fake rows that exist nowhere else. If one shows up outside the server, its secret proves which view it came from.
Trap rows
When a buyer's view is created, the server mints twelve rows that look like real ones of each type: a name, an email at a trap domain, a phone number, a URL. Each row carries a random 32-byte secret, written into its email, URL and phone number.
The onchain proof
Before the view answers its first query, the server commits the merkle root of the view's trap rows in Canaries.commitView. The leaf is keccak256(keccak256(abi.encode(viewId, secret))). Revealing a secret with its proof is checked by the contract and can only be done by someone who saw that row.
A case, step by step
- The keeper sweeps the trap endpoints every 10 minutes. A fetched URL or a mail to a trap address gives it the secret.
- Anyone calls
reportRenter(viewId, secret, proof, evidenceHash). The buyer's deposit is frozen. - The buyer has 48 hours to call
dispute. A disputed case goes to the arbiter. - Otherwise anyone calls
finalize: the whole USDG deposit moves to the users.
Server trap rows
A second set of trap rows is never shown to any buyer; its root is fixed when the server registers. If one of those shows up, the leak came from the server itself: reportEnclave opens the same 48 hour case, and finalizing it slashes the operator's 100,000 $POD stake, half burned and half to the users.