Compute proofs

How to read and verify a Groth16 receipt

Every proof-bearing kernel publishes the cryptographic receipt for its own result in the same file as its own code, in a public repository under a CC BY 4.0 license. This page explains what each field of a receipt means, reads one real receipt from the top, and shows four ways to verify one.

Where the receipts live

Every receipt sits in the public repository

Each receipt is a JSON object embedded in the published shard file that also carries the node's metadata, schema references, and conformance fixtures. The whole set lives in the public repository, one file per node, so a receipt and the logic it attests can be read side by side. For example, the receipt for the Basel 3.1 reporting delta node sits inside its node file, under the compute_proof key.

receiptFormat
groth16-bn254: the Groth16 proving scheme (Groth, EUROCRYPT 2016) instantiated over the BN254 elliptic curve. The same receipt carries a system: risc0 field naming the zkVM that produced it.
Why this format Groth16 proof size and verification cost stay small even for large computations, and BN254 verification is cheap enough for a smart contract to run.
imageId
A SHA-256 digest identifying the exact guest program binary the zkVM executed. This is the identity the seal is bound to: a receipt made by a different binary carries a different imageId.
Binding each imageId is also published in the node's compute_images list, and the coverage gate refuses a receipt whose imageId is missing from that list.
seal
The Groth16 proof itself, base64-encoded: a few hundred bytes of cryptographic material that verifies against RISC Zero's published verifying key. It is the compressed proof that a valid execution produced this journal.
Verified against the RISC Zero verifying key, which our in-browser verifier and the on-chain recipe both pin. Verification has two outcomes: the pairing check passes, or the receipt fails.
journal
The public output committed by that execution. It carries the digest of the kernel source that ran (kernel_digest) and the output payload itself, which the coverage gate requires to equal the node's published output byte for byte.
Checked a journal that commits an error fails the gate, since a valid seal over a failed run would prove only that the failure happened. The coverage gate has rejected that case structurally since August 2026, when it was observed once in practice.
The claim

What the seal establishes

Verifying a receipt is a local cryptographic check: given the seal, the journal, and the imageId, anyone can confirm that the seal is a valid Groth16 proof, under the published verifying key, for an execution of that exact guest binary that halted normally and committed exactly this journal. Running the check requires no trust in us, in the server that served the page, or in the deployment pipeline. The published result provably came from running the published logic.

The check is also cheap: a browser verifies in milliseconds, and Ethereum has shipped native BN254 pairing checks since EIP-196 and EIP-197 went live in the Byzantium hard fork (October 2017), so a smart contract can verify too. Our on-chain verification recipe uses exactly that path, one read-only call against RISC Zero's deployed verifier contract.

Publishing every receipt in a versioned public repository puts them where tampering is visible, the same transparency pattern Certificate Transparency standardized for certificates (RFC 9162) and SLSA standardized for build provenance. The deploy side of that pattern, which binds the served bytes of this site to a named commit and workflow run, is described on the Methods page.

Worked example

One receipt, read from the top

This is the receipt from the Basel 3.1 reporting delta node file, the same object a verifier consumes. The seal is shortened to a head and tail of the real value and the asset-class table is trimmed to one row; every other value is verbatim from the file.

{
  "type": "ZkVmReceipt",
  "system": "risc0",
  "receiptFormat": "groth16-bn254",
  "imageId": "sha256:a1a0bc89b5b1febaeda3519f6dbade0fa5ac16beeb143c4e1b01689573567bc6",
  "seal": "IHfBGtT0qGiU2bFEFgG3pWVb1Q94FzrdJfBcYBtr ... M7u/slkH989njTyjh/Q==",
  "journal": {
    "chaingraph_version": "0.4.0",
    "kernel_digest": "sha256:bb655f6f08ccd299198d1eff963940525ec31c073ef296bfce08503620cb28c7",
    "output": {
      "asset_class_summary": [
        {
          "id": "residential_mortgage",
          "label": "Residential Mortgage",
          "ead_bn": 100,
          "current_rwa_bn": 35,
          "basel31_rwa_bn": 20,
          "rwa_delta_bn": -15,
          "rwa_delta_pct": -42.86
        }
      ],
      "current_rwa_bn": 35,
      "basel31_rwa_bn": 20,
      "rwa_delta_bn": -15,
      "rwa_delta_pct": -42.86,
      "floor_rwa_bn": 25.375,
      "output_floor_binding": false,
      "cet1_ratio_current_pct": 15.5,
      "cet1_ratio_basel31_pct": 27.13,
      "capital_shortfall_bn": 0,
      "compliance_flags": ["OUTPUT_FLOOR_NOT_BINDING", "CET1_ADEQUATE"],
      "verdict": "MINIMAL_IMPACT"
    }
  }
}
  1. Name the scheme

    receiptFormat says which proving scheme and curve to expect: a Groth16 proof over BN254. system: risc0 says the RISC Zero zkVM produced it, so RISC Zero's published verifying key is the one that applies.

  2. Identify the program that ran

    imageId is the SHA-256 of the exact guest binary inside the zkVM. The same node file publishes that digest in its compute_images list under system: risc0 (valid from 2026-07-10), and the coverage gate fails any receipt whose imageId is absent from that list.

  3. The seal itself

    The seal is the proof, base64-encoded. Nothing in it is meant to be read by eye; it is material for the pairing check. Verification runs against RISC Zero's verifying key in a browser (Verification Desk) or through an Ethereum precompile (on-chain recipe).

  4. Bind the receipt to the source

    journal.kernel_digest is the hash of the kernel source that produced this output, sha256:bb655f6f.... The node publishes the same digest as its sha256-source image, so the guest binary, the seal, and the published kernel source all point at each other.

  5. Check what was committed

    journal.output is the output of that one execution: here, the Basel 3.1 output-floor recomputation over the node's recorded input, with the risk-weighted-assets delta (-15bn, -42.86%), the floor test (25.375bn floor, not binding), and the verdict MINIMAL_IMPACT. The coverage gate requires this object to equal the node's published output byte for byte, which is what makes this a receipt for the result on the page rather than for some other run of the same code.

Two questions sit outside any receipt. Whether the kernel's logic is a correct model of the Basel 3.1 output floor is answered by the specification and property evidence described on the mechanical verification page, and whether the bytes served today still match what this receipt attests is answered by the deploy manifest, because a receipt attests one execution in the past.

Verify one yourself

Four ways to check a receipt

In the browser no network
Open the Verification Desk and drop in any node's JSON file. Its compute-proof layer verifies the BN254 seal with a self-contained reference verifier vendored from the same code the suite ships, entirely in your browser.
Good for checking a receipt you have already downloaded, with zero setup and zero network calls.
On-chain one eth_call
The receipt verification recipe walks through checking a receipt against RISC Zero's deployed on-chain verifier with a single read-only eth_call, using any Ethereum RPC endpoint.
Good for a trust root outside our infrastructure entirely: the verifier contract is RISC Zero's, not ours.
From the repository CLI
Clone the repo and run node scripts/check-compute-proof-coverage.mjs. The gate replays the structural checks for every receipt in the estate and fails against its committed ratchet baseline if any regress.
Good for auditing the whole set at once, or the coverage gate's own behavior: the script is public, commented, and tested.
The normative text SPEC.md
Section 18 of the OpenChainGraph specification defines what a compute-integrity receipt must contain, where it lives, and which checks make one malformed. The spec, its version history, and every gate that enforces it are in the same public repository.
Good for checking the rule each gate enforces against its normative source.

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, receipt model of journal plus seal, accessed September 2026. RFC 9162, Certificate Transparency Version 2.0, December 2021. All statements on this page are as of September 2026.