DOCS · RECEIPTS
Receipts
Every simulated run writes a receipt. It pins the raw inputs, your limits, the market snapshot and the result by SHA-256, so anyone can rerun it and get the same hashes: verified and reproducible.
What is in a receipt
receipt.json # hashes, label, limits, statement
manifest.json # file list and sizes
inputs.json # the raw simulator input
What is checked
The verifier re-derives every hash, checks the manifest and reruns the simulator on inputs.json. It does not read the network and does not submit an order.
| Check | Mismatch |
|---|---|
Receipt version 1 or 2, kind, label and the statement verified and reproducible | version mismatch, kind mismatch, label mismatch, statement mismatch |
| SHA-256 of the limits payload | limits_hash mismatch |
| SHA-256 of the market-snapshot rows | market_snapshot_id mismatch |
SHA-256 of inputs.json | data_snapshot_id mismatch |
SHA-256 of manifest.json | manifest_sha256 mismatch |
| SHA-256 of the stored simulator result | result_sha256 mismatch |
| Simulator rerun on the raw inputs | result.<path> mismatch |
| Frozen limits on that rerun | guard mismatch: <code> |
Check from the command line
node --experimental-strip-types examples/verify-receipt.ts path/to/receipt-dir
A match prints VERIFIED and exits 0. A difference prints MISMATCH with each field and exits 1. Step by step on the verify page.
Check from code
import { verifyReceipt } from "@perpbrain/sdk";
const report = verifyReceipt(receipt, manifestBytes, inputsBytes);
report.status; // "VERIFIED" or "MISMATCH"
Agents can call the MCP tool verify_receipt for the same check.
Check in the browser
verify/web/ in the SDK is a static page. Serve it with any static server and drop the receipt files on it. It hashes them locally with WebCrypto and uploads nothing. The full simulator rerun stays in verifyReceipt.
Results cards
renderReceiptCard draws a static SVG from a verified receipt. It shows the SIMULATED label, the receipt hash, the limits preset and loosened flag, the NOT_MODELLED items and the execution-cost section. There is no headline number.
Try tampering
fixtures/receipts/ ships one good receipt and five tampered ones (limits hash, snapshot id, result, data, manifest). Each fails with the matching line above.