8000 Tags · risc0/zirgen · GitHub
[go: up one dir, main page]

Skip to content

Tags

Tags

v3.1.0

Toggle v3.1.0's commit message

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
Require exactly one execution per rv32im trace

The only constraints on an isFirstCycle row were next_state@1 ==
ControlDone and cycle == 0, and every execution ends in ControlDone
padding, so a prover could start a second execution on any later row.
The memory argument keys records by address, timestamp and value only,
so two executions with overlapping cycle numbers could consume each
other's records and skip a guest's input validation.

Fix: add a public value `totalCycles` and require, on every first-cycle
row, that the (circularly) preceding row has cycle number
totalCycles - 1. That alone still admits two executions of exactly N/2
rows each, so every verifier of the seal must also check
totalCycles == 2^po2: the lift_rv32im_v2[_povw]_<po2> programs do it in
readReceiptClaimAndPovwNonce (po2 is a compile-time constant there),
and the Rust verifier in risc0 does it in its check_code callback.

- top.zir: `global totalCycles`, `cycle@1 = totalCycles - 1` in the
  is_first_cycle arm; protocol string RV32IM:v2rev2___ -> v2rev3___
- predicates.cpp: read termA1high/low and totalCycles, assert against
  1 << po2
- run.cpp / wrap_dsl: set the global in the test harness (actual trace
  length, since the tests use non-power-of-two segment sizes)
- golden_hashes.txt: the 22 lift programs change, nothing else
- BOOTSTRAP.md: document the fix, the pack-zkrs flow that replaced the
  ZKR zip/S3 upload, and two new gotchas (parallel witgen crashes on a
  constraint failure; adding a global changes the seal layout)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DgZM4hzKQyMXxe7RduJiYz
0