Repository navigation
Tags
Tags
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