|
| 1 | +# Repro: privacy-prove fails on virtual OS PIE that uses keccak builtin |
| 2 | + |
| 3 | +This branch carries an `#[ignore]`-gated integration test that demonstrates a |
| 4 | +deterministic proving failure in `privacy-prove` when the inner task (a Starknet |
| 5 | +virtual OS run) contains keccak builtin usage by a user contract. |
| 6 | + |
| 7 | +The keccak **syscall** in the virtual OS is **not** the cause — that path proves |
| 8 | +fine. The failure is triggered by the keccak **builtin** appearing in the OS PIE. |
| 9 | + |
| 10 | +## Test |
| 11 | + |
| 12 | +`crates/starknet_os_flow_tests/src/virtual_os_test.rs::prove_and_verify_keccak_tx` |
| 13 | + |
| 14 | +It invokes `test_contract::test_keccak`, which exercises both the keccak builtin |
| 15 | +(`keccak::keccak_u256s_le_inputs`) and the keccak syscall (failure path with an |
| 16 | +invalid length). |
| 17 | + |
| 18 | +## How to run |
| 19 | + |
| 20 | +Requires the project's Python venv (for the Cairo 0 compiler) and the |
| 21 | +nightly Rust toolchain that the prover crate needs. |
| 22 | + |
| 23 | +```bash |
| 24 | +# From the repo root: |
| 25 | +source sequencer_venv/bin/activate |
| 26 | + |
| 27 | +cargo +nightly-2025-07-14 test \ |
| 28 | + -p starknet_os_flow_tests \ |
| 29 | + --features starknet_transaction_prover/stwo_proving \ |
| 30 | + --release \ |
| 31 | + prove_and_verify_keccak_tx \ |
| 32 | + -- --ignored --nocapture |
| 33 | +``` |
| 34 | + |
| 35 | +First run cold-builds the workspace in release mode (~5 min on a fast |
| 36 | +machine); subsequent runs are fast. The test itself runs the OS, proves, and |
| 37 | +verifies in ~40 s once built. |
| 38 | + |
| 39 | +## Observed failure |
| 40 | + |
| 41 | +``` |
| 42 | +thread 'virtual_os_test::prove_and_verify_keccak_tx' panicked at |
| 43 | +crates/starknet_os_flow_tests/src/virtual_os_test_manager.rs:42:53: |
| 44 | +Proving virtual OS should not fail.: |
| 45 | +ProvingError(ProverExecution( |
| 46 | + ".../simple_bootloader/execute_task.cairo:209:5: Error at pc=0:615: |
| 47 | + Got an exception while executing a hint: Hint Error: |
| 48 | + Error while relocating Cairo PIE memory: Memory addresses must be relocatable |
| 49 | + Cairo traceback (most recent call last): |
| 50 | + <start>:3:1: (pc=0:2) |
| 51 | + .../simple_bootloader/privacy_simple_bootloader.cairo:109:5: (pc=0:1116) |
| 52 | + .../simple_bootloader/run_simple_bootloader.cairo:114:9: (pc=0:727) |
| 53 | + .../simple_bootloader/run_simple_bootloader.cairo:199:5: (pc=0:782)" |
| 54 | +)) |
| 55 | +``` |
| 56 | + |
| 57 | +OS execution succeeds — the failure is strictly in the proving step. |
| 58 | + |
| 59 | +## Suspected root cause |
| 60 | + |
| 61 | +1. `privacy_prove::consts::CAIRO_RUN_CONFIG` (`crates/privacy_prove/src/consts.rs` |
| 62 | + in `proving-utils` rev `580135e`) selects `LayoutName::stwo_no_ecop`. |
| 63 | +2. `BuiltinsInstanceDef::stwo_no_ecop()` in `cairo-vm-3.2.0` returns |
| 64 | + `keccak: None, ecdsa: None, ec_op: None`. |
| 65 | +3. The privacy bootloader's `simple_bootloader_simulate_keccak` hint installs an |
| 66 | + auto-deduction-rule-based simulated keccak segment, but the relocation logic |
| 67 | + in |
| 68 | + `cairo-program-runner-lib::hints::load_cairo_pie::build_cairo_pie_relocation_table` |
| 69 | + reads `cairo_pie_execution_segment[idx]` for each declared builtin and |
| 70 | + `extract_segment`s a relocatable from it. When the inner OS PIE has actually |
| 71 | + exercised keccak (so the keccak builtin segment in the PIE is non-empty), the |
| 72 | + value found at that cell is a felt (Int), not a relocatable, and |
| 73 | + `extract_segment` returns `MemoryError::AddressNotRelocatable`. |
| 74 | + |
| 75 | +## Isolation experiment (already verified locally) |
| 76 | + |
| 77 | +Comment out the keccak BUILTIN call inside |
| 78 | +`crates/blockifier_test_utils/resources/feature_contracts/cairo1/test_contract.cairo::test_keccak` |
| 79 | +(the `keccak::keccak_u256s_le_inputs(...)` block, lines ~642–647 on this branch), |
| 80 | +leaving only the keccak SYSCALL failure-path call. Re-run the same command — the |
| 81 | +test now proves and verifies cleanly. This confirms the failure is exercised by |
| 82 | +the keccak BUILTIN, not the SYSCALL. |
| 83 | + |
| 84 | +## Baselines that pass |
| 85 | + |
| 86 | +- `cargo +nightly-2025-07-14 test -p starknet_os_flow_tests --features starknet_transaction_prover/stwo_proving --release generate_proof_fixtures -- --ignored` |
| 87 | + (fund-account tx, no syscalls) |
| 88 | +- `prove_and_verify_keccak_tx` modified to call `test_storage_read` instead of |
| 89 | + `test_keccak` (non-keccak syscall) |
| 90 | + |
| 91 | +Both succeed on this branch, confirming the proving path itself works and only |
| 92 | +the keccak BUILTIN trip path is affected. |
0 commit comments