Skip to content

Draft 0.4.0#625

Draft
Raid5594 wants to merge 29 commits into
devfrom
draft-0.4.0
Draft

Draft 0.4.0#625
Raid5594 wants to merge 29 commits into
devfrom
draft-0.4.0

Conversation

@Raid5594
Copy link
Copy Markdown

What ❔

Why ❔

Is this a breaking change?

  • Yes
  • No

Checklist

  • PR title corresponds to the body of PR (we generate changelog entries from PRs).
  • Tests for the changes have been added / updated.
  • Documentation comments have been added / updated.
  • Code has been formatted.

antoniolocascio and others added 13 commits April 23, 2026 10:18
Reimplement the hints for ecrecover from ethproofs.
Instead of having a new full implementation of ecrecover, this PR
introduces "hooks" for 3 secp256k1 field operations. These hooks have
two implmentations: default, where the implementation is straightforward
(same implementation as before this PR) and oracle-based, where we use
the new callable oracles.
This way, most of the logic for ecrecover is reused.

Given that this is a critical part of the system, the PR includes:
* PBT for "good" case (showing equivalence when using the right oracle)
* Tests for the "bad" case (showing panics if the oracle lies)
* Modifies the fuzz target for ecrecover to compare the forward and
oracle runs. I've ran the fuzzer for over 1h without finding issues.

<!-- What are the changes this PR brings about? -->
<!-- Example: This PR adds a PR template to the repo. -->
<!-- (For bigger PRs adding more context is appreciated) -->

<!-- Why are these changes done? What goal do they contribute to? What
are the principles behind them? -->
<!-- The `Why` has to be clear to non-Matter Labs entities running their
own ZK Chain -->
<!-- Example: PR templates ensure PR reviewers, observers, and future
iterators are in context about the evolution of repos. -->

- [ ] Yes
- [ ] No

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [ ] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [ ] Tests for the changes have been added / updated.
- [ ] Documentation comments have been added / updated.
- [ ] Code has been formatted.
…coding (#572)

## What ❔

Remove the `artifacts_len` field and artifact bytes from the pubdata
diff compression encoding:

- **Format 0** (publish bytecode): remove `artifacts_len` field (4
bytes), publish only the raw code bytes (`unpadded_code_len`) instead of
the full bytecode blob (code + padding + artifacts)
- **Format 4** (not_publish_bytecode): remove `artifacts_len` from the
length calculation — fixes a pre-existing bug where
`diff_compression_length()` counted +4 bytes for `artifacts_len` but
`diff_compression()` never actually wrote it
- Bump `PUBDATA_ENCODING_VERSION` from 1 to 2
- Update format documentation comments and unit test

## Why ❔

Bytecode artifacts (jump table, etc.) are fully deterministic from the
raw bytecode and do not need to be published in pubdata. Removing them
reduces pubdata size for contract deployments without losing any
information — the receiver can recompute artifacts from the code.

## Is this a breaking change?
- [x] Yes
- [ ] No

This changes the pubdata encoding format (version 1 → 2). The settlement
layer / receiver must be updated to parse the new format.

## Checklist

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted.

---------

Co-authored-by: Claude Code <claude-code@anthropic.com>
## What ❔

Per-opcode EVM benchmarking infrastructure that collects gas, native
resource, and RISC-V cycle stats for every EVM opcode execution. Enables
computing cycles/gas and native/gas ratios to guide proving cost
optimizations.

**Components:**
- `EvmOpcodeStatsTracer` — forward-mode tracer collecting per-opcode
gas, native, count with min/max/median
- Per-opcode cycle markers in the interpreter loop
(`opcode_start!/opcode_end!`) — aggregated in `print_cycle_markers()`
with min/max/median
- Per-execution sample dump mode — write `(gas, native)` and `cycles`
per execution for detailed ratio analysis
- `join_samples.py` — joins tracer + cycle samples, computes
per-execution cycles/gas with p50/p95/p99/max
- `compare_opcode_stats.py` — CI integration: compact diff table when
per-opcode stats change
- `visualize_opcode_stats.py` — total cycle bar chart + sorted
cycles/gas ratio curves
- Integration into `eth_runner` single-run and CI bench workflow

**Usage:**
```bash
# Basic run (prints per-opcode stats table)
bash bench_scripts/bench.sh quick

# Full per-execution analysis
OPCODE_SAMPLES_DIR=samples OPCODE_CYCLE_SAMPLES_DIR=cycle_samples bash bench_scripts/bench.sh quick
python3 bench_scripts/join_samples.py samples/ cycle_samples/ --summary --out-dir joined/
python3 bench_scripts/visualize_opcode_stats.py joined/ --out-dir charts/
```

**Benchmark impact:** +0.34% effective cycles with benchmarking features
enabled. Zero overhead in production builds (all behind `#[cfg(feature =
"cycle_marker")]`).

## Why ❔

To compute per-opcode `cycles/gas` and `native/gas` ratios for verifying
the native resource model against actual RISC-V proving costs.

## Is this a breaking change?
- [ ] Yes
- [x] No

All code is behind feature flags or in benchmarking-only paths.
Production proving builds are unaffected — verified by audit of all
changed files and benchmark comparison.

## Checklist

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted.

---------

Co-authored-by: Antonio Locascio <antonio.locascio1@gmail.com>
Co-authored-by: vv-dev-ai <vv@matterlabs.dev>
Co-authored-by: Claude Code <claude-code@anthropic.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## What

Add `compare_opcode_cycles.py` script and wire it into the bench CI
workflow so that per-opcode RISC-V cycle diffs are posted on PRs.

The bench CI already collected per-opcode cycle stats in `.bench` files
on both the base and head sides (via `opcode_start!/opcode_end!` cycle
markers), but had no script to compare them. The existing
`compare_opcode_stats.py` only compared forward-mode gas/native stats,
which don't change when the execution implementation changes without
modifying resource accounting (e.g. the custom U256 PR).

## Why

Without this, PRs that affect RISC-V execution performance (like the
custom U256 migration) show overall effective cycle improvements in the
benchmark report but lack visibility into which specific EVM opcodes
improved or regressed. This makes it harder to review and reason about
performance changes.

## Is this a breaking change?
- [ ] Yes
- [x] No

## Checklist

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted.

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This PR changes the way we compute prover input. Before, we needed to
run the slow risc-v simulator to do so.
Now, we can do on native architecture.
This run is also responsible for computing the pubdata.
<!-- What are the changes this PR brings about? -->
<!-- Example: This PR adds a PR template to the repo. -->
<!-- (For bigger PRs adding more context is appreciated) -->

<!-- Why are these changes done? What goal do they contribute to? What
are the principles behind them? -->
<!-- The `Why` has to be clear to non-Matter Labs entities running their
own ZK Chain -->
<!-- Example: PR templates ensure PR reviewers, observers, and future
iterators are in context about the evolution of repos. -->

- [ ] Yes
- [ ] No

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [ ] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [ ] Tests for the changes have been added / updated.
- [ ] Documentation comments have been added / updated.
- [ ] Code has been formatted.
## What ❔

We had an invalid worst case calculation + small cleanup

## Why ❔

<!-- Why are these changes done? What goal do they contribute to? What
are the principles behind them? -->
<!-- The `Why` has to be clear to non-Matter Labs entities running their
own ZK Chain -->
<!-- Example: PR templates ensure PR reviewers, observers, and future
iterators are in context about the evolution of repos. -->

## Is this a breaking change?
- [ ] Yes
- [ ] No

## Checklist

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [ ] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [ ] Tests for the changes have been added / updated.
- [ ] Documentation comments have been added / updated.
- [ ] Code has been formatted.

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the removed `risc_v_simulator` crate with `riscv_transpiler`
from zksync-airbender dev branch (v2). This migrates the entire RISC-V
execution and oracle infrastructure to the new VM API.

**Dependencies & toolchain:**
- `risc_v_simulator` removed from workspace, replaced by
`riscv_transpiler` + `common_constants` (git deps pointing to airbender
`dev` branch)
- Toolchain bumped to `nightly-2026-02-10` in both root and `zksync_os/`
(required by airbender v2's `blake2s_u32`)
- `zksync_os/reproduce/Dockerfile` updated to match

**oracle_provider:**
- `ZkEENonDeterminismSource`, `OracleQueryProcessor`, and
`ReadWitnessSource` are **no longer generic** over memory type
- Processors take `&dyn RamPeek` instead of `&M` where `M: MemorySource`
- `DummyMemorySource` now implements `RamPeek`
- Implements new `NonDeterminismCSRSource` trait from
`riscv_transpiler::vm` (with `write_with_memory_access`,
`write_with_memory_access_dyn`)

**callable_oracles:**
- All query processors (`ArithmeticQuery`,
`BlobCommitmentAndProofQuery`, `FieldOpsQuery`, `HashToPrimeSource`, and
their `Native*` variants) simplified to non-generic structs
- Memory reads use `peek_word(addr)` instead of `memory.get(addr,
AccessType, &mut trap)`
- Fixed pre-existing overflow check in `read_memory_as_u64` (now uses
byte length for bounds check)

**zksync_os_runner:**
- Rewritten to use `VM::run_basic_unrolled` with `SimpleTape` +
`RamWithRomRegion`
- Requires `.bin` + `.text` file pair (already produced by `dump_bin.sh`
via `objcopy --only-section=.text`)
- `DiagnosticsConfig` parameter removed; flamegraph support via
feature-gated `run_basic_unrolled_with_flamegraph`
- `simulate_witness_tracing` rewritten using `SimpleSnapshotter`

**cycle_marker:**
- Fully wired to new `CycleMarkerHooks` API from
[zksync-airbender#237](matter-labs/zksync-airbender#237)
- `print_cycle_markers` now takes a `CycleMarker` argument (scoped via
`CycleMarkerHooks::with()`)
- Runner uses `VM::<DelegationsCounters, CycleMarkerHooks>` when feature
is enabled
- Re-exports `CycleMarkerHooks`, `CycleMarker`, `Mark` from
`riscv_transpiler::cycle`
- Inline asm now uses hardcoded `x0` to match transpiler's strict `csrrw
x0, 0x7ff, x0` decoder

**forward_system:**
- All 12 query processors and system type aliases updated to non-generic
oracle types

**tests/rig:**
- `flamegraph_output` wired through to
`run_default_with_flamegraph_path` (replaces old `ProfilerConfig`)
- Oracle factory trait methods return non-generic
`ZkEENonDeterminismSource`
- `run_prover` rewritten to use
`execution_utils::unrolled::prove_unrolled_for_machine_configuration_into_program_proof`

**Other:**
- Removed stabilized `ptr_as_ref_unchecked` feature gate from
`evm_interpreter`
- Updated `Cargo.lock` for latest `zksync_os_interface` (adds
`pubdata_used` to `BlockOutput`)
- Rebuilt blake2s test binaries and committed `.text` files
- Fixed pre-existing clippy lints (`sort_by_key`,
`default_constructed_unit_structs`, `manual_checked_ops`, conditional
`P256VerifyErrors` import)

The `risc_v_simulator` crate was removed from zksync-airbender in
[zksync-airbender#233](matter-labs/zksync-airbender#233)
and
[zksync-airbender#235](matter-labs/zksync-airbender#235).
The new `riscv_transpiler` provides a more efficient VM with batch
execution, optional JIT compilation (x86_64), and integrated witness
snapshotting. This migration is required to stay on the airbender dev
branch.

- [x] Yes
- [ ] No

**Breaking API changes:**
- `zksync_os_runner::run()` and `run_and_get_effective_cycles()` no
longer take a `DiagnosticsConfig` parameter
- `run_and_get_effective_cycles_from_bytes()` now requires both
`img_bytes` and `text_bytes`
- `ZkEENonDeterminismSource`, `ReadWitnessSource`,
`OracleQueryProcessor` are no longer generic over memory type
- `cycle_marker::print_cycle_markers()` now takes a `CycleMarker`
argument instead of reading from a global
- `MemorySource` trait replaced by `RamPeek` (re-exported from
`riscv_transpiler::vm`)

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted.

---------

Co-authored-by: antoniolocascio <antonio.locascio1@gmail.com>
## What ❔

Move RISC-V binary artifacts from flat files in `zksync_os/` (e.g.
`for_tests.bin`) to a structured `dist/<app>/app.{bin,elf,text}` layout
(e.g. `dist/for_tests/app.bin`).

## Why ❔

This prepares for the airbender-platform migration where `cargo
airbender build` outputs to this layout natively. Splitting this out as
a separate PR keeps the platform migration PR focused on the actual API
changes.

## Changes

- `dump_bin.sh`: output to `dist/<app>/` instead of flat files
- `chain.rs`: add `get_zksync_os_dist_dir()`, update path resolution
- `binary_checker`: update paths to `dist/<app>/app.text`
- `reproduce.sh`: copy from `dist/<app>/app.bin`
- `.gitignore`: add `/dist`

## Is this a breaking change?
- [ ] Yes
- [x] No

The build script output changes but all consumers are updated in this
PR.

## Checklist

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: vibelyova <265594496+vibelyova@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## What ❔
- Removed unused storage-type markers/bitflags.
- Split `storage_types` into focused modules.
- Moved `MAX_EVENT_TOPICS` from storage types into system constants and
updated imports.

## Why ❔
- Reduces dead code and improves module structure.
- Places constants with the correct domain ownership for easier
maintenance.

## Is this a breaking change?
- [ ] Yes
- [x] No

## Checklist
- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [ ] Tests for the changes have been added / updated.
- [ ] Documentation comments have been added / updated.
- [x] Code has been formatted.
## What ❔

Add tests that verify the system correctly validates and rejects
invalid/malicious oracle responses. Covers two oracle validation areas:

**Block metadata gas limit validation (4 tests):**
- `test_block_rejects_excessive_gas_limit` — gas limit just above
`MAX_BLOCK_GAS_LIMIT` is rejected
- `test_block_accepts_max_gas_limit` — exact boundary value is accepted
- `test_block_rejects_u64_max_gas_limit` — extreme overflow value is
rejected
- `test_empty_block_rejects_excessive_gas_limit` — validation fires
before any transactions are processed

**DA commitment scheme validation (2 tests):**
- `test_da_commitment_scheme_accepts_all_valid_ids` — all valid IDs 0–4
are accepted
- `test_da_commitment_scheme_rejects_invalid_ids` — IDs 5, 128, 255 are
rejected

## Why ❔

Oracle responses come from an untrusted host and must be validated.
These tests confirm that existing validation logic correctly rejects
malicious metadata. Gas limit validation prevents resource accounting
overflow (ergs = gas × 256). DA commitment scheme validation prevents
use of undefined commitment modes.

## Is this a breaking change?
- [ ] Yes
- [x] No

## Checklist

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted.

---------

Co-authored-by: Claude Code <claude-code@anthropic.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Integrate airbender-platform into zksync-os (Phase 1), replacing direct
dependencies on `riscv_transpiler`, `execution_utils`, and
`prover_examples` with the platform's standardized build, execution, and
proving pipeline.

- `cargo airbender build` replaces `cargo build --target riscv32i` +
`cargo objcopy` in `dump_bin.sh`
- Target changed from `riscv32i-unknown-none-elf` to
`riscv32im-risc0-zkvm-elf`
- Build artifacts use `dist/<app>/` layout with `manifest.toml` (from
prep PR #614)

- `#[airbender::main(allocator_init = init_allocator)]` replaces manual
boot assembly, `.data`/`.rodata` section loading, custom
`memcpy.s`/`memset.s`, allocator init, and panic handler
- CSR read/write uses `airbender::rt::sys::{read_word, write_word}`
instead of `riscv_common`
- `heapless` dependency removed; `quasi_uart` simplified accordingly

- `TranspilerRunner` (via `Program::load` + `runner.run(&[u32])`)
replaces direct `VM` usage
- Runner now accepts pre-recorded `&[u32]` input instead of interactive
oracle sources
- `CpuProver` replaces manual `execution_utils` wiring for e2e proving
- `FlamegraphOptions` preserved as public API; flamegraph support now
unconditionally available via `airbender-host`

- RISC-V run now consumes `prover_input_forward` (pre-recorded words
from native run) directly
- Interactive oracle wrapping (`ReadWitnessSource`) removed from the
RISC-V run path
- `simulate_witness_gen` feature removed - it was already obsolete, now
became incompatible with new API
- eth_stf path: uses `EthereumStorageSystemTypesWithPostOps` with
`USE_ADVICE=true` and native callable oracles for prover-input recording

- Added: `airbender-guest`, `airbender-host`, `airbender-sdk` (from
`matter-labs/airbender-platform` rev `7e559f95`)
- Removed: `common_constants`, `prover_examples`, `execution_utils`,
`heapless`, `riscv_common`
- Kept: `riscv_transpiler` at rev `73f46c2b` (transitive via
`airbender-host`)

- All workflows install `cargo-airbender` and use it for RISC-V builds
- Blake test binaries built in CI instead of committed to git
- `ZKSYNC_USE_CUDA_STUBS=true` added to all workflows

- `EthereumStorageSystemTypesWithPostOps` changed `USE_ADVICE` from
`false` to `true` -- ensures prover-input recording makes the same
oracle advice queries (ecrecover/modexp) as the RISC-V proving binary
- Native callable oracles (`NativeArithmeticQuery`,
`NativeFieldOpsQuery`, `NativeBlobCommitmentAndProofQuery`) used for
eth_stf prover-input recording since there is no guest memory to read
during native execution
- The witness equality check (`prover_input_forward == proof_input`) was
removed -- in the new architecture the RISC-V run consumes
`prover_input_forward` directly, making the comparison tautological

- Crypto crate consolidation with `airbender-crypto`
- Wire format migration to airbender-platform codec

Airbender-platform provides a standardized, maintained build/run/prove
pipeline. Direct dependency on low-level transpiler internals is fragile
and duplicates platform functionality. This migration enables future
improvements (JIT execution, codec migration, GPU proving) with minimal
zksync-os changes.

- [x] Yes
- [ ] No

Wire format is unchanged (still `UsizeSerializable`). Binary target
changed from `riscv32i-unknown-none-elf` to `riscv32im-risc0-zkvm-elf`.

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted.

---------

Co-authored-by: vibelyova <265594496+vibelyova@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…630)

## What ❔

Two small related cleanups to CI:

1. **Consolidate the toolchain setup into a single composite action.**
The old `install-cargo-airbender` action only installed cargo-airbender,
so every job using it repeated the same rust + `cargo install
cargo-binutils` prelude. Rename to `.github/actions/setup-toolchain` and
fold the rust toolchain install + `cargo install cargo-binutils` into
it. The 3-step pattern at each call site becomes a single `uses:`.

2. **Migrate `bench-base` to `cargo airbender build`.** The merge-base
now includes the airbender-platform migration (#619) so the old
`riscv32i-unknown-none-elf` target-add + `|| for-tests` fallback are no
longer needed. Setup is kept inline in `bench-base` because that job
checks out the merge-base commit, which may predate the
`setup-toolchain` composite action itself.

## Why ❔

Less boilerplate; single place to pin the airbender-platform rev used by
CI.

## Is this a breaking change?
- [ ] Yes
- [x] No

## Checklist

- [x] PR title corresponds to the body of PR.
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted.

Co-authored-by: vibelyova <265594496+vibelyova@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
antoniolocascio and others added 16 commits April 23, 2026 11:34
…oop (#631)

## What ❔
Block-level overheads (pubdata encoding envelope, future pre-tx-loop
system work) must be visible to per-tx block-limit enforcement, not only
to the final reported value. Seed block_data.block_pubdata_used and
block_data.block_computational_native_used with BLOCK_INTRINSIC_*
constants at pre-tx-loop start so check_for_block_limits enforces the
true budget.

Plumb both counters out through the result keeper via new
record_block_native_used / record_block_pubdata_used hooks, so the
forward path's BlockOutput.{computational_native_used, pubdata_used} are
the bootloader's post-accumulation values rather than an independent
per-tx sum (native) or a zero placeholder (pubdata).
<!-- What are the changes this PR brings about? -->
<!-- Example: This PR adds a PR template to the repo. -->
<!-- (For bigger PRs adding more context is appreciated) -->

## Why ❔

<!-- Why are these changes done? What goal do they contribute to? What
are the principles behind them? -->
<!-- The `Why` has to be clear to non-Matter Labs entities running their
own ZK Chain -->
<!-- Example: PR templates ensure PR reviewers, observers, and future
iterators are in context about the evolution of repos. -->

## Is this a breaking change?
- [ ] Yes
- [ ] No

## Checklist

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [ ] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [ ] Tests for the changes have been added / updated.
- [ ] Documentation comments have been added / updated.
- [ ] Code has been formatted.
## What

Add Pectra (Prague) EVM execution compatibility to the ZK STF:

- **Move precompiles to shared location:** Relocate EIP-2537 (BLS12-381)
and EIP-152 (BLAKE2F) from `block_flow/ethereum/hooks/` to
`bootloader/hooks/`, making them usable by both ZK and Ethereum STFs.
The Ethereum hooks module re-exports from the shared location behind
feature gates.
- **Add `pectra` composite feature flag:** Enables all
execution-affecting Pectra EIPs (`eip-7702`, `eip_7623`, `eip-4844`,
`eip-2537`, `eip-152`). Propagated through `forward_system`, `rig`, and
`evm_tester` crates. Also updates `eth_stf` to include the new
`basic_bootloader` feature flags.
- **Register precompiles in ZK STF:** Feature-gated initialization of
BLS12-381 and BLAKE2F precompiles in `zk/post_init_op.rs`.
- **Add `--hardfork` CLI flag to EVM tester:** Global override that
takes precedence over per-test/per-directory hardfork settings, enabling
`--hardfork Prague` runs. Balance check logic updated to allow full
checking for Prague.

## Why

The ZK STF (production) only supports Cancun, while the Ethereum STF
(unreviewed) already has Pectra. We need Pectra execution compatibility
in the ZK STF without taking unreviewed code to production. EIP-7702,
EIP-7623, and EIP-4844 were already implemented behind feature flags —
this PR moves the remaining precompiles (BLS12-381, BLAKE2F) to a shared
location and wires up a single `pectra` feature to enable everything.

Usage:
```bash
cargo run --bin evm-tester --release \
  --features "zksync_os_forward_system/evm_tester_pectra,zksync_os_forward_system/no_print" \
  -- --hardfork Prague
```

## Is this a breaking change?
- [ ] Yes
- [x] No

## Checklist

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [ ] Tests for the changes have been added / updated.
- [ ] Documentation comments have been added / updated.
- [x] Code has been formatted.

---------

Co-authored-by: Antonio Locascio <antoniolocascio@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## What ❔

Follow-up cleanup after #619 (airbender-platform migration). Builds on
#630 (composite toolchain action + `bench-base` migration), which was
split out and merged separately into `draft-0.4.0`.

### CI
- **Drop the 10× crypto test loop** — run once, without `--quiet` so
failures are readable.
- **Remove `-j 3` throttling** across `ci.yml` and `bench.yml`. The flag
caps `cargo`'s *build* parallelism to 3 and has no effect on test
determinism (that would be `--test-threads`). The CI runners have plenty
of cores.
- **Speed up fuzzer regression**:
- `cargo fuzz build -s none` drops AddressSanitizer for regression
replay; this also skips the implicit `-Zbuild-std` (stdlib rebuild).
- Drop the redundant `dump_bin.sh --type for-tests` step — `fuzz.sh
regression` already does it via `prepare()`.
- Replace `fuzz.sh install` (reinstalls cargo-binutils, cargo-airbender,
rustfilt, lcov-util, and npm @lcov-viewer/cli) with a targeted `cargo
install cargo-fuzz --locked`.
- **Simplify `bench-base`** — now that the composite `setup-toolchain`
action exists in the merge-base (#630), use it instead of inlining the
rust + cargo-airbender setup.

### `reproduce.sh` rewrite
Replace the Dockerfile-based reproduce pipeline with `cargo airbender
build --reproducible` (which spawns its own pinned container per build
and shares a cargo registry volume across builds).
- Drop `zksync_os/reproduce/Dockerfile`.
- `reproduce.sh` regenerates both `Cargo.lock` files (workspace +
guest), then runs `dump_bin.sh --type <t> --reproducible` sequentially
for every app type.
- Sequential, not parallel: concurrent `--reproducible` builds race on
the shared `airbender-cargo-registry` Docker volume (`.cargo-ok` /
`.cache` mkdir conflicts). Proper fix belongs in `cargo-airbender`
(multi-binary-per-container support).
- Copy `dist/<app>/app.bin → zksync_os/<app>.bin` at the end for
backwards compatibility with downstream consumers (release workflow,
zksync-era).

### `zksync_os_runner` API cleanup
Collapse `run` / `run_and_get_effective_cycles` / `run_with_flamegraph`
into a single builder:
```rust
zksync_os_runner::Runner::new(dist_dir)
    .with_cycles(1 << 25)                    // optional; default 1 << 36
    .with_flamegraph(opts)                   // optional
    .run(&input_words);                      // -> RunResult { output, block_effective }
```
The default cycle limit is `1 << 36`, which is what every non-test
caller was passing. `block_effective` is only populated when the
`cycle_marker` feature is enabled.

### Script / binary cleanup in `zksync_os/`
- Delete stale helper scripts (`dump_bin_manual.sh`, `objdump.sh`,
`objdump_manual.sh`, `sections_layout.sh`, `show_asm.sh`,
`build_release_std.sh`, `dump_bin_no_delegation.sh`) — all referenced
the obsolete `riscv32i-unknown-none-elf` target, the `_manual` variants
hardcoded macOS toolchain paths, and they don't work with the new `cargo
airbender build` flow.
- Fix `upd_local_era.sh` — source paths (`singleblock_batch.bin`) were
broken since the move to `dist/<app>/app.bin` layout.

### Misc
- Replace the local `QuasiUART` with airbender-platform's
implementation.
- Bump `airbender-platform` to `097f1489`.

## Why ❔

Cleaner post-migration state, and CI savings on jobs where every minute
counts (fuzzer, bench).

## Is this a breaking change?
- [ ] Yes
- [x] No

(`zksync_os_runner` API change affects only in-repo callers, all updated
here.)

## Checklist

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted.

---------

Co-authored-by: Antonio Locascio <antonio.locascio1@gmail.com>
Co-authored-by: vv-dev-ai <vv@matterlabs.dev>
Co-authored-by: Claude Code <claude-code@anthropic.com>
Co-authored-by: Vladislav Volosnikov <Volosnikov.apmath@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Lyova Potyomkin <lyova.potyomkin@gmail.com>
Co-authored-by: vibelyova <265594496+vibelyova@users.noreply.github.com>
## What ❔

Bumps `airbender-platform` dependency from `097f1489` to `ff643be8`
across all Cargo.toml files.

## Why ❔

Latest changes in `zksync-airbender` cause `airbender-platform` to not
compile. This commit pins `zksync-airbender` in `airbender-platform`.
Bench-base will still fail

## Is this a breaking change?
- [ ] Yes
- [x] No

## Checklist

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [ ] Tests for the changes have been added / updated.
- [ ] Documentation comments have been added / updated.
- [x] Code has been formatted.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: vibelyova <265594496+vibelyova@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## What ❔

Removes the unused `callable_oracles::hash_to_prime` module and tightens
`read_memory_as_u8` to require word-aligned offsets.

## Why ❔

`hash_to_prime` is not registered in the callable oracle wiring and its
evaluator was unfinished. The only remaining caller of
`read_memory_as_u8` already requires a 4-byte aligned pointer, so the
helper now asserts the same contract instead of carrying an unused
unaligned branch.

## Is this a breaking change?
- [ ] Yes
- [x] No

## Checklist

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted.
## What ❔

Migrate from the local `crypto` crate to the upstream `airbender-crypto`
from `airbender-platform`. The local crate is deleted and replaced with
a workspace dependency using `package = "airbender-crypto"` aliased as
`crypto` to avoid renaming imports.

Depends on: matter-labs/airbender-platform#58

## Why ❔

Consolidate cryptographic primitives in a single upstream crate
(`airbender-crypto`) instead of maintaining a local fork. The upstream
crate now includes hook support for oracle-based EC field operations
needed by proving mode.

## Changes

- Add `crypto` workspace dependency pointing to `airbender-crypto` via
git
- Delete local `crypto/` directory (109 files)
- Update all per-crate Cargo.toml to use workspace dependency
- Update `callable_oracles` field hints: method renames
(`sqrt_in_place_inner` → `sqrt_in_place`, `invert_in_place_inner` →
`invert_in_place`)
- Update `ecrecover`: use `recover_with_hooks` for oracle path, hookless
`recover` for non-oracle path
- Update import paths: `crypto::secp256k1::FieldElement` →
`crypto::secp256k1::field::FieldElement` (types not re-exported at
secp256k1 level in airbender-crypto)
- Update `crypto::sha3::Digest` → `crypto::MiniDigest` (Digest trait
re-export changed)

## Is this a breaking change?
- [ ] Yes
- [x] No

## Checklist

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted.

---------

Co-authored-by: vibelyova <265594496+vibelyova@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## What ❔

Migrates the EVM interpreter from `ruint::aliases::U256` to the custom
non-`Copy` `u256::U256` and adds oracle-backed advice for MULMOD and DIV
opcodes.

### Custom U256 migration (from PR #588, #598)
- Custom U256 utilities in `zk_ee` (`custom_u256_utils`)
- EVM interpreter stack, opcode, and frame state migration to non-Copy
U256
- Forward system tracer boundary adaptation (lazy conversion to alloy
U256)
- Delegation feature wiring through the proving path
- `push_u64`/`push_b160` for direct small-value stack writes
- Specialized PUSH1 to skip bytereverse+shift overhead
- Environment opcodes (chainid, timestamp, etc.) use
`push_u64`/`push_b160`

### Oracle-backed MULMOD and DIV advice
- New `U256_MULMOD_ADVICE_QUERY_ID` and `U256_DIV_REM_ADVICE_QUERY_ID`
oracle queries
- IOOracle-based advice functions in
`zk_ee::utils::u256_arithmetic_advice` that work on both RISC-V and
native (no raw CSR — uses `IOOracle::raw_query`)
- Value-based query format (limbs serialized directly via
`UsizeSerializable`) — same handler works for both `ArithmeticQuery` and
`NativeArithmeticQuery`
- `NativeArithmeticQuery` extended to serve both query IDs, keeping
witness streams synchronized between RISC-V simulation and native
prover-input runs

### Performance optimizations
- `widening_mul_assign_into` with both halves from limbs instead of
`widening_mul_assign`
- Direct sub+borrow for `r < d` checks instead of `Ord::cmp` (saves 1 EQ
delegation)
- `write_be_bytes_into` for LOG topics and storage opcode boundary
conversions (avoids clone+bytereverse delegation)
- Limb-by-limb `i256_cmp` avoids clone+sub delegation in SLT/SGT
same-sign comparison
- `UsizeDeserializable` impl for `[T; N]` arrays

## Why ❔

The proving-oriented custom U256 reduces RISC-V cycle count by routing
arithmetic through the prover's bigint delegation circuit instead of
software implementations. Oracle advice replaces expensive software
division (especially 512÷256 for MULMOD) with a hint+verify pattern that
costs fewer delegation calls.

## Is this a breaking change?
- [ ] Yes
- [x] No

## Checklist

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted.

---------

Co-authored-by: vibelyova <vibelyova@proton.me>
Co-authored-by: vibelyova <265594496+vibelyova@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
#646)

## What ❔

Specialize the PUSH2 opcode in the EVM interpreter, mirroring the
existing PUSH1 specialization.

The generic `push<const N: usize>()` path copies bytecode bytes into a
`U256`, byte-reverses the full 32-byte value, and right-shifts off the
unused high bytes. For a 2-byte payload that already fits in a `u64`,
all of that is wasted work.

The new `push2()`:
- Reads up to 2 big-endian bytes from the bytecode (zero-padding missing
trailing bytes, matching the generic path's right-padding semantics on
truncated bytecode).
- Assembles a `u64` and pushes it directly via `EvmStack::push_u64`.
- Bypasses the U256 copy + bytereverse + shift.

Dispatch in `interpreter.rs` swaps `self.push::<2>()` for
`self.push2()`.

## Why ❔

PUSH2 was the third-largest sampled opcode cost in profiling of the
`custom-u256` branch (~5.2% of opcode cycles in `block_19299001`), and
the structure of the work matched the PUSH1 specialization pattern
already in the tree. Removing the bytereverse + shift round-trip brings
PUSH2 to parity with PUSH1 in cycles, which translates to a measurable
block-level reduction in proving cost.

### Benchmark

`bench_scripts/bench.sh compare`, baseline = `custom-u256` at HEAD:

| Block | Base Eff | Head Eff | Δ |
|-------|----------|----------|---|
| `block_19299001` | 210,947,355 | 208,664,035 | **−1.08%** |
| `block_22244135` | 139,404,849 | 134,713,085 | **−3.37%** |

Per-opcode (block_19299001, 107,945 PUSH2 executions):
- PUSH2 median cycles: 144 → 67 (**−48.5%**)
- PUSH2 total cycles: −7.23M (−48.8%)
- Delegations (Blake / BigInt / Keccak): unchanged
- No regressions visible on other opcodes (noise only on low-count ops)

Note: `block_23292836` fixture is missing locally so it's not in the
comparison.

## Is this a breaking change?
- [ ] Yes
- [x] No

No protocol-visible behavior change. Gas and native cost charging are
identical (`gas_constants::VERYLOW`, `PUSH_NATIVE_COSTS[2]`). The pushed
value is bit-for-bit identical to the generic path on all inputs,
including the truncated-bytecode edge case where the missing low byte is
zero-padded.

## Checklist

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- Existing tests cover PUSH2 behavior (Ethereum spec fixtures +
interpreter rig tests). No semantic change → no new tests needed.
Verified locally: `cargo test -p evm_interpreter` (13/13),
`tests/instances/evm` (14/14), `tests/instances/unit` (46/46).
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
## What ❔

Move `evm_tester`, `evm_divergence_validator`, `eth_runner`, and
`nostd_compression` from workspace `exclude` into `members`, and
introduce `default-members`. Only `zksync_os` and `circuit_test_program`
(RISC-V targets) remain excluded.

`default-members` includes all previously-existing workspace members
(core crates + test infrastructure + test instances). The three newly
added tool crates (`evm-tester`, `evm_divergence_validator`,
`eth_runner`) are non-default because they enable conflicting features
on `forward_system` via `rig` that break other tests through workspace
feature unification. They have their own dedicated CI jobs.

Changes:
- Relax `evm_tester` exact version pins, convert shared deps to
`workspace = true`
- Remove `web3` dependency from `evm_tester` (replaced with `alloy`
types), eliminating vulnerable transitive deps (`idna`, `rustls-webpki`)
- Convert `eth_runner` and `evm_divergence_validator` deps to workspace
refs
- Remove standalone `Cargo.lock` files (now using workspace lockfile)
- Set `airbender-host` `default-features = false` at workspace level;
`zksync_os_runner` explicitly opts into `gpu-prover`
- Fix all clippy warnings in newly added crates
- Add CI clippy and cargo-deny jobs for the excluded `zksync_os` RISC-V
crate
- Fix pre-existing clippy issues (`useless_conversion` in
`mock_precompiles`, `unit_arg` in `zksync_os`)

## Why ❔

Previously excluded crates had independent dependency resolution,
duplicated `Cargo.lock` files, couldn't use `[workspace.dependencies]`
or `[patch]`, and weren't covered by `cargo-deny` or `clippy`. Moving
them into the workspace gives unified dependency management, removes
~16k lines of duplicated lockfile, and surfaces vulnerabilities that
were previously hidden.

## Is this a breaking change?
- [ ] Yes
- [x] No

## Checklist

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [ ] Tests for the changes have been added / updated.
- [ ] Documentation comments have been added / updated.
- [x] Code has been formatted.

---------

Co-authored-by: vibelyova <265594496+vibelyova@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## What ❔

Adds four cycle-marker labels in the STF that the benchmarking pipeline
relies on:

- `keccak_execution_environment` — wraps the EVM SHA3 opcode dispatch
(incl. the `len == 0` empty-slice shortcut)
- `ecrecover_execution_environment` — wraps the EE-precompile ecrecover
dispatch via a new `EcRecoverEEInvocation` wrapper
- `da_commitment` — wraps the per-block `write_pubdata` call (keccak-DA
absorbs there; blob-DA appends + KZG fires later under the pre-existing
`blob_versioned_hash` marker)
- `state_commitment_update` — renamed from `verify_and_apply_batch` to
reflect what the marker actually wraps (the state-tree merkle commit,
distinct from DA commit and per-blob KZG)

Also extracts `install_precompile_hook` from `add_precompile_ext` so the
`PRECOMPILE_ADDRESSES_LOWS` sanity check stays centralized for any
future custom invocation type.

## Why ❔

Split out from #645 so the STF instrumentation can be reviewed without
wading through the CI workflow, joiner scripts, tracers, and docs that
consume the markers. Pure observability: no state-transition behavior
changes. The new markers fire only on EE-initiated invocations, so they
don't double-count the bootloader's intrinsic keccak/ecrecover calls.
The benchmarking pipeline (CI + bench_scripts + forward-system tracers +
docs) follows in a separate PR rebased onto this branch.

## Is this a breaking change?
- [ ] Yes
- [x] No

## Checklist

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
## What ❔

End-to-end benchmark pipeline that consumes the STF cycle markers added
in #656.

- `cycle_marker`: per-execution `<label>.cycles` (raw) and
`<label>.effective.cycles` (raw + delegation weights) dumps; weighting
uses the existing `process_block` formula (`raw + 16×Blake + 4×BigInt +
4×Keccak`).
- `forward_system`: `Pair` tracer combinator + `PrecompileStatsTracer`
(per-precompile gas/native, dump samples parallel to
`EvmOpcodeStatsTracer`).
- `bench_scripts/`: shared `benchlib.py`; `compare_*` / `join_*`
scripts; `cycles_per_native_report.py` for local cycles/native ratio
reports.
- Test scaffolding: `tests/rig/src/chain.rs` `SeqLabelsGuard` (needed
under `BlobsZKsyncOS` DA where `blob_versioned_hash` fires only in
proving mode); `eth_runner` tracer composition + `BENCH_DA_SCHEME`;
precompile sweep tests.
- `.github/workflows/bench.yml`: full bench job — both DA schemes,
`for-tests-benchmarking-pectra` proving binary, headline + collapsible
PR comment, merge-base fallbacks for graceful degradation against older
base commits.
- `bench-fast` profile (root + `eth_runner` mirror) to speed up
host-side bench builds.
- `docs/benchmarking.md`: rewrite as agent-targeted reference.

## Why ❔

Split from the original #645 so reviewers can scrutinize the STF
instrumentation in #656 (the small / security-relevant half) separately
from this pipeline scaffolding (CI/scripts/tracers/docs/test rigging —
review-skim). Once #656 lands, this PR's base auto-retargets to
`draft-0.4.0`.

## Is this a breaking change?
- [ ] Yes
- [x] No

## Checklist

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
## What ❔

`apply_write_impl` returned `(V, V)` where the second element
(`val_at_tx_start`) was ignored at all three callers (one had
`#[allow(unused_variables)]`, two used `_`). Drop it.

With the second return gone, `refund_for_storage_write` is moved before
`addr_data.update(...)` so `val_at_tx_start` and `val_current` can stay
borrowed straight from `addr_data` — eliminating the
`val_at_tx_start.clone()` and the redundant
`addr_data.current().value().clone()`. Body V clones: 2 → 1.

## Why ❔

Reduces wasted work in the SSTORE / SLOAD hot path. The cleanup also
removes an `#[allow(unused_variables)]` smell at the caller site.

Bench (`bench_scripts/bench.sh` on `block_19299001` / `block_22244135`):

| Block | Eff cycles Δ | Raw cycles Δ |
|---|---|---|
| `block_19299001` | −0.036% (−74K) | −0.047% (−74K) |
| `block_22244135` | −0.037% (−49K) | −0.046% (−49K) |

Per-opcode: `SSTORE` median −3.8% (2,355 → 2,266), total −3.5% (~85K
cycles across 950 SSTOREs). All Blake / BigInt / Keccak delegation
counts unchanged — no behavior drift in the proven path.

## Is this a breaking change?
- [ ] Yes
- [x] No

(Internal API — only the three in-tree callers of `apply_write_impl`.)

## Checklist

- [x] PR title corresponds to the body of PR.
- [x] Tests for the changes have been added / updated. (No new tests;
existing `basic_system` unit suite + block replay cover the path.
Pre-existing MPT test failures on `draft-0.4.0` are unrelated and
reproduce on the unmodified parent branch.)
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
## What ❔

Replaces `Bytes32`'s `Ord` impl on **the RISC-V proving target only**
with a word-by-word equality scan over the underlying `inner: [usize;
BYTES32_USIZE_SIZE]` (N=4 on 64-bit, 8 on RISC-V32):

- Equal-prefix iterations stay in the fast path: load word, compare
word, branch.
- On the first differing word, resolve byte-lex order by walking the
bytes of just that word — cheaper than `swap_bytes()` on RV32 without
the Zbb extension (which this target does not enable).
- `cmp` / `partial_cmp` are `#[inline]` since they sit on the BTreeMap
descent hot path.

On non-RV32 targets (forward / sequencer host) the impl falls back to
the original `as_u8_array_ref().cmp(...)`. libc's `memcmp` is already
SIMD-vectorized (SSE2/AVX/NEON), so the byte path beats a pure-Rust word
loop on the host. The chunked helper (`cmp_word_chunked`) is still
compiled on every target so the equivalence tests can validate it on the
host.

Affected:
- `zk_ee/src/utils/bytes32.rs`

## Why ❔

From the flamegraph analysis on `draft-0.4.0`:

- `impls::compare_bytes` is the **second-highest self-cost function in
the binary at 6.47 %**. On no-std RISC-V the `<[u8]>::cmp` path falls
back to `compiler-builtins`' generic `memcmp`
(`compiler-builtins/src/mem/impls.rs:388`) — a plain byte loop with no
chunking.
- Almost all of that self-cost is reached through `Bytes32::cmp`
(directly, or via `WarmStorageKey::cmp` → `Bytes32::cmp`) sitting inside
`NodeRef::find_key_index` in HistoryMap / preimage /
FlatStorageCommitment lookups.

Comparing word-aligned 32-byte values byte-by-byte is wasteful when the
struct is already a `[usize; N]` with `align(8)`. Forward mode doesn't
need the rewrite because libc memcmp already handles it efficiently.

## Benchmark results

Branch vs `origin/draft-0.4.0` (commit `59bdedfa`):

| Block | Base eff | Head eff | Δ eff | Δ raw |
|---|---|---|---|---|
| `19299001` | 208,601,280 | 204,648,699 | **−1.89 %** | **−2.49 %** |
| `22244135` | 134,741,585 | 132,504,954 | **−1.66 %** | **−2.10 %** |

Blake / Bigint / Keccak delegation counts unchanged in both runs — pure
raw-cycle reduction.

### Variant comparison (RV32 only — host path is unchanged)

| Variant | block 19299001 Δ eff | block 22244135 Δ eff |
|---|---|---|
| word-cmp + `to_be()` bswap on mismatch | −1.56 % | −1.39 % |
| **word-cmp + `#[inline]` + byte-fallback (this PR)** | **−1.89 %** |
**−1.66 %** |
| word-cmp + 2-word XOR-OR fusion | −1.68 % | −1.45 % |

The 2-word XOR-OR variant regresses vs the simple loop — the extra
arithmetic per executed iteration doesn't pay for the halved branch
count on RV32. Picked the byte-fallback variant.

## Is this a breaking change?
- [ ] Yes
- [x] No

Public API of `Bytes32` is unchanged. `Ord` / `PartialOrd` impls produce
identical orderings to the previous implementation on every target
(verified by `cmp_tests::cmp_matches_byte_lex_on_pseudorandom_pairs`,
which invokes `cmp_word_chunked` directly so the helper is exercised on
the host too).

## Stackability with #668 / #669

This PR targets the leaf `compare_bytes` cost; #668 / #669 target the
BTreeMap lookups themselves on the pending-list paths. They hit
different code regions and are expected to compose (overlap only where
BTreeMap node descent invokes `Bytes32::cmp` — and even there the
per-compare cost goes down).

## Checklist

- [x] PR title corresponds to the body of PR.
- [x] Tests for the changes have been added / updated. (Equivalence
tests added: `cmp_matches_byte_lex_on_handcrafted_pairs`,
`cmp_matches_byte_lex_on_pseudorandom_pairs`. Both invoke
`cmp_word_chunked` directly so the chunked path is exercised on the
host.)
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
## What ❔

Adds FRI precompile to zksync-os.
FRI proofs submitted in the sidecar with FRI transactions are checked
during transaction validation and the call to precompile within the same
transaction reveals whether the proof is valid (under current
assumptions, transactions that include invalid proofs are dropped from
the block).
<!-- What are the changes this PR brings about? -->
<!-- Example: This PR adds a PR template to the repo. -->
<!-- (For bigger PRs adding more context is appreciated) -->

## Why ❔

The goal is to add a new tx type, that would allow GW users to submit
FRI proofs along the transaction in the sidecar. This would in turn,
enable faster interop.
<!-- Why are these changes done? What goal do they contribute to? What
are the principles behind them? -->
<!-- The `Why` has to be clear to non-Matter Labs entities running their
own ZK Chain -->
<!-- Example: PR templates ensure PR reviewers, observers, and future
iterators are in context about the evolution of repos. -->

## Is this a breaking change?
- [x] Yes
- [ ] No

## Checklist

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted.

---------

Co-authored-by: Antonio Locascio <antonio.locascio1@gmail.com>
Co-authored-by: vv-dev-ai <vv@matterlabs.dev>
Co-authored-by: Claude Code <claude-code@anthropic.com>
Co-authored-by: Vladislav Volosnikov <Volosnikov.apmath@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Lyova Potyomkin <lyova.potyomkin@gmail.com>
Co-authored-by: vibelyova <vibelyova@proton.me>
Co-authored-by: vibelyova <265594496+vibelyova@users.noreply.github.com>
## What ❔

Migates to interface v0.1.3

## Why ❔

<!-- Why are these changes done? What goal do they contribute to? What
are the principles behind them? -->
<!-- The `Why` has to be clear to non-Matter Labs entities running their
own ZK Chain -->
<!-- Example: PR templates ensure PR reviewers, observers, and future
iterators are in context about the evolution of repos. -->

## Is this a breaking change?
- [ ] Yes
- [x] No

## Checklist

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [ ] Tests for the changes have been added / updated.
- [ ] Documentation comments have been added / updated.
- [x] Code has been formatted.
## What ❔

Brings the **Fusaka (Osaka)** hardfork to `draft-0.4.0` — validated on
the Ethereum execution-spec tests and benchmarked on real post-BPO
mainnet blocks.

**EIPs** (rebased from #589; the ~29 Pectra-groundwork commits are
dropped — already on `draft-0.4.0` via #552):
EIP-7939 (CLZ), 7823 (modexp input limit) + modexp repricing, 7825
(per-tx gas cap), 7934 (block RLP limit), 7918 (blob base-fee reserve),
per-tx blob validation, behind a `fusaka` feature flag.

**Validation**
- EVM execution-spec tester now defaults to Fusaka and is **green** (0
failures). Required fixing the EIP-7623 intrinsic-native bound,
cache-warmth tracking, and mock-precompile gating; the latest BPO blob
schedule sits behind a compile-time `fusaka-blobs` feature. Intentional
L2 divergences (beacon-chain L1 requests / withdrawals) and two
replay-unsupported EIP-7934 cases are suppressed in the indexes.
- Benchmarks now run **ten representative Osaka blocks** (covering
EIP-7702, BLOCKHASH, blob/BPO, BLS12-381, precompiles), replacing the
two Cancun fixtures. Each passes forward execution + RISC-V proving
against the Ethereum reference.

**`eth_runner` replay fixes** (needed to bench real Osaka blocks):
process EIP-7702 (type-4) txs, supply the 256 `BLOCKHASH` ancestors,
compute the blob base fee with the fork's
`BLOB_BASE_FEE_UPDATE_FRACTION`, and correct prestate reconstruction for
accounts created mid-block, and capture EIP-7702 delegate-target code
the prestate tracer omits. The bench PR comment now reports the
per-block **average** cycles, with the per-block breakdown under a
spoiler.

## Why ❔

Lands the Fusaka EIPs on the current base without re-introducing
already-present Pectra changes, and backs them with spec-test +
real-block-replay validation so the Osaka semantics are proven correct
on the RISC-V proving target. The Osaka bench fixtures keep performance
tracking representative of current mainnet.

## Is this a breaking change?
- [x] Yes
- [ ] No

## Checklist

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted.

---------

Co-authored-by: Antonio Locascio <antoniolocascio@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants