diff --git a/.gitignore b/.gitignore index b80edca8..a3bbc762 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,6 @@ verifier.bin .vscode/ .env + +# standalone test runs inside patch crates generate their own lockfiles +patches/*/Cargo.lock diff --git a/AGENTS.md b/AGENTS.md index a24607ee..dd07aabf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -13,7 +13,7 @@ Critical context for AI agents working on this repo. Read this before making cha ## OpenVM Version Sensitivity -This project uses **OpenVM v2.0.0** as its ZKVM. Guest executables (`.vmexe`) and host code **must be built from the exact same OpenVM version**. Even a minor version bump can change: +This project uses **OpenVM `develop-v2.1.0` branch** (RV64 guest toolchain) as its ZKVM. Guest executables (`.vmexe`) and host code **must be built from the exact same OpenVM version**. Even a minor version bump can change: - The guest/host data layout (hint streams, public inputs) - The Halo2 SRS degree requirement @@ -21,29 +21,58 @@ This project uses **OpenVM v2.0.0** as its ZKVM. Guest executables (`.vmexe`) an - Field algebra APIs - ECC constructor signatures +### v2.1.0 (RV64) migration notes + +Compared to v2.0.0, the `develop-v2.1.0` branch changes: + +- Guest target is now `riscv64im-unknown-openvm-elf` (built into the `openvm-1.94.1` + rust fork toolchain). Guest builds MUST use `OPENVM_RUST_TOOLCHAIN=openvm-1.94.1` + (the default in the Makefile and in `openvm-build`). The old + `riscv32im-risc0-zkvm-elf` / `nightly-2025-11-20` combination is gone. + The toolchain is installed via `cargo openvm toolchain install` (see Dockerfile; it + extracts to `~/.openvm/toolchains/openvm-1.94.1` and symlinks it from + `~/.rustup/toolchains/`). The prebuilt binaries require **glibc ≥ 2.39** + (Ubuntu 24.04+); on older hosts see the glibc failure pattern below. +- Crate renames: `openvm-rv32im-{guest,transpiler,circuit}` → `openvm-riscv-{guest,transpiler,circuit}`. +- `openvm.toml`: `[app_vm_config.rv32i]`/`rv32m` → `rv64i`/`rv64m`. +- SDK API: `Sdk::riscv32`/`AppConfig::riscv32` → `riscv64`; `Sdk::execute*` now + takes a compiled instance — call `sdk.compile*` / `sdk.compile_metered_cost` + first, then `sdk.execute(&compiled, ...)` / `sdk.execute_metered_cost(&compiled, ...)`. +- Hint stream words are 8 bytes: `hint_store_u32!` → `hint_store_u64!` / + `hint_buffer_chunked`, and the hint-stream length prefix is a `u64`. +- User public values are **single bytes** (1 byte per cell, stored in the low byte + of a u32 field element). `NUM_PUBLIC_VALUES` is 32 cells (= 32 bytes); the + 32-byte pi hash fills all 32 cells. (Earlier v2.1.0 snapshots used u16 cells; + upstream restored byte-sized public values in commit `b3c95cd00`.) +- Guest cfg gates: `target_os = "zkvm"` → `target_os = "openvm"`. +- Host toolchain: `rust-toolchain.toml` uses `nightly-2026-01-18` (required by the + openvm-sdk `tco` feature). + ### How to update OpenVM dependencies correctly -OpenVM is declared as a **git dependency** (`tag = "v2.0.0"`) in `Cargo.toml`, and the exact commit is also pinned in `Cargo.lock`. The `openvm-org/openvm.git` and `openvm-org/stark-backend.git` entries MUST stay on matching tags — `openvm`'s own `Cargo.toml` pins a specific `stark-backend` tag, and a mismatch produces duplicate-registry / type-mismatch errors. Because the tag is immutable, the declared ref and the locked commit should always agree. The real hazard is a bare `cargo update`: it will **not** change the OpenVM tag, but it will bump unrelated crates.io packages (e.g. `alloy`, `revm`) which often break compatibility with the `scroll-tech/reth` and `sbv` forks. +OpenVM is declared as a **git dependency** (`branch = "develop-v2.1.0"`) in `Cargo.toml`, and the exact commit is also pinned in `Cargo.lock`. The `openvm-org/stark-backend.git` entries MUST stay on the tag that `openvm`'s own `Cargo.toml` pins for that branch (currently `tag = "v2.0.0"`) — a mismatch produces duplicate-registry / type-mismatch errors. A branch ref moves: after fetching, verify the locked commit is the one you expect. The real hazard is a bare `cargo update`: it will bump unrelated crates.io packages (e.g. `alloy`, `revm`) which often break compatibility with the `scroll-tech/reth` and `sbv` forks. **Do NOT run a global `cargo update` unless you are prepared to upgrade the entire `alloy`/`revm`/`reth`/`sbv` dependency chain together.** -To move to a newer OpenVM tag, retarget every `openvm-org/openvm.git` and `openvm-org/stark-backend.git` entry in `Cargo.toml` to the new tag, then refresh only those git sources — `cargo metadata` is enough — rather than a global `cargo update`. Verify with `git diff Cargo.lock` that no other package's version/source changed. Then rebuild guests and run tests as described below. +To move to a newer OpenVM ref, retarget every `openvm-org/openvm.git` entry in `Cargo.toml` to the new tag/branch and set `openvm-org/stark-backend.git` to whatever tag that openvm ref's own `Cargo.toml` pins, then refresh only those git sources — `cargo metadata` is enough — rather than a global `cargo update`. Verify with `git diff Cargo.lock` that no other package's version/source changed. Then rebuild guests and run tests as described below. ### After ANY OpenVM version upgrade, you MUST: 1. **Update the hardcoded version string** in `crates/build-guest/src/verifier.rs`: ```rust - let solidity_sdk_tag = "v2.0"; // MUST match openvm-solidity-sdk tag - let verifier_path = "v2.0-deferral"; // bundle/deferral verifier + let solidity_sdk_tag = "v2.1"; // MUST match openvm-solidity-sdk tag + let verifier_path = "v2.1-deferral"; // bundle/deferral verifier ``` + (As of the `develop-v2.1.0` upgrade, `openvm-solidity-sdk` has no `v2.1` tag yet, + so the download fails and `auto` mode falls back to local verifier generation.) 2. **Force-rebuild ALL guest assets** (auto mode skips existing files): ```bash # Local build - OPENVM_RUST_TOOLCHAIN=nightly-2025-11-20 cargo run --release -p scroll-zkvm-build-guest -- --mode force + OPENVM_RUST_TOOLCHAIN=openvm-1.94.1 cargo run --release -p scroll-zkvm-build-guest -- --mode force # Docker build (matches CI) - OPENVM_RUST_TOOLCHAIN=nightly-2025-11-20 make build-guest + OPENVM_RUST_TOOLCHAIN=openvm-1.94.1 make build-guest ``` This regenerates: `app.elf`, `app.vmexe`, commitment `.rs` files, `agg_vk.bin`, `openVmVk.json`, and the EVM verifier (`verifier.sol` + `verifier.bin`). @@ -67,7 +96,7 @@ To move to a newer OpenVM tag, retarget every `openvm-org/openvm.git` and `openv These are cached proving keys. They are **not** automatically invalidated on version bumps. 5. **Check SRS params** in `~/.openvm/params/`: - - OpenVM v2.0.0 requires `kzg_bn254_24.srs` (2 GB); the SNARK step in e2e tests also needs `kzg_bn254_22.srs` and `kzg_bn254_23.srs` + - OpenVM v2.x requires `kzg_bn254_24.srs` (2 GB); the SNARK step in e2e tests also needs `kzg_bn254_22.srs` and `kzg_bn254_23.srs` - Download any missing file with `make $HOME/.openvm/params/.srs` - If a file is empty/corrupted, replace it (check for `.1` or `.part` suffixes from interrupted downloads) @@ -77,6 +106,224 @@ To move to a newer OpenVM tag, retarget every `openvm-org/openvm.git` and `openv ``` Integration tests reuse cached proofs by default. Stale proofs from a previous OpenVM version will cause failures. +### Guest ELF link fails with `undefined symbol: native_keccak256` +**Cause**: The circuit crate enabled `alloy-primitives/native-keccak` (so `alloy_primitives::keccak256` +calls the `native_keccak256` extern) but links the wrong provider crate. The extern is defined in +**`openvm-keccak256`** (guest-libs, also exports `native_keccakf`/`native_xorin`), NOT in +`openvm-keccak256-guest` (extensions — only defines `native_xorin`/`native_keccakf`). +**Fix**: depend on `openvm-keccak256` and import it in `circuit.rs` (`use openvm_keccak256;`), +mirroring `batch-circuit`. Check the actual keccak backend per circuit with +`cargo tree -p --prefix none -f "{p} {f}" | grep ^alloy-primitives`: +the guest graph must show `native-keccak` and must NOT show `tiny-keccak` (a software fallback — +the bundle circuit once spent 63% of its cycles in `tiny_keccak::keccakf` because of this). + +## Guest Cycle Profiling + +Function-level cycle attribution is available via openvm's `perf-metrics` feature (function +spans from ELF symbol bounds + a metrics recorder in the prover): + +1. **Build guests with profiling metadata** (adds `fn_bounds` + `guest.symbols` to the assets; + exe commitments are unaffected): + ```bash + # in the guest-build container, like a normal force build but with the feature + BUILD_PROJECT=chunk,batch,bundle OPENVM_BUILD_LOCKED=1 \ + cargo run --release --locked -p scroll-zkvm-build-guest \ + --features scroll-zkvm-build-guest/perf-metrics -- --mode force + ``` + (The transpiler requires `GUEST_SYMBOLS_PATH` when `function-span` is on; build-guest sets it + per project to `releases/dev//guest.symbols`. build-guest also inserts a synthetic + `[0, first_fn)` fn bound — without it openvm's `update_current_fn` panics on entry-trampoline PCs.) + +2. **Run any proving test** with the prover-side feature and an output dir: + ```bash + PROFILE_METRICS_DIR=/tmp/prof GPU=1 cargo test --release --locked \ + --features scroll-zkvm-integration/cuda,scroll-zkvm-integration/perf-metrics \ + -p scroll-zkvm-integration --test batch_circuit e2e -- --exact --nocapture + ``` + Every proof writes `/-.json` (per-proof counter deltas) in the + `scripts/flamegraph.py` metrics format. + +3. **Analyze** with `scripts/profile_top.py --symbols releases/dev//guest.symbols` + (top functions by executed instructions, inclusive span stacks). `scripts/flamegraph.py` + `--guest-symbols` works on the same files for SVG flamegraphs. + +Caveats: +- The profile counts *executed instructions* per function. On the GPU proving path the + per-AIR `cells_used` metrics are NOT emitted (CPU prove only), and the instruction replay + inflates wall-clock proving time ~4x — never compare wall times from a `perf-metrics` build + against a clean build. +- **GPU prove replay is truncated**: the GPU postflight program log only covers the first + ~26% of a chunk-sized execution (53.4M of 203M instructions — verify against the + `execute_metered_insns` counter or `total_cycles`; if `frequency` totals are much lower, + the sample is partial). Witness-processing phases sit early in the execution, so a + truncated sample over-weights them vs EVM execution. For a full-execution profile, run the + prove on CPU (no `cuda` feature): the CPU replay covers every segment. +- The execute-only path (`tester_execute`, e.g. `test-execute-chunk`) also honors + `PROFILE_METRICS_DIR` and writes `execute-0.json`, but the metered-cost executor emits no + function-span counters there — it is only useful for total cycle counts. +- The recorder accumulates per process; the prover writes per-proof deltas, so each JSON holds + exactly one proof's profile even when a test proves many circuits (e2e bundle). + +## Local patch crates (`patches/`) + +- `patches/openvm-mem` — memmove recursion fix (see failure patterns). This is the only live + patch right now. + +## Cycle-optimization experiments (2026-09, reverted) + +We tried two further guest-cycle patches for the **chunk** circuit, measured them carefully, +and then **reverted** them — the cycles saved did not justify carrying forked dependencies. +The experiment code is preserved in commit `430b7acc` if it is ever wanted again. + +### What was tried, and the measured numbers + +Preset: GalileoV2 chunk, 6 blocks / 630 txs / 35.2M gas. Baseline 202,969,694 guest +instructions; e2e STARK prove 44.15s (RTX 4090). + +| change | cycles saved | note | +|---|---|---| +| `risc0-ethereum-trie`: hand-written MPT node parser (no per-list `Vec`, single-copy compact path) | −6.9M | decode side only | +| + inline fast path for 33-byte digest children | −15.6M | the single biggest win | +| `openvm-keccak256-guest`: `native_xorin` aligned-stack staging for unaligned input | −2.3M | 27% of absorbs took slow path | +| **total** | **−12.1%** (→178.4M) | e2e time only **−6.2%** (→41.4s) | + +Key structural insight: a chunk witness MPT holds ~11.5k real nodes but **~111k 33-byte +digest children** (upper branches are nearly full) — each digest child used to cost a full +decoder recursion + a heap box; inlining them was 2/3 of the total win. Also from the +ground-truth instrumentation: the chunk guest executes **87,192 keccak absorbs over 10.08 +MB** of input (~60% of it witness state nodes and bytecode hashing, which is inherent to +the stateless proof model). + +pi hashes were bit-identical across all changes; e2e chunk/batch/bundle all passed. + +### Where the chunk bottleneck actually is (full-execution CPU-prove profile, 194M instr) + +- **~50%+: the revm interpreter itself** (dispatch loop, instruction handlers, mstore/mload, + journal). No fork-level fix — needs an interpreter redesign (superinstructions, register + dispatch), which is a revm-scale project with high fork drift. +- **~32% of trace cells: KeccakfPermAir** — driven by hashing the witness MPT nodes + + bytecode (proof-model-inherent; only a smaller witness or a cheaper keccak circuit helps). +- **~23% of trace cells: Poseidon2 memory-merkle periphery** — scales with guest memory + traffic. +- MPT witness decode (after the reverted patches ~13%, before ~21%), `calculate_state_root` + dirty-path re-encode 7.7%, jumpdest `into_analyzed` 6.5%, ecrecover msm 4.1%, witness + bincode deserialize 2.4%, keccak call wrappers 4.8%. + +Realistic ceiling for more fork-level work: ~3-6%. The step change would be the interpreter +or the proof model, not more micro-patches. + +### Directions tried and rejected (do not retry blindly) + +- **SWAR / word-at-a-time jumpdest scan**: real contract code has a PUSH-opcode byte in + **~83% of 8-byte words**, so the word fast path almost never engages and the mask setup is + pure overhead (a first version was 3x *slower*). The upstream byte loop is at its floor. + (When bit-parallel tricks are needed elsewhere: the classic `(x−LO)&~x&HI` zero-byte mask + has false positives from cross-byte borrows; use `!(((x&0x7f..)+0x7f..)|x)&HI` instead.) +- **Deduplicating witness codes before analysis**: already done host-side in + `ChunkWitness::new` (a `HashSet<&Bytes>` filter) — nothing left on the table. +- **Reducing keccak absorb count**: witness state/code hashing is proof verification, not + overhead — it cannot be skipped without changing the security model. +- **Patching `revm-bytecode` directly**: a `[patch]` cannot intercept *path* deps inside a + git dependency (scroll-revm's crates inter-depend via workspace `path`), so it would + require vendoring the whole revm repo. Not worth it. + +### Methodology lessons + +- **GPU-prove function profiles truncate after ~26%** of a chunk-sized execution (the GPU + postflight program log only covers the first segments). Any hotspot ranking from + `PROFILE_METRICS_DIR` + GPU is a *biased, early-phase* sample — use a CPU prove for a + full-execution profile (~45 min for chunk, covers 100%). +- Cycle counts: `test_execute`'s metered `instret` equals the true retired-instruction count + (verified against in-guest counters); it is the right iteration metric and needs no GPU. +- `[patch]` table edits: afterwards run **no** bare `cargo update`/`cargo metadata` — + unpinned git deps (branch-HEAD `risc0-ethereum`, `da-codec`, ...) float to the newest + fetched commit and `alloy-evm`'s `revm` req re-resolves to registry `30.2.0`, breaking the + build with duplicate-revm type mismatches. Hand-edit `Cargo.lock` to the minimal diff (for + a path patch: delete the package's `source =` line, adjust its dep list) and verify with + `cargo metadata --locked` (must exit 0 without touching the lock). + + +## Host-side proving speed experiments (2026-09) + +Compile-option / feature-flag sweep for **end-to-end proving time** (GPU 1, RTX 4090, +EPYC 9554). Baseline: chunk `test-single-chunk` prove 43.89s (202,969,694 cycles, exec +2.35s), `test-e2e-batch` 54.9s, `test-e2e-bundle` 163.8s (of which the bundle +STARK→SNARK→EVM span ≈ 101s). + +### Adopted (in tree) + +- `openvm-sdk` feature **`mimalloc`** (workspace `Cargo.toml`). Upstream defaults to + `jemalloc`; we build with `default-features = false` and had **no** custom allocator. + **This is essentially the whole bundle win**: attribution runs show + native+LTO *without* mimalloc = 162.6s (≈ baseline 163.8s), adding mimalloc → 125.9s. + (halo2 SNARK host code is allocation-dominated; mimalloc also gives chunk exec −11%.) +- **Cached `StarkProver` per `Prover`** (`crates/prover/src/prover/mod.rs`): + `Sdk::prove()` rebuilds a `StarkProver` (re-committing the program on device) on + *every* call — ~1.1s per small chunk proof, ~3s for the big 203M-cycle chunk. + Caching it (cleared by `reset()`) gives batch e2e 51.3s → 47.3s (−8%) with 3 chunks, + and chunk `test-single-chunk` 43.0s → 39.8s. +- `[profile.release] lto = "thin", codegen-units = 1` — kept, but attribution says its + runtime effect here is ≈ 0 (it mainly raises build time; drop it if build time hurts). + Does not affect guest builds (`maxperf` already sets fat/1 explicitly). +- Recommended env (NOT committed; makes binaries machine-specific): + `RUSTFLAGS="-C target-cpu=native"` — measured ≈ 0 on both chunk and bundle in + isolation; harmless to use on fixed proving hardware. + +Final config (mimalloc + LTO + native + prover cache): **chunk 39.8s (−9.3%), batch e2e +47.3s (−13.8%), bundle e2e ~126-130s (−21%..−23%)**. Per-phase in bundle e2e: chunks −3% +(−15% with cache), batch −8~15%, exec −15~20%, the 101s bundle STARK+SNARK span → ~69-73s +(−30%). + +### Tried and rejected (measured, do not retry blindly) + +- **`jemalloc`**: chunk prove 49.6s — **13% SLOWER** than no custom allocator under the + GPU proving flow. (mimalloc and jemalloc behave very differently here.) +- **`rvr`** (runtime native-compiled execution), even *with* the StarkProver cache: + - First proof pays ~85s of clang compiles (metered + preflight-tracer artifacts in + `PreparedContinuation::new`); with the cache, *subsequent* chunk proofs do get + faster: 7.91s → 6.02s (**−24%**), i.e. preflight ~10s → ~2-3s on a 203M chunk. + - But `execute_guest`'s `sdk.compile_metered_cost()` (the cycle-count/precheck call in + `gen_proof_stark`) recompiles a native artifact **on every proof** (~22.5s each) — + the returned `CompiledExeMeteredCost<'_>` borrows the SDK so it can't be cached in + `Prover` without unsafe or an SDK API change. Net: still a loss. + - And RVR + deferral is **broken at this rev**: `rvr_ext_deferral.c` fails with + `use of undeclared identifier 'OPENVM_MEM_SIZE'` — batch/bundle can't run at all. + - Toolchain note if ever retried: prebuilt LLVM 22.1.8 at `/home/scroll/tools/llvm-22` + works with `RVR_CC=clang-22 RVR_LD=lld LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/11` + (`RVR_LD=ld.lld` is rejected by clang-22; `-lstdc++` needs the GCC dir on + `LIBRARY_PATH`). +- **`VPMM_PAGES` preallocation** (openvm VPMM pool): no measurable effect. +- **`halo2curves-axiom` `asm` feature** (x86_64 bn254 field asm): bundle e2e 125.81s + with vs 125.87s without — no effect; the halo2-gpu SNARK path is not CPU-field-bound. + NB: enabling it must be done in a **host-only** crate's dep (e.g. crates/prover), + never in workspace deps — the asm module is x86_64-only and would break riscv64 guest + builds through feature unification. +- CUDA side was already optimal: kernels compile for `sm_89` (auto-detected) with + `-O3` (`CUDA_OPT_LEVEL` default). `CUDA_ARCH` env override only affects build time. + +### Where the remaining chunk time goes (GPU prove, 24 segments) + +Per 203M-cycle chunk: ~25s GPU kernels (logup-zerocheck 16.4s, stacked_commit 6.1s, +whir 4.7s, merkle 5.9s), ~10s CPU preflight (per-segment re-execution), ~3s trace gen, +~3.3s metered executions. Per segment: CPU ≈ 0.62s (preflight+tracegen+postflight), +GPU ≈ 0.73s, run **strictly serially** (`sdk-config/src/preflight_driver.rs`) — the GPU +is idle ~40-45% of app-prove time. A software pipeline (preflight of segment i+1 +overlapping GPU prove of segment i) is the biggest known host-side lever left +(~20-25% off chunk) but is a medium-large fork of openvm-sdk-config: execution state +chains sequentially through one `VirtualMachine`, while postflight/tracegen/prove need +`&mut vm` and the engine — splitting that ownership safely is ~300+ lines with a +~1-segment-trace VRAM increase. Not done. + +A smaller same-direction win inside our own tree: `gen_proof_stark` runs +`execute_and_check` purely for cycle count + PI≠0 precheck, then `prove()` executes +again — removing the double execution (take instret from the prove path) saves +~2s/chunk. Not done (behavioral change: loses the fail-fast precheck). + +Span breakdown recipe: run the test with `--no-default-features --features +scroll-zkvm-integration/scroll,scroll-zkvm-integration/cuda` (the default `limit-logs` +feature hard-filters to scroll_zkvm_* targets and hides all openvm spans), with +`RUST_LOG="off,scroll_zkvm_integration=debug,scroll_zkvm_prover=debug,openvm_circuit=info,openvm_cuda_backend=info,openvm_stark_backend=info,openvm_sdk=info,openvm_continuations=info"`. + ## Common Failure Patterns ### `NativeHintSliceSubEx` assertion failure @@ -102,7 +349,7 @@ This happens when: **Fix**: Regenerate with: ```bash -OPENVM_RUST_TOOLCHAIN=nightly-2025-11-20 cargo run --release -p scroll-zkvm-build-guest -- --mode force +OPENVM_RUST_TOOLCHAIN=openvm-1.94.1 cargo run --release -p scroll-zkvm-build-guest -- --mode force ``` (The default `auto` mode will fall back to local generation if the download fails; use `RECOMPUTE_MODE=yes` to force local generation immediately.) @@ -114,6 +361,76 @@ OPENVM_RUST_TOOLCHAIN=nightly-2025-11-20 cargo run --release -p scroll-zkvm-buil ### Docker build fails with stale CID The `build-guest.sh` script may fail if a stale `build-guest.cid` file exists. Use local build (`cargo run -p scroll-zkvm-build-guest`) as fallback. +### Guest build fails: `GLIBC_2.3x' not found` / `GLIBCXX_3.4.32' not found` +**Symptoms**: `scroll-zkvm-build-guest` fails during the RV64 guest build with +`rustc: /lib/x86_64-linux-gnu/libc.so.6: version 'GLIBC_2.39' not found (required by +.../openvm-1.94.1/lib/librustc_driver-*.so)`. +**Cause**: The prebuilt `openvm-1.94.1` toolchain installed by `cargo openvm toolchain +install` requires glibc ≥ 2.39 (Ubuntu 24.04+). Older hosts (e.g. Ubuntu 22.04, glibc +2.35) cannot run it. +**Fix**: Run the guest build inside an Ubuntu 24.04 container with the repo and the +rustup/cargo/openvm dirs mounted (host-compiled binaries run fine inside; glibc is +forward-compatible): +```bash +cat > /tmp/Dockerfile.guest2404 <<'EOF' +FROM ubuntu:24.04 +RUN apt-get update && apt-get install -y --no-install-recommends build-essential ca-certificates git && rm -rf /var/lib/apt/lists/* +EOF +docker build -t guest-build-2404:local -f /tmp/Dockerfile.guest2404 /tmp + +docker run --rm --user $(id -u):$(id -g) \ + -e HOME="$HOME" -e RUSTUP_HOME="$HOME/.rustup" -e CARGO_HOME="$HOME/.cargo" \ + -e OPENVM_RUST_TOOLCHAIN=openvm-1.94.1 \ + -e PATH="$HOME/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" \ + -v "$PWD:$PWD" -v "$HOME/.rustup:$HOME/.rustup" -v "$HOME/.cargo:$HOME/.cargo" \ + -v "$HOME/.openvm:$HOME/.openvm" -w "$PWD" \ + guest-build-2404:local \ + "$HOME/.cargo/bin/cargo" run --release -p scroll-zkvm-build-guest -- --mode force +``` +⚠️ The `~/.openvm` mount is **required**: the toolchain really lives at +`~/.openvm/toolchains/openvm-1.94.1` and is only symlinked from +`~/.rustup/toolchains/`; without the mount rustup reports +`override toolchain 'openvm-1.94.1' is not installed` (dangling symlink → ENOENT). +Tip: set `OPENVM_GUEST_LOGFILE=` to capture the inner guest cargo output — it +defaults to `/dev/tty`, which is invisible in containers/CI. + +### Guest crashes with `upper 4 bytes must be zero` (TryFromIntError) in store/addi +**Symptoms**: `test-execute-chunk` / proving panics in `openvm_riscv_circuit` with a +register holding `0xfffffffffffffe60` (=-416) or similar sign-extended garbage, and the +stack pointer walks down by a fixed stride (e.g. 416) until it wraps. +**Cause**: Upstream `openvm-mem` (introduced in commit `d664effb1`, "use rust native +memory intrinsics") implements `copy_forward`/`copy_backward` with 64-byte aggregate +copies (`load::<64>`/`store::<64>`). LLVM lowers those aggregate copies into calls to +`memmove`, which makes `memmove` recursively call itself and overflow the guest stack. +**Fix**: We ship a local override at `patches/openvm-mem` (wired via +`[patch."https://github.com/openvm-org/openvm.git"]` in `Cargo.toml`) that does the +block copies with 8× `u64` loads-then-stores instead of one 64-byte aggregate. If you +bump OpenVM and upstream fixes `openvm-mem`, delete the `[patch]` entry and the +`patches/openvm-mem` directory. + +### `subtree size exceeds the address space's configured leaf count` (bundle root/SNARK) +**Symptoms**: `test-e2e-bundle` fails during `gen_proof_snark` (the Halo2 wrap of the +bundle root proof) with this assert from +`crates/vm/src/system/cuda/merkle_tree/mod.rs`, for `DEFERRAL_AS` (address space 4) +with `num_cells=0`. +**Cause**: OpenVM commit `a935d8b3d` ("perf: sparse initial memory snapshot and GPU +Merkle build") added a strict leaf-count assert. The SDK's `compute_root_proof_heights` +builds the root config from a default `AppConfig::riscv64` (which has `deferral=None`), +so `apply_optimizations` zeroes `DEFERRAL_AS.num_cells` — but deferral is actually +active and the root proof touches that address space. +**Fix**: Fixed upstream by `46709d24` ("fix: keep the dummy root-keygen app config +self-consistent", #3118), which re-runs `apply_optimizations()` in +`compute_root_proof_heights` so the dummy root-keygen config keeps `DEFERRAL_AS` +allocated. We track `develop-v2.1.0` HEAD (`29fc511e`), which includes the fix. If you +ever need to pin between `a935d8b3d` and `46709d24`, this assert will come back. + +### Field-independent instructions (#3109) +As of `29fc511e` ("refactor(v2.1): make program instructions field-independent"), +`Instruction` / `Program` / `VmExe` are **non-generic** (no ``); operands are +`InstructionOperand(i32)` restricted to the signed 30-bit domain. This changes the +`app.vmexe` serialization format, so any OpenVM bump across this commit requires a +full force rebuild of guest assets. + ## GPU Features Two levels of GPU acceleration exist, wired as cargo features: @@ -154,7 +471,7 @@ Do **not** reintroduce `sdk.prover()` / `sdk.agg_vk()` calls in read-only (verif # Force rebuild all guest assets (required after OpenVM upgrade). # Default RECOMPUTE_MODE=auto falls back to local generation if the download fails. # Use RECOMPUTE_MODE=yes to skip the download and force local generation. -OPENVM_RUST_TOOLCHAIN=nightly-2025-11-20 cargo run --release -p scroll-zkvm-build-guest -- --mode force +OPENVM_RUST_TOOLCHAIN=openvm-1.94.1 cargo run --release -p scroll-zkvm-build-guest -- --mode force # Run end-to-end tests (ALWAYS use make, never raw cargo test) GPU=1 make test-e2e-bundle @@ -176,6 +493,20 @@ can waste hours of CPU time. Always run it as: cargo test --release -p scroll-zkvm-build-guest test_verifier ``` +### RVR native execution toolchain (currently disabled) + +The optional `rvr` feature of `openvm-sdk` compiles guest code to native C at runtime for +faster execution. It is **not** enabled in `Cargo.toml` by default (the default path uses +the interpreter, which is slower but well-tested). If you enable it, you need +**LLVM clang-22 + lld-22** on the host: + +- Set `RVR_CC=clang-22` and `RVR_LD=lld` (or `RVR_LD=ld.lld`) when running tests. +- If the system clang is older, install clang-22/lld-22 via conda-forge and put it on `PATH`: + ```bash + mamba install -y -c conda-forge clang=22 lld=22 llvm=22 + PATH="/home/scroll/miniforge3/bin:$PATH" RVR_CC=clang-22 RVR_LD=lld GPU=1 make test-single-chunk + ``` + ## Deferral Model (OpenVM v2+) OpenVM v2 replaces the traditional root-verifier recursion with a **deferred compute model**: @@ -219,3 +550,5 @@ If any of these mismatch, the EVM verifier will reject proofs with `ProofVerific - `chunk-circuit`: requires `system.config.continuation_enabled = true` - `batch-circuit` / `bundle-circuit`: aggregation FRI params are supplied in code via `AggregationConfig { params: default_agg_params() }`; the checked-in `openvm.toml` files do not contain `leaf_fri_params` - FRI params format in OpenVM v2: `commit_proof_of_work_bits` + `query_proof_of_work_bits` +- VM extension sections in `openvm.toml` are `[app_vm_config.rv64i]` / `[app_vm_config.rv64m]` (RV64) +- Guest ELFs land in `target/riscv64im-unknown-openvm-elf/maxperf/` diff --git a/Cargo.lock b/Cargo.lock index 311be3bd..651d84ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,54 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "abi_stable" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d6512d3eb05ffe5004c59c206de7f99c34951504056ce23fc953842f12c445" -dependencies = [ - "abi_stable_derive", - "abi_stable_shared", - "const_panic", - "core_extensions", - "crossbeam-channel", - "generational-arena", - "libloading", - "lock_api", - "parking_lot", - "paste", - "repr_offset", - "rustc_version 0.4.1", - "serde", - "serde_derive", - "serde_json", -] - -[[package]] -name = "abi_stable_derive" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7178468b407a4ee10e881bc7a328a65e739f0863615cca4429d43916b05e898" -dependencies = [ - "abi_stable_shared", - "as_derive_utils", - "core_extensions", - "proc-macro2", - "quote", - "rustc_version 0.4.1", - "syn 1.0.109", - "typed-arena", -] - -[[package]] -name = "abi_stable_shared" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b5df7688c123e63f4d4d649cba63f2967ba7f7861b1664fca3f77d3dad2b63" -dependencies = [ - "core_extensions", -] - [[package]] name = "addr2line" version = "0.25.1" @@ -585,7 +537,7 @@ checksum = "6d792e205ed3b72f795a8044c52877d2e6b6e9b1d13f431478121d8d4eaa9028" dependencies = [ "alloy-sol-macro-input", "const-hex", - "heck 0.5.0", + "heck", "indexmap 2.12.0", "proc-macro-error2", "proc-macro2", @@ -603,7 +555,7 @@ checksum = "0bd1247a8f90b465ef3f1207627547ec16940c35597875cdc09c49d58b19693c" dependencies = [ "const-hex", "dunce", - "heck 0.5.0", + "heck", "macro-string", "proc-macro2", "quote", @@ -770,7 +722,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -781,7 +733,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -1105,18 +1057,6 @@ dependencies = [ "serde", ] -[[package]] -name = "as_derive_utils" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff3c96645900a44cf11941c111bd08a6573b0e2f9f69bc9264b179d8fae753c4" -dependencies = [ - "core_extensions", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "async-stream" version = "0.3.6" @@ -1319,12 +1259,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "bitstream-io" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" - [[package]] name = "bitvec" version = "1.0.1" @@ -1666,7 +1600,7 @@ version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", "syn 2.0.110", @@ -1741,15 +1675,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "const_panic" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e262cdaac42494e3ae34c43969f9cdeb7da178bdb4b66fa6a1ea2edb4c8ae652" -dependencies = [ - "typewit", -] - [[package]] name = "constant_time_eq" version = "0.3.1" @@ -1781,21 +1706,6 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" -[[package]] -name = "core_extensions" -version = "1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42bb5e5d0269fd4f739ea6cedaf29c16d81c27a7ce7582008e90eb50dcd57003" -dependencies = [ - "core_extensions_proc_macros", -] - -[[package]] -name = "core_extensions_proc_macros" -version = "1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "533d38ecd2709b7608fb8e18e4504deb99e9a72879e6aa66373a76d8dc4259ea" - [[package]] name = "cpufeatures" version = "0.2.17" @@ -2412,7 +2322,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -2714,15 +2624,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" -[[package]] -name = "generational-arena" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877e94aff08e743b651baaea359664321055749b398adff8740a7399af7796e7" -dependencies = [ - "cfg-if 1.0.4", -] - [[package]] name = "generic-array" version = "0.14.9" @@ -2886,7 +2787,7 @@ dependencies = [ "crossbeam", "ff 0.13.1", "group 0.13.0", - "halo2curves-axiom 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "halo2curves-axiom 0.7.2", "itertools 0.11.0", "maybe-rayon", "pairing 0.23.0", @@ -2901,7 +2802,7 @@ dependencies = [ [[package]] name = "halo2-axiom-gpu" version = "1.0.0" -source = "git+https://github.com/axiom-crypto/halo2-gpu.git?tag=v1.0.0#97ef2d02aa3348fc04b520c3c2562a9c13b57126" +source = "git+https://github.com/axiom-crypto/halo2-gpu.git?branch=develop-v2.1.0#85ad4c2a623ae520fc1454fcb5adf15ec1bb4410" dependencies = [ "ahash", "anyhow", @@ -2916,7 +2817,7 @@ dependencies = [ "git-version", "group 0.13.0", "halo2-axiom", - "halo2curves-axiom 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "halo2curves-axiom 0.7.2", "itertools 0.11.0", "lazy_static", "libc", @@ -2941,7 +2842,7 @@ dependencies = [ [[package]] name = "halo2-base" version = "0.5.4" -source = "git+https://github.com/axiom-crypto/halo2-lib.git?tag=v0.5.4#a69fdee77f41bdd48ad658b69673dea5a0815db4" +source = "git+https://github.com/axiom-crypto/halo2-lib.git?branch=develop-v2.1.0#d59f41ac884d18a985025090a227fa6733398ae8" dependencies = [ "getset", "halo2-axiom", @@ -2962,7 +2863,7 @@ dependencies = [ [[package]] name = "halo2-ecc" version = "0.5.4" -source = "git+https://github.com/axiom-crypto/halo2-lib.git?tag=v0.5.4#a69fdee77f41bdd48ad658b69673dea5a0815db4" +source = "git+https://github.com/axiom-crypto/halo2-lib.git?branch=develop-v2.1.0#d59f41ac884d18a985025090a227fa6733398ae8" dependencies = [ "halo2-base", "itertools 0.11.0", @@ -3022,8 +2923,8 @@ dependencies = [ [[package]] name = "halo2curves-axiom" -version = "0.7.2" -source = "git+https://github.com/axiom-crypto/halo2curves.git?tag=v0.7.2#3a65a710e27fe03711f6fb4fc0c4469ae351974a" +version = "0.7.3" +source = "git+https://github.com/axiom-crypto/halo2curves.git?tag=v0.7.3#d744f712fbeaf62576b2b10842822919551c5ef8" dependencies = [ "blake2b_simd", "digest 0.10.7", @@ -3083,12 +2984,6 @@ dependencies = [ "serde", ] -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - [[package]] name = "heck" version = "0.5.0" @@ -3583,7 +3478,7 @@ dependencies = [ [[package]] name = "k256" version = "0.13.4" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "ecdsa", "elliptic-curve", @@ -3635,12 +3530,12 @@ checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libloading" -version = "0.7.4" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if 1.0.4", - "winapi", + "windows-link 0.2.1", ] [[package]] @@ -3649,6 +3544,15 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +[[package]] +name = "libmimalloc-sys" +version = "0.1.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a45a52f43e1c16f667ccfe4dd8c85b7f7c204fd5e3bf46c5b0db9a5c3c0b8e9" +dependencies = [ + "cc", +] + [[package]] name = "libsecp256k1" version = "0.7.2" @@ -3853,6 +3757,15 @@ dependencies = [ "sketches-ddsketch", ] +[[package]] +name = "mimalloc" +version = "0.1.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d4139bb28d14ad1facf21d5eb8825051b326e172d216b39f6d31df53cc97862" +dependencies = [ + "libmimalloc-sys", +] + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -3962,7 +3875,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -4100,7 +4013,7 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 3.4.0", "proc-macro2", "quote", "syn 2.0.110", @@ -4308,44 +4221,48 @@ dependencies = [ [[package]] name = "openvm" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "bytemuck", "getrandom 0.2.16", "getrandom 0.3.4", "num-bigint", "openvm-custom-insn", + "openvm-mem", "openvm-platform", - "openvm-rv32im-guest", + "openvm-riscv-guest", "serde", ] [[package]] name = "openvm-algebra-circuit" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "blstrs", "cfg-if 1.0.4", "derive-new 0.6.0", "derive_more 1.0.0", "eyre", - "halo2curves-axiom 0.7.2 (git+https://github.com/axiom-crypto/halo2curves.git?tag=v0.7.2)", + "halo2curves-axiom 0.7.3", "num-bigint", "num-traits", "once_cell", "openvm-algebra-transpiler", + "openvm-algebra-utils", "openvm-circuit", "openvm-circuit-derive", "openvm-circuit-primitives", "openvm-circuit-primitives-derive", "openvm-cpu-backend", "openvm-cuda-backend", + "openvm-cuda-builder", "openvm-cuda-common", "openvm-instructions", "openvm-mod-circuit-builder", - "openvm-rv32-adapters", - "openvm-rv32im-circuit", + "openvm-platform", + "openvm-riscv-adapters", + "openvm-riscv-circuit", "openvm-stark-backend", "openvm-stark-sdk", "rand 0.9.4", @@ -4357,7 +4274,7 @@ dependencies = [ [[package]] name = "openvm-algebra-complex-macros" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "openvm-macros-common", "quote", @@ -4367,15 +4284,15 @@ dependencies = [ [[package]] name = "openvm-algebra-guest" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ - "halo2curves-axiom 0.7.2 (git+https://github.com/axiom-crypto/halo2curves.git?tag=v0.7.2)", + "halo2curves-axiom 0.7.3", "num-bigint", "once_cell", "openvm-algebra-complex-macros", "openvm-algebra-moduli-macros", "openvm-custom-insn", - "openvm-rv32im-guest", + "openvm-riscv-guest", "serde-big-array", "strum_macros 0.26.4", ] @@ -4383,7 +4300,7 @@ dependencies = [ [[package]] name = "openvm-algebra-moduli-macros" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "num-bigint", "num-prime", @@ -4395,21 +4312,30 @@ dependencies = [ [[package]] name = "openvm-algebra-transpiler" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "openvm-algebra-guest", + "openvm-decoder", "openvm-instructions", "openvm-instructions-derive", - "openvm-stark-backend", "openvm-transpiler", - "rrs-lib", "strum 0.26.3", ] +[[package]] +name = "openvm-algebra-utils" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" +dependencies = [ + "num-bigint", + "num-traits", + "rand 0.9.4", +] + [[package]] name = "openvm-benchmarks-prove" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "clap", "eyre", @@ -4422,7 +4348,6 @@ dependencies = [ "openvm-stark-sdk", "openvm-transpiler", "openvm-verify-stark-host", - "p3-field", "rand_chacha 0.3.1", "tiny-keccak", "tracing", @@ -4432,7 +4357,7 @@ dependencies = [ [[package]] name = "openvm-benchmarks-utils" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "cargo_metadata 0.18.1", "clap", @@ -4446,7 +4371,7 @@ dependencies = [ [[package]] name = "openvm-bigint-circuit" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "cfg-if 1.0.4", "derive-new 0.6.0", @@ -4461,9 +4386,9 @@ dependencies = [ "openvm-cuda-builder", "openvm-cuda-common", "openvm-instructions", - "openvm-rv32-adapters", - "openvm-rv32im-circuit", - "openvm-rv32im-transpiler", + "openvm-riscv-adapters", + "openvm-riscv-circuit", + "openvm-riscv-transpiler", "openvm-stark-backend", "openvm-stark-sdk", "rand 0.9.4", @@ -4473,7 +4398,7 @@ dependencies = [ [[package]] name = "openvm-bigint-guest" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "openvm-platform", "strum_macros 0.26.4", @@ -4482,22 +4407,21 @@ dependencies = [ [[package]] name = "openvm-bigint-transpiler" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "openvm-bigint-guest", + "openvm-decoder", "openvm-instructions", "openvm-instructions-derive", - "openvm-rv32im-transpiler", - "openvm-stark-backend", + "openvm-riscv-transpiler", "openvm-transpiler", - "rrs-lib", "strum 0.26.3", ] [[package]] name = "openvm-build" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "cargo_metadata 0.18.1", "eyre", @@ -4509,10 +4433,10 @@ dependencies = [ [[package]] name = "openvm-circuit" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ - "abi_stable", "backtrace", + "bytemuck", "bytesize", "cfg-if 1.0.4", "dashmap", @@ -4532,6 +4456,7 @@ dependencies = [ "openvm-cuda-builder", "openvm-cuda-common", "openvm-instructions", + "openvm-platform", "openvm-poseidon2-air", "openvm-stark-backend", "openvm-stark-sdk", @@ -4539,6 +4464,8 @@ dependencies = [ "p3-field", "rand 0.9.4", "rustc-hash 2.1.1", + "rvr-openvm", + "rvr-state", "serde", "serde-big-array", "static_assertions", @@ -4549,7 +4476,7 @@ dependencies = [ [[package]] name = "openvm-circuit-derive" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "itertools 0.14.0", "proc-macro2", @@ -4560,7 +4487,7 @@ dependencies = [ [[package]] name = "openvm-circuit-primitives" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "derive-new 0.6.0", "itertools 0.14.0", @@ -4580,7 +4507,7 @@ dependencies = [ [[package]] name = "openvm-circuit-primitives-derive" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "itertools 0.14.0", "proc-macro2", @@ -4591,7 +4518,7 @@ dependencies = [ [[package]] name = "openvm-codec-derive" version = "2.0.0" -source = "git+https://github.com/openvm-org/stark-backend.git?tag=v2.0.0#16d60de724c21dcadfde7d8315a1db507e5832d7" +source = "git+https://github.com/openvm-org/stark-backend.git?branch=develop-v2.1.0#be2b6983cbd70976b37acbb72ceb1b3593dc67ae" dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", @@ -4602,7 +4529,7 @@ dependencies = [ [[package]] name = "openvm-continuations" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "cfg-if 1.0.4", "derivative", @@ -4616,6 +4543,7 @@ dependencies = [ "openvm-cpu-backend", "openvm-cuda-backend", "openvm-cuda-common", + "openvm-instructions", "openvm-poseidon2-air", "openvm-recursion-circuit", "openvm-recursion-circuit-derive", @@ -4633,7 +4561,7 @@ dependencies = [ [[package]] name = "openvm-cpu-backend" version = "2.0.0" -source = "git+https://github.com/openvm-org/stark-backend.git?tag=v2.0.0#16d60de724c21dcadfde7d8315a1db507e5832d7" +source = "git+https://github.com/openvm-org/stark-backend.git?branch=develop-v2.1.0#be2b6983cbd70976b37acbb72ceb1b3593dc67ae" dependencies = [ "cfg-if 1.0.4", "derive-new 0.7.0", @@ -4658,7 +4586,7 @@ dependencies = [ [[package]] name = "openvm-cuda-backend" version = "2.0.0" -source = "git+https://github.com/openvm-org/stark-backend.git?tag=v2.0.0#16d60de724c21dcadfde7d8315a1db507e5832d7" +source = "git+https://github.com/openvm-org/stark-backend.git?branch=develop-v2.1.0#be2b6983cbd70976b37acbb72ceb1b3593dc67ae" dependencies = [ "derive-new 0.7.0", "getset", @@ -4685,7 +4613,7 @@ dependencies = [ [[package]] name = "openvm-cuda-builder" version = "2.0.0" -source = "git+https://github.com/openvm-org/stark-backend.git?tag=v2.0.0#16d60de724c21dcadfde7d8315a1db507e5832d7" +source = "git+https://github.com/openvm-org/stark-backend.git?branch=develop-v2.1.0#be2b6983cbd70976b37acbb72ceb1b3593dc67ae" dependencies = [ "cc", "glob", @@ -4694,7 +4622,7 @@ dependencies = [ [[package]] name = "openvm-cuda-common" version = "2.0.0" -source = "git+https://github.com/openvm-org/stark-backend.git?tag=v2.0.0#16d60de724c21dcadfde7d8315a1db507e5832d7" +source = "git+https://github.com/openvm-org/stark-backend.git?branch=develop-v2.1.0#be2b6983cbd70976b37acbb72ceb1b3593dc67ae" dependencies = [ "bytesize", "ctor", @@ -4708,17 +4636,22 @@ dependencies = [ [[package]] name = "openvm-custom-insn" version = "0.1.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "proc-macro2", "quote", "syn 2.0.110", ] +[[package]] +name = "openvm-decoder" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" + [[package]] name = "openvm-deferral-circuit" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "cfg-if 1.0.4", "dashmap", @@ -4736,7 +4669,7 @@ dependencies = [ "openvm-deferral-transpiler", "openvm-instructions", "openvm-poseidon2-air", - "openvm-rv32im-circuit", + "openvm-riscv-circuit", "openvm-stark-backend", "openvm-stark-sdk", "p3-field", @@ -4748,7 +4681,7 @@ dependencies = [ [[package]] name = "openvm-deferral-guest" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "openvm-custom-insn", "strum_macros 0.26.4", @@ -4757,14 +4690,13 @@ dependencies = [ [[package]] name = "openvm-deferral-transpiler" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "eyre", "openvm-deferral-guest", "openvm-instructions", "openvm-instructions-derive", "openvm-transpiler", - "p3-field", "rrs-lib", "serde", "strum 0.26.3", @@ -4773,13 +4705,13 @@ dependencies = [ [[package]] name = "openvm-ecc-circuit" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "blstrs", "cfg-if 1.0.4", "derive-new 0.6.0", "derive_more 1.0.0", - "halo2curves-axiom 0.7.2 (git+https://github.com/axiom-crypto/halo2curves.git?tag=v0.7.2)", + "halo2curves-axiom 0.7.3", "hex-literal 1.1.0", "lazy_static", "num-bigint", @@ -4795,7 +4727,9 @@ dependencies = [ "openvm-ecc-transpiler", "openvm-instructions", "openvm-mod-circuit-builder", - "openvm-rv32-adapters", + "openvm-platform", + "openvm-riscv-adapters", + "openvm-riscv-circuit", "openvm-stark-backend", "openvm-stark-sdk", "rand 0.9.4", @@ -4807,18 +4741,18 @@ dependencies = [ [[package]] name = "openvm-ecc-guest" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "ecdsa", "elliptic-curve", "group 0.13.0", - "halo2curves-axiom 0.7.2 (git+https://github.com/axiom-crypto/halo2curves.git?tag=v0.7.2)", + "halo2curves-axiom 0.7.3", "once_cell", "openvm", "openvm-algebra-guest", "openvm-custom-insn", "openvm-ecc-sw-macros", - "openvm-rv32im-guest", + "openvm-riscv-guest", "serde", "strum_macros 0.26.4", ] @@ -4826,7 +4760,7 @@ dependencies = [ [[package]] name = "openvm-ecc-sw-macros" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "openvm-macros-common", "quote", @@ -4836,21 +4770,20 @@ dependencies = [ [[package]] name = "openvm-ecc-transpiler" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ + "openvm-decoder", "openvm-ecc-guest", "openvm-instructions", "openvm-instructions-derive", - "openvm-stark-backend", "openvm-transpiler", - "rrs-lib", "strum 0.26.3", ] [[package]] name = "openvm-instructions" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "backtrace", "derive-new 0.6.0", @@ -4858,7 +4791,6 @@ dependencies = [ "num-bigint", "num-traits", "openvm-instructions-derive", - "openvm-stark-backend", "serde", "strum 0.26.3", "strum_macros 0.26.4", @@ -4867,7 +4799,7 @@ dependencies = [ [[package]] name = "openvm-instructions-derive" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "quote", "syn 2.0.110", @@ -4876,7 +4808,7 @@ dependencies = [ [[package]] name = "openvm-keccak256" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "openvm-keccak256-guest", "spin 0.10.0", @@ -4885,7 +4817,7 @@ dependencies = [ [[package]] name = "openvm-keccak256-circuit" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "derive-new 0.6.0", "derive_more 1.0.0", @@ -4900,7 +4832,7 @@ dependencies = [ "openvm-cuda-common", "openvm-instructions", "openvm-keccak256-transpiler", - "openvm-rv32im-circuit", + "openvm-riscv-circuit", "openvm-stark-backend", "openvm-stark-sdk", "p3-keccak-air", @@ -4913,7 +4845,7 @@ dependencies = [ [[package]] name = "openvm-keccak256-guest" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "openvm-platform", ] @@ -4921,36 +4853,38 @@ dependencies = [ [[package]] name = "openvm-keccak256-transpiler" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ + "openvm-decoder", "openvm-instructions", "openvm-instructions-derive", "openvm-keccak256-guest", - "openvm-stark-backend", "openvm-transpiler", - "rrs-lib", "strum 0.26.3", ] [[package]] name = "openvm-macros-common" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "syn 2.0.110", ] +[[package]] +name = "openvm-mem" +version = "2.0.0" + [[package]] name = "openvm-mod-circuit-builder" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "itertools 0.14.0", "num-bigint", "num-traits", "openvm-circuit", "openvm-circuit-primitives", - "openvm-instructions", "openvm-stark-backend", "openvm-stark-sdk", "rand 0.8.6", @@ -4961,10 +4895,10 @@ dependencies = [ [[package]] name = "openvm-pairing" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "group 0.13.0", - "halo2curves-axiom 0.7.2 (git+https://github.com/axiom-crypto/halo2curves.git?tag=v0.7.2)", + "halo2curves-axiom 0.7.3", "hex-literal 1.1.0", "itertools 0.14.0", "num-bigint", @@ -4978,20 +4912,20 @@ dependencies = [ "openvm-ecc-sw-macros", "openvm-pairing-guest", "openvm-platform", - "openvm-rv32im-guest", + "openvm-riscv-guest", "serde", ] [[package]] name = "openvm-pairing-circuit" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "cfg-if 1.0.4", "derive-new 0.6.0", "derive_more 1.0.0", "eyre", - "halo2curves-axiom 0.7.2 (git+https://github.com/axiom-crypto/halo2curves.git?tag=v0.7.2)", + "halo2curves-axiom 0.7.3", "num-bigint", "num-traits", "openvm-algebra-circuit", @@ -5006,7 +4940,7 @@ dependencies = [ "openvm-mod-circuit-builder", "openvm-pairing-guest", "openvm-pairing-transpiler", - "openvm-rv32im-circuit", + "openvm-riscv-circuit", "openvm-stark-backend", "openvm-stark-sdk", "rand 0.9.4", @@ -5017,10 +4951,10 @@ dependencies = [ [[package]] name = "openvm-pairing-guest" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ - "blstrs", - "halo2curves-axiom 0.7.2 (git+https://github.com/axiom-crypto/halo2curves.git?tag=v0.7.2)", + "blst", + "halo2curves-axiom 0.7.3", "hex-literal 1.1.0", "itertools 0.14.0", "lazy_static", @@ -5038,30 +4972,30 @@ dependencies = [ [[package]] name = "openvm-pairing-transpiler" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ + "openvm-decoder", "openvm-instructions", "openvm-pairing-guest", - "openvm-stark-backend", "openvm-transpiler", - "rrs-lib", "strum 0.26.3", ] [[package]] name = "openvm-platform" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ + "critical-section", "libm", "openvm-custom-insn", - "openvm-rv32im-guest", + "openvm-riscv-guest", ] [[package]] name = "openvm-poseidon2-air" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "derivative", "lazy_static", @@ -5079,7 +5013,7 @@ dependencies = [ [[package]] name = "openvm-recursion-circuit" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "derive-new 0.6.0", "itertools 0.14.0", @@ -5107,16 +5041,16 @@ dependencies = [ [[package]] name = "openvm-recursion-circuit-derive" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "quote", "syn 2.0.110", ] [[package]] -name = "openvm-rv32-adapters" +name = "openvm-riscv-adapters" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "derive-new 0.6.0", "itertools 0.14.0", @@ -5124,16 +5058,16 @@ dependencies = [ "openvm-circuit-primitives", "openvm-circuit-primitives-derive", "openvm-instructions", - "openvm-rv32im-circuit", + "openvm-riscv-circuit", "openvm-stark-backend", "openvm-stark-sdk", "rand 0.9.4", ] [[package]] -name = "openvm-rv32im-circuit" +name = "openvm-riscv-circuit" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "cfg-if 1.0.4", "derive-new 0.6.0", @@ -5150,7 +5084,8 @@ dependencies = [ "openvm-cuda-builder", "openvm-cuda-common", "openvm-instructions", - "openvm-rv32im-transpiler", + "openvm-platform", + "openvm-riscv-transpiler", "openvm-stark-backend", "openvm-stark-sdk", "rand 0.9.4", @@ -5160,25 +5095,24 @@ dependencies = [ ] [[package]] -name = "openvm-rv32im-guest" +name = "openvm-riscv-guest" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "openvm-custom-insn", "strum_macros 0.26.4", ] [[package]] -name = "openvm-rv32im-transpiler" +name = "openvm-riscv-transpiler" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ + "openvm-decoder", "openvm-instructions", "openvm-instructions-derive", - "openvm-rv32im-guest", - "openvm-stark-backend", + "openvm-riscv-guest", "openvm-transpiler", - "rrs-lib", "serde", "strum 0.26.3", "tracing", @@ -5187,7 +5121,7 @@ dependencies = [ [[package]] name = "openvm-sdk" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "alloy-sol-types", "bitcode", @@ -5226,7 +5160,7 @@ dependencies = [ [[package]] name = "openvm-sdk-config" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "bon", "cfg-if 1.0.4", @@ -5247,8 +5181,8 @@ dependencies = [ "openvm-keccak256-transpiler", "openvm-pairing-circuit", "openvm-pairing-transpiler", - "openvm-rv32im-circuit", - "openvm-rv32im-transpiler", + "openvm-riscv-circuit", + "openvm-riscv-transpiler", "openvm-sha2-circuit", "openvm-sha2-transpiler", "openvm-stark-backend", @@ -5257,12 +5191,13 @@ dependencies = [ "openvm-verify-stark-circuit", "serde", "toml", + "tracing", ] [[package]] name = "openvm-sha2" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "openvm-sha2-guest", "sha2 0.10.9", @@ -5271,7 +5206,7 @@ dependencies = [ [[package]] name = "openvm-sha2-air" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "ndarray", "num_enum", @@ -5285,7 +5220,7 @@ dependencies = [ [[package]] name = "openvm-sha2-circuit" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "cfg-if 1.0.4", "derive-new 0.6.0", @@ -5301,7 +5236,7 @@ dependencies = [ "openvm-cuda-builder", "openvm-cuda-common", "openvm-instructions", - "openvm-rv32im-circuit", + "openvm-riscv-circuit", "openvm-sha2-air", "openvm-sha2-transpiler", "openvm-stark-backend", @@ -5314,7 +5249,7 @@ dependencies = [ [[package]] name = "openvm-sha2-guest" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "openvm-platform", ] @@ -5322,21 +5257,20 @@ dependencies = [ [[package]] name = "openvm-sha2-transpiler" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ + "openvm-decoder", "openvm-instructions", "openvm-instructions-derive", "openvm-sha2-guest", - "openvm-stark-backend", "openvm-transpiler", - "rrs-lib", "strum 0.26.3", ] [[package]] name = "openvm-stark-backend" version = "2.0.0" -source = "git+https://github.com/openvm-org/stark-backend.git?tag=v2.0.0#16d60de724c21dcadfde7d8315a1db507e5832d7" +source = "git+https://github.com/openvm-org/stark-backend.git?branch=develop-v2.1.0#be2b6983cbd70976b37acbb72ceb1b3593dc67ae" dependencies = [ "cfg-if 1.0.4", "derivative", @@ -5346,6 +5280,7 @@ dependencies = [ "hex-literal 1.1.0", "itertools 0.14.0", "metrics", + "mimalloc", "num-bigint", "openvm-codec-derive", "p3-air", @@ -5369,7 +5304,7 @@ dependencies = [ [[package]] name = "openvm-stark-sdk" version = "2.0.0" -source = "git+https://github.com/openvm-org/stark-backend.git?tag=v2.0.0#16d60de724c21dcadfde7d8315a1db507e5832d7" +source = "git+https://github.com/openvm-org/stark-backend.git?branch=develop-v2.1.0#be2b6983cbd70976b37acbb72ceb1b3593dc67ae" dependencies = [ "dashmap", "derive-new 0.7.0", @@ -5400,7 +5335,7 @@ dependencies = [ [[package]] name = "openvm-static-verifier" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "halo2-base", "itertools 0.14.0", @@ -5424,14 +5359,13 @@ dependencies = [ [[package]] name = "openvm-transpiler" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "elf", "eyre", + "openvm-decoder", "openvm-instructions", "openvm-platform", - "openvm-stark-backend", - "rrs-lib", "rustc-demangle", "thiserror 1.0.69", ] @@ -5439,7 +5373,7 @@ dependencies = [ [[package]] name = "openvm-verify-stark-circuit" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "bitcode", "cfg-if 1.0.4", @@ -5469,7 +5403,7 @@ dependencies = [ [[package]] name = "openvm-verify-stark-guest" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "openvm-deferral-guest", ] @@ -5477,7 +5411,7 @@ dependencies = [ [[package]] name = "openvm-verify-stark-host" version = "2.0.0" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "bitcode", "eyre", @@ -5516,7 +5450,7 @@ dependencies = [ [[package]] name = "p256" version = "0.13.2" -source = "git+https://github.com/openvm-org/openvm.git?tag=v2.0.0#15a7ab6baed03d75050dbef2bbad4b4e98fb8dba" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" dependencies = [ "ecdsa", "elliptic-curve", @@ -6419,15 +6353,6 @@ version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" -[[package]] -name = "repr_offset" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb1070755bd29dffc19d0971cab794e607839ba2ef4b69a9e6fbc8733c1b72ea" -dependencies = [ - "tstr", -] - [[package]] name = "reqwest" version = "0.12.24" @@ -7835,7 +7760,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -7865,6 +7790,61 @@ dependencies = [ "wait-timeout", ] +[[package]] +name = "ruzstd" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a252f5e20f038fe7b4ea53e073e65398d652c864cc162fc77c56c2f13717b888" +dependencies = [ + "twox-hash", +] + +[[package]] +name = "rvr-openvm" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" +dependencies = [ + "openvm-instructions", + "openvm-platform", + "rvr-openvm-build", + "rvr-openvm-ir", + "rvr-openvm-lift", + "rvr-state", + "thiserror 1.0.69", +] + +[[package]] +name = "rvr-openvm-build" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" + +[[package]] +name = "rvr-openvm-ir" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" +dependencies = [ + "serde", +] + +[[package]] +name = "rvr-openvm-lift" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" +dependencies = [ + "libloading", + "openvm-instructions", + "openvm-stark-backend", + "rustc-hash 2.1.1", + "rvr-openvm-ir", + "thiserror 1.0.69", + "tracing", +] + +[[package]] +name = "rvr-state" +version = "2.0.0" +source = "git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0#29fc511e6892a3e45455404f25293468bc880228" + [[package]] name = "ryu" version = "1.0.20" @@ -8122,7 +8102,7 @@ dependencies = [ "alloy-primitives", "bincode 2.0.1", "openvm", - "openvm-keccak256-guest", + "openvm-keccak256", "scroll-zkvm-types-bundle", "scroll-zkvm-types-circuit", ] @@ -8133,7 +8113,7 @@ version = "0.9.0" dependencies = [ "bincode 2.0.1", "ecies", - "k256 0.13.4 (git+https://github.com/openvm-org/openvm.git?tag=v2.0.0)", + "k256 0.13.4 (git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0)", "openvm", "openvm-algebra-complex-macros", "openvm-algebra-guest", @@ -8142,9 +8122,9 @@ dependencies = [ "openvm-keccak256", "openvm-pairing", "openvm-pairing-guest", - "openvm-rv32im-guest", + "openvm-riscv-guest", "openvm-sha2", - "p256 0.13.2 (git+https://github.com/openvm-org/openvm.git?tag=v2.0.0)", + "p256 0.13.2 (git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0)", "scroll-zkvm-types-chunk", "scroll-zkvm-types-circuit", ] @@ -8165,6 +8145,7 @@ dependencies = [ "clap", "csv", "dotenvy", + "encoder-standard", "eyre", "futures", "glob", @@ -8198,7 +8179,6 @@ dependencies = [ "tracing", "tracing-subscriber 0.3.20", "url", - "vm-zstd", ] [[package]] @@ -8211,6 +8191,8 @@ dependencies = [ "eyre", "git-version", "hex", + "metrics", + "metrics-util", "openvm-circuit", "openvm-continuations", "openvm-cuda-backend", @@ -8245,6 +8227,7 @@ dependencies = [ "once_cell", "openvm-circuit", "openvm-sdk", + "openvm-sdk-config", "openvm-stark-sdk", "openvm-static-verifier", "openvm-verify-stark-host", @@ -8275,7 +8258,7 @@ version = "0.9.0" dependencies = [ "alloy-primitives", "c-kzg", - "halo2curves-axiom 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "halo2curves-axiom 0.7.2", "itertools 0.14.0", "openvm", "openvm-algebra-guest", @@ -8283,10 +8266,10 @@ dependencies = [ "openvm-pairing", "openvm-pairing-guest", "openvm-sha2", + "ruzstd", "sbv-primitives", "scroll-zkvm-types-base", "serde", - "vm-zstd", ] [[package]] @@ -8311,12 +8294,12 @@ dependencies = [ "ecies", "hex-literal 0.4.1", "itertools 0.14.0", - "k256 0.13.4 (git+https://github.com/openvm-org/openvm.git?tag=v2.0.0)", + "k256 0.13.4 (git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0)", "openvm-ecc-guest", "openvm-pairing", "openvm-pairing-guest", "openvm-sha2", - "p256 0.13.2 (git+https://github.com/openvm-org/openvm.git?tag=v2.0.0)", + "p256 0.13.2 (git+https://github.com/openvm-org/openvm.git?branch=develop-v2.1.0)", "sbv-core", "sbv-helpers", "sbv-primitives", @@ -8335,7 +8318,7 @@ dependencies = [ "openvm", "openvm-custom-insn", "openvm-deferral-guest", - "openvm-rv32im-guest", + "openvm-riscv-guest", "openvm-verify-stark-guest", "scroll-zkvm-types-base", ] @@ -8730,7 +8713,7 @@ checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" [[package]] name = "snark-verifier" version = "0.2.6" -source = "git+https://github.com/axiom-crypto/snark-verifier.git?tag=v0.2.6#89abe4719d54c68ba07480a1b2204d736cdf0fec" +source = "git+https://github.com/axiom-crypto/snark-verifier.git?branch=develop-v2.1.0#369f98ff87dbdde689ec576aa9c5fd2609599481" dependencies = [ "halo2-base", "halo2-ecc", @@ -8751,7 +8734,7 @@ dependencies = [ [[package]] name = "snark-verifier-sdk" version = "0.2.6" -source = "git+https://github.com/axiom-crypto/snark-verifier.git?tag=v0.2.6#89abe4719d54c68ba07480a1b2204d736cdf0fec" +source = "git+https://github.com/axiom-crypto/snark-verifier.git?branch=develop-v2.1.0#369f98ff87dbdde689ec576aa9c5fd2609599481" dependencies = [ "ark-std 0.3.0", "bincode 1.3.3", @@ -8875,12 +8858,6 @@ dependencies = [ "syn 2.0.110", ] -[[package]] -name = "strum" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" - [[package]] name = "strum" version = "0.26.3" @@ -8899,26 +8876,13 @@ dependencies = [ "strum_macros 0.27.2", ] -[[package]] -name = "strum_macros" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.110", -] - [[package]] name = "strum_macros" version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", "rustversion", @@ -8931,7 +8895,7 @@ version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", "syn 2.0.110", @@ -9027,7 +8991,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -9470,25 +9434,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] -name = "tstr" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f8e0294f14baae476d0dd0a2d780b2e24d66e349a9de876f5126777a37bdba7" -dependencies = [ - "tstr_proc_macros", -] - -[[package]] -name = "tstr_proc_macros" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78122066b0cb818b8afd08f7ed22f7fdbc3e90815035726f0840d0d26c0747a" - -[[package]] -name = "typed-arena" -version = "2.0.2" +name = "twox-hash" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" +checksum = "5283634e518fe9e82c7b20520bb4bc209009fd16c82077c802f8111ecbb0117a" [[package]] name = "typenum" @@ -9496,12 +9445,6 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" -[[package]] -name = "typewit" -version = "1.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8c1ae7cc0fdb8b842d65d127cb981574b0d2b249b74d1c7a2986863dc134f71" - [[package]] name = "ucd-trie" version = "0.1.7" @@ -9618,20 +9561,6 @@ version = "0.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1" -[[package]] -name = "vm-zstd" -version = "0.1.1" -source = "git+https://github.com/scroll-tech/rust-zstd-decompressor.git?rev=b027327#b0273278316245fef733df54cc29ee3baa3d7382" -dependencies = [ - "anyhow", - "bitstream-io", - "encoder-standard", - "itertools 0.11.0", - "serde", - "strum 0.25.0", - "strum_macros 0.25.3", -] - [[package]] name = "wait-timeout" version = "0.2.1" @@ -9779,7 +9708,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 41ae7a6f..a2d3bfd7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,54 +26,55 @@ version = "0.9.0" [workspace.dependencies] # openvm guest libs -openvm = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0" } -openvm-algebra-complex-macros = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-custom-insn = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-sha2 = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0" } -openvm-sha2-guest = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-p256 = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", package = "p256", features = [ +openvm = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0" } +openvm-algebra-complex-macros = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-custom-insn = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-sha2 = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0" } +openvm-sha2-guest = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-p256 = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", package = "p256", features = [ "std", ] } -openvm-k256 = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", package = "k256", features = [ +openvm-k256 = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", package = "k256", features = [ "std", ] } -openvm-pairing = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0" } -openvm-keccak256 = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-keccak256-guest = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-algebra-guest = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-ecc-guest = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-bigint-guest = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-pairing-guest = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-rv32im-guest = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } +openvm-pairing = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0" } +openvm-keccak256 = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-keccak256-guest = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-algebra-guest = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-ecc-guest = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-bigint-guest = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-pairing-guest = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-riscv-guest = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } # openvm host libs -openvm-benchmarks-prove = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-benchmarks-utils = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-build = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-circuit = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-continuations = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-instructions = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-sdk-config = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-static-verifier = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-verify-stark-host = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-recursion-circuit = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-verify-stark-guest = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-verify-stark-circuit = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-deferral-circuit = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-cuda-backend = { git = "https://github.com/openvm-org/stark-backend.git", tag = "v2.0.0", default-features = false } -openvm-deferral-guest = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-rv32im-transpiler = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } -openvm-sdk = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false, features = [ +openvm-benchmarks-prove = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-benchmarks-utils = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-build = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-circuit = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-continuations = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-instructions = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-sdk-config = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-static-verifier = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-verify-stark-host = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-recursion-circuit = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-verify-stark-guest = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-verify-stark-circuit = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-deferral-circuit = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-cuda-backend = { git = "https://github.com/openvm-org/stark-backend.git", branch = "develop-v2.1.0", default-features = false } +openvm-deferral-guest = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-riscv-transpiler = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } +openvm-sdk = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false, features = [ "parallel", "evm-prove", "tco", - "unprotected" + "unprotected", + "mimalloc" ] } -openvm-transpiler = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.0", default-features = false } +openvm-transpiler = { git = "https://github.com/openvm-org/openvm.git", branch = "develop-v2.1.0", default-features = false } # more openvm related libs -openvm-stark-backend = { git = "https://github.com/openvm-org/stark-backend.git", tag = "v2.0.0", default-features = false } -openvm-stark-sdk = { git = "https://github.com/openvm-org/stark-backend.git", tag = "v2.0.0", default-features = false } +openvm-stark-backend = { git = "https://github.com/openvm-org/stark-backend.git", branch = "develop-v2.1.0", default-features = false } +openvm-stark-sdk = { git = "https://github.com/openvm-org/stark-backend.git", branch = "develop-v2.1.0", default-features = false } sbv-core = { git = "https://github.com/scroll-tech/stateless-block-verifier", tag = "scroll-v91.2" } sbv-helpers = { git = "https://github.com/scroll-tech/stateless-block-verifier", tag = "scroll-v91.2", features = ["dev"] } @@ -120,7 +121,7 @@ serde = { version = "1", default-features = false, features = ["derive"] } serde_json = { version = "1.0" } serde_with = "3.11.0" base64 = "0.22" -snark-verifier-sdk = { git = "https://github.com/axiom-crypto/snark-verifier.git", tag = "v0.2.6", default-features = false, features = [ +snark-verifier-sdk = { git = "https://github.com/axiom-crypto/snark-verifier.git", branch = "develop-v2.1.0", default-features = false, features = [ "loader_halo2", "display", "revm", @@ -128,7 +129,7 @@ snark-verifier-sdk = { git = "https://github.com/axiom-crypto/snark-verifier.git tiny-keccak = "2.0" thiserror = "2" tracing = "0.1" -vm-zstd = { git = "https://github.com/scroll-tech/rust-zstd-decompressor.git", rev = "b027327" } +encoder-standard = { git = "https://github.com/scroll-tech/da-codec.git" } toml = "0.8.14" tracing-subscriber = "0.3" sysinfo = { version = "0.35", default-features = false } @@ -162,11 +163,24 @@ revm-precompile = { git = "https://github.com/scroll-tech/revm", tag = "scroll-v revm-primitives = { git = "https://github.com/scroll-tech/revm", tag = "scroll-v91" } revm-state = { git = "https://github.com/scroll-tech/revm", tag = "scroll-v91" } +# openvm-mem's copy_forward/copy_backward use 64-byte aggregate copies that LLVM lowers +# into `memmove` calls, making `memmove` recurse until the guest stack overflows. +# Override with a local copy that uses u64 chunks instead. See patches/openvm-mem. +# (Two further guest-cycle patches — openvm-keccak256-guest and risc0-ethereum-trie — +# were tried, measured at −12.1% chunk cycles, and reverted as not worth the fork. +# See AGENTS.md "Cycle-optimization experiments" and commit 430b7acc.) +[patch."https://github.com/openvm-org/openvm.git"] +openvm-mem = { path = "patches/openvm-mem" } + [profile.maxperf] inherits = "release" lto = "fat" codegen-units = 1 +[profile.release] +lto = "thin" +codegen-units = 1 + [profile.profiling] inherits = "release" debug = 2 diff --git a/Dockerfile b/Dockerfile index dff929ec..f28a405d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,11 +2,17 @@ FROM rust:1.93 WORKDIR /app -# Install the nightly toolchain used by openvm-build for guest programs, -# plus the RISC-V target and rust-src needed for -Z build-std. -RUN rustup toolchain install nightly-2025-11-20 && \ - rustup target add --toolchain nightly-2025-11-20 riscv32im-unknown-none-elf && \ - rustup component add --toolchain nightly-2025-11-20 rust-src llvm-tools rustc-dev +# Host toolchain required by rust-toolchain.toml (openvm-sdk "tco" feature). +RUN rustup toolchain install nightly-2026-01-18 && \ + rustup component add --toolchain nightly-2026-01-18 llvm-tools rustc-dev + +# cargo-openvm CLI from the pinned OpenVM rev, plus the RV64 guest toolchain +# (installs the `openvm-1.94.1` rustup toolchain used by openvm-build). +RUN cargo install --locked --git https://github.com/openvm-org/openvm.git --rev fc1a0001e63d5685fb40c1ffb10c6ce0d55677ce cargo-openvm && \ + cargo openvm toolchain install && \ + ln -s "$(rustup which cargo)" "$(dirname "$(rustup +openvm-1.94.1 which rustc)")/cargo" + +ENV OPENVM_RUST_TOOLCHAIN=openvm-1.94.1 RUN wget https://github.com/ethereum/solc-bin/raw/refs/heads/gh-pages/linux-amd64/solc-linux-amd64-v0.8.19+commit.7dd6d404 -O /usr/local/bin/solc && \ chmod +x /usr/local/bin/solc diff --git a/Makefile b/Makefile index 919c9eb1..35c805b9 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ export RUST_BACKTRACE RUST_LOG ?= off,scroll_zkvm_integration=debug,scroll_zkvm_verifier=debug,scroll_zkvm_prover=debug,p3_fri=warn,p3_dft=warn,openvm_circuit=warn export RUST_LOG -OPENVM_RUST_TOOLCHAIN ?= nightly-2025-11-20 +OPENVM_RUST_TOOLCHAIN ?= openvm-1.94.1 export OPENVM_RUST_TOOLCHAIN # Set GPU config if GPU=1 is set diff --git a/build-guest.sh b/build-guest.sh index 7c1b5239..169dd979 100755 --- a/build-guest.sh +++ b/build-guest.sh @@ -20,8 +20,11 @@ cleanup() { # set trap to cleanup on exit trap cleanup EXIT -# run docker image -docker run --cidfile ./build-guest.cid --platform linux/amd64 build-guest:local make build-guest-local +# run docker image (mount host SRS params: local EVM verifier generation needs them) +mkdir -p "$HOME/.openvm/params" +docker run --cidfile ./build-guest.cid --platform linux/amd64 \ + -v "$HOME/.openvm/params:/root/.openvm/params:ro" \ + build-guest:local make build-guest-local container_id=$(cat ./build-guest.cid) # copy vm commitments from container to local diff --git a/crates/build-guest/Cargo.toml b/crates/build-guest/Cargo.toml index 5fec3fda..e36681dc 100644 --- a/crates/build-guest/Cargo.toml +++ b/crates/build-guest/Cargo.toml @@ -31,3 +31,5 @@ clap = { version = "4.0", features = ["derive"] } [features] default = ["scroll"] scroll = ["scroll-zkvm-types/scroll"] +# Bake function bounds into .vmexe files for guest cycle profiling. +perf-metrics = ["openvm-sdk/perf-metrics"] diff --git a/crates/build-guest/src/main.rs b/crates/build-guest/src/main.rs index 830a2422..de4b6115 100644 --- a/crates/build-guest/src/main.rs +++ b/crates/build-guest/src/main.rs @@ -40,7 +40,7 @@ use openvm_continuations::CommitBytes; use openvm_instructions::exe::VmExe; use openvm_recursion_circuit::batch_constraint::commit_child_vk; use openvm_sdk::{ - F, Sdk, + Sdk, config::{AggregationConfig, AggregationSystemParams, AggregationTreeConfig, AppConfig}, fs::write_object_to_file, prover::MultiDeferralCircuitProver, @@ -267,6 +267,21 @@ fn generate_app_assets(workspace_dir: &Path, release_output_dir: &PathBuf) -> Re // 1. Build ELF + // Create the assets dir if not already present. + let path_assets = Path::new(release_output_dir).join(project_name); + fs::create_dir_all(&path_assets)?; + + // With `perf-metrics`, the transpiler records function bounds in the exe and + // requires GUEST_SYMBOLS_PATH to dump the demangled symbol table (consumed by + // scripts/flamegraph.py --guest-symbols). `sdk.build` already decodes the ELF, + // so this must be set before it. + #[cfg(feature = "perf-metrics")] + { + let guest_symbols_path = path_assets.join("guest.symbols"); + println!("{LOG_PREFIX} GUEST_SYMBOLS_PATH={guest_symbols_path:?}"); + std::env::set_var("GUEST_SYMBOLS_PATH", &guest_symbols_path); + } + // Store current directory and change to project directory let original_dir = env::current_dir()?; env::set_current_dir(&project_path)?; @@ -297,12 +312,9 @@ fn generate_app_assets(workspace_dir: &Path, release_output_dir: &PathBuf) -> Re original_dir.display() ); - // Create the assets dir if not already present. - let path_assets = Path::new(release_output_dir).join(project_name); - fs::create_dir_all(&path_assets)?; let elf_src = workspace_dir .join("target") - .join("riscv32im-risc0-zkvm-elf") + .join("riscv64im-unknown-openvm-elf") .join("maxperf") .join(format!("scroll-zkvm-{project_name}-circuit")); let path_app_elf: PathBuf = path_assets.join("app.elf"); @@ -310,7 +322,29 @@ fn generate_app_assets(workspace_dir: &Path, release_output_dir: &PathBuf) -> Re println!("{LOG_PREFIX} elf written to {path_app_elf:?}"); // 2. Transpile ELF to VM Executable - let app_exe: VmExe = (*sdk.convert_to_exe(elf)?).clone(); + let app_exe: VmExe = (*sdk.convert_to_exe(elf)?).clone(); + + // openvm's `update_current_fn` unwraps the greatest function bound <= pc, + // which panics if execution touches a pc below the first STT_FUNC symbol + // (entry trampolines etc.). Cover that range with a synthetic bound whose + // name is offset 0 in the symbols string table (the empty string). + #[cfg(feature = "perf-metrics")] + let app_exe = { + let mut app_exe = app_exe; + if let Some((&min_start, _)) = app_exe.fn_bounds.iter().next() { + if min_start > 0 { + app_exe.fn_bounds.insert( + 0, + openvm_instructions::exe::FnBound { + start: 0, + end: min_start - 1, + name: "0".to_string(), + }, + ); + } + } + app_exe + }; // Write exe to disc. let path_app_exe: PathBuf = path_assets.join("app.vmexe"); @@ -446,7 +480,7 @@ fn build_recompute_sdk( let batch_app_config: AppConfig = if batch_config_path.exists() { toml::from_str(&fs::read_to_string(&batch_config_path)?)? } else { - AppConfig::riscv32(app_params.clone()) + AppConfig::riscv64(app_params.clone()) }; let batch_sdk = Sdk::builder() .app_config(batch_app_config) @@ -459,7 +493,7 @@ fn build_recompute_sdk( let bundle_app_config: AppConfig = if bundle_config_path.exists() { toml::from_str(&fs::read_to_string(&bundle_config_path)?)? } else { - AppConfig::riscv32(app_params.clone()) + AppConfig::riscv64(app_params.clone()) }; // The bundle's deferral circuit verifies batch proofs; its memory layout must @@ -486,6 +520,10 @@ pub fn build_evm_verifier( let agg_params = default_agg_params(); let sdk = build_recompute_sdk(release_output_dir, &app_params, &agg_params)?; let verifier = sdk.generate_halo2_verifier_solidity()?; + // NOTE: as of openvm develop-v2.1.0 (commit b3c95cd00 "restore byte-sized + // public values"), user public values are single bytes again, matching the + // SDK's Solidity template. The previous u16-cell workaround + // (patch_verifier_for_u16_public_values) is no longer applied. Ok((sdk, verifier)) } @@ -555,15 +593,15 @@ fn compile_solidity_bytecode(verifier_output_dir: &Path) -> Result> { // matches as closely as possible. let sources: std::collections::HashMap = [ ( - "src/v2.0-deferral/interfaces/IOpenVmHalo2Verifier.sol".to_string(), + "src/v2.1-deferral/interfaces/IOpenVmHalo2Verifier.sol".to_string(), read(&interface_path)?, ), ( - "src/v2.0-deferral/Halo2Verifier.sol".to_string(), + "src/v2.1-deferral/Halo2Verifier.sol".to_string(), read(&halo2_path)?, ), ( - "src/v2.0-deferral/OpenVmHalo2Verifier.sol".to_string(), + "src/v2.1-deferral/OpenVmHalo2Verifier.sol".to_string(), read(&parent_path)?, ), ] @@ -640,7 +678,7 @@ fn compile_solidity_bytecode(verifier_output_dir: &Path) -> Result> { let bytecode_hex = parsed .get("contracts") - .and_then(|c| c.get("src/v2.0-deferral/OpenVmHalo2Verifier.sol")) + .and_then(|c| c.get("src/v2.1-deferral/OpenVmHalo2Verifier.sol")) .and_then(|c| c.get("OpenVmHalo2Verifier")) .and_then(|c| c.get("evm")) .and_then(|c| c.get("bytecode")) @@ -703,7 +741,7 @@ fn generate_evm_verifier( } RecomputeMode::No => { println!("{LOG_PREFIX} RECOMPUTE_MODE=no: downloading pre-built verifier only."); - let sdk = Sdk::riscv32(app_params, agg_params); + let sdk = Sdk::riscv64(app_params, agg_params); let verifier = verifier::download_evm_verifier()?; write_evm_verifier_artifacts(verifier_output_dir, &verifier, &sdk, force_overwrite)?; } @@ -714,7 +752,7 @@ fn generate_evm_verifier( match verifier::download_evm_verifier() { Ok(verifier) => { println!("{LOG_PREFIX} Download succeeded; using pre-built verifier."); - let sdk = Sdk::riscv32(app_params, agg_params); + let sdk = Sdk::riscv64(app_params, agg_params); write_evm_verifier_artifacts( verifier_output_dir, &verifier, diff --git a/crates/build-guest/src/verifier.rs b/crates/build-guest/src/verifier.rs index 1fec1cdc..18d38a16 100644 --- a/crates/build-guest/src/verifier.rs +++ b/crates/build-guest/src/verifier.rs @@ -10,11 +10,12 @@ use eyre::Result; pub fn download_evm_verifier() -> Result { // The `openvm-solidity-sdk` release tag to download from. This is NOT the // same as the `openvm` crate version; the SDK follows its own tagging. - let solidity_sdk_tag = "v2.0"; + let solidity_sdk_tag = "v2.1"; // We generate/download the bundle (deferral-enabled) verifier. The plain - // `v2.0-base` verifier is used for leaf circuits that do not defer proof - // verification. - let verifier_path = "v2.0-deferral"; + // `v2.1-base` verifier is used for leaf circuits that do not defer proof + // verification. Note: openvm-solidity-sdk has not published a v2.1 tag yet, + // so the download will fail and auto mode falls back to local generation. + let verifier_path = "v2.1-deferral"; let verifier_url = format!( "https://raw.githubusercontent.com/openvm-org/openvm-solidity-sdk/{solidity_sdk_tag}/src/{verifier_path}/OpenVmHalo2Verifier.sol" ); diff --git a/crates/circuits/batch-circuit/batch_exe_commit.rs b/crates/circuits/batch-circuit/batch_exe_commit.rs index ed996ef2..e5495f4b 100644 --- a/crates/circuits/batch-circuit/batch_exe_commit.rs +++ b/crates/circuits/batch-circuit/batch_exe_commit.rs @@ -1,4 +1,4 @@ #![cfg_attr(rustfmt, rustfmt_skip)] //! Generated by crates/build-guest. DO NOT EDIT! -pub const COMMIT: [u32; 8] = [1863431439, 1670830010, 33016243, 26011158, 931370893, 994260763, 630117706, 207332781]; +pub const COMMIT: [u32; 8] = [236400959, 1921678370, 1681141574, 435295083, 1495503815, 21325623, 212114691, 392953574]; diff --git a/crates/circuits/batch-circuit/batch_vm_commit.rs b/crates/circuits/batch-circuit/batch_vm_commit.rs index 9129f9cc..9c3722b8 100644 --- a/crates/circuits/batch-circuit/batch_vm_commit.rs +++ b/crates/circuits/batch-circuit/batch_vm_commit.rs @@ -1,4 +1,4 @@ #![cfg_attr(rustfmt, rustfmt_skip)] //! Generated by crates/build-guest. DO NOT EDIT! -pub const COMMIT: [u32; 8] = [405660519, 24296687, 1842754465, 1433680155, 781042942, 896967232, 568979095, 327499695]; +pub const COMMIT: [u32; 8] = [628643739, 1391655643, 612908973, 1977999238, 335322123, 1575930128, 1995361175, 572648692]; diff --git a/crates/circuits/batch-circuit/openvm.toml b/crates/circuits/batch-circuit/openvm.toml index a309c5b2..bfb51ff7 100644 --- a/crates/circuits/batch-circuit/openvm.toml +++ b/crates/circuits/batch-circuit/openvm.toml @@ -5,9 +5,9 @@ num_queries = 100 commit_proof_of_work_bits = 16 query_proof_of_work_bits = 16 -[app_vm_config.rv32i] +[app_vm_config.rv64i] -[app_vm_config.rv32m] +[app_vm_config.rv64m] [app_vm_config.io] diff --git a/crates/circuits/batch-circuit/src/circuit.rs b/crates/circuits/batch-circuit/src/circuit.rs index bae66db0..3ef4a6b1 100644 --- a/crates/circuits/batch-circuit/src/circuit.rs +++ b/crates/circuits/batch-circuit/src/circuit.rs @@ -86,10 +86,13 @@ impl AggCircuit for BatchCircuit { proofs .iter() .map(|proof| { + // Each public value cell is a single byte; the pi hash occupies all + // 32 cells. let transformed = proof .public_values .iter() - .map(|&val| u8::try_from(val).expect("0 < public value < 256")) + .take(32) + .map(|&val| val as u8) .collect::>(); B256::from_slice(transformed.as_slice()) }) diff --git a/crates/circuits/bundle-circuit/Cargo.toml b/crates/circuits/bundle-circuit/Cargo.toml index 9319ec41..fcee2adc 100644 --- a/crates/circuits/bundle-circuit/Cargo.toml +++ b/crates/circuits/bundle-circuit/Cargo.toml @@ -11,9 +11,9 @@ scroll-zkvm-types-circuit.workspace = true scroll-zkvm-types-bundle.workspace = true openvm = { workspace = true, features = ["std"] } -openvm-keccak256-guest.workspace = true +openvm-keccak256 = { workspace = true } -alloy-primitives = { workspace = true } +alloy-primitives = { workspace = true, features = ["native-keccak"] } [features] default = [] diff --git a/crates/circuits/bundle-circuit/bundle_exe_commit.rs b/crates/circuits/bundle-circuit/bundle_exe_commit.rs index 0367eaa9..80971976 100644 --- a/crates/circuits/bundle-circuit/bundle_exe_commit.rs +++ b/crates/circuits/bundle-circuit/bundle_exe_commit.rs @@ -1,4 +1,4 @@ #![cfg_attr(rustfmt, rustfmt_skip)] //! Generated by crates/build-guest. DO NOT EDIT! -pub const COMMIT: [u32; 8] = [230646913, 1550155984, 1593546189, 445636947, 993877920, 922842868, 418587344, 1363280000]; +pub const COMMIT: [u32; 8] = [159067914, 70283829, 1094250858, 1695200420, 1766304820, 1211651143, 955692376, 2323832]; diff --git a/crates/circuits/bundle-circuit/bundle_vm_commit.rs b/crates/circuits/bundle-circuit/bundle_vm_commit.rs index fefe129f..8457738a 100644 --- a/crates/circuits/bundle-circuit/bundle_vm_commit.rs +++ b/crates/circuits/bundle-circuit/bundle_vm_commit.rs @@ -1,4 +1,4 @@ #![cfg_attr(rustfmt, rustfmt_skip)] //! Generated by crates/build-guest. DO NOT EDIT! -pub const COMMIT: [u32; 8] = [1986621377, 858531750, 1460740544, 1489416258, 402142684, 1028207948, 2010771520, 956067622]; +pub const COMMIT: [u32; 8] = [1473077767, 915340244, 1015753118, 931874796, 1629597349, 1264003766, 1595028109, 54844257]; diff --git a/crates/circuits/bundle-circuit/openvm.toml b/crates/circuits/bundle-circuit/openvm.toml index a727c8fc..277ae5f1 100644 --- a/crates/circuits/bundle-circuit/openvm.toml +++ b/crates/circuits/bundle-circuit/openvm.toml @@ -5,9 +5,9 @@ num_queries = 100 commit_proof_of_work_bits = 16 query_proof_of_work_bits = 16 -[app_vm_config.rv32i] +[app_vm_config.rv64i] -[app_vm_config.rv32m] +[app_vm_config.rv64m] [app_vm_config.io] diff --git a/crates/circuits/bundle-circuit/src/circuit.rs b/crates/circuits/bundle-circuit/src/circuit.rs index a7e8b4dc..38978b54 100644 --- a/crates/circuits/bundle-circuit/src/circuit.rs +++ b/crates/circuits/bundle-circuit/src/circuit.rs @@ -15,7 +15,7 @@ use scroll_zkvm_types_circuit::{ use crate::child_commitments; #[allow(unused_imports, clippy::single_component_path_imports)] -use openvm_keccak256_guest; +use openvm_keccak256; // trigger extern native-keccak256 #[derive(Default)] pub struct BundleCircuit; @@ -79,10 +79,13 @@ impl AggCircuit for BundleCircuit { proofs .iter() .map(|proof| { + // Each public value cell is a single byte; the pi hash occupies all + // 32 cells. let transformed = proof .public_values .iter() - .map(|&val| u8::try_from(val).expect("0 < public value < 256")) + .take(32) + .map(|&val| val as u8) .collect::>(); B256::from_slice(transformed.as_slice()) }) diff --git a/crates/circuits/chunk-circuit/Cargo.toml b/crates/circuits/chunk-circuit/Cargo.toml index 9318aed9..b64aa42c 100644 --- a/crates/circuits/chunk-circuit/Cargo.toml +++ b/crates/circuits/chunk-circuit/Cargo.toml @@ -22,7 +22,7 @@ openvm-ecc-guest = { workspace = true } openvm-keccak256 = { workspace = true } openvm-pairing-guest = { workspace = true, features = ["bn254"] } openvm-sha2 = { workspace = true } -openvm-rv32im-guest= { workspace = true } +openvm-riscv-guest= { workspace = true } [features] diff --git a/crates/circuits/chunk-circuit/chunk_exe_commit.rs b/crates/circuits/chunk-circuit/chunk_exe_commit.rs index 67a4cc79..37f12f0d 100644 --- a/crates/circuits/chunk-circuit/chunk_exe_commit.rs +++ b/crates/circuits/chunk-circuit/chunk_exe_commit.rs @@ -1,4 +1,4 @@ #![cfg_attr(rustfmt, rustfmt_skip)] //! Generated by crates/build-guest. DO NOT EDIT! -pub const COMMIT: [u32; 8] = [531865979, 758192281, 811911046, 811449566, 1267419821, 805792427, 542783805, 385536798]; +pub const COMMIT: [u32; 8] = [1192406321, 1007067640, 1433639583, 1891545475, 903990723, 621677400, 1106027141, 1005293682]; diff --git a/crates/circuits/chunk-circuit/chunk_vm_commit.rs b/crates/circuits/chunk-circuit/chunk_vm_commit.rs index 377afbee..a9bced4b 100644 --- a/crates/circuits/chunk-circuit/chunk_vm_commit.rs +++ b/crates/circuits/chunk-circuit/chunk_vm_commit.rs @@ -1,4 +1,4 @@ #![cfg_attr(rustfmt, rustfmt_skip)] //! Generated by crates/build-guest. DO NOT EDIT! -pub const COMMIT: [u32; 8] = [555659689, 632784023, 888007277, 1549787677, 735342146, 1738460513, 1543370985, 1220762107]; +pub const COMMIT: [u32; 8] = [322604582, 189444280, 87460111, 1707829116, 1997509938, 1357280705, 319517109, 1974772180]; diff --git a/crates/circuits/chunk-circuit/openvm.toml b/crates/circuits/chunk-circuit/openvm.toml index 9ddc457b..896f4bfc 100644 --- a/crates/circuits/chunk-circuit/openvm.toml +++ b/crates/circuits/chunk-circuit/openvm.toml @@ -5,13 +5,13 @@ num_queries = 100 commit_proof_of_work_bits = 16 query_proof_of_work_bits = 16 -[app_vm_config.rv32i] +[app_vm_config.rv64i] [app_vm_config.io] [app_vm_config.keccak] -[app_vm_config.rv32m] +[app_vm_config.rv64m] range_tuple_checker_sizes = [256, 8192] [app_vm_config.bigint] diff --git a/crates/integration/Cargo.toml b/crates/integration/Cargo.toml index 9118616d..4b6554a7 100644 --- a/crates/integration/Cargo.toml +++ b/crates/integration/Cargo.toml @@ -45,7 +45,7 @@ eyre.workspace = true rayon.workspace = true serde.workspace = true futures.workspace = true -vm-zstd = { workspace = true, features = ["zstd"] } +encoder-standard = { workspace = true } tokio = { workspace = true, features = ["full"] } hex.workspace = true @@ -75,4 +75,4 @@ cuda = ["scroll-zkvm-prover/cuda"] # halo2 (SNARK) proving on GPU; implies cuda. VRAM-heavy, see scroll-zkvm-prover. halo2-gpu = ["scroll-zkvm-prover/halo2-gpu"] limit-logs = [] -perf-metrics = ["openvm-sdk/perf-metrics"] +perf-metrics = ["openvm-sdk/perf-metrics", "scroll-zkvm-prover/perf-metrics"] diff --git a/crates/integration/src/lib.rs b/crates/integration/src/lib.rs index 46039a5e..9cc3b564 100644 --- a/crates/integration/src/lib.rs +++ b/crates/integration/src/lib.rs @@ -1,7 +1,11 @@ use cargo_metadata::MetadataCommand; use once_cell::sync::OnceCell; use openvm_circuit::arch::deferral::DeferralState; +use openvm_sdk::config::AggregationSystemParams; use openvm_sdk::{DeferralInput, Sdk, StdIn}; +use openvm_stark_sdk::config::{ + internal_params_with_100_bits_security, leaf_params_with_100_bits_security, +}; use openvm_stark_sdk::openvm_stark_backend::codec::Decode; use openvm_verify_stark_circuit::extension::{get_deferral_state, get_raw_deferral_results}; use openvm_verify_stark_host::{ @@ -20,7 +24,7 @@ use scroll_zkvm_types::{ types_agg::ProgramCommitment, utils::serialize_vk, }; -use scroll_zkvm_verifier::verifier::{AGG_STARK_PROVING_KEY, UniversalVerifier}; +use scroll_zkvm_verifier::verifier::UniversalVerifier; use std::collections::HashMap; use std::{ io::Cursor, @@ -409,13 +413,23 @@ pub fn tester_execute( .map(|p| p.as_stark_proof().expect("must be stark proof")), )?; - let _app_vm_config = app_config.app_vm_config.clone(); + // Use the circuit-specific app config so the executor supports all required + // extensions (keccak, ecc, pairing, etc.). Aggregation params are only needed + // to satisfy the SDK builder; key generation is lazy and never triggered by + // the execution-only test path. let sdk = Sdk::builder() .app_config(app_config) - .agg_pk(AGG_STARK_PROVING_KEY.clone()) + .agg_params(AggregationSystemParams { + leaf: leaf_params_with_100_bits_security(), + internal: internal_params_with_100_bits_security(), + }) .build() .map_err(|e| eyre::eyre!("sdk build failed: {e}"))?; + #[cfg(feature = "perf-metrics")] + scroll_zkvm_prover::prover::profile_dump::install(); let ret = scroll_zkvm_prover::utils::vm::execute_guest(&sdk, app_exe, &stdin)?; + #[cfg(feature = "perf-metrics")] + scroll_zkvm_prover::prover::profile_dump::dump("execute"); Ok(ret) } diff --git a/crates/integration/src/testers/bundle.rs b/crates/integration/src/testers/bundle.rs index 36467aff..f751789d 100644 --- a/crates/integration/src/testers/bundle.rs +++ b/crates/integration/src/testers/bundle.rs @@ -137,11 +137,7 @@ impl BundleTaskGenerator { let pi_hash = info.pi_hash_by_version(version); let proof = AggregationInput { - public_values: pi_hash - .as_slice() - .iter() - .map(|&b| b as u32) - .collect::>(), + public_values: crate::utils::pi_hash_to_public_values(&pi_hash), commitment, }; batch_proofs.push(proof); diff --git a/crates/integration/src/utils/mod.rs b/crates/integration/src/utils/mod.rs index edb72841..fd311bd6 100644 --- a/crates/integration/src/utils/mod.rs +++ b/crates/integration/src/utils/mod.rs @@ -17,7 +17,24 @@ use scroll_zkvm_types::{ utils::{keccak256, point_eval, serialize_vk}, }; use std::env; -use vm_zstd::zstd_encode; +use std::io::Write; + +/// Encode payload bytes into a single zstd frame without the 4-byte magic number, +/// matching the scroll envelope format (see `zstd_decode` in scroll-zkvm-types-batch). +fn zstd_encode(raw_input_bytes: &[u8]) -> Vec { + use encoder_standard::{N_BLOCK_SIZE_TARGET, init_zstd_encoder}; + + // compression level = 0 defaults to using level=3, which is zstd's default. + let mut encoder = init_zstd_encoder(N_BLOCK_SIZE_TARGET); + + // set source length, which will be reflected in the frame header. + encoder + .set_pledged_src_size(Some(raw_input_bytes.len() as u64)) + .unwrap(); + + encoder.write_all(raw_input_bytes).unwrap(); + encoder.finish().unwrap() +} #[allow(dead_code)] fn final_l1_index(blk: &BlockWitness) -> u64 { @@ -40,6 +57,18 @@ fn blks_tx_bytes<'a>(blks: impl Iterator) -> Vec { }) } +/// Encode a 32-byte pi hash as OpenVM public values: each public value cell is a +/// single byte, so the 32-byte hash fills all `NUM_PUBLIC_VALUES` (32) cells. +pub(crate) fn pi_hash_to_public_values(pi_hash: &B256) -> Vec { + let mut public_values = pi_hash + .as_slice() + .iter() + .map(|&b| b as u32) + .collect::>(); + public_values.resize(scroll_zkvm_types::types_agg::NUM_PUBLIC_VALUES, 0); + public_values +} + #[derive(Clone, Debug)] pub struct LastHeader { pub batch_index: u64, @@ -316,11 +345,7 @@ pub fn build_batch_witnesses( .map(|chunk_info| { let pi_hash = chunk_info.pi_hash_by_version(version); AggregationInput { - public_values: pi_hash - .as_slice() - .iter() - .map(|&b| b as u32) - .collect::>(), + public_values: pi_hash_to_public_values(&pi_hash), commitment, } }) @@ -389,11 +414,7 @@ pub fn build_batch_witnesses_validium( .map(|chunk_info| { let pi_hash = chunk_info.pi_hash_by_version(version); AggregationInput { - public_values: pi_hash - .as_slice() - .iter() - .map(|&b| b as u32) - .collect::>(), + public_values: pi_hash_to_public_values(&pi_hash), commitment, } }) diff --git a/crates/prover/Cargo.toml b/crates/prover/Cargo.toml index 7876b554..64a75825 100644 --- a/crates/prover/Cargo.toml +++ b/crates/prover/Cargo.toml @@ -35,6 +35,8 @@ thiserror.workspace = true toml = "0.8" cudarc = { version = "0.9", optional = true } +metrics = { version = "0.23", optional = true } +metrics-util = { version = "0.17", optional = true } [dev-dependencies] @@ -44,5 +46,8 @@ cuda = ["openvm-sdk/cuda", "dep:cudarc", "openvm-verify-stark-circuit/cuda", "de # GPU acceleration for the halo2 (SNARK) prover on top of `cuda`. Needs much # more VRAM than STARK proving; enable only on 24 GB-class GPUs. halo2-gpu = ["cuda", "openvm-sdk/halo2-gpu"] +# Per-function guest cycle profiling. Dumps a metrics JSON (flamegraph.py +# format) at the path in env PROFILE_METRICS_JSON after each proof. +perf-metrics = ["openvm-sdk/perf-metrics", "dep:metrics", "dep:metrics-util"] diff --git a/crates/prover/src/lib.rs b/crates/prover/src/lib.rs index a5776558..e10295ee 100644 --- a/crates/prover/src/lib.rs +++ b/crates/prover/src/lib.rs @@ -3,7 +3,7 @@ mod error; pub use error::Error; -mod prover; +pub mod prover; pub use prover::{Prover, ProverConfig}; pub mod setup; diff --git a/crates/prover/src/prover/mod.rs b/crates/prover/src/prover/mod.rs index a6945d14..44249332 100644 --- a/crates/prover/src/prover/mod.rs +++ b/crates/prover/src/prover/mod.rs @@ -10,7 +10,7 @@ use openvm_sdk::config::{ AggregationConfig, AggregationSystemParams, AggregationTreeConfig, AppConfig, }; use openvm_sdk::prover::{DeferralAggProver, MultiDeferralCircuitProver}; -use openvm_sdk::{F, SC, Sdk, StdIn}; +use openvm_sdk::{SC, Sdk, StdIn}; use openvm_sdk_config::{SdkVmConfig, deferral::SupportedDeferral}; use openvm_stark_backend::StarkEngine; use openvm_stark_sdk::{ @@ -43,6 +43,104 @@ type SdkAppConfig = AppConfig; // Re-export from openvm_sdk. pub use openvm_sdk::{self}; +/// Dumps guest profiling counters (per-function cycles, cells used) recorded +/// by openvm's `perf-metrics` feature into JSON files in the format that +/// `scripts/flamegraph.py` consumes. Enabled by setting PROFILE_METRICS_DIR to +/// an output directory. Every proof writes `-.json` holding the +/// counter *delta* since the previous proof in this process, so each file +/// contains exactly one proof's guest profile. +#[cfg(feature = "perf-metrics")] +pub mod profile_dump { + use std::collections::HashMap; + use std::sync::{Mutex, OnceLock}; + + static SNAPSHOTTER: OnceLock> = OnceLock::new(); + static PREV: Mutex>> = Mutex::new(None); + static NEXT_IDX: Mutex> = + Mutex::new(std::collections::BTreeMap::new()); + + fn snapshotter() -> Option<&'static metrics_util::debugging::Snapshotter> { + std::env::var_os("PROFILE_METRICS_DIR")?; + SNAPSHOTTER + .get_or_init(|| { + let recorder = metrics_util::debugging::DebuggingRecorder::new(); + let snapshotter = recorder.snapshotter(); + metrics::set_global_recorder(recorder) + .ok() + .map(|_| snapshotter) + }) + .as_ref() + } + + pub fn install() { + let _ = snapshotter(); + } + + pub fn dump(prover_name: &str) { + let Some(snapshotter) = snapshotter() else { + return; + }; + let dir = std::env::var("PROFILE_METRICS_DIR").expect("checked by snapshotter()"); + + #[derive(serde::Serialize)] + struct Entry { + metric: String, + labels: Vec<(String, String)>, + value: u64, + } + + // Current absolute counter values, keyed by a stable serialization. + let mut entries = HashMap::)>::new(); + let mut cur = HashMap::::new(); + for (key, _unit, _desc, value) in snapshotter.snapshot().into_vec() { + if key.kind() != metrics_util::MetricKind::Counter { + continue; + } + let metrics_util::debugging::DebugValue::Counter(value) = value else { + continue; + }; + let key = key.key(); + let labels: Vec<(String, String)> = key + .labels() + .map(|l| (l.key().to_string(), l.value().to_string())) + .collect(); + let id = format!("{}\0{:?}", key.name(), labels); + entries.insert(id.clone(), (key.name().to_string(), labels)); + cur.insert(id, value); + } + + let mut prev = PREV.lock().unwrap(); + let prev_map = prev.get_or_insert_with(HashMap::new); + let mut delta_entries = Vec::new(); + for (id, value) in &cur { + let delta = value.saturating_sub(prev_map.get(id).copied().unwrap_or(0)); + if delta == 0 { + continue; + } + let (metric, labels) = &entries[id]; + delta_entries.push(Entry { + metric: metric.clone(), + labels: labels.clone(), + value: delta, + }); + } + *prev_map = cur; + drop(prev); + + let mut idx_map = NEXT_IDX.lock().unwrap(); + let idx = idx_map.entry(prover_name.to_string()).or_insert(0); + let path = format!("{dir}/{prover_name}-{idx}.json"); + *idx += 1; + drop(idx_map); + + let json = serde_json::json!({ "counter": delta_entries }); + match std::fs::write(&path, serde_json::to_string(&json).unwrap()) { + Ok(()) => tracing::info!("profile metrics written to {path}"), + Err(err) => tracing::warn!("failed to write profile metrics to {path}: {err}"), + } + } +} + /// Default aggregation parameters shared by all provers. fn default_agg_params() -> AggregationSystemParams { AggregationSystemParams { @@ -69,15 +167,31 @@ pub struct Prover { /// Prover name pub prover_name: String, /// The program exe. - pub app_exe: Arc>, + pub app_exe: Arc, /// Prover configuration. pub config: ProverConfig, /// SDKConfig app_config: SdkAppConfig, /// Lazily initialized SDK sdk: OnceLock, + /// Lazily built, cached `StarkProver`. `Sdk::prove()` rebuilds one on every + /// call, which re-commits the program on device (and with the `rvr` feature + /// would recompile the native execution artifacts from scratch — tens of + /// seconds per proof). Cache it once per SDK instance; `reset()` clears it. + stark_prover: OnceLock>, } +#[cfg(feature = "cuda")] +type SdkStarkProver = openvm_sdk::prover::StarkProver< + openvm_cuda_backend::BabyBearPoseidon2GpuEngine, + openvm_sdk_config::SdkVmGpuBuilder, +>; +#[cfg(not(feature = "cuda"))] +type SdkStarkProver = openvm_sdk::prover::StarkProver< + openvm_stark_sdk::config::baby_bear_poseidon2::BabyBearPoseidon2CpuEngine, + openvm_sdk_config::SdkVmCpuBuilder, +>; + /// Configure the [`Prover`]. #[derive(Debug, Clone, Default)] pub struct ProverConfig { @@ -99,11 +213,13 @@ impl Prover { prover_name: name.unwrap_or("universal").to_string(), app_config, sdk: OnceLock::new(), + stark_prover: OnceLock::new(), }) } /// Release OpenVM SDK resources pub fn reset(&mut self) { + self.stark_prover = OnceLock::new(); self.sdk = OnceLock::new(); } @@ -351,10 +467,27 @@ impl Prover { let execution_time_mills = t.elapsed().as_millis() as u64; let t = std::time::Instant::now(); + #[cfg(feature = "perf-metrics")] + profile_dump::install(); let sdk = self.get_sdk()?; - let (vm_stark_proof, baseline) = sdk - .prove(self.app_exe.clone(), stdin, def_inputs) - .map_err(|e| Error::GenProof(e.to_string()))?; + // Reuse a cached `StarkProver` instead of `Sdk::prove()`, which rebuilds + // one (re-committing the program on device) on every call. + let stark_prover = self.stark_prover.get_or_try_init(|| { + sdk.prover(self.app_exe.clone()) + .map(std::sync::Mutex::new) + .map_err(|e| Error::GenProof(e.to_string())) + })?; + let (vm_stark_proof, baseline) = { + let mut prover = stark_prover + .lock() + .map_err(|e| Error::GenProof(format!("stark prover lock poisoned: {e}")))?; + let (proof, _metadata) = prover + .prove(stdin, def_inputs) + .map_err(|e| Error::GenProof(e.to_string()))?; + (proof, prover.generate_baseline()) + }; + #[cfg(feature = "perf-metrics")] + profile_dump::dump(&self.prover_name); let proving_time_mills = t.elapsed().as_millis() as u64; let proving_time_s = proving_time_mills as f32 / 1000.0f32; let prove_speed = (total_cycles as f32 / 1_000_000.0f32) / proving_time_s; // MHz @@ -423,10 +556,14 @@ impl Prover { ) -> Result { self.execute_and_check(&stdin)?; + #[cfg(feature = "perf-metrics")] + profile_dump::install(); let sdk = self.get_sdk()?; let evm_proof = sdk .prove_evm(self.app_exe.clone(), stdin, def_inputs) .map_err(|e| Error::GenProof(format!("{}", e)))?; + #[cfg(feature = "perf-metrics")] + profile_dump::dump(&self.prover_name); Ok(evm_proof) } diff --git a/crates/prover/src/setup.rs b/crates/prover/src/setup.rs index 4187cb70..d9e9ce19 100644 --- a/crates/prover/src/setup.rs +++ b/crates/prover/src/setup.rs @@ -1,87 +1,18 @@ -use std::{collections::BTreeMap, fs::read_to_string, path::Path}; +use std::{fs::read_to_string, path::Path}; -use openvm_circuit::arch::instructions::{ - exe::{FnBounds, VmExe}, - instruction::{DebugInfo, Instruction}, - program::Program, -}; -use openvm_sdk::F; +use openvm_circuit::arch::instructions::exe::VmExe; use openvm_sdk::config::AppConfig; use openvm_sdk::fs::read_object_from_file; use openvm_sdk_config::SdkVmConfig; use crate::Error; -/// Wrapper around [`openvm_sdk::fs::read_exe_from_file`]. -pub fn read_app_exe>(path: P) -> Result, Error> { - if let Ok(r) = read_object_from_file(&path) { - return Ok(r); - } - - println!("loading vmexe failed, trying old format.."); - - /// Executable program for OpenVM. - #[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)] - #[serde(bound(serialize = "F: Serialize", deserialize = "F: Deserialize<'de>"))] - pub struct OldProgram { - #[serde(deserialize_with = "deserialize_instructions_and_debug_infos")] - pub instructions_and_debug_infos: Vec, Option)>>, - pub step: u32, - pub pc_base: u32, - } - #[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)] - #[serde(bound( - serialize = "F: serde::Serialize", - deserialize = "F: std::cmp::Ord + serde::Deserialize<'de>" - ))] - pub struct OldVmExe { - /// Program to execute. - pub program: OldProgram, - /// Start address of pc. - pub pc_start: u32, - /// Initial memory image. - pub init_memory: BTreeMap<(u32, u32), F>, - /// Starting + ending bounds for each function. - pub fn_bounds: FnBounds, - } - use serde::{Deserialize, Deserializer, Serialize}; - - #[allow(clippy::type_complexity)] - fn deserialize_instructions_and_debug_infos<'de, F: Deserialize<'de>, D: Deserializer<'de>>( - deserializer: D, - ) -> Result, Option)>>, D::Error> { - let (inst_data, total_len): (Vec<(Instruction, u32)>, u32) = - Deserialize::deserialize(deserializer)?; - let mut ret: Vec, Option)>> = Vec::new(); - ret.resize_with(total_len as usize, || None); - for (inst, i) in inst_data { - ret[i as usize] = Some((inst, None)); - } - Ok(ret) - } - - let old_exe: OldVmExe = read_object_from_file(&path).map_err(|e| Error::Setup { +/// Read and deserialize [`VmExe`] from the given path. +pub fn read_app_exe>(path: P) -> Result { + read_object_from_file(&path).map_err(|e| Error::Setup { path: path.as_ref().into(), src: e.to_string(), - })?; - use openvm_stark_sdk::openvm_stark_backend::p3_field::{PrimeField32, integers::QuotientMap}; - let exe = VmExe:: { - program: Program:: { - instructions_and_debug_infos: old_exe.program.instructions_and_debug_infos, - pc_base: old_exe.program.pc_base, - }, - pc_start: old_exe.pc_start, - init_memory: old_exe - .init_memory - .into_iter() - .map(|(k, v)| { - assert!(v < F::from_int(256u32)); - (k, v.as_canonical_u32() as u8) - }) - .collect(), - fn_bounds: old_exe.fn_bounds, - }; - Ok(exe) + }) } /// Read and deserialize [`openvm_sdk::config::AppConfig`] from the given path to the TOML config. diff --git a/crates/prover/src/utils/mod.rs b/crates/prover/src/utils/mod.rs index ddc48a04..c6407e9c 100644 --- a/crates/prover/src/utils/mod.rs +++ b/crates/prover/src/utils/mod.rs @@ -76,11 +76,12 @@ pub fn save_stdin_as_json(stdin: &openvm_sdk::StdIn, filename: &str) { let mut json: serde_json::Value = serde_json::from_str("{\"input\":[]}").unwrap(); let json_input = json["input"].as_array_mut().unwrap(); for item in &stdin.buffer { - use openvm_stark_sdk::openvm_stark_backend::p3_field::PrimeField32; let mut bytes: Vec = vec![0x02]; - for f in item { - let u32_bytes = f.as_canonical_u32().to_le_bytes(); - bytes.extend_from_slice(&u32_bytes); + for b in item { + // The new OpenVM SDK stores stdin as raw bytes; keep the historical + // 0x02 (little-endian u32 word) serialization so the dumped JSON is + // still accepted by `cargo openvm`. + bytes.extend_from_slice(&[*b, 0, 0, 0]); } json_input.push(serde_json::Value::String(format!( "0x{}", diff --git a/crates/prover/src/utils/vm.rs b/crates/prover/src/utils/vm.rs index ee6be715..7c1411ee 100644 --- a/crates/prover/src/utils/vm.rs +++ b/crates/prover/src/utils/vm.rs @@ -16,7 +16,8 @@ pub fn execute_guest( inputs: &StdIn, ) -> Result { let exe = sdk.convert_to_exe(exe)?; - match sdk.execute_metered_cost(exe.clone(), inputs.clone()) { + let compiled_metered_cost = sdk.compile_metered_cost(exe.clone())?; + match sdk.execute_metered_cost(&compiled_metered_cost, inputs.clone()) { Ok((public_values, (_cost, instret))) => { if public_values.iter().all(|&x| x == 0) { return Err(SdkError::Other(eyre::eyre!( @@ -30,7 +31,8 @@ pub fn execute_guest( } Err(e) => { tracing::warn!("Metered execution failed: {e}, falling back to execute"); - let public_values = sdk.execute(exe, inputs.clone())?; + let compiled = sdk.compile(exe)?; + let public_values = sdk.execute(&compiled, inputs.clone())?; if public_values.iter().all(|&x| x == 0) { return Err(SdkError::Other(eyre::eyre!( "public_values are all 0s upon execute" diff --git a/crates/types/Cargo.toml b/crates/types/Cargo.toml index 518da567..34a31ce4 100644 --- a/crates/types/Cargo.toml +++ b/crates/types/Cargo.toml @@ -14,6 +14,7 @@ types-batch = { path = "batch", package = "scroll-zkvm-types-batch", features = types-bundle = { path = "bundle", package = "scroll-zkvm-types-bundle" } openvm-sdk = { workspace = true } +openvm-sdk-config = { workspace = true } openvm-verify-stark-host = { workspace = true } openvm-static-verifier = { workspace = true } openvm-circuit = { workspace = true } diff --git a/crates/types/batch/Cargo.toml b/crates/types/batch/Cargo.toml index e2836f22..fa46497e 100644 --- a/crates/types/batch/Cargo.toml +++ b/crates/types/batch/Cargo.toml @@ -11,7 +11,7 @@ version.workspace = true alloy-primitives = { workspace = true } serde.workspace = true itertools.workspace = true -vm-zstd = { workspace = true } +ruzstd = "0.9" types-base = { path = "../base", package = "scroll-zkvm-types-base" } openvm = { workspace = true, features = ["std"] } diff --git a/crates/types/batch/src/blob_consistency/mod.rs b/crates/types/batch/src/blob_consistency/mod.rs index a6498d47..fba44da7 100644 --- a/crates/types/batch/src/blob_consistency/mod.rs +++ b/crates/types/batch/src/blob_consistency/mod.rs @@ -42,8 +42,11 @@ impl BlobPolynomial { "too many bytes in batch data" ); - for (i, &byte) in blob_bytes.iter().enumerate() { - coefficients[i / 31][1 + (i % 31)] = byte; + for (coefficient, bytes) in coefficients + .iter_mut() + .zip(blob_bytes.chunks(N_DATA_BYTES_PER_COEFFICIENT)) + { + coefficient[1..1 + bytes.len()].copy_from_slice(bytes); } Self(coefficients.map(|coeff| U256::from_be_bytes(coeff))) diff --git a/crates/types/batch/src/builder/v7.rs b/crates/types/batch/src/builder/v7.rs index b2e69930..04d7ee94 100644 --- a/crates/types/batch/src/builder/v7.rs +++ b/crates/types/batch/src/builder/v7.rs @@ -79,14 +79,21 @@ impl super::BatchInfoBuilder for GenericBatchInfoBuilderV7

{ "blob-envelope bigger than allowed", ); - let envelope_bytes = { - let mut padded = args.blob_bytes.to_vec(); - padded.resize(N_BLOB_BYTES, 0); - padded + // Blob bytes from the witness are already padded to N_BLOB_BYTES; only + // fall back to local padding for shorter (e.g. hand-crafted) inputs. + let envelope_bytes_storage; + let envelope_bytes: &[u8] = if args.blob_bytes.len() == N_BLOB_BYTES { + args.blob_bytes.as_slice() + } else { + envelope_bytes_storage = { + let mut padded = args.blob_bytes.to_vec(); + padded.resize(N_BLOB_BYTES, 0); + padded + }; + &envelope_bytes_storage }; - let envelope = <::Envelope as Envelope>::from_slice( - envelope_bytes.as_slice(), - ); + let envelope = + <::Envelope as Envelope>::from_slice(envelope_bytes); let payload = Self::Payload::from_envelope(&envelope); let blob_versioned_hash = args.header.blob_versioned_hash(); diff --git a/crates/types/batch/src/payload/mod.rs b/crates/types/batch/src/payload/mod.rs index 9e258e69..84fb9eb7 100644 --- a/crates/types/batch/src/payload/mod.rs +++ b/crates/types/batch/src/payload/mod.rs @@ -30,6 +30,25 @@ pub trait Envelope { } } +/// Decode zstd-compressed payload bytes using the standard pure-Rust decoder. +/// +/// The scroll envelope stores a single zstd frame without the 4-byte magic number, +/// so the magic is prepended (zero-copy) before handing the stream to the decoder. +pub(crate) fn zstd_decode(src: &[u8]) -> Vec { + use ruzstd::decoding::StreamingDecoder; + use ruzstd::io::Read; + + const ZSTD_MAGIC: [u8; 4] = [0x28, 0xB5, 0x2F, 0xFD]; + let mut stream = ZSTD_MAGIC.as_slice().chain(src); + let mut decoder = + StreamingDecoder::new(&mut stream).expect("zstd decoder init should succeed"); + let mut decoded = Vec::new(); + decoder + .read_to_end(&mut decoded) + .expect("zstd decode should succeed"); + decoded +} + pub trait Payload { type BatchHeader: BatchHeader; diff --git a/crates/types/batch/src/payload/v6.rs b/crates/types/batch/src/payload/v6.rs index 0a3ad2f1..302ecfd0 100644 --- a/crates/types/batch/src/payload/v6.rs +++ b/crates/types/batch/src/payload/v6.rs @@ -80,9 +80,7 @@ impl Payload for PayloadV6 { fn from_envelope(envelope: &Self::Envelope) -> Self { // Decode the payload bytes from the envelope bytes. let payload_bytes = if envelope.is_encoded { - vm_zstd::process(envelope.envelope_bytes.as_slice()) - .expect("envelope to payload v6 should succeed zstd-decoding") - .decoded_data + super::zstd_decode(envelope.envelope_bytes.as_slice()) } else { envelope.envelope_bytes.to_vec() }; diff --git a/crates/types/batch/src/payload/v7.rs b/crates/types/batch/src/payload/v7.rs index 80c78d6c..ee0be727 100644 --- a/crates/types/batch/src/payload/v7.rs +++ b/crates/types/batch/src/payload/v7.rs @@ -144,9 +144,7 @@ impl super::Payload for GenericPayloadV7 { fn from_envelope(envelope: &Self::Envelope) -> Self { // Conditionally decode depending on the flag set in the envelope. let payload_bytes = if envelope.is_encoded & 1 == 1 { - vm_zstd::process(&envelope.unpadded_bytes) - .expect("zstd decode should succeed") - .decoded_data + super::zstd_decode(&envelope.unpadded_bytes) } else { envelope.unpadded_bytes.to_vec() }; diff --git a/crates/types/batch/src/witness.rs b/crates/types/batch/src/witness.rs index fb7e569c..220ed64f 100644 --- a/crates/types/batch/src/witness.rs +++ b/crates/types/batch/src/witness.rs @@ -94,6 +94,7 @@ pub struct BatchWitness { /// Chunk infos. pub chunk_infos: Vec, /// Blob bytes. + #[serde(with = "bytes_vec")] pub blob_bytes: Vec, /// Witness for point evaluation. /// @@ -112,6 +113,51 @@ impl ProofCarryingWitness for BatchWitness { } } +/// Serde helper for large byte vectors. The wire format stays identical to +/// bincode's default `Vec` encoding (length prefix + raw bytes), but +/// deserialization claims the whole slice in one shot instead of decoding +/// element by element. +mod bytes_vec { + use serde::{Deserializer, Serializer}; + + pub fn serialize(bytes: &[u8], serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_bytes(bytes) + } + + pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + { + struct Visitor; + impl<'de> serde::de::Visitor<'de> for Visitor { + type Value = Vec; + + fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.write_str("a byte array") + } + + fn visit_bytes(self, v: &[u8]) -> Result { + Ok(v.to_vec()) + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: serde::de::SeqAccess<'de>, + { + let mut out = Vec::with_capacity(seq.size_hint().unwrap_or(0)); + while let Some(b) = seq.next_element()? { + out.push(b); + } + Ok(out) + } + } + deserializer.deserialize_bytes(Visitor) + } +} + impl From<&BatchWitness> for BatchInfo { fn from(witness: &BatchWitness) -> Self { let chunk_infos = witness.chunk_infos.to_vec(); diff --git a/crates/types/chunk/src/scroll/execute.rs b/crates/types/chunk/src/scroll/execute.rs index 512bf82e..d0127215 100644 --- a/crates/types/chunk/src/scroll/execute.rs +++ b/crates/types/chunk/src/scroll/execute.rs @@ -84,7 +84,7 @@ pub fn execute(witness: ChunkWitness) -> Result { }), }; - #[cfg(target_os = "zkvm")] + #[cfg(target_os = "openvm")] println!("chunk_info = {}", chunk_info); Ok(chunk_info) diff --git a/crates/types/circuit/Cargo.toml b/crates/types/circuit/Cargo.toml index 0b776e7f..8d51dc04 100644 --- a/crates/types/circuit/Cargo.toml +++ b/crates/types/circuit/Cargo.toml @@ -11,7 +11,7 @@ version.workspace = true scroll-zkvm-types-base.workspace = true alloy-primitives.workspace = true openvm = { workspace = true, features = ["std"] } -openvm-rv32im-guest.workspace = true +openvm-riscv-guest.workspace = true openvm-custom-insn.workspace = true openvm-verify-stark-guest.workspace = true openvm-deferral-guest.workspace = true diff --git a/crates/types/circuit/src/io.rs b/crates/types/circuit/src/io.rs index 8a368d7d..9e0f4a77 100644 --- a/crates/types/circuit/src/io.rs +++ b/crates/types/circuit/src/io.rs @@ -5,29 +5,28 @@ use openvm::platform as openvm_platform; /// /// rkyv needs special alignment for its data structures, use a pre-aligned buffer with rkyv::access_unchecked /// is more efficient than rkyv::access. -#[cfg(target_os = "zkvm")] +#[cfg(target_os = "openvm")] #[inline(always)] pub fn read_witnesses_rkyv_raw() -> Vec { use std::alloc::{GlobalAlloc, Layout, System}; - openvm_rv32im_guest::hint_input(); - let mut len: u32 = 0; - openvm_rv32im_guest::hint_store_u32!((&mut len) as *mut u32 as u32); - let num_words = len.div_ceil(4); - let size = (num_words * 4) as usize; + openvm_riscv_guest::hint_input(); + // The hint-stream length prefix is a single 8-byte word on the rv64 guest. + let mut len: u64 = 0; + openvm_riscv_guest::hint_store_u64!((&mut len) as *mut u64); + let num_words = (len as usize).div_ceil(8); + let size = num_words * 8; let layout = Layout::from_size_align(size, 16).unwrap(); let ptr_start = unsafe { System.alloc(layout) }; - let mut ptr = ptr_start; - for _ in 0..num_words { - openvm_rv32im_guest::hint_store_u32!(ptr as u32); - ptr = unsafe { ptr.add(4) }; - } + // SAFETY: `ptr_start` points to an allocation of `size == num_words * 8` bytes, + // so the chunked dword writes stay within the allocation. + unsafe { openvm_riscv_guest::hint_buffer_chunked(ptr_start, num_words) }; unsafe { Vec::from_raw_parts(ptr_start, len as usize, size) } } /// Read the witnesses from the hint stream. pub fn read_witnesses() -> Vec { - #[cfg(not(target_os = "zkvm"))] + #[cfg(not(target_os = "openvm"))] return openvm::io::read_vec(); // avoid compiler complaint - #[cfg(target_os = "zkvm")] + #[cfg(target_os = "openvm")] return read_witnesses_rkyv_raw(); } diff --git a/crates/types/circuit/src/lib.rs b/crates/types/circuit/src/lib.rs index 51884428..0ae9195e 100644 --- a/crates/types/circuit/src/lib.rs +++ b/crates/types/circuit/src/lib.rs @@ -60,7 +60,7 @@ where fn verify_proofs(witness: &Self::Witness) -> Vec { let proofs = witness.get_proofs(); - #[cfg(all(target_os = "zkvm", target_arch = "riscv32"))] + #[cfg(target_os = "openvm")] { let input_commits: Vec<[u8; 32]> = openvm::io::read(); assert_eq!( @@ -79,7 +79,7 @@ where } } - #[cfg(not(all(target_os = "zkvm", target_arch = "riscv32")))] + #[cfg(not(target_os = "openvm"))] { for proof in proofs.iter() { Self::verify_commitments(&proof.commitment); @@ -135,15 +135,16 @@ fn u32_array_to_commit(arr: &[u32; 8]) -> [u8; 32] { } /// Verify a root proof using deferred STARK verification (v2). -#[cfg(all(target_os = "zkvm", target_arch = "riscv32"))] +#[cfg(target_os = "openvm")] fn verify_proof(commitment: &ProgramCommitment, public_inputs: &[u32], input_commit: &[u8; 32]) { use openvm_verify_stark_guest::{ProofOutput, verify_stark}; // Sanity check for the number of public-input values. assert_eq!(public_inputs.len(), NUM_PUBLIC_VALUES); - // OpenVM stores each user public value byte as a 32-bit field element; the - // verify-stark guest helper collapses them back to dense bytes. + // OpenVM stores each user public value as a single byte in the low byte of a + // 32-bit field element; the verify-stark guest helper collapses them back to + // dense bytes (1 byte per cell). let expected = ProofOutput { app_exe_commit: u32_array_to_commit(&commitment.exe), app_vm_commit: u32_array_to_commit(&commitment.vm), @@ -153,7 +154,7 @@ fn verify_proof(commitment: &ProgramCommitment, public_inputs: &[u32], input_com verify_stark::<0>(input_commit, &expected); } -#[cfg(not(all(target_os = "zkvm", target_arch = "riscv32")))] +#[cfg(not(target_os = "openvm"))] fn verify_proof(_commitment: &ProgramCommitment, _public_inputs: &[u32], _input_commit: &[u8; 32]) { // This function is guest-only: the actual deferred STARK verification happens inside // the zkvm guest via `openvm_verify_stark_guest::verify_stark`. Calling it on a non-zkvm diff --git a/crates/types/src/proof.rs b/crates/types/src/proof.rs index a46006a0..60134d8c 100644 --- a/crates/types/src/proof.rs +++ b/crates/types/src/proof.rs @@ -25,7 +25,7 @@ pub struct EvmProof { //pub accumulator: Vec, /// The public inputs of the SNARK proof. /// Previously the `instance`s are U256 values, with accumulator and digests. - /// For real user PI values, they will be like 0x0000..00000ab, only 1 byte non zero. + /// For real user PI values, they will be like 0x0000..00000ab, only 2 bytes (u16 cell) non zero. /// Usually of length (12+2+32)x32 /// Now: the `instance` is splitted. The `user_public_values` is "dense". /// Each byte is valid PI. Usually of length 32. @@ -220,8 +220,9 @@ impl ProofEnum { } Self::Evm(evm_proof) => { // The first 12 scalars are accumulators. - // The next 2 scalars are digests. - // The next 32 scalars are the public input hash. + // The next 2 scalars are app commits. + // The remaining scalars are user public values: each holds a + // u16 cell in its low 2 bytes (scalars are big-endian encoded). let pi_hash_bytes = evm_proof .instances .iter() @@ -230,11 +231,11 @@ impl ProofEnum { .cloned() .collect::>(); - // The 32 scalars of public input hash actually only have the LSB that is the - // meaningful byte. pi_hash_bytes .chunks_exact(32) - .map(|bytes32_chunk| bytes32_chunk[31] as u32) + .map(|bytes32_chunk| { + (bytes32_chunk[30] as u32) << 8 | bytes32_chunk[31] as u32 + }) .collect::>() } } diff --git a/crates/types/src/zkvm.rs b/crates/types/src/zkvm.rs index 9fb4496a..63490e42 100644 --- a/crates/types/src/zkvm.rs +++ b/crates/types/src/zkvm.rs @@ -1,21 +1,33 @@ use once_cell::sync::Lazy; use openvm_sdk::Sdk; use openvm_sdk::config::AggregationSystemParams; -use openvm_sdk::keygen::AggProvingKey; +use openvm_sdk::keygen::SdkCachedProvingKey; +use openvm_sdk_config::SdkVmConfig; use openvm_stark_sdk::config::{ MAX_APP_LOG_STACKED_HEIGHT, app_params_with_100_bits_security, internal_params_with_100_bits_security, leaf_params_with_100_bits_security, }; -/// Proving key for STARK aggregation. Primarily used to aggregate +/// Cached proving keys for STARK aggregation. Primarily used to aggregate /// [continuation proofs][openvm_sdk::prover::vm::ContinuationVmProof]. -pub static AGG_STARK_PROVING_KEY: Lazy = Lazy::new(build_agg_pk); +/// +/// Starting with OpenVM develop-v2.1.0, the SDK builder requires both `app_pk` +/// and `agg_pk` to be supplied together when seeding with pre-generated keys, +/// so we cache the full [`SdkCachedProvingKey`] instead of only `AggProvingKey`. +pub static AGG_STARK_PROVING_KEY: Lazy> = Lazy::new(build_agg_pk); -fn build_agg_pk() -> AggProvingKey { +fn build_agg_pk() -> SdkCachedProvingKey { let app_params = app_params_with_100_bits_security(MAX_APP_LOG_STACKED_HEIGHT); let agg_params = AggregationSystemParams { leaf: leaf_params_with_100_bits_security(), internal: internal_params_with_100_bits_security(), }; - Sdk::riscv32(app_params, agg_params).agg_pk().clone() + let sdk = Sdk::riscv64(app_params, agg_params); + SdkCachedProvingKey { + app_pk: sdk.app_pk().clone(), + agg_pk: sdk.agg_pk(), + deferral_pk: None, + deferral_agg_pk: None, + root_pk: None, + } } diff --git a/crates/verifier/src/verifier.rs b/crates/verifier/src/verifier.rs index f321279e..16c0732c 100644 --- a/crates/verifier/src/verifier.rs +++ b/crates/verifier/src/verifier.rs @@ -98,7 +98,7 @@ impl UniversalVerifier { let loaded_mvk = openvm_sdk::fs::read_object_from_file(path_agg_vk).unwrap_or_else(|_| { tracing::warn!("root_verifier_vk not found on disk, computing on-the-fly (slow)..."); - AGG_STARK_PROVING_KEY.internal_recursive.get_vk().clone() + AGG_STARK_PROVING_KEY.agg_pk.internal_recursive.get_vk().clone() }); Ok(Self { diff --git a/docs/openvm-v2-migration.md b/docs/openvm-v2-migration.md index 6beb8c4b..3f445f72 100644 --- a/docs/openvm-v2-migration.md +++ b/docs/openvm-v2-migration.md @@ -275,3 +275,46 @@ Still required to complete the upgrade (per the checklist above): force-rebuild guest assets with the default `RECOMPUTE_MODE=auto` (or `yes` to skip the download attempt), clear stale `.output/` caches, and re-run the `make test-e2e-*` suite. + +--- + +## 9. Update: v2.0.0 → develop-v2.1.0 (RV64) + +The move to the `develop-v2.1.0` branch (commit `fd569c7`) is a **major migration**: +OpenVM switches the guest ISA from RV32 to RV64. What changed: + +- `Cargo.toml`: every `openvm-org/openvm.git` entry moved from `tag = "v2.0.0"` to + `branch = "develop-v2.1.0"`; the three `openvm-org/stark-backend.git` entries + stay on `tag = "v2.0.0"` (that is what openvm's own `Cargo.toml` pins on this + branch). Crate renames: `openvm-rv32im-guest`/`openvm-rv32im-transpiler` → + `openvm-riscv-guest`/`openvm-riscv-transpiler`. +- Guest toolchain: `OPENVM_RUST_TOOLCHAIN=nightly-2025-11-20` → `openvm-1.94.0` + (the openvm rust fork with the built-in `riscv64im-unknown-openvm-elf` target). + `rust-toolchain.toml` host channel → `nightly-2026-01-18` (openvm-sdk `tco` + feature); the `riscv32im-unknown-none-elf` target entry was dropped. +- `openvm.toml` (all three circuits): `[app_vm_config.rv32i]`/`rv32m` → + `rv64i`/`rv64m`. +- SDK API: `Sdk::riscv32`/`AppConfig::riscv32` → `riscv64`; `Sdk::execute*` now + takes a compiled instance (`sdk.compile_metered_cost(exe)?` then + `sdk.execute_metered_cost(&compiled, inputs)`; same for `compile`/`execute`). +- Hint stream is 8-byte granular: guest `read_witnesses_rkyv_raw` reads a `u64` + length prefix (`hint_store_u64!`) then uses `hint_buffer_chunked`. +- User public values are u16 cells (2 LE bytes per cell; `NUM_PUBLIC_VALUES` is + still 32 cells). Affected spots: guest `verify_proof` expected PVs, + `aggregated_pi_hashes` in batch/bundle circuits, fabricated + `AggregationInput.public_values` in integration utils, and the EVM branch of + `types/src/proof.rs::public_values()`. +- Guest cfg gates: `target_os = "zkvm"` → `target_os = "openvm"`. +- `crates/build-guest/src/verifier.rs`: `solidity_sdk_tag = "v2.1"`, + `verifier_path = "v2.1-deferral"`. `openvm-solidity-sdk` has no `v2.1` tag yet, + so the download fails and `auto` mode falls back to local verifier generation. +- EVM verifier workaround: the branch's Solidity template still expects 1 byte + per public value while the SDK packs u16 cells as 2 LE bytes. + `crates/build-guest/src/main.rs::patch_verifier_for_u16_public_values` + rewrites the generated wrapper (length check ×2, per-cell byte expansion) and + clears the precompiled artifact so `verifier.bin` is recompiled from the + patched source by `solc`. +- SRS: still `kzg_bn254_24.srs` (unchanged). + +Verification: `GPU=1 make test-single-chunk`, `test-multi-chunk`, +`test-e2e-batch`, `test-e2e-bundle` all pass (CUDA, RTX 3090). diff --git a/patches/openvm-mem/Cargo.toml b/patches/openvm-mem/Cargo.toml new file mode 100644 index 00000000..c23190ac --- /dev/null +++ b/patches/openvm-mem/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "openvm-mem" +description = "libc memory intrinsics (memcpy, memset, memmove, memcmp, bcmp) for OpenVM guest programs." +version = "2.0.0" +edition = "2021" + +[lints] diff --git a/patches/openvm-mem/src/lib.rs b/patches/openvm-mem/src/lib.rs new file mode 100644 index 00000000..ec1f16dd --- /dev/null +++ b/patches/openvm-mem/src/lib.rs @@ -0,0 +1,344 @@ +//! libc memory intrinsics for OpenVM guest programs. +//! +//! OpenVM costs a misaligned load or store the same as an aligned one, and the guest target +//! enables `+unaligned-scalar-mem`. A conventional libc spends most of its complexity avoiding +//! misaligned access, and all of that is wasted work here, so these implementations do no +//! alignment work at all: they issue 8-byte accesses at whatever address they are given and cover +//! short runs with overlapping moves rather than byte loops. +//! +//! `#![no_builtins]` keeps LLVM's loop-idiom pass from lowering the loops here back into calls to +//! the very symbols they define. It is scoped to this crate so the rest of the guest still gets +//! normal libcall recognition. + +#![cfg(any(test, openvm_intrinsics, target_os = "openvm"))] +#![no_std] +#![no_builtins] + +/// Bytes moved per iteration of the bulk loops. +const BLOCK: usize = 64; + +#[inline(always)] +unsafe fn load(src: *const u8) -> [u8; N] { + (src as *const [u8; N]).read() +} + +#[inline(always)] +unsafe fn store(dest: *mut u8, val: [u8; N]) { + (dest as *mut [u8; N]).write(val) +} + +/// Scalar accessors. Values are kept in registers, unlike byte arrays wide enough to spill. +macro_rules! scalar_accessors { + ($read:ident, $write:ident, $t:ty) => { + #[inline(always)] + unsafe fn $read(src: *const u8) -> $t { + <$t>::from_ne_bytes(load::<{ core::mem::size_of::<$t>() }>(src)) + } + #[inline(always)] + unsafe fn $write(dest: *mut u8, val: $t) { + store::<{ core::mem::size_of::<$t>() }>(dest, val.to_ne_bytes()) + } + }; +} +scalar_accessors!(read_u64, write_u64, u64); +scalar_accessors!(read_u32, write_u32, u32); +scalar_accessors!(read_u16, write_u16, u16); + +/// Copies the first and last `WORDS * 8` bytes of an `n`-byte range, which together cover it when +/// `n <= WORDS * 16`. +/// +/// Every load is issued before any store, so this stays correct when the ranges overlap: the two +/// runs together read exactly the bytes they go on to write. `WORDS` is a constant, so the loops +/// unroll and the values stay in registers. +#[inline(always)] +unsafe fn copy_overlapping(dest: *mut u8, src: *const u8, n: usize) { + let back = n - WORDS * 8; + let mut head = [0u64; WORDS]; + let mut tail = [0u64; WORDS]; + let mut i = 0; + while i < WORDS { + head[i] = read_u64(src.add(i * 8)); + tail[i] = read_u64(src.add(back + i * 8)); + i += 1; + } + i = 0; + while i < WORDS { + write_u64(dest.add(i * 8), head[i]); + write_u64(dest.add(back + i * 8), tail[i]); + i += 1; + } +} + +/// Copies `n < BLOCK` bytes using two overlapping runs of same-width moves. +#[inline(always)] +unsafe fn copy_tail(dest: *mut u8, src: *const u8, n: usize) { + if n >= 32 { + copy_overlapping::<4>(dest, src, n); + } else if n >= 16 { + copy_overlapping::<2>(dest, src, n); + } else if n >= 8 { + copy_overlapping::<1>(dest, src, n); + } else if n >= 4 { + let (a, b) = (read_u32(src), read_u32(src.add(n - 4))); + write_u32(dest, a); + write_u32(dest.add(n - 4), b); + } else if n >= 2 { + let (a, b) = (read_u16(src), read_u16(src.add(n - 2))); + write_u16(dest, a); + write_u16(dest.add(n - 2), b); + } else if n == 1 { + *dest = *src; + } +} + +/// Copies low addresses first. +/// +/// # Safety +/// +/// `src` must be valid for reads of `n` bytes and `dest` valid for writes of `n` bytes. The +/// ranges may overlap only when `dest <= src`. +#[inline(always)] +unsafe fn copy_forward(dest: *mut u8, src: *const u8, n: usize) { + let (mut dest, mut src, mut rem) = (dest, src, n); + while rem >= BLOCK { + // Load all words into registers before storing, matching the original + // load-then-store ordering. u64 accesses avoid LLVM lowering the 64-byte + // aggregate copy into a `memmove` call (which would recurse into us). + let mut buf = [0u64; BLOCK / 8]; + let mut i = 0; + while i < BLOCK / 8 { + buf[i] = read_u64(src.add(i * 8)); + i += 1; + } + i = 0; + while i < BLOCK / 8 { + write_u64(dest.add(i * 8), buf[i]); + i += 1; + } + dest = dest.add(BLOCK); + src = src.add(BLOCK); + rem -= BLOCK; + } + copy_tail(dest, src, rem); +} + +#[cfg(any(openvm_intrinsics, target_os = "openvm"))] +#[no_mangle] +pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 { + copy_forward(dest, src, n); + dest +} + +/// Copies high addresses first. +/// +/// # Safety +/// +/// `src` must be valid for reads of `n` bytes and `dest` valid for writes of `n` bytes. The +/// ranges may overlap only when `dest >= src`; use [`copy_forward`] otherwise. +#[inline(always)] +unsafe fn copy_backward(dest: *mut u8, src: *const u8, n: usize) { + let mut rem = n; + while rem >= BLOCK { + rem -= BLOCK; + // See copy_forward: keep loads before stores with u64 accesses to avoid an + // aggregate-copy-to-`memmove` lowering that would recurse. + let mut buf = [0u64; BLOCK / 8]; + let mut i = 0; + while i < BLOCK / 8 { + buf[i] = read_u64(src.add(rem + i * 8)); + i += 1; + } + i = 0; + while i < BLOCK / 8 { + write_u64(dest.add(rem + i * 8), buf[i]); + i += 1; + } + } + // Everything still unwritten lives below `rem`, and `copy_tail` loads before it stores. + copy_tail(dest, src, rem); +} + +/// Copies `n` bytes, choosing a direction that tolerates overlap. +/// +/// # Safety +/// +/// `src` must be valid for reads of `n` bytes and `dest` valid for writes of `n` bytes. +#[inline(always)] +unsafe fn move_bytes(dest: *mut u8, src: *const u8, n: usize) { + // Copying upwards is safe unless `dest` starts inside the source range. The wrapping + // subtraction folds `dest < src` into the same comparison: it underflows past any real `n`. + if (dest as usize).wrapping_sub(src as usize) >= n { + copy_forward(dest, src, n); + } else { + copy_backward(dest, src, n); + } +} + +#[cfg(any(openvm_intrinsics, target_os = "openvm"))] +#[no_mangle] +pub unsafe extern "C" fn memmove(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 { + move_bytes(dest, src, n); + dest +} + +/// Writes `WORDS` words at `dest` and `WORDS` more ending at `dest + n`. +#[inline(always)] +unsafe fn set_overlapping(dest: *mut u8, word: u64, n: usize) { + let back = n - WORDS * 8; + let mut i = 0; + while i < WORDS { + write_u64(dest.add(i * 8), word); + write_u64(dest.add(back + i * 8), word); + i += 1; + } +} + +/// Writes `n < BLOCK` copies of `word`'s low byte using two overlapping runs of stores. +/// +/// Overlapping stores of the same value are idempotent, so no ordering care is needed. +#[inline(always)] +unsafe fn set_tail(dest: *mut u8, word: u64, n: usize) { + if n >= 32 { + set_overlapping::<4>(dest, word, n); + } else if n >= 16 { + set_overlapping::<2>(dest, word, n); + } else if n >= 8 { + set_overlapping::<1>(dest, word, n); + } else if n >= 4 { + write_u32(dest, word as u32); + write_u32(dest.add(n - 4), word as u32); + } else if n >= 2 { + write_u16(dest, word as u16); + write_u16(dest.add(n - 2), word as u16); + } else if n == 1 { + *dest = word as u8; + } +} + +/// Fills `n` bytes with `val`. +/// +/// # Safety +/// +/// `dest` must be valid for writes of `n` bytes. +#[inline(always)] +unsafe fn set_bytes(dest: *mut u8, val: u8, n: usize) { + let word = u64::from_ne_bytes([val; 8]); + let (mut dest, mut rem) = (dest, n); + while rem >= BLOCK { + let mut i = 0; + while i < BLOCK / 8 { + write_u64(dest.add(i * 8), word); + i += 1; + } + dest = dest.add(BLOCK); + rem -= BLOCK; + } + set_tail(dest, word, rem); +} + +#[cfg(any(openvm_intrinsics, target_os = "openvm"))] +#[no_mangle] +pub unsafe extern "C" fn memset(dest: *mut u8, val: core::ffi::c_int, n: usize) -> *mut u8 { + set_bytes(dest, val as u8, n); + dest +} + +const WORD: usize = core::mem::size_of::(); + +/// Reads a word with byte 0 in the low bits, so bit order matches address order. +#[inline(always)] +unsafe fn read_word(src: *const u8) -> u64 { + u64::from_le_bytes(load::(src)) +} + +/// Difference of the lowest-addressed byte on which `a` and `b` disagree. `a != b` required. +#[inline(always)] +fn byte_ordering(a: u64, b: u64) -> i32 { + let shift = (a ^ b).trailing_zeros() & !7; + (((a >> shift) & 0xff) as i32) - (((b >> shift) & 0xff) as i32) +} + +/// Compares `n` bytes, returning a value whose sign matches the first differing byte. +/// +/// # Safety +/// +/// `a` and `b` must be valid for reads of `n` bytes. +#[inline(always)] +unsafe fn compare_bytes(a: *const u8, b: *const u8, n: usize) -> i32 { + if n >= WORD { + // Advancing the pointers keeps the loop one instruction shorter than indexing off a base. + let (mut a, mut b, mut rem) = (a, b, n); + while rem >= WORD { + let (x, y) = (read_word(a), read_word(b)); + if x != y { + return byte_ordering(x, y); + } + a = a.add(WORD); + b = b.add(WORD); + rem -= WORD; + } + if rem != 0 { + // Overlapping final word. Everything before it already matched, so the first + // difference within it is also the first difference overall. + let (x, y) = (read_word(a.sub(WORD - rem)), read_word(b.sub(WORD - rem))); + if x != y { + return byte_ordering(x, y); + } + } + return 0; + } + // Under a word there is nothing to widen into; at most seven iterations. + let mut i = 0; + while i < n { + let (x, y) = (*a.add(i), *b.add(i)); + if x != y { + return x as i32 - y as i32; + } + i += 1; + } + 0 +} + +/// Reports whether `n` bytes differ, without ordering them. +/// +/// # Safety +/// +/// `a` and `b` must be valid for reads of `n` bytes. +#[inline(always)] +unsafe fn bytes_differ(a: *const u8, b: *const u8, n: usize) -> bool { + if n >= WORD { + let (mut a, mut b, mut rem) = (a, b, n); + while rem >= WORD { + if read_word(a) != read_word(b) { + return true; + } + a = a.add(WORD); + b = b.add(WORD); + rem -= WORD; + } + return rem != 0 && read_word(a.sub(WORD - rem)) != read_word(b.sub(WORD - rem)); + } + let mut i = 0; + while i < n { + if *a.add(i) != *b.add(i) { + return true; + } + i += 1; + } + false +} + +#[cfg(any(openvm_intrinsics, target_os = "openvm"))] +#[no_mangle] +pub unsafe extern "C" fn memcmp(a: *const u8, b: *const u8, n: usize) -> core::ffi::c_int { + compare_bytes(a, b, n) +} + +#[cfg(any(openvm_intrinsics, target_os = "openvm"))] +#[no_mangle] +pub unsafe extern "C" fn bcmp(a: *const u8, b: *const u8, n: usize) -> core::ffi::c_int { + bytes_differ(a, b, n) as core::ffi::c_int +} + +#[cfg(test)] +mod tests; diff --git a/patches/openvm-mem/src/tests.rs b/patches/openvm-mem/src/tests.rs new file mode 100644 index 00000000..6bf96db5 --- /dev/null +++ b/patches/openvm-mem/src/tests.rs @@ -0,0 +1,124 @@ +extern crate std; + +use std::{vec, vec::Vec}; + +use super::*; + +const PAD: u8 = 0xAA; +/// Every source/destination offset within a memory block, plus one past it. +const OFFSETS: usize = 9; +/// Exercises both bulk-loop iterations and every `copy_tail` arm. +const MAX_LEN: usize = 200; + +fn pattern(len: usize) -> Vec { + (0..len) + .map(|i| (i as u8).wrapping_mul(31).wrapping_add(7)) + .collect() +} + +#[test] +fn compare_bytes_matches_slice_cmp() { + let a = pattern(MAX_LEN + 2 * OFFSETS); + for n in 0..=MAX_LEN { + for a_off in 0..OFFSETS { + for b_off in 0..OFFSETS { + // Flip one byte at a time so every position is the first difference in turn, + // including positions only the overlapping final word can reach. + for flip in (0..n).chain([usize::MAX]) { + let mut b = a.clone(); + if flip != usize::MAX { + b[b_off + flip] ^= 0x80; + } + let got = + unsafe { compare_bytes(a.as_ptr().add(a_off), b.as_ptr().add(b_off), n) }; + let want = a[a_off..a_off + n].cmp(&b[b_off..b_off + n]); + assert_eq!( + got.signum(), + match want { + std::cmp::Ordering::Less => -1, + std::cmp::Ordering::Equal => 0, + std::cmp::Ordering::Greater => 1, + }, + "n={n} a_off={a_off} b_off={b_off} flip={flip}" + ); + let differ = + unsafe { bytes_differ(a.as_ptr().add(a_off), b.as_ptr().add(b_off), n) }; + assert_eq!(differ, want != std::cmp::Ordering::Equal); + } + } + } + } +} + +/// Overlap distances that straddle the bulk-loop stride in both copy directions. +const MAX_DELTA: usize = BLOCK + OFFSETS; + +#[test] +fn move_bytes_matches_copy_within() { + let base = pattern(MAX_LEN + 2 * MAX_DELTA); + let mut buf = base.clone(); + let mut expected = base.clone(); + for n in 0..=MAX_LEN { + for delta in 0..=MAX_DELTA { + // `dest` above `src` forces the backward copy, below it the forward one. + for (src_off, dest_off) in [ + (MAX_DELTA, MAX_DELTA + delta), + (MAX_DELTA + delta, MAX_DELTA), + ] { + buf.copy_from_slice(&base); + expected.copy_from_slice(&base); + expected.copy_within(src_off..src_off + n, dest_off); + unsafe { move_bytes(buf.as_mut_ptr().add(dest_off), buf.as_ptr().add(src_off), n) }; + assert_eq!(buf, expected, "n={n} delta={delta} dest_off={dest_off}"); + } + } + } +} + +#[test] +fn set_bytes_matches_fill() { + for n in 0..=MAX_LEN { + for dest_off in 0..OFFSETS { + let mut dest = vec![PAD; MAX_LEN + 2 * OFFSETS]; + unsafe { set_bytes(dest.as_mut_ptr().add(dest_off), 0x5C, n) }; + assert!( + dest[dest_off..dest_off + n].iter().all(|&b| b == 0x5C), + "n={n} dest_off={dest_off}" + ); + assert!( + dest[..dest_off].iter().all(|&b| b == PAD) + && dest[dest_off + n..].iter().all(|&b| b == PAD), + "wrote outside the destination range: n={n} dest_off={dest_off}" + ); + } + } +} + +#[test] +fn copy_forward_matches_slice_copy() { + let src = pattern(MAX_LEN + 2 * OFFSETS); + for n in 0..=MAX_LEN { + for src_off in 0..OFFSETS { + for dest_off in 0..OFFSETS { + let mut dest = vec![PAD; MAX_LEN + 2 * OFFSETS]; + unsafe { + copy_forward( + dest.as_mut_ptr().add(dest_off), + src.as_ptr().add(src_off), + n, + ) + }; + assert_eq!( + &dest[dest_off..dest_off + n], + &src[src_off..src_off + n], + "n={n} src_off={src_off} dest_off={dest_off}" + ); + assert!( + dest[..dest_off].iter().all(|&b| b == PAD) + && dest[dest_off + n..].iter().all(|&b| b == PAD), + "wrote outside the destination range: n={n} dest_off={dest_off}" + ); + } + } + } +} diff --git a/releases/dev/verifier/Halo2Verifier.sol b/releases/dev/verifier/Halo2Verifier.sol index ffe645a4..58cb0db4 100644 --- a/releases/dev/verifier/Halo2Verifier.sol +++ b/releases/dev/verifier/Halo2Verifier.sol @@ -1,3 +1,4 @@ + // SPDX-License-Identifier: MIT pragma solidity 0.8.19; @@ -23,2108 +24,1591 @@ contract Halo2Verifier { { let y_square := mulmod(y, y, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) let x_square := mulmod(x, x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let x_cube := - mulmod(x_square, x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let x_cube_plus_3 := - addmod(x_cube, 3, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + let x_cube := mulmod(x_square, x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + let x_cube_plus_3 := addmod(x_cube, 3, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) let is_affine := eq(x_cube_plus_3, y_square) valid := and(valid, is_affine) } } mstore(0xa0, mod(calldataload(0x0), f_q)) - mstore(0xc0, mod(calldataload(0x20), f_q)) - mstore(0xe0, mod(calldataload(0x40), f_q)) - mstore(0x100, mod(calldataload(0x60), f_q)) - mstore(0x120, mod(calldataload(0x80), f_q)) - mstore(0x140, mod(calldataload(0xa0), f_q)) - mstore(0x160, mod(calldataload(0xc0), f_q)) - mstore(0x180, mod(calldataload(0xe0), f_q)) - mstore(0x1a0, mod(calldataload(0x100), f_q)) - mstore(0x1c0, mod(calldataload(0x120), f_q)) - mstore(0x1e0, mod(calldataload(0x140), f_q)) - mstore(0x200, mod(calldataload(0x160), f_q)) - mstore(0x220, mod(calldataload(0x180), f_q)) - mstore(0x240, mod(calldataload(0x1a0), f_q)) - mstore(0x260, mod(calldataload(0x1c0), f_q)) - mstore(0x280, mod(calldataload(0x1e0), f_q)) - mstore(0x2a0, mod(calldataload(0x200), f_q)) - mstore(0x2c0, mod(calldataload(0x220), f_q)) - mstore(0x2e0, mod(calldataload(0x240), f_q)) - mstore(0x300, mod(calldataload(0x260), f_q)) - mstore(0x320, mod(calldataload(0x280), f_q)) - mstore(0x340, mod(calldataload(0x2a0), f_q)) - mstore(0x360, mod(calldataload(0x2c0), f_q)) - mstore(0x380, mod(calldataload(0x2e0), f_q)) - mstore(0x3a0, mod(calldataload(0x300), f_q)) - mstore(0x3c0, mod(calldataload(0x320), f_q)) - mstore(0x3e0, mod(calldataload(0x340), f_q)) - mstore(0x400, mod(calldataload(0x360), f_q)) - mstore(0x420, mod(calldataload(0x380), f_q)) - mstore(0x440, mod(calldataload(0x3a0), f_q)) - mstore(0x460, mod(calldataload(0x3c0), f_q)) - mstore(0x480, mod(calldataload(0x3e0), f_q)) - mstore(0x4a0, mod(calldataload(0x400), f_q)) - mstore(0x4c0, mod(calldataload(0x420), f_q)) - mstore(0x4e0, mod(calldataload(0x440), f_q)) - mstore(0x500, mod(calldataload(0x460), f_q)) - mstore(0x520, mod(calldataload(0x480), f_q)) - mstore(0x540, mod(calldataload(0x4a0), f_q)) - mstore(0x560, mod(calldataload(0x4c0), f_q)) - mstore(0x580, mod(calldataload(0x4e0), f_q)) - mstore(0x5a0, mod(calldataload(0x500), f_q)) - mstore(0x5c0, mod(calldataload(0x520), f_q)) - mstore(0x5e0, mod(calldataload(0x540), f_q)) - mstore(0x600, mod(calldataload(0x560), f_q)) - mstore(0x620, mod(calldataload(0x580), f_q)) - mstore(0x640, mod(calldataload(0x5a0), f_q)) - mstore(0x80, 6020310274882453454325098127953009151037386282312380019987349433040645771845) - - { - let x := calldataload(0x5c0) - mstore(0x660, x) - let y := calldataload(0x5e0) - mstore(0x680, y) - success := and(validate_ec_point(x, y), success) - } - mstore(0x6a0, keccak256(0x80, 1568)) - { - let hash := mload(0x6a0) - mstore(0x6c0, mod(hash, f_q)) - mstore(0x6e0, hash) - } - - { - let x := calldataload(0x600) - mstore(0x700, x) - let y := calldataload(0x620) - mstore(0x720, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x640) - mstore(0x740, x) - let y := calldataload(0x660) - mstore(0x760, y) - success := and(validate_ec_point(x, y), success) - } - mstore(0x780, keccak256(0x6e0, 160)) - { - let hash := mload(0x780) - mstore(0x7a0, mod(hash, f_q)) - mstore(0x7c0, hash) - } - mstore8(2016, 1) - mstore(0x7e0, keccak256(0x7c0, 33)) - { - let hash := mload(0x7e0) - mstore(0x800, mod(hash, f_q)) - mstore(0x820, hash) - } +mstore(0xc0, mod(calldataload(0x20), f_q)) +mstore(0xe0, mod(calldataload(0x40), f_q)) +mstore(0x100, mod(calldataload(0x60), f_q)) +mstore(0x120, mod(calldataload(0x80), f_q)) +mstore(0x140, mod(calldataload(0xa0), f_q)) +mstore(0x160, mod(calldataload(0xc0), f_q)) +mstore(0x180, mod(calldataload(0xe0), f_q)) +mstore(0x1a0, mod(calldataload(0x100), f_q)) +mstore(0x1c0, mod(calldataload(0x120), f_q)) +mstore(0x1e0, mod(calldataload(0x140), f_q)) +mstore(0x200, mod(calldataload(0x160), f_q)) +mstore(0x220, mod(calldataload(0x180), f_q)) +mstore(0x240, mod(calldataload(0x1a0), f_q)) +mstore(0x260, mod(calldataload(0x1c0), f_q)) +mstore(0x280, mod(calldataload(0x1e0), f_q)) +mstore(0x2a0, mod(calldataload(0x200), f_q)) +mstore(0x2c0, mod(calldataload(0x220), f_q)) +mstore(0x2e0, mod(calldataload(0x240), f_q)) +mstore(0x300, mod(calldataload(0x260), f_q)) +mstore(0x320, mod(calldataload(0x280), f_q)) +mstore(0x340, mod(calldataload(0x2a0), f_q)) +mstore(0x360, mod(calldataload(0x2c0), f_q)) +mstore(0x380, mod(calldataload(0x2e0), f_q)) +mstore(0x3a0, mod(calldataload(0x300), f_q)) +mstore(0x3c0, mod(calldataload(0x320), f_q)) +mstore(0x3e0, mod(calldataload(0x340), f_q)) +mstore(0x400, mod(calldataload(0x360), f_q)) +mstore(0x420, mod(calldataload(0x380), f_q)) +mstore(0x440, mod(calldataload(0x3a0), f_q)) +mstore(0x460, mod(calldataload(0x3c0), f_q)) +mstore(0x480, mod(calldataload(0x3e0), f_q)) +mstore(0x4a0, mod(calldataload(0x400), f_q)) +mstore(0x4c0, mod(calldataload(0x420), f_q)) +mstore(0x4e0, mod(calldataload(0x440), f_q)) +mstore(0x500, mod(calldataload(0x460), f_q)) +mstore(0x520, mod(calldataload(0x480), f_q)) +mstore(0x540, mod(calldataload(0x4a0), f_q)) +mstore(0x560, mod(calldataload(0x4c0), f_q)) +mstore(0x580, mod(calldataload(0x4e0), f_q)) +mstore(0x5a0, mod(calldataload(0x500), f_q)) +mstore(0x5c0, mod(calldataload(0x520), f_q)) +mstore(0x5e0, mod(calldataload(0x540), f_q)) +mstore(0x600, mod(calldataload(0x560), f_q)) +mstore(0x620, mod(calldataload(0x580), f_q)) +mstore(0x640, mod(calldataload(0x5a0), f_q)) +mstore(0x80, 2479125767233137909638766696349905838230848442510599249225196178102818148724) + + { + let x := calldataload(0x5c0) + mstore(0x660, x) + let y := calldataload(0x5e0) + mstore(0x680, y) + success := and(validate_ec_point(x, y), success) + } +mstore(0x6a0, keccak256(0x80, 1568)) +{ + let hash := mload(0x6a0) + mstore(0x6c0, mod(hash, f_q)) + mstore(0x6e0, hash) + } - { - let x := calldataload(0x680) - mstore(0x840, x) - let y := calldataload(0x6a0) - mstore(0x860, y) - success := and(validate_ec_point(x, y), success) - } + { + let x := calldataload(0x600) + mstore(0x700, x) + let y := calldataload(0x620) + mstore(0x720, y) + success := and(validate_ec_point(x, y), success) + } - { - let x := calldataload(0x6c0) - mstore(0x880, x) - let y := calldataload(0x6e0) - mstore(0x8a0, y) - success := and(validate_ec_point(x, y), success) - } + { + let x := calldataload(0x640) + mstore(0x740, x) + let y := calldataload(0x660) + mstore(0x760, y) + success := and(validate_ec_point(x, y), success) + } +mstore(0x780, keccak256(0x6e0, 160)) +{ + let hash := mload(0x780) + mstore(0x7a0, mod(hash, f_q)) + mstore(0x7c0, hash) + } +mstore8(2016, 1) +mstore(0x7e0, keccak256(0x7c0, 33)) +{ + let hash := mload(0x7e0) + mstore(0x800, mod(hash, f_q)) + mstore(0x820, hash) + } - { - let x := calldataload(0x700) - mstore(0x8c0, x) - let y := calldataload(0x720) - mstore(0x8e0, y) - success := and(validate_ec_point(x, y), success) - } - mstore(0x900, keccak256(0x820, 224)) - { - let hash := mload(0x900) - mstore(0x920, mod(hash, f_q)) - mstore(0x940, hash) - } + { + let x := calldataload(0x680) + mstore(0x840, x) + let y := calldataload(0x6a0) + mstore(0x860, y) + success := and(validate_ec_point(x, y), success) + } - { - let x := calldataload(0x740) - mstore(0x960, x) - let y := calldataload(0x760) - mstore(0x980, y) - success := and(validate_ec_point(x, y), success) - } + { + let x := calldataload(0x6c0) + mstore(0x880, x) + let y := calldataload(0x6e0) + mstore(0x8a0, y) + success := and(validate_ec_point(x, y), success) + } - { - let x := calldataload(0x780) - mstore(0x9a0, x) - let y := calldataload(0x7a0) - mstore(0x9c0, y) - success := and(validate_ec_point(x, y), success) - } + { + let x := calldataload(0x700) + mstore(0x8c0, x) + let y := calldataload(0x720) + mstore(0x8e0, y) + success := and(validate_ec_point(x, y), success) + } +mstore(0x900, keccak256(0x820, 224)) +{ + let hash := mload(0x900) + mstore(0x920, mod(hash, f_q)) + mstore(0x940, hash) + } - { - let x := calldataload(0x7c0) - mstore(0x9e0, x) - let y := calldataload(0x7e0) - mstore(0xa00, y) - success := and(validate_ec_point(x, y), success) - } + { + let x := calldataload(0x740) + mstore(0x960, x) + let y := calldataload(0x760) + mstore(0x980, y) + success := and(validate_ec_point(x, y), success) + } - { - let x := calldataload(0x800) - mstore(0xa20, x) - let y := calldataload(0x820) - mstore(0xa40, y) - success := and(validate_ec_point(x, y), success) - } - mstore(0xa60, keccak256(0x940, 288)) - { - let hash := mload(0xa60) - mstore(0xa80, mod(hash, f_q)) - mstore(0xaa0, hash) - } - mstore(0xac0, mod(calldataload(0x840), f_q)) - mstore(0xae0, mod(calldataload(0x860), f_q)) - mstore(0xb00, mod(calldataload(0x880), f_q)) - mstore(0xb20, mod(calldataload(0x8a0), f_q)) - mstore(0xb40, mod(calldataload(0x8c0), f_q)) - mstore(0xb60, mod(calldataload(0x8e0), f_q)) - mstore(0xb80, mod(calldataload(0x900), f_q)) - mstore(0xba0, mod(calldataload(0x920), f_q)) - mstore(0xbc0, mod(calldataload(0x940), f_q)) - mstore(0xbe0, mod(calldataload(0x960), f_q)) - mstore(0xc00, mod(calldataload(0x980), f_q)) - mstore(0xc20, mod(calldataload(0x9a0), f_q)) - mstore(0xc40, mod(calldataload(0x9c0), f_q)) - mstore(0xc60, mod(calldataload(0x9e0), f_q)) - mstore(0xc80, mod(calldataload(0xa00), f_q)) - mstore(0xca0, mod(calldataload(0xa20), f_q)) - mstore(0xcc0, mod(calldataload(0xa40), f_q)) - mstore(0xce0, mod(calldataload(0xa60), f_q)) - mstore(0xd00, mod(calldataload(0xa80), f_q)) - mstore(0xd20, keccak256(0xaa0, 640)) - { - let hash := mload(0xd20) - mstore(0xd40, mod(hash, f_q)) - mstore(0xd60, hash) - } - mstore8(3456, 1) - mstore(0xd80, keccak256(0xd60, 33)) - { - let hash := mload(0xd80) - mstore(0xda0, mod(hash, f_q)) - mstore(0xdc0, hash) - } + { + let x := calldataload(0x780) + mstore(0x9a0, x) + let y := calldataload(0x7a0) + mstore(0x9c0, y) + success := and(validate_ec_point(x, y), success) + } - { - let x := calldataload(0xaa0) - mstore(0xde0, x) - let y := calldataload(0xac0) - mstore(0xe00, y) - success := and(validate_ec_point(x, y), success) - } - mstore(0xe20, keccak256(0xdc0, 96)) - { - let hash := mload(0xe20) - mstore(0xe40, mod(hash, f_q)) - mstore(0xe60, hash) - } + { + let x := calldataload(0x7c0) + mstore(0x9e0, x) + let y := calldataload(0x7e0) + mstore(0xa00, y) + success := and(validate_ec_point(x, y), success) + } - { - let x := calldataload(0xae0) - mstore(0xe80, x) - let y := calldataload(0xb00) - mstore(0xea0, y) - success := and(validate_ec_point(x, y), success) - } - { - success := and(lt(mload(0xa0), shl(88, 1)), success) - let x := mload(0xa0) - success := and(lt(mload(0xc0), shl(88, 1)), success) - x := add(x, shl(88, mload(0xc0))) - success := and(lt(mload(0xe0), shl(80, 1)), success) - x := add(x, shl(176, mload(0xe0))) - mstore(3776, x) - success := and(lt(mload(0x100), shl(88, 1)), success) - let y := mload(0x100) - success := and(lt(mload(0x120), shl(88, 1)), success) - y := add(y, shl(88, mload(0x120))) - success := and(lt(mload(0x140), shl(80, 1)), success) - y := add(y, shl(176, mload(0x140))) - mstore(3808, y) + { + let x := calldataload(0x800) + mstore(0xa20, x) + let y := calldataload(0x820) + mstore(0xa40, y) + success := and(validate_ec_point(x, y), success) + } +mstore(0xa60, keccak256(0x940, 288)) +{ + let hash := mload(0xa60) + mstore(0xa80, mod(hash, f_q)) + mstore(0xaa0, hash) + } +mstore(0xac0, mod(calldataload(0x840), f_q)) +mstore(0xae0, mod(calldataload(0x860), f_q)) +mstore(0xb00, mod(calldataload(0x880), f_q)) +mstore(0xb20, mod(calldataload(0x8a0), f_q)) +mstore(0xb40, mod(calldataload(0x8c0), f_q)) +mstore(0xb60, mod(calldataload(0x8e0), f_q)) +mstore(0xb80, mod(calldataload(0x900), f_q)) +mstore(0xba0, mod(calldataload(0x920), f_q)) +mstore(0xbc0, mod(calldataload(0x940), f_q)) +mstore(0xbe0, mod(calldataload(0x960), f_q)) +mstore(0xc00, mod(calldataload(0x980), f_q)) +mstore(0xc20, mod(calldataload(0x9a0), f_q)) +mstore(0xc40, mod(calldataload(0x9c0), f_q)) +mstore(0xc60, mod(calldataload(0x9e0), f_q)) +mstore(0xc80, mod(calldataload(0xa00), f_q)) +mstore(0xca0, mod(calldataload(0xa20), f_q)) +mstore(0xcc0, mod(calldataload(0xa40), f_q)) +mstore(0xce0, mod(calldataload(0xa60), f_q)) +mstore(0xd00, mod(calldataload(0xa80), f_q)) +mstore(0xd20, keccak256(0xaa0, 640)) +{ + let hash := mload(0xd20) + mstore(0xd40, mod(hash, f_q)) + mstore(0xd60, hash) + } +mstore8(3456, 1) +mstore(0xd80, keccak256(0xd60, 33)) +{ + let hash := mload(0xd80) + mstore(0xda0, mod(hash, f_q)) + mstore(0xdc0, hash) + } - success := and(validate_ec_point(x, y), success) - } - { - success := and(lt(mload(0x160), shl(88, 1)), success) - let x := mload(0x160) - success := and(lt(mload(0x180), shl(88, 1)), success) - x := add(x, shl(88, mload(0x180))) - success := and(lt(mload(0x1a0), shl(80, 1)), success) - x := add(x, shl(176, mload(0x1a0))) - mstore(3840, x) - success := and(lt(mload(0x1c0), shl(88, 1)), success) - let y := mload(0x1c0) - success := and(lt(mload(0x1e0), shl(88, 1)), success) - y := add(y, shl(88, mload(0x1e0))) - success := and(lt(mload(0x200), shl(80, 1)), success) - y := add(y, shl(176, mload(0x200))) - mstore(3872, y) + { + let x := calldataload(0xaa0) + mstore(0xde0, x) + let y := calldataload(0xac0) + mstore(0xe00, y) + success := and(validate_ec_point(x, y), success) + } +mstore(0xe20, keccak256(0xdc0, 96)) +{ + let hash := mload(0xe20) + mstore(0xe40, mod(hash, f_q)) + mstore(0xe60, hash) + } - success := and(validate_ec_point(x, y), success) - } - mstore(0xf40, mulmod(mload(0xa80), mload(0xa80), f_q)) - mstore(0xf60, mulmod(mload(0xf40), mload(0xf40), f_q)) - mstore(0xf80, mulmod(mload(0xf60), mload(0xf60), f_q)) - mstore(0xfa0, mulmod(mload(0xf80), mload(0xf80), f_q)) - mstore(0xfc0, mulmod(mload(0xfa0), mload(0xfa0), f_q)) - mstore(0xfe0, mulmod(mload(0xfc0), mload(0xfc0), f_q)) - mstore(0x1000, mulmod(mload(0xfe0), mload(0xfe0), f_q)) - mstore(0x1020, mulmod(mload(0x1000), mload(0x1000), f_q)) - mstore(0x1040, mulmod(mload(0x1020), mload(0x1020), f_q)) - mstore(0x1060, mulmod(mload(0x1040), mload(0x1040), f_q)) - mstore(0x1080, mulmod(mload(0x1060), mload(0x1060), f_q)) - mstore(0x10a0, mulmod(mload(0x1080), mload(0x1080), f_q)) - mstore(0x10c0, mulmod(mload(0x10a0), mload(0x10a0), f_q)) - mstore(0x10e0, mulmod(mload(0x10c0), mload(0x10c0), f_q)) - mstore(0x1100, mulmod(mload(0x10e0), mload(0x10e0), f_q)) - mstore(0x1120, mulmod(mload(0x1100), mload(0x1100), f_q)) - mstore(0x1140, mulmod(mload(0x1120), mload(0x1120), f_q)) - mstore(0x1160, mulmod(mload(0x1140), mload(0x1140), f_q)) - mstore(0x1180, mulmod(mload(0x1160), mload(0x1160), f_q)) - mstore(0x11a0, mulmod(mload(0x1180), mload(0x1180), f_q)) - mstore(0x11c0, mulmod(mload(0x11a0), mload(0x11a0), f_q)) - mstore(0x11e0, mulmod(mload(0x11c0), mload(0x11c0), f_q)) - mstore( - 0x1200, - addmod( - mload(0x11e0), - 21888242871839275222246405745257275088548364400416034343698204186575808495616, - f_q - ) - ) - mstore( - 0x1220, - mulmod( - mload(0x1200), - 21888237653275510688422624196183639687472264873923820041627027729598873448513, - f_q - ) - ) - mstore( - 0x1240, - mulmod( - mload(0x1220), - 13225785879531581993054172815365636627224369411478295502904397545373139154045, - f_q - ) - ) - mstore( - 0x1260, - addmod(mload(0xa80), 8662456992307693229192232929891638461323994988937738840793806641202669341572, f_q) - ) - mstore( - 0x1280, - mulmod( - mload(0x1220), - 10939663269433627367777756708678102241564365262857670666700619874077960926249, - f_q - ) - ) - mstore( - 0x12a0, - addmod(mload(0xa80), 10948579602405647854468649036579172846983999137558363676997584312497847569368, f_q) - ) - mstore( - 0x12c0, - mulmod( - mload(0x1220), - 11016257578652593686382655500910603527869149377564754001549454008164059876499, - f_q - ) - ) - mstore( - 0x12e0, - addmod(mload(0xa80), 10871985293186681535863750244346671560679215022851280342148750178411748619118, f_q) - ) - mstore( - 0x1300, - mulmod( - mload(0x1220), - 15402826414547299628414612080036060696555554914079673875872749760617770134879, - f_q - ) - ) - mstore( - 0x1320, - addmod(mload(0xa80), 6485416457291975593831793665221214391992809486336360467825454425958038360738, f_q) - ) - mstore( - 0x1340, - mulmod( - mload(0x1220), - 21710372849001950800533397158415938114909991150039389063546734567764856596059, - f_q - ) - ) - mstore( - 0x1360, - addmod(mload(0xa80), 177870022837324421713008586841336973638373250376645280151469618810951899558, f_q) - ) - mstore( - 0x1380, - mulmod(mload(0x1220), 2785514556381676080176937710880804108647911392478702105860685610379369825016, f_q) - ) - mstore( - 0x13a0, - addmod(mload(0xa80), 19102728315457599142069468034376470979900453007937332237837518576196438670601, f_q) - ) - mstore( - 0x13c0, - mulmod(mload(0x1220), 8734126352828345679573237859165904705806588461301144420590422589042130041188, f_q) - ) - mstore( - 0x13e0, - addmod(mload(0xa80), 13154116519010929542673167886091370382741775939114889923107781597533678454429, f_q) - ) - mstore(0x1400, mulmod(mload(0x1220), 1, f_q)) - mstore( - 0x1420, - addmod(mload(0xa80), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q) - ) - mstore( - 0x1440, - mulmod( - mload(0x1220), - 11211301017135681023579411905410872569206244553457844956874280139879520583390, - f_q - ) - ) - mstore( - 0x1460, - addmod(mload(0xa80), 10676941854703594198666993839846402519342119846958189386823924046696287912227, f_q) - ) - mstore( - 0x1480, - mulmod(mload(0x1220), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q) - ) - mstore( - 0x14a0, - addmod(mload(0xa80), 20461838439117790833741043996939313553025008529160428886800406442142042007110, f_q) - ) - mstore( - 0x14c0, - mulmod( - mload(0x1220), - 12619617507853212586156872920672483948819476989779550311307282715684870266992, - f_q - ) - ) - mstore( - 0x14e0, - addmod(mload(0xa80), 9268625363986062636089532824584791139728887410636484032390921470890938228625, f_q) - ) - mstore( - 0x1500, - mulmod( - mload(0x1220), - 19032961837237948602743626455740240236231119053033140765040043513661803148152, - f_q - ) - ) - mstore( - 0x1520, - addmod(mload(0xa80), 2855281034601326619502779289517034852317245347382893578658160672914005347465, f_q) - ) - mstore( - 0x1540, - mulmod(mload(0x1220), 915149353520972163646494413843788069594022902357002628455555785223409501882, f_q) - ) - mstore( - 0x1560, - addmod(mload(0xa80), 20973093518318303058599911331413487018954341498059031715242648401352398993735, f_q) - ) - mstore( - 0x1580, - mulmod(mload(0x1220), 3766081621734395783232337525162072736827576297943013392955872170138036189193, f_q) - ) - mstore( - 0x15a0, - addmod(mload(0xa80), 18122161250104879439014068220095202351720788102473020950742332016437772306424, f_q) - ) - mstore( - 0x15c0, - mulmod(mload(0x1220), 4245441013247250116003069945606352967193023389718465410501109428393342802981, f_q) - ) - mstore( - 0x15e0, - addmod(mload(0xa80), 17642801858592025106243335799650922121355341010697568933197094758182465692636, f_q) - ) - mstore( - 0x1600, - mulmod(mload(0x1220), 5854133144571823792863860130267644613802765696134002830362054821530146160770, f_q) - ) - mstore( - 0x1620, - addmod(mload(0xa80), 16034109727267451429382545614989630474745598704282031513336149365045662334847, f_q) - ) - mstore( - 0x1640, - mulmod(mload(0x1220), 5980488956150442207659150513163747165544364597008566989111579977672498964212, f_q) - ) - mstore( - 0x1660, - addmod(mload(0xa80), 15907753915688833014587255232093527923003999803407467354586624208903309531405, f_q) - ) - mstore( - 0x1680, - mulmod( - mload(0x1220), - 14557038802599140430182096396825290815503940951075961210638273254419942783582, - f_q - ) - ) - mstore( - 0x16a0, - addmod(mload(0xa80), 7331204069240134792064309348431984273044423449340073133059930932155865712035, f_q) - ) - mstore( - 0x16c0, - mulmod( - mload(0x1220), - 13553911191894110065493137367144919847521088405945523452288398666974237857208, - f_q - ) - ) - mstore( - 0x16e0, - addmod(mload(0xa80), 8334331679945165156753268378112355241027275994470510891409805519601570638409, f_q) - ) - mstore( - 0x1700, - mulmod(mload(0x1220), 9697063347556872083384215826199993067635178715531258559890418744774301211662, f_q) - ) - mstore( - 0x1720, - addmod(mload(0xa80), 12191179524282403138862189919057282020913185684884775783807785441801507283955, f_q) - ) - mstore( - 0x1740, - mulmod( - mload(0x1220), - 10807735674816066981985242612061336605021639643453679977988966079770672437131, - f_q - ) - ) - mstore( - 0x1760, - addmod(mload(0xa80), 11080507197023208240261163133195938483526724756962354365709238106805136058486, f_q) - ) - mstore( - 0x1780, - mulmod( - mload(0x1220), - 12459868075641381822485233712013080087763946065665469821362892189399541605692, - f_q - ) - ) - mstore( - 0x17a0, - addmod(mload(0xa80), 9428374796197893399761172033244195000784418334750564522335311997176266889925, f_q) - ) - mstore( - 0x17c0, - mulmod( - mload(0x1220), - 16038300751658239075779628684257016433412502747804121525056508685985277092575, - f_q - ) - ) - mstore( - 0x17e0, - addmod(mload(0xa80), 5849942120181036146466777061000258655135861652611912818641695500590531403042, f_q) - ) - mstore( - 0x1800, - mulmod(mload(0x1220), 6955697244493336113861667751840378876927906302623587437721024018233754910398, f_q) - ) - mstore( - 0x1820, - addmod(mload(0xa80), 14932545627345939108384737993416896211620458097792446905977180168342053585219, f_q) - ) - mstore( - 0x1840, - mulmod( - mload(0x1220), - 13498745591877810872211159461644682954739332524336278910448604883789771736885, - f_q - ) - ) - mstore( - 0x1860, - addmod(mload(0xa80), 8389497279961464350035246283612592133809031876079755433249599302786036758732, f_q) - ) - mstore( - 0x1880, - mulmod( - mload(0x1220), - 20345677989844117909528750049476969581182118546166966482506114734614108237981, - f_q - ) - ) - mstore( - 0x18a0, - addmod(mload(0xa80), 1542564881995157312717655695780305507366245854249067861192089451961700257636, f_q) - ) - mstore( - 0x18c0, - mulmod(mload(0x1220), 790608022292213379425324383664216541739009722347092850716054055768832299157, f_q) - ) - mstore( - 0x18e0, - addmod(mload(0xa80), 21097634849547061842821081361593058546809354678068941492982150130806976196460, f_q) - ) - mstore( - 0x1900, - mulmod(mload(0x1220), 5289443209903185443361862148540090689648485914368835830972895623576469023722, f_q) - ) - mstore( - 0x1920, - addmod(mload(0xa80), 16598799661936089778884543596717184398899878486047198512725308562999339471895, f_q) - ) - mstore( - 0x1940, - mulmod( - mload(0x1220), - 15161189183906287273290738379431332336600234154579306802151507052820126345529, - f_q - ) - ) - mstore( - 0x1960, - addmod(mload(0xa80), 6727053687932987948955667365825942751948130245836727541546697133755682150088, f_q) - ) - mstore( - 0x1980, - mulmod(mload(0x1220), 557567375339945239933617516585967620814823575807691402619711360028043331811, f_q) - ) - mstore( - 0x19a0, - addmod(mload(0xa80), 21330675496499329982312788228671307467733540824608342941078492826547765163806, f_q) - ) - mstore( - 0x19c0, - mulmod( - mload(0x1220), - 16611719114775828483319365659907682366622074960672212059891361227499450055959, - f_q - ) - ) - mstore( - 0x19e0, - addmod(mload(0xa80), 5276523757063446738927040085349592721926289439743822283806842959076358439658, f_q) - ) - mstore( - 0x1a00, - mulmod(mload(0x1220), 4509404676247677387317362072810231899718070082381452255950861037254608304934, f_q) - ) - mstore( - 0x1a20, - addmod(mload(0xa80), 17378838195591597834929043672447043188830294318034582087747343149321200190683, f_q) - ) - mstore( - 0x1a40, - mulmod(mload(0x1220), 6866457077948847028333856457654941632900463970069876241424363695212127143359, f_q) - ) - mstore( - 0x1a60, - addmod(mload(0xa80), 15021785793890428193912549287602333455647900430346158102273840491363681352258, f_q) - ) - mstore( - 0x1a80, - mulmod( - mload(0x1220), - 20169013865622130318472103510465966222180994822334426398191891983290742724178, - f_q - ) - ) - mstore( - 0x1aa0, - addmod(mload(0xa80), 1719229006217144903774302234791308866367369578081607945506312203285065771439, f_q) - ) - mstore( - 0x1ac0, - mulmod( - mload(0x1220), - 14874205783542236433261764022044465911656512639684999678853651860683757650009, - f_q - ) - ) - mstore( - 0x1ae0, - addmod(mload(0xa80), 7014037088297038788984641723212809176891851760731034664844552325892050845608, f_q) - ) - mstore( - 0x1b00, - mulmod(mload(0x1220), 2579947959091681244170407980400327834520881737801886423874592072501514087543, f_q) - ) - mstore( - 0x1b20, - addmod(mload(0xa80), 19308294912747593978075997764856947254027482662614147919823612114074294408074, f_q) - ) - mstore( - 0x1b40, - mulmod( - mload(0x1220), - 17011225028452114973964561549541821925778010085385130152192105634715080939230, - f_q - ) - ) - mstore( - 0x1b60, - addmod(mload(0xa80), 4877017843387160248281844195715453162770354315030904191506098551860727556387, f_q) - ) - mstore( - 0x1b80, - mulmod(mload(0x1220), 1881761935718519990121799628252273658786792458106649887437395059872945867717, f_q) - ) - mstore( - 0x1ba0, - addmod(mload(0xa80), 20006480936120755232124606117005001429761571942309384456260809126702862627900, f_q) - ) - mstore( - 0x1bc0, - mulmod( - mload(0x1220), - 21662285561588145310352318480822402603888953131447478827940284064946709915517, - f_q - ) - ) - mstore( - 0x1be0, - addmod(mload(0xa80), 225957310251129911894087264434872484659411268968555515757920121629098580100, f_q) - ) - mstore( - 0x1c00, - mulmod( - mload(0x1220), - 21846745818185811051373434299876022191132089169516983080959277716660228899818, - f_q - ) - ) - mstore( - 0x1c20, - addmod(mload(0xa80), 41497053653464170872971445381252897416275230899051262738926469915579595799, f_q) - ) - mstore( - 0x1c40, - mulmod( - mload(0x1220), - 11770617947510597378885200406447716404126404817511323735042103519754393416137, - f_q - ) - ) - mstore( - 0x1c60, - addmod(mload(0xa80), 10117624924328677843361205338809558684421959582904710608656100666821415079480, f_q) - ) - mstore( - 0x1c80, - mulmod( - mload(0x1220), - 13018529307372270489258244406856841315962482733096074798317807775255504614069, - f_q - ) - ) - mstore( - 0x1ca0, - addmod(mload(0xa80), 8869713564467004732988161338400433772585881667319959545380396411320303881548, f_q) - ) - mstore( - 0x1cc0, - mulmod(mload(0x1220), 5276270562549512946272803945594037128265390012927669941530122528135796334063, f_q) - ) - mstore( - 0x1ce0, - addmod(mload(0xa80), 16611972309289762275973601799663237960282974387488364402168081658440012161554, f_q) - ) - mstore( - 0x1d00, - mulmod(mload(0x1220), 1459528961030896569807206253631725410868595642414057264270714861278164633285, f_q) - ) - mstore( - 0x1d20, - addmod(mload(0xa80), 20428713910808378652439199491625549677679768758001977079427489325297643862332, f_q) - ) - mstore( - 0x1d40, - mulmod(mload(0x1220), 3194789416964050406424265110350613664596286587119568977604859939037397011192, f_q) - ) - mstore( - 0x1d60, - addmod(mload(0xa80), 18693453454875224815822140634906661423952077813296465366093344247538411484425, f_q) - ) - mstore( - 0x1d80, - mulmod(mload(0x1220), 3090451643741879200285099477849831179472024364989630500355756836624424014697, f_q) - ) - mstore( - 0x1da0, - addmod(mload(0xa80), 18797791228097396021961306267407443909076340035426403843342447349951384480920, f_q) - ) - mstore( - 0x1dc0, - mulmod( - mload(0x1220), - 15927748781034921005593027077824543133423706442106451156060388409950986747549, - f_q - ) - ) - mstore( - 0x1de0, - addmod(mload(0xa80), 5960494090804354216653378667432731955124657958309583187637815776624821748068, f_q) - ) - mstore( - 0x1e00, - mulmod( - mload(0x1220), - 21594472933355353940227302948201802990541640451776958309590170926766063614527, - f_q - ) - ) - mstore( - 0x1e20, - addmod(mload(0xa80), 293769938483921282019102797055472098006723948639076034108033259809744881090, f_q) - ) - mstore( - 0x1e40, - mulmod( - mload(0x1220), - 18627493688178473377890450102960302362510276568110871848038317193719995024144, - f_q - ) - ) - mstore( - 0x1e60, - addmod(mload(0xa80), 3260749183660801844355955642296972726038087832305162495659886992855813471473, f_q) - ) - mstore( - 0x1e80, - mulmod( - mload(0x1220), - 15233875724801927436678555222002139405060841628305391430751578735629430475003, - f_q - ) - ) - mstore( - 0x1ea0, - addmod(mload(0xa80), 6654367147037347785567850523255135683487522772110642912946625450946378020614, f_q) - ) - mstore( - 0x1ec0, - mulmod( - mload(0x1220), - 12662796367122493153085459582914902083443981635312477834616629373139110863873, - f_q - ) - ) - mstore( - 0x1ee0, - addmod(mload(0xa80), 9225446504716782069160946162342373005104382765103556509081574813436697631744, f_q) - ) - mstore( - 0x1f00, - mulmod(mload(0x1220), 9228489335593836417731216695316971397516686186585289059470421738439643366942, f_q) - ) - mstore( - 0x1f20, - addmod(mload(0xa80), 12659753536245438804515189049940303691031678213830745284227782448136165128675, f_q) - ) - mstore( - 0x1f40, - mulmod(mload(0x1220), 6904960663187367776878651408524770307710353971752548687936010869699798414796, f_q) - ) - mstore( - 0x1f60, - addmod(mload(0xa80), 14983282208651907445367754336732504780838010428663485655762193316876010080821, f_q) - ) - { - let prod := mload(0x1260) + { + let x := calldataload(0xae0) + mstore(0xe80, x) + let y := calldataload(0xb00) + mstore(0xea0, y) + success := and(validate_ec_point(x, y), success) + } +{ + success := and(lt(mload(0xa0), shl(88, 1)), success) +let x := mload(0xa0) +success := and(lt(mload(0xc0), shl(88, 1)), success) +x := add(x, shl(88, mload(0xc0))) +success := and(lt(mload(0xe0), shl(80, 1)), success) +x := add(x, shl(176, mload(0xe0))) +mstore(3776, x) +success := and(lt(mload(0x100), shl(88, 1)), success) +let y := mload(0x100) +success := and(lt(mload(0x120), shl(88, 1)), success) +y := add(y, shl(88, mload(0x120))) +success := and(lt(mload(0x140), shl(80, 1)), success) +y := add(y, shl(176, mload(0x140))) +mstore(3808, y) + + success := and(validate_ec_point(x, y), success) + } +{ + success := and(lt(mload(0x160), shl(88, 1)), success) +let x := mload(0x160) +success := and(lt(mload(0x180), shl(88, 1)), success) +x := add(x, shl(88, mload(0x180))) +success := and(lt(mload(0x1a0), shl(80, 1)), success) +x := add(x, shl(176, mload(0x1a0))) +mstore(3840, x) +success := and(lt(mload(0x1c0), shl(88, 1)), success) +let y := mload(0x1c0) +success := and(lt(mload(0x1e0), shl(88, 1)), success) +y := add(y, shl(88, mload(0x1e0))) +success := and(lt(mload(0x200), shl(80, 1)), success) +y := add(y, shl(176, mload(0x200))) +mstore(3872, y) + + success := and(validate_ec_point(x, y), success) + } +mstore(0xf40, mulmod(mload(0xa80), mload(0xa80), f_q)) +mstore(0xf60, mulmod(mload(0xf40), mload(0xf40), f_q)) +mstore(0xf80, mulmod(mload(0xf60), mload(0xf60), f_q)) +mstore(0xfa0, mulmod(mload(0xf80), mload(0xf80), f_q)) +mstore(0xfc0, mulmod(mload(0xfa0), mload(0xfa0), f_q)) +mstore(0xfe0, mulmod(mload(0xfc0), mload(0xfc0), f_q)) +mstore(0x1000, mulmod(mload(0xfe0), mload(0xfe0), f_q)) +mstore(0x1020, mulmod(mload(0x1000), mload(0x1000), f_q)) +mstore(0x1040, mulmod(mload(0x1020), mload(0x1020), f_q)) +mstore(0x1060, mulmod(mload(0x1040), mload(0x1040), f_q)) +mstore(0x1080, mulmod(mload(0x1060), mload(0x1060), f_q)) +mstore(0x10a0, mulmod(mload(0x1080), mload(0x1080), f_q)) +mstore(0x10c0, mulmod(mload(0x10a0), mload(0x10a0), f_q)) +mstore(0x10e0, mulmod(mload(0x10c0), mload(0x10c0), f_q)) +mstore(0x1100, mulmod(mload(0x10e0), mload(0x10e0), f_q)) +mstore(0x1120, mulmod(mload(0x1100), mload(0x1100), f_q)) +mstore(0x1140, mulmod(mload(0x1120), mload(0x1120), f_q)) +mstore(0x1160, mulmod(mload(0x1140), mload(0x1140), f_q)) +mstore(0x1180, mulmod(mload(0x1160), mload(0x1160), f_q)) +mstore(0x11a0, mulmod(mload(0x1180), mload(0x1180), f_q)) +mstore(0x11c0, mulmod(mload(0x11a0), mload(0x11a0), f_q)) +mstore(0x11e0, mulmod(mload(0x11c0), mload(0x11c0), f_q)) +mstore(0x1200, addmod(mload(0x11e0), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q)) +mstore(0x1220, mulmod(mload(0x1200), 21888237653275510688422624196183639687472264873923820041627027729598873448513, f_q)) +mstore(0x1240, mulmod(mload(0x1220), 13225785879531581993054172815365636627224369411478295502904397545373139154045, f_q)) +mstore(0x1260, addmod(mload(0xa80), 8662456992307693229192232929891638461323994988937738840793806641202669341572, f_q)) +mstore(0x1280, mulmod(mload(0x1220), 10939663269433627367777756708678102241564365262857670666700619874077960926249, f_q)) +mstore(0x12a0, addmod(mload(0xa80), 10948579602405647854468649036579172846983999137558363676997584312497847569368, f_q)) +mstore(0x12c0, mulmod(mload(0x1220), 11016257578652593686382655500910603527869149377564754001549454008164059876499, f_q)) +mstore(0x12e0, addmod(mload(0xa80), 10871985293186681535863750244346671560679215022851280342148750178411748619118, f_q)) +mstore(0x1300, mulmod(mload(0x1220), 15402826414547299628414612080036060696555554914079673875872749760617770134879, f_q)) +mstore(0x1320, addmod(mload(0xa80), 6485416457291975593831793665221214391992809486336360467825454425958038360738, f_q)) +mstore(0x1340, mulmod(mload(0x1220), 21710372849001950800533397158415938114909991150039389063546734567764856596059, f_q)) +mstore(0x1360, addmod(mload(0xa80), 177870022837324421713008586841336973638373250376645280151469618810951899558, f_q)) +mstore(0x1380, mulmod(mload(0x1220), 2785514556381676080176937710880804108647911392478702105860685610379369825016, f_q)) +mstore(0x13a0, addmod(mload(0xa80), 19102728315457599142069468034376470979900453007937332237837518576196438670601, f_q)) +mstore(0x13c0, mulmod(mload(0x1220), 8734126352828345679573237859165904705806588461301144420590422589042130041188, f_q)) +mstore(0x13e0, addmod(mload(0xa80), 13154116519010929542673167886091370382741775939114889923107781597533678454429, f_q)) +mstore(0x1400, mulmod(mload(0x1220), 1, f_q)) +mstore(0x1420, addmod(mload(0xa80), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q)) +mstore(0x1440, mulmod(mload(0x1220), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q)) +mstore(0x1460, addmod(mload(0xa80), 10676941854703594198666993839846402519342119846958189386823924046696287912227, f_q)) +mstore(0x1480, mulmod(mload(0x1220), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q)) +mstore(0x14a0, addmod(mload(0xa80), 20461838439117790833741043996939313553025008529160428886800406442142042007110, f_q)) +mstore(0x14c0, mulmod(mload(0x1220), 12619617507853212586156872920672483948819476989779550311307282715684870266992, f_q)) +mstore(0x14e0, addmod(mload(0xa80), 9268625363986062636089532824584791139728887410636484032390921470890938228625, f_q)) +mstore(0x1500, mulmod(mload(0x1220), 19032961837237948602743626455740240236231119053033140765040043513661803148152, f_q)) +mstore(0x1520, addmod(mload(0xa80), 2855281034601326619502779289517034852317245347382893578658160672914005347465, f_q)) +mstore(0x1540, mulmod(mload(0x1220), 915149353520972163646494413843788069594022902357002628455555785223409501882, f_q)) +mstore(0x1560, addmod(mload(0xa80), 20973093518318303058599911331413487018954341498059031715242648401352398993735, f_q)) +mstore(0x1580, mulmod(mload(0x1220), 3766081621734395783232337525162072736827576297943013392955872170138036189193, f_q)) +mstore(0x15a0, addmod(mload(0xa80), 18122161250104879439014068220095202351720788102473020950742332016437772306424, f_q)) +mstore(0x15c0, mulmod(mload(0x1220), 4245441013247250116003069945606352967193023389718465410501109428393342802981, f_q)) +mstore(0x15e0, addmod(mload(0xa80), 17642801858592025106243335799650922121355341010697568933197094758182465692636, f_q)) +mstore(0x1600, mulmod(mload(0x1220), 5854133144571823792863860130267644613802765696134002830362054821530146160770, f_q)) +mstore(0x1620, addmod(mload(0xa80), 16034109727267451429382545614989630474745598704282031513336149365045662334847, f_q)) +mstore(0x1640, mulmod(mload(0x1220), 5980488956150442207659150513163747165544364597008566989111579977672498964212, f_q)) +mstore(0x1660, addmod(mload(0xa80), 15907753915688833014587255232093527923003999803407467354586624208903309531405, f_q)) +mstore(0x1680, mulmod(mload(0x1220), 14557038802599140430182096396825290815503940951075961210638273254419942783582, f_q)) +mstore(0x16a0, addmod(mload(0xa80), 7331204069240134792064309348431984273044423449340073133059930932155865712035, f_q)) +mstore(0x16c0, mulmod(mload(0x1220), 13553911191894110065493137367144919847521088405945523452288398666974237857208, f_q)) +mstore(0x16e0, addmod(mload(0xa80), 8334331679945165156753268378112355241027275994470510891409805519601570638409, f_q)) +mstore(0x1700, mulmod(mload(0x1220), 9697063347556872083384215826199993067635178715531258559890418744774301211662, f_q)) +mstore(0x1720, addmod(mload(0xa80), 12191179524282403138862189919057282020913185684884775783807785441801507283955, f_q)) +mstore(0x1740, mulmod(mload(0x1220), 10807735674816066981985242612061336605021639643453679977988966079770672437131, f_q)) +mstore(0x1760, addmod(mload(0xa80), 11080507197023208240261163133195938483526724756962354365709238106805136058486, f_q)) +mstore(0x1780, mulmod(mload(0x1220), 12459868075641381822485233712013080087763946065665469821362892189399541605692, f_q)) +mstore(0x17a0, addmod(mload(0xa80), 9428374796197893399761172033244195000784418334750564522335311997176266889925, f_q)) +mstore(0x17c0, mulmod(mload(0x1220), 16038300751658239075779628684257016433412502747804121525056508685985277092575, f_q)) +mstore(0x17e0, addmod(mload(0xa80), 5849942120181036146466777061000258655135861652611912818641695500590531403042, f_q)) +mstore(0x1800, mulmod(mload(0x1220), 6955697244493336113861667751840378876927906302623587437721024018233754910398, f_q)) +mstore(0x1820, addmod(mload(0xa80), 14932545627345939108384737993416896211620458097792446905977180168342053585219, f_q)) +mstore(0x1840, mulmod(mload(0x1220), 13498745591877810872211159461644682954739332524336278910448604883789771736885, f_q)) +mstore(0x1860, addmod(mload(0xa80), 8389497279961464350035246283612592133809031876079755433249599302786036758732, f_q)) +mstore(0x1880, mulmod(mload(0x1220), 20345677989844117909528750049476969581182118546166966482506114734614108237981, f_q)) +mstore(0x18a0, addmod(mload(0xa80), 1542564881995157312717655695780305507366245854249067861192089451961700257636, f_q)) +mstore(0x18c0, mulmod(mload(0x1220), 790608022292213379425324383664216541739009722347092850716054055768832299157, f_q)) +mstore(0x18e0, addmod(mload(0xa80), 21097634849547061842821081361593058546809354678068941492982150130806976196460, f_q)) +mstore(0x1900, mulmod(mload(0x1220), 5289443209903185443361862148540090689648485914368835830972895623576469023722, f_q)) +mstore(0x1920, addmod(mload(0xa80), 16598799661936089778884543596717184398899878486047198512725308562999339471895, f_q)) +mstore(0x1940, mulmod(mload(0x1220), 15161189183906287273290738379431332336600234154579306802151507052820126345529, f_q)) +mstore(0x1960, addmod(mload(0xa80), 6727053687932987948955667365825942751948130245836727541546697133755682150088, f_q)) +mstore(0x1980, mulmod(mload(0x1220), 557567375339945239933617516585967620814823575807691402619711360028043331811, f_q)) +mstore(0x19a0, addmod(mload(0xa80), 21330675496499329982312788228671307467733540824608342941078492826547765163806, f_q)) +mstore(0x19c0, mulmod(mload(0x1220), 16611719114775828483319365659907682366622074960672212059891361227499450055959, f_q)) +mstore(0x19e0, addmod(mload(0xa80), 5276523757063446738927040085349592721926289439743822283806842959076358439658, f_q)) +mstore(0x1a00, mulmod(mload(0x1220), 4509404676247677387317362072810231899718070082381452255950861037254608304934, f_q)) +mstore(0x1a20, addmod(mload(0xa80), 17378838195591597834929043672447043188830294318034582087747343149321200190683, f_q)) +mstore(0x1a40, mulmod(mload(0x1220), 6866457077948847028333856457654941632900463970069876241424363695212127143359, f_q)) +mstore(0x1a60, addmod(mload(0xa80), 15021785793890428193912549287602333455647900430346158102273840491363681352258, f_q)) +mstore(0x1a80, mulmod(mload(0x1220), 20169013865622130318472103510465966222180994822334426398191891983290742724178, f_q)) +mstore(0x1aa0, addmod(mload(0xa80), 1719229006217144903774302234791308866367369578081607945506312203285065771439, f_q)) +mstore(0x1ac0, mulmod(mload(0x1220), 14874205783542236433261764022044465911656512639684999678853651860683757650009, f_q)) +mstore(0x1ae0, addmod(mload(0xa80), 7014037088297038788984641723212809176891851760731034664844552325892050845608, f_q)) +mstore(0x1b00, mulmod(mload(0x1220), 2579947959091681244170407980400327834520881737801886423874592072501514087543, f_q)) +mstore(0x1b20, addmod(mload(0xa80), 19308294912747593978075997764856947254027482662614147919823612114074294408074, f_q)) +mstore(0x1b40, mulmod(mload(0x1220), 17011225028452114973964561549541821925778010085385130152192105634715080939230, f_q)) +mstore(0x1b60, addmod(mload(0xa80), 4877017843387160248281844195715453162770354315030904191506098551860727556387, f_q)) +mstore(0x1b80, mulmod(mload(0x1220), 1881761935718519990121799628252273658786792458106649887437395059872945867717, f_q)) +mstore(0x1ba0, addmod(mload(0xa80), 20006480936120755232124606117005001429761571942309384456260809126702862627900, f_q)) +mstore(0x1bc0, mulmod(mload(0x1220), 21662285561588145310352318480822402603888953131447478827940284064946709915517, f_q)) +mstore(0x1be0, addmod(mload(0xa80), 225957310251129911894087264434872484659411268968555515757920121629098580100, f_q)) +mstore(0x1c00, mulmod(mload(0x1220), 21846745818185811051373434299876022191132089169516983080959277716660228899818, f_q)) +mstore(0x1c20, addmod(mload(0xa80), 41497053653464170872971445381252897416275230899051262738926469915579595799, f_q)) +mstore(0x1c40, mulmod(mload(0x1220), 11770617947510597378885200406447716404126404817511323735042103519754393416137, f_q)) +mstore(0x1c60, addmod(mload(0xa80), 10117624924328677843361205338809558684421959582904710608656100666821415079480, f_q)) +mstore(0x1c80, mulmod(mload(0x1220), 13018529307372270489258244406856841315962482733096074798317807775255504614069, f_q)) +mstore(0x1ca0, addmod(mload(0xa80), 8869713564467004732988161338400433772585881667319959545380396411320303881548, f_q)) +mstore(0x1cc0, mulmod(mload(0x1220), 5276270562549512946272803945594037128265390012927669941530122528135796334063, f_q)) +mstore(0x1ce0, addmod(mload(0xa80), 16611972309289762275973601799663237960282974387488364402168081658440012161554, f_q)) +mstore(0x1d00, mulmod(mload(0x1220), 1459528961030896569807206253631725410868595642414057264270714861278164633285, f_q)) +mstore(0x1d20, addmod(mload(0xa80), 20428713910808378652439199491625549677679768758001977079427489325297643862332, f_q)) +mstore(0x1d40, mulmod(mload(0x1220), 3194789416964050406424265110350613664596286587119568977604859939037397011192, f_q)) +mstore(0x1d60, addmod(mload(0xa80), 18693453454875224815822140634906661423952077813296465366093344247538411484425, f_q)) +mstore(0x1d80, mulmod(mload(0x1220), 3090451643741879200285099477849831179472024364989630500355756836624424014697, f_q)) +mstore(0x1da0, addmod(mload(0xa80), 18797791228097396021961306267407443909076340035426403843342447349951384480920, f_q)) +mstore(0x1dc0, mulmod(mload(0x1220), 15927748781034921005593027077824543133423706442106451156060388409950986747549, f_q)) +mstore(0x1de0, addmod(mload(0xa80), 5960494090804354216653378667432731955124657958309583187637815776624821748068, f_q)) +mstore(0x1e00, mulmod(mload(0x1220), 21594472933355353940227302948201802990541640451776958309590170926766063614527, f_q)) +mstore(0x1e20, addmod(mload(0xa80), 293769938483921282019102797055472098006723948639076034108033259809744881090, f_q)) +mstore(0x1e40, mulmod(mload(0x1220), 18627493688178473377890450102960302362510276568110871848038317193719995024144, f_q)) +mstore(0x1e60, addmod(mload(0xa80), 3260749183660801844355955642296972726038087832305162495659886992855813471473, f_q)) +mstore(0x1e80, mulmod(mload(0x1220), 15233875724801927436678555222002139405060841628305391430751578735629430475003, f_q)) +mstore(0x1ea0, addmod(mload(0xa80), 6654367147037347785567850523255135683487522772110642912946625450946378020614, f_q)) +mstore(0x1ec0, mulmod(mload(0x1220), 12662796367122493153085459582914902083443981635312477834616629373139110863873, f_q)) +mstore(0x1ee0, addmod(mload(0xa80), 9225446504716782069160946162342373005104382765103556509081574813436697631744, f_q)) +mstore(0x1f00, mulmod(mload(0x1220), 9228489335593836417731216695316971397516686186585289059470421738439643366942, f_q)) +mstore(0x1f20, addmod(mload(0xa80), 12659753536245438804515189049940303691031678213830745284227782448136165128675, f_q)) +mstore(0x1f40, mulmod(mload(0x1220), 6904960663187367776878651408524770307710353971752548687936010869699798414796, f_q)) +mstore(0x1f60, addmod(mload(0xa80), 14983282208651907445367754336732504780838010428663485655762193316876010080821, f_q)) +{ + let prod := mload(0x1260) prod := mulmod(mload(0x12a0), prod, f_q) mstore(0x1f80, prod) - + prod := mulmod(mload(0x12e0), prod, f_q) mstore(0x1fa0, prod) - + prod := mulmod(mload(0x1320), prod, f_q) mstore(0x1fc0, prod) - + prod := mulmod(mload(0x1360), prod, f_q) mstore(0x1fe0, prod) - + prod := mulmod(mload(0x13a0), prod, f_q) mstore(0x2000, prod) - + prod := mulmod(mload(0x13e0), prod, f_q) mstore(0x2020, prod) - + prod := mulmod(mload(0x1420), prod, f_q) mstore(0x2040, prod) - + prod := mulmod(mload(0x1460), prod, f_q) mstore(0x2060, prod) - + prod := mulmod(mload(0x14a0), prod, f_q) mstore(0x2080, prod) - + prod := mulmod(mload(0x14e0), prod, f_q) mstore(0x20a0, prod) - + prod := mulmod(mload(0x1520), prod, f_q) mstore(0x20c0, prod) - + prod := mulmod(mload(0x1560), prod, f_q) mstore(0x20e0, prod) - + prod := mulmod(mload(0x15a0), prod, f_q) mstore(0x2100, prod) - + prod := mulmod(mload(0x15e0), prod, f_q) mstore(0x2120, prod) - + prod := mulmod(mload(0x1620), prod, f_q) mstore(0x2140, prod) - + prod := mulmod(mload(0x1660), prod, f_q) mstore(0x2160, prod) - + prod := mulmod(mload(0x16a0), prod, f_q) mstore(0x2180, prod) - + prod := mulmod(mload(0x16e0), prod, f_q) mstore(0x21a0, prod) - + prod := mulmod(mload(0x1720), prod, f_q) mstore(0x21c0, prod) - + prod := mulmod(mload(0x1760), prod, f_q) mstore(0x21e0, prod) - + prod := mulmod(mload(0x17a0), prod, f_q) mstore(0x2200, prod) - + prod := mulmod(mload(0x17e0), prod, f_q) mstore(0x2220, prod) - + prod := mulmod(mload(0x1820), prod, f_q) mstore(0x2240, prod) - + prod := mulmod(mload(0x1860), prod, f_q) mstore(0x2260, prod) - + prod := mulmod(mload(0x18a0), prod, f_q) mstore(0x2280, prod) - + prod := mulmod(mload(0x18e0), prod, f_q) mstore(0x22a0, prod) - + prod := mulmod(mload(0x1920), prod, f_q) mstore(0x22c0, prod) - + prod := mulmod(mload(0x1960), prod, f_q) mstore(0x22e0, prod) - + prod := mulmod(mload(0x19a0), prod, f_q) mstore(0x2300, prod) - + prod := mulmod(mload(0x19e0), prod, f_q) mstore(0x2320, prod) - + prod := mulmod(mload(0x1a20), prod, f_q) mstore(0x2340, prod) - + prod := mulmod(mload(0x1a60), prod, f_q) mstore(0x2360, prod) - + prod := mulmod(mload(0x1aa0), prod, f_q) mstore(0x2380, prod) - + prod := mulmod(mload(0x1ae0), prod, f_q) mstore(0x23a0, prod) - + prod := mulmod(mload(0x1b20), prod, f_q) mstore(0x23c0, prod) - + prod := mulmod(mload(0x1b60), prod, f_q) mstore(0x23e0, prod) - + prod := mulmod(mload(0x1ba0), prod, f_q) mstore(0x2400, prod) - + prod := mulmod(mload(0x1be0), prod, f_q) mstore(0x2420, prod) - + prod := mulmod(mload(0x1c20), prod, f_q) mstore(0x2440, prod) - + prod := mulmod(mload(0x1c60), prod, f_q) mstore(0x2460, prod) - + prod := mulmod(mload(0x1ca0), prod, f_q) mstore(0x2480, prod) - + prod := mulmod(mload(0x1ce0), prod, f_q) mstore(0x24a0, prod) - + prod := mulmod(mload(0x1d20), prod, f_q) mstore(0x24c0, prod) - + prod := mulmod(mload(0x1d60), prod, f_q) mstore(0x24e0, prod) - + prod := mulmod(mload(0x1da0), prod, f_q) mstore(0x2500, prod) - + prod := mulmod(mload(0x1de0), prod, f_q) mstore(0x2520, prod) - + prod := mulmod(mload(0x1e20), prod, f_q) mstore(0x2540, prod) - + prod := mulmod(mload(0x1e60), prod, f_q) mstore(0x2560, prod) - + prod := mulmod(mload(0x1ea0), prod, f_q) mstore(0x2580, prod) - + prod := mulmod(mload(0x1ee0), prod, f_q) mstore(0x25a0, prod) - + prod := mulmod(mload(0x1f20), prod, f_q) mstore(0x25c0, prod) - + prod := mulmod(mload(0x1f60), prod, f_q) mstore(0x25e0, prod) - + prod := mulmod(mload(0x1200), prod, f_q) mstore(0x2600, prod) - } - mstore(0x2640, 32) - mstore(0x2660, 32) - mstore(0x2680, 32) - mstore(0x26a0, mload(0x2600)) - mstore(0x26c0, 21888242871839275222246405745257275088548364400416034343698204186575808495615) - mstore(0x26e0, 21888242871839275222246405745257275088548364400416034343698204186575808495617) - success := and(eq(staticcall(gas(), 0x5, 0x2640, 0xc0, 0x2620, 0x20), 1), success) - { - let inv := mload(0x2620) - let v - - v := mload(0x1200) - mstore(4608, mulmod(mload(0x25e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1f60) - mstore(8032, mulmod(mload(0x25c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1f20) - mstore(7968, mulmod(mload(0x25a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1ee0) - mstore(7904, mulmod(mload(0x2580), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1ea0) - mstore(7840, mulmod(mload(0x2560), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1e60) - mstore(7776, mulmod(mload(0x2540), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1e20) - mstore(7712, mulmod(mload(0x2520), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1de0) - mstore(7648, mulmod(mload(0x2500), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1da0) - mstore(7584, mulmod(mload(0x24e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1d60) - mstore(7520, mulmod(mload(0x24c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1d20) - mstore(7456, mulmod(mload(0x24a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1ce0) - mstore(7392, mulmod(mload(0x2480), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1ca0) - mstore(7328, mulmod(mload(0x2460), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1c60) - mstore(7264, mulmod(mload(0x2440), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1c20) - mstore(7200, mulmod(mload(0x2420), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1be0) - mstore(7136, mulmod(mload(0x2400), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1ba0) - mstore(7072, mulmod(mload(0x23e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1b60) - mstore(7008, mulmod(mload(0x23c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1b20) - mstore(6944, mulmod(mload(0x23a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1ae0) - mstore(6880, mulmod(mload(0x2380), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1aa0) - mstore(6816, mulmod(mload(0x2360), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1a60) - mstore(6752, mulmod(mload(0x2340), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1a20) - mstore(6688, mulmod(mload(0x2320), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x19e0) - mstore(6624, mulmod(mload(0x2300), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x19a0) - mstore(6560, mulmod(mload(0x22e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1960) - mstore(6496, mulmod(mload(0x22c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1920) - mstore(6432, mulmod(mload(0x22a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x18e0) - mstore(6368, mulmod(mload(0x2280), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x18a0) - mstore(6304, mulmod(mload(0x2260), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1860) - mstore(6240, mulmod(mload(0x2240), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1820) - mstore(6176, mulmod(mload(0x2220), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x17e0) - mstore(6112, mulmod(mload(0x2200), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x17a0) - mstore(6048, mulmod(mload(0x21e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1760) - mstore(5984, mulmod(mload(0x21c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1720) - mstore(5920, mulmod(mload(0x21a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x16e0) - mstore(5856, mulmod(mload(0x2180), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x16a0) - mstore(5792, mulmod(mload(0x2160), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1660) - mstore(5728, mulmod(mload(0x2140), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1620) - mstore(5664, mulmod(mload(0x2120), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x15e0) - mstore(5600, mulmod(mload(0x2100), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x15a0) - mstore(5536, mulmod(mload(0x20e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1560) - mstore(5472, mulmod(mload(0x20c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1520) - mstore(5408, mulmod(mload(0x20a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x14e0) - mstore(5344, mulmod(mload(0x2080), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x14a0) - mstore(5280, mulmod(mload(0x2060), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1460) - mstore(5216, mulmod(mload(0x2040), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1420) - mstore(5152, mulmod(mload(0x2020), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x13e0) - mstore(5088, mulmod(mload(0x2000), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x13a0) - mstore(5024, mulmod(mload(0x1fe0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1360) - mstore(4960, mulmod(mload(0x1fc0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1320) - mstore(4896, mulmod(mload(0x1fa0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x12e0) - mstore(4832, mulmod(mload(0x1f80), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x12a0) - mstore(4768, mulmod(mload(0x1260), inv, f_q)) - inv := mulmod(v, inv, f_q) + + } +mstore(0x2640, 32) +mstore(0x2660, 32) +mstore(0x2680, 32) +mstore(0x26a0, mload(0x2600)) +mstore(0x26c0, 21888242871839275222246405745257275088548364400416034343698204186575808495615) +mstore(0x26e0, 21888242871839275222246405745257275088548364400416034343698204186575808495617) +success := and(eq(staticcall(gas(), 0x5, 0x2640, 0xc0, 0x2620, 0x20), 1), success) +{ + + let inv := mload(0x2620) + let v + + v := mload(0x1200) + mstore(4608, mulmod(mload(0x25e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1f60) + mstore(8032, mulmod(mload(0x25c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1f20) + mstore(7968, mulmod(mload(0x25a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1ee0) + mstore(7904, mulmod(mload(0x2580), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1ea0) + mstore(7840, mulmod(mload(0x2560), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1e60) + mstore(7776, mulmod(mload(0x2540), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1e20) + mstore(7712, mulmod(mload(0x2520), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1de0) + mstore(7648, mulmod(mload(0x2500), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1da0) + mstore(7584, mulmod(mload(0x24e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1d60) + mstore(7520, mulmod(mload(0x24c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1d20) + mstore(7456, mulmod(mload(0x24a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1ce0) + mstore(7392, mulmod(mload(0x2480), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1ca0) + mstore(7328, mulmod(mload(0x2460), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1c60) + mstore(7264, mulmod(mload(0x2440), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1c20) + mstore(7200, mulmod(mload(0x2420), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1be0) + mstore(7136, mulmod(mload(0x2400), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1ba0) + mstore(7072, mulmod(mload(0x23e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1b60) + mstore(7008, mulmod(mload(0x23c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1b20) + mstore(6944, mulmod(mload(0x23a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1ae0) + mstore(6880, mulmod(mload(0x2380), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1aa0) + mstore(6816, mulmod(mload(0x2360), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1a60) + mstore(6752, mulmod(mload(0x2340), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1a20) + mstore(6688, mulmod(mload(0x2320), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x19e0) + mstore(6624, mulmod(mload(0x2300), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x19a0) + mstore(6560, mulmod(mload(0x22e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1960) + mstore(6496, mulmod(mload(0x22c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1920) + mstore(6432, mulmod(mload(0x22a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x18e0) + mstore(6368, mulmod(mload(0x2280), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x18a0) + mstore(6304, mulmod(mload(0x2260), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1860) + mstore(6240, mulmod(mload(0x2240), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1820) + mstore(6176, mulmod(mload(0x2220), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x17e0) + mstore(6112, mulmod(mload(0x2200), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x17a0) + mstore(6048, mulmod(mload(0x21e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1760) + mstore(5984, mulmod(mload(0x21c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1720) + mstore(5920, mulmod(mload(0x21a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x16e0) + mstore(5856, mulmod(mload(0x2180), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x16a0) + mstore(5792, mulmod(mload(0x2160), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1660) + mstore(5728, mulmod(mload(0x2140), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1620) + mstore(5664, mulmod(mload(0x2120), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x15e0) + mstore(5600, mulmod(mload(0x2100), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x15a0) + mstore(5536, mulmod(mload(0x20e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1560) + mstore(5472, mulmod(mload(0x20c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1520) + mstore(5408, mulmod(mload(0x20a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x14e0) + mstore(5344, mulmod(mload(0x2080), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x14a0) + mstore(5280, mulmod(mload(0x2060), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1460) + mstore(5216, mulmod(mload(0x2040), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1420) + mstore(5152, mulmod(mload(0x2020), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x13e0) + mstore(5088, mulmod(mload(0x2000), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x13a0) + mstore(5024, mulmod(mload(0x1fe0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1360) + mstore(4960, mulmod(mload(0x1fc0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1320) + mstore(4896, mulmod(mload(0x1fa0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x12e0) + mstore(4832, mulmod(mload(0x1f80), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x12a0) + mstore(4768, mulmod(mload(0x1260), inv, f_q)) + inv := mulmod(v, inv, f_q) mstore(0x1260, inv) - } - mstore(0x2700, mulmod(mload(0x1240), mload(0x1260), f_q)) - mstore(0x2720, mulmod(mload(0x1280), mload(0x12a0), f_q)) - mstore(0x2740, mulmod(mload(0x12c0), mload(0x12e0), f_q)) - mstore(0x2760, mulmod(mload(0x1300), mload(0x1320), f_q)) - mstore(0x2780, mulmod(mload(0x1340), mload(0x1360), f_q)) - mstore(0x27a0, mulmod(mload(0x1380), mload(0x13a0), f_q)) - mstore(0x27c0, mulmod(mload(0x13c0), mload(0x13e0), f_q)) - mstore(0x27e0, mulmod(mload(0x1400), mload(0x1420), f_q)) - mstore(0x2800, mulmod(mload(0x1440), mload(0x1460), f_q)) - mstore(0x2820, mulmod(mload(0x1480), mload(0x14a0), f_q)) - mstore(0x2840, mulmod(mload(0x14c0), mload(0x14e0), f_q)) - mstore(0x2860, mulmod(mload(0x1500), mload(0x1520), f_q)) - mstore(0x2880, mulmod(mload(0x1540), mload(0x1560), f_q)) - mstore(0x28a0, mulmod(mload(0x1580), mload(0x15a0), f_q)) - mstore(0x28c0, mulmod(mload(0x15c0), mload(0x15e0), f_q)) - mstore(0x28e0, mulmod(mload(0x1600), mload(0x1620), f_q)) - mstore(0x2900, mulmod(mload(0x1640), mload(0x1660), f_q)) - mstore(0x2920, mulmod(mload(0x1680), mload(0x16a0), f_q)) - mstore(0x2940, mulmod(mload(0x16c0), mload(0x16e0), f_q)) - mstore(0x2960, mulmod(mload(0x1700), mload(0x1720), f_q)) - mstore(0x2980, mulmod(mload(0x1740), mload(0x1760), f_q)) - mstore(0x29a0, mulmod(mload(0x1780), mload(0x17a0), f_q)) - mstore(0x29c0, mulmod(mload(0x17c0), mload(0x17e0), f_q)) - mstore(0x29e0, mulmod(mload(0x1800), mload(0x1820), f_q)) - mstore(0x2a00, mulmod(mload(0x1840), mload(0x1860), f_q)) - mstore(0x2a20, mulmod(mload(0x1880), mload(0x18a0), f_q)) - mstore(0x2a40, mulmod(mload(0x18c0), mload(0x18e0), f_q)) - mstore(0x2a60, mulmod(mload(0x1900), mload(0x1920), f_q)) - mstore(0x2a80, mulmod(mload(0x1940), mload(0x1960), f_q)) - mstore(0x2aa0, mulmod(mload(0x1980), mload(0x19a0), f_q)) - mstore(0x2ac0, mulmod(mload(0x19c0), mload(0x19e0), f_q)) - mstore(0x2ae0, mulmod(mload(0x1a00), mload(0x1a20), f_q)) - mstore(0x2b00, mulmod(mload(0x1a40), mload(0x1a60), f_q)) - mstore(0x2b20, mulmod(mload(0x1a80), mload(0x1aa0), f_q)) - mstore(0x2b40, mulmod(mload(0x1ac0), mload(0x1ae0), f_q)) - mstore(0x2b60, mulmod(mload(0x1b00), mload(0x1b20), f_q)) - mstore(0x2b80, mulmod(mload(0x1b40), mload(0x1b60), f_q)) - mstore(0x2ba0, mulmod(mload(0x1b80), mload(0x1ba0), f_q)) - mstore(0x2bc0, mulmod(mload(0x1bc0), mload(0x1be0), f_q)) - mstore(0x2be0, mulmod(mload(0x1c00), mload(0x1c20), f_q)) - mstore(0x2c00, mulmod(mload(0x1c40), mload(0x1c60), f_q)) - mstore(0x2c20, mulmod(mload(0x1c80), mload(0x1ca0), f_q)) - mstore(0x2c40, mulmod(mload(0x1cc0), mload(0x1ce0), f_q)) - mstore(0x2c60, mulmod(mload(0x1d00), mload(0x1d20), f_q)) - mstore(0x2c80, mulmod(mload(0x1d40), mload(0x1d60), f_q)) - mstore(0x2ca0, mulmod(mload(0x1d80), mload(0x1da0), f_q)) - mstore(0x2cc0, mulmod(mload(0x1dc0), mload(0x1de0), f_q)) - mstore(0x2ce0, mulmod(mload(0x1e00), mload(0x1e20), f_q)) - mstore(0x2d00, mulmod(mload(0x1e40), mload(0x1e60), f_q)) - mstore(0x2d20, mulmod(mload(0x1e80), mload(0x1ea0), f_q)) - mstore(0x2d40, mulmod(mload(0x1ec0), mload(0x1ee0), f_q)) - mstore(0x2d60, mulmod(mload(0x1f00), mload(0x1f20), f_q)) - mstore(0x2d80, mulmod(mload(0x1f40), mload(0x1f60), f_q)) - { - let result := mulmod(mload(0x27e0), mload(0xa0), f_q) - result := addmod(mulmod(mload(0x2800), mload(0xc0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2820), mload(0xe0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2840), mload(0x100), f_q), result, f_q) - result := addmod(mulmod(mload(0x2860), mload(0x120), f_q), result, f_q) - result := addmod(mulmod(mload(0x2880), mload(0x140), f_q), result, f_q) - result := addmod(mulmod(mload(0x28a0), mload(0x160), f_q), result, f_q) - result := addmod(mulmod(mload(0x28c0), mload(0x180), f_q), result, f_q) - result := addmod(mulmod(mload(0x28e0), mload(0x1a0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2900), mload(0x1c0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2920), mload(0x1e0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2940), mload(0x200), f_q), result, f_q) - result := addmod(mulmod(mload(0x2960), mload(0x220), f_q), result, f_q) - result := addmod(mulmod(mload(0x2980), mload(0x240), f_q), result, f_q) - result := addmod(mulmod(mload(0x29a0), mload(0x260), f_q), result, f_q) - result := addmod(mulmod(mload(0x29c0), mload(0x280), f_q), result, f_q) - result := addmod(mulmod(mload(0x29e0), mload(0x2a0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2a00), mload(0x2c0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2a20), mload(0x2e0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2a40), mload(0x300), f_q), result, f_q) - result := addmod(mulmod(mload(0x2a60), mload(0x320), f_q), result, f_q) - result := addmod(mulmod(mload(0x2a80), mload(0x340), f_q), result, f_q) - result := addmod(mulmod(mload(0x2aa0), mload(0x360), f_q), result, f_q) - result := addmod(mulmod(mload(0x2ac0), mload(0x380), f_q), result, f_q) - result := addmod(mulmod(mload(0x2ae0), mload(0x3a0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2b00), mload(0x3c0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2b20), mload(0x3e0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2b40), mload(0x400), f_q), result, f_q) - result := addmod(mulmod(mload(0x2b60), mload(0x420), f_q), result, f_q) - result := addmod(mulmod(mload(0x2b80), mload(0x440), f_q), result, f_q) - result := addmod(mulmod(mload(0x2ba0), mload(0x460), f_q), result, f_q) - result := addmod(mulmod(mload(0x2bc0), mload(0x480), f_q), result, f_q) - result := addmod(mulmod(mload(0x2be0), mload(0x4a0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2c00), mload(0x4c0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2c20), mload(0x4e0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2c40), mload(0x500), f_q), result, f_q) - result := addmod(mulmod(mload(0x2c60), mload(0x520), f_q), result, f_q) - result := addmod(mulmod(mload(0x2c80), mload(0x540), f_q), result, f_q) - result := addmod(mulmod(mload(0x2ca0), mload(0x560), f_q), result, f_q) - result := addmod(mulmod(mload(0x2cc0), mload(0x580), f_q), result, f_q) - result := addmod(mulmod(mload(0x2ce0), mload(0x5a0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2d00), mload(0x5c0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2d20), mload(0x5e0), f_q), result, f_q) - result := addmod(mulmod(mload(0x2d40), mload(0x600), f_q), result, f_q) - result := addmod(mulmod(mload(0x2d60), mload(0x620), f_q), result, f_q) - result := addmod(mulmod(mload(0x2d80), mload(0x640), f_q), result, f_q) - mstore(11680, result) - } - mstore(0x2dc0, mulmod(mload(0xb00), mload(0xae0), f_q)) - mstore(0x2de0, addmod(mload(0xac0), mload(0x2dc0), f_q)) - mstore(0x2e00, addmod(mload(0x2de0), sub(f_q, mload(0xb20)), f_q)) - mstore(0x2e20, mulmod(mload(0x2e00), mload(0xb80), f_q)) - mstore(0x2e40, mulmod(mload(0x920), mload(0x2e20), f_q)) - mstore(0x2e60, addmod(1, sub(f_q, mload(0xc40)), f_q)) - mstore(0x2e80, mulmod(mload(0x2e60), mload(0x27e0), f_q)) - mstore(0x2ea0, addmod(mload(0x2e40), mload(0x2e80), f_q)) - mstore(0x2ec0, mulmod(mload(0x920), mload(0x2ea0), f_q)) - mstore(0x2ee0, mulmod(mload(0xc40), mload(0xc40), f_q)) - mstore(0x2f00, addmod(mload(0x2ee0), sub(f_q, mload(0xc40)), f_q)) - mstore(0x2f20, mulmod(mload(0x2f00), mload(0x2700), f_q)) - mstore(0x2f40, addmod(mload(0x2ec0), mload(0x2f20), f_q)) - mstore(0x2f60, mulmod(mload(0x920), mload(0x2f40), f_q)) - mstore(0x2f80, addmod(1, sub(f_q, mload(0x2700)), f_q)) - mstore(0x2fa0, addmod(mload(0x2720), mload(0x2740), f_q)) - mstore(0x2fc0, addmod(mload(0x2fa0), mload(0x2760), f_q)) - mstore(0x2fe0, addmod(mload(0x2fc0), mload(0x2780), f_q)) - mstore(0x3000, addmod(mload(0x2fe0), mload(0x27a0), f_q)) - mstore(0x3020, addmod(mload(0x3000), mload(0x27c0), f_q)) - mstore(0x3040, addmod(mload(0x2f80), sub(f_q, mload(0x3020)), f_q)) - mstore(0x3060, mulmod(mload(0xbe0), mload(0x7a0), f_q)) - mstore(0x3080, addmod(mload(0xb40), mload(0x3060), f_q)) - mstore(0x30a0, addmod(mload(0x3080), mload(0x800), f_q)) - mstore(0x30c0, mulmod(mload(0xc00), mload(0x7a0), f_q)) - mstore(0x30e0, addmod(mload(0xac0), mload(0x30c0), f_q)) - mstore(0x3100, addmod(mload(0x30e0), mload(0x800), f_q)) - mstore(0x3120, mulmod(mload(0x3100), mload(0x30a0), f_q)) - mstore(0x3140, mulmod(mload(0xc20), mload(0x7a0), f_q)) - mstore(0x3160, addmod(mload(0x2da0), mload(0x3140), f_q)) - mstore(0x3180, addmod(mload(0x3160), mload(0x800), f_q)) - mstore(0x31a0, mulmod(mload(0x3180), mload(0x3120), f_q)) - mstore(0x31c0, mulmod(mload(0x31a0), mload(0xc60), f_q)) - mstore(0x31e0, mulmod(1, mload(0x7a0), f_q)) - mstore(0x3200, mulmod(mload(0xa80), mload(0x31e0), f_q)) - mstore(0x3220, addmod(mload(0xb40), mload(0x3200), f_q)) - mstore(0x3240, addmod(mload(0x3220), mload(0x800), f_q)) - mstore( - 0x3260, - mulmod(4131629893567559867359510883348571134090853742863529169391034518566172092834, mload(0x7a0), f_q) - ) - mstore(0x3280, mulmod(mload(0xa80), mload(0x3260), f_q)) - mstore(0x32a0, addmod(mload(0xac0), mload(0x3280), f_q)) - mstore(0x32c0, addmod(mload(0x32a0), mload(0x800), f_q)) - mstore(0x32e0, mulmod(mload(0x32c0), mload(0x3240), f_q)) - mstore( - 0x3300, - mulmod(8910878055287538404433155982483128285667088683464058436815641868457422632747, mload(0x7a0), f_q) - ) - mstore(0x3320, mulmod(mload(0xa80), mload(0x3300), f_q)) - mstore(0x3340, addmod(mload(0x2da0), mload(0x3320), f_q)) - mstore(0x3360, addmod(mload(0x3340), mload(0x800), f_q)) - mstore(0x3380, mulmod(mload(0x3360), mload(0x32e0), f_q)) - mstore(0x33a0, mulmod(mload(0x3380), mload(0xc40), f_q)) - mstore(0x33c0, addmod(mload(0x31c0), sub(f_q, mload(0x33a0)), f_q)) - mstore(0x33e0, mulmod(mload(0x33c0), mload(0x3040), f_q)) - mstore(0x3400, addmod(mload(0x2f60), mload(0x33e0), f_q)) - mstore(0x3420, mulmod(mload(0x920), mload(0x3400), f_q)) - mstore(0x3440, addmod(1, sub(f_q, mload(0xc80)), f_q)) - mstore(0x3460, mulmod(mload(0x3440), mload(0x27e0), f_q)) - mstore(0x3480, addmod(mload(0x3420), mload(0x3460), f_q)) - mstore(0x34a0, mulmod(mload(0x920), mload(0x3480), f_q)) - mstore(0x34c0, mulmod(mload(0xc80), mload(0xc80), f_q)) - mstore(0x34e0, addmod(mload(0x34c0), sub(f_q, mload(0xc80)), f_q)) - mstore(0x3500, mulmod(mload(0x34e0), mload(0x2700), f_q)) - mstore(0x3520, addmod(mload(0x34a0), mload(0x3500), f_q)) - mstore(0x3540, mulmod(mload(0x920), mload(0x3520), f_q)) - mstore(0x3560, addmod(mload(0xcc0), mload(0x7a0), f_q)) - mstore(0x3580, mulmod(mload(0x3560), mload(0xca0), f_q)) - mstore(0x35a0, addmod(mload(0xd00), mload(0x800), f_q)) - mstore(0x35c0, mulmod(mload(0x35a0), mload(0x3580), f_q)) - mstore(0x35e0, mulmod(mload(0xac0), mload(0xba0), f_q)) - mstore(0x3600, addmod(mload(0x35e0), mload(0x7a0), f_q)) - mstore(0x3620, mulmod(mload(0x3600), mload(0xc80), f_q)) - mstore(0x3640, addmod(mload(0xb60), mload(0x800), f_q)) - mstore(0x3660, mulmod(mload(0x3640), mload(0x3620), f_q)) - mstore(0x3680, addmod(mload(0x35c0), sub(f_q, mload(0x3660)), f_q)) - mstore(0x36a0, mulmod(mload(0x3680), mload(0x3040), f_q)) - mstore(0x36c0, addmod(mload(0x3540), mload(0x36a0), f_q)) - mstore(0x36e0, mulmod(mload(0x920), mload(0x36c0), f_q)) - mstore(0x3700, addmod(mload(0xcc0), sub(f_q, mload(0xd00)), f_q)) - mstore(0x3720, mulmod(mload(0x3700), mload(0x27e0), f_q)) - mstore(0x3740, addmod(mload(0x36e0), mload(0x3720), f_q)) - mstore(0x3760, mulmod(mload(0x920), mload(0x3740), f_q)) - mstore(0x3780, mulmod(mload(0x3700), mload(0x3040), f_q)) - mstore(0x37a0, addmod(mload(0xcc0), sub(f_q, mload(0xce0)), f_q)) - mstore(0x37c0, mulmod(mload(0x37a0), mload(0x3780), f_q)) - mstore(0x37e0, addmod(mload(0x3760), mload(0x37c0), f_q)) - mstore(0x3800, mulmod(mload(0x11e0), mload(0x11e0), f_q)) - mstore(0x3820, mulmod(mload(0x3800), mload(0x11e0), f_q)) - mstore(0x3840, mulmod(mload(0x3820), mload(0x11e0), f_q)) - mstore(0x3860, mulmod(1, mload(0x11e0), f_q)) - mstore(0x3880, mulmod(1, mload(0x3800), f_q)) - mstore(0x38a0, mulmod(1, mload(0x3820), f_q)) - mstore(0x38c0, mulmod(mload(0x37e0), mload(0x1200), f_q)) - mstore(0x38e0, mulmod(mload(0xf40), mload(0xa80), f_q)) - mstore(0x3900, mulmod(mload(0x38e0), mload(0xa80), f_q)) - mstore( - 0x3920, - mulmod(mload(0xa80), 8734126352828345679573237859165904705806588461301144420590422589042130041188, f_q) - ) - mstore(0x3940, addmod(mload(0xe40), sub(f_q, mload(0x3920)), f_q)) - mstore(0x3960, mulmod(mload(0xa80), 1, f_q)) - mstore(0x3980, addmod(mload(0xe40), sub(f_q, mload(0x3960)), f_q)) - mstore( - 0x39a0, - mulmod(mload(0xa80), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q) - ) - mstore(0x39c0, addmod(mload(0xe40), sub(f_q, mload(0x39a0)), f_q)) - mstore( - 0x39e0, - mulmod(mload(0xa80), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q) - ) - mstore(0x3a00, addmod(mload(0xe40), sub(f_q, mload(0x39e0)), f_q)) - mstore( - 0x3a20, - mulmod(mload(0xa80), 12619617507853212586156872920672483948819476989779550311307282715684870266992, f_q) - ) - mstore(0x3a40, addmod(mload(0xe40), sub(f_q, mload(0x3a20)), f_q)) - mstore( - 0x3a60, - mulmod(3544324119167359571073009690693121464267965232733679586767649244433889388945, mload(0x38e0), f_q) - ) - mstore(0x3a80, mulmod(mload(0x3a60), 1, f_q)) - { - let result := mulmod(mload(0xe40), mload(0x3a60), f_q) - result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3a80)), f_q), result, f_q) - mstore(15008, result) - } - mstore( - 0x3ac0, - mulmod(3860370625838117017501327045244227871206764201116468958063324100051382735289, mload(0x38e0), f_q) - ) - mstore( - 0x3ae0, - mulmod( - mload(0x3ac0), - 11211301017135681023579411905410872569206244553457844956874280139879520583390, - f_q - ) - ) - { - let result := mulmod(mload(0xe40), mload(0x3ac0), f_q) - result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3ae0)), f_q), result, f_q) - mstore(15104, result) - } - mstore( - 0x3b20, - mulmod( - 21616901807277407275624036604424346159916096890712898844034238973395610537327, - mload(0x38e0), - f_q - ) - ) - mstore( - 0x3b40, - mulmod(mload(0x3b20), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q) - ) - { - let result := mulmod(mload(0xe40), mload(0x3b20), f_q) - result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3b40)), f_q), result, f_q) - mstore(15200, result) - } - mstore( - 0x3b80, - mulmod(3209408481237076479025468386201293941554240476766691830436732310949352383503, mload(0x38e0), f_q) - ) - mstore( - 0x3ba0, - mulmod( - mload(0x3b80), - 12619617507853212586156872920672483948819476989779550311307282715684870266992, - f_q - ) - ) - { - let result := mulmod(mload(0xe40), mload(0x3b80), f_q) - result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3ba0)), f_q), result, f_q) - mstore(15296, result) - } - mstore(0x3be0, mulmod(1, mload(0x3980), f_q)) - mstore(0x3c00, mulmod(mload(0x3be0), mload(0x39c0), f_q)) - mstore(0x3c20, mulmod(mload(0x3c00), mload(0x3a00), f_q)) - mstore(0x3c40, mulmod(mload(0x3c20), mload(0x3a40), f_q)) - mstore( - 0x3c60, - mulmod(10676941854703594198666993839846402519342119846958189386823924046696287912228, mload(0xa80), f_q) - ) - mstore(0x3c80, mulmod(mload(0x3c60), 1, f_q)) - { - let result := mulmod(mload(0xe40), mload(0x3c60), f_q) - result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3c80)), f_q), result, f_q) - mstore(15520, result) - } - mstore( - 0x3cc0, - mulmod(11211301017135681023579411905410872569206244553457844956874280139879520583389, mload(0xa80), f_q) - ) - mstore( - 0x3ce0, - mulmod( - mload(0x3cc0), - 11211301017135681023579411905410872569206244553457844956874280139879520583390, - f_q - ) - ) - { - let result := mulmod(mload(0xe40), mload(0x3cc0), f_q) - result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3ce0)), f_q), result, f_q) - mstore(15616, result) - } - mstore( - 0x3d20, - mulmod(13154116519010929542673167886091370382741775939114889923107781597533678454430, mload(0xa80), f_q) - ) - mstore(0x3d40, mulmod(mload(0x3d20), 1, f_q)) - { - let result := mulmod(mload(0xe40), mload(0x3d20), f_q) - result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3d40)), f_q), result, f_q) - mstore(15712, result) - } - mstore( - 0x3d80, - mulmod(8734126352828345679573237859165904705806588461301144420590422589042130041187, mload(0xa80), f_q) - ) - mstore( - 0x3da0, - mulmod(mload(0x3d80), 8734126352828345679573237859165904705806588461301144420590422589042130041188, f_q) - ) - { - let result := mulmod(mload(0xe40), mload(0x3d80), f_q) - result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3da0)), f_q), result, f_q) - mstore(15808, result) - } - mstore(0x3de0, mulmod(mload(0x3be0), mload(0x3940), f_q)) - { - let result := mulmod(mload(0xe40), 1, f_q) - result := addmod( - mulmod( - mload(0xa80), - 21888242871839275222246405745257275088548364400416034343698204186575808495616, - f_q - ), - result, - f_q - ) - mstore(15872, result) - } - { - let prod := mload(0x3aa0) + + } +mstore(0x2700, mulmod(mload(0x1240), mload(0x1260), f_q)) +mstore(0x2720, mulmod(mload(0x1280), mload(0x12a0), f_q)) +mstore(0x2740, mulmod(mload(0x12c0), mload(0x12e0), f_q)) +mstore(0x2760, mulmod(mload(0x1300), mload(0x1320), f_q)) +mstore(0x2780, mulmod(mload(0x1340), mload(0x1360), f_q)) +mstore(0x27a0, mulmod(mload(0x1380), mload(0x13a0), f_q)) +mstore(0x27c0, mulmod(mload(0x13c0), mload(0x13e0), f_q)) +mstore(0x27e0, mulmod(mload(0x1400), mload(0x1420), f_q)) +mstore(0x2800, mulmod(mload(0x1440), mload(0x1460), f_q)) +mstore(0x2820, mulmod(mload(0x1480), mload(0x14a0), f_q)) +mstore(0x2840, mulmod(mload(0x14c0), mload(0x14e0), f_q)) +mstore(0x2860, mulmod(mload(0x1500), mload(0x1520), f_q)) +mstore(0x2880, mulmod(mload(0x1540), mload(0x1560), f_q)) +mstore(0x28a0, mulmod(mload(0x1580), mload(0x15a0), f_q)) +mstore(0x28c0, mulmod(mload(0x15c0), mload(0x15e0), f_q)) +mstore(0x28e0, mulmod(mload(0x1600), mload(0x1620), f_q)) +mstore(0x2900, mulmod(mload(0x1640), mload(0x1660), f_q)) +mstore(0x2920, mulmod(mload(0x1680), mload(0x16a0), f_q)) +mstore(0x2940, mulmod(mload(0x16c0), mload(0x16e0), f_q)) +mstore(0x2960, mulmod(mload(0x1700), mload(0x1720), f_q)) +mstore(0x2980, mulmod(mload(0x1740), mload(0x1760), f_q)) +mstore(0x29a0, mulmod(mload(0x1780), mload(0x17a0), f_q)) +mstore(0x29c0, mulmod(mload(0x17c0), mload(0x17e0), f_q)) +mstore(0x29e0, mulmod(mload(0x1800), mload(0x1820), f_q)) +mstore(0x2a00, mulmod(mload(0x1840), mload(0x1860), f_q)) +mstore(0x2a20, mulmod(mload(0x1880), mload(0x18a0), f_q)) +mstore(0x2a40, mulmod(mload(0x18c0), mload(0x18e0), f_q)) +mstore(0x2a60, mulmod(mload(0x1900), mload(0x1920), f_q)) +mstore(0x2a80, mulmod(mload(0x1940), mload(0x1960), f_q)) +mstore(0x2aa0, mulmod(mload(0x1980), mload(0x19a0), f_q)) +mstore(0x2ac0, mulmod(mload(0x19c0), mload(0x19e0), f_q)) +mstore(0x2ae0, mulmod(mload(0x1a00), mload(0x1a20), f_q)) +mstore(0x2b00, mulmod(mload(0x1a40), mload(0x1a60), f_q)) +mstore(0x2b20, mulmod(mload(0x1a80), mload(0x1aa0), f_q)) +mstore(0x2b40, mulmod(mload(0x1ac0), mload(0x1ae0), f_q)) +mstore(0x2b60, mulmod(mload(0x1b00), mload(0x1b20), f_q)) +mstore(0x2b80, mulmod(mload(0x1b40), mload(0x1b60), f_q)) +mstore(0x2ba0, mulmod(mload(0x1b80), mload(0x1ba0), f_q)) +mstore(0x2bc0, mulmod(mload(0x1bc0), mload(0x1be0), f_q)) +mstore(0x2be0, mulmod(mload(0x1c00), mload(0x1c20), f_q)) +mstore(0x2c00, mulmod(mload(0x1c40), mload(0x1c60), f_q)) +mstore(0x2c20, mulmod(mload(0x1c80), mload(0x1ca0), f_q)) +mstore(0x2c40, mulmod(mload(0x1cc0), mload(0x1ce0), f_q)) +mstore(0x2c60, mulmod(mload(0x1d00), mload(0x1d20), f_q)) +mstore(0x2c80, mulmod(mload(0x1d40), mload(0x1d60), f_q)) +mstore(0x2ca0, mulmod(mload(0x1d80), mload(0x1da0), f_q)) +mstore(0x2cc0, mulmod(mload(0x1dc0), mload(0x1de0), f_q)) +mstore(0x2ce0, mulmod(mload(0x1e00), mload(0x1e20), f_q)) +mstore(0x2d00, mulmod(mload(0x1e40), mload(0x1e60), f_q)) +mstore(0x2d20, mulmod(mload(0x1e80), mload(0x1ea0), f_q)) +mstore(0x2d40, mulmod(mload(0x1ec0), mload(0x1ee0), f_q)) +mstore(0x2d60, mulmod(mload(0x1f00), mload(0x1f20), f_q)) +mstore(0x2d80, mulmod(mload(0x1f40), mload(0x1f60), f_q)) +{ + let result := mulmod(mload(0x27e0), mload(0xa0), f_q) +result := addmod(mulmod(mload(0x2800), mload(0xc0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2820), mload(0xe0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2840), mload(0x100), f_q), result, f_q) +result := addmod(mulmod(mload(0x2860), mload(0x120), f_q), result, f_q) +result := addmod(mulmod(mload(0x2880), mload(0x140), f_q), result, f_q) +result := addmod(mulmod(mload(0x28a0), mload(0x160), f_q), result, f_q) +result := addmod(mulmod(mload(0x28c0), mload(0x180), f_q), result, f_q) +result := addmod(mulmod(mload(0x28e0), mload(0x1a0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2900), mload(0x1c0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2920), mload(0x1e0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2940), mload(0x200), f_q), result, f_q) +result := addmod(mulmod(mload(0x2960), mload(0x220), f_q), result, f_q) +result := addmod(mulmod(mload(0x2980), mload(0x240), f_q), result, f_q) +result := addmod(mulmod(mload(0x29a0), mload(0x260), f_q), result, f_q) +result := addmod(mulmod(mload(0x29c0), mload(0x280), f_q), result, f_q) +result := addmod(mulmod(mload(0x29e0), mload(0x2a0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2a00), mload(0x2c0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2a20), mload(0x2e0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2a40), mload(0x300), f_q), result, f_q) +result := addmod(mulmod(mload(0x2a60), mload(0x320), f_q), result, f_q) +result := addmod(mulmod(mload(0x2a80), mload(0x340), f_q), result, f_q) +result := addmod(mulmod(mload(0x2aa0), mload(0x360), f_q), result, f_q) +result := addmod(mulmod(mload(0x2ac0), mload(0x380), f_q), result, f_q) +result := addmod(mulmod(mload(0x2ae0), mload(0x3a0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2b00), mload(0x3c0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2b20), mload(0x3e0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2b40), mload(0x400), f_q), result, f_q) +result := addmod(mulmod(mload(0x2b60), mload(0x420), f_q), result, f_q) +result := addmod(mulmod(mload(0x2b80), mload(0x440), f_q), result, f_q) +result := addmod(mulmod(mload(0x2ba0), mload(0x460), f_q), result, f_q) +result := addmod(mulmod(mload(0x2bc0), mload(0x480), f_q), result, f_q) +result := addmod(mulmod(mload(0x2be0), mload(0x4a0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2c00), mload(0x4c0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2c20), mload(0x4e0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2c40), mload(0x500), f_q), result, f_q) +result := addmod(mulmod(mload(0x2c60), mload(0x520), f_q), result, f_q) +result := addmod(mulmod(mload(0x2c80), mload(0x540), f_q), result, f_q) +result := addmod(mulmod(mload(0x2ca0), mload(0x560), f_q), result, f_q) +result := addmod(mulmod(mload(0x2cc0), mload(0x580), f_q), result, f_q) +result := addmod(mulmod(mload(0x2ce0), mload(0x5a0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2d00), mload(0x5c0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2d20), mload(0x5e0), f_q), result, f_q) +result := addmod(mulmod(mload(0x2d40), mload(0x600), f_q), result, f_q) +result := addmod(mulmod(mload(0x2d60), mload(0x620), f_q), result, f_q) +result := addmod(mulmod(mload(0x2d80), mload(0x640), f_q), result, f_q) +mstore(11680, result) + } +mstore(0x2dc0, mulmod(mload(0xb00), mload(0xae0), f_q)) +mstore(0x2de0, addmod(mload(0xac0), mload(0x2dc0), f_q)) +mstore(0x2e00, addmod(mload(0x2de0), sub(f_q, mload(0xb20)), f_q)) +mstore(0x2e20, mulmod(mload(0x2e00), mload(0xb80), f_q)) +mstore(0x2e40, mulmod(mload(0x920), mload(0x2e20), f_q)) +mstore(0x2e60, addmod(1, sub(f_q, mload(0xc40)), f_q)) +mstore(0x2e80, mulmod(mload(0x2e60), mload(0x27e0), f_q)) +mstore(0x2ea0, addmod(mload(0x2e40), mload(0x2e80), f_q)) +mstore(0x2ec0, mulmod(mload(0x920), mload(0x2ea0), f_q)) +mstore(0x2ee0, mulmod(mload(0xc40), mload(0xc40), f_q)) +mstore(0x2f00, addmod(mload(0x2ee0), sub(f_q, mload(0xc40)), f_q)) +mstore(0x2f20, mulmod(mload(0x2f00), mload(0x2700), f_q)) +mstore(0x2f40, addmod(mload(0x2ec0), mload(0x2f20), f_q)) +mstore(0x2f60, mulmod(mload(0x920), mload(0x2f40), f_q)) +mstore(0x2f80, addmod(1, sub(f_q, mload(0x2700)), f_q)) +mstore(0x2fa0, addmod(mload(0x2720), mload(0x2740), f_q)) +mstore(0x2fc0, addmod(mload(0x2fa0), mload(0x2760), f_q)) +mstore(0x2fe0, addmod(mload(0x2fc0), mload(0x2780), f_q)) +mstore(0x3000, addmod(mload(0x2fe0), mload(0x27a0), f_q)) +mstore(0x3020, addmod(mload(0x3000), mload(0x27c0), f_q)) +mstore(0x3040, addmod(mload(0x2f80), sub(f_q, mload(0x3020)), f_q)) +mstore(0x3060, mulmod(mload(0xbe0), mload(0x7a0), f_q)) +mstore(0x3080, addmod(mload(0xb40), mload(0x3060), f_q)) +mstore(0x30a0, addmod(mload(0x3080), mload(0x800), f_q)) +mstore(0x30c0, mulmod(mload(0xc00), mload(0x7a0), f_q)) +mstore(0x30e0, addmod(mload(0xac0), mload(0x30c0), f_q)) +mstore(0x3100, addmod(mload(0x30e0), mload(0x800), f_q)) +mstore(0x3120, mulmod(mload(0x3100), mload(0x30a0), f_q)) +mstore(0x3140, mulmod(mload(0xc20), mload(0x7a0), f_q)) +mstore(0x3160, addmod(mload(0x2da0), mload(0x3140), f_q)) +mstore(0x3180, addmod(mload(0x3160), mload(0x800), f_q)) +mstore(0x31a0, mulmod(mload(0x3180), mload(0x3120), f_q)) +mstore(0x31c0, mulmod(mload(0x31a0), mload(0xc60), f_q)) +mstore(0x31e0, mulmod(1, mload(0x7a0), f_q)) +mstore(0x3200, mulmod(mload(0xa80), mload(0x31e0), f_q)) +mstore(0x3220, addmod(mload(0xb40), mload(0x3200), f_q)) +mstore(0x3240, addmod(mload(0x3220), mload(0x800), f_q)) +mstore(0x3260, mulmod(4131629893567559867359510883348571134090853742863529169391034518566172092834, mload(0x7a0), f_q)) +mstore(0x3280, mulmod(mload(0xa80), mload(0x3260), f_q)) +mstore(0x32a0, addmod(mload(0xac0), mload(0x3280), f_q)) +mstore(0x32c0, addmod(mload(0x32a0), mload(0x800), f_q)) +mstore(0x32e0, mulmod(mload(0x32c0), mload(0x3240), f_q)) +mstore(0x3300, mulmod(8910878055287538404433155982483128285667088683464058436815641868457422632747, mload(0x7a0), f_q)) +mstore(0x3320, mulmod(mload(0xa80), mload(0x3300), f_q)) +mstore(0x3340, addmod(mload(0x2da0), mload(0x3320), f_q)) +mstore(0x3360, addmod(mload(0x3340), mload(0x800), f_q)) +mstore(0x3380, mulmod(mload(0x3360), mload(0x32e0), f_q)) +mstore(0x33a0, mulmod(mload(0x3380), mload(0xc40), f_q)) +mstore(0x33c0, addmod(mload(0x31c0), sub(f_q, mload(0x33a0)), f_q)) +mstore(0x33e0, mulmod(mload(0x33c0), mload(0x3040), f_q)) +mstore(0x3400, addmod(mload(0x2f60), mload(0x33e0), f_q)) +mstore(0x3420, mulmod(mload(0x920), mload(0x3400), f_q)) +mstore(0x3440, addmod(1, sub(f_q, mload(0xc80)), f_q)) +mstore(0x3460, mulmod(mload(0x3440), mload(0x27e0), f_q)) +mstore(0x3480, addmod(mload(0x3420), mload(0x3460), f_q)) +mstore(0x34a0, mulmod(mload(0x920), mload(0x3480), f_q)) +mstore(0x34c0, mulmod(mload(0xc80), mload(0xc80), f_q)) +mstore(0x34e0, addmod(mload(0x34c0), sub(f_q, mload(0xc80)), f_q)) +mstore(0x3500, mulmod(mload(0x34e0), mload(0x2700), f_q)) +mstore(0x3520, addmod(mload(0x34a0), mload(0x3500), f_q)) +mstore(0x3540, mulmod(mload(0x920), mload(0x3520), f_q)) +mstore(0x3560, addmod(mload(0xcc0), mload(0x7a0), f_q)) +mstore(0x3580, mulmod(mload(0x3560), mload(0xca0), f_q)) +mstore(0x35a0, addmod(mload(0xd00), mload(0x800), f_q)) +mstore(0x35c0, mulmod(mload(0x35a0), mload(0x3580), f_q)) +mstore(0x35e0, mulmod(mload(0xac0), mload(0xba0), f_q)) +mstore(0x3600, addmod(mload(0x35e0), mload(0x7a0), f_q)) +mstore(0x3620, mulmod(mload(0x3600), mload(0xc80), f_q)) +mstore(0x3640, addmod(mload(0xb60), mload(0x800), f_q)) +mstore(0x3660, mulmod(mload(0x3640), mload(0x3620), f_q)) +mstore(0x3680, addmod(mload(0x35c0), sub(f_q, mload(0x3660)), f_q)) +mstore(0x36a0, mulmod(mload(0x3680), mload(0x3040), f_q)) +mstore(0x36c0, addmod(mload(0x3540), mload(0x36a0), f_q)) +mstore(0x36e0, mulmod(mload(0x920), mload(0x36c0), f_q)) +mstore(0x3700, addmod(mload(0xcc0), sub(f_q, mload(0xd00)), f_q)) +mstore(0x3720, mulmod(mload(0x3700), mload(0x27e0), f_q)) +mstore(0x3740, addmod(mload(0x36e0), mload(0x3720), f_q)) +mstore(0x3760, mulmod(mload(0x920), mload(0x3740), f_q)) +mstore(0x3780, mulmod(mload(0x3700), mload(0x3040), f_q)) +mstore(0x37a0, addmod(mload(0xcc0), sub(f_q, mload(0xce0)), f_q)) +mstore(0x37c0, mulmod(mload(0x37a0), mload(0x3780), f_q)) +mstore(0x37e0, addmod(mload(0x3760), mload(0x37c0), f_q)) +mstore(0x3800, mulmod(mload(0x11e0), mload(0x11e0), f_q)) +mstore(0x3820, mulmod(mload(0x3800), mload(0x11e0), f_q)) +mstore(0x3840, mulmod(mload(0x3820), mload(0x11e0), f_q)) +mstore(0x3860, mulmod(1, mload(0x11e0), f_q)) +mstore(0x3880, mulmod(1, mload(0x3800), f_q)) +mstore(0x38a0, mulmod(1, mload(0x3820), f_q)) +mstore(0x38c0, mulmod(mload(0x37e0), mload(0x1200), f_q)) +mstore(0x38e0, mulmod(mload(0xf40), mload(0xa80), f_q)) +mstore(0x3900, mulmod(mload(0x38e0), mload(0xa80), f_q)) +mstore(0x3920, mulmod(mload(0xa80), 8734126352828345679573237859165904705806588461301144420590422589042130041188, f_q)) +mstore(0x3940, addmod(mload(0xe40), sub(f_q, mload(0x3920)), f_q)) +mstore(0x3960, mulmod(mload(0xa80), 1, f_q)) +mstore(0x3980, addmod(mload(0xe40), sub(f_q, mload(0x3960)), f_q)) +mstore(0x39a0, mulmod(mload(0xa80), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q)) +mstore(0x39c0, addmod(mload(0xe40), sub(f_q, mload(0x39a0)), f_q)) +mstore(0x39e0, mulmod(mload(0xa80), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q)) +mstore(0x3a00, addmod(mload(0xe40), sub(f_q, mload(0x39e0)), f_q)) +mstore(0x3a20, mulmod(mload(0xa80), 12619617507853212586156872920672483948819476989779550311307282715684870266992, f_q)) +mstore(0x3a40, addmod(mload(0xe40), sub(f_q, mload(0x3a20)), f_q)) +mstore(0x3a60, mulmod(3544324119167359571073009690693121464267965232733679586767649244433889388945, mload(0x38e0), f_q)) +mstore(0x3a80, mulmod(mload(0x3a60), 1, f_q)) +{ + let result := mulmod(mload(0xe40), mload(0x3a60), f_q) +result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3a80)), f_q), result, f_q) +mstore(15008, result) + } +mstore(0x3ac0, mulmod(3860370625838117017501327045244227871206764201116468958063324100051382735289, mload(0x38e0), f_q)) +mstore(0x3ae0, mulmod(mload(0x3ac0), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q)) +{ + let result := mulmod(mload(0xe40), mload(0x3ac0), f_q) +result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3ae0)), f_q), result, f_q) +mstore(15104, result) + } +mstore(0x3b20, mulmod(21616901807277407275624036604424346159916096890712898844034238973395610537327, mload(0x38e0), f_q)) +mstore(0x3b40, mulmod(mload(0x3b20), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q)) +{ + let result := mulmod(mload(0xe40), mload(0x3b20), f_q) +result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3b40)), f_q), result, f_q) +mstore(15200, result) + } +mstore(0x3b80, mulmod(3209408481237076479025468386201293941554240476766691830436732310949352383503, mload(0x38e0), f_q)) +mstore(0x3ba0, mulmod(mload(0x3b80), 12619617507853212586156872920672483948819476989779550311307282715684870266992, f_q)) +{ + let result := mulmod(mload(0xe40), mload(0x3b80), f_q) +result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3ba0)), f_q), result, f_q) +mstore(15296, result) + } +mstore(0x3be0, mulmod(1, mload(0x3980), f_q)) +mstore(0x3c00, mulmod(mload(0x3be0), mload(0x39c0), f_q)) +mstore(0x3c20, mulmod(mload(0x3c00), mload(0x3a00), f_q)) +mstore(0x3c40, mulmod(mload(0x3c20), mload(0x3a40), f_q)) +mstore(0x3c60, mulmod(10676941854703594198666993839846402519342119846958189386823924046696287912228, mload(0xa80), f_q)) +mstore(0x3c80, mulmod(mload(0x3c60), 1, f_q)) +{ + let result := mulmod(mload(0xe40), mload(0x3c60), f_q) +result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3c80)), f_q), result, f_q) +mstore(15520, result) + } +mstore(0x3cc0, mulmod(11211301017135681023579411905410872569206244553457844956874280139879520583389, mload(0xa80), f_q)) +mstore(0x3ce0, mulmod(mload(0x3cc0), 11211301017135681023579411905410872569206244553457844956874280139879520583390, f_q)) +{ + let result := mulmod(mload(0xe40), mload(0x3cc0), f_q) +result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3ce0)), f_q), result, f_q) +mstore(15616, result) + } +mstore(0x3d20, mulmod(13154116519010929542673167886091370382741775939114889923107781597533678454430, mload(0xa80), f_q)) +mstore(0x3d40, mulmod(mload(0x3d20), 1, f_q)) +{ + let result := mulmod(mload(0xe40), mload(0x3d20), f_q) +result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3d40)), f_q), result, f_q) +mstore(15712, result) + } +mstore(0x3d80, mulmod(8734126352828345679573237859165904705806588461301144420590422589042130041187, mload(0xa80), f_q)) +mstore(0x3da0, mulmod(mload(0x3d80), 8734126352828345679573237859165904705806588461301144420590422589042130041188, f_q)) +{ + let result := mulmod(mload(0xe40), mload(0x3d80), f_q) +result := addmod(mulmod(mload(0xa80), sub(f_q, mload(0x3da0)), f_q), result, f_q) +mstore(15808, result) + } +mstore(0x3de0, mulmod(mload(0x3be0), mload(0x3940), f_q)) +{ + let result := mulmod(mload(0xe40), 1, f_q) +result := addmod(mulmod(mload(0xa80), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q), result, f_q) +mstore(15872, result) + } +{ + let prod := mload(0x3aa0) prod := mulmod(mload(0x3b00), prod, f_q) mstore(0x3e20, prod) - + prod := mulmod(mload(0x3b60), prod, f_q) mstore(0x3e40, prod) - + prod := mulmod(mload(0x3bc0), prod, f_q) mstore(0x3e60, prod) - + prod := mulmod(mload(0x3ca0), prod, f_q) mstore(0x3e80, prod) - + prod := mulmod(mload(0x3d00), prod, f_q) mstore(0x3ea0, prod) - + prod := mulmod(mload(0x3c00), prod, f_q) mstore(0x3ec0, prod) - + prod := mulmod(mload(0x3d60), prod, f_q) mstore(0x3ee0, prod) - + prod := mulmod(mload(0x3dc0), prod, f_q) mstore(0x3f00, prod) - + prod := mulmod(mload(0x3de0), prod, f_q) mstore(0x3f20, prod) - + prod := mulmod(mload(0x3e00), prod, f_q) mstore(0x3f40, prod) - + prod := mulmod(mload(0x3be0), prod, f_q) mstore(0x3f60, prod) - } - mstore(0x3fa0, 32) - mstore(0x3fc0, 32) - mstore(0x3fe0, 32) - mstore(0x4000, mload(0x3f60)) - mstore(0x4020, 21888242871839275222246405745257275088548364400416034343698204186575808495615) - mstore(0x4040, 21888242871839275222246405745257275088548364400416034343698204186575808495617) - success := and(eq(staticcall(gas(), 0x5, 0x3fa0, 0xc0, 0x3f80, 0x20), 1), success) - { - let inv := mload(0x3f80) - let v - - v := mload(0x3be0) - mstore(15328, mulmod(mload(0x3f40), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3e00) - mstore(15872, mulmod(mload(0x3f20), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3de0) - mstore(15840, mulmod(mload(0x3f00), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3dc0) - mstore(15808, mulmod(mload(0x3ee0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3d60) - mstore(15712, mulmod(mload(0x3ec0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3c00) - mstore(15360, mulmod(mload(0x3ea0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3d00) - mstore(15616, mulmod(mload(0x3e80), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3ca0) - mstore(15520, mulmod(mload(0x3e60), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3bc0) - mstore(15296, mulmod(mload(0x3e40), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3b60) - mstore(15200, mulmod(mload(0x3e20), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3b00) - mstore(15104, mulmod(mload(0x3aa0), inv, f_q)) - inv := mulmod(v, inv, f_q) + + } +mstore(0x3fa0, 32) +mstore(0x3fc0, 32) +mstore(0x3fe0, 32) +mstore(0x4000, mload(0x3f60)) +mstore(0x4020, 21888242871839275222246405745257275088548364400416034343698204186575808495615) +mstore(0x4040, 21888242871839275222246405745257275088548364400416034343698204186575808495617) +success := and(eq(staticcall(gas(), 0x5, 0x3fa0, 0xc0, 0x3f80, 0x20), 1), success) +{ + + let inv := mload(0x3f80) + let v + + v := mload(0x3be0) + mstore(15328, mulmod(mload(0x3f40), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3e00) + mstore(15872, mulmod(mload(0x3f20), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3de0) + mstore(15840, mulmod(mload(0x3f00), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3dc0) + mstore(15808, mulmod(mload(0x3ee0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3d60) + mstore(15712, mulmod(mload(0x3ec0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3c00) + mstore(15360, mulmod(mload(0x3ea0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3d00) + mstore(15616, mulmod(mload(0x3e80), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3ca0) + mstore(15520, mulmod(mload(0x3e60), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3bc0) + mstore(15296, mulmod(mload(0x3e40), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3b60) + mstore(15200, mulmod(mload(0x3e20), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3b00) + mstore(15104, mulmod(mload(0x3aa0), inv, f_q)) + inv := mulmod(v, inv, f_q) mstore(0x3aa0, inv) - } - { - let result := mload(0x3aa0) - result := addmod(mload(0x3b00), result, f_q) - result := addmod(mload(0x3b60), result, f_q) - result := addmod(mload(0x3bc0), result, f_q) - mstore(16480, result) - } - mstore(0x4080, mulmod(mload(0x3c40), mload(0x3c00), f_q)) - { - let result := mload(0x3ca0) - result := addmod(mload(0x3d00), result, f_q) - mstore(16544, result) - } - mstore(0x40c0, mulmod(mload(0x3c40), mload(0x3de0), f_q)) - { - let result := mload(0x3d60) - result := addmod(mload(0x3dc0), result, f_q) - mstore(16608, result) - } - mstore(0x4100, mulmod(mload(0x3c40), mload(0x3be0), f_q)) - { - let result := mload(0x3e00) - mstore(16672, result) - } - { - let prod := mload(0x4060) + + } +{ + let result := mload(0x3aa0) +result := addmod(mload(0x3b00), result, f_q) +result := addmod(mload(0x3b60), result, f_q) +result := addmod(mload(0x3bc0), result, f_q) +mstore(16480, result) + } +mstore(0x4080, mulmod(mload(0x3c40), mload(0x3c00), f_q)) +{ + let result := mload(0x3ca0) +result := addmod(mload(0x3d00), result, f_q) +mstore(16544, result) + } +mstore(0x40c0, mulmod(mload(0x3c40), mload(0x3de0), f_q)) +{ + let result := mload(0x3d60) +result := addmod(mload(0x3dc0), result, f_q) +mstore(16608, result) + } +mstore(0x4100, mulmod(mload(0x3c40), mload(0x3be0), f_q)) +{ + let result := mload(0x3e00) +mstore(16672, result) + } +{ + let prod := mload(0x4060) prod := mulmod(mload(0x40a0), prod, f_q) mstore(0x4140, prod) - + prod := mulmod(mload(0x40e0), prod, f_q) mstore(0x4160, prod) - + prod := mulmod(mload(0x4120), prod, f_q) mstore(0x4180, prod) - } - mstore(0x41c0, 32) - mstore(0x41e0, 32) - mstore(0x4200, 32) - mstore(0x4220, mload(0x4180)) - mstore(0x4240, 21888242871839275222246405745257275088548364400416034343698204186575808495615) - mstore(0x4260, 21888242871839275222246405745257275088548364400416034343698204186575808495617) - success := and(eq(staticcall(gas(), 0x5, 0x41c0, 0xc0, 0x41a0, 0x20), 1), success) - { - let inv := mload(0x41a0) - let v - - v := mload(0x4120) - mstore(16672, mulmod(mload(0x4160), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x40e0) - mstore(16608, mulmod(mload(0x4140), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x40a0) - mstore(16544, mulmod(mload(0x4060), inv, f_q)) - inv := mulmod(v, inv, f_q) + + } +mstore(0x41c0, 32) +mstore(0x41e0, 32) +mstore(0x4200, 32) +mstore(0x4220, mload(0x4180)) +mstore(0x4240, 21888242871839275222246405745257275088548364400416034343698204186575808495615) +mstore(0x4260, 21888242871839275222246405745257275088548364400416034343698204186575808495617) +success := and(eq(staticcall(gas(), 0x5, 0x41c0, 0xc0, 0x41a0, 0x20), 1), success) +{ + + let inv := mload(0x41a0) + let v + + v := mload(0x4120) + mstore(16672, mulmod(mload(0x4160), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x40e0) + mstore(16608, mulmod(mload(0x4140), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x40a0) + mstore(16544, mulmod(mload(0x4060), inv, f_q)) + inv := mulmod(v, inv, f_q) mstore(0x4060, inv) - } - mstore(0x4280, mulmod(mload(0x4080), mload(0x40a0), f_q)) - mstore(0x42a0, mulmod(mload(0x40c0), mload(0x40e0), f_q)) - mstore(0x42c0, mulmod(mload(0x4100), mload(0x4120), f_q)) - mstore(0x42e0, mulmod(mload(0xd40), mload(0xd40), f_q)) - mstore(0x4300, mulmod(mload(0x42e0), mload(0xd40), f_q)) - mstore(0x4320, mulmod(mload(0x4300), mload(0xd40), f_q)) - mstore(0x4340, mulmod(mload(0x4320), mload(0xd40), f_q)) - mstore(0x4360, mulmod(mload(0x4340), mload(0xd40), f_q)) - mstore(0x4380, mulmod(mload(0x4360), mload(0xd40), f_q)) - mstore(0x43a0, mulmod(mload(0x4380), mload(0xd40), f_q)) - mstore(0x43c0, mulmod(mload(0x43a0), mload(0xd40), f_q)) - mstore(0x43e0, mulmod(mload(0x43c0), mload(0xd40), f_q)) - mstore(0x4400, mulmod(mload(0xda0), mload(0xda0), f_q)) - mstore(0x4420, mulmod(mload(0x4400), mload(0xda0), f_q)) - mstore(0x4440, mulmod(mload(0x4420), mload(0xda0), f_q)) - { - let result := mulmod(mload(0xac0), mload(0x3aa0), f_q) - result := addmod(mulmod(mload(0xae0), mload(0x3b00), f_q), result, f_q) - result := addmod(mulmod(mload(0xb00), mload(0x3b60), f_q), result, f_q) - result := addmod(mulmod(mload(0xb20), mload(0x3bc0), f_q), result, f_q) - mstore(17504, result) - } - mstore(0x4480, mulmod(mload(0x4460), mload(0x4060), f_q)) - mstore(0x44a0, mulmod(sub(f_q, mload(0x4480)), 1, f_q)) - mstore(0x44c0, mulmod(mload(0x44a0), 1, f_q)) - mstore(0x44e0, mulmod(1, mload(0x4080), f_q)) - { - let result := mulmod(mload(0xc40), mload(0x3ca0), f_q) - result := addmod(mulmod(mload(0xc60), mload(0x3d00), f_q), result, f_q) - mstore(17664, result) - } - mstore(0x4520, mulmod(mload(0x4500), mload(0x4280), f_q)) - mstore(0x4540, mulmod(sub(f_q, mload(0x4520)), 1, f_q)) - mstore(0x4560, mulmod(mload(0x44e0), 1, f_q)) - { - let result := mulmod(mload(0xc80), mload(0x3ca0), f_q) - result := addmod(mulmod(mload(0xca0), mload(0x3d00), f_q), result, f_q) - mstore(17792, result) - } - mstore(0x45a0, mulmod(mload(0x4580), mload(0x4280), f_q)) - mstore(0x45c0, mulmod(sub(f_q, mload(0x45a0)), mload(0xd40), f_q)) - mstore(0x45e0, mulmod(mload(0x44e0), mload(0xd40), f_q)) - mstore(0x4600, addmod(mload(0x4540), mload(0x45c0), f_q)) - mstore(0x4620, mulmod(mload(0x4600), mload(0xda0), f_q)) - mstore(0x4640, mulmod(mload(0x4560), mload(0xda0), f_q)) - mstore(0x4660, mulmod(mload(0x45e0), mload(0xda0), f_q)) - mstore(0x4680, addmod(mload(0x44c0), mload(0x4620), f_q)) - mstore(0x46a0, mulmod(1, mload(0x40c0), f_q)) - { - let result := mulmod(mload(0xcc0), mload(0x3d60), f_q) - result := addmod(mulmod(mload(0xce0), mload(0x3dc0), f_q), result, f_q) - mstore(18112, result) - } - mstore(0x46e0, mulmod(mload(0x46c0), mload(0x42a0), f_q)) - mstore(0x4700, mulmod(sub(f_q, mload(0x46e0)), 1, f_q)) - mstore(0x4720, mulmod(mload(0x46a0), 1, f_q)) - mstore(0x4740, mulmod(mload(0x4700), mload(0x4400), f_q)) - mstore(0x4760, mulmod(mload(0x4720), mload(0x4400), f_q)) - mstore(0x4780, addmod(mload(0x4680), mload(0x4740), f_q)) - mstore(0x47a0, mulmod(1, mload(0x4100), f_q)) - { - let result := mulmod(mload(0xd00), mload(0x3e00), f_q) - mstore(18368, result) - } - mstore(0x47e0, mulmod(mload(0x47c0), mload(0x42c0), f_q)) - mstore(0x4800, mulmod(sub(f_q, mload(0x47e0)), 1, f_q)) - mstore(0x4820, mulmod(mload(0x47a0), 1, f_q)) - { - let result := mulmod(mload(0xb40), mload(0x3e00), f_q) - mstore(18496, result) - } - mstore(0x4860, mulmod(mload(0x4840), mload(0x42c0), f_q)) - mstore(0x4880, mulmod(sub(f_q, mload(0x4860)), mload(0xd40), f_q)) - mstore(0x48a0, mulmod(mload(0x47a0), mload(0xd40), f_q)) - mstore(0x48c0, addmod(mload(0x4800), mload(0x4880), f_q)) - { - let result := mulmod(mload(0xb60), mload(0x3e00), f_q) - mstore(18656, result) - } - mstore(0x4900, mulmod(mload(0x48e0), mload(0x42c0), f_q)) - mstore(0x4920, mulmod(sub(f_q, mload(0x4900)), mload(0x42e0), f_q)) - mstore(0x4940, mulmod(mload(0x47a0), mload(0x42e0), f_q)) - mstore(0x4960, addmod(mload(0x48c0), mload(0x4920), f_q)) - { - let result := mulmod(mload(0xb80), mload(0x3e00), f_q) - mstore(18816, result) - } - mstore(0x49a0, mulmod(mload(0x4980), mload(0x42c0), f_q)) - mstore(0x49c0, mulmod(sub(f_q, mload(0x49a0)), mload(0x4300), f_q)) - mstore(0x49e0, mulmod(mload(0x47a0), mload(0x4300), f_q)) - mstore(0x4a00, addmod(mload(0x4960), mload(0x49c0), f_q)) - { - let result := mulmod(mload(0xba0), mload(0x3e00), f_q) - mstore(18976, result) - } - mstore(0x4a40, mulmod(mload(0x4a20), mload(0x42c0), f_q)) - mstore(0x4a60, mulmod(sub(f_q, mload(0x4a40)), mload(0x4320), f_q)) - mstore(0x4a80, mulmod(mload(0x47a0), mload(0x4320), f_q)) - mstore(0x4aa0, addmod(mload(0x4a00), mload(0x4a60), f_q)) - { - let result := mulmod(mload(0xbe0), mload(0x3e00), f_q) - mstore(19136, result) - } - mstore(0x4ae0, mulmod(mload(0x4ac0), mload(0x42c0), f_q)) - mstore(0x4b00, mulmod(sub(f_q, mload(0x4ae0)), mload(0x4340), f_q)) - mstore(0x4b20, mulmod(mload(0x47a0), mload(0x4340), f_q)) - mstore(0x4b40, addmod(mload(0x4aa0), mload(0x4b00), f_q)) - { - let result := mulmod(mload(0xc00), mload(0x3e00), f_q) - mstore(19296, result) - } - mstore(0x4b80, mulmod(mload(0x4b60), mload(0x42c0), f_q)) - mstore(0x4ba0, mulmod(sub(f_q, mload(0x4b80)), mload(0x4360), f_q)) - mstore(0x4bc0, mulmod(mload(0x47a0), mload(0x4360), f_q)) - mstore(0x4be0, addmod(mload(0x4b40), mload(0x4ba0), f_q)) - { - let result := mulmod(mload(0xc20), mload(0x3e00), f_q) - mstore(19456, result) - } - mstore(0x4c20, mulmod(mload(0x4c00), mload(0x42c0), f_q)) - mstore(0x4c40, mulmod(sub(f_q, mload(0x4c20)), mload(0x4380), f_q)) - mstore(0x4c60, mulmod(mload(0x47a0), mload(0x4380), f_q)) - mstore(0x4c80, addmod(mload(0x4be0), mload(0x4c40), f_q)) - mstore(0x4ca0, mulmod(mload(0x3860), mload(0x4100), f_q)) - mstore(0x4cc0, mulmod(mload(0x3880), mload(0x4100), f_q)) - mstore(0x4ce0, mulmod(mload(0x38a0), mload(0x4100), f_q)) - { - let result := mulmod(mload(0x38c0), mload(0x3e00), f_q) - mstore(19712, result) - } - mstore(0x4d20, mulmod(mload(0x4d00), mload(0x42c0), f_q)) - mstore(0x4d40, mulmod(sub(f_q, mload(0x4d20)), mload(0x43a0), f_q)) - mstore(0x4d60, mulmod(mload(0x47a0), mload(0x43a0), f_q)) - mstore(0x4d80, mulmod(mload(0x4ca0), mload(0x43a0), f_q)) - mstore(0x4da0, mulmod(mload(0x4cc0), mload(0x43a0), f_q)) - mstore(0x4dc0, mulmod(mload(0x4ce0), mload(0x43a0), f_q)) - mstore(0x4de0, addmod(mload(0x4c80), mload(0x4d40), f_q)) - { - let result := mulmod(mload(0xbc0), mload(0x3e00), f_q) - mstore(19968, result) - } - mstore(0x4e20, mulmod(mload(0x4e00), mload(0x42c0), f_q)) - mstore(0x4e40, mulmod(sub(f_q, mload(0x4e20)), mload(0x43c0), f_q)) - mstore(0x4e60, mulmod(mload(0x47a0), mload(0x43c0), f_q)) - mstore(0x4e80, addmod(mload(0x4de0), mload(0x4e40), f_q)) - mstore(0x4ea0, mulmod(mload(0x4e80), mload(0x4420), f_q)) - mstore(0x4ec0, mulmod(mload(0x4820), mload(0x4420), f_q)) - mstore(0x4ee0, mulmod(mload(0x48a0), mload(0x4420), f_q)) - mstore(0x4f00, mulmod(mload(0x4940), mload(0x4420), f_q)) - mstore(0x4f20, mulmod(mload(0x49e0), mload(0x4420), f_q)) - mstore(0x4f40, mulmod(mload(0x4a80), mload(0x4420), f_q)) - mstore(0x4f60, mulmod(mload(0x4b20), mload(0x4420), f_q)) - mstore(0x4f80, mulmod(mload(0x4bc0), mload(0x4420), f_q)) - mstore(0x4fa0, mulmod(mload(0x4c60), mload(0x4420), f_q)) - mstore(0x4fc0, mulmod(mload(0x4d60), mload(0x4420), f_q)) - mstore(0x4fe0, mulmod(mload(0x4d80), mload(0x4420), f_q)) - mstore(0x5000, mulmod(mload(0x4da0), mload(0x4420), f_q)) - mstore(0x5020, mulmod(mload(0x4dc0), mload(0x4420), f_q)) - mstore(0x5040, mulmod(mload(0x4e60), mload(0x4420), f_q)) - mstore(0x5060, addmod(mload(0x4780), mload(0x4ea0), f_q)) - mstore(0x5080, mulmod(1, mload(0x3c40), f_q)) - mstore(0x50a0, mulmod(1, mload(0xe40), f_q)) - mstore(0x50c0, 0x0000000000000000000000000000000000000000000000000000000000000001) - mstore(0x50e0, 0x0000000000000000000000000000000000000000000000000000000000000002) - mstore(0x5100, mload(0x5060)) - success := and(eq(staticcall(gas(), 0x7, 0x50c0, 0x60, 0x50c0, 0x40), 1), success) - mstore(0x5120, mload(0x50c0)) - mstore(0x5140, mload(0x50e0)) - mstore(0x5160, mload(0x660)) - mstore(0x5180, mload(0x680)) - success := and(eq(staticcall(gas(), 0x6, 0x5120, 0x80, 0x5120, 0x40), 1), success) - mstore(0x51a0, mload(0x840)) - mstore(0x51c0, mload(0x860)) - mstore(0x51e0, mload(0x4640)) - success := and(eq(staticcall(gas(), 0x7, 0x51a0, 0x60, 0x51a0, 0x40), 1), success) - mstore(0x5200, mload(0x5120)) - mstore(0x5220, mload(0x5140)) - mstore(0x5240, mload(0x51a0)) - mstore(0x5260, mload(0x51c0)) - success := and(eq(staticcall(gas(), 0x6, 0x5200, 0x80, 0x5200, 0x40), 1), success) - mstore(0x5280, mload(0x880)) - mstore(0x52a0, mload(0x8a0)) - mstore(0x52c0, mload(0x4660)) - success := and(eq(staticcall(gas(), 0x7, 0x5280, 0x60, 0x5280, 0x40), 1), success) - mstore(0x52e0, mload(0x5200)) - mstore(0x5300, mload(0x5220)) - mstore(0x5320, mload(0x5280)) - mstore(0x5340, mload(0x52a0)) - success := and(eq(staticcall(gas(), 0x6, 0x52e0, 0x80, 0x52e0, 0x40), 1), success) - mstore(0x5360, mload(0x700)) - mstore(0x5380, mload(0x720)) - mstore(0x53a0, mload(0x4760)) - success := and(eq(staticcall(gas(), 0x7, 0x5360, 0x60, 0x5360, 0x40), 1), success) - mstore(0x53c0, mload(0x52e0)) - mstore(0x53e0, mload(0x5300)) - mstore(0x5400, mload(0x5360)) - mstore(0x5420, mload(0x5380)) - success := and(eq(staticcall(gas(), 0x6, 0x53c0, 0x80, 0x53c0, 0x40), 1), success) - mstore(0x5440, mload(0x740)) - mstore(0x5460, mload(0x760)) - mstore(0x5480, mload(0x4ec0)) - success := and(eq(staticcall(gas(), 0x7, 0x5440, 0x60, 0x5440, 0x40), 1), success) - mstore(0x54a0, mload(0x53c0)) - mstore(0x54c0, mload(0x53e0)) - mstore(0x54e0, mload(0x5440)) - mstore(0x5500, mload(0x5460)) - success := and(eq(staticcall(gas(), 0x6, 0x54a0, 0x80, 0x54a0, 0x40), 1), success) - mstore(0x5520, 0x213cf40011f8738900198c599b174deea636c934734af4175066ca297f6aee32) - mstore(0x5540, 0x1551f2933d6608d18f1e2a1109615b45127e58443760b02d78fcb4f974b3e3ce) - mstore(0x5560, mload(0x4ee0)) - success := and(eq(staticcall(gas(), 0x7, 0x5520, 0x60, 0x5520, 0x40), 1), success) - mstore(0x5580, mload(0x54a0)) - mstore(0x55a0, mload(0x54c0)) - mstore(0x55c0, mload(0x5520)) - mstore(0x55e0, mload(0x5540)) - success := and(eq(staticcall(gas(), 0x6, 0x5580, 0x80, 0x5580, 0x40), 1), success) - mstore(0x5600, 0x21c6ea7d6dbcd767ffb9d9beeb4f9c2f8243bc65290f2d75a59aea4f65ba8f3d) - mstore(0x5620, 0x24d0a0acb031c9a5687da08cdaf96650aae5c60435739bda8bbd574eb962622c) - mstore(0x5640, mload(0x4f00)) - success := and(eq(staticcall(gas(), 0x7, 0x5600, 0x60, 0x5600, 0x40), 1), success) - mstore(0x5660, mload(0x5580)) - mstore(0x5680, mload(0x55a0)) - mstore(0x56a0, mload(0x5600)) - mstore(0x56c0, mload(0x5620)) - success := and(eq(staticcall(gas(), 0x6, 0x5660, 0x80, 0x5660, 0x40), 1), success) - mstore(0x56e0, 0x1b17b25aa929dcad654497848acfba2fc23c687717f4e6437765014649c6ee15) - mstore(0x5700, 0x1b73aa6e3e6bc14b25ca8373a4d01a79c62903f91fcb76d095ffb6ac9c692049) - mstore(0x5720, mload(0x4f20)) - success := and(eq(staticcall(gas(), 0x7, 0x56e0, 0x60, 0x56e0, 0x40), 1), success) - mstore(0x5740, mload(0x5660)) - mstore(0x5760, mload(0x5680)) - mstore(0x5780, mload(0x56e0)) - mstore(0x57a0, mload(0x5700)) - success := and(eq(staticcall(gas(), 0x6, 0x5740, 0x80, 0x5740, 0x40), 1), success) - mstore(0x57c0, 0x25d0a5ef48f837d14233ce2f0961acb9ea1aecc12db0d3056c898cc9e5af5032) - mstore(0x57e0, 0x16f5118c4e2170b94e6137b7eca44571aabe677276a76ea0739b73f04bc853d2) - mstore(0x5800, mload(0x4f40)) - success := and(eq(staticcall(gas(), 0x7, 0x57c0, 0x60, 0x57c0, 0x40), 1), success) - mstore(0x5820, mload(0x5740)) - mstore(0x5840, mload(0x5760)) - mstore(0x5860, mload(0x57c0)) - mstore(0x5880, mload(0x57e0)) - success := and(eq(staticcall(gas(), 0x6, 0x5820, 0x80, 0x5820, 0x40), 1), success) - mstore(0x58a0, 0x1300f711a49a47d1cc1e27868541625117f9280a357c0c2b8ff0b13d790af07e) - mstore(0x58c0, 0x1496bd40d661139862d6a21270441c823a376eceed145dd6c2e3fa1772cda2e6) - mstore(0x58e0, mload(0x4f60)) - success := and(eq(staticcall(gas(), 0x7, 0x58a0, 0x60, 0x58a0, 0x40), 1), success) - mstore(0x5900, mload(0x5820)) - mstore(0x5920, mload(0x5840)) - mstore(0x5940, mload(0x58a0)) - mstore(0x5960, mload(0x58c0)) - success := and(eq(staticcall(gas(), 0x6, 0x5900, 0x80, 0x5900, 0x40), 1), success) - mstore(0x5980, 0x2796a29f6addcfdaef342d7f8d985a5c979587ef95d818d223c6d4e714d6c47c) - mstore(0x59a0, 0x0796ed448832f14fa093a077b57b5f6f0ec7536b3012777973a0456806821d54) - mstore(0x59c0, mload(0x4f80)) - success := and(eq(staticcall(gas(), 0x7, 0x5980, 0x60, 0x5980, 0x40), 1), success) - mstore(0x59e0, mload(0x5900)) - mstore(0x5a00, mload(0x5920)) - mstore(0x5a20, mload(0x5980)) - mstore(0x5a40, mload(0x59a0)) - success := and(eq(staticcall(gas(), 0x6, 0x59e0, 0x80, 0x59e0, 0x40), 1), success) - mstore(0x5a60, 0x261ab0f335502b5ba92ab4fff6f7a02112a6b9c5e281ae4d61d2883e5a245f2e) - mstore(0x5a80, 0x22b7d8c7bd000ddcabc27ad346fe991bf62cb53131a912201e57da270c061af1) - mstore(0x5aa0, mload(0x4fa0)) - success := and(eq(staticcall(gas(), 0x7, 0x5a60, 0x60, 0x5a60, 0x40), 1), success) - mstore(0x5ac0, mload(0x59e0)) - mstore(0x5ae0, mload(0x5a00)) - mstore(0x5b00, mload(0x5a60)) - mstore(0x5b20, mload(0x5a80)) - success := and(eq(staticcall(gas(), 0x6, 0x5ac0, 0x80, 0x5ac0, 0x40), 1), success) - mstore(0x5b40, mload(0x960)) - mstore(0x5b60, mload(0x980)) - mstore(0x5b80, mload(0x4fc0)) - success := and(eq(staticcall(gas(), 0x7, 0x5b40, 0x60, 0x5b40, 0x40), 1), success) - mstore(0x5ba0, mload(0x5ac0)) - mstore(0x5bc0, mload(0x5ae0)) - mstore(0x5be0, mload(0x5b40)) - mstore(0x5c00, mload(0x5b60)) - success := and(eq(staticcall(gas(), 0x6, 0x5ba0, 0x80, 0x5ba0, 0x40), 1), success) - mstore(0x5c20, mload(0x9a0)) - mstore(0x5c40, mload(0x9c0)) - mstore(0x5c60, mload(0x4fe0)) - success := and(eq(staticcall(gas(), 0x7, 0x5c20, 0x60, 0x5c20, 0x40), 1), success) - mstore(0x5c80, mload(0x5ba0)) - mstore(0x5ca0, mload(0x5bc0)) - mstore(0x5cc0, mload(0x5c20)) - mstore(0x5ce0, mload(0x5c40)) - success := and(eq(staticcall(gas(), 0x6, 0x5c80, 0x80, 0x5c80, 0x40), 1), success) - mstore(0x5d00, mload(0x9e0)) - mstore(0x5d20, mload(0xa00)) - mstore(0x5d40, mload(0x5000)) - success := and(eq(staticcall(gas(), 0x7, 0x5d00, 0x60, 0x5d00, 0x40), 1), success) - mstore(0x5d60, mload(0x5c80)) - mstore(0x5d80, mload(0x5ca0)) - mstore(0x5da0, mload(0x5d00)) - mstore(0x5dc0, mload(0x5d20)) - success := and(eq(staticcall(gas(), 0x6, 0x5d60, 0x80, 0x5d60, 0x40), 1), success) - mstore(0x5de0, mload(0xa20)) - mstore(0x5e00, mload(0xa40)) - mstore(0x5e20, mload(0x5020)) - success := and(eq(staticcall(gas(), 0x7, 0x5de0, 0x60, 0x5de0, 0x40), 1), success) - mstore(0x5e40, mload(0x5d60)) - mstore(0x5e60, mload(0x5d80)) - mstore(0x5e80, mload(0x5de0)) - mstore(0x5ea0, mload(0x5e00)) - success := and(eq(staticcall(gas(), 0x6, 0x5e40, 0x80, 0x5e40, 0x40), 1), success) - mstore(0x5ec0, mload(0x8c0)) - mstore(0x5ee0, mload(0x8e0)) - mstore(0x5f00, mload(0x5040)) - success := and(eq(staticcall(gas(), 0x7, 0x5ec0, 0x60, 0x5ec0, 0x40), 1), success) - mstore(0x5f20, mload(0x5e40)) - mstore(0x5f40, mload(0x5e60)) - mstore(0x5f60, mload(0x5ec0)) - mstore(0x5f80, mload(0x5ee0)) - success := and(eq(staticcall(gas(), 0x6, 0x5f20, 0x80, 0x5f20, 0x40), 1), success) - mstore(0x5fa0, mload(0xde0)) - mstore(0x5fc0, mload(0xe00)) - mstore(0x5fe0, sub(f_q, mload(0x5080))) - success := and(eq(staticcall(gas(), 0x7, 0x5fa0, 0x60, 0x5fa0, 0x40), 1), success) - mstore(0x6000, mload(0x5f20)) - mstore(0x6020, mload(0x5f40)) - mstore(0x6040, mload(0x5fa0)) - mstore(0x6060, mload(0x5fc0)) - success := and(eq(staticcall(gas(), 0x6, 0x6000, 0x80, 0x6000, 0x40), 1), success) - mstore(0x6080, mload(0xe80)) - mstore(0x60a0, mload(0xea0)) - mstore(0x60c0, mload(0x50a0)) - success := and(eq(staticcall(gas(), 0x7, 0x6080, 0x60, 0x6080, 0x40), 1), success) - mstore(0x60e0, mload(0x6000)) - mstore(0x6100, mload(0x6020)) - mstore(0x6120, mload(0x6080)) - mstore(0x6140, mload(0x60a0)) - success := and(eq(staticcall(gas(), 0x6, 0x60e0, 0x80, 0x60e0, 0x40), 1), success) - mstore(0x6160, mload(0x60e0)) - mstore(0x6180, mload(0x6100)) - mstore(0x61a0, mload(0xe80)) - mstore(0x61c0, mload(0xea0)) - mstore(0x61e0, mload(0xec0)) - mstore(0x6200, mload(0xee0)) - mstore(0x6220, mload(0xf00)) - mstore(0x6240, mload(0xf20)) - mstore(0x6260, keccak256(0x6160, 256)) - mstore(25216, mod(mload(25184), f_q)) - mstore(0x62a0, mulmod(mload(0x6280), mload(0x6280), f_q)) - mstore(0x62c0, mulmod(1, mload(0x6280), f_q)) - mstore(0x62e0, mload(0x61e0)) - mstore(0x6300, mload(0x6200)) - mstore(0x6320, mload(0x62c0)) - success := and(eq(staticcall(gas(), 0x7, 0x62e0, 0x60, 0x62e0, 0x40), 1), success) - mstore(0x6340, mload(0x6160)) - mstore(0x6360, mload(0x6180)) - mstore(0x6380, mload(0x62e0)) - mstore(0x63a0, mload(0x6300)) - success := and(eq(staticcall(gas(), 0x6, 0x6340, 0x80, 0x6340, 0x40), 1), success) - mstore(0x63c0, mload(0x6220)) - mstore(0x63e0, mload(0x6240)) - mstore(0x6400, mload(0x62c0)) - success := and(eq(staticcall(gas(), 0x7, 0x63c0, 0x60, 0x63c0, 0x40), 1), success) - mstore(0x6420, mload(0x61a0)) - mstore(0x6440, mload(0x61c0)) - mstore(0x6460, mload(0x63c0)) - mstore(0x6480, mload(0x63e0)) - success := and(eq(staticcall(gas(), 0x6, 0x6420, 0x80, 0x6420, 0x40), 1), success) - mstore(0x64a0, mload(0x6340)) - mstore(0x64c0, mload(0x6360)) - mstore(0x64e0, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) + + } +mstore(0x4280, mulmod(mload(0x4080), mload(0x40a0), f_q)) +mstore(0x42a0, mulmod(mload(0x40c0), mload(0x40e0), f_q)) +mstore(0x42c0, mulmod(mload(0x4100), mload(0x4120), f_q)) +mstore(0x42e0, mulmod(mload(0xd40), mload(0xd40), f_q)) +mstore(0x4300, mulmod(mload(0x42e0), mload(0xd40), f_q)) +mstore(0x4320, mulmod(mload(0x4300), mload(0xd40), f_q)) +mstore(0x4340, mulmod(mload(0x4320), mload(0xd40), f_q)) +mstore(0x4360, mulmod(mload(0x4340), mload(0xd40), f_q)) +mstore(0x4380, mulmod(mload(0x4360), mload(0xd40), f_q)) +mstore(0x43a0, mulmod(mload(0x4380), mload(0xd40), f_q)) +mstore(0x43c0, mulmod(mload(0x43a0), mload(0xd40), f_q)) +mstore(0x43e0, mulmod(mload(0x43c0), mload(0xd40), f_q)) +mstore(0x4400, mulmod(mload(0xda0), mload(0xda0), f_q)) +mstore(0x4420, mulmod(mload(0x4400), mload(0xda0), f_q)) +mstore(0x4440, mulmod(mload(0x4420), mload(0xda0), f_q)) +{ + let result := mulmod(mload(0xac0), mload(0x3aa0), f_q) +result := addmod(mulmod(mload(0xae0), mload(0x3b00), f_q), result, f_q) +result := addmod(mulmod(mload(0xb00), mload(0x3b60), f_q), result, f_q) +result := addmod(mulmod(mload(0xb20), mload(0x3bc0), f_q), result, f_q) +mstore(17504, result) + } +mstore(0x4480, mulmod(mload(0x4460), mload(0x4060), f_q)) +mstore(0x44a0, mulmod(sub(f_q, mload(0x4480)), 1, f_q)) +mstore(0x44c0, mulmod(mload(0x44a0), 1, f_q)) +mstore(0x44e0, mulmod(1, mload(0x4080), f_q)) +{ + let result := mulmod(mload(0xc40), mload(0x3ca0), f_q) +result := addmod(mulmod(mload(0xc60), mload(0x3d00), f_q), result, f_q) +mstore(17664, result) + } +mstore(0x4520, mulmod(mload(0x4500), mload(0x4280), f_q)) +mstore(0x4540, mulmod(sub(f_q, mload(0x4520)), 1, f_q)) +mstore(0x4560, mulmod(mload(0x44e0), 1, f_q)) +{ + let result := mulmod(mload(0xc80), mload(0x3ca0), f_q) +result := addmod(mulmod(mload(0xca0), mload(0x3d00), f_q), result, f_q) +mstore(17792, result) + } +mstore(0x45a0, mulmod(mload(0x4580), mload(0x4280), f_q)) +mstore(0x45c0, mulmod(sub(f_q, mload(0x45a0)), mload(0xd40), f_q)) +mstore(0x45e0, mulmod(mload(0x44e0), mload(0xd40), f_q)) +mstore(0x4600, addmod(mload(0x4540), mload(0x45c0), f_q)) +mstore(0x4620, mulmod(mload(0x4600), mload(0xda0), f_q)) +mstore(0x4640, mulmod(mload(0x4560), mload(0xda0), f_q)) +mstore(0x4660, mulmod(mload(0x45e0), mload(0xda0), f_q)) +mstore(0x4680, addmod(mload(0x44c0), mload(0x4620), f_q)) +mstore(0x46a0, mulmod(1, mload(0x40c0), f_q)) +{ + let result := mulmod(mload(0xcc0), mload(0x3d60), f_q) +result := addmod(mulmod(mload(0xce0), mload(0x3dc0), f_q), result, f_q) +mstore(18112, result) + } +mstore(0x46e0, mulmod(mload(0x46c0), mload(0x42a0), f_q)) +mstore(0x4700, mulmod(sub(f_q, mload(0x46e0)), 1, f_q)) +mstore(0x4720, mulmod(mload(0x46a0), 1, f_q)) +mstore(0x4740, mulmod(mload(0x4700), mload(0x4400), f_q)) +mstore(0x4760, mulmod(mload(0x4720), mload(0x4400), f_q)) +mstore(0x4780, addmod(mload(0x4680), mload(0x4740), f_q)) +mstore(0x47a0, mulmod(1, mload(0x4100), f_q)) +{ + let result := mulmod(mload(0xd00), mload(0x3e00), f_q) +mstore(18368, result) + } +mstore(0x47e0, mulmod(mload(0x47c0), mload(0x42c0), f_q)) +mstore(0x4800, mulmod(sub(f_q, mload(0x47e0)), 1, f_q)) +mstore(0x4820, mulmod(mload(0x47a0), 1, f_q)) +{ + let result := mulmod(mload(0xb40), mload(0x3e00), f_q) +mstore(18496, result) + } +mstore(0x4860, mulmod(mload(0x4840), mload(0x42c0), f_q)) +mstore(0x4880, mulmod(sub(f_q, mload(0x4860)), mload(0xd40), f_q)) +mstore(0x48a0, mulmod(mload(0x47a0), mload(0xd40), f_q)) +mstore(0x48c0, addmod(mload(0x4800), mload(0x4880), f_q)) +{ + let result := mulmod(mload(0xb60), mload(0x3e00), f_q) +mstore(18656, result) + } +mstore(0x4900, mulmod(mload(0x48e0), mload(0x42c0), f_q)) +mstore(0x4920, mulmod(sub(f_q, mload(0x4900)), mload(0x42e0), f_q)) +mstore(0x4940, mulmod(mload(0x47a0), mload(0x42e0), f_q)) +mstore(0x4960, addmod(mload(0x48c0), mload(0x4920), f_q)) +{ + let result := mulmod(mload(0xb80), mload(0x3e00), f_q) +mstore(18816, result) + } +mstore(0x49a0, mulmod(mload(0x4980), mload(0x42c0), f_q)) +mstore(0x49c0, mulmod(sub(f_q, mload(0x49a0)), mload(0x4300), f_q)) +mstore(0x49e0, mulmod(mload(0x47a0), mload(0x4300), f_q)) +mstore(0x4a00, addmod(mload(0x4960), mload(0x49c0), f_q)) +{ + let result := mulmod(mload(0xba0), mload(0x3e00), f_q) +mstore(18976, result) + } +mstore(0x4a40, mulmod(mload(0x4a20), mload(0x42c0), f_q)) +mstore(0x4a60, mulmod(sub(f_q, mload(0x4a40)), mload(0x4320), f_q)) +mstore(0x4a80, mulmod(mload(0x47a0), mload(0x4320), f_q)) +mstore(0x4aa0, addmod(mload(0x4a00), mload(0x4a60), f_q)) +{ + let result := mulmod(mload(0xbe0), mload(0x3e00), f_q) +mstore(19136, result) + } +mstore(0x4ae0, mulmod(mload(0x4ac0), mload(0x42c0), f_q)) +mstore(0x4b00, mulmod(sub(f_q, mload(0x4ae0)), mload(0x4340), f_q)) +mstore(0x4b20, mulmod(mload(0x47a0), mload(0x4340), f_q)) +mstore(0x4b40, addmod(mload(0x4aa0), mload(0x4b00), f_q)) +{ + let result := mulmod(mload(0xc00), mload(0x3e00), f_q) +mstore(19296, result) + } +mstore(0x4b80, mulmod(mload(0x4b60), mload(0x42c0), f_q)) +mstore(0x4ba0, mulmod(sub(f_q, mload(0x4b80)), mload(0x4360), f_q)) +mstore(0x4bc0, mulmod(mload(0x47a0), mload(0x4360), f_q)) +mstore(0x4be0, addmod(mload(0x4b40), mload(0x4ba0), f_q)) +{ + let result := mulmod(mload(0xc20), mload(0x3e00), f_q) +mstore(19456, result) + } +mstore(0x4c20, mulmod(mload(0x4c00), mload(0x42c0), f_q)) +mstore(0x4c40, mulmod(sub(f_q, mload(0x4c20)), mload(0x4380), f_q)) +mstore(0x4c60, mulmod(mload(0x47a0), mload(0x4380), f_q)) +mstore(0x4c80, addmod(mload(0x4be0), mload(0x4c40), f_q)) +mstore(0x4ca0, mulmod(mload(0x3860), mload(0x4100), f_q)) +mstore(0x4cc0, mulmod(mload(0x3880), mload(0x4100), f_q)) +mstore(0x4ce0, mulmod(mload(0x38a0), mload(0x4100), f_q)) +{ + let result := mulmod(mload(0x38c0), mload(0x3e00), f_q) +mstore(19712, result) + } +mstore(0x4d20, mulmod(mload(0x4d00), mload(0x42c0), f_q)) +mstore(0x4d40, mulmod(sub(f_q, mload(0x4d20)), mload(0x43a0), f_q)) +mstore(0x4d60, mulmod(mload(0x47a0), mload(0x43a0), f_q)) +mstore(0x4d80, mulmod(mload(0x4ca0), mload(0x43a0), f_q)) +mstore(0x4da0, mulmod(mload(0x4cc0), mload(0x43a0), f_q)) +mstore(0x4dc0, mulmod(mload(0x4ce0), mload(0x43a0), f_q)) +mstore(0x4de0, addmod(mload(0x4c80), mload(0x4d40), f_q)) +{ + let result := mulmod(mload(0xbc0), mload(0x3e00), f_q) +mstore(19968, result) + } +mstore(0x4e20, mulmod(mload(0x4e00), mload(0x42c0), f_q)) +mstore(0x4e40, mulmod(sub(f_q, mload(0x4e20)), mload(0x43c0), f_q)) +mstore(0x4e60, mulmod(mload(0x47a0), mload(0x43c0), f_q)) +mstore(0x4e80, addmod(mload(0x4de0), mload(0x4e40), f_q)) +mstore(0x4ea0, mulmod(mload(0x4e80), mload(0x4420), f_q)) +mstore(0x4ec0, mulmod(mload(0x4820), mload(0x4420), f_q)) +mstore(0x4ee0, mulmod(mload(0x48a0), mload(0x4420), f_q)) +mstore(0x4f00, mulmod(mload(0x4940), mload(0x4420), f_q)) +mstore(0x4f20, mulmod(mload(0x49e0), mload(0x4420), f_q)) +mstore(0x4f40, mulmod(mload(0x4a80), mload(0x4420), f_q)) +mstore(0x4f60, mulmod(mload(0x4b20), mload(0x4420), f_q)) +mstore(0x4f80, mulmod(mload(0x4bc0), mload(0x4420), f_q)) +mstore(0x4fa0, mulmod(mload(0x4c60), mload(0x4420), f_q)) +mstore(0x4fc0, mulmod(mload(0x4d60), mload(0x4420), f_q)) +mstore(0x4fe0, mulmod(mload(0x4d80), mload(0x4420), f_q)) +mstore(0x5000, mulmod(mload(0x4da0), mload(0x4420), f_q)) +mstore(0x5020, mulmod(mload(0x4dc0), mload(0x4420), f_q)) +mstore(0x5040, mulmod(mload(0x4e60), mload(0x4420), f_q)) +mstore(0x5060, addmod(mload(0x4780), mload(0x4ea0), f_q)) +mstore(0x5080, mulmod(1, mload(0x3c40), f_q)) +mstore(0x50a0, mulmod(1, mload(0xe40), f_q)) +mstore(0x50c0, 0x0000000000000000000000000000000000000000000000000000000000000001) + mstore(0x50e0, 0x0000000000000000000000000000000000000000000000000000000000000002) +mstore(0x5100, mload(0x5060)) +success := and(eq(staticcall(gas(), 0x7, 0x50c0, 0x60, 0x50c0, 0x40), 1), success) +mstore(0x5120, mload(0x50c0)) + mstore(0x5140, mload(0x50e0)) +mstore(0x5160, mload(0x660)) + mstore(0x5180, mload(0x680)) +success := and(eq(staticcall(gas(), 0x6, 0x5120, 0x80, 0x5120, 0x40), 1), success) +mstore(0x51a0, mload(0x840)) + mstore(0x51c0, mload(0x860)) +mstore(0x51e0, mload(0x4640)) +success := and(eq(staticcall(gas(), 0x7, 0x51a0, 0x60, 0x51a0, 0x40), 1), success) +mstore(0x5200, mload(0x5120)) + mstore(0x5220, mload(0x5140)) +mstore(0x5240, mload(0x51a0)) + mstore(0x5260, mload(0x51c0)) +success := and(eq(staticcall(gas(), 0x6, 0x5200, 0x80, 0x5200, 0x40), 1), success) +mstore(0x5280, mload(0x880)) + mstore(0x52a0, mload(0x8a0)) +mstore(0x52c0, mload(0x4660)) +success := and(eq(staticcall(gas(), 0x7, 0x5280, 0x60, 0x5280, 0x40), 1), success) +mstore(0x52e0, mload(0x5200)) + mstore(0x5300, mload(0x5220)) +mstore(0x5320, mload(0x5280)) + mstore(0x5340, mload(0x52a0)) +success := and(eq(staticcall(gas(), 0x6, 0x52e0, 0x80, 0x52e0, 0x40), 1), success) +mstore(0x5360, mload(0x700)) + mstore(0x5380, mload(0x720)) +mstore(0x53a0, mload(0x4760)) +success := and(eq(staticcall(gas(), 0x7, 0x5360, 0x60, 0x5360, 0x40), 1), success) +mstore(0x53c0, mload(0x52e0)) + mstore(0x53e0, mload(0x5300)) +mstore(0x5400, mload(0x5360)) + mstore(0x5420, mload(0x5380)) +success := and(eq(staticcall(gas(), 0x6, 0x53c0, 0x80, 0x53c0, 0x40), 1), success) +mstore(0x5440, mload(0x740)) + mstore(0x5460, mload(0x760)) +mstore(0x5480, mload(0x4ec0)) +success := and(eq(staticcall(gas(), 0x7, 0x5440, 0x60, 0x5440, 0x40), 1), success) +mstore(0x54a0, mload(0x53c0)) + mstore(0x54c0, mload(0x53e0)) +mstore(0x54e0, mload(0x5440)) + mstore(0x5500, mload(0x5460)) +success := and(eq(staticcall(gas(), 0x6, 0x54a0, 0x80, 0x54a0, 0x40), 1), success) +mstore(0x5520, 0x0b1b66f975ddca0acbfb7616fdfb45b58fa2e61370d8050b1db3f63da1d620a9) + mstore(0x5540, 0x19a35018fbf062d680f5f4dd5a9ddc3027e4cb5d14c71a750c30ca098ca90b35) +mstore(0x5560, mload(0x4ee0)) +success := and(eq(staticcall(gas(), 0x7, 0x5520, 0x60, 0x5520, 0x40), 1), success) +mstore(0x5580, mload(0x54a0)) + mstore(0x55a0, mload(0x54c0)) +mstore(0x55c0, mload(0x5520)) + mstore(0x55e0, mload(0x5540)) +success := and(eq(staticcall(gas(), 0x6, 0x5580, 0x80, 0x5580, 0x40), 1), success) +mstore(0x5600, 0x21c6ea7d6dbcd767ffb9d9beeb4f9c2f8243bc65290f2d75a59aea4f65ba8f3d) + mstore(0x5620, 0x24d0a0acb031c9a5687da08cdaf96650aae5c60435739bda8bbd574eb962622c) +mstore(0x5640, mload(0x4f00)) +success := and(eq(staticcall(gas(), 0x7, 0x5600, 0x60, 0x5600, 0x40), 1), success) +mstore(0x5660, mload(0x5580)) + mstore(0x5680, mload(0x55a0)) +mstore(0x56a0, mload(0x5600)) + mstore(0x56c0, mload(0x5620)) +success := and(eq(staticcall(gas(), 0x6, 0x5660, 0x80, 0x5660, 0x40), 1), success) +mstore(0x56e0, 0x1b17b25aa929dcad654497848acfba2fc23c687717f4e6437765014649c6ee15) + mstore(0x5700, 0x1b73aa6e3e6bc14b25ca8373a4d01a79c62903f91fcb76d095ffb6ac9c692049) +mstore(0x5720, mload(0x4f20)) +success := and(eq(staticcall(gas(), 0x7, 0x56e0, 0x60, 0x56e0, 0x40), 1), success) +mstore(0x5740, mload(0x5660)) + mstore(0x5760, mload(0x5680)) +mstore(0x5780, mload(0x56e0)) + mstore(0x57a0, mload(0x5700)) +success := and(eq(staticcall(gas(), 0x6, 0x5740, 0x80, 0x5740, 0x40), 1), success) +mstore(0x57c0, 0x25d0a5ef48f837d14233ce2f0961acb9ea1aecc12db0d3056c898cc9e5af5032) + mstore(0x57e0, 0x16f5118c4e2170b94e6137b7eca44571aabe677276a76ea0739b73f04bc853d2) +mstore(0x5800, mload(0x4f40)) +success := and(eq(staticcall(gas(), 0x7, 0x57c0, 0x60, 0x57c0, 0x40), 1), success) +mstore(0x5820, mload(0x5740)) + mstore(0x5840, mload(0x5760)) +mstore(0x5860, mload(0x57c0)) + mstore(0x5880, mload(0x57e0)) +success := and(eq(staticcall(gas(), 0x6, 0x5820, 0x80, 0x5820, 0x40), 1), success) +mstore(0x58a0, 0x1253193b69dc358c09220c36b04a3c026b8b9912dcd40b8671634fcdb50657c1) + mstore(0x58c0, 0x1d936da500b58a7118360c92841b2f8f0e636245f8b5ec34db6235b56dc25848) +mstore(0x58e0, mload(0x4f60)) +success := and(eq(staticcall(gas(), 0x7, 0x58a0, 0x60, 0x58a0, 0x40), 1), success) +mstore(0x5900, mload(0x5820)) + mstore(0x5920, mload(0x5840)) +mstore(0x5940, mload(0x58a0)) + mstore(0x5960, mload(0x58c0)) +success := and(eq(staticcall(gas(), 0x6, 0x5900, 0x80, 0x5900, 0x40), 1), success) +mstore(0x5980, 0x28b5b520d4b614165e1aa123b55428806f77327c2b3a4d8c467a323f4b4f7b43) + mstore(0x59a0, 0x0d4825d9ce7cd6f2efe68b77dc1fc56d7b4cb9d52224c14ccfcb75b76fc6b1fc) +mstore(0x59c0, mload(0x4f80)) +success := and(eq(staticcall(gas(), 0x7, 0x5980, 0x60, 0x5980, 0x40), 1), success) +mstore(0x59e0, mload(0x5900)) + mstore(0x5a00, mload(0x5920)) +mstore(0x5a20, mload(0x5980)) + mstore(0x5a40, mload(0x59a0)) +success := and(eq(staticcall(gas(), 0x6, 0x59e0, 0x80, 0x59e0, 0x40), 1), success) +mstore(0x5a60, 0x261ab0f335502b5ba92ab4fff6f7a02112a6b9c5e281ae4d61d2883e5a245f2e) + mstore(0x5a80, 0x22b7d8c7bd000ddcabc27ad346fe991bf62cb53131a912201e57da270c061af1) +mstore(0x5aa0, mload(0x4fa0)) +success := and(eq(staticcall(gas(), 0x7, 0x5a60, 0x60, 0x5a60, 0x40), 1), success) +mstore(0x5ac0, mload(0x59e0)) + mstore(0x5ae0, mload(0x5a00)) +mstore(0x5b00, mload(0x5a60)) + mstore(0x5b20, mload(0x5a80)) +success := and(eq(staticcall(gas(), 0x6, 0x5ac0, 0x80, 0x5ac0, 0x40), 1), success) +mstore(0x5b40, mload(0x960)) + mstore(0x5b60, mload(0x980)) +mstore(0x5b80, mload(0x4fc0)) +success := and(eq(staticcall(gas(), 0x7, 0x5b40, 0x60, 0x5b40, 0x40), 1), success) +mstore(0x5ba0, mload(0x5ac0)) + mstore(0x5bc0, mload(0x5ae0)) +mstore(0x5be0, mload(0x5b40)) + mstore(0x5c00, mload(0x5b60)) +success := and(eq(staticcall(gas(), 0x6, 0x5ba0, 0x80, 0x5ba0, 0x40), 1), success) +mstore(0x5c20, mload(0x9a0)) + mstore(0x5c40, mload(0x9c0)) +mstore(0x5c60, mload(0x4fe0)) +success := and(eq(staticcall(gas(), 0x7, 0x5c20, 0x60, 0x5c20, 0x40), 1), success) +mstore(0x5c80, mload(0x5ba0)) + mstore(0x5ca0, mload(0x5bc0)) +mstore(0x5cc0, mload(0x5c20)) + mstore(0x5ce0, mload(0x5c40)) +success := and(eq(staticcall(gas(), 0x6, 0x5c80, 0x80, 0x5c80, 0x40), 1), success) +mstore(0x5d00, mload(0x9e0)) + mstore(0x5d20, mload(0xa00)) +mstore(0x5d40, mload(0x5000)) +success := and(eq(staticcall(gas(), 0x7, 0x5d00, 0x60, 0x5d00, 0x40), 1), success) +mstore(0x5d60, mload(0x5c80)) + mstore(0x5d80, mload(0x5ca0)) +mstore(0x5da0, mload(0x5d00)) + mstore(0x5dc0, mload(0x5d20)) +success := and(eq(staticcall(gas(), 0x6, 0x5d60, 0x80, 0x5d60, 0x40), 1), success) +mstore(0x5de0, mload(0xa20)) + mstore(0x5e00, mload(0xa40)) +mstore(0x5e20, mload(0x5020)) +success := and(eq(staticcall(gas(), 0x7, 0x5de0, 0x60, 0x5de0, 0x40), 1), success) +mstore(0x5e40, mload(0x5d60)) + mstore(0x5e60, mload(0x5d80)) +mstore(0x5e80, mload(0x5de0)) + mstore(0x5ea0, mload(0x5e00)) +success := and(eq(staticcall(gas(), 0x6, 0x5e40, 0x80, 0x5e40, 0x40), 1), success) +mstore(0x5ec0, mload(0x8c0)) + mstore(0x5ee0, mload(0x8e0)) +mstore(0x5f00, mload(0x5040)) +success := and(eq(staticcall(gas(), 0x7, 0x5ec0, 0x60, 0x5ec0, 0x40), 1), success) +mstore(0x5f20, mload(0x5e40)) + mstore(0x5f40, mload(0x5e60)) +mstore(0x5f60, mload(0x5ec0)) + mstore(0x5f80, mload(0x5ee0)) +success := and(eq(staticcall(gas(), 0x6, 0x5f20, 0x80, 0x5f20, 0x40), 1), success) +mstore(0x5fa0, mload(0xde0)) + mstore(0x5fc0, mload(0xe00)) +mstore(0x5fe0, sub(f_q, mload(0x5080))) +success := and(eq(staticcall(gas(), 0x7, 0x5fa0, 0x60, 0x5fa0, 0x40), 1), success) +mstore(0x6000, mload(0x5f20)) + mstore(0x6020, mload(0x5f40)) +mstore(0x6040, mload(0x5fa0)) + mstore(0x6060, mload(0x5fc0)) +success := and(eq(staticcall(gas(), 0x6, 0x6000, 0x80, 0x6000, 0x40), 1), success) +mstore(0x6080, mload(0xe80)) + mstore(0x60a0, mload(0xea0)) +mstore(0x60c0, mload(0x50a0)) +success := and(eq(staticcall(gas(), 0x7, 0x6080, 0x60, 0x6080, 0x40), 1), success) +mstore(0x60e0, mload(0x6000)) + mstore(0x6100, mload(0x6020)) +mstore(0x6120, mload(0x6080)) + mstore(0x6140, mload(0x60a0)) +success := and(eq(staticcall(gas(), 0x6, 0x60e0, 0x80, 0x60e0, 0x40), 1), success) +mstore(0x6160, mload(0x60e0)) + mstore(0x6180, mload(0x6100)) +mstore(0x61a0, mload(0xe80)) + mstore(0x61c0, mload(0xea0)) +mstore(0x61e0, mload(0xec0)) + mstore(0x6200, mload(0xee0)) +mstore(0x6220, mload(0xf00)) + mstore(0x6240, mload(0xf20)) +mstore(0x6260, keccak256(0x6160, 256)) +mstore(25216, mod(mload(25184), f_q)) +mstore(0x62a0, mulmod(mload(0x6280), mload(0x6280), f_q)) +mstore(0x62c0, mulmod(1, mload(0x6280), f_q)) +mstore(0x62e0, mload(0x61e0)) + mstore(0x6300, mload(0x6200)) +mstore(0x6320, mload(0x62c0)) +success := and(eq(staticcall(gas(), 0x7, 0x62e0, 0x60, 0x62e0, 0x40), 1), success) +mstore(0x6340, mload(0x6160)) + mstore(0x6360, mload(0x6180)) +mstore(0x6380, mload(0x62e0)) + mstore(0x63a0, mload(0x6300)) +success := and(eq(staticcall(gas(), 0x6, 0x6340, 0x80, 0x6340, 0x40), 1), success) +mstore(0x63c0, mload(0x6220)) + mstore(0x63e0, mload(0x6240)) +mstore(0x6400, mload(0x62c0)) +success := and(eq(staticcall(gas(), 0x7, 0x63c0, 0x60, 0x63c0, 0x40), 1), success) +mstore(0x6420, mload(0x61a0)) + mstore(0x6440, mload(0x61c0)) +mstore(0x6460, mload(0x63c0)) + mstore(0x6480, mload(0x63e0)) +success := and(eq(staticcall(gas(), 0x6, 0x6420, 0x80, 0x6420, 0x40), 1), success) +mstore(0x64a0, mload(0x6340)) + mstore(0x64c0, mload(0x6360)) +mstore(0x64e0, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) mstore(0x6500, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) mstore(0x6520, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) mstore(0x6540, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) - mstore(0x6560, mload(0x6420)) - mstore(0x6580, mload(0x6440)) - mstore(0x65a0, 0x172aa93c41f16e1e04d62ac976a5d945f4be0acab990c6dc19ac4a7cf68bf77b) +mstore(0x6560, mload(0x6420)) + mstore(0x6580, mload(0x6440)) +mstore(0x65a0, 0x172aa93c41f16e1e04d62ac976a5d945f4be0acab990c6dc19ac4a7cf68bf77b) mstore(0x65c0, 0x2ae0c8c3a090f7200ff398ee9845bbae8f8c1445ae7b632212775f60a0e21600) mstore(0x65e0, 0x190fa476a5b352809ed41d7a0d7fe12b8f685e3c12a6d83855dba27aaf469643) mstore(0x6600, 0x1c0a500618907df9e4273d5181e31088deb1f05132de037cbfe73888f97f77c9) - success := and(eq(staticcall(gas(), 0x8, 0x64a0, 0x180, 0x64a0, 0x20), 1), success) - success := and(eq(mload(0x64a0), 1), success) +success := and(eq(staticcall(gas(), 0x8, 0x64a0, 0x180, 0x64a0, 0x20), 1), success) +success := and(eq(mload(0x64a0), 1), success) // Revert if anything fails if iszero(success) { revert(0, 0) } // Return empty bytes on success return(0, 0) + } } } + \ No newline at end of file diff --git a/releases/dev/verifier/verifier.bin b/releases/dev/verifier/verifier.bin index e43ee5e5..25efe4f9 100644 Binary files a/releases/dev/verifier/verifier.bin and b/releases/dev/verifier/verifier.bin differ diff --git a/releases/dev/verifier/verifier.sol b/releases/dev/verifier/verifier.sol index 121b4b45..61169af2 100644 --- a/releases/dev/verifier/verifier.sol +++ b/releases/dev/verifier/verifier.sol @@ -58,13 +58,8 @@ contract OpenVmHalo2Verifier is Halo2Verifier, IOpenVmHalo2Verifier { /// @param appExeCommit The commitment to the OpenVM application executable whose execution /// is being verified. /// @param appVmCommit The commitment to the VM configuration. - function verify(bytes calldata publicValues, bytes calldata proofData, bytes32 appExeCommit, bytes32 appVmCommit) - external - view - { - if (publicValues.length != PUBLIC_VALUES_LENGTH) { - revert InvalidPublicValuesLength(PUBLIC_VALUES_LENGTH, publicValues.length); - } + function verify(bytes calldata publicValues, bytes calldata proofData, bytes32 appExeCommit, bytes32 appVmCommit) external view { + if (publicValues.length != PUBLIC_VALUES_LENGTH) revert InvalidPublicValuesLength(PUBLIC_VALUES_LENGTH, publicValues.length); if (proofData.length != PROOF_DATA_LENGTH) revert InvalidProofDataLength(PROOF_DATA_LENGTH, proofData.length); if (uint256(appExeCommit) >= BN254_SCALAR_MODULUS) revert InvalidAppExeCommit(appExeCommit); if (uint256(appVmCommit) >= BN254_SCALAR_MODULUS) revert InvalidAppVmCommit(appVmCommit); @@ -72,7 +67,7 @@ contract OpenVmHalo2Verifier is Halo2Verifier, IOpenVmHalo2Verifier { // Other than the fallback() in `Halo2Verifier`, there is only one // function selector on the external ABI: `verify(..)`, which has // selector 0x24270d54. If `proofData` ever began with 0x24270d54, this - // function would be called again instead of hitting the fallback. + // function would be called again instead of hitting the fallback. // // If a valid proof ever began with 0x24270d54, it would fail to verify. // However, `snark-verifier`'s proof structure guarantees that the first @@ -119,12 +114,11 @@ contract OpenVmHalo2Verifier is Halo2Verifier, IOpenVmHalo2Verifier { /// /// @return proofPtr Memory pointer to the beginning of the constructed /// proof. This pointer does not follow `bytes memory` semantics. - function _constructProof( - bytes calldata publicValues, - bytes calldata proofData, - bytes32 appExeCommit, - bytes32 appVmCommit - ) internal pure returns (MemoryPointer proofPtr) { + function _constructProof(bytes calldata publicValues, bytes calldata proofData, bytes32 appExeCommit, bytes32 appVmCommit) + internal + pure + returns (MemoryPointer proofPtr) + { uint256 fullProofLength = FULL_PROOF_LENGTH; // The expected proof format using hex offsets: diff --git a/rust-toolchain.toml b/rust-toolchain.toml index c6357706..e822dc9f 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,5 @@ [toolchain] -channel = "nightly-2025-11-20" -targets = ["riscv32im-unknown-none-elf", "x86_64-unknown-linux-gnu"] +# Nightly required by the openvm-sdk "tco" feature (see openvm's rust-toolchain.toml). +channel = "nightly-2026-01-18" +targets = ["x86_64-unknown-linux-gnu"] components = ["llvm-tools", "rustc-dev"] diff --git a/scripts/profile_top.py b/scripts/profile_top.py new file mode 100644 index 00000000..5e63a87e --- /dev/null +++ b/scripts/profile_top.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python3 +"""Aggregate guest profiling metrics JSON (dumped by scroll-zkvm-prover's +`perf-metrics` feature via PROFILE_METRICS_DIR) into human-readable tops: + + - top functions by executed instructions ("frequency"), self-attribution + (leaf frame of the cycle tracker span stack) + - top inclusive span stacks (flamegraph-style), also written as .stacks + - top AIRs by cells used ("cells_used") + +Function spans are decimal offsets into the guest symbols string table +(dumped by build-guest as guest.symbols when built with `perf-metrics`). + +Usage: profile_top.py metrics.json [--symbols guest.symbols] [--top 30] +""" + +import argparse +import json +import sys +from collections import defaultdict + + +def load_symbols(path): + if not path: + return None + with open(path, "rb") as f: + return f.read() + + +def resolve(name, symbols): + """Resolve a span frame: decimal offset into the string table, or a plain name.""" + if symbols is None or not name or not name.isdigit(): + return name + offset = int(name) + end = symbols.find(b"\0", offset) + if end == -1 or offset >= len(symbols): + return name + return symbols[offset:end].decode(errors="replace") + + +def shorten(name, maxlen=110): + """Collapse verbose Rust paths: keep the last meaningful segments.""" + if len(name) <= maxlen: + return name + # strip generic args for readability + out = [] + depth = 0 + for ch in name: + if ch == "<": + depth += 1 + elif ch == ">": + depth -= 1 + elif depth == 0: + out.append(ch) + name = "".join(out) + if len(name) > maxlen: + name = "..." + name[-maxlen:] + return name + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("metrics_json") + ap.add_argument("--symbols", default=None) + ap.add_argument("--top", type=int, default=30) + args = ap.parse_args() + + with open(args.metrics_json) as f: + data = json.load(f) + + symbols = load_symbols(args.symbols) + + instr_self = defaultdict(int) # leaf function -> instructions + instr_inclusive = defaultdict(int) # full stack -> instructions + cells_air = defaultdict(int) # air name -> cells + cells_span_air = defaultdict(int) # (span leaf fn, air) -> cells + + for entry in data.get("counter", []): + metric = entry["metric"] + labels = dict(entry["labels"]) + value = int(entry["value"]) + span = labels.get("cycle_tracker_span", "") + frames = [resolve(f, symbols) for f in span.split(";") if f != ""] + leaf = frames[-1] if frames else "" + + if metric == "frequency": + instr_self[leaf] += value + instr_inclusive[";".join(frames)] += value + elif metric == "cells_used": + air = labels.get("air_name", "?") + cells_air[air] += value + cells_span_air[(leaf, air)] += value + + total_instr = sum(instr_self.values()) + total_cells = sum(cells_air.values()) + + print(f"== total guest instructions (frequency): {total_instr:,}") + print(f"== total trace cells (cells_used): {total_cells:,}") + print() + print(f"-- top {args.top} functions by instructions (self) --") + for name, v in sorted(instr_self.items(), key=lambda kv: -kv[1])[: args.top]: + print(f"{v:>14,} {100.0*v/max(total_instr,1):5.1f}% {shorten(name)}") + print() + print(f"-- top {args.top} AIRs by cells used --") + for name, v in sorted(cells_air.items(), key=lambda kv: -kv[1])[: args.top]: + print(f"{v:>14,} {100.0*v/max(total_cells,1):5.1f}% {name}") + print() + print(f"-- top {args.top} (function, AIR) by cells used --") + for (fn, air), v in sorted(cells_span_air.items(), key=lambda kv: -kv[1])[: args.top]: + print(f"{v:>14,} {100.0*v/max(total_cells,1):5.1f}% {air} <- {shorten(fn, 80)}") + print() + print(f"-- top {args.top} inclusive span stacks by instructions --") + for stack, v in sorted(instr_inclusive.items(), key=lambda kv: -kv[1])[: args.top]: + print(f"{v:>14,} {100.0*v/max(total_instr,1):5.1f}% {shorten(stack, 160)}") + + +if __name__ == "__main__": + main()