This workspace contains code for executing Ethereum block validation logic within different Zero-Knowledge Virtual Machines (zkVMs) where the input is generated by the execution spec tests.
The primary goal is to measure and compare the performance (currently in cycle counts) of running a standardized benchmarking workload (including known worse-cases) with the same stateless validation logic* across various zkVM platforms.
*We cannot guarantee the logic will be the same for targets that are not supported by the Rust toolchain. An example of this currently is Cairo.
The workspace is organized into several key components:
crates/metrics
: Defines common data structures (BenchmarkRun<Metadata>
) for storing and serializing benchmark results with generic metadata support.crates/witness-generator
: A library that provides functionality for generating benchmark fixture files (BlockAndWitness
: individual block + witness pairs) required for stateless block validation by processing standard Ethereum test fixtures or RPC endpoints.crates/witness-generator-cli
: A standalone binary that uses thewitness-generator
library to generate fixture files. These are saved in thezkevm-fixtures-input
folder. The crate includes Docker support for containerized deployment.crates/ere-hosts
: A standalone binary that runs benchmarks across different zkVM platforms using pre-generated fixture files fromzkevm-fixtures-input
.crates/benchmark-runner
: Provides a unified framework for running benchmarks across different zkVM implementations, including guest program input generation and execution orchestration.ere-guests/
: Directory containing guest program implementations organized by program type, with each type containing implementations for different zkVM platforms. See the Guest Program Types section for detailed information about each type.zkevm-fixtures
: (Git submodule) Contains the Ethereum execution layer test fixtures used bywitness-generator-cli
.zkevm-fixtures-input
: Default directory wherewitness-generator-cli
saves individual fixture files (.json
) that are consumed byere-hosts
.zkevm-metrics
: Directory where benchmark results (cycle counts) are stored by the host programs, organized by zkVM type.scripts
: Contains helper scripts (e.g., fetching fixtures).xtask
: Cargo xtask runner for automating tasks.
The benchmarking process is decoupled into two distinct phases:
- Fixture Generation (
witness-generator-cli
): Processes Ethereum test fixtures (EEST) or RPC data to generate individualBlockAndWitness
fixtures as JSON files saved inzkevm-fixtures-input/
. - Benchmark Execution (
ere-hosts
): Reads fromzkevm-fixtures-input/
and runs performance benchmarks across different zkVM platforms.
This decoupling provides several benefits:
- Independent fixture generation and benchmark execution
- Reuse of generated fixtures across multiple benchmark runs
Each zkVM benchmark implementation follows a common pattern using the EreDockerized system:
-
Guest Program:
- Located within the
ere-guests/
directory, organized by guest program type and execution client (for stateless-validator). - For stateless validator programs: Contains implementations for different execution clients (
reth/
andethrex/
) with each supporting multiple zkVMs. - For other program types: Contains implementations organized by zkVM platform.
- All guest programs are automatically compiled in Docker containers specific to each zkVM platform.
- Guest programs use platform-specific mechanisms to delineate code regions for cycle counting.
- This code is compiled automatically for the target zkVM's architecture through EreDockerized containers.
- It reads block/witness data from its zkVM environment's standard input.
- Uses platform-specific mechanisms (often
println!
markers) to delineate code regions for cycle counting.
- Located within the
-
Host Program:
- Located within
crates/ere-hosts/
with unified logic across all zkVM platforms. - A standalone Rust binary that orchestrates benchmarking for different guest program types and execution clients.
- Uses the
benchmark-runner
crate with EreDockerized to automatically compile and execute guest programs. - Supports multiple guest program types via command-line arguments (e.g.,
stateless-validator
,empty-program
). - For stateless-validator, supports multiple execution clients (
--execution-client reth
or--execution-client ethrex
). - Automatically handles zkVM compilation and execution through Docker containers.
- Collects cycle count metrics reported by each zkVM platform.
- Saves results using the
metrics
crate into the appropriate subdirectory withinzkevm-metrics/
.
- Located within
-
Automatic zkVM Management:
- All zkVMs are now managed through EreDockerized, eliminating the need for manual toolchain setup.
- Docker containers handle compilation, patching, and execution for each zkVM platform.
- The benchmark runner automatically applies precompile patches as needed.
- Rust Toolchain: A standard Rust installation managed by
rustup
. - Docker: All zkVMs now use EreDockerized, which means you don't need to install zkVM-specific toolchains locally. Docker handles all the compilation and execution environments.
- Git: Required for cloning the repository.
- Common Shell Utilities: The scripts in the
./scripts
directory require abash
-compatible shell and standard utilities likecurl
,jq
, andtar
.
-
Clone the Repository:
git clone <repository-url> cd zkevm-benchmark-workload
-
Fetch/Update Benchmark Fixtures:
./scripts/download-and-extract-fixtures.sh
-
Generate Benchmark Input Files:
Generate fixture files:
cargo run --release -- tests --include 10M- --include Prague # Or generate from local EEST fixtures cargo run --release -- tests --eest-fixtures-path /path/to/local/eest/fixtures # Or generate from RPC cargo run --release -- rpc --last-n-blocks 2 --rpc-url <your-rpc-url> # Or listen for new blocks continuously cargo run --release -- rpc --follow --rpc-url <your-rpc-url>
This creates individual
.json
files in thezkevm-fixtures-input/
directory that will be consumed by the benchmark runner. -
Patching Precompiles: Each zkVM requires particular dependencies to be patched for efficiency purposes. This repository contains an
xtask
that will automate this process by callingcargo <zkvm-name>
. See.cargo/config.toml
for how this is setup andprecompile-patches/
for the patches that each zkVM requires. -
Run Benchmarks:
Navigate to
crates/ere-hosts/
and run benchmarks using the generated fixture files. You must specify which guest program type to benchmark. All zkVMs are now dockerized, so no additional setup is required:cd crates/ere-hosts # Run Ethereum stateless validator benchmarks with Reth execution client cargo run --release -- --zkvms risc0 stateless-validator --execution-client reth # Run Ethereum stateless validator benchmarks with Ethrex execution client cargo run --release -- --zkvms sp1 stateless-validator --execution-client ethrex # Run empty program benchmarks (for measuring zkVM overhead) cargo run --release -- empty-program # Run block encoding length benchmarks (with RLP encoding format) cargo run --release -- block-encoding-length --loop-count 100 --format rlp # Run block encoding length benchmarks (with SSZ encoding format) cargo run --release -- block-encoding-length --loop-count 100 --format ssz # Use custom input folder for stateless validator benchmarks cargo run --release -- stateless-validator --execution-client reth --input-folder my-fixtures
See the respective README files in each crate for detailed usage instructions.
This repository supports multiple guest program types for comprehensive zkVM benchmarking across different computational workloads. Each guest program type is designed to measure specific aspects of zkVM performance:
-
stateless-validator
- The primary benchmarking workload that executes Ethereum stateless block validation logic- Purpose: Measures zkVM performance on realistic Ethereum state transition computations
- Input: Requires
BlockAndWitness
fixture files generated bywitness-generator-cli
- Computation: Validates Ethereum blocks using either Reth or Ethrex execution clients
- Execution Clients:
reth
: Usesreth_stateless::validation::stateless_validation
ethrex
: Uses Ethrex's stateless validation implementation
-
empty-program
- Minimal program for measuring zkVM overhead- Purpose: Measures the baseline overhead of zkVM execution without computational workload
- Input: No input files required
- Computation: Minimal operations to establish zkVM baseline performance
- Usage:
cargo run -- empty-program
-
block-encoding-length
- Measures block encoding performance with support for both RLP and SSZ formats- Purpose: Benchmarks the performance of calculating encoded length of Ethereum blocks using different encoding formats
- Input: Uses the same
BlockAndWitness
fixture files asstateless-validator
- Computation: Repeatedly calls encoding length calculation functions on block headers and bodies
- Encoding Formats: Supports both RLP (
--format rlp
) and SSZ (--format ssz
) encoding - Usage:
cargo run -- block-encoding-length --loop-count 100 --format rlp
Each guest program type follows a consistent structure across different zkVM platforms. For stateless-validator
, there are separate implementations for different execution clients:
ere-guests/<program-type>/
├── reth/ # Reth execution client implementations
│ ├── sp1/ # SP1 zkVM implementation
│ │ ├── Cargo.toml
│ │ └── src/main.rs
│ ├── risc0/ # RISC0 implementation
│ ├── openvm/ # OpenVM implementation
│ ├── pico/ # Pico implementation
│ └── zisk/ # Zisk implementation
├── ethrex/ # Ethrex execution client implementations
│ ├── sp1/ # SP1 zkVM implementation
│ ├── risc0/ # RISC0 implementation (if available)
│ └── ... (other zkVMs)
└── ... (other execution clients)
For other guest program types (e.g., empty-program
, block-encoding-length
):
ere-guests/<program-type>/
├── sp1/ # SP1 implementation
├── risc0/ # RISC0 implementation
├── zisk/ # Zisk implementation
└── ... (other zkVMs)
The architecture is designed to be extensible. To add a new guest program type:
-
Create the guest program directory structure:
ere-guests/your-new-program-type/ ├── sp1/ │ ├── Cargo.toml │ └── src/main.rs ├── risc0/ │ ├── Cargo.toml │ └── src/main.rs └── ... (other zkVMs)
-
Add the new command to
ere-hosts
:- Add a new variant to the
GuestProgramCommand
enum incrates/ere-hosts/src/main.rs
- Add corresponding logic to handle the new guest program type
- Update the
get_zkvm_instances
function to point to the correct subdirectory
- Add a new variant to the
-
Update documentation to include the new guest program type in the supported benchmarks table and usage examples
The repository includes automated Docker image building through GitHub Actions:
- Automated Builds: Docker images are automatically built and pushed to GitHub Container Registry (
ghcr.io
) on pushes to the master branch - Manual Builds: Docker builds can be triggered manually via GitHub Actions workflow dispatch
- Container Registry: Pre-built images are available at
ghcr.io/<repository>/witness-generator-cli
- Multi-platform Support: Images are built for multiple architectures and cached for efficient builds
The Docker workflow (.github/workflows/docker-build.yml
) provides:
- Automatic tagging with git SHA and
latest
for the default branch - Docker layer caching for faster subsequent builds
- Integration with GitHub's container registry with proper authentication
The Docker image provides a self-contained environment for running the witness generator without local Rust toolchain setup.