A §18 proof is a small piece of cryptography attached to a result. It says the published code, given these inputs, produced this exact output. You can check that in a few milliseconds, on your own machine, with no network, without re-running the calculation, and without taking the operator's word for it. If you need to, the proof can confirm the output while keeping the inputs private.
This page explains why that matters for regulated financial work, walks through how the proof is built and checked one step at a time with the math and code for each step, and tells you what we got wrong on the way so your team can skip the same mistakes.
Every regulated decision has to be defensible later: a capital calculation, a sanctions screen, an IFRS 17 measurement, a margin or settlement instruction. Today, to trust someone else's number you either re-run their tool and trust your own copy of it, or you accept an attestation and trust their controls. OpenChainGraph already gives every result an execution_hash, a SHA-256 over the canonical inputs and outputs:
That hash lets two parties confirm their outputs are identical. It does not tell you which code produced the number, or that the code ran faithfully on the inputs it claims. In finance that gap is expensive and concrete. Auditors re-perform calculations by hand. Counterparties stand up duplicate infrastructure just to reconcile. Supervisors accept SOC reports and management attestations they cannot independently check. The trust is social, not mathematical.
A compute-integrity proof closes that gap. Here is what it buys you, specifically in a regulated setting:
The mechanism is a zero-knowledge virtual machine (a zkVM): a processor that runs a program and emits a proof that it ran it correctly. The work is in feeding it the right thing to run and making the result reproducible. Here is the whole pipeline, with the math and code at each step.
Each tool's logic is a pure function. The same inputs always return the same output, with no clock, no randomness, no I/O.
Why it matters: a proof of a computation is only meaningful if the computation is reproducible in the first place. Determinism is the foundation everything else sits on.
Take the SHA-256 of the kernel's source code. That hash is the kernel's identity, and it is published next to the tool so "the published model" becomes a precise, checkable claim rather than a label.
The guest is a small program compiled for the zkVM's instruction set (RISC-V, RV64IM). It embeds a JavaScript engine (QuickJS), takes the kernel source and the inputs, runs compute, and writes three things to its public output, the journal.
Why it matters: because the kernel source is an input rather than baked in, one guest covers every kernel, present and future. We do not maintain a separate proving program per tool.
Compiling the guest with a pinned toolchain produces a deterministic fingerprint of the program, the ImageID. Publish it.
Why it matters: anyone can rebuild the guest from public source and get the same ImageID. That is how a third party confirms exactly what program runs their data, trusting no one.
A prover runs the guest in the zkVM and produces a STARK receipt, then wraps it into a Groth16 proof over the BN254 curve, about 200 bytes. This is heavy and happens out of band, never in a browser and never on a request path. Always with development mode off, so the receipt is real.
Why it matters: a small Groth16 proof verifies with a couple of pairings, so checking is cheap, and keeping proving off-line means the live service stays fast and never holds private data.
The receipt rides inside the result's artifact and is excluded from the execution_hash preimage.
A self-contained pairing check confirms the proof against the published ImageID and the journal. No network, no toolchain, milliseconds. This is the part a regulator or counterparty runs.
That is the trust model in one line: rebuild the guest and you confirm what code runs; check the proof and you confirm it ran that code on those inputs to get that output. No hardware enclave, no consensus, no operator to trust.
We took the AINumbers suite from zero §18 coverage to a real proof on every clean kernel. None of it was faked (more on that below). Here is the honest account, so you can plan around the same problems instead of discovering them.
The obvious first idea is to rewrite each kernel in the zkVM's native language and prove that. We considered it and walked away. A separate guest per kernel means a separate thing to maintain, and every one is a fresh chance to drift from the JavaScript the browser actually runs. Putting one JavaScript engine in the guest and passing the kernel source as input gave us a single program, a single ImageID, and no per-tool proving code. If you adopt this, do the same: one guest, source as input.
The arithmetic standard (IEEE-754) only guarantees the same bits across engines for the basic operations. The library functions do not carry that guarantee, and they can differ in the last unit in the last place between two correct engines. A handful of our kernels (the machine-learning and quantitative ones) produced guest output that differed from the browser by exactly that last bit, and a last-bit difference means the proof does not match the canonical result.
The fix was a shared deterministic math library, used identically in all three places. Those roughly twelve transcendental kernels were the last and hardest part of the entire effort. If your kernels do pricing, risk, or ML math, budget for this first, not last.
One kernel validated URLs with a spec-faithful parser. Inside the guest, that cost roughly 5.4 billion cycles, which is effectively un-provable at any sane price. We replaced it with a small deterministic check and used that same check on every path, so the output never diverged.
The lesson generalizes: faithful-inside-the-guest is sometimes the wrong target. The real requirement is deterministic and identical everywhere, and a simpler function that meets it beats an expensive one that does not.
Two more classes of bug had nothing to do with math. One kernel imported a helper module lazily, which let execution order vary; making the import eager fixed it. Another formatted numbers with the locale-aware formatter, which quietly picked up the host's locale and changed the output.
Neither looked like a determinism problem at a glance. The takeaway is that determinism is a property of the whole runtime, the imports and the formatting and the locale, not just the arithmetic.
The prover has a development mode (RISC0_DEV_MODE=1) that emits a fake receipt which still passes verification. A fake proof sitting in a standards repository is the worst outcome we could ship, worse than shipping no proof at all, because it looks real. We ran every single proof with RISC0_DEV_MODE=0, and the rule we held to was simple: if we could not produce a real proof, we shipped nothing for that kernel and said so. Hold the same line.
The full suite proved on a single consumer GPU (an RTX 3080) in about five and a half hours. The Groth16 wrap ran roughly 252 seconds per kernel. The first toolchain build took 5 to 15 minutes. Verifying any of the proofs is milliseconds. Proving is the investment and it is a one-time, off-line cost; verifying is free and universal. If you have no GPU, a proving network (such as Boundless or Succinct) is an option for the proving step, but keep it out of the verify path.
Before generating a single proof, sort your kernels into three buckets: the ones using only basic arithmetic are ready immediately, the ones using integer powers need a quick check that the exponent really is an integer, and the transcendental ones need the deterministic math work first. That sort is your project plan. We classified all of ours up front, and it told us exactly where the hard work was.
Most verifiable-compute approaches anchor trust in one of two places. OCG §18 uses neither in the verify path.
| Approach | What you have to trust | OCG §18 |
|---|---|---|
| Secure hardware (TEE, confidential compute) | A chip vendor's attestation and supply chain | No enclave. Trust comes from the reproducible re-execution and the proof. |
| Blockchain or token network | A consensus set and its economic incentives | No chain in the verify path. Verification is a local pairing check. |
| Operator attestation (SOC reports) | The operator's controls and an auditor's review of them | No operator trust. The proof binds the published code to this output. |
Proving can use heavy compute, and a proving network is one way to get it. Verification stays self-contained, offline, and chain-free. That split is the whole promise: proving may be expensive and optional, checking is cheap and for everyone.
You need only the artifact, the published ImageID, and the verifier. Take any OCG artifact that carries a compute_proof, look up that tool's ImageID in chaingraph.json, and run the self-contained verifier. It does one pairing check and returns true only for a real proof of that exact output.
If you want to generate proofs, or independently confirm that the published ImageID matches the published guest source, you run the prover. Rebuild the guest and confirm you get the same ImageID we published, then prove with development mode off.
Then check that the journal's output equals what the JavaScript kernel produces for the same inputs, and verify your own receipt with the same self-contained verifier. The exact field definitions are in the technical spec under §17 and §18.
OpenChainGraph Standard §17 (kernel identity) and §18 (compute-integrity), in the technical spec. RISC Zero receipts (journal and seal). Ethereum Foundation zkVM Standards v0 (RV64IM). Software provenance by running an interpreter in a zkVM (arXiv 2026). Floating point in zero-knowledge systems. QuickJS. RFC 8785 (JSON Canonicalization Scheme).