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.
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.
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.
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.Anatomy of the receipt
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.
The binding triangle
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.
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.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.What the seal check does
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.
eth_call on-chainimageId 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 four ways to verify and their trust roots
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.
Where the seal stops
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.
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.