zk-proven judge
Each verdict in a proven batch carries a succinct zero-knowledge proof (SP1, Groth16) that verdict = judge(trace) for the judge program registered on-chain. A contract checks it. You do not have to trust Karatum's servers or any TEE vendor for the judging step.
What is proven, and what is not
- Proven. For every trace in the batch, the Karatum judge (ported to Rust, run in the SP1 RISC-V zkVM) parses the trace, applies the verdict rules of its task type and computes the trace hash and the verdict hash. The proof commits to a Merkle root over keccak256(keccak256(traceHash ‖ verdictHash)). A malformed trace makes the program abort, so no proof exists for it.
- Not proven. That the trace is honest: the evidence in it (transfers, balances, approvals) was collected by the runner from the Mirror fork. Pair the proof with a TEE-run runner or a Flight Record for that part. The Rust port is checked against the published TypeScript evaluator by differential tests, not by a proof of equivalence.
Full method, costs and how to reproduce: docs/methodology/zk-judge.md. Re-execution path: verifiable judge.
Rust port vs the published evaluator
Run zkdiff-2026-10-16-seed7: 21,744 / 21,744 cases identical (same accept/reject decision, same verdict, checks and reason, same verdict, trace and task-spec hashes), against bundle 0x6f1b3cdd70…2adcbe. Includes all 134 stored traces; 10,107 cases judged by both, 11,637 rejected by both.
Proven batches
| Batch | Verdicts | Cycles | Proving (CPU) | On-chain |
|---|---|---|---|---|
| judge-sample-2049:all:134 root 0xe34d4ed032…622983 | 134 | 91.8 M | 54.4 min | 0xc8884bd2…775860 · 812,888 gas |
Contracts (Ethereum Sepolia)
- ZkJudgeVerifier
- 0x5b03cf51e29F91DEAc8A129d5373fF6D28b4B823 (no owner; submitBatch is permissionless)
- SP1 verifier
- Succinct gateway 0x397A5f7f3d…48dA9B → Groth16 v6.1.0 0xb69f2584CB…a6f4e2
- Program allow-list
- EvaluatorRegistry (revoking the vkey there invalidates every batch of that program)