Compute proofs · Interactive explainer

How a Groth16 receipt is made, and what it binds

A drawn companion to the Groth16 receipts reference page. Six scenes follow one real receipt from the kernel that produced it to the checks that keep it accurate: the two lanes that meet in a node file, the fields a verifier reads, the three bindings that make the receipt count for the published result, and the four ways to check one yourself. Every value shown is a real value from the public repository. Written for auditors and engineers meeting a zkVM receipt for the first time.

Before stage 1 · Foundation

What has to be proved

A receipt is a claim about one execution. For the claim to be worth anything, three facts have to hold together: the execution ran a specific program, the program ran to completion under the zkVM, and it committed exactly one output. Leave any of the three out and the remaining two prove almost nothing: a proof over an unnamed binary binds to whatever binary the prover happened to run, and a proof over an unnamed output could be carried to any result on the page.

Groth16 compresses all three facts into a seal of a few hundred bytes. The compression is the point: the original run may have taken minutes of zkVM time, but checking the seal afterwards takes milliseconds, on any machine, with no access to the original inputs and no re-run of the computation. Minutes of proving, paid once by the publisher, become milliseconds of checking, available to everyone.

which programimageId ran to completionzkVM execution committed this outputjournal one Groth16 receipta few hundred bytes
three facts about one execution → one succinct seal · checking replaces re-running
Stage 1 of 6

The two lanes that meet in a node file

A receipt has two parents that never meet in time. The publish lane is fast: kernel source, its digest, the guest binary built for the zkVM, its imageId, and the node's recorded inputs all land in the repository like any other code. The prove lane is heavy: the guest runs inside the zkVM, the journal is committed, and a prover produces the Groth16 seal over a Rust toolchain with real compute behind it. Only when both lanes are done does the receipt, the pair of imageId and seal and journal, take its place in the node file next to the code it attests.

PUBLISH LANE · IN THE REPOSITORY kernel sourcethe node's .mjs file kernel_digestsha256:bb655f6f… guest binarybuilt for the zkVM imageIdsha256:a1a0bc89… recorded inputspolicy_parameters node filemetadataschema refsconformance fixturescompute_proof:imageId · sealjournal:kernel_digestoutput = publishedoutput, byte for byte PROVE LANE · OFF-BAND, HEAVY guest + inputsinside the zkVM zkVM executionhalts normally journaloutput committed Groth16 proverseal, over BN254
publish lane: code and digests land in seconds · prove lane: zkVM run and sealing take real compute · the receipt joins the node file when both finish
Two identities
Source digest, binary digest
kernel_digest names the source code; imageId names the guest binary built from it. A receipt carries both bindings, one to the code a human can read and one to the binary the zkVM actually executed.
Off-band
Proving never runs in a browser
The prover needs a Rust toolchain and serious compute. The site and the MCP worker verify receipts; producing new ones happens in the proving pipeline, and the standard forbids claiming otherwise.
Stage 2 of 6

Anatomy of the receipt

PractitionerNormative version: SPEC §18

This is the receipt from the Basel 3.1 reporting delta node, the same object the reference page reads from the top. Every value is verbatim from the published node file; the seal is shortened to a head and tail. Select a field to read what it holds and which check looks at it.

compute_proof art-07-basel31-reporting-delta-calculator "system": "risc0""receiptFormat": "groth16-bn254" "imageId":"sha256:a1a0bc89b5b1febaeda3519f6dbade0…" "seal":"IHfBGtT0qGiU2bFEFgG3…M7u/slkH989njTyjh/Q==" "journal":"kernel_digest":"sha256:bb655f6f08ccd299198d1eff963940…" "output":"rwa_delta_bn": -15"rwa_delta_pct": -42.86"verdict": "MINIMAL_IMPACT"
Field reader
Select a field
Five fields carry the whole claim. Together they answer: which zkVM made this proof, which binary ran, what the proof material is, which source produced the output, and what the output says.
Checked by each field has its own checker; select a field to see it
Not prose
The seal is material, never a message
Base64 decoding the seal yields curve points and field elements, readable by a pairing check and by nothing else. Its only two states are a pass and a failure.
Scope
One receipt, one execution
The journal commits the output of a single run over the node's recorded input. Byte equality with the published output is what turns it from a proof about some run into a proof about the result on the page.
Stage 3 of 6

The binding triangle

PractitionerNormative version: SPEC §18

A receipt earns its keep by pointing three ways at once: at the source code a reviewer can read, at the binary the zkVM executed, and at the published output a reader came for. Each edge of the triangle has a named check waiting for it to slip. Push one of the three buttons to break an edge and watch which check notices.

kernel sourcepublished as sha256-source image guest binaryimageId listed in compute_images published outputthe result on the page receiptseal + journal built from this source seal covers this imageId journal.output = output journal.kernel_digest = source digest (advisory three-way cross-check)
source ↔ binary ↔ output, held together by one receipt · each edge names the check that watches it
nominal: all three bindings hold
Nominal state. The imageId is in the node's compute_images list, the journal equals the published output byte for byte, and the seal verifies under the published key. All three checks are wired to fail loudly the moment one edge slips.
Structural
Some checks need no cryptography
Membership in compute_images and byte equality of the journal are ordinary file comparisons. They run in the coverage gate on every change, which is why a mismatched receipt cannot reach the site even before any pairing math runs.
Cryptographic
One check only math can do
That the seal was produced by a proving ceremony over this binary and this journal is the pairing check's verdict. Everything else could be forged by editing files; the seal cannot.
Stage 4 of 6

What the seal check does

PractitionerNormative version: SPEC §18

Verification consumes four things: the seal, the journal, the imageId, and the zkVM vendor's published verifying key. It runs a fixed, small sequence of BN254 pairing operations and returns one of two verdicts. Nothing about the check depends on our infrastructure: the key is the vendor's, the math is the standard's, and the check is cheap enough for a browser tab or a smart contract.

verifier inputssealjournalimageId verifying keypublished by the zkVM vendor BN254pairing check passthis program producedthis output failthe receipt is rejected;there is no third verdict
four inputs → one fixed pairing sequence → pass or fail · milliseconds in a browser, one read-only eth_call on-chain
what passesThe seal is a valid Groth16 proof, under the vendor's key, for an execution of the binary named by the imageId that halted normally and committed exactly this journal. That sentence is the whole verdict; the check adds nothing about the code's logic or about later deployments.
the mathA pairing is an operation that eats two elliptic-curve points and returns one field element, and Groth16 arranges a handful of them into an equation that holds only for a proof built by the ceremony. Constant work, a few milliseconds, no setup beyond the key.
delegationVerification delegates to the named system's vetted verifier, the same way hashing delegates to WebCrypto and signing delegates to Ed25519 implementations. The trust question becomes: whose verifier, and the answer is published next to the receipt format.
Stage 5 of 6

The four ways to verify and their trust roots

Beginner

One receipt, four doors. They differ in what you have to trust to believe the result: a page's vendored code, Ethereum's precompiles, your own machine, or a specification's gate suite. Pick the door your auditor accepts; the verdict is the same through all four.

In the browserverification-desk.html, zero network callsdrop in any node's JSON; the BN254 sealverifies in a self-contained reference verifiertrust root: the vendored verifier in your tab On-chainone read-only eth_call, any Ethereum RPCthe BN254 precompiles (EIP-196/197, livesince October 2017) run the vendor's contracttrust root: Ethereum + the vendor's verifier From a clonenode scripts/check-compute-proof-coverage.mjsreplays the structural checks for every receiptagainst a committed ratchet baselinetrust root: your machine + the committed baseline The normative textSPEC.md section 18what a receipt must contain, where it lives,and which checks make one malformedtrust root: the spec + the gates that enforce it
same receipt, four doors · the trust root is the only thing that differs
Stage 6 of 6

Where the seal stops

Beginner

The seal answers one question about one execution in the past. Two neighboring questions live outside it, and the site answers each on its own page: whether the kernel's logic models the regulation correctly is the mechanical verification question, and whether the bytes served today still match the receipt's node is answered by the deploy manifest.

WHAT THE SEAL COVERS one past execution this binary · this journal · this moment is the logicright?mechanical verification served bytes,still these?the deploy manifest
the dashed line is the seal's edge · the two gold questions are answered by their own evidence pages

Sources: Groth, On the Size of Pairing-based Non-interactive Arguments, EUROCRYPT 2016. EIP-196 and EIP-197, BN256 curve and pairing precompiles, live since October 2017. RISC Zero proof system documentation, dev.risczero.com, accessed September 2026. Receipt values verbatim from the art-07 node file. All statements on this page are as of September 2026.