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, andCostEstimationere-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.setupswitches an instance to anotherElfand keeps the state that does not depend on the program. -
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.6.0 |
RV64IMA |
V | ||
| ZisK | 1.3.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);
type P = SP1Platform;
pub fn main() {
// 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);
}
fn fib(n: u64) -> u64 {
let mut a = 0;
let mut b = 1;
for _ in 0..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.rs
use 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;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let guest_directory = Path::new("path/to/guest");
// Compile guest program with SP1 customized toolchain
let 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();
// Execute
let (public_values, execution_duration) = zkvm.execute(&input)?;
assert_eq!(public_values, expected_output);
println!("Execution duration: {execution_duration:?}");
// Prove
let (public_values, proof, proving_time) = zkvm.prove(&input)?;
assert_eq!(public_values, expected_output);
println!("Proving time: {proving_time:?}");
// Verify
let 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.rs
use ere_compiler_core::Compiler;
use ere_dockerized::{
CompilerKind, DockerizedCompiler, DockerizedzkVM, DockerizedzkVMConfig, zkVMKind,
};
use ere_prover_core::{Input, ProverResource, zkVMProver};
use std::path::Path;
fn main() -> 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 operations
let 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();
// Execute
let (public_values, execution_duration) = zkvm.execute(&input)?;
assert_eq!(public_values, expected_output);
println!("Execution duration: {execution_duration:?}");
// Prove
let (public_values, proof, proving_time) = zkvm.prove(&input)?;
assert_eq!(public_values, expected_output);
println!("Proving time: {proving_time:?}");
// Verify
let 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_IMAGE_TAG |
Overrides the image tag, by default the short git revision of ere. GPU images still get the -cuda suffix. |
`` |
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. |
`` |
ERE_ZISK_PROVING_KEY_VOLUME |
Volume or absolute host path mounted at the ZisK proving key directory, so the downloaded key persists across containers. | `` |
ERE_ZISK_CACHE_VOLUME |
Volume or absolute host path mounted at the ZisK cache directory, so the ROM setup of each program persists across containers. | `` |
ERE_OPENVM_CACHE_VOLUME |
Volume or absolute host path mounted at the OpenVM rvr cache directory, so each compiled program persists across containers. |
`` |
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.