Compile. Execute. Prove. Verify.
One ergonomic Rust API, multiple zero‑knowledge virtual machines.
- Table of Contents
- Supported Rust Versions (MSRV)
- Overview
- Architecture
- Supported zkVMs
- Examples
- Environment Variables
- Directory Layout
- Contributing
- Disclaimer
- License
The current MSRV (minimum supported rust version) is 1.91.
This repository contains the following crates:
- Traits
ere-compiler-core-Compilertrait andElftype for compiling guest programsere-prover-core-zkVMProvertrait,Input,ProverResource, and execution/proving reportsere-platform-core-Platformtrait for guest programere-verifier-core-zkVMVerifiertrait andPublicValues
- Per-zkVM implementations for
ere-compiler-core(host) - Per-zkVM implementations for
ere-prover-core(host) - Per-zkVM implementations for
ere-platform-core(guest) - Per-zkVM implementations for
ere-verifier-core(lightweight host verifier) ere-dockerized- Docker wrapper that spawnsere-servercontainers to run zkVM operations without local SDK installationere-cluster-client-zisk- ZisK distributed-cluster client used byere-prover-ziskwhenProverResource::Clusteris selectedere-codec- Canonical byte codec (Encode/Decode+ macros) shared across cratesere-catalog- Catalog of supported zkVMs and compilers (zkVMKind,CompilerKind, SDK versions, Docker image tag)- Internal crates
ere-compiler- CLI binary to runCompilerused byere-dockerizedere-server- Server binary that exposeszkVMProveroperations over gRPC (also provides akeygensubcommand)ere-server-api- gRPC wire contract (proto/api.protoand generated prost/twirp types) shared byere-serverandere-server-clientere-server-client- Client library forere-server, used byere-dockerizedere-util-build- Build-time utilities (SDK version + Docker image tag detection)ere-util-compile- Cross-compilation utilities (CargoBuildCmd,RustTarget, toolchain management)ere-util-test- Testing utilities (Program,TestCase,BasicProgram, codec markers)ere-util-tokio- Tokio runtime bridge (block_on) used by sync constructors that call async SDK APIs
Host-side traits:
Compiler(fromere-compiler-core)Compile a guest program into an
Elf.zkVMProver(fromere-prover-core)Execute, prove and verify. A zkVM prover instance is created for an
Elfproduced by aCompiler.Elfspecific verifying key generation happens in the constructor.zkVMVerifier(fromere-verifier-core)zkVM verifier that is created by a succinct
ProgramVkfor specificElfproduced byzkVMProver. A zkVM verifier instance verifies aProofand returnsPublicValues. Pulled in standalone by verify-only consumers without the prover deps if upstream zkVM SDK provides verifier-only crate.
Guest-side trait (ere-platform-core):
PlatformProvides platform-dependent methods for IO read/write and cycle tracking. It also re-exports the runtime SDK of the zkVM, guaranteed to match the host when
ere-prover-{zkvm}andere-platform-{zkvm}share the same version.
Host and guest communicate through raw bytes. Serialization/deserialization can be done in any way as long as they agree with each other.
The Input structure holds stdin as raw bytes. Set them with Input::new().with_stdin(data), and the guest reads them back via Platform::read_input().
zkVM-specific stdin APIs (e.g., sp1_zkvm::io::read) can also be used directly when finer-grained control is needed.
Public values written in the guest program (via Platform::write_output() or zkVM-specific output APIs) are returned as raw bytes to the host after zkVMProver::execute, zkVMProver::prove and zkVMProver::verify methods.
Different zkVMs handles public values in different approaches:
| zkVM | Size Limit | Note |
|---|---|---|
| OpenVM | 256 bytes | Padded to 256 bytes with zeros |
| SP1 | unlimited | Hashed internally |
| ZisK | 256 bytes |
| zkVM | Version | ISA | GPU | Multi GPU | Cluster |
|---|---|---|---|---|---|
| OpenVM | 2.1.0-preview | RV64IMA | V | ||
| SP1 | 6.4.0 | RV64IMA | V | ||
| ZisK | 1.1.0-alpha | RV64IMA | V | V | V |
Install the required zkVM SDKs locally for better performance and debugging.
Install the SP1 SDK as an example
bash scripts/sdk_installers/install_sp1_sdk.sh# guest/Cargo.toml
[workspace]
[package]
name = "guest"edition = "2024"
[dependencies]
ere-platform-sp1 = { git = "https://github.com/eth-act/ere.git" }// guest/src/main.rs#![no_main]use ere_platform_sp1::{sp1_zkvm,Platform,SP1Platform};
sp1_zkvm::entrypoint!(main);typeP = SP1Platform;pubfnmain(){// Read serialized input and deserialize it.let input = P::read_input();let n = u64::from_le_bytes(input.as_slice().try_into().unwrap());// Compute nth fib.let fib_n = fib(n);// Write serialized output.let output = [input.as_slice(),&fib_n.to_le_bytes()].concat();P::write_output(&output);}fnfib(n:u64) -> u64{letmut a = 0;letmut b = 1;for _ in0..n {let c = a + b;
a = b;
b = c;}
a
}# host/Cargo.toml
[workspace]
[package]
name = "host"edition = "2024"
[dependencies]
ere-prover-core = { git = "https://github.com/eth-act/ere.git" }
ere-prover-sp1 = { git = "https://github.com/eth-act/ere.git" }// host/src/main.rsuse ere_compiler_core::Compiler;use ere_compiler_sp1::SP1RustRv64imaCustomized;use ere_prover_core::{Input,ProverResource, zkVMProver};use ere_prover_sp1::SP1Prover;use std::path::Path;fnmain() -> Result<(),Box<dyn std::error::Error>>{let guest_directory = Path::new("path/to/guest");// Compile guest program with SP1 customized toolchainlet compiler = SP1RustRv64imaCustomized;let elf = compiler.compile(guest_directory,&[])?;// Create zkVM instance (setup/preprocessing happens here)let zkvm = SP1Prover::new(elf,ProverResource::Cpu)?;// Prepare input as raw bytes. The prover handles any framing needed by the SDK.let stdin = 10u64.to_le_bytes().to_vec();let input = Input::new().with_stdin(stdin.clone());let expected_output = [stdin,55u64.to_le_bytes().to_vec()].concat();// Executelet(public_values, report) = zkvm.execute(&input)?;assert_eq!(public_values, expected_output);println!("Execution cycles: {}", report.total_num_cycles);// Provelet(public_values, proof, report) = zkvm.prove(&input)?;assert_eq!(public_values, expected_output);println!("Proving time: {:?}", report.proving_time);// Verifylet public_values = zkvm.verify(&proof)?;assert_eq!(public_values, expected_output);println!("Proof verified successfully!");Ok(())}Use Docker for zkVM operations without installing SDKs locally. Only requires Docker to be installed.
We use the same guest program created above.
# host/Cargo.toml
[workspace]
[package]
name = "host"edition = "2024"
[dependencies]
ere-prover-core = { git = "https://github.com/eth-act/ere.git" }
ere-dockerized = { git = "https://github.com/eth-act/ere.git" }// host/src/main.rsuse ere_compiler_core::Compiler;use ere_dockerized::{CompilerKind,DockerizedCompiler,DockerizedzkVM,DockerizedzkVMConfig, zkVMKind,};use ere_prover_core::{Input,ProverResource, zkVMProver};use std::path::Path;fnmain() -> Result<(),Box<dyn std::error::Error>>{let guest_directory = Path::new("path/to/guest");// Compile guest program with SP1 customized toolchain (builds Docker images if needed)let compiler =
DockerizedCompiler::new(zkVMKind::SP1,CompilerKind::RustCustomized, guest_directory)?;let elf = compiler.compile(guest_directory,&[])?;// Create zkVM instance (builds Docker images if needed)// It spawns a container that runs a gRPC server handling zkVM operationslet zkvm = DockerizedzkVM::new(
zkVMKind::SP1,
elf,ProverResource::Cpu,DockerizedzkVMConfig::default(),)?;// Prepare input as raw bytes. The prover handles any framing needed by the SDK.let stdin = 10u64.to_le_bytes().to_vec();let input = Input::new().with_stdin(stdin.clone());let expected_output = [stdin,55u64.to_le_bytes().to_vec()].concat();// Executelet(public_values, report) = zkvm.execute(&input)?;assert_eq!(public_values, expected_output);println!("Execution cycles: {}", report.total_num_cycles);// Provelet(public_values, proof, report) = zkvm.prove(&input)?;assert_eq!(public_values, expected_output);println!("Proving time: {:?}", report.proving_time);// Verifylet public_values = zkvm.verify(&proof)?;assert_eq!(public_values, expected_output);println!("Proof verified successfully!");Ok(())}| Variable | Description | Default |
|---|---|---|
ERE_IMAGE_REGISTRY | Specifies docker image registry of the images. When specified, it will try to pull image from the registry and possibly skip building. | `` |
ERE_FORCE_REBUILD_DOCKER_IMAGE | Force to rebuild docker images locally even they exist, it also prevents pulling image from registry. | false |
ERE_GPU_DEVICES | Specifies which GPU devices to use when running Docker containers for GPU-enabled zkVMs. The value is passed to Docker's --gpus flag. | all |
ERE_DOCKER_NETWORK | Specifies the Docker network being used (if any) so spawned ere-server-* containers will join that network. | `` |
Example usage:
# Use all GPUs (default)
ere prove ...
# Use specific GPU devices
ERE_GPU_DEVICES="device=0" ere prove ...
# Use multiple specific GPUs
ERE_GPU_DEVICES="device=0,1" ere prove ...
# Can also signal to use any available GPUs
ERE_GPU_DEVICES="4" ere prove ...ere/
├── crates/ # Rust crates
│ ├── catalog/ # ere-catalog
│ ├── codec/ # ere-codec
│ ├── prover/
│ │ ├── core/ # ere-prover-core
│ │ └── {zkvm}/ # ere-prover-{zkvm}
│ ├── platform/
│ │ ├── core/ # ere-platform-core
│ │ └── {zkvm}/ # ere-platform-{zkvm}
│ ├── verifier/
│ │ ├── core/ # ere-verifier-core
│ │ └── {zkvm}/ # ere-verifier-{zkvm}
│ ├── dockerized/ # ere-dockerized
│ ├── compiler/
│ │ ├── cli/ # ere-compiler
│ │ ├── core/ # ere-compiler-core
│ │ └── {zkvm}/ # ere-compiler-{zkvm}
│ ├── server/
│ │ ├── api/ # ere-server-api
│ │ ├── cli/ # ere-server
│ │ └── client/ # ere-server-client
│ ├── cluster-client/
│ │ └── zisk/ # ere-cluster-client-zisk
│ └── util/
│ ├── build/ # ere-util-build
│ ├── compile/ # ere-util-compile
│ ├── test/ # ere-util-test
│ └── tokio/ # ere-util-tokio
│
├── docker/ # Dockerfile used by ere-dockerized
│ ├── Dockerfile.base # ere-base
│ └── {zkvm}/
│ ├── Dockerfile.base # ere-base-{zkvm}
│ ├── Dockerfile.compiler # ere-compiler-{zkvm}
│ └── Dockerfile.server # ere-server-{zkvm}
│
├── scripts/ # SDK installation scripts per zkVM
└── tests/ # Guest programs per zkVM for integration test
PRs and issues are welcome!
zkVMs evolve quickly; expect breaking changes. Although the API is generic, its primary target is zkEVMs, which may for example, guide the default set of precompiles.
Licensed under either of
- MIT license (LICENSE‑MIT or http://opensource.org/licenses/MIT)
- Apache License, Version 2.0 (LICENSE‑APACHE or http://www.apache.org/licenses/LICENSE-2.0)
at your option.