OpenChainGraph · Explainer

From receipt to verify() calldata

An offline builder for the read-only on-chain receipt check. Paste a published §18 compute-integrity receipt and read back everything the deployed RISC Zero verifier consumes: the journal bytes (UTF-8 of the canonical JSON), their SHA-256, the imageId, the seal with its 4 byte selector prefix, and the assembled verify(bytes,bytes32,bytes32) calldata with the exact cast call to run elsewhere. Every number is computed on this page; nothing is transmitted and the seal itself is never checked here, only assembled for the contract that will.

Presenter mode shows one step per screen. Arrow keys move, A toggles autoplay, Esc exits.
1
Step 1

What you are holding

A published compute-integrity receipt is one JSON object carrying four facts: the program that ran, the output it committed, the Groth16 seal over that commitment, and the parameter set the proof was made under. Only three of them cross the chain boundary.

the receiptimageId · seal · journalgroth16-bn254 imageId · 32 bytes journalDigest · 32 seal 256 + 4 selector the deployed routerconsumes exactly these three

The envelope is the OpenChainGraph standard's §18 compute proof: type ZkVmReceipt, system risc0, receiptFormat groth16-bn254, plus imageId, seal and the journal. The imageId is the SHA-256 identity of the exact guest program that ran in the zkVM; the journal is the output the guest committed; the seal is the 256 byte Groth16 proof binding the two together. The deployed verifier consumes the imageId, a digest of the journal, and the seal. Everything else on this page exists to get those three exactly right.

Who asks at this stepany CLI agent
Here is a published §18 receipt in JSON. Name which of its members the deployed RISC Zero verifier consumes, and what each one binds the proof to.
2
Step 2

The journal bytes and their digest

The verifier never sees the journal object; it sees one SHA-256 digest. The bytes that get hashed are the canonical JSON of the journal: RFC 8785 (JCS), encoded UTF-8, keys sorted at every nesting depth, no insignificant whitespace. Hash any other serialization and an honest receipt fails, which is how you know you hashed the right bytes.

journal objectkeys as published canonical JSONkeys sorted, UTF-8no whitespace sha2560000000000000000…

Serialization is not a technicality. The published worked example on this page is the one receipt in the estate corpus whose journal carries unsorted nested keys, so the stored-order bytes and the canonical bytes genuinely differ, and only the canonical digest verifies on-chain. That is the standard's §18.7 byte contract, and the deployed contract agrees with it: the recipe page shows both directions recorded live against the router.

Who asks at this stepany CLI agent
Compute the RFC 8785 canonical serialization of this journal object. Report the UTF-8 byte length and the SHA-256 digest, and show the canonical JSON itself.
3
Step 3

The seal and its 4 byte prefix

Base64-decoded, the seal is exactly 256 bytes: three elliptic curve points of a Groth16 proof over the BN254 curve. On the wire it travels with a 4 byte selector in front, 73c457ba, which routes the call to the verifier implementation whose parameters match how the proof was made. The joined 260 bytes are what the call carries.

seal, base64344 characters 256 raw bytesGroth16 over BN254 73c457baselector = 260 bytes

The selector is derived from the verifier parameters (the risc0 control root, the BN254 control id, the Groth16 verifying key digest) rather than from a crate version string. The estate's receipts are proven with cargo-risczero 3.0.5 against the parameter set risc0-ethereum shipped as its 3.0.0 verifier generation, whose selector is 0x73c457ba. Before verifying you can confirm the routing live with a one word getVerifier call; the recipe page shows that step too.

Who asks at this stepany CLI agent
Decode this base64 seal to raw bytes, confirm the length is exactly 256, and prepend the risc0 v3.0.x selector 73c457ba to form the 260 byte on-chain seal.
4
Step 4

Build the calldata

Paste a published receipt. This page recomputes the journal digest locally and assembles the exact call the deployed verifier consumes. It never checks the seal itself, and it makes no request of any kind: the on-chain check happens when you run the command below somewhere that has cast, or hand the calldata to a read-only eth_call as the recipe page shows.

A genuine receipt is about 2 KB; pastes over 100 KB are rejected. Published or synthetic receipts only. All processing stays on this page.

Layout, for checking the builder's work: 4 byte function selector ab750e75, one 32 byte offset word (0x…60), the imageId word, the journalDigest word, a 32 byte length word (0x…104 = 260), then the selector prefixed seal zero padded to a 288 byte word: 420 bytes total. The recipe page carries the full byte table, the router addresses on more chains, and the two independent RPC habit worth keeping.

Who asks at this stepagent with cast
Run this cast call against the VerifierRouter and report exactly what comes back: empty output means the receipt verified; a revert carrying 0x439cc0cd means it did not.
5
Step 5

What the pass establishes

Read this label twice:

This check proves a RISC Zero Groth16 proof of this journal under this program id verifies on the deployed verifier. It does not prove the rule is correct, and the deployed verifier for this version can be stopped by its operator.
seal verifiesthis journal, this image rule correct?not a proof's job policy fresh?compare publications verifier up?operator can stop it
Who asks at this stepreport drafting
Given this verified receipt, draft the two sentences a report should carry: what the on-chain pass establishes, and the two things it deliberately does not claim.
🔒 All inputs are processed locally in your browser. No data is transmitted. Do not enter real personal data — use synthetic or anonymised inputs only.