second-prover: the RISC Zero shard host, pinned guest and bench runner from proving-v2 (proof system 2, image id 0x9ae0f416), and the exporter's account-dump seeding, as the base of mission item 9

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
igneum-labs 2026-10-07 08:41:08 +00:00
parent 5e5a309a04
commit b3bfa60218
91 changed files with 14344 additions and 6 deletions

View file

@ -0,0 +1,36 @@
# Proof-system watch
One fixed shard, every candidate, one row each. The row says what a 12 GB card and a phone verifier would
see; the quarterly run says what moved.
## The fixed shard
Four fixtures, shard 0 of each: `proving/fixtures/fees-v1-shards2.json` (the adopted shard size `S_p`, 4,717,439
SP1 cycles, "the v1 shard"), `proving/fixtures/block-338-shard1.json` (one FULL shard at the prototype shard size,
60,415,376 cycles: the heaviest shard the chain ever cut; 30 GB on the stock SP1 server),
`proving/fixtures/block-72854-empty-block-first.json` (despite its name a 23.6 M-cycle shard: the first block after
an empty one; 17 s at 20 GB on the stock server) and `proving/fixtures/block-58927-empty-reward.json` (an empty
block, 278,423 RISC Zero cycles, "the empty shard"). The statement is
`igneum_prove_core::shard::shard_statement`; every candidate commits the same `ShardOutput` bytes. The 12 GB tier
is judged on the v1 shard; the prototype shard is the ceiling, not the gate.
## The candidates and how each is run
| Candidate | Binary | How | Recursion | Audit |
|---|---|---|---|---|
| SP1 stock 6.8.1 (Hypercube: SP1 6.x is the Hypercube prover, docs/analysis/proving-methods.md 1.1) | `proving/igneum-prove/target/release/igneum-prove-host` | `--mode compressed --shard 0`, `SP1_PROVER=cpu` on the Mac, `cuda` on PC 2 | yes (compressed, aggregator guest) | yes (KALOS, Cantina, Zellic, Veridise; docs/plans/funding.md 2a) |
| SP1 patched server (the prover-floor agent's v3/v4 build) | the same host, `~/.sp1/bin/sp1-gpu-server` replaced | PC 2 only (`HOME=/opt/igneum-floor/home`); n/a on the Mac (no CUDA) | yes | the server fork is not audited; the guest and verifier are the stock ones |
| SP1 Hypercube separate release | n/a | the stock row is the Hypercube prover; no separate release exists to run | | |
| RISC Zero (proof system 2) | `proving/igneum-prove-r0/target/release/igneum-prove-r0-host` | `--mode compressed --shard 0`, Metal on the Mac, CUDA on PC 2 | yes (succinct receipt; composition for an aggregator) | yes (Veridise, Hexens; funding.md 2a) |
| Jolt | n/a | no guest for our shard, no shipped recursion, no Metal release used here (proving-methods.md route F): n/a until a guest is written | no | no |
## The row
`rows/<date>-<machine>-<candidate>.json`: `candidate, machine, backend (cpu|cuda|metal), fixture, shard, cycles,
wall_s, prove_s, peak_memory_mib (max RSS on the Mac; nvidia-smi memory.used on a CUDA box), proof_bytes,
verify_s (one core), recursion, audit, verified (by the pinned verifier), command, source`. `node table.mjs`
renders every row into the table below. A cell that was not measured says `n/a` and why.
## Latest table
(rendered by `node bench/proof-systems/table.mjs > bench/proof-systems/TABLE.md`)

View file

@ -0,0 +1,86 @@
| Candidate | Machine, backend, note | Fixture | Cycles | Prove s | Wall s | Peak memory MiB | Proof bytes | Verify s (one core) | Recursion | Audit | Verified | Date |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| sp1-patched | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda, 4060 8 GB alone, patched 2^25 | block-338-shard1.json shard 0 | 60415376 | 87.0 | 94.9 | 7628 | 1272897 | 0.319 | yes | no | yes | 20261006-1604 |
| sp1-patched | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda, 4060 8 GB alone, patched 2^26 | block-338-shard1.json shard 0 | 60415376 | 41.3 | 49.3 | 7596 | 1272897 | 0.328 | yes | no | yes | 20261006-1603 |
| sp1-patched | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda | n/a: the prove run failed (exit 1): /tmp/tmp.7ILTbMmhGd/time.log:Error: CudaClientError: The server returned an internal error | | | | | | | | | | 20261006-1603 |
| r0 | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda, 4060 8 GB alone, po2 19 | block-338-shard1.json shard 0 | 89482640 | 401.9 | 403.5 | 6752 | 223882 | 0.224 | yes | yes | yes | 20261006-1541 |
| r0 | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda | n/a: the prove run failed (exit 101): /tmp/tmp.75fL1zX5AZ/time.log: out of memory | | | | | | | | | | 20261006-1541 |
| sp1 | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda | n/a: the prove run failed (exit 1): /tmp/tmp.klQ694HVLB/time.log:Error: CudaClientError: Failed to read the response: Custom { kind: UnexpectedEof, error: early eof } | | | | | | | | | | 20261006-1541 |
| sp1-patched | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda, 4060 8 GB alone, patched 2^25 | block-72854-empty-block-first.json shard 0 | 23594943 | 79.6 | 87.2 | 7628 | 1272897 | 0.319 | yes | no | yes | 20261006-1539 |
| sp1-patched | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda | n/a: the prove run failed (exit 1): /tmp/tmp.13mBtKKglh/time.log:Error: CudaClientError: The server returned an internal error | | | | | | | | | | 20261006-1539 |
| r0 | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda, 4060 8 GB alone, po2 19 | block-72854-empty-block-first.json shard 0 | 134734531 | 697.3 | 701.3 | 6730 | 223882 | 0.225 | yes | yes | yes | 20261006-1512 |
| r0 | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda | n/a: the prove run failed (exit 101): /tmp/tmp.JPJDVvnbik/time.log: out of memory | | | | | | | | | | 20261006-1512 |
| sp1 | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda | n/a: the prove run failed (exit 1): /tmp/tmp.NUem292PRA/time.log:Error: CudaClientError: Failed to read the response: Custom { kind: UnexpectedEof, error: early eof } | | | | | | | | | | 20261006-1511 |
| sp1-patched | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda, 4060 8 GB alone, patched 2^25 | block-58927-empty-reward.json shard 0 | 257467 | 5.9 | 12.9 | 7596 | 1272897 | 0.325 | yes | no | yes | 20261006-1511 |
| sp1-patched | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda, 4060 8 GB alone, patched 2^26 | block-58927-empty-reward.json shard 0 | 257467 | 4.2 | 11.2 | 7564 | 1272897 | 0.321 | yes | no | yes | 20261006-1511 |
| sp1-patched | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda, 4060 8 GB alone, patched 2^27 | block-58927-empty-reward.json shard 0 | 257467 | 3.3 | 10.5 | 7470 | 1272897 | 0.320 | yes | no | yes | 20261006-1511 |
| sp1-patched | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda, 4060 8 GB alone, patched default | block-58927-empty-reward.json shard 0 | 257467 | 3.3 | 10.4 | 7406 | 1272897 | 0.323 | yes | no | yes | 20261006-1511 |
| r0 | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda, 4060 8 GB alone, po2 19 | block-58927-empty-reward.json shard 0 | 278423 | 3.8 | 4.3 | 6876 | 223882 | 0.225 | yes | yes | yes | 20261006-1510 |
| r0 | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda, 4060 8 GB alone, po2 20 | block-58927-empty-reward.json shard 0 | 278423 | 3.8 | 4.3 | 6812 | 223882 | 0.223 | yes | yes | yes | 20261006-1510 |
| sp1 | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda | n/a: the prove run failed (exit 1): /tmp/tmp.0JSHMJ96SK/time.log:Error: CudaClientError: Failed to read the response: Custom { kind: UnexpectedEof, error: early eof } | | | | | | | | | | 20261006-1510 |
| sp1-patched | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda, 4060 8 GB alone, patched 2^25 | fees-v1-shards2.json shard 0 | 4717439 | 12.8 | 19.8 | 7660 | 1272897 | 0.318 | yes | no | yes | 20261006-1510 |
| sp1-patched | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda, 4060 8 GB alone, patched 2^26 | fees-v1-shards2.json shard 0 | 4717439 | 7.9 | 15.1 | 7692 | 1272897 | 0.316 | yes | no | yes | 20261006-1510 |
| sp1-patched | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda | n/a: the prove run failed (exit 124): /tmp/tmp.pKGGDBy0r0/time.log:called `Result::unwrap()` on an `Err` value: JoinError::Panic(Id(456), called `Result::unwrap()` on an `Err` value: OutOfMemory, ...) | | | | | | | | | | 20261006-1455 |
| r0 | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda, 4060 8 GB alone, po2 19 | fees-v1-shards2.json shard 0 | 10049917 | 47.1 | 47.7 | 6720 | 223882 | 0.221 | yes | yes | yes | 20261006-1454 |
| r0 | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda | n/a: the prove run failed (exit 101): /tmp/tmp.khG85FrAuh/time.log: out of memory | | | | | | | | | | 20261006-1453 |
| sp1 | rz-4060 (RTX 4060 8 GB, Vast.ai), cuda | n/a: the prove run failed (exit 1): /tmp/tmp.yOqeSspoDW/time.log:Error: CudaClientError: Failed to read the response: Custom { kind: UnexpectedEof, error: early eof } | | | | | | | | | | 20261006-1453 |
| sp1-patched | rz-3060 (RTX 3060 12 GB, Vast, driver 580), cuda, 3060 12 GB alone, patched 2^26 | block-58927-empty-reward.json shard 0 | 257467 | 7.3 | 27.5 | 7203 | 1272897 | 0.542 | yes | no | yes | 20261006-1408 |
| sp1-patched | rz-3060 (RTX 3060 12 GB, Vast, driver 580), cuda, 3060 12 GB alone, patched 2^27 | block-58927-empty-reward.json shard 0 | 257467 | 5.6 | 25.9 | 7301 | 1272897 | 0.562 | yes | no | yes | 20261006-1408 |
| sp1-patched | rz-4090 (RTX 4090 24 GB, RunPod, driver 570), cuda, 4090 24 GB alone, patched 2^25 | block-338-shard1.json shard 0 | 60415376 | 57.5 | 78.0 | 8128 | 1272897 | 0.571 | yes | no | yes | 20261006-1408 |
| r0 | rz-3060 (RTX 3060 12 GB, Vast, driver 580), cuda, 3060 12 GB alone, po2 19 | block-58927-empty-reward.json shard 0 | 278423 | 5.7 | 6.8 | 7345 | 223882 | 0.466 | yes | yes | yes | 20261006-1407 |
| r0 | rz-3060 (RTX 3060 12 GB, Vast, driver 580), cuda, 3060 12 GB alone, po2 20 | block-58927-empty-reward.json shard 0 | 278423 | 5.6 | 6.7 | 7345 | 223882 | 0.464 | yes | yes | yes | 20261006-1407 |
| sp1 | rz-3060 (RTX 3060 12 GB, Vast, driver 580), cuda | n/a: the prove run failed (exit 1): /tmp/tmp.qVtcFNc806/time.log:Error: CudaClientError: Failed to read the response: Custom { kind: UnexpectedEof, error: early eof } | | | | | | | | | | 20261006-1407 |
| sp1-patched | rz-3060 (RTX 3060 12 GB, Vast, driver 580), cuda, 3060 12 GB alone, patched default | block-58927-empty-reward.json shard 0 | 257467 | 5.5 | 24.7 | 7205 | 1272897 | 0.537 | yes | no | yes | 20261006-1407 |
| sp1-patched | rz-4090 (RTX 4090 24 GB, RunPod, driver 570), cuda, 4090 24 GB alone, patched 2^26 | block-338-shard1.json shard 0 | 60415376 | 29.2 | 51.3 | 8192 | 1272897 | 0.547 | yes | no | yes | 20261006-1407 |
| sp1-patched | rz-4090 (RTX 4090 24 GB, RunPod, driver 570), cuda, 4090 24 GB alone, patched 2^27 | block-338-shard1.json shard 0 | 60415376 | 21.2 | 42.3 | 11202 | 1272897 | 0.548 | yes | no | yes | 20261006-1407 |
| sp1-patched | rz-4090 (RTX 4090 24 GB, RunPod, driver 570), cuda, 4090 24 GB alone, patched default | block-338-shard1.json shard 0 | 60415376 | 19.5 | 42.2 | 18344 | 1272897 | 0.546 | yes | no | yes | 20261006-1406 |
| r0 | rz-4090 (RTX 4090 24 GB, RunPod, driver 570), cuda, 4090 24 GB alone, po2 19 | block-338-shard1.json shard 0 | 89482640 | 281.4 | 286.0 | 8846 | 223882 | 0.460 | yes | yes | yes | 20261006-1401 |
| r0 | rz-4090 (RTX 4090 24 GB, RunPod, driver 570), cuda, 4090 24 GB alone, po2 20 | block-338-shard1.json shard 0 | 89482640 | 178.5 | 182.5 | 13390 | 223882 | 0.467 | yes | yes | yes | 20261006-1358 |
| r0 | rz-3060 (RTX 3060 12 GB, Vast, driver 580), cuda, 3060 12 GB alone, po2 19 | block-338-shard1.json shard 0 | 89482640 | 578.2 | 582.5 | 7285 | 223882 | 0.459 | yes | yes | yes | 20261006-1357 |
| sp1 | rz-4090 (RTX 4090 24 GB, RunPod, driver 570), cuda, 4090 24 GB alone | block-338-shard1.json shard 0 | 60415376 | 19.1 | 41.8 | 20680 | 1272897 | 0.540 | yes | yes | yes | 20261006-1357 |
| r0 | rz-3060 (RTX 3060 12 GB, Vast, driver 580), cuda, 3060 12 GB alone, po2 19 | fees-v1-shards2.json shard 0 | 10049917 | 68.5 | 69.9 | 7339 | 223882 | 0.459 | yes | yes | yes | 20261006-1356 |
| sp1-patched | rz-4090 (RTX 4090 24 GB, RunPod, driver 570), cuda, 4090 24 GB alone, patched 2^25 | block-72854-empty-block-first.json shard 0 | 23594943 | 50.7 | 69.5 | 8192 | 1272897 | 0.549 | yes | no | yes | 20261006-1356 |
| sp1-patched | rz-4090 (RTX 4090 24 GB, RunPod, driver 570), cuda, 4090 24 GB alone, patched 2^26 | block-72854-empty-block-first.json shard 0 | 23594943 | 27.1 | 46.1 | 8160 | 1272897 | 0.545 | yes | no | yes | 20261006-1355 |
| sp1-patched | rz-4090 (RTX 4090 24 GB, RunPod, driver 570), cuda, 4090 24 GB alone, patched 2^27 | block-72854-empty-block-first.json shard 0 | 23594943 | 20.0 | 40.1 | 10754 | 1272897 | 0.533 | yes | no | yes | 20261006-1354 |
| sp1-patched | rz-4090 (RTX 4090 24 GB, RunPod, driver 570), cuda, 4090 24 GB alone, patched default | block-72854-empty-block-first.json shard 0 | 23594943 | 16.8 | 38.5 | 17576 | 1272897 | 0.544 | yes | no | yes | 20261006-1354 |
| sp1-patched | rz-3060 (RTX 3060 12 GB, Vast, driver 580), cuda, 3060 12 GB alone, patched 2^26 | block-338-shard1.json shard 0 | 60415376 | 58.3 | 81.1 | 7555 | 1272897 | 0.547 | yes | no | yes | 20261006-1349 |
| sp1-patched | rz-3060 (RTX 3060 12 GB, Vast, driver 580), cuda, 3060 12 GB alone, patched 2^27 | block-338-shard1.json shard 0 | 60415376 | 39.6 | 61.6 | 10661 | 1272897 | 0.550 | yes | no | yes | 20261006-1348 |
| sp1-patched | rz-3060 (RTX 3060 12 GB, Vast, driver 580), cuda, 3060 12 GB alone, patched default | block-338-shard1.json shard 0 | 60415376 | 39.2 | 61.1 | 10661 | 1272897 | 0.555 | yes | no | yes | 20261006-1347 |
| r0 | rz-4090 (RTX 4090 24 GB, RunPod, driver 570), cuda, 4090 24 GB alone, po2 19 | block-72854-empty-block-first.json shard 0 | 134734531 | 509.7 | 518.3 | 20484 | 223882 | 0.452 | yes | yes | yes | 20261006-1345 |
| r0 | rz-3060 (RTX 3060 12 GB, Vast, driver 580), cuda, 3060 12 GB alone | block-338-shard1.json shard 0 | 89482640 | 427.6 | 431.7 | 10153 | 223882 | 0.460 | yes | yes | yes | 20261006-1339 |
| sp1 | rz-3060 (RTX 3060 12 GB, Vast, driver 580), cuda | n/a: the prove run failed (exit 1): /tmp/tmp.bcgeLFKAkK/time.log:Error: CudaClientError: Failed to read the response: Custom { kind: UnexpectedEof, error: early eof } | | | | | | | | | | 20261006-1339 |
| r0 | rz-4090 (RTX 4090 24 GB, RunPod, driver 570), cuda, 4090 24 GB alone, po2 20 | block-72854-empty-block-first.json shard 0 | 134734531 | 354.6 | 362.9 | 20468 | 223882 | 0.453 | yes | yes | yes | 20261006-1339 |
| sp1-patched | rz-3060 (RTX 3060 12 GB, Vast, driver 580), cuda, 3060 12 GB alone, patched 2^26 | block-72854-empty-block-first.json shard 0 | 23594943 | 57.4 | 77.5 | 7491 | 1272897 | 0.546 | yes | no | yes | 20261006-1338 |
| sp1 | rz-4090 (RTX 4090 24 GB, RunPod, driver 570), cuda, 4090 24 GB alone | block-72854-empty-block-first.json shard 0 | 23594943 | 17.0 | 38.9 | 20136 | 1272897 | 0.531 | yes | yes | yes | 20261006-1338 |
| sp1-patched | rz-4090 (RTX 4090 24 GB, RunPod, driver 570), cuda, 4090 24 GB alone, patched 2^25 | fees-v1-shards2.json shard 0 | 4717439 | 9.5 | 26.8 | 8384 | 1272897 | 0.546 | yes | no | yes | 20261006-1338 |
| sp1-patched | rz-3060 (RTX 3060 12 GB, Vast, driver 580), cuda, 3060 12 GB alone, patched 2^27 | block-72854-empty-block-first.json shard 0 | 23594943 | 39.5 | 60.7 | 10245 | 1272897 | 0.550 | yes | no | yes | 20261006-1337 |
| sp1-patched | rz-4090 (RTX 4090 24 GB, RunPod, driver 570), cuda, 4090 24 GB alone, patched 2^26 | fees-v1-shards2.json shard 0 | 4717439 | 6.8 | 24.6 | 8192 | 1272897 | 0.546 | yes | no | yes | 20261006-1337 |
| sp1-patched | rz-4090 (RTX 4090 24 GB, RunPod, driver 570), cuda, 4090 24 GB alone, patched 2^27 | fees-v1-shards2.json shard 0 | 4717439 | 6.2 | 24.6 | 10850 | 1272897 | 0.543 | yes | no | yes | 20261006-1337 |
| sp1-patched | rz-3060 (RTX 3060 12 GB, Vast, driver 580), cuda, 3060 12 GB alone, patched default | block-72854-empty-block-first.json shard 0 | 23594943 | 39.7 | 61.0 | 9957 | 1272897 | 0.556 | yes | no | yes | 20261006-1336 |
| r0 | rz-4090 (RTX 4090 24 GB, RunPod, driver 570), cuda, 4090 24 GB alone, po2 19 | fees-v1-shards2.json shard 0 | 10049917 | 32.7 | 34.2 | 8500 | 223882 | 0.460 | yes | yes | yes | 20261006-1336 |
| sp1-patched | rz-4090 (RTX 4090 24 GB, RunPod, driver 570), cuda, 4090 24 GB alone, patched default | fees-v1-shards2.json shard 0 | 4717439 | 6.4 | 26.9 | 14696 | 1272897 | 0.546 | yes | no | yes | 20261006-1336 |
| r0 | rz-4090 (RTX 4090 24 GB, RunPod, driver 570), cuda, 4090 24 GB alone, po2 20 | fees-v1-shards2.json shard 0 | 10049917 | 23.1 | 24.6 | 13280 | 223882 | 0.455 | yes | yes | yes | 20261006-1335 |
| sp1 | rz-4090 (RTX 4090 24 GB, RunPod, driver 570), cuda, 4090 24 GB alone | fees-v1-shards2.json shard 0 | 4717439 | 6.4 | 127.5 | 17800 | 1272897 | 0.542 | yes | yes | yes | 20261006-1333 |
| r0 | rz-3060 (RTX 3060 12 GB, Vast, driver 580), cuda, 3060 12 GB alone | block-72854-empty-block-first.json shard 0 | 134734531 | 773.0 | 781.3 | 10173 | 223882 | 0.478 | yes | yes | yes | 20261006-1323 |
| sp1 | rz-3060 (RTX 3060 12 GB, Vast, driver 580), cuda | n/a: the prove run failed (exit 1): /tmp/tmp.tTBbwV8taM/time.log:Error: CudaClientError: Failed to read the response: Custom { kind: UnexpectedEof, error: early eof } | | | | | | | | | | 20261006-1323 |
| sp1-patched | rz-3060 (RTX 3060 12 GB, Vast, driver 580), cuda, 3060 12 GB alone, patched 2^26 | fees-v1-shards2.json shard 0 | 4717439 | 13.1 | 31.6 | 7587 | 1272897 | 0.551 | yes | no | yes | 20261006-1322 |
| sp1-patched | rz-3060 (RTX 3060 12 GB, Vast, driver 580), cuda, 3060 12 GB alone, patched 2^27 | fees-v1-shards2.json shard 0 | 4717439 | 9.5 | 31.5 | 10181 | 1272897 | 0.545 | yes | no | yes | 20261006-1321 |
| sp1-patched | rz-3060 (RTX 3060 12 GB, Vast, driver 580), cuda, 3060 12 GB alone, patched default | fees-v1-shards2.json shard 0 | 4717439 | 10.0 | 32.4 | 10117 | 1272897 | 0.536 | yes | no | yes | 20261006-1321 |
| r0 | rz-3060 (RTX 3060 12 GB, Vast, driver 580), cuda, 3060 12 GB alone | fees-v1-shards2.json shard 0 | 10049917 | 53.0 | 54.4 | 10071 | 223882 | 0.454 | yes | yes | yes | 20261006-1320 |
| sp1 | rz-3060 (RTX 3060 12 GB, Vast, driver 580), cuda | n/a: the prove run failed (exit 1): /tmp/tmp.rVivH09Uqp/time.log:Error: CudaClientError: Failed to read the response: Custom { kind: UnexpectedEof, error: early eof } | | | | | | | | | | 20261006-1319 |
| sp1-patched | DESKTOP-KMCV30N, cuda, beside the miner, patched 2^26 | block-338-shard1.json shard 0 | 60415376 | 138.0 | 148.1 | 12129 | 1272897 | 0.323 | yes | no | yes | 20261006-1203 |
| sp1-patched | DESKTOP-KMCV30N, cuda, beside the miner, patched default | block-338-shard1.json shard 0 | 60415376 | 38.1 | 52.0 | 27501 | 1272897 | 0.327 | yes | no | yes | 20261006-1202 |
| sp1 | DESKTOP-KMCV30N, cuda, beside the miner | block-338-shard1.json shard 0 | 60415376 | 37.6 | 53.7 | 30413 | 1272897 | 0.327 | yes | yes | yes | 20261006-1201 |
| sp1-patched | DESKTOP-KMCV30N, cuda, beside the miner, patched 2^26 | fees-v1-shards2.json shard 0 | 4717439 | 27.0 | 36.2 | 12012 | 1272897 | 0.324 | yes | no | yes | 20261006-1201 |
| sp1-patched | DESKTOP-KMCV30N, cuda, beside the miner, patched default | fees-v1-shards2.json shard 0 | 4717439 | 15.1 | 28.9 | 18637 | 1272897 | 0.327 | yes | no | yes | 20261006-1200 |
| r0 | MacBook-Pro, cpu, CPU HAL (metal build), po2 19 | block-58927-empty-reward.json shard 0 | 278423 | 46.5 | 46.9 | 7935 | 223882 | 0.210 | yes | yes | yes | 20261006-1200 |
| r0 | MacBook-Pro, cpu, CPU HAL (metal build), po2 20 | block-58927-empty-reward.json shard 0 | 278423 | 47.9 | 48.4 | 7933 | 223882 | 0.210 | yes | yes | yes | 20261006-1200 |
| r0 | MacBook-Pro, cpu, CPU HAL (metal build), po2 21 | block-58927-empty-reward.json shard 0 | 278423 | 49.0 | 49.4 | 7936 | 223882 | 0.210 | yes | yes | yes | 20261006-1200 |
| r0 | MacBook-Pro, cpu, CPU HAL (cpu build), po2 20 | fees-v1-shards2.json shard 0 | 10049917 | 585.8 | 587.7 | 10093 | 223882 | 0.210 | yes | yes | yes | 20261006-1200 |
| r0 | MacBook-Pro, cpu, CPU HAL (metal build), po2 19 | fees-v1-shards2.json shard 0 | 10049917 | 698.7 | 699.2 | 8013 | 223882 | 0.210 | yes | yes | yes | 20261006-1200 |
| r0 | MacBook-Pro, cpu, CPU HAL (metal build), po2 20 | fees-v1-shards2.json shard 0 | 10049917 | 574.4 | 575.0 | 10166 | 223882 | 0.210 | yes | yes | yes | 20261006-1200 |
| r0 | MacBook-Pro, cpu, CPU HAL (metal build), po2 21 | fees-v1-shards2.json shard 0 | 10049917 | 560.9 | 561.5 | 19497 | 223882 | 0.210 | yes | yes | yes | 20261006-1200 |
| sp1 | DESKTOP-KMCV30N, cuda, beside the miner | fees-v1-shards2.json shard 0 | 4717439 | 14.8 | 31.1 | 22477 | 1272897 | 0.321 | yes | yes | yes | 20261006-1159 |
| jolt | MacBook-Pro, cpu | n/a: no guest for our shard statement and no shipped recursion (proving-methods.md route F) | | | | | | | | | | 20261006-1146 |
| sp1-patched | MacBook-Pro, cpu | n/a: the patched server exists only on PC 2 (/opt/igneum-floor/home) | | | | | | | | | | 20261006-1146 |
| sp1 | MacBook-Pro, cpu | fees-v1-shards2.json shard 0 | 4717439 | 71.7 | 80.3 | 27821 | 1272897 | 0.258 | yes | yes | yes | 20261006-1146 |

68
bench/proof-systems/run.sh Executable file
View file

@ -0,0 +1,68 @@
#!/usr/bin/env bash
# The proof-system watch, one machine: proves the fixed shard on every candidate that runs here and writes one row
# each to rows/. Usage: bench/proof-systems/run.sh [--candidates sp1,r0] [--backend cpu|cuda|metal] [--fixture <path>] [--shard N]
# Run it through the measure lock on the Mac (tools/lock/with-lock.sh measure); on a CUDA box set --backend cuda.
set -uo pipefail
HERE="$(cd "$(dirname "$0")" && pwd)"; ROOT="$(cd "$HERE/../.." && pwd)"
CANDS="sp1,r0"; BACKEND=""; FIXTURE="$ROOT/proving/fixtures/fees-v1-shards2.json"; SHARD=0; LABEL=""; OUT="$HERE/rows"
SP1_HOST="$ROOT/proving/igneum-prove/target/release/igneum-prove-host"
R0_HOST="$ROOT/proving/igneum-prove-r0/target/release/igneum-prove-r0-host"
PATCHED_HOME="/opt/igneum-floor/home"; PATCHED_ENV=""; R0_PO2=""
# --label: a note on the row ("beside the miner", "alone"); --sp1-host/--r0-host/--out: paths on a machine where the
# tree is not checked out (PC 2's WSL: /opt/igneum-segal/igneum-prove-host); --patched-home: the patched server's HOME
while [ $# -gt 0 ]; do case "$1" in --candidates) CANDS="$2"; shift 2;; --backend) BACKEND="$2"; shift 2;; --fixture) FIXTURE="$2"; shift 2;; --shard) SHARD="$2"; shift 2;; --label) LABEL="$2"; shift 2;; --sp1-host) SP1_HOST="$2"; shift 2;; --r0-host) R0_HOST="$2"; shift 2;; --out) OUT="$2"; shift 2;; --patched-home) PATCHED_HOME="$2"; shift 2;; --patched-env) PATCHED_ENV="$2"; shift 2;; --r0-po2) R0_PO2="$2"; shift 2;; *) echo "unknown $1"; exit 2;; esac; done
MACHINE="$(hostname -s)"; DATE="$(date -u +%Y%m%d-%H%M)"; mkdir -p "$OUT"
if [ -z "$BACKEND" ]; then if command -v nvidia-smi >/dev/null 2>&1; then BACKEND=cuda; elif [ "$(uname)" = Darwin ]; then BACKEND=metal; else BACKEND=cpu; fi; fi
# the time tool: the Mac's /usr/bin/time -l prints "maximum resident set size" in bytes, GNU time -v in KB
if [ "$(uname)" = Darwin ]; then TIME="/usr/bin/time -l"; else TIME="/usr/bin/time -v"; fi
# the wall-clock cap (the fleet finding, 6 October 2026: on a card too small for a profile the patched sp1-gpu-server
# hangs at the card's limit with 0% utilisation instead of failing); a run past it is a row that says "timed out"
CAP_S="${BENCH_CAP_S:-900}"
if command -v timeout >/dev/null 2>&1; then CAP="timeout -k 10 $CAP_S"; elif command -v gtimeout >/dev/null 2>&1; then CAP="gtimeout -k 10 $CAP_S"; else CAP=""; fi
peak_mib() { if [ "$(uname)" = Darwin ]; then awk '/maximum resident set size/ {printf "%d", $1/1048576}' "$1"; else awk '/Maximum resident set size/ {printf "%d", $NF/1024}' "$1"; fi; }
row() { # candidate backend host mode-env verify-mode
local cand="$1" backend="$2" host="$3" env="$4"; local name="$cand"
local dir; dir="$(mktemp -d)"; local res="$dir/results.json"; local tlog="$dir/time.log"; local plog="$dir/prove.log"
if [ ! -x "$host" ]; then printf '{"candidate":"%s","machine":"%s","backend":"%s","fixture":"%s","shard":%s,"na":"host not built: %s","date":"%s"}\n' "$cand" "$MACHINE" "$backend" "$(basename "$FIXTURE")" "$SHARD" "$host" "$DATE" > "$OUT/$DATE-$MACHINE-$cand.json"; echo "row $cand: n/a (no host)"; return; fi
local smi=""; if [ "$backend" = cuda ]; then nvidia-smi --query-gpu=memory.used --format=csv,noheader,nounits -l 1 > "$dir/smi.csv" 2>/dev/null & smi=$!; fi
local t0; t0=$(date +%s.%N)
local extra=""; if [ "$cand" = r0 ] && [ -n "$R0_PO2" ]; then extra="--po2 $R0_PO2"; fi
env $env $CAP $TIME "$host" "$FIXTURE" --mode compressed --shard "$SHARD" --prover 0xCAfc6e74000000000000000000000000000000c2 $extra --out "$res" > "$plog" 2> "$tlog"
local rc=$?; [ $rc -eq 124 ] || [ $rc -eq 137 ] && echo "RESULT timed out after $CAP_S s" >> "$plog"
pkill -f sp1-gpu-server 2>/dev/null; rm -f /tmp/sp1-cuda-*.sock local wall; wall=$(python3 -c "import time; print(round(time.time() - $t0, 2))")
[ -n "$smi" ] && { kill $smi 2>/dev/null; sleep 1; }
local peak; if [ "$backend" = cuda ] && [ -s "$dir/smi.csv" ]; then peak=$(sort -n "$dir/smi.csv" | tail -1); else peak=$(peak_mib "$tlog"); fi
# a failed run keeps its logs beside the row (6 October 2026: the 4060's three failures kept one line each)
if [ $rc -ne 0 ] || [ ! -f "$res" ]; then local tag; tag="$DATE-$MACHINE-$cand$( [ -n "$LABEL" ] && printf -- '-%s' "${LABEL// /-}" )"; cp "$plog" "$OUT/$tag.prove.log" 2>/dev/null; cp "$tlog" "$OUT/$tag.time.log" 2>/dev/null; fi
if [ $rc -ne 0 ] || [ ! -f "$res" ]; then printf '{"candidate":"%s","machine":"%s","backend":"%s","fixture":"%s","shard":%s,"na":"the prove run failed (exit %s): %s","date":"%s"}\n' "$cand" "$MACHINE" "$backend" "$(basename "$FIXTURE")" "$SHARD" "$rc" "$(grep -E 'RESULT|rror|panicked|out of memory|OOM' "$plog" "$tlog" | tail -1 | tr -d '"' | cut -c1-300)" "$DATE" > "$OUT/$DATE-$MACHINE-$cand$( [ -n "$LABEL" ] && printf -- '-%s' "${LABEL// /-}" ).json"; echo "row $cand: failed ($(grep -E 'panicked|out of memory|OOM|rror' "$plog" "$tlog" | tail -1 | cut -c1-160))"; return; fi
# the verify on one core, three runs
local stmt pf; stmt=$(python3 -c "import json; print(json.load(open('$res'))['statement'])"); pf=$(python3 -c "import json; print(json.load(open('$res'))['proof_file'])")
local vs=""; for i in 1 2 3; do local v0; v0=$(date +%s.%N); env $env "$host" --mode verify --proof "$pf" --statement "$stmt" > "$dir/verify-$i.log" 2>&1; local vrc=$?; vs="$vs$(python3 -c "import time; print(round(time.time() - $v0, 3))"),"; [ $vrc -ne 0 ] && { echo "row $cand: VERIFY FAILED"; break; }; done
python3 - "$res" "$cand" "$MACHINE" "$backend" "$FIXTURE" "$SHARD" "$wall" "$peak" "${vs%,}" "$vrc" "$DATE" "$env" "$OUT" "$LABEL" <<'PY'
import json, sys
res, cand, machine, backend, fixture, shard, wall, peak, vs, vrc, date, env, out, label = sys.argv[1:]
r = json.load(open(res))
vl = [float(x) for x in vs.split(',') if x]
row = {
'candidate': cand, 'machine': machine, 'backend': backend, 'fixture': fixture.split('/')[-1], 'shard': int(shard), 'date': date,
'cycles': r.get('cycles'), 'wall_s': float(wall), 'prove_s': r.get('compressed_prove_seconds'), 'peak_memory_mib': int(peak) if str(peak).isdigit() else None,
'proof_bytes': r.get('compressed_proof_bytes'), 'verify_s': min(vl) if vl else None, 'verify_runs': vl, 'verified': vrc == '0' and bool(vl),
'recursion': cand in ('sp1', 'sp1-patched', 'r0'), 'audit': cand in ('sp1', 'r0'), 'proof_system': r.get('proof_system', 1), 'image_or_program_id': r.get('image_id') or r.get('program_id'),
'command': f"{env} <host> {fixture} --mode compressed --shard {shard}", 'source': 'bench/proof-systems/run.sh', 'label': label,
}
tag = ('-' + label.replace(' ', '-')) if label else ''
json.dump(row, open(f"{out}/{date}-{machine}-{cand}{tag}.json", 'w'), indent=1)
print(f"row {cand}: prove {row['prove_s']} s, wall {row['wall_s']} s, peak {row['peak_memory_mib']} MiB, proof {row['proof_bytes']} B, verify {row['verify_s']} s, verified {row['verified']}")
PY
rm -rf "$dir"
}
for c in ${CANDS//,/ }; do
case "$c" in
sp1) if [ "$BACKEND" = cuda ]; then row sp1 cuda "$SP1_HOST" "SP1_PROVER=cuda RUST_LOG=off"; else row sp1 cpu "$SP1_HOST" "SP1_PROVER=cpu RUST_LOG=off"; fi ;;
sp1-patched) if [ "$BACKEND" = cuda ] && [ -d "$PATCHED_HOME" ]; then row sp1-patched cuda "$SP1_HOST" "HOME=$PATCHED_HOME SP1_PROVER=cuda RUST_LOG=off $PATCHED_ENV"; else printf '{"candidate":"sp1-patched","machine":"%s","backend":"%s","na":"the patched server exists only on PC 2 (/opt/igneum-floor/home)","date":"%s"}\n' "$MACHINE" "$BACKEND" "$DATE" > "$OUT/$DATE-$MACHINE-sp1-patched.json"; echo "row sp1-patched: n/a"; fi ;;
r0) if [ "$BACKEND" = cuda ]; then row r0 cuda "$R0_HOST" "RISC0_PROVER=local RUST_LOG=off"; elif [ "$BACKEND" = metal ]; then row r0 metal "$R0_HOST" "RISC0_PROVER=local RUST_LOG=off"; else row r0 cpu "$R0_HOST" "RISC0_PROVER=local RUST_LOG=off"; fi ;;
jolt) printf '{"candidate":"jolt","machine":"%s","backend":"%s","na":"no guest for our shard statement and no shipped recursion (proving-methods.md route F)","date":"%s"}\n' "$MACHINE" "$BACKEND" "$DATE" > "$OUT/$DATE-$MACHINE-jolt.json"; echo "row jolt: n/a" ;;
*) echo "unknown candidate $c" ;;
esac
done
echo "rows in $OUT"

View file

@ -0,0 +1,13 @@
// Renders every row in rows/ into one markdown table (the latest row per candidate and machine first).
import { readdirSync, readFileSync } from 'node:fs';
const dir = new URL('./rows/', import.meta.url).pathname;
const rows = readdirSync(dir).filter(f => f.endsWith('.json')).map(f => ({ file: f, ...JSON.parse(readFileSync(dir + f, 'utf8')) })).sort((a, b) => (b.date || '').localeCompare(a.date || ''));
const latest = new Map();
for (const r of rows) { const k = `${r.candidate}@${r.machine}@${r.backend}@${r.label || ''}@${r.fixture || ''}`; if (!latest.has(k)) latest.set(k, r); }
const fmt = (v, d = 1) => v === null || v === undefined ? 'n/a' : typeof v === 'number' ? v.toFixed(d) : String(v);
console.log('| Candidate | Machine, backend, note | Fixture | Cycles | Prove s | Wall s | Peak memory MiB | Proof bytes | Verify s (one core) | Recursion | Audit | Verified | Date |');
console.log('|---|---|---|---|---|---|---|---|---|---|---|---|---|');
for (const r of latest.values()) {
if (r.na) { console.log(`| ${r.candidate} | ${r.machine}, ${r.backend || 'n/a'} | n/a: ${r.na} | | | | | | | | | | ${r.date} |`); continue; }
console.log(`| ${r.candidate} | ${r.machine}, ${r.backend}${r.label ? ', ' + r.label : ''} | ${r.fixture} shard ${r.shard} | ${fmt(r.cycles, 0)} | ${fmt(r.prove_s)} | ${fmt(r.wall_s)} | ${fmt(r.peak_memory_mib, 0)} | ${fmt(r.proof_bytes, 0)} | ${fmt(r.verify_s, 3)} | ${r.recursion ? 'yes' : 'no'} | ${r.audit ? 'yes' : 'no'} | ${r.verified ? 'yes' : 'NO'} | ${r.date} |`);
}

3
proving/igneum-prove-r0/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
target/
*.bin
!elf/igneum-prove-r0-guest.bin

6583
proving/igneum-prove-r0/Cargo.lock generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,33 @@
# Igneum proving, proof system version 2 (6 October 2026): RISC Zero 3.0.6 proving the SAME shard statement as the
# SP1 guest in proving/igneum-prove (igneum-prove-core, unchanged, pulled by path), with Metal on Apple silicon and
# CUDA on NVIDIA behind cargo features. The guest lives in methods/guest with its own lock file and RISC Zero's
# accelerated crate patches; it is a pinned build artefact under elf/ (pin-guest.sh), never built by a normal host
# build. Design: docs/analysis/proving-methods.md route D; plan: docs/plans/proving-v2-risc0.md.
[workspace]
resolver = "2"
members = ["host", "methods"]
exclude = ["methods/guest"]
[workspace.package]
version = "0.1.0"
edition = "2021"
license = "ISC"
[workspace.dependencies]
igneum-prove-core = { path = "../igneum-prove/core" }
risc0-zkvm = { version = "=3.0.6", default-features = false }
risc0-build = { version = "=3.0.6" }
alloy-primitives = { version = "=1.7.3", default-features = false, features = ["std", "rlp", "serde", "k256"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
bincode = "=1.3.3"
hex = "0.4.3"
anyhow = "1.0"
sha2 = "0.10"
# This Mac has the Command Line Tools and no Xcode, so no `metal` shader compiler; risc0-sys compiles the zkp Metal
# kernels on EVERY macOS build of the prover (`xcrun metal`) although no circuit in 3.0.6 selects the Metal HAL (the
# arm is commented out in rv32im, recursion and keccak). The local copy of risc0-build-kernel 2.0.1 (patches/, one
# change in `compile_metal`) writes an empty metallib when RISC0_SKIP_METAL_KERNELS is set. Unset, it is upstream.
[patch.crates-io]
risc0-build-kernel = { path = "patches/risc0-build-kernel" }

View file

@ -0,0 +1,34 @@
#!/usr/bin/env bash
# The Mac measurement of proof system 2 (6 October 2026; docs/bench-log.md "6 October 2026, RISC Zero as proof
# system 2 on the Mac (Metal)"): for each fixture and po2, one `--mode compressed --shard 0` run of the host under
# `/usr/bin/time -l` (wall, user, sys, maximum resident set), then three `--mode verify` runs of its receipt with
# RAYON_NUM_THREADS=1 (one core). Run through the MEASURE lock with the miner paused:
# /Users/joshm/Projects/igneum/tools/lock/with-lock.sh measure proving/igneum-prove-r0/bench/mac-2026-10-06.sh <host binary> <tag> <po2...>
# Fixtures: FIXTURES env (default: the v1 shard fees-v1-shards2.json and the empty shard block-58927-empty-reward.json).
set -uo pipefail
HERE="$(cd "$(dirname "$0")" && pwd)"
HOST="${1:?host binary}"; TAG="${2:?tag, e.g. metal}"; shift 2
PO2S="${*:-20}"
FIX="$HERE/../../fixtures"
FIXTURES="${FIXTURES:-fees-v1-shards2.json block-58927-empty-reward.json}"
OUT="$HERE/out-2026-10-06"; mkdir -p "$OUT"
for f in $FIXTURES; do
name="${f%.json}"
for po2 in $PO2S; do
run="$name-$TAG-po2$po2"
echo "=== $run start $(date -u +%FT%TZ)"
/usr/bin/time -l "$HOST" "$FIX/$f" --mode compressed --shard 0 --po2 "$po2" --out "$OUT/$run.json" > "$OUT/$run.log" 2> "$OUT/$run.time"
echo "exit $?" >> "$OUT/$run.time"
grep -h "RESULT execute\|RESULT compressed" "$OUT/$run.log"; grep -h "real\|maximum resident\|^exit" "$OUT/$run.time"
proof=$(python3 -c "import json;print(json.load(open('$OUT/$run.json'))['proof_file'])" 2>/dev/null)
stmt=$(python3 -c "import json;print(json.load(open('$OUT/$run.json'))['statement'])" 2>/dev/null)
if [ -n "$proof" ]; then
for k in 1 2 3; do
RAYON_NUM_THREADS=1 /usr/bin/time -l "$HOST" --mode verify --proof "$proof" --statement "$stmt" > "$OUT/$run.verify$k.log" 2> "$OUT/$run.verify$k.time"
echo "verify $k exit $?" >> "$OUT/$run.verify$k.time"
grep -h "RESULT verify" "$OUT/$run.verify$k.log" | cut -c1-120; grep -h "real\|maximum resident\|^verify" "$OUT/$run.verify$k.time"
done
fi
echo "=== $run end $(date -u +%FT%TZ)"
done
done

View file

@ -0,0 +1,53 @@
{
"backend": "metal",
"block": 58927,
"block_hash": "0x272a99725fa79fdc631d1ff4b1978a26ad49fb5cf226b558561a35579c836996",
"budget": 7500000,
"compressed_proof_bytes": 223882,
"compressed_prove_seconds": 46.465535042,
"compressed_verify_seconds": 0.00926925,
"consensus_budget": true,
"cycles": 278423,
"daa_score": 0,
"execute_seconds": 0.19567625,
"execute_segments": [
{
"cycles": 278423,
"po2": 19
}
],
"fee_set": "prototype",
"fees_v1_activation_daa": null,
"fixture": "/Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/../../fixtures/block-58927-empty-reward.json",
"image_id": "0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72",
"native_seconds": 0.000114125,
"number": 58927,
"paging_cycles": 118603,
"po2": 19,
"proof_file": "/Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/out-2026-10-06/block-58927-shard-0-r0.bin",
"proof_sha256": "0x52def54e44e7ad0771023ff6aa9e5412c7cef6a94b759d27950410cb9e42b9d4",
"proof_system": 2,
"prover": "0x1919191919191919191919191919191919191919",
"reserved_cycles": 127262,
"risc0_crate_version": "3.0.6",
"seal_bytes": 222668,
"segments": 1,
"setup_seconds": 0.187576083,
"shard_budget": 7500000,
"shard_index": 0,
"shard_pgas": [
0
],
"shard_program_id": "0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72",
"shard_witness_bytes": [
13717
],
"shards": 1,
"statement": "0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958",
"test_cut": false,
"total_cycles": 524288,
"user_cycles": 278423,
"witness_bytes": [
13717
]
}

View file

@ -0,0 +1,15 @@
igneum-prove-r0-host sources 9d1377458bda9488: fixture /Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/../../fixtures/block-58927-empty-reward.json: chain 4463 block 58927 (0x272a99725fa79fdc631d1ff4b1978a26ad49fb5cf226b558561a35579c836996) at DAA score 0, 0 transactions in 0 including blocks, 11 accounts in the pre-state, plan 1 shard(s) at S_p = 7500000 pgas; fee schedule prototype, calibrated v1 from DAA score never: this block meters with prototype (intrinsic 200 pgas, B_p 30000000); proof system 2 (RISC Zero 3.0.6), backend metal (risc0 3.0.6: CPU HAL, the Metal arm is commented out in every circuit), segment po2 19; prover payout 0x1919191919191919191919191919191919191919; 2026-10-06T12:20:50Z
STAGE native start 2026-10-06T12:20:50Z
RESULT native: 0.0001 s, pre 0xea9db302b3b1fe3b859d5fb417408fecefeb06aa43721ed7fdf354975582f2c7 post 0x7886b9cfbbbdfe12509affbd4df83cb317e9708eeb627bd49b575cbfa47999c4 receipts 0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 gas 0 pgas 0 executed 0 skipped 0: MATCHES the fixture's expected values at 2026-10-06T12:20:50Z
RESULT shard 0 native: txs 0..0 (0 executed, 0 skipped), gas 0, pgas 0, witness 2 accounts 0 slots 2 leaves 9 hashes, input 13717 bytes, pre 0xea9db302b3b1fe3b859d5fb417408fecefeb06aa43721ed7fdf354975582f2c7 post 0x7886b9cfbbbdfe12509affbd4df83cb317e9708eeb627bd49b575cbfa47999c4
RESULT plan: 1 shard(s) chain from 0xea9db302b3b1fe3b859d5fb417408fecefeb06aa43721ed7fdf354975582f2c7 to 0x7886b9cfbbbdfe12509affbd4df83cb317e9708eeb627bd49b575cbfa47999c4 and sum to gas 0 pgas 0: the cut equals the block; native aggregation receipts 0x6fcd3e8e97da273711ccefb79abdd246c5663c7d61057f82bae745ceac5dcc75 provers 0xe8a6c07ee13e9afa662a1bf0bf69bae726aa8fdb541308bdd4b63bbc60175f27
RESULT tamper account balance: REJECTED (pre-root 0x61857fe806042480d26d91e9b75ffb347d4b3070f2a2e25300fe8dc493a8b441 is not the node's 0xea9db302b3b1fe3b859d5fb417408fecefeb06aa43721ed7fdf354975582f2c7)
STAGE setup start 2026-10-06T12:20:50Z
RESULT setup: 0.188 s (image id recomputed from the embedded guest), proof system 2 image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:20:50Z
RESULT pinned: setup matches the manifest (pinned guests: shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (3667564 bytes, sha256 0x2be67ce3e5a24010) aggregator id 0x0000000000000000000000000000000000000000000000000000000000000000 (0 bytes), pinned 2026-10-06T11:54:47Z on Darwin MacBook-Pro.local 25.6.0 Darwin Kernel Version 25.6.0: Fri Jul 31 19:19:08 PDT 2026; root:xnu-12377.161.14~5/RELEASE_ARM64_T6050 arm64, RISC Zero 3.0.6 proof system 2)
STAGE execute shard 0 start 2026-10-06T12:20:50Z
RESULT execute shard 0: 278423 user cycles in 1 segment(s) [(19, 278423)] (po2, cycles), 0.20 s at 2026-10-06T12:20:50Z
STAGE compressed shard 0 (succinct receipt, po2 19) start 2026-10-06T12:20:50Z
RESULT compressed shard 0: prove 46.5 s (1 segment(s), total cycles 524288, user cycles 278423, paging 118603, reserved 127262), receipt 223882 bytes (seal 222668 bytes), verify 0.009 s, VERIFIED; statement 0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958 proof sha256 0x52def54e44e7ad0771023ff6aa9e5412c7cef6a94b759d27950410cb9e42b9d4 prover 0x1919191919191919191919191919191919191919 at 2026-10-06T12:21:37Z
proof written to /Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/out-2026-10-06/block-58927-shard-0-r0.bin
results written to /Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/out-2026-10-06/block-58927-empty-reward-metal-po219.json

View file

@ -0,0 +1,19 @@
46.91 real 703.04 user 5.76 sys
8321089536 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
532601 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
0 voluntary context switches
1137793 involuntary context switches
6908658886941 instructions retired
2967412347960 cycles elapsed
8273156384 peak memory footprint
exit 0

View file

@ -0,0 +1,4 @@
STAGE setup start 2026-10-06T12:21:37Z
RESULT setup: 0.193 s (image id recomputed from the embedded guest, no prover), shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:21:37Z
STAGE verify start 2026-10-06T12:21:37Z
RESULT verify: VERIFIED in 0.010 s; block 58927 shard 0 prover 0x1919191919191919191919191919191919191919 statement 0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958 (want 0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958) image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (ours) succinct receipt 223882 bytes at 2026-10-06T12:21:37Z

View file

@ -0,0 +1,19 @@
0.21 real 0.20 user 0.00 sys
32817152 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
2376 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
0 voluntary context switches
143 involuntary context switches
3181784306 instructions retired
906141388 cycles elapsed
22151552 peak memory footprint
verify 1 exit 0

View file

@ -0,0 +1,4 @@
STAGE setup start 2026-10-06T12:21:37Z
RESULT setup: 0.188 s (image id recomputed from the embedded guest, no prover), shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:21:37Z
STAGE verify start 2026-10-06T12:21:37Z
RESULT verify: VERIFIED in 0.009 s; block 58927 shard 0 prover 0x1919191919191919191919191919191919191919 statement 0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958 (want 0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958) image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (ours) succinct receipt 223882 bytes at 2026-10-06T12:21:37Z

View file

@ -0,0 +1,19 @@
0.21 real 0.20 user 0.00 sys
32735232 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
2371 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
0 voluntary context switches
71 involuntary context switches
3179378641 instructions retired
889872025 cycles elapsed
22102376 peak memory footprint
verify 2 exit 0

View file

@ -0,0 +1,4 @@
STAGE setup start 2026-10-06T12:21:37Z
RESULT setup: 0.188 s (image id recomputed from the embedded guest, no prover), shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:21:38Z
STAGE verify start 2026-10-06T12:21:38Z
RESULT verify: VERIFIED in 0.009 s; block 58927 shard 0 prover 0x1919191919191919191919191919191919191919 statement 0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958 (want 0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958) image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (ours) succinct receipt 223882 bytes at 2026-10-06T12:21:38Z

View file

@ -0,0 +1,19 @@
0.21 real 0.20 user 0.00 sys
32784384 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
2373 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
0 voluntary context switches
82 involuntary context switches
3178994457 instructions retired
887547243 cycles elapsed
22151528 peak memory footprint
verify 3 exit 0

View file

@ -0,0 +1,53 @@
{
"backend": "metal",
"block": 58927,
"block_hash": "0x272a99725fa79fdc631d1ff4b1978a26ad49fb5cf226b558561a35579c836996",
"budget": 7500000,
"compressed_proof_bytes": 223882,
"compressed_prove_seconds": 47.948946833,
"compressed_verify_seconds": 0.00925125,
"consensus_budget": true,
"cycles": 278423,
"daa_score": 0,
"execute_seconds": 0.195876292,
"execute_segments": [
{
"cycles": 278423,
"po2": 19
}
],
"fee_set": "prototype",
"fees_v1_activation_daa": null,
"fixture": "/Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/../../fixtures/block-58927-empty-reward.json",
"image_id": "0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72",
"native_seconds": 0.000116458,
"number": 58927,
"paging_cycles": 118603,
"po2": 20,
"proof_file": "/Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/out-2026-10-06/block-58927-shard-0-r0.bin",
"proof_sha256": "0x97e8ed96a5d99e73074f9e1200d9fe3678b27b72728098b500eeb53fda477400",
"proof_system": 2,
"prover": "0x1919191919191919191919191919191919191919",
"reserved_cycles": 127262,
"risc0_crate_version": "3.0.6",
"seal_bytes": 222668,
"segments": 1,
"setup_seconds": 0.187640292,
"shard_budget": 7500000,
"shard_index": 0,
"shard_pgas": [
0
],
"shard_program_id": "0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72",
"shard_witness_bytes": [
13717
],
"shards": 1,
"statement": "0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958",
"test_cut": false,
"total_cycles": 524288,
"user_cycles": 278423,
"witness_bytes": [
13717
]
}

View file

@ -0,0 +1,15 @@
igneum-prove-r0-host sources 9d1377458bda9488: fixture /Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/../../fixtures/block-58927-empty-reward.json: chain 4463 block 58927 (0x272a99725fa79fdc631d1ff4b1978a26ad49fb5cf226b558561a35579c836996) at DAA score 0, 0 transactions in 0 including blocks, 11 accounts in the pre-state, plan 1 shard(s) at S_p = 7500000 pgas; fee schedule prototype, calibrated v1 from DAA score never: this block meters with prototype (intrinsic 200 pgas, B_p 30000000); proof system 2 (RISC Zero 3.0.6), backend metal (risc0 3.0.6: CPU HAL, the Metal arm is commented out in every circuit), segment po2 20; prover payout 0x1919191919191919191919191919191919191919; 2026-10-06T12:08:21Z
STAGE native start 2026-10-06T12:08:21Z
RESULT native: 0.0001 s, pre 0xea9db302b3b1fe3b859d5fb417408fecefeb06aa43721ed7fdf354975582f2c7 post 0x7886b9cfbbbdfe12509affbd4df83cb317e9708eeb627bd49b575cbfa47999c4 receipts 0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 gas 0 pgas 0 executed 0 skipped 0: MATCHES the fixture's expected values at 2026-10-06T12:08:21Z
RESULT shard 0 native: txs 0..0 (0 executed, 0 skipped), gas 0, pgas 0, witness 2 accounts 0 slots 2 leaves 9 hashes, input 13717 bytes, pre 0xea9db302b3b1fe3b859d5fb417408fecefeb06aa43721ed7fdf354975582f2c7 post 0x7886b9cfbbbdfe12509affbd4df83cb317e9708eeb627bd49b575cbfa47999c4
RESULT plan: 1 shard(s) chain from 0xea9db302b3b1fe3b859d5fb417408fecefeb06aa43721ed7fdf354975582f2c7 to 0x7886b9cfbbbdfe12509affbd4df83cb317e9708eeb627bd49b575cbfa47999c4 and sum to gas 0 pgas 0: the cut equals the block; native aggregation receipts 0x6fcd3e8e97da273711ccefb79abdd246c5663c7d61057f82bae745ceac5dcc75 provers 0xe8a6c07ee13e9afa662a1bf0bf69bae726aa8fdb541308bdd4b63bbc60175f27
RESULT tamper account balance: REJECTED (pre-root 0x61857fe806042480d26d91e9b75ffb347d4b3070f2a2e25300fe8dc493a8b441 is not the node's 0xea9db302b3b1fe3b859d5fb417408fecefeb06aa43721ed7fdf354975582f2c7)
STAGE setup start 2026-10-06T12:08:21Z
RESULT setup: 0.188 s (image id recomputed from the embedded guest), proof system 2 image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:08:21Z
RESULT pinned: setup matches the manifest (pinned guests: shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (3667564 bytes, sha256 0x2be67ce3e5a24010) aggregator id 0x0000000000000000000000000000000000000000000000000000000000000000 (0 bytes), pinned 2026-10-06T11:54:47Z on Darwin MacBook-Pro.local 25.6.0 Darwin Kernel Version 25.6.0: Fri Jul 31 19:19:08 PDT 2026; root:xnu-12377.161.14~5/RELEASE_ARM64_T6050 arm64, RISC Zero 3.0.6 proof system 2)
STAGE execute shard 0 start 2026-10-06T12:08:21Z
RESULT execute shard 0: 278423 user cycles in 1 segment(s) [(19, 278423)] (po2, cycles), 0.20 s at 2026-10-06T12:08:21Z
STAGE compressed shard 0 (succinct receipt, po2 20) start 2026-10-06T12:08:21Z
RESULT compressed shard 0: prove 47.9 s (1 segment(s), total cycles 524288, user cycles 278423, paging 118603, reserved 127262), receipt 223882 bytes (seal 222668 bytes), verify 0.009 s, VERIFIED; statement 0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958 proof sha256 0x97e8ed96a5d99e73074f9e1200d9fe3678b27b72728098b500eeb53fda477400 prover 0x1919191919191919191919191919191919191919 at 2026-10-06T12:09:09Z
proof written to /Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/out-2026-10-06/block-58927-shard-0-r0.bin
results written to /Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/out-2026-10-06/block-58927-empty-reward-metal-po220.json

View file

@ -0,0 +1,19 @@
48.40 real 731.01 user 6.03 sys
8319320064 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
537386 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
1 voluntary context switches
1162295 involuntary context switches
6908899365207 instructions retired
2996016463192 cycles elapsed
8271386912 peak memory footprint
exit 0

View file

@ -0,0 +1,4 @@
STAGE setup start 2026-10-06T12:09:09Z
RESULT setup: 0.190 s (image id recomputed from the embedded guest, no prover), shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:09:09Z
STAGE verify start 2026-10-06T12:09:09Z
RESULT verify: VERIFIED in 0.009 s; block 58927 shard 0 prover 0x1919191919191919191919191919191919191919 statement 0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958 (want 0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958) image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (ours) succinct receipt 223882 bytes at 2026-10-06T12:09:09Z

View file

@ -0,0 +1,19 @@
0.21 real 0.20 user 0.00 sys
32800768 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
2375 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
0 voluntary context switches
224 involuntary context switches
3181491647 instructions retired
892572562 cycles elapsed
22167936 peak memory footprint
verify 1 exit 0

View file

@ -0,0 +1,4 @@
STAGE setup start 2026-10-06T12:09:09Z
RESULT setup: 0.191 s (image id recomputed from the embedded guest, no prover), shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:09:10Z
STAGE verify start 2026-10-06T12:09:10Z
RESULT verify: VERIFIED in 0.010 s; block 58927 shard 0 prover 0x1919191919191919191919191919191919191919 statement 0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958 (want 0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958) image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (ours) succinct receipt 223882 bytes at 2026-10-06T12:09:10Z

View file

@ -0,0 +1,19 @@
0.21 real 0.20 user 0.00 sys
32817152 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
2376 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
0 voluntary context switches
199 involuntary context switches
3180863887 instructions retired
897216803 cycles elapsed
22200704 peak memory footprint
verify 2 exit 0

View file

@ -0,0 +1,4 @@
STAGE setup start 2026-10-06T12:09:10Z
RESULT setup: 0.188 s (image id recomputed from the embedded guest, no prover), shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:09:10Z
STAGE verify start 2026-10-06T12:09:10Z
RESULT verify: VERIFIED in 0.009 s; block 58927 shard 0 prover 0x1919191919191919191919191919191919191919 statement 0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958 (want 0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958) image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (ours) succinct receipt 223882 bytes at 2026-10-06T12:09:10Z

View file

@ -0,0 +1,19 @@
0.21 real 0.20 user 0.00 sys
32784384 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
2374 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
0 voluntary context switches
103 involuntary context switches
3179641154 instructions retired
888784534 cycles elapsed
22118760 peak memory footprint
verify 3 exit 0

View file

@ -0,0 +1,53 @@
{
"backend": "metal",
"block": 58927,
"block_hash": "0x272a99725fa79fdc631d1ff4b1978a26ad49fb5cf226b558561a35579c836996",
"budget": 7500000,
"compressed_proof_bytes": 223882,
"compressed_prove_seconds": 48.974515,
"compressed_verify_seconds": 0.009147667,
"consensus_budget": true,
"cycles": 278423,
"daa_score": 0,
"execute_seconds": 0.197636917,
"execute_segments": [
{
"cycles": 278423,
"po2": 19
}
],
"fee_set": "prototype",
"fees_v1_activation_daa": null,
"fixture": "/Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/../../fixtures/block-58927-empty-reward.json",
"image_id": "0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72",
"native_seconds": 0.000117208,
"number": 58927,
"paging_cycles": 118603,
"po2": 21,
"proof_file": "/Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/out-2026-10-06/block-58927-shard-0-r0.bin",
"proof_sha256": "0xd422ff039289d0807875ce7e32202e9daae5be238636f7ec01c1b19511c3e148",
"proof_system": 2,
"prover": "0x1919191919191919191919191919191919191919",
"reserved_cycles": 127262,
"risc0_crate_version": "3.0.6",
"seal_bytes": 222668,
"segments": 1,
"setup_seconds": 0.188892084,
"shard_budget": 7500000,
"shard_index": 0,
"shard_pgas": [
0
],
"shard_program_id": "0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72",
"shard_witness_bytes": [
13717
],
"shards": 1,
"statement": "0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958",
"test_cut": false,
"total_cycles": 524288,
"user_cycles": 278423,
"witness_bytes": [
13717
]
}

View file

@ -0,0 +1,15 @@
igneum-prove-r0-host sources 9d1377458bda9488: fixture /Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/../../fixtures/block-58927-empty-reward.json: chain 4463 block 58927 (0x272a99725fa79fdc631d1ff4b1978a26ad49fb5cf226b558561a35579c836996) at DAA score 0, 0 transactions in 0 including blocks, 11 accounts in the pre-state, plan 1 shard(s) at S_p = 7500000 pgas; fee schedule prototype, calibrated v1 from DAA score never: this block meters with prototype (intrinsic 200 pgas, B_p 30000000); proof system 2 (RISC Zero 3.0.6), backend metal (risc0 3.0.6: CPU HAL, the Metal arm is commented out in every circuit), segment po2 21; prover payout 0x1919191919191919191919191919191919191919; 2026-10-06T12:31:00Z
STAGE native start 2026-10-06T12:31:00Z
RESULT native: 0.0001 s, pre 0xea9db302b3b1fe3b859d5fb417408fecefeb06aa43721ed7fdf354975582f2c7 post 0x7886b9cfbbbdfe12509affbd4df83cb317e9708eeb627bd49b575cbfa47999c4 receipts 0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 gas 0 pgas 0 executed 0 skipped 0: MATCHES the fixture's expected values at 2026-10-06T12:31:00Z
RESULT shard 0 native: txs 0..0 (0 executed, 0 skipped), gas 0, pgas 0, witness 2 accounts 0 slots 2 leaves 9 hashes, input 13717 bytes, pre 0xea9db302b3b1fe3b859d5fb417408fecefeb06aa43721ed7fdf354975582f2c7 post 0x7886b9cfbbbdfe12509affbd4df83cb317e9708eeb627bd49b575cbfa47999c4
RESULT plan: 1 shard(s) chain from 0xea9db302b3b1fe3b859d5fb417408fecefeb06aa43721ed7fdf354975582f2c7 to 0x7886b9cfbbbdfe12509affbd4df83cb317e9708eeb627bd49b575cbfa47999c4 and sum to gas 0 pgas 0: the cut equals the block; native aggregation receipts 0x6fcd3e8e97da273711ccefb79abdd246c5663c7d61057f82bae745ceac5dcc75 provers 0xe8a6c07ee13e9afa662a1bf0bf69bae726aa8fdb541308bdd4b63bbc60175f27
RESULT tamper account balance: REJECTED (pre-root 0x61857fe806042480d26d91e9b75ffb347d4b3070f2a2e25300fe8dc493a8b441 is not the node's 0xea9db302b3b1fe3b859d5fb417408fecefeb06aa43721ed7fdf354975582f2c7)
STAGE setup start 2026-10-06T12:31:00Z
RESULT setup: 0.189 s (image id recomputed from the embedded guest), proof system 2 image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:31:00Z
RESULT pinned: setup matches the manifest (pinned guests: shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (3667564 bytes, sha256 0x2be67ce3e5a24010) aggregator id 0x0000000000000000000000000000000000000000000000000000000000000000 (0 bytes), pinned 2026-10-06T11:54:47Z on Darwin MacBook-Pro.local 25.6.0 Darwin Kernel Version 25.6.0: Fri Jul 31 19:19:08 PDT 2026; root:xnu-12377.161.14~5/RELEASE_ARM64_T6050 arm64, RISC Zero 3.0.6 proof system 2)
STAGE execute shard 0 start 2026-10-06T12:31:00Z
RESULT execute shard 0: 278423 user cycles in 1 segment(s) [(19, 278423)] (po2, cycles), 0.20 s at 2026-10-06T12:31:00Z
STAGE compressed shard 0 (succinct receipt, po2 21) start 2026-10-06T12:31:00Z
RESULT compressed shard 0: prove 49.0 s (1 segment(s), total cycles 524288, user cycles 278423, paging 118603, reserved 127262), receipt 223882 bytes (seal 222668 bytes), verify 0.009 s, VERIFIED; statement 0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958 proof sha256 0xd422ff039289d0807875ce7e32202e9daae5be238636f7ec01c1b19511c3e148 prover 0x1919191919191919191919191919191919191919 at 2026-10-06T12:31:49Z
proof written to /Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/out-2026-10-06/block-58927-shard-0-r0.bin
results written to /Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/out-2026-10-06/block-58927-empty-reward-metal-po221.json

View file

@ -0,0 +1,19 @@
49.44 real 719.04 user 6.33 sys
8322269184 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
543515 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
5 voluntary context switches
1262652 involuntary context switches
6910031145353 instructions retired
3011724189331 cycles elapsed
8274336032 peak memory footprint
exit 0

View file

@ -0,0 +1,4 @@
STAGE setup start 2026-10-06T12:31:50Z
RESULT setup: 0.189 s (image id recomputed from the embedded guest, no prover), shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:31:50Z
STAGE verify start 2026-10-06T12:31:50Z
RESULT verify: VERIFIED in 0.010 s; block 58927 shard 0 prover 0x1919191919191919191919191919191919191919 statement 0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958 (want 0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958) image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (ours) succinct receipt 223882 bytes at 2026-10-06T12:31:50Z

View file

@ -0,0 +1,19 @@
0.21 real 0.20 user 0.00 sys
32899072 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
2382 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
0 voluntary context switches
154 involuntary context switches
3180242902 instructions retired
892924976 cycles elapsed
22200680 peak memory footprint
verify 1 exit 0

View file

@ -0,0 +1,4 @@
STAGE setup start 2026-10-06T12:31:50Z
RESULT setup: 0.190 s (image id recomputed from the embedded guest, no prover), shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:31:50Z
STAGE verify start 2026-10-06T12:31:50Z
RESULT verify: VERIFIED in 0.009 s; block 58927 shard 0 prover 0x1919191919191919191919191919191919191919 statement 0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958 (want 0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958) image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (ours) succinct receipt 223882 bytes at 2026-10-06T12:31:50Z

View file

@ -0,0 +1,19 @@
0.21 real 0.20 user 0.00 sys
32866304 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
2379 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
0 voluntary context switches
163 involuntary context switches
3181093168 instructions retired
891892824 cycles elapsed
22184296 peak memory footprint
verify 2 exit 0

View file

@ -0,0 +1,4 @@
STAGE setup start 2026-10-06T12:31:50Z
RESULT setup: 0.191 s (image id recomputed from the embedded guest, no prover), shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:31:50Z
STAGE verify start 2026-10-06T12:31:50Z
RESULT verify: VERIFIED in 0.009 s; block 58927 shard 0 prover 0x1919191919191919191919191919191919191919 statement 0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958 (want 0xe1aa970082666180cbb81f6d434da7c0525a7560db9c43b399fab2da22017958) image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (ours) succinct receipt 223882 bytes at 2026-10-06T12:31:50Z

View file

@ -0,0 +1,19 @@
0.21 real 0.20 user 0.00 sys
32931840 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
2383 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
0 voluntary context switches
183 involuntary context switches
3181015452 instructions retired
894146138 cycles elapsed
22233472 peak memory footprint
verify 3 exit 0

View file

@ -0,0 +1,96 @@
{
"backend": "cpu",
"block": 351,
"block_hash": "0x94569ddafb92bf8da9f8c68478184aba50674f64e9880de461b7d64ff4f91248",
"budget": 30000,
"compressed_proof_bytes": 223882,
"compressed_prove_seconds": 585.765148792,
"compressed_verify_seconds": 0.009500791,
"consensus_budget": true,
"cycles": 10049917,
"daa_score": 1105,
"execute_seconds": 0.307009042,
"execute_segments": [
{
"cycles": 845030,
"po2": 20
},
{
"cycles": 894979,
"po2": 20
},
{
"cycles": 1000813,
"po2": 20
},
{
"cycles": 1000813,
"po2": 20
},
{
"cycles": 870778,
"po2": 20
},
{
"cycles": 884222,
"po2": 20
},
{
"cycles": 914126,
"po2": 20
},
{
"cycles": 1001096,
"po2": 20
},
{
"cycles": 1001096,
"po2": 20
},
{
"cycles": 867817,
"po2": 20
},
{
"cycles": 769147,
"po2": 20
}
],
"fee_set": "calibrated v1",
"fees_v1_activation_daa": 800,
"fixture": "/Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/../../fixtures/fees-v1-shards2.json",
"image_id": "0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72",
"native_seconds": 0.006371375,
"number": 351,
"paging_cycles": 1093455,
"po2": 20,
"proof_file": "/Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/out-2026-10-06/block-351-shard-0-r0.bin",
"proof_sha256": "0x324b5d91ea3c51b458b00bf29c27c2362bfa803a08f3762ec04d0b748b59de12",
"proof_system": 2,
"prover": "0x1919191919191919191919191919191919191919",
"reserved_cycles": 390964,
"risc0_crate_version": "3.0.6",
"seal_bytes": 222668,
"segments": 11,
"setup_seconds": 0.198069958,
"shard_budget": 30000,
"shard_index": 0,
"shard_pgas": [
22172,
14762
],
"shard_program_id": "0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72",
"shard_witness_bytes": [
18390,
20355
],
"shards": 2,
"statement": "0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0",
"test_cut": false,
"total_cycles": 11534336,
"user_cycles": 10049917,
"witness_bytes": [
18390,
20355
]
}

View file

@ -0,0 +1,18 @@
igneum-prove-r0-host sources 9d1377458bda9488: fixture /Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/../../fixtures/fees-v1-shards2.json: chain 4463 block 351 (0x94569ddafb92bf8da9f8c68478184aba50674f64e9880de461b7d64ff4f91248) at DAA score 1105, 11 transactions in 1 including blocks, 37 accounts in the pre-state, plan 2 shard(s) at S_p = 30000 pgas; fee schedule prototype, calibrated v1 from DAA score 800: this block meters with calibrated v1 (intrinsic 300 pgas, B_p 120000); proof system 2 (RISC Zero 3.0.6), backend cpu, segment po2 20; prover payout 0x1919191919191919191919191919191919191919; 2026-10-06T12:31:52Z
STAGE native start 2026-10-06T12:31:52Z
RESULT native: 0.0064 s, pre 0xc9843c8c66e433ac2ba754e53ce0fe6b6ea1532d019fbf53ffa8dbc74d486afc post 0x3bebd12b2a83e7412262a36175df979712ebc80c1a22fe40e595de8448ed18b2 receipts 0x8082bda08be11e3bd00837e243e87fb9eb8e3e9d15def7fbd13a4c0480bb5e1b gas 355287 pgas 36934 executed 11 skipped 0: MATCHES the fixture's expected values at 2026-10-06T12:31:52Z
RESULT shard 0 native: txs 0..4 (4 executed, 0 skipped), gas 145786, pgas 22172, witness 9 accounts 1 slots 11 leaves 25 hashes, input 18390 bytes, pre 0xc9843c8c66e433ac2ba754e53ce0fe6b6ea1532d019fbf53ffa8dbc74d486afc post 0x0f5fc23a4d70c9a1053b250097203d9d8fd0ec5cec8abefd12f2f94d5dda08fc
RESULT shard 1 native: txs 4..11 (7 executed, 0 skipped), gas 209501, pgas 14762, witness 15 accounts 3 slots 19 leaves 20 hashes, input 20355 bytes, pre 0x0f5fc23a4d70c9a1053b250097203d9d8fd0ec5cec8abefd12f2f94d5dda08fc post 0x3bebd12b2a83e7412262a36175df979712ebc80c1a22fe40e595de8448ed18b2
RESULT plan: 2 shard(s) chain from 0xc9843c8c66e433ac2ba754e53ce0fe6b6ea1532d019fbf53ffa8dbc74d486afc to 0x3bebd12b2a83e7412262a36175df979712ebc80c1a22fe40e595de8448ed18b2 and sum to gas 355287 pgas 36934: the cut equals the block; native aggregation receipts 0x365372e9cc446b0707c32b951514b961e7622efcb71af2a2325fdc6df9ca93bd provers 0x34f9ea37671801505c040024f1f6d78839adf45b6194f908a5bb61191785d60c
RESULT tamper account balance: REJECTED (pre-root 0xa0f77e1dbae468e0bfdeb192294a2869d172dd70137d27a2415fabe10c7423de is not the node's 0xc9843c8c66e433ac2ba754e53ce0fe6b6ea1532d019fbf53ffa8dbc74d486afc)
RESULT tamper storage or code: REJECTED (the statement cannot be proven)
RESULT tamper dropped account: REJECTED (the statement cannot be proven)
STAGE setup start 2026-10-06T12:31:52Z
RESULT setup: 0.198 s (image id recomputed from the embedded guest), proof system 2 image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:31:52Z
RESULT pinned: setup matches the manifest (pinned guests: shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (3667564 bytes, sha256 0x2be67ce3e5a24010) aggregator id 0x0000000000000000000000000000000000000000000000000000000000000000 (0 bytes), pinned 2026-10-06T11:54:47Z on Darwin MacBook-Pro.local 25.6.0 Darwin Kernel Version 25.6.0: Fri Jul 31 19:19:08 PDT 2026; root:xnu-12377.161.14~5/RELEASE_ARM64_T6050 arm64, RISC Zero 3.0.6 proof system 2)
STAGE execute shard 0 start 2026-10-06T12:31:52Z
RESULT execute shard 0: 10049917 user cycles in 11 segment(s) [(20, 845030), (20, 894979), (20, 1000813), (20, 1000813), (20, 870778), (20, 884222), (20, 914126), (20, 1001096), (20, 1001096), (20, 867817), (20, 769147)] (po2, cycles), 0.31 s at 2026-10-06T12:31:52Z
STAGE compressed shard 0 (succinct receipt, po2 20) start 2026-10-06T12:31:52Z
RESULT compressed shard 0: prove 585.8 s (11 segment(s), total cycles 11534336, user cycles 10049917, paging 1093455, reserved 390964), receipt 223882 bytes (seal 222668 bytes), verify 0.010 s, VERIFIED; statement 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0 proof sha256 0x324b5d91ea3c51b458b00bf29c27c2362bfa803a08f3762ec04d0b748b59de12 prover 0x1919191919191919191919191919191919191919 at 2026-10-06T12:41:38Z
proof written to /Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/out-2026-10-06/block-351-shard-0-r0.bin
results written to /Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/out-2026-10-06/fees-v1-shards2-cpu-po220.json

View file

@ -0,0 +1,19 @@
587.71 real 9004.99 user 61.58 sys
10583965696 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
919145 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
5 voluntary context switches
14927529 involuntary context switches
87396928599390 instructions retired
37486609496932 cycles elapsed
10542112664 peak memory footprint
exit 0

View file

@ -0,0 +1,4 @@
STAGE setup start 2026-10-06T12:41:38Z
RESULT setup: 0.191 s (image id recomputed from the embedded guest, no prover), shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:41:38Z
STAGE verify start 2026-10-06T12:41:38Z
RESULT verify: VERIFIED in 0.012 s; block 351 shard 0 prover 0x1919191919191919191919191919191919191919 statement 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0 (want 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0) image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (ours) succinct receipt 223882 bytes at 2026-10-06T12:41:38Z

View file

@ -0,0 +1,19 @@
0.21 real 0.20 user 0.00 sys
32931840 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
2379 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
0 voluntary context switches
133 involuntary context switches
3180550995 instructions retired
906112055 cycles elapsed
22233472 peak memory footprint
verify 1 exit 0

View file

@ -0,0 +1,4 @@
STAGE setup start 2026-10-06T12:41:39Z
RESULT setup: 0.194 s (image id recomputed from the embedded guest, no prover), shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:41:39Z
STAGE verify start 2026-10-06T12:41:39Z
RESULT verify: VERIFIED in 0.010 s; block 351 shard 0 prover 0x1919191919191919191919191919191919191919 statement 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0 (want 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0) image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (ours) succinct receipt 223882 bytes at 2026-10-06T12:41:39Z

View file

@ -0,0 +1,19 @@
0.21 real 0.20 user 0.00 sys
32931840 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
2381 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
0 voluntary context switches
151 involuntary context switches
3180465471 instructions retired
913518068 cycles elapsed
22282624 peak memory footprint
verify 2 exit 0

View file

@ -0,0 +1,4 @@
STAGE setup start 2026-10-06T12:41:39Z
RESULT setup: 0.191 s (image id recomputed from the embedded guest, no prover), shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:41:39Z
STAGE verify start 2026-10-06T12:41:39Z
RESULT verify: VERIFIED in 0.009 s; block 351 shard 0 prover 0x1919191919191919191919191919191919191919 statement 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0 (want 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0) image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (ours) succinct receipt 223882 bytes at 2026-10-06T12:41:39Z

View file

@ -0,0 +1,19 @@
0.21 real 0.20 user 0.00 sys
32899072 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
2380 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
0 voluntary context switches
269 involuntary context switches
3183131820 instructions retired
892594392 cycles elapsed
22249856 peak memory footprint
verify 3 exit 0

View file

@ -0,0 +1,148 @@
{
"backend": "metal",
"block": 351,
"block_hash": "0x94569ddafb92bf8da9f8c68478184aba50674f64e9880de461b7d64ff4f91248",
"budget": 30000,
"compressed_proof_bytes": 223882,
"compressed_prove_seconds": 698.704864625,
"compressed_verify_seconds": 0.009746125,
"consensus_budget": true,
"cycles": 10049917,
"daa_score": 1105,
"execute_seconds": 0.309079666,
"execute_segments": [
{
"cycles": 387088,
"po2": 19
},
{
"cycles": 386779,
"po2": 19
},
{
"cycles": 385873,
"po2": 19
},
{
"cycles": 446412,
"po2": 19
},
{
"cycles": 476525,
"po2": 19
},
{
"cycles": 476525,
"po2": 19
},
{
"cycles": 476525,
"po2": 19
},
{
"cycles": 476525,
"po2": 19
},
{
"cycles": 476525,
"po2": 19
},
{
"cycles": 440623,
"po2": 19
},
{
"cycles": 356273,
"po2": 19
},
{
"cycles": 375134,
"po2": 19
},
{
"cycles": 436621,
"po2": 19
},
{
"cycles": 393484,
"po2": 19
},
{
"cycles": 476808,
"po2": 19
},
{
"cycles": 476808,
"po2": 19
},
{
"cycles": 476808,
"po2": 19
},
{
"cycles": 476808,
"po2": 19
},
{
"cycles": 476808,
"po2": 19
},
{
"cycles": 476808,
"po2": 19
},
{
"cycles": 349954,
"po2": 19
},
{
"cycles": 462364,
"po2": 19
},
{
"cycles": 340421,
"po2": 19
},
{
"cycles": 45418,
"po2": 17
}
],
"fee_set": "calibrated v1",
"fees_v1_activation_daa": 800,
"fixture": "/Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/../../fixtures/fees-v1-shards2.json",
"image_id": "0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72",
"native_seconds": 0.004128125,
"number": 351,
"paging_cycles": 1442953,
"po2": 19,
"proof_file": "/Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/out-2026-10-06/block-351-shard-0-r0.bin",
"proof_sha256": "0xaae17490df851262141653d38ec9d3d40cca47819ce33061a3409e5433c242d4",
"proof_system": 2,
"prover": "0x1919191919191919191919191919191919191919",
"reserved_cycles": 696826,
"risc0_crate_version": "3.0.6",
"seal_bytes": 222668,
"segments": 24,
"setup_seconds": 0.187895375,
"shard_budget": 30000,
"shard_index": 0,
"shard_pgas": [
22172,
14762
],
"shard_program_id": "0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72",
"shard_witness_bytes": [
18390,
20355
],
"shards": 2,
"statement": "0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0",
"test_cut": false,
"total_cycles": 12189696,
"user_cycles": 10049917,
"witness_bytes": [
18390,
20355
]
}

View file

@ -0,0 +1,18 @@
igneum-prove-r0-host sources 9d1377458bda9488: fixture /Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/../../fixtures/fees-v1-shards2.json: chain 4463 block 351 (0x94569ddafb92bf8da9f8c68478184aba50674f64e9880de461b7d64ff4f91248) at DAA score 1105, 11 transactions in 1 including blocks, 37 accounts in the pre-state, plan 2 shard(s) at S_p = 30000 pgas; fee schedule prototype, calibrated v1 from DAA score 800: this block meters with calibrated v1 (intrinsic 300 pgas, B_p 120000); proof system 2 (RISC Zero 3.0.6), backend metal (risc0 3.0.6: CPU HAL, the Metal arm is commented out in every circuit), segment po2 19; prover payout 0x1919191919191919191919191919191919191919; 2026-10-06T12:09:10Z
STAGE native start 2026-10-06T12:09:10Z
RESULT native: 0.0041 s, pre 0xc9843c8c66e433ac2ba754e53ce0fe6b6ea1532d019fbf53ffa8dbc74d486afc post 0x3bebd12b2a83e7412262a36175df979712ebc80c1a22fe40e595de8448ed18b2 receipts 0x8082bda08be11e3bd00837e243e87fb9eb8e3e9d15def7fbd13a4c0480bb5e1b gas 355287 pgas 36934 executed 11 skipped 0: MATCHES the fixture's expected values at 2026-10-06T12:09:10Z
RESULT shard 0 native: txs 0..4 (4 executed, 0 skipped), gas 145786, pgas 22172, witness 9 accounts 1 slots 11 leaves 25 hashes, input 18390 bytes, pre 0xc9843c8c66e433ac2ba754e53ce0fe6b6ea1532d019fbf53ffa8dbc74d486afc post 0x0f5fc23a4d70c9a1053b250097203d9d8fd0ec5cec8abefd12f2f94d5dda08fc
RESULT shard 1 native: txs 4..11 (7 executed, 0 skipped), gas 209501, pgas 14762, witness 15 accounts 3 slots 19 leaves 20 hashes, input 20355 bytes, pre 0x0f5fc23a4d70c9a1053b250097203d9d8fd0ec5cec8abefd12f2f94d5dda08fc post 0x3bebd12b2a83e7412262a36175df979712ebc80c1a22fe40e595de8448ed18b2
RESULT plan: 2 shard(s) chain from 0xc9843c8c66e433ac2ba754e53ce0fe6b6ea1532d019fbf53ffa8dbc74d486afc to 0x3bebd12b2a83e7412262a36175df979712ebc80c1a22fe40e595de8448ed18b2 and sum to gas 355287 pgas 36934: the cut equals the block; native aggregation receipts 0x365372e9cc446b0707c32b951514b961e7622efcb71af2a2325fdc6df9ca93bd provers 0x34f9ea37671801505c040024f1f6d78839adf45b6194f908a5bb61191785d60c
RESULT tamper account balance: REJECTED (pre-root 0xa0f77e1dbae468e0bfdeb192294a2869d172dd70137d27a2415fabe10c7423de is not the node's 0xc9843c8c66e433ac2ba754e53ce0fe6b6ea1532d019fbf53ffa8dbc74d486afc)
RESULT tamper storage or code: REJECTED (the statement cannot be proven)
RESULT tamper dropped account: REJECTED (the statement cannot be proven)
STAGE setup start 2026-10-06T12:09:10Z
RESULT setup: 0.188 s (image id recomputed from the embedded guest), proof system 2 image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:09:10Z
RESULT pinned: setup matches the manifest (pinned guests: shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (3667564 bytes, sha256 0x2be67ce3e5a24010) aggregator id 0x0000000000000000000000000000000000000000000000000000000000000000 (0 bytes), pinned 2026-10-06T11:54:47Z on Darwin MacBook-Pro.local 25.6.0 Darwin Kernel Version 25.6.0: Fri Jul 31 19:19:08 PDT 2026; root:xnu-12377.161.14~5/RELEASE_ARM64_T6050 arm64, RISC Zero 3.0.6 proof system 2)
STAGE execute shard 0 start 2026-10-06T12:09:10Z
RESULT execute shard 0: 10049917 user cycles in 24 segment(s) [(19, 387088), (19, 386779), (19, 385873), (19, 446412), (19, 476525), (19, 476525), (19, 476525), (19, 476525), (19, 476525), (19, 440623), (19, 356273), (19, 375134), (19, 436621), (19, 393484), (19, 476808), (19, 476808), (19, 476808), (19, 476808), (19, 476808), (19, 476808), (19, 349954), (19, 462364), (19, 340421), (17, 45418)] (po2, cycles), 0.31 s at 2026-10-06T12:09:10Z
STAGE compressed shard 0 (succinct receipt, po2 19) start 2026-10-06T12:09:10Z
RESULT compressed shard 0: prove 698.7 s (24 segment(s), total cycles 12189696, user cycles 10049917, paging 1442953, reserved 696826), receipt 223882 bytes (seal 222668 bytes), verify 0.010 s, VERIFIED; statement 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0 proof sha256 0xaae17490df851262141653d38ec9d3d40cca47819ce33061a3409e5433c242d4 prover 0x1919191919191919191919191919191919191919 at 2026-10-06T12:20:49Z
proof written to /Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/out-2026-10-06/block-351-shard-0-r0.bin
results written to /Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/out-2026-10-06/fees-v1-shards2-metal-po219.json

View file

@ -0,0 +1,19 @@
699.24 real 10764.36 user 84.27 sys
8402812928 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
849283 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
0 voluntary context switches
17450623 involuntary context switches
108532502048478 instructions retired
44590909740103 cycles elapsed
8337201560 peak memory footprint
exit 0

View file

@ -0,0 +1,4 @@
STAGE setup start 2026-10-06T12:20:49Z
RESULT setup: 0.189 s (image id recomputed from the embedded guest, no prover), shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:20:49Z
STAGE verify start 2026-10-06T12:20:49Z
RESULT verify: VERIFIED in 0.009 s; block 351 shard 0 prover 0x1919191919191919191919191919191919191919 statement 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0 (want 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0) image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (ours) succinct receipt 223882 bytes at 2026-10-06T12:20:49Z

View file

@ -0,0 +1,19 @@
0.21 real 0.20 user 0.00 sys
32768000 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
2373 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
0 voluntary context switches
93 involuntary context switches
3179593942 instructions retired
890475022 cycles elapsed
22167936 peak memory footprint
verify 1 exit 0

View file

@ -0,0 +1,4 @@
STAGE setup start 2026-10-06T12:20:49Z
RESULT setup: 0.188 s (image id recomputed from the embedded guest, no prover), shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:20:50Z
STAGE verify start 2026-10-06T12:20:50Z
RESULT verify: VERIFIED in 0.009 s; block 351 shard 0 prover 0x1919191919191919191919191919191919191919 statement 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0 (want 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0) image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (ours) succinct receipt 223882 bytes at 2026-10-06T12:20:50Z

View file

@ -0,0 +1,19 @@
0.21 real 0.20 user 0.00 sys
32800768 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
2375 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
0 voluntary context switches
76 involuntary context switches
3179878158 instructions retired
890703123 cycles elapsed
22184320 peak memory footprint
verify 2 exit 0

View file

@ -0,0 +1,4 @@
STAGE setup start 2026-10-06T12:20:50Z
RESULT setup: 0.187 s (image id recomputed from the embedded guest, no prover), shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:20:50Z
STAGE verify start 2026-10-06T12:20:50Z
RESULT verify: VERIFIED in 0.009 s; block 351 shard 0 prover 0x1919191919191919191919191919191919191919 statement 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0 (want 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0) image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (ours) succinct receipt 223882 bytes at 2026-10-06T12:20:50Z

View file

@ -0,0 +1,19 @@
0.21 real 0.20 user 0.00 sys
32784384 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
2373 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
0 voluntary context switches
58 involuntary context switches
3179475647 instructions retired
889445692 cycles elapsed
22118760 peak memory footprint
verify 3 exit 0

View file

@ -0,0 +1,96 @@
{
"backend": "metal",
"block": 351,
"block_hash": "0x94569ddafb92bf8da9f8c68478184aba50674f64e9880de461b7d64ff4f91248",
"budget": 30000,
"compressed_proof_bytes": 223882,
"compressed_prove_seconds": 574.4259095,
"compressed_verify_seconds": 0.009229875,
"consensus_budget": true,
"cycles": 10049917,
"daa_score": 1105,
"execute_seconds": 0.295685042,
"execute_segments": [
{
"cycles": 845030,
"po2": 20
},
{
"cycles": 894979,
"po2": 20
},
{
"cycles": 1000813,
"po2": 20
},
{
"cycles": 1000813,
"po2": 20
},
{
"cycles": 870778,
"po2": 20
},
{
"cycles": 884222,
"po2": 20
},
{
"cycles": 914126,
"po2": 20
},
{
"cycles": 1001096,
"po2": 20
},
{
"cycles": 1001096,
"po2": 20
},
{
"cycles": 867817,
"po2": 20
},
{
"cycles": 769147,
"po2": 20
}
],
"fee_set": "calibrated v1",
"fees_v1_activation_daa": 800,
"fixture": "/Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/../../fixtures/fees-v1-shards2.json",
"image_id": "0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72",
"native_seconds": 0.0038775,
"number": 351,
"paging_cycles": 1093455,
"po2": 20,
"proof_file": "/Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/out-2026-10-06/block-351-shard-0-r0.bin",
"proof_sha256": "0xeb1b375349cc6101e0d8b22cbd08d2207f1f20740b0b7b2df54c7bd0a9985f7c",
"proof_system": 2,
"prover": "0x1919191919191919191919191919191919191919",
"reserved_cycles": 390964,
"risc0_crate_version": "3.0.6",
"seal_bytes": 222668,
"segments": 11,
"setup_seconds": 0.179734833,
"shard_budget": 30000,
"shard_index": 0,
"shard_pgas": [
22172,
14762
],
"shard_program_id": "0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72",
"shard_witness_bytes": [
18390,
20355
],
"shards": 2,
"statement": "0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0",
"test_cut": false,
"total_cycles": 11534336,
"user_cycles": 10049917,
"witness_bytes": [
18390,
20355
]
}

View file

@ -0,0 +1,18 @@
igneum-prove-r0-host sources 9d1377458bda9488: fixture /Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/../../fixtures/fees-v1-shards2.json: chain 4463 block 351 (0x94569ddafb92bf8da9f8c68478184aba50674f64e9880de461b7d64ff4f91248) at DAA score 1105, 11 transactions in 1 including blocks, 37 accounts in the pre-state, plan 2 shard(s) at S_p = 30000 pgas; fee schedule prototype, calibrated v1 from DAA score 800: this block meters with calibrated v1 (intrinsic 300 pgas, B_p 120000); proof system 2 (RISC Zero 3.0.6), backend metal (risc0 3.0.6: CPU HAL, the Metal arm is commented out in every circuit), segment po2 20; prover payout 0x1919191919191919191919191919191919191919; 2026-10-06T11:58:45Z
STAGE native start 2026-10-06T11:58:45Z
RESULT native: 0.0039 s, pre 0xc9843c8c66e433ac2ba754e53ce0fe6b6ea1532d019fbf53ffa8dbc74d486afc post 0x3bebd12b2a83e7412262a36175df979712ebc80c1a22fe40e595de8448ed18b2 receipts 0x8082bda08be11e3bd00837e243e87fb9eb8e3e9d15def7fbd13a4c0480bb5e1b gas 355287 pgas 36934 executed 11 skipped 0: MATCHES the fixture's expected values at 2026-10-06T11:58:45Z
RESULT shard 0 native: txs 0..4 (4 executed, 0 skipped), gas 145786, pgas 22172, witness 9 accounts 1 slots 11 leaves 25 hashes, input 18390 bytes, pre 0xc9843c8c66e433ac2ba754e53ce0fe6b6ea1532d019fbf53ffa8dbc74d486afc post 0x0f5fc23a4d70c9a1053b250097203d9d8fd0ec5cec8abefd12f2f94d5dda08fc
RESULT shard 1 native: txs 4..11 (7 executed, 0 skipped), gas 209501, pgas 14762, witness 15 accounts 3 slots 19 leaves 20 hashes, input 20355 bytes, pre 0x0f5fc23a4d70c9a1053b250097203d9d8fd0ec5cec8abefd12f2f94d5dda08fc post 0x3bebd12b2a83e7412262a36175df979712ebc80c1a22fe40e595de8448ed18b2
RESULT plan: 2 shard(s) chain from 0xc9843c8c66e433ac2ba754e53ce0fe6b6ea1532d019fbf53ffa8dbc74d486afc to 0x3bebd12b2a83e7412262a36175df979712ebc80c1a22fe40e595de8448ed18b2 and sum to gas 355287 pgas 36934: the cut equals the block; native aggregation receipts 0x365372e9cc446b0707c32b951514b961e7622efcb71af2a2325fdc6df9ca93bd provers 0x34f9ea37671801505c040024f1f6d78839adf45b6194f908a5bb61191785d60c
RESULT tamper account balance: REJECTED (pre-root 0xa0f77e1dbae468e0bfdeb192294a2869d172dd70137d27a2415fabe10c7423de is not the node's 0xc9843c8c66e433ac2ba754e53ce0fe6b6ea1532d019fbf53ffa8dbc74d486afc)
RESULT tamper storage or code: REJECTED (the statement cannot be proven)
RESULT tamper dropped account: REJECTED (the statement cannot be proven)
STAGE setup start 2026-10-06T11:58:45Z
RESULT setup: 0.180 s (image id recomputed from the embedded guest), proof system 2 image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T11:58:45Z
RESULT pinned: setup matches the manifest (pinned guests: shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (3667564 bytes, sha256 0x2be67ce3e5a24010) aggregator id 0x0000000000000000000000000000000000000000000000000000000000000000 (0 bytes), pinned 2026-10-06T11:54:47Z on Darwin MacBook-Pro.local 25.6.0 Darwin Kernel Version 25.6.0: Fri Jul 31 19:19:08 PDT 2026; root:xnu-12377.161.14~5/RELEASE_ARM64_T6050 arm64, RISC Zero 3.0.6 proof system 2)
STAGE execute shard 0 start 2026-10-06T11:58:45Z
RESULT execute shard 0: 10049917 user cycles in 11 segment(s) [(20, 845030), (20, 894979), (20, 1000813), (20, 1000813), (20, 870778), (20, 884222), (20, 914126), (20, 1001096), (20, 1001096), (20, 867817), (20, 769147)] (po2, cycles), 0.30 s at 2026-10-06T11:58:45Z
STAGE compressed shard 0 (succinct receipt, po2 20) start 2026-10-06T11:58:45Z
RESULT compressed shard 0: prove 574.4 s (11 segment(s), total cycles 11534336, user cycles 10049917, paging 1093455, reserved 390964), receipt 223882 bytes (seal 222668 bytes), verify 0.009 s, VERIFIED; statement 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0 proof sha256 0xeb1b375349cc6101e0d8b22cbd08d2207f1f20740b0b7b2df54c7bd0a9985f7c prover 0x1919191919191919191919191919191919191919 at 2026-10-06T12:08:20Z
proof written to /Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/out-2026-10-06/block-351-shard-0-r0.bin
results written to /Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/out-2026-10-06/fees-v1-shards2-metal-po220.json

View file

@ -0,0 +1,19 @@
574.95 real 9035.51 user 57.36 sys
10660036608 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
923759 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
1 voluntary context switches
13342880 involuntary context switches
87378072717456 instructions retired
37413942830420 cycles elapsed
10615103384 peak memory footprint
exit 0

View file

@ -0,0 +1,4 @@
STAGE setup start 2026-10-06T12:08:20Z
RESULT setup: 0.190 s (image id recomputed from the embedded guest, no prover), shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:08:20Z
STAGE verify start 2026-10-06T12:08:20Z
RESULT verify: VERIFIED in 0.009 s; block 351 shard 0 prover 0x1919191919191919191919191919191919191919 statement 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0 (want 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0) image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (ours) succinct receipt 223882 bytes at 2026-10-06T12:08:20Z

View file

@ -0,0 +1,19 @@
0.21 real 0.20 user 0.00 sys
32817152 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
2376 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
0 voluntary context switches
173 involuntary context switches
3182051598 instructions retired
892914822 cycles elapsed
22135168 peak memory footprint
verify 1 exit 0

View file

@ -0,0 +1,4 @@
STAGE setup start 2026-10-06T12:08:20Z
RESULT setup: 0.189 s (image id recomputed from the embedded guest, no prover), shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:08:20Z
STAGE verify start 2026-10-06T12:08:20Z
RESULT verify: VERIFIED in 0.009 s; block 351 shard 0 prover 0x1919191919191919191919191919191919191919 statement 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0 (want 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0) image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (ours) succinct receipt 223882 bytes at 2026-10-06T12:08:20Z

View file

@ -0,0 +1,19 @@
0.21 real 0.20 user 0.00 sys
32768000 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
2373 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
0 voluntary context switches
128 involuntary context switches
3180411429 instructions retired
894125292 cycles elapsed
22135168 peak memory footprint
verify 2 exit 0

View file

@ -0,0 +1,4 @@
STAGE setup start 2026-10-06T12:08:20Z
RESULT setup: 0.188 s (image id recomputed from the embedded guest, no prover), shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:08:21Z
STAGE verify start 2026-10-06T12:08:21Z
RESULT verify: VERIFIED in 0.009 s; block 351 shard 0 prover 0x1919191919191919191919191919191919191919 statement 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0 (want 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0) image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (ours) succinct receipt 223882 bytes at 2026-10-06T12:08:21Z

View file

@ -0,0 +1,19 @@
0.21 real 0.20 user 0.00 sys
32784384 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
2374 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
0 voluntary context switches
87 involuntary context switches
3179308350 instructions retired
889726379 cycles elapsed
22151528 peak memory footprint
verify 3 exit 0

View file

@ -0,0 +1,76 @@
{
"backend": "metal",
"block": 351,
"block_hash": "0x94569ddafb92bf8da9f8c68478184aba50674f64e9880de461b7d64ff4f91248",
"budget": 30000,
"compressed_proof_bytes": 223882,
"compressed_prove_seconds": 560.90603875,
"compressed_verify_seconds": 0.009724542,
"consensus_budget": true,
"cycles": 10049917,
"daa_score": 1105,
"execute_seconds": 0.308031958,
"execute_segments": [
{
"cycles": 1819410,
"po2": 21
},
{
"cycles": 2049389,
"po2": 21
},
{
"cycles": 1882565,
"po2": 21
},
{
"cycles": 1990545,
"po2": 21
},
{
"cycles": 1913659,
"po2": 21
},
{
"cycles": 394349,
"po2": 20
}
],
"fee_set": "calibrated v1",
"fees_v1_activation_daa": 800,
"fixture": "/Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/../../fixtures/fees-v1-shards2.json",
"image_id": "0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72",
"native_seconds": 0.004194333,
"number": 351,
"paging_cycles": 854857,
"po2": 21,
"proof_file": "/Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/out-2026-10-06/block-351-shard-0-r0.bin",
"proof_sha256": "0x9c523b4670114620e9283b2991e3ee3827368311aa0b3920ed584e1f78c86829",
"proof_system": 2,
"prover": "0x1919191919191919191919191919191919191919",
"reserved_cycles": 629562,
"risc0_crate_version": "3.0.6",
"seal_bytes": 222668,
"segments": 6,
"setup_seconds": 0.188316666,
"shard_budget": 30000,
"shard_index": 0,
"shard_pgas": [
22172,
14762
],
"shard_program_id": "0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72",
"shard_witness_bytes": [
18390,
20355
],
"shards": 2,
"statement": "0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0",
"test_cut": false,
"total_cycles": 11534336,
"user_cycles": 10049917,
"witness_bytes": [
18390,
20355
]
}

View file

@ -0,0 +1,18 @@
igneum-prove-r0-host sources 9d1377458bda9488: fixture /Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/../../fixtures/fees-v1-shards2.json: chain 4463 block 351 (0x94569ddafb92bf8da9f8c68478184aba50674f64e9880de461b7d64ff4f91248) at DAA score 1105, 11 transactions in 1 including blocks, 37 accounts in the pre-state, plan 2 shard(s) at S_p = 30000 pgas; fee schedule prototype, calibrated v1 from DAA score 800: this block meters with calibrated v1 (intrinsic 300 pgas, B_p 120000); proof system 2 (RISC Zero 3.0.6), backend metal (risc0 3.0.6: CPU HAL, the Metal arm is commented out in every circuit), segment po2 21; prover payout 0x1919191919191919191919191919191919191919; 2026-10-06T12:21:38Z
STAGE native start 2026-10-06T12:21:38Z
RESULT native: 0.0042 s, pre 0xc9843c8c66e433ac2ba754e53ce0fe6b6ea1532d019fbf53ffa8dbc74d486afc post 0x3bebd12b2a83e7412262a36175df979712ebc80c1a22fe40e595de8448ed18b2 receipts 0x8082bda08be11e3bd00837e243e87fb9eb8e3e9d15def7fbd13a4c0480bb5e1b gas 355287 pgas 36934 executed 11 skipped 0: MATCHES the fixture's expected values at 2026-10-06T12:21:38Z
RESULT shard 0 native: txs 0..4 (4 executed, 0 skipped), gas 145786, pgas 22172, witness 9 accounts 1 slots 11 leaves 25 hashes, input 18390 bytes, pre 0xc9843c8c66e433ac2ba754e53ce0fe6b6ea1532d019fbf53ffa8dbc74d486afc post 0x0f5fc23a4d70c9a1053b250097203d9d8fd0ec5cec8abefd12f2f94d5dda08fc
RESULT shard 1 native: txs 4..11 (7 executed, 0 skipped), gas 209501, pgas 14762, witness 15 accounts 3 slots 19 leaves 20 hashes, input 20355 bytes, pre 0x0f5fc23a4d70c9a1053b250097203d9d8fd0ec5cec8abefd12f2f94d5dda08fc post 0x3bebd12b2a83e7412262a36175df979712ebc80c1a22fe40e595de8448ed18b2
RESULT plan: 2 shard(s) chain from 0xc9843c8c66e433ac2ba754e53ce0fe6b6ea1532d019fbf53ffa8dbc74d486afc to 0x3bebd12b2a83e7412262a36175df979712ebc80c1a22fe40e595de8448ed18b2 and sum to gas 355287 pgas 36934: the cut equals the block; native aggregation receipts 0x365372e9cc446b0707c32b951514b961e7622efcb71af2a2325fdc6df9ca93bd provers 0x34f9ea37671801505c040024f1f6d78839adf45b6194f908a5bb61191785d60c
RESULT tamper account balance: REJECTED (pre-root 0xa0f77e1dbae468e0bfdeb192294a2869d172dd70137d27a2415fabe10c7423de is not the node's 0xc9843c8c66e433ac2ba754e53ce0fe6b6ea1532d019fbf53ffa8dbc74d486afc)
RESULT tamper storage or code: REJECTED (the statement cannot be proven)
RESULT tamper dropped account: REJECTED (the statement cannot be proven)
STAGE setup start 2026-10-06T12:21:38Z
RESULT setup: 0.188 s (image id recomputed from the embedded guest), proof system 2 image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:21:38Z
RESULT pinned: setup matches the manifest (pinned guests: shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (3667564 bytes, sha256 0x2be67ce3e5a24010) aggregator id 0x0000000000000000000000000000000000000000000000000000000000000000 (0 bytes), pinned 2026-10-06T11:54:47Z on Darwin MacBook-Pro.local 25.6.0 Darwin Kernel Version 25.6.0: Fri Jul 31 19:19:08 PDT 2026; root:xnu-12377.161.14~5/RELEASE_ARM64_T6050 arm64, RISC Zero 3.0.6 proof system 2)
STAGE execute shard 0 start 2026-10-06T12:21:38Z
RESULT execute shard 0: 10049917 user cycles in 6 segment(s) [(21, 1819410), (21, 2049389), (21, 1882565), (21, 1990545), (21, 1913659), (20, 394349)] (po2, cycles), 0.31 s at 2026-10-06T12:21:38Z
STAGE compressed shard 0 (succinct receipt, po2 21) start 2026-10-06T12:21:38Z
RESULT compressed shard 0: prove 560.9 s (6 segment(s), total cycles 11534336, user cycles 10049917, paging 854857, reserved 629562), receipt 223882 bytes (seal 222668 bytes), verify 0.010 s, VERIFIED; statement 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0 proof sha256 0x9c523b4670114620e9283b2991e3ee3827368311aa0b3920ed584e1f78c86829 prover 0x1919191919191919191919191919191919191919 at 2026-10-06T12:30:59Z
proof written to /Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/out-2026-10-06/block-351-shard-0-r0.bin
results written to /Users/joshm/Projects/igneum-wt-proving-v2/proving/igneum-prove-r0/bench/out-2026-10-06/fees-v1-shards2-metal-po221.json

View file

@ -0,0 +1,19 @@
561.46 real 8598.97 user 55.46 sys
20444495872 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
3874449 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
9 voluntary context switches
14075380 involuntary context switches
81049594882103 instructions retired
35926038330023 cycles elapsed
20417870608 peak memory footprint
exit 0

View file

@ -0,0 +1,4 @@
STAGE setup start 2026-10-06T12:30:59Z
RESULT setup: 0.198 s (image id recomputed from the embedded guest, no prover), shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:31:00Z
STAGE verify start 2026-10-06T12:31:00Z
RESULT verify: VERIFIED in 0.010 s; block 351 shard 0 prover 0x1919191919191919191919191919191919191919 statement 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0 (want 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0) image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (ours) succinct receipt 223882 bytes at 2026-10-06T12:31:00Z

View file

@ -0,0 +1,19 @@
0.22 real 0.20 user 0.00 sys
32849920 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
2378 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
0 voluntary context switches
374 involuntary context switches
3182997047 instructions retired
906948193 cycles elapsed
22217088 peak memory footprint
verify 1 exit 0

View file

@ -0,0 +1,4 @@
STAGE setup start 2026-10-06T12:31:00Z
RESULT setup: 0.195 s (image id recomputed from the embedded guest, no prover), shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:31:00Z
STAGE verify start 2026-10-06T12:31:00Z
RESULT verify: VERIFIED in 0.010 s; block 351 shard 0 prover 0x1919191919191919191919191919191919191919 statement 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0 (want 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0) image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (ours) succinct receipt 223882 bytes at 2026-10-06T12:31:00Z

View file

@ -0,0 +1,19 @@
0.21 real 0.20 user 0.00 sys
32882688 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
2377 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
0 voluntary context switches
363 involuntary context switches
3182890769 instructions retired
905927975 cycles elapsed
22233472 peak memory footprint
verify 2 exit 0

View file

@ -0,0 +1,4 @@
STAGE setup start 2026-10-06T12:31:00Z
RESULT setup: 0.189 s (image id recomputed from the embedded guest, no prover), shard program id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 at 2026-10-06T12:31:00Z
STAGE verify start 2026-10-06T12:31:00Z
RESULT verify: VERIFIED in 0.010 s; block 351 shard 0 prover 0x1919191919191919191919191919191919191919 statement 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0 (want 0x6adcc7fab21512b58cfa3778756718fd37aea6cccb311e12d2ca33b5f4bf10c0) image id 0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72 (ours) succinct receipt 223882 bytes at 2026-10-06T12:31:00Z

View file

@ -0,0 +1,19 @@
0.21 real 0.20 user 0.00 sys
32800768 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
2375 page reclaims
0 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
0 voluntary context switches
148 involuntary context switches
3180898962 instructions retired
891079178 cycles elapsed
22167936 peak memory footprint
verify 3 exit 0

Binary file not shown.

View file

@ -0,0 +1,41 @@
{
"build": {
"core_sources": "proving/igneum-prove/core/src/*.rs (sorted, concatenated)",
"core_sources_sha256": "0x2bdc089364126f31ff2e26ee55e1c50faa2177d9c0cdbee5be42d00609cb9e5f",
"docker": false,
"guest_cargo_lock_sha256": "0xc56a9e6a1b4ef697596440ceeb9e0bbe11655fbb63aae7b38c6966612016d6ab",
"guest_cargo_toml_sha256": "0x1cb0a3c02fa429725738d0e1ec09442379c6d4c99542b74348fd91d638148886",
"guest_crate": "igneum-prove-r0-guest (methods/guest, its own workspace and Cargo.lock)",
"guest_sources_sha256": "0xc6c34a98bafdd3c45c1807399657e4bed5843fb9fec14c591df29982bc092a9a",
"note": "built with the rzup toolchain on the pinning machine (no docker); a build on another machine must reproduce this image id or the pin is re-done here",
"patches": [
"k256 = { git = \"https://github.com/risc0/RustCrypto-elliptic-curves\", tag = \"k256/v0.13.4-risczero.1\" }",
"crypto-bigint = { git = \"https://github.com/risc0/RustCrypto-crypto-bigint\", tag = \"v0.5.5-risczero.0\" }",
"tiny-keccak = { git = \"https://github.com/risc0/tiny-keccak\", tag = \"tiny-keccak/v2.0.2-risczero.0\" }",
"sha2 = { git = \"https://github.com/risc0/RustCrypto-hashes\", tag = \"sha2-v0.10.9-risczero.0\" }",
"sha2-011 = { git = \"https://github.com/risc0/RustCrypto-hashes\", tag = \"sha2-v0.11.0-risczero.0\", package = \"sha2\" }"
],
"risc0_build_features": [
"unstable"
],
"risc0_zkvm_guest_features": [
"std",
"unstable"
],
"rzup": "Installed components:; cargo-risczero; * 3.0.6; r0vm; * 3.0.6; rust; * 1.97.0; rzup home: /Users/joshm/.risc0"
},
"format": "igneum-prove-r0-manifest-v1",
"guest": {
"elf": "igneum-prove-r0-guest.bin",
"elf_bytes": 3667564,
"elf_kind": "risc0-build ProgramBinary (user ELF + RISC Zero v1compat kernel); the image id is over this binary",
"elf_sha256": "0x2be67ce3e5a240104156712a127e460378926e8d4f30f277272314a49d70c98f",
"image_id": "0x9ae0f416ee43e9ea8908c555d424fe23e3592677ffc42a763476623d0eb5cf72",
"user_elf_bytes": 3635140,
"user_elf_sha256": "0x89a84da0e4bbf0e859f92944202ab54569fad79e089eca3228af09e1ab8bbb68"
},
"pinned_at": "2026-10-06T11:54:47Z",
"pinned_on": "Darwin MacBook-Pro.local 25.6.0 Darwin Kernel Version 25.6.0: Fri Jul 31 19:19:08 PDT 2026; root:xnu-12377.161.14~5/RELEASE_ARM64_T6050 arm64",
"proof_system": 2,
"risc0_crate_version": "3.0.6"
}

View file

@ -0,0 +1,40 @@
[package]
name = "igneum-prove-r0-host"
description = "RISC Zero host, proof system version 2: loads a block fixture, cuts and witnesses its shards, runs one shard natively, in the executor (cycles) and proves it to a succinct receipt on the CPU, Metal or CUDA; verifies receipts against the pinned image id; the same CLI shape and results keys as the SP1 host"
version.workspace = true
edition.workspace = true
license.workspace = true
[dependencies]
igneum-prove-core.workspace = true
risc0-zkvm = { workspace = true, features = ["prove", "std"] }
alloy-primitives.workspace = true
alloy-trie = { version = "=0.9.8", default-features = false, features = ["std"] }
alloy-rlp = { version = "=0.3.16", default-features = false }
igneum-evm-types = { path = "../../../vendor/igneum-node-exec/igneum/evm-types" }
bincode.workspace = true
serde.workspace = true
serde_json.workspace = true
anyhow.workspace = true
hex.workspace = true
sha2.workspace = true
[[bin]]
name = "igneum-prove-r0-host"
path = "src/main.rs"
[build-dependencies]
sha2.workspace = true
hex.workspace = true
[features]
default = []
# The Metal prover (Apple silicon): the full STARK on the GPU, unified memory.
metal = ["risc0-zkvm/metal"]
# The CUDA prover (NVIDIA, Linux x86_64 or WSL2).
cuda = ["risc0-zkvm/cuda"]
# Does not embed the pinned files, so it builds before elf/ exists.
[[bin]]
name = "igneum-prove-r0-pin"
path = "src/bin/pin.rs"

View file

@ -0,0 +1,27 @@
//! Stamps the host with a hash of the native sources it was built from (`IGNEUM_PROVE_R0_SOURCES`, printed in
//! the host's first line; the stale-build class of 5 October 2026): the SP1 core (`../igneum-prove/core/src`)
//! and `host/src`, the same recipe as proving/igneum-prove/host/build.rs.
use sha2::{Digest, Sha256};
use std::path::Path;
fn main() {
let host = Path::new(env!("CARGO_MANIFEST_DIR"));
let core = host.join("../../igneum-prove/core/src");
let mut files: Vec<std::path::PathBuf> = Vec::new();
for dir in [core, host.join("src")] {
for entry in std::fs::read_dir(&dir).expect("source dir") {
let path = entry.expect("entry").path();
if path.extension().map(|e| e == "rs").unwrap_or(false) {
files.push(path);
}
}
}
files.sort();
let mut h = Sha256::new();
for f in &files {
println!("cargo:rerun-if-changed={}", f.display());
h.update(std::fs::read(f).expect("read source"));
}
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rustc-env=IGNEUM_PROVE_R0_SOURCES={}", &hex::encode(h.finalize())[..16]);
}

View file

@ -0,0 +1,121 @@
//! igneum-prove-r0-pin: turns a fresh guest build into the pinned artefacts the host embeds (host/src/pinned.rs).
//!
//! Usage: igneum-prove-r0-pin [--from <guest program binary>] [--out <elf dir>]
//! default --from: the file named igneum-prove-r0-guest.bin under target/riscv-guest (what
//! `IGNEUM_BUILD_GUESTS=1 cargo build -p igneum-prove-r0-methods` leaves behind: risc0-build's
//! ProgramBinary, the user ELF combined with RISC Zero's v1compat kernel; the image id is computed over
//! this binary, not over the bare user ELF next to it), default --out: elf/.
//!
//! Reads the binary, computes its image id (risc0_zkvm::compute_image_id, the same function the verifier uses),
//! writes elf/igneum-prove-r0-guest.bin and elf/manifest-r0.json with the SHA-256, the image id and the build
//! inputs (crate version, rzup components, the guest's Cargo.lock and sources, the core sources, the patches).
//! This binary does not include the pinned files, so it builds before elf/ exists.
use anyhow::{Context, Result};
use sha2::{Digest, Sha256};
use std::path::{Path, PathBuf};
fn sha256_hex(bytes: &[u8]) -> String {
format!("0x{}", hex::encode(Sha256::digest(bytes)))
}
fn now_utc() -> String {
let secs = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).map(|d| d.as_secs()).unwrap_or(0);
let (h, m, s) = ((secs / 3600) % 24, (secs / 60) % 60, secs % 60);
let z = (secs / 86400) as i64 + 719468;
let era = z.div_euclid(146097);
let doe = z - era * 146097;
let yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
let y = yoe + era * 400;
let doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
let mp = (5 * doy + 2) / 153;
let d = doy - (153 * mp + 2) / 5 + 1;
let mo = if mp < 10 { mp + 3 } else { mp - 9 };
let y = if mo <= 2 { y + 1 } else { y };
format!("{y:04}-{mo:02}-{d:02}T{h:02}:{m:02}:{s:02}Z")
}
fn find_guest(dir: &Path) -> Option<PathBuf> {
let mut hit = None;
for entry in std::fs::read_dir(dir).ok()?.flatten() {
let p = entry.path();
if p.is_dir() {
if let Some(h) = find_guest(&p) {
hit = Some(h);
}
} else if p.file_name().map(|n| n == "igneum-prove-r0-guest.bin").unwrap_or(false) {
hit = Some(p);
}
}
hit
}
/// SHA-256 over the sorted files of a directory with one extension (the IGNEUM_PROVE_SOURCES recipe).
fn dir_hash(dir: &Path, ext: &str) -> String {
let mut files: Vec<PathBuf> = std::fs::read_dir(dir).map(|r| r.flatten().map(|e| e.path()).filter(|p| p.extension().map(|e| e == ext).unwrap_or(false)).collect()).unwrap_or_default();
files.sort();
let mut h = Sha256::new();
for f in &files {
h.update(std::fs::read(f).unwrap_or_default());
}
format!("0x{}", hex::encode(h.finalize()))
}
fn cmd(program: &str, args: &[&str]) -> String {
std::process::Command::new(program).args(args).output().ok().map(|o| String::from_utf8_lossy(&o.stdout).trim().to_string()).unwrap_or_else(|| "unknown".into())
}
fn main() -> Result<()> {
let args: Vec<String> = std::env::args().collect();
let arg = |name: &str| args.iter().position(|a| a == name).and_then(|i| args.get(i + 1)).cloned();
let here = PathBuf::from(env!("CARGO_MANIFEST_DIR")).parent().map(|p| p.to_path_buf()).unwrap_or_default();
let from = match arg("--from") {
Some(p) => PathBuf::from(p),
None => find_guest(&here.join("target/riscv-guest")).context("no igneum-prove-r0-guest.bin under target/riscv-guest (build it first: IGNEUM_BUILD_GUESTS=1 cargo build -p igneum-prove-r0-methods)")?,
};
let out = arg("--out").map(PathBuf::from).unwrap_or_else(|| here.join("elf"));
std::fs::create_dir_all(&out)?;
let elf = std::fs::read(&from).with_context(|| format!("read {}", from.display()))?;
let id = risc0_zkvm::compute_image_id(&elf).map_err(|e| anyhow::anyhow!("compute_image_id: {e}"))?;
let id_hex = format!("0x{}", hex::encode(id.as_bytes()));
std::fs::write(out.join("igneum-prove-r0-guest.bin"), &elf)?;
let user_elf = std::fs::read(from.with_extension("")).ok();
println!("RESULT pin igneum-prove-r0-guest: {} bytes, sha256 {}, image id {id_hex} (from {}; user ELF {} bytes)", elf.len(), sha256_hex(&elf), from.display(), user_elf.as_ref().map(|e| e.len()).unwrap_or(0));
let guest_dir = here.join("methods/guest");
let patches: Vec<String> = std::fs::read_to_string(guest_dir.join("Cargo.toml")).unwrap_or_default().lines().skip_while(|l| !l.starts_with("[patch.crates-io]")).skip(1).take_while(|l| !l.starts_with('[')).filter(|l| l.contains("git = ")).map(|l| l.trim().to_string()).collect();
let rzup_home = std::env::var("HOME").map(|h| format!("{h}/.risc0/bin/rzup")).unwrap_or_else(|_| "rzup".into());
let rzup_show = cmd(&rzup_home, &["show"]).lines().map(|l| l.trim().to_string()).filter(|l| !l.is_empty() && !l.starts_with('-')).collect::<Vec<_>>().join("; ");
let manifest = serde_json::json!({
"format": "igneum-prove-r0-manifest-v1",
"proof_system": 2,
"risc0_crate_version": "3.0.6",
"pinned_at": now_utc(),
"pinned_on": cmd("uname", &["-a"]),
"guest": {
"elf": "igneum-prove-r0-guest.bin",
"elf_kind": "risc0-build ProgramBinary (user ELF + RISC Zero v1compat kernel); the image id is over this binary",
"user_elf_bytes": user_elf.as_ref().map(|e| e.len()).unwrap_or(0),
"user_elf_sha256": user_elf.as_ref().map(|e| sha256_hex(e)).unwrap_or_default(),
"elf_bytes": elf.len(),
"elf_sha256": sha256_hex(&elf),
"image_id": id_hex,
},
"build": {
"guest_crate": "igneum-prove-r0-guest (methods/guest, its own workspace and Cargo.lock)",
"guest_cargo_lock_sha256": sha256_hex(&std::fs::read(guest_dir.join("Cargo.lock")).unwrap_or_default()),
"guest_cargo_toml_sha256": sha256_hex(&std::fs::read(guest_dir.join("Cargo.toml")).unwrap_or_default()),
"guest_sources_sha256": dir_hash(&guest_dir.join("src"), "rs"),
"core_sources_sha256": dir_hash(&here.join("../igneum-prove/core/src"), "rs"),
"core_sources": "proving/igneum-prove/core/src/*.rs (sorted, concatenated)",
"patches": patches,
"risc0_zkvm_guest_features": ["std", "unstable"],
"risc0_build_features": ["unstable"],
"rzup": rzup_show,
"docker": false,
"note": "built with the rzup toolchain on the pinning machine (no docker); a build on another machine must reproduce this image id or the pin is re-done here",
},
});
std::fs::write(out.join("manifest-r0.json"), format!("{}\n", serde_json::to_string_pretty(&manifest)?))?;
println!("RESULT pin: manifest written to {}; rebuild the host so it embeds these files", out.join("manifest-r0.json").display());
Ok(())
}

View file

@ -0,0 +1,478 @@
//! igneum-prove-r0-host: proof system version 2 (RISC Zero 3.0.6) proving one shard of an Igneum chain block
//! fixture, the SAME shard statement bytes as the SP1 host (design 5.1; docs/analysis/proving-methods.md route D).
//!
//! Usage: igneum-prove-r0-host <fixture.json> [--mode native|execute|compressed] [--shard N] [--po2 N]
//! [--budget <test pgas>] [--prover 0x<payout address>] [--out <results.json>]
//! igneum-prove-r0-host --mode verify --proof <file> --statement 0x<keccak of the journal>
//! igneum-prove-r0-host --mode id
//!
//! Modes build on each other, as in the SP1 host. `native` cuts the block into shards at `S_p`, builds every
//! shard's witness, runs every shard statement natively, checks that the shards chain and sum to the block, and
//! shows that a tampered witness fails. `execute` runs every shard guest in the RISC Zero executor (user cycles
//! and segments, no proof). `compressed` proves one shard (the `--shard` index, default 0) to a SUCCINCT receipt
//! (the constant-size STARK, RISC Zero's analogue of SP1's compressed proof), verified against the pinned image
//! id, and writes the receipt and a results JSON with the SP1 host's keys plus `proof_system: 2` and `image_id`.
//! `--po2 N` sets the segment limit (2^N cycles a segment; RISC Zero's default is 20). The backend is a build
//! feature: `cpu` (none), `metal` (macOS; in risc0 3.0.6 every circuit's Metal arm is commented out, so the
//! prover runs its CPU HAL on Apple silicon and the feature only records the intent), `cuda` (NVIDIA).
//! Every stage prints a `STAGE ... start` line and one `RESULT` line with a UTC timestamp (ledger P20).
//!
//! The guest is pinned (`pinned.rs`): the host embeds the ELF and manifest under `elf/`, checks the hash at every
//! start, recomputes the image id in the prove and verify modes. `--mode id` prints the pinned id in the SP1
//! host's wording (the node's parser). `--mode verify` needs no prover: the receipt is verified against the
//! pinned image id and keccak256(journal) is compared with the statement; exit 0 = verified, 3 = not.
mod pinned;
use alloy_primitives::{Address, B256};
use anyhow::{anyhow, bail, Context, Result};
use igneum_prove_core::agg::{self, AggInput};
use igneum_prove_core::shard::{build_shards, shard_statement, BuiltShard, ShardInput, ShardOutput};
use igneum_prove_core::Fixture;
use risc0_zkvm::{default_executor, default_prover, ExecutorEnv, ProverOpts, Receipt};
use sha2::Digest as _;
use std::time::Instant;
pub const RISC0_CRATE_VERSION: &str = "3.0.6";
pub const PROOF_SYSTEM: u64 = 2;
pub const DEFAULT_PO2: u32 = 20;
fn now() -> String {
let secs = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).map(|d| d.as_secs()).unwrap_or(0);
let (h, m, s) = ((secs / 3600) % 24, (secs / 60) % 60, secs % 60);
let z = (secs / 86400) as i64 + 719468;
let era = z.div_euclid(146097);
let doe = z - era * 146097;
let yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
let y = yoe + era * 400;
let doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
let mp = (5 * doy + 2) / 153;
let d = doy - (153 * mp + 2) / 5 + 1;
let mo = if mp < 10 { mp + 3 } else { mp - 9 };
let y = if mo <= 2 { y + 1 } else { y };
format!("{y:04}-{mo:02}-{d:02}T{h:02}:{m:02}:{s:02}Z")
}
fn stage(name: &str) {
println!("STAGE {name} start {}", now());
}
/// The build's backend. `metal` is honest about 3.0.6: no circuit selects the Metal HAL there.
fn backend() -> &'static str {
if cfg!(feature = "cuda") {
"cuda"
} else if cfg!(feature = "metal") {
"metal (risc0 3.0.6: CPU HAL, the Metal arm is commented out in every circuit)"
} else {
"cpu"
}
}
fn backend_key() -> &'static str {
if cfg!(feature = "cuda") {
"cuda"
} else if cfg!(feature = "metal") {
"metal"
} else {
"cpu"
}
}
fn main() -> Result<()> {
let args: Vec<String> = std::env::args().collect();
let arg = |name: &str| args.iter().position(|a| a == name).and_then(|i| args.get(i + 1)).cloned();
let mode = arg("--mode").unwrap_or_else(|| "compressed".into());
let pinned = pinned::Pinned::load()?;
if mode == "id" {
println!("RESULT id: {}", pinned.describe());
return Ok(());
}
if mode == "verify" {
return run_verify(&pinned, &arg("--proof").context("--proof <file>")?, &arg("--statement").context("--statement 0x<keccak of the journal>")?);
}
let prover: Address = arg("--prover").map(|s| s.parse()).transpose()?.unwrap_or_else(|| Address::from_slice(&[0x19; 20]));
let out_path = arg("--out");
let po2: u32 = arg("--po2").map(|s| s.parse()).transpose()?.unwrap_or(DEFAULT_PO2);
let path = args.get(1).filter(|a| !a.starts_with("--")).context("usage: igneum-prove-r0-host <fixture.json> [--mode native|execute|compressed] [--shard N] [--po2 N] [--budget <test pgas>] [--prover 0x..] [--out results.json]; --mode verify --proof <file> --statement 0x..; --mode id")?;
let shard_index: usize = arg("--shard").map(|s| s.parse()).transpose()?.unwrap_or(0);
let test_budget: Option<u64> = arg("--budget").map(|s| s.parse()).transpose()?;
let fixture: Fixture = serde_json::from_str(&std::fs::read_to_string(path).with_context(|| format!("read {path}"))?)?;
if fixture.format != igneum_prove_core::fixture::FORMAT {
bail!("fixture format {} is not {} (regenerate with igneum-prove-export)", fixture.format, igneum_prove_core::fixture::FORMAT);
}
let block = &fixture.block;
let txs: usize = block.blocks.iter().map(|b| b.txs.len()).sum();
let fee_set = block.fees.at(block.env.daa_score);
if let Some(b) = test_budget {
println!("TEST CUT: the block is re-planned at a budget of {b} pgas (the fixture's plan at {} is not compared)", fixture.plan.shard_budget);
}
if test_budget.is_none() && fixture.plan.consensus && fixture.plan.shard_budget != fee_set.shard_proving_gas_budget {
bail!("the fixture's plan says consensus budget {} but the fee set at DAA score {} ({}) has S_p {}; regenerate with igneum-prove-export", fixture.plan.shard_budget, block.env.daa_score, fee_set.name(), fee_set.shard_proving_gas_budget);
}
println!(
"igneum-prove-r0-host sources {}: fixture {path}: chain {} block {} ({}) at DAA score {}, {txs} transactions in {} including blocks, {} accounts in the pre-state, plan {} shard(s) at S_p = {} pgas{}; fee schedule {}: this block meters with {} (intrinsic {} pgas, B_p {}); proof system {PROOF_SYSTEM} (RISC Zero {RISC0_CRATE_VERSION}), backend {}, segment po2 {po2}; prover payout {prover}; {}",
env!("IGNEUM_PROVE_R0_SOURCES"),
block.chain_id,
block.env.number,
block.env.hash,
block.env.daa_score,
block.blocks.len(),
block.pre_state.len(),
fixture.plan.shards.len(),
fixture.plan.shard_budget,
if fixture.plan.consensus { "" } else { " (TEST CUT below the consensus budget)" },
block.fees.describe(),
fee_set.name(),
fee_set.pgas.intrinsic_pgas_per_tx,
fee_set.block_proving_gas_limit,
backend(),
now()
);
let mut results = serde_json::Map::new();
results.insert("fixture".into(), path.clone().into());
results.insert("block".into(), block.env.number.into());
results.insert("prover".into(), backend_key().into());
results.insert("backend".into(), backend_key().into());
results.insert("proof_system".into(), PROOF_SYSTEM.into());
results.insert("risc0_crate_version".into(), RISC0_CRATE_VERSION.into());
results.insert("image_id".into(), pinned.image_id.to_string().into());
results.insert("po2".into(), po2.into());
results.insert("shard_budget".into(), fixture.plan.shard_budget.into());
results.insert("consensus_budget".into(), fixture.plan.consensus.into());
results.insert("daa_score".into(), block.env.daa_score.into());
results.insert("fee_set".into(), fee_set.name().into());
results.insert("fees_v1_activation_daa".into(), if block.fees.v1_activation_daa == u64::MAX { serde_json::Value::Null } else { block.fees.v1_activation_daa.into() });
// 1. Native: the cut, the witnesses, every shard statement, the chain and the sums, against the fixture.
stage("native");
let t = Instant::now();
let budget = test_budget.unwrap_or(fixture.plan.shard_budget);
let (outcome, pre_root, shards) = build_shards(block, budget, prover);
let native_s = t.elapsed().as_secs_f64();
results.insert("budget".into(), budget.into());
results.insert("test_cut".into(), test_budget.is_some().into());
let e = &fixture.expected;
let same = pre_root == e.pre_state_root && outcome.state_root == e.post_state_root && outcome.receipts_root == e.receipts_root && outcome.tx_commitment == e.tx_commitment && outcome.gas_used == e.gas_used && outcome.pgas_used == e.pgas_used;
println!(
"RESULT native: {:.4} s, pre {} post {} receipts {} gas {} pgas {} executed {} skipped {}: {} at {}",
native_s,
pre_root,
outcome.state_root,
outcome.receipts_root,
outcome.gas_used,
outcome.pgas_used,
outcome.executed.len(),
outcome.skipped.len(),
if same { "MATCHES the fixture's expected values" } else { "DIFFERS from the fixture's expected values" },
now()
);
if !same {
bail!("native execution differs from the fixture; regenerate the fixture with igneum-prove-export");
}
if e.node_state_root != e.post_state_root {
bail!("the fixture's node state root differs from its expected post-state root; the exporter must not have produced this file");
}
if test_budget.is_none() && shards.len() != fixture.plan.shards.len() {
bail!("the plan has {} shards here and {} in the fixture", shards.len(), fixture.plan.shards.len());
}
let (mut sum_gas, mut sum_pgas) = (0u64, 0u64);
let mut prev_root = pre_root;
let mut prev_link = igneum_prove_core::Carry::default().link();
for (i, s) in shards.iter().enumerate() {
let o = &s.output;
let (accounts, slots, leaves, hashes) = s.input.witness.stats();
let bytes = bincode::serialize(&s.input)?.len();
if let (None, Some(x)) = (test_budget, fixture.plan.shards.get(i)) {
if o.pre_root != x.pre_root || o.post_root != x.post_root || o.receipts_root != x.receipts_root || o.link_in != x.link_in || o.link_out != x.link_out || o.gas_used != x.gas_used || o.pgas_used != x.pgas_used {
bail!("shard {}: the native statement differs from the fixture's plan", o.shard_index);
}
}
if o.pre_root != prev_root || o.link_in != prev_link {
bail!("shard {}: does not continue the previous shard", o.shard_index);
}
prev_root = o.post_root;
prev_link = o.link_out;
sum_gas += o.gas_used;
sum_pgas += o.pgas_used;
results.entry("shard_witness_bytes").or_insert_with(|| serde_json::Value::Array(Vec::new())).as_array_mut().unwrap().push(serde_json::Value::from(bytes as u64));
println!(
"RESULT shard {} native: txs {}..{} ({} executed, {} skipped), gas {}, pgas {}{}, witness {accounts} accounts {slots} slots {leaves} leaves {hashes} hashes, input {bytes} bytes, pre {} post {}",
o.shard_index,
s.spec.tx_start,
s.spec.tx_end,
o.executed,
o.skipped,
o.gas_used,
o.pgas_used,
if s.spec.over_budget { " (ONE TRANSACTION ABOVE S_p)" } else { "" },
o.pre_root,
o.post_root
);
}
if prev_root != outcome.state_root || sum_gas != outcome.gas_used || sum_pgas != outcome.pgas_used {
bail!("the shards do not chain to the block's post-root or do not sum to its gas and pgas");
}
let native_block = agg::aggregate(&AggInput { shard_vk: [0; 8], shards: shards.iter().map(|s| s.output.to_bytes()).collect(), parent_hash: block.env.parent_hash, prev: None }, &mut |_, _| {});
if native_block.post_root != outcome.state_root || native_block.tx_commitment != outcome.tx_commitment || native_block.gas_used != outcome.gas_used {
bail!("the native aggregation does not reproduce the block");
}
println!("RESULT plan: {} shard(s) chain from {} to {} and sum to gas {} pgas {}: the cut equals the block; native aggregation receipts {} provers {}", shards.len(), pre_root, outcome.state_root, sum_gas, sum_pgas, native_block.receipts, native_block.provers);
results.insert("native_seconds".into(), native_s.into());
results.insert("shards".into(), (shards.len() as u64).into());
results.insert("shard_pgas".into(), shards.iter().map(|s| serde_json::Value::from(s.output.pgas_used)).collect::<Vec<_>>().into());
results.insert("witness_bytes".into(), shards.iter().map(|s| serde_json::Value::from(bincode::serialize(&s.input).map(|b| b.len() as u64).unwrap_or(0))).collect::<Vec<_>>().into());
// 2. Tampered witnesses must fail (the same three cases as the SP1 host).
tamper_checks(&shards[0])?;
if mode == "native" {
return finish(results, out_path);
}
// 3. The pinned guest: the image id recomputed from the embedded ELF must be the manifest's.
stage("setup");
let t = Instant::now();
pinned.check_image_id()?;
let setup_s = t.elapsed().as_secs_f64();
println!("RESULT setup: {setup_s:.3} s (image id recomputed from the embedded guest), proof system {PROOF_SYSTEM} image id {} at {}", pinned.image_id, now());
println!("RESULT pinned: setup matches the manifest ({})", pinned.describe());
results.insert("setup_seconds".into(), setup_s.into());
results.insert("shard_program_id".into(), pinned.image_id.to_string().into());
match mode.as_str() {
"execute" => run_execute(&pinned, &shards, po2, &mut results)?,
"compressed" => run_compressed(&pinned, &shards, shard_index, po2, out_path.as_deref(), &mut results)?,
other => bail!("unknown mode {other}"),
}
finish(results, out_path)
}
fn tamper_checks(shard: &BuiltShard) -> Result<()> {
let quiet = std::panic::take_hook();
std::panic::set_hook(Box::new(|_| {}));
let outcome = |name: &str, input: ShardInput, expect_root: B256| -> Result<()> {
let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| shard_statement(&input)));
let verdict = match &r {
Err(_) => "REJECTED (the statement cannot be proven)".to_string(),
Ok(o) if o.pre_root != expect_root => format!("REJECTED (pre-root {} is not the node's {})", o.pre_root, expect_root),
Ok(_) => "ACCEPTED".to_string(),
};
println!("RESULT tamper {name}: {verdict}");
if verdict.starts_with("ACCEPTED") {
bail!("a tampered witness ({name}) was accepted");
}
Ok(())
};
let expect = shard.output.pre_root;
let mut a = shard.input.clone();
let addresses: Vec<B256> = a.witness.accounts.iter().map(|acc| alloy_primitives::keccak256(acc.address)).collect();
if let Some((_, v)) = a.witness.trie.leaves.iter_mut().find(|(k, _)| addresses.contains(k)) {
let mut acc = <alloy_trie::TrieAccount as alloy_rlp::Decodable>::decode(&mut v.as_ref()).expect("leaf decodes");
acc.balance += alloy_primitives::U256::from(1);
*v = alloy_rlp::encode(acc).into();
}
outcome("account balance", a, expect)?;
let mut b = shard.input.clone();
let mut touched = false;
for acc in b.witness.accounts.iter_mut() {
if let Some((_, v)) = acc.storage.leaves.first_mut() {
let mut bytes = v.to_vec();
let last = bytes.len() - 1;
bytes[last] ^= 0x01;
*v = bytes.into();
touched = true;
break;
}
}
if !touched {
for acc in b.witness.accounts.iter_mut() {
if !acc.code.is_empty() {
let mut bytes = acc.code.to_vec();
bytes[0] ^= 0x01;
acc.code = bytes.into();
touched = true;
break;
}
}
}
if touched {
outcome("storage or code", b, expect)?;
}
let mut c = shard.input.clone();
let victim = c.txs.first().and_then(|t| igneum_evm_types::decode_and_check(&t.raw, c.chain_id).ok()).map(|tx| tx.sender);
if let Some(sender) = victim {
c.witness.accounts.retain(|acc| acc.address != sender);
outcome("dropped account", c, expect)?;
}
std::panic::set_hook(quiet);
Ok(())
}
fn env_for(input: &ShardInput, po2: u32) -> Result<ExecutorEnv<'static>> {
let bytes = bincode::serialize(input)?;
ExecutorEnv::builder().segment_limit_po2(po2).write_frame(&bytes).build().map_err(|e| anyhow!("executor env: {e}"))
}
fn check_shard_output(out: &ShardOutput, native: &ShardOutput) -> Result<()> {
if out != native {
bail!("the guest's journal differs from the native run:\n guest {out:?}\n native {native:?}");
}
Ok(())
}
/// One executor run: the journal (checked against the native statement), the user cycles, the segments.
fn execute_shard(pinned: &pinned::Pinned, s: &BuiltShard, po2: u32) -> Result<(ShardOutput, u64, Vec<(u32, u32)>, f64)> {
let env = env_for(&s.input, po2)?;
let t = Instant::now();
let session = default_executor().execute(env, pinned.elf()).map_err(|e| anyhow!("execute: {e}"))?;
let dt = t.elapsed().as_secs_f64();
let out = ShardOutput::from_bytes(&session.journal.bytes).context("the journal is not a shard statement")?;
check_shard_output(&out, &s.output)?;
if session.journal.bytes != s.output.to_bytes() {
bail!("the journal bytes are not the native statement bytes");
}
let segments: Vec<(u32, u32)> = session.segments.iter().map(|g| (g.po2, g.cycles)).collect();
Ok((out, session.cycles(), segments, dt))
}
fn run_execute(pinned: &pinned::Pinned, shards: &[BuiltShard], po2: u32, results: &mut serde_json::Map<String, serde_json::Value>) -> Result<()> {
let mut cycles_all = Vec::new();
for s in shards {
stage(&format!("execute shard {}", s.output.shard_index));
let (out, cycles, segments, dt) = execute_shard(pinned, s, po2)?;
println!("RESULT execute shard {}: {} user cycles in {} segment(s) {:?} (po2, cycles), {:.2} s, {:.0} cycles per EVM gas, {:.0} cycles per pgas at {}", out.shard_index, cycles, segments.len(), segments, dt, cycles as f64 / out.gas_used.max(1) as f64, cycles as f64 / out.pgas_used.max(1) as f64, now());
cycles_all.push(serde_json::Value::from(cycles));
}
results.insert("shard_cycles".into(), cycles_all.into());
Ok(())
}
/// The prover's mode (spec 7.7 for version 2): execute (the cycle count), then the succinct receipt of one
/// shard, verified against the pinned image id; writes `<out dir>/block-N-shard-i-r0.bin` and records the
/// statement (keccak of the journal, what the proof record carries) and the receipt's SHA-256.
fn run_compressed(pinned: &pinned::Pinned, shards: &[BuiltShard], index: usize, po2: u32, out_dir: Option<&str>, results: &mut serde_json::Map<String, serde_json::Value>) -> Result<()> {
let s = shards.get(index).ok_or_else(|| anyhow!("shard {index} is not in the plan ({} shards)", shards.len()))?;
let i = s.output.shard_index;
results.insert("shard_index".into(), i.into());
stage(&format!("execute shard {i}"));
let (_, cycles, segments, dt) = execute_shard(pinned, s, po2)?;
println!("RESULT execute shard {i}: {cycles} user cycles in {} segment(s) {:?} (po2, cycles), {dt:.2} s at {}", segments.len(), segments, now());
results.insert("cycles".into(), cycles.into());
results.insert("execute_seconds".into(), dt.into());
results.insert("execute_segments".into(), segments.iter().map(|(p, c)| serde_json::json!({"po2": p, "cycles": c})).collect::<Vec<_>>().into());
stage(&format!("compressed shard {i} (succinct receipt, po2 {po2})"));
let env = env_for(&s.input, po2)?;
let t = Instant::now();
let info = default_prover().prove_with_opts(env, pinned.elf(), &ProverOpts::succinct()).map_err(|e| anyhow!("prove: {e}"))?;
let dt = t.elapsed().as_secs_f64();
let receipt = info.receipt;
let stats = info.stats;
let t = Instant::now();
let ok = receipt.verify(pinned.image_digest()).is_ok();
let vdt = t.elapsed().as_secs_f64();
let journal_ok = receipt.journal.bytes == s.output.to_bytes();
let bytes = bincode::serialize(&receipt)?;
let statement = alloy_primitives::keccak256(&receipt.journal.bytes);
let proof_hash: [u8; 32] = sha2::Sha256::digest(&bytes).into();
println!(
"RESULT compressed shard {i}: prove {dt:.1} s ({} segment(s), total cycles {}, user cycles {}, paging {}, reserved {}), receipt {} bytes (seal {} bytes), verify {vdt:.3} s, {}; statement {statement} proof sha256 0x{} prover {} at {}",
stats.segments,
stats.total_cycles,
stats.user_cycles,
stats.paging_cycles,
stats.reserved_cycles,
bytes.len(),
receipt.seal_size(),
if ok && journal_ok { "VERIFIED" } else if ok { "VERIFY FAILED (journal is not the native statement)" } else { "VERIFY FAILED" },
hex::encode(proof_hash),
s.output.prover,
now()
);
if !ok || !journal_ok {
bail!("succinct receipt of shard {i} did not verify");
}
results.insert("compressed_prove_seconds".into(), dt.into());
results.insert("compressed_verify_seconds".into(), vdt.into());
results.insert("compressed_proof_bytes".into(), bytes.len().into());
results.insert("seal_bytes".into(), receipt.seal_size().into());
results.insert("segments".into(), stats.segments.into());
results.insert("total_cycles".into(), stats.total_cycles.into());
results.insert("user_cycles".into(), stats.user_cycles.into());
results.insert("paging_cycles".into(), stats.paging_cycles.into());
results.insert("reserved_cycles".into(), stats.reserved_cycles.into());
results.insert("statement".into(), statement.to_string().into());
results.insert("proof_sha256".into(), format!("0x{}", hex::encode(proof_hash)).into());
results.insert("block_hash".into(), s.input.env.hash.to_string().into());
results.insert("number".into(), s.input.env.number.into());
results.insert("prover".into(), s.output.prover.to_string().into());
let dir = out_dir.and_then(|p| std::path::Path::new(p).parent().map(|d| d.to_path_buf())).unwrap_or_else(|| std::path::PathBuf::from("."));
let file = dir.join(format!("block-{}-shard-{i}-r0.bin", s.input.env.number));
std::fs::write(&file, &bytes)?;
results.insert("proof_file".into(), file.display().to_string().into());
println!("proof written to {}", file.display());
Ok(())
}
/// The image id a receipt claims (the pre-state digest of its claim), printed next to ours so a receipt from a
/// host with another guest build is rejected with the reason in the node log.
fn claimed_image_id(receipt: &Receipt) -> Option<B256> {
use risc0_zkvm::sha::Digestible;
let claim = receipt.claim().ok()?;
let claim = claim.as_value().ok()?;
Some(B256::from_slice(claim.pre.digest().as_bytes()))
}
/// `--mode verify --proof <file> --statement 0x..`: verifies the succinct receipt against the PINNED image id and
/// checks that keccak256 of its journal is the statement. Exit 0 = verified, 3 = not verified.
fn run_verify(pinned: &pinned::Pinned, proof_path: &str, statement: &str) -> Result<()> {
let bytes = std::fs::read(proof_path).with_context(|| format!("read {proof_path}"))?;
let want: B256 = statement.parse().context("statement is not 32 bytes of hex")?;
stage("setup");
let t = Instant::now();
pinned.check_image_id()?;
println!("RESULT setup: {:.3} s (image id recomputed from the embedded guest, no prover), shard program id {} at {}", t.elapsed().as_secs_f64(), pinned.image_id, now());
stage("verify");
let t = Instant::now();
let receipt: Receipt = match bincode::deserialize(&bytes) {
Ok(r) => r,
Err(e) => {
println!("RESULT verify: NOT VERIFIED in {:.3} s; the file is not a bincode RISC Zero receipt ({e}) at {}", t.elapsed().as_secs_f64(), now());
std::process::exit(3)
}
};
let got = alloy_primitives::keccak256(&receipt.journal.bytes);
let output = ShardOutput::from_bytes(&receipt.journal.bytes);
let claimed = claimed_image_id(&receipt);
let same_program = claimed == Some(pinned.image_id);
let crypto_ok = same_program && receipt.verify(pinned.image_digest()).is_ok();
let ok = crypto_ok && got == want && output.is_some();
let dt = t.elapsed().as_secs_f64();
let kind = match &receipt.inner {
risc0_zkvm::InnerReceipt::Succinct(_) => "succinct",
risc0_zkvm::InnerReceipt::Composite(_) => "composite",
risc0_zkvm::InnerReceipt::Groth16(_) => "groth16",
_ => "other",
};
let program = match claimed {
Some(c) if same_program => format!("image id {c} (ours)"),
Some(c) => format!("image id {c} IS NOT OURS {} (the prover runs another guest build)", pinned.image_id),
None => "no claim in the receipt".to_string(),
};
match &output {
Some(o) => println!("RESULT verify: {} in {dt:.3} s; block {} shard {} prover {} statement {got} (want {want}) {program} {kind} receipt {} bytes at {}", if ok { "VERIFIED" } else { "NOT VERIFIED" }, o.number, o.shard_index, o.prover, bytes.len(), now()),
None => println!("RESULT verify: NOT VERIFIED in {dt:.3} s; the journal is not a shard statement; {program} {kind} receipt at {}", now()),
}
if ok {
Ok(())
} else {
std::process::exit(3)
}
}
fn finish(results: serde_json::Map<String, serde_json::Value>, out_path: Option<String>) -> Result<()> {
if let Some(p) = out_path {
std::fs::write(&p, serde_json::to_string_pretty(&serde_json::Value::Object(results))?)?;
println!("results written to {p}");
}
Ok(())
}

View file

@ -0,0 +1,88 @@
//! The pinned guest (6 October 2026, the rule of proving/igneum-prove/host/src/pinned.rs applied to proof system
//! version 2): the host embeds the guest program binary (risc0-build's ProgramBinary: the user ELF with RISC
//! Zero's v1compat kernel, what the image id is computed over) and the manifest committed under elf/, checks the ELF's SHA-256 against
//! the manifest at every start, and in the prove and verify modes recomputes the image id from the ELF and
//! refuses when it is not the manifest's. Changing the guest: pin-guest.sh. Every prover and verifier of version 2
//! moves to a new pin together.
use alloy_primitives::B256;
use anyhow::{bail, Context, Result};
use risc0_zkvm::Digest;
use serde::Deserialize;
use sha2::Digest as _;
pub const GUEST_ELF: &[u8] = include_bytes!("../../elf/igneum-prove-r0-guest.bin");
const MANIFEST: &str = include_str!("../../elf/manifest-r0.json");
#[derive(Deserialize)]
pub struct Manifest {
pub format: String,
pub risc0_crate_version: String,
pub pinned_at: String,
pub pinned_on: String,
pub guest: GuestEntry,
#[serde(default)]
pub build: serde_json::Value,
}
#[derive(Deserialize)]
pub struct GuestEntry {
pub elf: String,
pub elf_bytes: usize,
pub elf_sha256: String,
pub image_id: String,
}
pub struct Pinned {
pub image_id: B256,
pub manifest: Manifest,
}
impl Pinned {
/// Parses the manifest and checks the embedded ELF against it (cheap: one SHA-256).
pub fn load() -> Result<Self> {
let manifest: Manifest = serde_json::from_str(MANIFEST).context("elf/manifest-r0.json")?;
if manifest.format != "igneum-prove-r0-manifest-v1" {
bail!("elf/manifest-r0.json has format {}, this host reads igneum-prove-r0-manifest-v1", manifest.format);
}
let sha = format!("0x{}", hex::encode(sha2::Sha256::digest(GUEST_ELF)));
if sha != manifest.guest.elf_sha256 || GUEST_ELF.len() != manifest.guest.elf_bytes {
bail!("the embedded guest ({} bytes, sha256 {sha}) is not the manifest's ({} bytes, {}): rebuild the host from a clean elf/", GUEST_ELF.len(), manifest.guest.elf_bytes, manifest.guest.elf_sha256);
}
let image_id: B256 = manifest.guest.image_id.parse().context("manifest image_id")?;
Ok(Self { image_id, manifest })
}
pub fn elf(&self) -> &'static [u8] {
GUEST_ELF
}
pub fn image_digest(&self) -> Digest {
Digest::from_bytes(self.image_id.0)
}
/// Recomputes the image id from the embedded ELF (the prove and verify modes) and compares.
pub fn check_image_id(&self) -> Result<()> {
let computed = risc0_zkvm::compute_image_id(GUEST_ELF).map_err(|e| anyhow::anyhow!("compute_image_id: {e}"))?;
let computed = B256::from_slice(computed.as_bytes());
if computed != self.image_id {
bail!("the embedded guest's image id {computed} is not the manifest's {}: this host would make proofs no other node accepts (re-pin with proving/igneum-prove-r0/pin-guest.sh)", self.image_id);
}
Ok(())
}
/// One line in the SP1 host's wording: the node's `parse_program_ids` reads the words after
/// "shard program id " and "aggregator id " (the aggregator id is all zeros until a version 2 aggregator exists).
pub fn describe(&self) -> String {
format!(
"pinned guests: shard program id {} ({} bytes, sha256 {}) aggregator id {} (0 bytes), pinned {} on {}, RISC Zero {} proof system 2",
self.image_id,
GUEST_ELF.len(),
&self.manifest.guest.elf_sha256[..18],
B256::ZERO,
self.manifest.pinned_at,
self.manifest.pinned_on,
self.manifest.risc0_crate_version
)
}
}

View file

@ -0,0 +1,14 @@
[package]
name = "igneum-prove-r0-methods"
description = "Builds the RISC Zero shard guest (methods/guest) when IGNEUM_BUILD_GUESTS=1, for pin-guest.sh; a normal build compiles nothing for the zkVM"
version.workspace = true
edition.workspace = true
license.workspace = true
[build-dependencies]
# `unstable`: the keccak precompile the tiny-keccak patch uses is behind this flag in 3.0.x (precompiles page)
risc0-build = { workspace = true, features = ["unstable"] }
# risc0-build reads the guest list here (the directories under methods/).
[package.metadata.risc0]
methods = ["guest"]

View file

@ -0,0 +1,16 @@
//! Builds the RISC Zero shard guest (methods/guest) with risc0-build when `IGNEUM_BUILD_GUESTS=1`, for
//! pin-guest.sh to turn into the pinned artefacts under elf/ (the same rule as the SP1 workspace: a normal host
//! build compiles nothing for the zkVM and needs no RISC Zero toolchain). Without the variable, methods.rs is a
//! comment and the host embeds elf/ (host/src/pinned.rs).
use std::{collections::HashMap, env, fs, path::PathBuf};
fn main() {
println!("cargo:rerun-if-env-changed=IGNEUM_BUILD_GUESTS");
let out = PathBuf::from(env::var("OUT_DIR").unwrap()).join("methods.rs");
if env::var("IGNEUM_BUILD_GUESTS").map(|v| v == "1").unwrap_or(false) {
let opts = risc0_build::GuestOptions::default();
risc0_build::embed_methods_with_options(HashMap::from([("igneum-prove-r0-guest", opts)]));
} else {
fs::write(&out, "// no guest built here: the host embeds the pinned guest under elf/ (IGNEUM_BUILD_GUESTS=1 builds one for pin-guest.sh)\n").unwrap();
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,33 @@
[package]
name = "igneum-prove-r0-guest"
description = "RISC Zero guest, proof system version 2: proves one shard of an Igneum chain block (design 5.1), the same statement bytes as the SP1 guest"
version = "0.1.0"
edition = "2021"
license = "ISC"
# Its own workspace: built by risc0-build for riscv32im-risc0-zkvm-elf with its own Cargo.lock (committed).
[workspace]
[dependencies]
risc0-zkvm = { version = "=3.0.6", default-features = false, features = ["std", "unstable"] }
igneum-prove-core = { path = "../../../igneum-prove/core" }
bincode = "=1.3.3"
# keccak256 through tiny-keccak so RISC Zero's patched tiny-keccak (the keccak circuit) is the backend; outside the
# zkVM the same crate computes the same bytes, so the statement is the SP1 guest's byte for byte
alloy-primitives = { version = "=1.7.3", default-features = false, features = ["tiny-keccak"] }
# RISC Zero's accelerated crates (https://dev.risczero.com/api/zkvm/precompiles, release-3.0), pinned by tag:
# k256 for the secp256k1 signature recovery (alloy-consensus `k256`), tiny-keccak for keccak256 (alloy-primitives
# `tiny-keccak`, the trie hashing), sha2 for the sha256 precompile (revm-precompile) and k256's hashing, both
# versions the lock resolves (0.10.9 and 0.11.0).
[patch.crates-io]
k256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "k256/v0.13.4-risczero.1" }
# the k256 patch imports `elliptic_curve::bigint::risc0`, which only the patched crypto-bigint has (the ecdsa example)
crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.5-risczero.0" }
tiny-keccak = { git = "https://github.com/risc0/tiny-keccak", tag = "tiny-keccak/v2.0.2-risczero.0" }
sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2-v0.10.9-risczero.0" }
sha2-011 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2-v0.11.0-risczero.0", package = "sha2" }
[profile.release]
lto = "thin"
opt-level = 3

View file

@ -0,0 +1,14 @@
//! The shard guest, proof system version 2 (RISC Zero). Input: bincode of `ShardInput` (one frame). Output
//! (the journal): `ShardOutput` in its fixed byte layout, the same bytes the SP1 guest commits, so a statement is
//! keccak256 of the journal in both families. Everything between is `igneum_prove_core::shard::shard_statement`,
//! the same code the host runs natively first.
use igneum_prove_core::shard::{shard_statement, ShardInput};
use risc0_zkvm::guest::env;
fn main() {
let input: Vec<u8> = env::read_frame();
let input: ShardInput = bincode::deserialize(&input).expect("ShardInput decodes");
let out = shard_statement(&input);
env::commit_slice(&out.to_bytes());
}

View file

@ -0,0 +1,3 @@
//! The guest built by build.rs when `IGNEUM_BUILD_GUESTS=1` (`IGNEUM_PROVE_R0_GUEST_ELF`, `_ID`, `_PATH`); empty
//! otherwise. The host never uses this crate: it embeds the pinned guest under elf/.
include!(concat!(env!("OUT_DIR"), "/methods.rs"));

View file

@ -0,0 +1,471 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "bitflags"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "cc"
version = "1.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362"
dependencies = [
"jobserver",
"libc",
"shlex",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cpufeatures"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
dependencies = [
"libc",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "directories"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d"
dependencies = [
"dirs-sys",
]
[[package]]
name = "dirs-sys"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
dependencies = [
"libc",
"option-ext",
"redox_users",
"windows-sys",
]
[[package]]
name = "either"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "errno"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "fastrand"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
dependencies = [
"cfg-if",
"libc",
"wasi 0.11.0+wasi-snapshot-preview1",
]
[[package]]
name = "getrandom"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0"
dependencies = [
"cfg-if",
"libc",
"r-efi",
"wasi 0.14.2+wasi-0.2.4",
]
[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "jobserver"
version = "0.1.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a"
dependencies = [
"getrandom 0.3.2",
"libc",
]
[[package]]
name = "libc"
version = "0.2.172"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
[[package]]
name = "libredox"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
"bitflags",
"libc",
]
[[package]]
name = "linux-raw-sys"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "option-ext"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "proc-macro2"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "r-efi"
version = "5.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
[[package]]
name = "rayon"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]]
name = "redox_users"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b"
dependencies = [
"getrandom 0.2.16",
"libredox",
"thiserror",
]
[[package]]
name = "risc0-build-kernel"
version = "2.0.1"
dependencies = [
"cc",
"directories",
"hex",
"rayon",
"sha2",
"tempfile",
]
[[package]]
name = "rustix"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "sha2"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "syn"
version = "2.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tempfile"
version = "3.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1"
dependencies = [
"fastrand",
"getrandom 0.3.2",
"once_cell",
"rustix",
"windows-sys",
]
[[package]]
name = "thiserror"
version = "2.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "typenum"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasi"
version = "0.14.2+wasi-0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
dependencies = [
"wit-bindgen-rt",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "wit-bindgen-rt"
version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
dependencies = [
"bitflags",
]

View file

@ -0,0 +1,49 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2021"
name = "risc0-build-kernel"
version = "2.0.1"
build = false
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "RISC Zero tool for building kernels"
homepage = "https://risczero.com/"
readme = false
license = "Apache-2.0"
repository = "https://github.com/risc0/risc0/"
[lib]
name = "risc0_build_kernel"
path = "src/lib.rs"
[dependencies.cc]
version = "1.2.2"
features = ["parallel"]
[dependencies.directories]
version = "6.0.0"
[dependencies.hex]
version = "0.4"
[dependencies.rayon]
version = "1.10"
[dependencies.sha2]
version = "0.10"
[dependencies.tempfile]
version = "3.12"

View file

@ -0,0 +1,225 @@
// Copyright 2024 RISC Zero, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
/// \file
/// Defines the core finite field data type, Fp, and some free functions on the type.
#include <metal_stdlib>
/// The Fp class is an element of the finite field F_p, where P is the prime number 15*2^27 + 1.
/// Put another way, Fp is basically integer arithmetic modulo P.
///
/// The 'Fp' datatype is the core type of all of the operations done within the zero knowledge
/// proofs, and is smallest 'addressable' datatype, and the base type of which all composite types
/// are built. In many ways, one can imagine it as the word size of a very strange architecture.
///
/// This specific prime P was chosen to:
/// - Be less than 2^31 so that it fits within a 32 bit word and doesn't overflow on addition.
/// - Otherwise have as large a power of 2 in the factors of P-1 as possible.
///
/// This last property is useful for number theoretical transforms (the fast fourier transform
/// equivalent on finite fields). See NTT.h for details.
///
/// The Fp class wraps all the standard arithmetic operations to make the finite field elements look
/// basically like ordinary numbers (which they mostly are).
class Fp {
public:
/// The value of P, the modulus of Fp.
static constant uint32_t P = 15 * (uint32_t(1) << 27) + 1;
static constant uint32_t M = 0x88000001;
static constant uint32_t R2 = 1172168163;
static constant uint32_t INVALID = 0xfffffffful;
private:
// The actual value, always < P.
uint32_t val;
// We make 'impls' of the core ops which all the other uses call. This is done to allow for
// tweaking of the implementation later, for example switching to montgomery representation or
// doing inline assembly or some crazy CUDA stuff.
// Add two numbers
static constexpr uint32_t add(uint32_t a, uint32_t b) {
uint32_t r = a + b;
return (r >= P ? r - P : r);
}
// Subtract two numbers
static constexpr uint32_t sub(uint32_t a, uint32_t b) {
uint32_t r = a - b;
return (r > P ? r + P : r);
}
// Multiply two numbers
static constexpr uint32_t mul(uint32_t a, uint32_t b) {
uint64_t o64 = uint64_t(a) * uint64_t(b);
uint32_t low = -uint32_t(o64);
uint32_t red = M * low;
o64 += uint64_t(red) * uint64_t(P);
uint32_t ret = o64 >> 32;
return (ret >= P ? ret - P : ret);
}
// Encode / Decode
static constexpr uint32_t encode(uint32_t a) { return mul(R2, a); }
static constexpr uint32_t decode(uint32_t a) { return mul(1, a); }
// A private constructor that take the 'internal' form.
constexpr Fp(uint32_t val, bool ignore) : val(val) {}
public:
/// Default constructor, sets value to 0.
constexpr Fp() : val(0) {}
/// Construct an FP from a uint32_t, wrap if needed
constexpr Fp(uint32_t val) : val(encode(val)) {}
/// Construct an Fp from an already-encoded raw value
static constexpr Fp fromRaw(uint32_t val) { return Fp(val, true); }
/// Convert to a uint32_t
constexpr uint32_t asUInt32() const { return decode(val); }
constexpr uint32_t asUInt32() device const { return decode(val); }
/// Return the raw underlying word
constexpr uint32_t asRaw() const { return val; }
/// Get the largest value, basically P - 1.
static constexpr Fp maxVal() { return P - 1; }
/// Get an 'invalid' Fp value
static constexpr Fp invalid() { return Fp(INVALID, true); }
constexpr inline Fp zeroize() {
if (val == INVALID) {
val = 0;
}
return *this;
}
// Implement all the various overloads
constexpr void operator=(uint32_t rhs) { val = encode(rhs); }
constexpr void operator=(uint32_t rhs) device { val = encode(rhs); }
constexpr Fp operator+(Fp rhs) const { return Fp(add(val, rhs.val), true); }
constexpr Fp operator-() const { return Fp(sub(0, val), true); }
constexpr Fp operator-(Fp rhs) const { return Fp(sub(val, rhs.val), true); }
constexpr Fp operator*(Fp rhs) const { return Fp(mul(val, rhs.val), true); }
constexpr Fp operator+(Fp rhs) device const { return Fp(add(val, rhs.val), true); }
constexpr Fp operator-() device const { return Fp(sub(0, val), true); }
constexpr Fp operator-(Fp rhs) device const { return Fp(sub(val, rhs.val), true); }
constexpr Fp operator*(Fp rhs) device const { return Fp(mul(val, rhs.val), true); }
constexpr Fp operator+=(Fp rhs) {
val = add(val, rhs.val);
return *this;
}
constexpr Fp operator+=(Fp rhs) device {
val = add(val, rhs.val);
return *this;
}
constexpr Fp operator-=(Fp rhs) {
val = sub(val, rhs.val);
return *this;
}
constexpr Fp operator*=(Fp rhs) {
val = mul(val, rhs.val);
return *this;
}
constexpr bool operator==(Fp rhs) const { return val == rhs.val; }
constexpr bool operator!=(Fp rhs) const { return val != rhs.val; }
constexpr bool operator<(Fp rhs) const { return decode(val) < decode(rhs.val); }
constexpr bool operator<=(Fp rhs) const { return decode(val) <= decode(rhs.val); }
constexpr bool operator>(Fp rhs) const { return decode(val) > decode(rhs.val); }
constexpr bool operator>=(Fp rhs) const { return decode(val) >= decode(rhs.val); }
constexpr bool operator==(Fp rhs) device const { return val == rhs.val; }
constexpr bool operator!=(Fp rhs) device const { return val != rhs.val; }
constexpr bool operator<(Fp rhs) device const { return decode(val) < decode(rhs.val); }
constexpr bool operator<=(Fp rhs) device const { return decode(val) <= decode(rhs.val); }
constexpr bool operator>(Fp rhs) device const { return decode(val) > decode(rhs.val); }
constexpr bool operator>=(Fp rhs) device const { return decode(val) >= decode(rhs.val); }
// Post-inc/dec
constexpr Fp operator++(int) {
Fp r = *this;
val = add(val, encode(1));
return r;
}
constexpr Fp operator--(int) {
Fp r = *this;
val = sub(val, encode(1));
return r;
}
// Pre-inc/dec
constexpr Fp operator++() {
val = add(val, encode(1));
return *this;
}
constexpr Fp operator--() {
val = sub(val, encode(1));
return *this;
}
};
/// Raise a value to a power
constexpr inline Fp pow(Fp x, size_t n) {
Fp tot = 1;
while (n != 0) {
if (n % 2 == 1) {
tot *= x;
}
n = n / 2;
x *= x;
}
return tot;
}
/// Compute the multiplicative inverse of x, or `1/x` in finite field terms. Since `x^(P-1) == 1
/// (mod P)` for any x != 0 (as a consequence of Fermat's little theorem), it follows that `x *
/// x^(P-2) == 1 (mod P)` for x != 0. That is, `x^(P-2)` is the multiplicative inverse of x.
/// Computed this way, the 'inverse' of zero comes out as zero, which is convenient in many cases, so
/// we leave it.
constexpr inline Fp inv(Fp x) {
return pow(x, Fp::P - 2);
}

View file

@ -0,0 +1,224 @@
// Copyright 2024 RISC Zero, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
/// \file
/// Defines FpExt, a finite field F_p^4, based on Fp via the irreducible polynomial x^4 - 11.
#include <metal_stdlib>
#include "fp.h"
// Defines instead of constexpr to appease CUDAs limitations around constants.
// undef'd at the end of this file.
#define BETA Fp(11)
#define NBETA Fp(Fp::P - 11)
/// Instances of FpExt are element of a finite field F_p^4. They are represented as elements of
/// F_p[X] / (X^4 - 11). Basically, this is a 'big' finite field (about 2^128 elements), which is
/// used when the security of various operations depends on the size of the field. It has the field
/// Fp as a subfield, which means operations by the two are compatible, which is important. The
/// irreducible polynomial was chosen to be the simplest possible one, x^4 - B, where 11 is the
/// smallest B which makes the polynomial irreducible.
struct FpExt {
/// The elements of FpExt, elems[0] + elems[1]*X + elems[2]*X^2 + elems[3]*x^4
Fp elems[4];
/// Default constructor makes the zero elements
constexpr FpExt() {}
/// Initialize from uint32_t
explicit constexpr FpExt(uint32_t x) {
elems[0] = x;
elems[1] = 0;
elems[2] = 0;
elems[3] = 0;
}
/// Convert from Fp to FpExt.
explicit constexpr FpExt(Fp x) {
elems[0] = x;
elems[1] = 0;
elems[2] = 0;
elems[3] = 0;
}
/// Explicitly construct an FpExt from parts
constexpr FpExt(Fp a, Fp b, Fp c, Fp d) {
elems[0] = a;
elems[1] = b;
elems[2] = c;
elems[3] = d;
}
constexpr inline FpExt zeroize() {
for (uint32_t i = 0; i < 4; i++) {
elems[i].zeroize();
}
return *this;
}
// Implement the addition/subtraction overloads
constexpr FpExt operator+=(FpExt rhs) {
for (uint32_t i = 0; i < 4; i++) {
elems[i] += rhs.elems[i];
}
return *this;
}
constexpr FpExt operator-=(FpExt rhs) {
for (uint32_t i = 0; i < 4; i++) {
elems[i] -= rhs.elems[i];
}
return *this;
}
constexpr FpExt operator+(FpExt rhs) const {
FpExt result = *this;
result += rhs;
return result;
}
constexpr FpExt operator-(FpExt rhs) const {
FpExt result = *this;
result -= rhs;
return result;
}
constexpr FpExt operator-() const { return FpExt() - *this; }
// Implement the simple multiplication case by the subfield Fp
// Fp * FpExt is done as a free function due to C++'s operator overloading rules.
constexpr FpExt operator*=(Fp rhs) {
for (uint32_t i = 0; i < 4; i++) {
elems[i] *= rhs;
}
return *this;
}
constexpr FpExt operator*(Fp rhs) const {
FpExt result = *this;
result *= rhs;
return result;
}
// Now we get to the interesting case of multiplication. Basically, multiply out the polynomial
// representations, and then reduce module x^4 - B, which means powers >= 4 get shifted back 4 and
// multiplied by -beta. We could write this as a double loops with some if's and hope it gets
// unrolled properly, but it's small enough to just hand write.
constexpr FpExt operator*(FpExt rhs) const {
// Rename the element arrays to something small for readability
#define a elems
#define b rhs.elems
return FpExt(a[0] * b[0] + NBETA * (a[1] * b[3] + a[2] * b[2] + a[3] * b[1]),
a[0] * b[1] + a[1] * b[0] + NBETA * (a[2] * b[3] + a[3] * b[2]),
a[0] * b[2] + a[1] * b[1] + a[2] * b[0] + NBETA * (a[3] * b[3]),
a[0] * b[3] + a[1] * b[2] + a[2] * b[1] + a[3] * b[0]);
#undef a
#undef b
}
constexpr FpExt operator*=(FpExt rhs) {
*this = *this * rhs;
return *this;
}
// Equality
constexpr bool operator==(FpExt rhs) const {
for (uint32_t i = 0; i < 4; i++) {
if (elems[i] != rhs.elems[i]) {
return false;
}
}
return true;
}
constexpr bool operator!=(FpExt rhs) const { return !(*this == rhs); }
constexpr Fp constPart() const { return elems[0]; }
constexpr FpExt operator+=(FpExt rhs) device {
for (uint32_t i = 0; i < 4; i++) {
elems[i] += rhs.elems[i];
}
return *this;
}
constexpr FpExt operator+(FpExt rhs) device const { return FpExt(*this) + rhs; }
constexpr FpExt operator-(FpExt rhs) device const { return FpExt(*this) - rhs; }
constexpr FpExt operator-() device const { return -FpExt(*this); }
constexpr FpExt operator*(FpExt rhs) device const { return FpExt(*this) * rhs; }
constexpr FpExt operator*(Fp rhs) device const { return FpExt(*this) * rhs; }
constexpr bool operator==(FpExt rhs) device const { return FpExt(*this) == rhs; }
constexpr bool operator!=(FpExt rhs) device const { return FpExt(*this) != rhs; }
constexpr Fp constPart() device const { return FpExt(*this).constPart(); }
};
/// Overload for case where LHS is Fp (RHS case is handled as a method)
constexpr inline FpExt operator*(Fp a, FpExt b) {
return b * a;
}
/// Raise an FpExt to a power
constexpr inline FpExt pow(FpExt x, size_t n) {
FpExt tot(1);
while (n != 0) {
if (n % 2 == 1) {
tot *= x;
}
n = n / 2;
x *= x;
}
return tot;
}
/// Compute the multiplicative inverse of an FpExt.
constexpr inline FpExt inv(FpExt in) {
#define a in.elems
// Compute the multiplicative inverse by basically looking at FpExt as a composite field and using
// the same basic methods used to invert complex numbers. We imagine that initially we have a
// numerator of 1, and a denominator of a. i.e out = 1 / a; We set a' to be a with the first and
// third components negated. We then multiply the numerator and the denominator by a', producing
// out = a' / (a * a'). By construction (a * a') has 0's in it's first and third elements. We
// call this number, 'b' and compute it as follows.
Fp b0 = a[0] * a[0] + BETA * (a[1] * (a[3] + a[3]) - a[2] * a[2]);
Fp b2 = a[0] * (a[2] + a[2]) - a[1] * a[1] + BETA * (a[3] * a[3]);
// Now, we make b' by inverting b2. When we multiply both sizes by b', we get out = (a' * b') /
// (b * b'). But by construction b * b' is in fact an element of Fp, call it c.
Fp c = b0 * b0 + BETA * b2 * b2;
// But we can now invert C directly, and multiply by a'*b', out = a'*b'*inv(c)
Fp ic = inv(c);
// Note: if c == 0 (really should only happen if in == 0), our 'safe' version of inverse results
// in ic == 0, and thus out = 0, so we have the same 'safe' behavior for FpExt. Oh, and since we
// want to multiply everything by ic, it's slightly faster to premultiply the two parts of b by ic
// (2 multiplies instead of 4)
b0 *= ic;
b2 *= ic;
return FpExt(a[0] * b0 + BETA * a[2] * b2,
-a[1] * b0 + NBETA * a[3] * b2,
-a[0] * b2 + a[2] * b0,
a[1] * b2 - a[3] * b0);
#undef a
}
#undef BETA
#undef NBETA

View file

@ -0,0 +1,388 @@
// Copyright 2025 RISC Zero, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::{
env, fs,
path::{Path, PathBuf},
process::Command,
};
use rayon::prelude::*;
use sha2::{Digest, Sha256};
use tempfile::tempdir_in;
const METAL_INCS: &[(&str, &str)] = &[
("fp.h", include_str!("../kernels/metal/fp.h")),
("fpext.h", include_str!("../kernels/metal/fpext.h")),
];
#[derive(Eq, PartialEq, Hash)]
#[non_exhaustive]
pub enum KernelType {
Cpp,
Cuda,
Metal,
}
pub struct KernelBuild {
kernel_type: KernelType,
flags: Vec<String>,
files: Vec<PathBuf>,
inc_dirs: Vec<PathBuf>,
deps: Vec<PathBuf>,
}
impl KernelBuild {
pub fn new(kernel_type: KernelType) -> Self {
Self {
kernel_type,
flags: Vec::new(),
files: Vec::new(),
inc_dirs: Vec::new(),
deps: Vec::new(),
}
}
/// Add a directory to the `-I` or include path for headers
pub fn include<P: AsRef<Path>>(&mut self, dir: P) -> &mut KernelBuild {
self.inc_dirs.push(dir.as_ref().to_path_buf());
self
}
/// Add an arbitrary flag to the invocation of the compiler
pub fn flag(&mut self, flag: &str) -> &mut KernelBuild {
self.flags.push(flag.to_string());
self
}
/// Add a file which will be compiled
pub fn file<P: AsRef<Path>>(&mut self, p: P) -> &mut KernelBuild {
self.files.push(p.as_ref().to_path_buf());
self
}
/// Add files which will be compiled
pub fn files<P>(&mut self, p: P) -> &mut KernelBuild
where
P: IntoIterator,
P::Item: AsRef<Path>,
{
for file in p.into_iter() {
self.file(file);
}
self
}
/// Add a file which will be compiled
pub fn file_opt<P: AsRef<Path>>(&mut self, _p: P, _opt: usize) -> &mut KernelBuild {
self
}
/// Add files which will be compiled
pub fn files_opt<P>(&mut self, _p: P, _opt: usize) -> &mut KernelBuild
where
P: IntoIterator,
P::Item: AsRef<Path>,
{
self
}
/// Add a dependency
pub fn dep<P: AsRef<Path>>(&mut self, p: P) -> &mut KernelBuild {
self.deps.push(p.as_ref().to_path_buf());
self
}
/// Add dependencies
pub fn deps<P>(&mut self, p: P) -> &mut KernelBuild
where
P: IntoIterator,
P::Item: AsRef<Path>,
{
for file in p.into_iter() {
self.dep(file);
}
self
}
pub fn compile(&mut self, output: &str) {
println!("cargo:rerun-if-env-changed=RISC0_SKIP_BUILD_KERNELS");
for src in self.files.iter() {
rerun_if_changed(src);
}
for dep in self.deps.iter() {
rerun_if_changed(dep);
}
match &self.kernel_type {
KernelType::Cpp => self.compile_cpp(output),
KernelType::Cuda => self.compile_cuda(output),
KernelType::Metal => self.compile_metal(output),
}
}
fn compile_cpp(&mut self, output: &str) {
if env::var("RISC0_SKIP_BUILD_KERNELS").is_ok() {
return;
}
// It's *highly* recommended to install `sccache` and use this combined with
// `RUSTC_WRAPPER=/path/to/sccache` to speed up rebuilds of C++ kernels
cc::Build::new()
.cpp(true)
.debug(false)
.files(&self.files)
.includes(&self.inc_dirs)
.flag_if_supported("/std:c++17")
.flag_if_supported("-std=c++17")
.flag_if_supported("-fno-var-tracking")
.flag_if_supported("-fno-var-tracking-assignments")
.flag_if_supported("-g0")
.compile(output);
}
fn compile_cuda(&mut self, output: &str) {
println!("cargo:rerun-if-env-changed=NVCC_APPEND_FLAGS");
println!("cargo:rerun-if-env-changed=NVCC_PREPEND_FLAGS");
println!("cargo:rerun-if-env-changed=RISC0_CUDART_LINKAGE");
println!("cargo:rerun-if-env-changed=NVCC_CCBIN");
for inc_dir in self.inc_dirs.iter() {
rerun_if_changed(inc_dir);
}
if env::var("RISC0_SKIP_BUILD_KERNELS").is_ok() {
let out_dir = env::var("OUT_DIR").map(PathBuf::from).unwrap();
let out_path = out_dir.join(format!("lib{output}-skip.a"));
fs::OpenOptions::new()
.create(true)
.truncate(true)
.write(true)
.open(&out_path)
.unwrap();
println!("cargo:{}={}", output, out_path.display());
return;
}
let mut build = cc::Build::new();
for file in self.files.iter() {
build.file(file);
}
for inc in self.inc_dirs.iter() {
build.include(inc);
}
for flag in self.flags.iter() {
build.flag(flag);
}
if env::var_os("NVCC_PREPEND_FLAGS").is_none() && env::var_os("NVCC_APPEND_FLAGS").is_none()
{
build.flag("-arch=native");
}
let cudart = env::var("RISC0_CUDART_LINKAGE").unwrap_or("static".to_string());
build
.cuda(true)
.cudart(&cudart)
.debug(false)
.ccbin(env::var("NVCC_CCBIN").is_err())
.flag("-diag-suppress=177")
.flag("-diag-suppress=2922")
.flag("-Xcudafe")
.flag("--display_error_number")
.flag("-Xcompiler")
.flag("-Wno-missing-braces,-Wno-unused-function")
.compile(output);
}
fn compile_metal(&mut self, output: &str) {
// Igneum (6 October 2026): this Mac has the Command Line Tools and no Xcode, so no `metal` compiler.
// In risc0 3.0.6 no circuit selects the Metal HAL (rv32im, recursion and keccak all have the Metal
// arm commented out in their `cfg_if`), yet risc0-sys builds the zkp Metal kernels on every macOS
// build and risc0-zkp `include_bytes!`s the result. With RISC0_SKIP_METAL_KERNELS set, an EMPTY
// metallib is written instead, so the CPU prover builds; a Metal HAL would fail to load it.
println!("cargo:rerun-if-env-changed=RISC0_SKIP_METAL_KERNELS");
if env::var("RISC0_SKIP_METAL_KERNELS").is_ok() {
let out_dir = env::var("OUT_DIR").map(PathBuf::from).unwrap();
let out_path = out_dir.join(format!("skip-metal-{output}")).with_extension("metallib");
fs::write(&out_path, []).unwrap();
println!("cargo:warning=RISC0_SKIP_METAL_KERNELS: {output} is an empty metallib (no Metal compiler on this machine; the Metal HAL is unused in risc0 3.0.6)");
println!("cargo:{}={}", output, out_path.display());
return;
}
let target = env::var("TARGET").unwrap();
let sdk_name = if target.ends_with("ios") {
"iphoneos"
} else if target.ends_with("ios-sim") {
"iphonesimulator"
} else if target.ends_with("darwin") {
"macosx"
} else {
panic!("unsupported target: {target}")
};
self.cached_compile(
output,
"metallib",
METAL_INCS,
&[],
&[sdk_name.to_string()],
|out_dir, out_path, sys_inc_dir, _flags| {
let files: Vec<_> = self.files.iter().map(|x| x.as_path()).collect();
let air_paths: Vec<_> = files
.into_par_iter()
.map(|src| {
let air_path = out_dir.join(src).with_extension("").with_extension("air");
if let Some(parent) = air_path.parent() {
fs::create_dir_all(parent).unwrap();
}
let mut cmd = Command::new("xcrun");
cmd.args(["--sdk", sdk_name]);
cmd.arg("metal");
cmd.arg("-o").arg(&air_path);
cmd.arg("-c").arg(src);
cmd.arg("-I").arg(sys_inc_dir);
cmd.arg("-Wno-unused-variable");
for inc_dir in self.inc_dirs.iter() {
cmd.arg("-I").arg(inc_dir);
}
println!("Running: {cmd:?}");
let status = cmd.status().unwrap();
if !status.success() {
panic!("Could not build metal kernels");
}
air_path
})
.collect();
let result = Command::new("xcrun")
.args(["--sdk", sdk_name])
.arg("metallib")
.args(air_paths)
.arg("-o")
.arg(out_path)
.status()
.unwrap();
if !result.success() {
panic!("Could not build metal kernels");
}
},
);
}
fn cached_compile<F: Fn(&Path, &Path, &Path, &[String])>(
&self,
output: &str,
extension: &str,
assets: &[(&str, &str)],
flags: &[String],
tags: &[String],
inner: F,
) {
let out_dir = env::var("OUT_DIR").map(PathBuf::from).unwrap();
if env::var("RISC0_SKIP_BUILD_KERNELS").is_ok() {
let out_path = out_dir
.join("skip-".to_string() + output)
.with_extension(extension);
fs::OpenOptions::new()
.create(true)
.truncate(true)
.write(true)
.open(&out_path)
.unwrap();
println!("cargo:{}={}", output, out_path.display());
return;
}
let out_path = out_dir.join(output).with_extension(extension);
let sys_inc_dir = out_dir.join("_sys_");
let cache_dir = risc0_cache();
if !cache_dir.is_dir() {
fs::create_dir_all(&cache_dir).unwrap();
}
let temp_dir = tempdir_in(&cache_dir).unwrap();
let mut hasher = Hasher::new();
for flag in flags {
hasher.add_flag(flag);
}
for tag in tags {
hasher.add_flag(tag);
}
for src in self.files.iter() {
hasher.add_file(src);
}
for (name, contents) in assets {
let path = sys_inc_dir.join(name);
if let Some(parent) = path.parent() {
fs::create_dir_all(parent).unwrap();
}
fs::write(&path, contents).unwrap();
hasher.add_file(path);
}
for dep in self.deps.iter() {
hasher.add_file(dep);
}
let digest = hasher.finalize();
let cache_path = cache_dir.join(digest).with_extension(extension);
if !cache_path.is_file() {
let tmp_dir = temp_dir.path();
let tmp_path = tmp_dir.join(output).with_extension(extension);
inner(tmp_dir, &tmp_path, &sys_inc_dir, flags);
fs::rename(tmp_path, &cache_path).unwrap();
}
fs::copy(cache_path, &out_path).unwrap();
println!("cargo:{}={}", output, out_path.display());
}
}
fn risc0_cache() -> PathBuf {
directories::ProjectDirs::from("com.risczero", "RISC Zero", "risc0")
.unwrap()
.cache_dir()
.into()
}
struct Hasher {
sha: Sha256,
}
impl Hasher {
pub fn new() -> Self {
Self { sha: Sha256::new() }
}
pub fn add_flag(&mut self, flag: &str) {
self.sha.update(flag);
}
pub fn add_file<P: AsRef<Path>>(&mut self, path: P) {
let bytes = fs::read(path).unwrap();
self.sha.update(bytes);
}
pub fn finalize(self) -> String {
hex::encode(self.sha.finalize())
}
}
fn rerun_if_changed<P: AsRef<Path>>(path: P) {
println!("cargo:rerun-if-changed={}", path.as_ref().display());
}

View file

@ -0,0 +1,22 @@
#!/usr/bin/env bash
# Re-pins the RISC Zero shard guest (proof system version 2): builds the guest from methods/guest with risc0-build
# (the rzup toolchain), computes its image id, writes proving/igneum-prove-r0/elf/ (the ELF and manifest-r0.json),
# rebuilds the host so it embeds them, prints `--mode id`. Every version 2 prover and verifier must then move to a
# host built from the new elf/ together. Run on the Mac through the build lock. Usage: proving/igneum-prove-r0/pin-guest.sh
# Host features: on a Mac `metal`; set HOST_FEATURES to override (e.g. cuda on PC 2).
set -euo pipefail
HERE="$(cd "$(dirname "$0")" && pwd)"
LOCK="$HERE/../../tools/lock/with-lock.sh"; [ -x "$LOCK" ] || LOCK=/Users/joshm/Projects/igneum/tools/lock/with-lock.sh
export PATH="$HOME/.cargo/bin:$HOME/.risc0/bin:$PATH"
cd "$HERE"
# No `metal` compiler (Command Line Tools only): the host build writes an empty metallib (patches/risc0-build-kernel).
if [ "$(uname)" = Darwin ] && ! xcrun --sdk macosx --find metal >/dev/null 2>&1; then export RISC0_SKIP_METAL_KERNELS=1; fi
FEATURES="${HOST_FEATURES:-}"; if [ -z "$FEATURES" ] && [ "$(uname)" = Darwin ]; then FEATURES=metal; fi
echo "1/4 building the guest (IGNEUM_BUILD_GUESTS=1, risc0-build) and the pin tool"
"$LOCK" build env IGNEUM_BUILD_GUESTS=1 nice -n 19 cargo build --release -j 4 -p igneum-prove-r0-methods -p igneum-prove-r0-host --bin igneum-prove-r0-pin
echo "2/4 pinning"
./target/release/igneum-prove-r0-pin
echo "3/4 rebuilding the host with the pinned files embedded (features: ${FEATURES:-none})"
"$LOCK" build env nice -n 19 cargo build --release -j 4 -p igneum-prove-r0-host --bin igneum-prove-r0-host ${FEATURES:+--features "$FEATURES"}
./target/release/igneum-prove-r0-host --mode id
echo "4/4 done: commit proving/igneum-prove-r0/elf/ and methods/guest/Cargo.lock with the host change; every version 2 prover and verifier moves together"

View file

@ -193,6 +193,9 @@ fn main() -> Result<()> {
// account nonce 1 (EIP-161), so the registry starts at nonce 1.
db.insert_account(DEVELOPER_REGISTRY_ADDRESS, 1, U256::ZERO, &registry_code, &[]);
// The exec restart (6 October 2026): the node's EVM state restarted empty at chain block R after the bodies
// below its pruning point were gone (`execRestart` in the export); the records below R are header-only, so the
// replay starts at R from the registry-only state (as the node did) and the BLOCKHASH ring starts there too.
// The account dump (0.3.14, 6 October 2026): an export from a node's ring carries the full state after its first
// segment (`preState`); the port seeds from it, checks its root against the node's at that segment and replays
// from the next one. Nothing older is needed, so a snapshot-restored node (thin older records) cuts the same
@ -202,7 +205,7 @@ fn main() -> Result<()> {
let mut db2 = IgneumDb::new();
for row in rows {
let storage: Vec<(U256, U256)> = row["storage"].as_array().map(|a| a.iter().map(|kv| Ok((kv[0].as_str().context("slot")?.parse()?, kv[1].as_str().context("value")?.parse()?))).collect::<Result<Vec<_>>>()).transpose()?.unwrap_or_default();
db2.insert_account(addr(&row["address"])?, row["nonce"].as_u64().context("nonce")?, u256(&row["balance"])?, &bytes(&row["code"])?, &storage);
db2.insert_account(addr(&row["address"])?, row["nonce"].as_u64().context("nonce")?, u256(&row["balance"])?, &bytes(&row["code"])?, &storage);
}
let node_root = b256(&segments[0]["stateRoot"])?;
let our_root = db2.state_root();
@ -216,9 +219,6 @@ fn main() -> Result<()> {
bail!("block {want} is not above the dump's block {}; export from one block below the wanted block", segments[0]["number"]);
}
}
// The exec restart (6 October 2026): the node's EVM state restarted empty at chain block R after the bodies
// below its pruning point were gone (`execRestart` in the export); the records below R are header-only, so a
// replay without a dump starts at R from the registry-only state (as the node did).
let restart = u64_of(&export["execRestart"]["number"])?.unwrap_or(0);
if restart > 0 && first_index == 0 {
println!("exec restart: the node's state restarted empty at chain block {restart}; the replay starts there, segments below are header-only");
@ -226,7 +226,6 @@ fn main() -> Result<()> {
bail!("block {want} lies below the exec restart at chain block {restart}: no state and no bodies exist for it");
}
}
let mut hashes: Vec<(u64, B256)> = Vec::new();
let mut fixture: Option<Fixture> = None;
let mut checked = 0usize;
@ -332,7 +331,7 @@ fn main() -> Result<()> {
if db.state_root() != final_root {
bail!("final state root {} differs from the export's {final_root}", db.state_root());
}
println!("replayed {checked} segments{}; every state root equals the node's; final root {final_root}", if first_index > 0 { " from the account dump" } else if restart > 0 { " from the exec restart" } else { " from genesis" });
println!("replayed {checked} segments from {}; every state root equals the node's; final root {final_root}", if restart > 0 { format!("the exec restart at chain block {restart}") } else { "genesis".to_string() });
let fixture = fixture.with_context(|| format!("block {want} is not in the export (0 to {})", segments.len() - 1))?;
let json = serde_json::to_string_pretty(&fixture)?;
std::fs::write(out_path, &json)?;