test(DON'T MERGE): develop-v2.1.0 - #3013
Draft
shuklaayush wants to merge 199 commits into
Draft
Conversation
makes the basic framework for using rvr extensions in openvm - adds an rvr feature flag - defines `RvrExtensionCtx` struct to provide mappings between opcode/executor/air indices - defines `VmRvrExtension` trait that extensions can implement to be registered - updated macro so that rvr `ExtensionRegistry` can be auto-generated in `SdkVmConfig` closes INT-7474, INT-7475, INT-7479
#2730) Moves the rvr files related to compiling and execution into openvm-circuit. Those rvr files previously depended on openvm-circuit and in order to enable rvr execution through the openvm pipeline, they had to be made a part of openvm-circuit to prevent circular dependencies. closes INT-7537
- Vm execution instance is made to use rvr execution, depending on the feature. Helper functions to convert between the existing `VmState` and the rvr state are also added. - The `VmConfig` macro now has a `create_rvr_extensions` method implementation, but instead of defining a new `VmRvrConfig` trait, the `create_rvr_extensions` method piggybacks on the existing `VmExecutionConfig`. This is to avoid complex feature-gated trait bounds. closes INT-6810, INT-7476
Enables running benchmarks through rvr extension. Benchmark tests do not check execution correctness and currently execution involving extensions other than RV32IM fail because `VmRvrExtension` trait implementation is not properly wired. closes INT-7480
Previously rvr execution had to use `executor_idx_to_air_idx` information in order to construct `ExtensionRegistry`. This was a problem for pure execution which didn't need air indices so the interface diverged between rvr and aot/interpreted. Now for rvr pure execution, dummy index values of `NO_CHIP` are used instead to keep the interface consistent. towards INT-7611
Removes the rvr tests and instead adds rvr comparison steps in existing openvm tests in a similar way to aot. Unlike aot, metered cost execution is also run and compared for rvr and interpreted modes. closes INT-7627
- Introduces a new `Rv32IoExtension` in rvr that handles the rv32io instructions (hint_storew, hint_buffer, reveal). This is mainly to have a struct managing the hint_store chip index. - Adds rvr tests to the CI file in the same way as aot. closes INT-7466
Implements the rvr feature for the keccak256 extension and also adds rvr tests to CI. Now extensions don't take a `staticlib_path` argument manually and instead uses the auto-built staticlib made by a build.rs file. closes INT-7468
Implements the rvr feature for the Algebra extension. The rvr side of the Algebra extension is now also split into `ModularRvrExtension` and `Fp2RvrExtension`. A notable change is to have the C code for the Algebra extension which uses `libsecp256k1` to also unconditionally contain the C code needed in the ECC extension, since they are closely related and doing so would avoid configuration dependencies. closes INT-7470, INT-7704
Implements the rvr feature for all extensions that are left - BigInt, Sha2, ECC, Pairing, Deferral. Code for tests and CI are also updated. Changes for the Deferral extension includes additions to the VM state used in rvr execution. closes INT-7465
closes INT-7821
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Changed rvr execution to use the existing openvm `VmState` instead of defining a new state struct and copying data between the two forms. The references and pointers to the fields in `VmState` are passed to the rvr execution functions so they can be used in C code. - The Deferral extension now uses a callback registration system to expose the Deferral related data to C code instead of piggybacking on the same mechanism of `OpenVmHostCallbacks`. This is enabled for each extension so that they can have per-extension data and state that is maintained separately. closes INT-7572
- Makes rvr metered execution use the existing `SegmentationCtx` of openvm instead of its own new structs and code. This fixes the discrepancy between rvr and interpreted/aot segmentation logic and resolves the issue of rvr making too many segments. (https://github.com/axiom-crypto/openvm-eth/actions/runs/26112543464) - Fixes the calculation of `num_insns` in segments that are used as segment boundaries. The instruction counts were recorded as multiples of `segment_check_insns` (1000) that didn't map to the actual basic block boundaries. Addresses the problem of overflowing GPU memory. (https://github.com/axiom-crypto/openvm-eth/actions/runs/26127167098) closes INT-7835
moves the rvr compilation stage for metered and metered cost out of execution and into instance construction closes INT-7626
closes INT-7648
Air indices are now represented as an enum in rvr code. The `AirIndex` enum has `Uninitialized` and `NoChip` variants that replace the previous `NO_CHIP = u32::MAX`. `AirIndex::Uninitialized` is only used in pure execution where air indices don't matter and causes a panic in rvr metered and metered cost execution. closes INT-7611
…#2807) - **RVR metered execution can now suspend at segment boundaries.** Previously only the interpreter and AOT backends supported segment-by-segment metered runs; RVR ran metered execution straight to termination. This branch adds a parallel `RvrMeteredSegmentInstance` (`RvrMeteredInstanceWith<F, SegmentBoundary>`) whose `execute_metered_until_segment_boundary` returns after the metered segmentation callback creates a segment, mirroring the suspend/resume shape the other two backends already expose. The tracer countdown is carried across calls by checkpointing `tracer.check_counter` into `segmentation_ctx.instrets_until_check` on suspend and restoring it on entry; both values are `try_from`-validated against u32 at the entry point (new `ExecuteError::InvalidMeteredContext`) and the hot C-callback's matching cast is guarded by `debug_assert_eq!`. Mid-segment suspension is out of scope: `initialize_segment_memory` resets the per-segment page-indices checkpoint buffer assuming the page buffers have already been flushed at a segment boundary. - **Generated-C surface reorganized by policy.** Block-begin and suspender helpers move into `c/block/{instret,metered,metered_segment}.h` and `c/suspender/{none,instret_limit,segment_boundary}.h`; tracer headers move under `c/tracer/`. A new `SuspendPolicy` enum drives which pair is included, with `compile_impl` rejecting incoherent combinations (`Metered` × `InstretLimit`, `Pure|MeteredCost` × `SegmentBoundary`) at compile time. Compile-time selection without preprocessor directives in the generated C, per the AGENTS.md guidance. - **`MeteredCtx` round-trip via `MeteredCtxParts`.** `SegmentationState` now carries the full `MemoryCtx` and `suspend_on_segment` flag, so a suspended metered run can be converted back to a `MeteredCtx` (`into_metered_ctx`) and resumed without losing page-tracking or segmentation state. A new test exercises the field-by-field round-trip. - **All RVR codegen inputs embedded at compile time.** Removes every `CARGO_MANIFEST_DIR` runtime dependency from the RVR project-emit pipeline so binaries (Docker images, etc.) no longer need the source tree to invoke `compile_impl`. Core C files (`openvm_io.{c,h}`, `rvr_ext_wrappers.c`) switch from `fs::copy` to `fs::write(include_str!(…))`. Extension `.a` staticlibs migrate from `staticlib_path() -> &Path` to `staticlib_file() -> (&'static str, &'static [u8])` via `include_bytes!(env!("RVR_*_FFI_STATICLIB"))`, with a new `write_extension_staticlibs` helper writing them to the temp project for `make` to link. Modular's libsecp256k1 amalgamation include (~85 `.c`/`.h` files, with test/bench/ctime/valgrind files filtered out) is collected by `extensions/algebra/rvr/build.rs` into a generated `SECP256K1_C_FILES` const and returned via the new `RvrExtension::extra_c_include_files()` hook (for files written but not compiled as their own TUs); `extra_cflags` switches to relative `-Isecp256k1/src` / `-Isecp256k1` against the temp project root. Trait return types are tightened from `&str` to `&'static str`. - **Up-front toolchain detection.** `compile_impl` probes the C compiler, linker, and `make` in PATH before building and reports all missing tools at once via `RuntimeToolchainError`. Adds `RVR_MAKE` override, forwards `HOST_OS` to the Makefile (replacing its `uname -s` shell-out), and threads path context into `CompileError` I/O variants. - **Metrics consolidation.** The four near-identical `Instant::now() … counter!().absolute() … gauge!().set()` blocks across interpreter / AOT / RVR are replaced by a single `ExecutionMetricTimer` helper in `arch::execution_metrics` (guarded against div-by-zero on sub-microsecond runs). A complementary `CompilationTimer` (`arch::compilation_metrics`) wraps every `*_instance` constructor and emits a `compile_{pure,metered,metered_cost,metered_segment}_ms` gauge labeled by backend (`interpreter` / `aot` / `rvr`). - **E1/E2/E3 jargon dropped.** `execute_e1` span/metric names become `execute_pure`; `terminate_execute_e12_*` → `terminate_execute_*`; const generic `E1` → `PURE_EXECUTION`. Comment references to "(E1)/(E2)/(E3)" are removed in favor of "pure/metered/preflight". - **Metric names.** `execute_e1_insns` → `execute_pure_insns`, `execute_e1_insn_mi/s` → `execute_pure_insn_mi/s`. Dashboards or alerting keyed on the old names need to be updated. - **`RvrExtension` trait surface.** `extra_c_source_paths() -> Vec<PathBuf>` → `extra_c_sources() -> Vec<(&'static str, &'static str)>`; `staticlib_path/paths()` → `staticlib_file/files()` returning embedded bytes; new optional `extra_c_include_files()` for files written but not compiled as TUs. Existing impls need a one-time conversion to `include_str!` / `include_bytes!`. - **`ExecutorInventory` generic param renames** (`E1`/`E2`/`E3` → `CombinedE`/`NewE`/`TargetE`) are visible in error messages but compatible. - **`CompileError` shape.** `CProject(io::Error)` → `CProject { path, source }`; `Toolchain(String)` → `Toolchain(#[from] RuntimeToolchainError)`; new `ToolchainCommand { command, source }`. Callers matching on these variants need to update. - **Binary size.** Embedded `.a` staticlibs and libsecp256k1 sources grow the binary by roughly 5–30 MB depending on enabled extensions. resolves int-7917 --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Splits the `GenericSdk::execute_*` methods into `GenericSdk::compile_*` and `GenericSdk::execute_compiled_*` methods for pure, metered and metered cost. This is to be able to reuse the "compiled" instance which, for rvr, takes a long time to create. closes INT-7842
Three correctness fixes in the RVR backend so that its per-segment VM state is byte-identical to the Rust preflight executor's, plus a test-coverage fix that closes the gap that hid all three bugs from `check_rvr_equivalence`. equivalence check` - `check_rvr_equivalence` (and its AOT sibling) only walked AS=1 (registers) byte-by-byte, silently missing any divergence in RV32 main memory (AS=2), public values (AS=3), and deferral (AS=4). All three correctness fixes below live in AS=2 or AS=4 and would have surfaced on the first `air_test`-style run if the check had walked every address space. Extracted the closure into a `check_vm_state_eq(lhs, rhs) -> eyre::Result<()>` free function shared by both the RVR and AOT equivalence checks, replacing the AS=1-only loop with a slice-level diff over every `LinearMemory`. Short-circuits at the first mismatch and reports `(AS, byte offset, lhs, rhs)`. Microseconds on typical test VM configs. - `SegmentationState::on_periodic_check` was bumping `segmentation_ctx.instret` by a full `segment_check_insns` interval up-front, then incrementing `tracer.check_counter` by the same delta on the way out. The anchor and the countdown ended up ahead of the actual VM by exactly `remaining_counter`, so the next interval inherited an inconsistent baseline. In termination paths this could let the segmenter seal a non-terminal block as the final segment. The callback now: - computes the actual block-boundary instret directly: `prev_anchor + (segment_check_insns - remaining_counter)`, - writes that back as the new anchor, - resets `check_counter` to a full fresh interval rather than incrementing. This matches the Rust metered executor's behavior at the same point. Mod-builder evaluates `SymbolicExpr` inputs **modulo the configured prime**. For `SETUP_ADDSUB` / `SETUP_MULDIV` and their Fp2 counterparts, the compute formula resolves to `Input(0)`, which during setup is the modulus `p` itself — so the variable is `p % p = 0`. The VM writes 32 zero bytes (64 for Fp2) to `rd`. `rvr_ext_mod_setup` and `rvr_ext_fp2_setup` were copying `rs1`'s bytes (the modulus) to `rd`. Those bytes then leaked into the guest's stack as register-loaded values, propagating downstream as a memory divergence between RVR and preflight at later segment boundaries. The FFI now traces the `rs1`/`rs2` reads (still required for chip metering) but writes zero bytes to `rd`. The deferral CALL FFI in RVR only traced AS=4 access for metering and never updated the `(input_acc, output_acc)` accumulator bytes. The Rust preflight executor (`DeferralCallExecutor::execute_e12_impl`) hashes each `(old_acc, commit)` pair via poseidon2 and writes the new accumulator F's to DEFERRAL_AS. Every deferral CALL therefore left RVR's AS=4 a hash-round behind preflight, producing a memory divergence that cascaded through subsequent CALLs. Plumbed a `(*mut F, len_in_F_units)` alias of DEFERRAL_AS through `OpenVmIoState` (via a new `deferral_memory_ptr` helper in `bridge.rs` with a debug-mode alignment check on the `u8 → F` cast) and registered a `DeferralCompressFn` poseidon2 closure on the host side. `host_deferral_call_lookup` now hashes the accumulators and writes the new F bytes into AS=4 in F-element units that exactly match preflight's `vm_write::<F, BLOCK_SIZE>` layout. `F::from_u32` is bijective with the perm output for `MontyField31`, so the stored bytes are byte-identical to what the preflight executor writes. resolves int-7974
Memory read and write functions now have an optional `check_bounds` invocation before accessing the memory. `check_bounds` checks that the access lies within the VM's addressable memory region and aborts otherwise. The same is applied for `openvm_io.h` functions that work with the user IO address space in data memory. To turn off protected mode, add the `openvm-cli/unprotected` feature. Mirrors the interpreter's `check_bounds` and `panic_oob` functions, and `unprotected` Cargo feature. closes INT-7702 --------- Co-authored-by: Ayush Shukla <ayush@axiom.xyz> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…2820) A perf pass on RVR metered execution. The main change isolates the rare segment-check callback into a cold per-block helper so the hot block stays frameless. ## Cold per-block segment-check helper Hot metered RVR blocks were paying a stack-frame cost because the rare `on_check` callback could fire from the same C function. Generated asm showed every metered block — even single-instruction ones — getting an entry prologue and stack spills to preserve guest-register parameters across the possible callback. Hot blocks now only test `check_counter < block_insn_count` inline. On underflow they musttail-jump to a cold per-block `block_0xPC_checkpoint(...)` helper that runs the segment-check callback, suspends/exits if needed, or musttails back to the hot block with a refreshed counter. Same semantics; the hot path is frameless again. ## Cleanup landing in the same patch - **`uses_page_tracking()` IR predicate.** Only blocks that can touch memory emit AS_MEMORY page-tracking locals. ~59% of blocks in the reth benchmark didn't need them. Extension emitters default to `true`; `HintNonQrInstr` opts out, plain host-only phantoms (`HintInput`, `HintRandom`, `PrintStr`) don't trigger page locals. - **Metered block ABI hoist.** `check_counter` (`_cc`) and `trace_heights` (`_th`) are passed as block parameters, removing `state->tracer` loads from every block. Metered mode uses 8 hot guest registers instead of 10 to fit the new parameters. - **`CompileOptions::keep_artifacts`.** Retains the generated RVR C tempdir on success and logs the path. Useful for codegen / asm audits. - Per-width fast traced memory helpers and clang-format / formatting cleanups across the FFI C/Rust crates. results in a modest ~100ms (out of 1.7s) improvement in metered execution of [reth benchmark](https://github.com/axiom-crypto/openvm-eth/actions/runs/26514539244) on my laptop, the improvement is much more significant (~20%)
In `rvr`, some constants are redefined or set as variables. Resolved
some of the dependency issues (e.g. circular dependency) to import the
constants instead.
Related constants:
1) `WORD_SIZE`: imported from `openvm_platform::WORD_SIZE`
2) `AS_MEMORY`: imported from
`openvm_instructions::riscv::RV32_MEMORY_AS`
3) `AS_REGISTER`: imported from
`openvm_instructions::riscv::RV32_REGISTER_AS`
4) `AS_PUBLIC_VALUES`: imported from
`openvm_instructions::PUBLIC_VALUES_AS` (moved to `openvm_instructions`
from `openvm-circuit`. Is it right choice????)
5) `DEFERRAL_AS`: imported from `openvm_instructions::DEFERRAL_AS`
6) `MAX_BLOCK_INSNS` (`rvr-openvm-lift/src/cfg.rs`): was `let`, now
`const`
The following ones are kept redefined:
1) `CHUNK`, `DEFERRAL_DIGEST_SIZE`: logically are from
`openvm-stark-sdk`. `openvm-circuit` and `openvm-recursion-circuit`
already redefine CHUNK. (can not import from them due to circular
dependency).
2) `DEFAULT_PAGE_BITS`, `DEFAULT_SEGMENT_CHECK_INSNS`: logically are
from `openvm-circuit::arch::execution_mode::metered::{ctx,
segment_ctx}`. These are host-side metered-execution defaults. (can not
import from them due to circular dependency)
towards INT-7571
`MAX_MEM_PAGES_PER_INSN ` is a worst-case number of pages a single instruction can touch. The worst-case unique pages per instruction (`HINT_BUFFER`) is `MAX_HINT_BUFFER_WORDS * WORD_SIZE` bytes divided by page size. One page covers `CHUNK * 2^PAGE_BITS` bytes. So the formula is: `MAX_MEM_PAGES_PER_INSN = div_ceil(MAX_HINT_BUFFER_WORDS * WORD_SIZE, CHUNK * 2^PAGE_BITS) + 1` `+1` misalignment. closes INT-7462
Add save and load compiled artifacts feature in `rvr` mode. The feature consist of having the ability to save compilation artifacts on disk and load them into the sdk to execute (part 1). Reusing of the persisted artifacts whenever possible instead of recompiling based on some metadata (part 2) will be done in separate PR. This PR is related to the part 1. The following methods were added: 1) `Sdk::load_compiled_pure`, `Sdk::load_compiled_metered`, `Sdk::load_compiled_metered_cost` and related methods for loading pure, metered and metered cost `.so` files 2) `RvrPureInstance::save`, `RvrMeteredInstance::save`, `RvrMeteredCostInstance::save` and related methods for saving `.so` file towards INT-7843
This PR adds misaligned memory access support. The current solution handles misaligned memory accesses by dividing it depending on: 1. block crossing: meaning it requires a second adjacent memory block for reading/writing from Memory AS. 2. cell crossing: due to cells being in u16, odd shifts (such as 1, 3, 5, 7) require lower and upper 8bits of adjacent cells. Since block crossing affects only 2, 4, and 8 byte load/stores, there are two adapters per load/store: aligned and misaligned. The difference between aligned and misaligned is additional logic for reading/writing a second adjacent memory block. For cell crossing problem, we handle it by storing lower 8 bits of touched cells - cells that are needed for successfully loading/storing. Using lower 8 bits, it is possible to derive upper 8 bits of touched cells. Also, as a part of optimization, we decided to remove `is_valid` column as it is derivable from the shift selector. resolves INT-7672 --------- Co-authored-by: GunaDD <gunadigan@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Ayush Shukla <ayush@axiom.xyz>
## Summary This PR is mostly refactoring and cleanup. The shared tracer and suspender abstraction had run its course: it made every RVR execution mode carry the same accounting and suspension machinery, which blocked further pure-execution performance work. Giving each mode its own state removes that constraint and unlocks a smaller hot path. - Pure RVR keeps only the state needed to run to completion. Its generated blocks have no instruction-retirement accounting or suspension check. - Pure execution with instruction tracking is a separate compile mode. It carries the remaining instruction count through generated block calls and writes the retired count when execution returns. - Metered and metered-cost execution keep their own mode data directly in the RVR state. - The shared tracer and suspender layers are removed. - Loaded RVR artifacts are checked against the execution mode requested by the caller. ## API changes The public API now makes each capability explicit. - `sdk.compile(...)` returns a completion-only pure artifact. - `sdk.compile_with_instret_tracking(...)` returns a tracked pure artifact that supports `execute_for` and `execute_from_state_for`. - Bounded execution returns `ExecutionOutcome::Terminated` or `ExecutionOutcome::Suspended`. - Completion-only execution returns the final VM state directly. Tracked completion also returns the instructions retired by that call. - Interpreter and preflight bounded calls use `_for` methods instead of optional instruction limits. - Metered segment execution uses the same explicit terminated-or-suspended outcome. ## Metrics - Tracked pure execution continues to report the instructions retired by the current call. - Completion-only pure RVR does not report instruction-count or throughput metrics because it does not track retired instructions. - Full metered RVR reports the current call's instruction delta instead of the cumulative instruction count. ## Validation - Built the SDK with and without RVR. - Built the RVR and metrics feature combination. - Ran Clippy with warnings denied on an x86 host. - Ran the RVR suspension and resume integration test. - Ran the tracked artifact save and load SDK test. - Checked the public API use in openvm-eth and rvr-openvm; neither needs a source change.
Executable ELF segments can contain embedded data such as jump tables or constant pools. Previously, transpilation failed whenever no registered extension could decode one of these words, even if it was never executed. This change emits an `unimp` instruction at the corresponding program slot instead. The original word remains unchanged in initialized memory, so embedded data can still be read normally; the program terminates only if control flow reaches that slot. Ambiguous instruction decodings remain an error. Includes a regression test with an undecodable word between valid RV64 instructions.
adapts #3032 for `develop-v2.1.0`
- BLS12-381 RVR arithmetic previously crossed the standard Rust FFI for each specialized Fp, Fr, Fp2, and G1 operation. - It now builds a pinned `blst` submodule and links direct `preserve_most` C wrappers for Fp, Fr, and Fp2 arithmetic and non-setup G1 add and double, using architecture-specific assembly where supported. - P-256, BN254, setup operations, and generic BigUint fallbacks remain on their existing paths. New RVR equivalence tests cover reduction and arithmetic in Fp, Fr, and Fp2 plus G1 add and double. [Benchmark comparison](https://github.com/openvm-org/rvr-openvm/actions/runs/29756429770) Resolves INT-8834
… shift instructions (#2973) ## Summary - Adds separate chips for `XORI`, `ORI`, `ANDI`, `SLTI`, `SLTIU`, `SLLI`, `SRLI`, and `SRAI`. These instructions previously shared chips with their register versions. - Splits the shared adapter into one adapter for register instructions and another for immediate instructions. The immediate adapter reads one register and takes the second input directly from the instruction. - Updates the opcodes, transpiler, executor, RVR, CPU and CUDA trace generation, and tests to use the new chips. --------- Co-authored-by: Ayush Shukla <ayush@axiom.xyz>
## Summary - Splits `ADDIW`, `SLLIW`, `SRLIW`, and `SRAIW` from their register-form word ALU chips, with dedicated immediate opcodes and adapters. - Updates the transpiler, RVR lifting, CPU/CUDA registration and trace generation, and adds boundary coverage for the new word-immediate paths. - Specializes the ADDI core range checks so the most-significant output limb is not checked redundantly when the adapter already constrains it. Resolves INT-8508
- `hint_input` used to copy the whole input into another buffer before the guest could read it. This added an expensive `memcpy` for large Reth inputs. - It now moves the input `Vec` into `HintStream`. The length prefix and zero padding are added as the guest reads the input. - The interpreter and RVR use the same `HintStream`. Other hints are still returned unchanged. [Benchmark comparison](https://github.com/openvm-org/rvr-openvm/actions/runs/29757990761) Resolves INT-8835
- trap when rvr reaches an invalid control-flow target or a host callback rejects its input - keep rv64 register operands full-width across host I/O - enable stricter generated C warnings and add boundary regression tests Resolves INT-8837
…ons (#3006) ## Summary GPU trace-generation and host-to-device (H2D) transfer optimizations for the VM prover, consolidated into one PR. Each logical change is a separate commit. ## Changes - **Pinned record-arena pool** — dense record arenas are served from a pinned host-memory pool with a background cleaner thread, so async DMAs from pinned buffers stay in flight instead of blocking on a pageable staging copy. - **Device-side boundary→Merkle record conversion** — memory boundary records are converted to Merkle records on the GPU, with pinned host-region registration for the transport. - **Pinned memory-image staging** — the per-segment memory-image upload is staged through pinned buffers. - **Tracegen tail trims** — merged inputs, a host-computed merged record count, exec-frequency upload via a pooled pinned buffer plus a device kernel, and span/metric cost gated to non-empty arenas only. - **`repr(C)` TouchedBlock layout** — the touched-block struct is laid out to match the CUDA inventory-record struct, enabling a zero-conversion bulk copy. - **Drop hidden stream sync** — remove the hidden stream synchronization in the CPU-to-GPU proving-context transport. System trace generation keeps the original system-first ordering. ## Results Measured on the openvm-eth standard block, RTX Pro 6000, single sandbox (device pool capped at 15 GiB): | metric | baseline | this PR | | --- | --- | --- | | trace generation | 7.79 s | 5.01 s (−36%) | | record H2D transport | 3.15 s | 0.13 s (−96%) | | app proving (end-to-end) | 86.97 s | 80.10 s (−7.9%) | Baseline and this PR were measured back-to-back on the same container under matched conditions (proving wall 818.8 s vs 818.6 s). [Benchmark comparison](https://github.com/axiom-crypto/openvm-eth/actions/runs/29834295151) --------- Co-authored-by: Yi Sun <5178036+yi-sun@users.noreply.github.com> Co-authored-by: GunaDD <gunadigan@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Ayush Shukla <ayush@axiom.xyz>
- fold fixed chip costs and extension rows into generated code - omit tracing that an execution mode does not use - tighten callback and chip-mapping validation without adding hot-path checks Resolves INT-8837
…#3042) - store finalized field expression programs directly in executors - keep range buses and carry checks in the air-only wrapper - remove fake range buses from interpreter, preflight, hybrid, and rvr execution Resolves INT-8194
- build rvr ecc setup programs from the configured curve - reject guest-provided modulus or coefficient values that do not match - cache each curve program and cover incorrect P-256 setup values Resolves INT-8836
- Adds a state-owned way to rebuild sparse H2D transfer metadata after untracked execution. - Reuses the optimized nonzero-byte scan in touched-page reconstruction and CPU Merkle initialization.
- Moves RV64I, RV64M, and RISC-V I/O instruction lifting, CFG behavior, and C emission into the RISC-V RVR extension. - Defines target-neutral RVR variables, control-flow effects, instruction emission, runtime hooks, and extension registration. - Resolves instruction handlers during artifact generation and emits direct C calls. - Adds bounded main-memory page accounting and buffer draining for variable-size extension accesses. - Adds coverage for lifting, CFG analysis, generated code, metering, and RISC-V integration. Resolves INT-7700 --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
- Metered segmentation checks used to scan every AIR to recompute proving-memory and interaction totals, even when many AIR trace heights are fixed. - The segmentation context now preaggregates contributions from fixed-height AIRs once and scans only variable AIRs at each checkpoint; fixed heights are preserved when starting the next segment. - Metered RVR artifacts now record and validate their AIR count, executor-to-AIR mapping, cost widths, and C/Rust metering layout before execution. Generated tracing also buffers large memory ranges for checkpoint expansion and adds explicit range and buffer-capacity checks. Resolves INT-8833
…3064) ## Problem The `MeteredSegment` checkpoint codegen emits ```c if (unlikely(checkpoint.suspend_signal)) { ... } ``` suspend_signal is a uint32_t (c/block/openvm_block_metered_segment.h) but unlikely() takes an int (c/openvm_util.h), so this passes an unsigned argument to a signed parameter. Under the Makefile's -Weverything -Werror that's a hard error: ``` error: implicit conversion changes signedness: 'uint32_t' to 'int' [-Werror,-Wsign-conversion] ``` Every other unlikely(...) call site passes a comparison (already int), so this is the only spot that trips it.
- BLS12-381 pairing witnesses previously used `blstrs` through an unsafe assumption that its Fp12 memory layout matched Halo2curves. - Witness exponentiation now uses public `blst` Fp12 operations and converts field elements through canonical encodings, so it does not depend on either library's private memory layout. - Tests compare the `blst` path with the existing implementation for zero, one, and random Fp12 inputs. [Benchmark comparison](https://github.com/openvm-org/rvr-openvm/actions/runs/29871734886)
Sanitizers landed default-on in #3065 and slowed generated-code execution
) This PR updated `PersistentBoundaryAir` to combine both initial and final states. This is done by storing initial and final values. On top of it, there is new addition of is_valid and is_dirty flags. This PR focuses on updating PersistentBoundaryAir columns. The second PR properly adds is_dirty flag (#3055). In this PR, for development purposes, it is set to one. towards INT-8828 --------- Co-authored-by: Ayush Shukla <ayush@axiom.xyz>
This PR adds leaf level dirty bit tracking and modifies MemoryMerkleAir to only have final rows for dirty nodes. The updated design tracks written blocks during preflight mode and derives dirty leaves from that knowledge. Depending on the leaf dirtiness, its parent is also considered dirty (and parent's parent too). By observing that only dirty nodes would have different final state at the end of the segment (w.r.t. the start of the segment), we only store dirty final rows for MemoryMerkleAir. Consequently, by removing non-dirty final rows, we need to balance out the number of interactions that the removed non-dirty rows did. This is done by repurposing `direction_different` columns as `child_mode`, a column that acts as `direction_different` for final rows and interaction adjustment for initial rows. In addition, as MerkleMemoryAir trace is no longer a fixed two rows per node, during GPU trace generation the device can't place the row by the static index. To mitigate it, we first compute the total height beforehand and actually compute were the row would go during tracegen. Both CPU and GPU tracegen are stored in interleaved fashion where first is final row and then initial row per node, except for the root where the first one is initial and second one is final. Not sure if it was originally intended to be in this format, maybe would be better to have initial and then final row? Might be later pr This is continuation of PersistentBoundaryAir update PR (#3051). The next step, metered mode tracking is done in the follow up PR (#3061). towards INT-8828 --------- Co-authored-by: Ayush Shukla <ayush@axiom.xyz>
- Replaces the guest `memcpy` and `memset` assembly with Rust implementations optimized for OpenVM memory access costs. - Adds `memmove`, `memcmp`, and `bcmp` through the dedicated `openvm-mem` crate. - Adds host property tests and an RV64 guest integration test for lengths, offsets, overlap, and comparison ordering. Supersedes #3071 --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
## Summary - Derives the memory-bus receive timestamp from each access timestamp and its range-checked decomposition. - Removes one trace column and one equality constraint from every memory access, reducing `MemoryReadAuxCols` from 3 to 2 columns and `MemoryWriteAuxCols` from 7 to 6. - Keeps the maximum interaction degree unchanged and updates the Rust and CUDA trace layouts. - Renames `LessThanAuxCols::lower_decomp` to `decomp` to describe its use in both less-than sub-AIRs. Resolves INT-8882
- BN254 pairing witnesses previously evaluated four large Fp12 exponentiations with Halo2curves. - The RVR pairing FFI now evaluates the same signed-NAF exponentiations through the public `mcl_rust` API while keeping the witness algorithm and raw Miller loop unchanged. - OpenVM uses MCL through Cargo and no longer carries a pairing-specific MCL submodule or C++ adapter. The dependency is pinned to a fork branch configured without MCL's test-only GMP support. - The implementation initializes MCL's Ethereum BN254 preset and verifies the 32-byte base-field serialization used by OpenVM. - OpenVM obtains the static library's native C++ link requirements from rustc and forwards them to the generated RVR shared-library link. - Tests compare MCL with Halo2curves for every production exponent, the complete pairing hint, each root-selection branch, malformed NAF input, and zero-input error handling. [Benchmark comparison](https://github.com/openvm-org/rvr-openvm/actions/runs/29878536875) Depends on herumi/mcl-rust#11 (comment)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.