Upgrade openvm (#98)

This commit is contained in:
Han
2025-08-21 00:47:10 +08:00
committed by GitHub
parent f8eef49fd0
commit 0505f0e6e9
14 changed files with 288 additions and 410 deletions

View File

@@ -14,6 +14,6 @@ jobs:
packages: write
with:
zkvm: jolt
toolchain: 1.85.0
toolchain: 1.86.0
test_ere_dockerized: false
test_options: ''

View File

@@ -14,6 +14,6 @@ jobs:
packages: write
with:
zkvm: openvm
toolchain: 1.85.0
toolchain: 1.86.0
test_ere_dockerized: true
test_options: ''

View File

@@ -14,6 +14,6 @@ jobs:
packages: write
with:
zkvm: risc0
toolchain: 1.85.0
toolchain: 1.86.0
test_ere_dockerized: true
test_options: ''

View File

@@ -14,6 +14,6 @@ jobs:
packages: write
with:
zkvm: sp1
toolchain: 1.85.0
toolchain: 1.86.0
test_ere_dockerized: true
test_options: ''

View File

@@ -14,6 +14,6 @@ jobs:
packages: write
with:
zkvm: zisk
toolchain: 1.85.0
toolchain: 1.86.0
test_ere_dockerized: false
test_options: 'execute compile'

View File

@@ -11,7 +11,7 @@ on:
description: 'Rust toolchain to use'
required: false
type: string
default: 1.85.0
default: 1.86.0
test_ere_dockerized:
description: 'Whether test ere-dockerized with the selected zkVM or not'
required: false

476
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -58,11 +58,12 @@ jolt-sdk = { git = "https://github.com/a16z/jolt.git", rev = "55b9830a3944dde55d
nexus-sdk = { git = "https://github.com/nexus-xyz/nexus-zkvm.git", tag = "v0.3.4" }
# OpenVM dependencies
openvm-build = { git = "https://github.com/openvm-org/openvm.git", tag = "v1.2.0", default-features = false }
openvm-circuit = { git = "https://github.com/openvm-org/openvm.git", tag = "v1.2.0", default-features = false }
openvm-sdk = { git = "https://github.com/openvm-org/openvm.git", tag = "v1.2.0", default-features = false }
openvm-stark-sdk = { git = "https://github.com/openvm-org/stark-backend.git", tag = "v1.1.0" }
openvm-transpiler = { git = "https://github.com/openvm-org/openvm.git", tag = "v1.2.0", default-features = false }
openvm-build = { git = "https://github.com/openvm-org/openvm.git", tag = "v1.4.0-rc.4", default-features = false }
openvm-circuit = { git = "https://github.com/openvm-org/openvm.git", tag = "v1.4.0-rc.4", default-features = false }
openvm-continuations = { git = "https://github.com/openvm-org/openvm.git", tag = "v1.4.0-rc.4", default-features = false }
openvm-sdk = { git = "https://github.com/openvm-org/openvm.git", tag = "v1.4.0-rc.4", default-features = false }
openvm-stark-sdk = { git = "https://github.com/openvm-org/stark-backend.git", tag = "v1.2.0-rc.1" }
openvm-transpiler = { git = "https://github.com/openvm-org/openvm.git", tag = "v1.4.0-rc.4", default-features = false }
# Pico dependencies
pico-vm = { git = "https://github.com/brevis-network/pico.git", tag = "v1.1.4" }

View File

@@ -13,6 +13,7 @@ toml.workspace = true
# OpenVM dependencies
openvm-build.workspace = true
openvm-circuit.workspace = true
openvm-continuations.workspace = true
openvm-sdk.workspace = true
openvm-stark-sdk.workspace = true
openvm-transpiler.workspace = true

View File

@@ -1,3 +1,4 @@
use openvm_sdk::{SdkError, commit::AppExecutionCommit};
use std::{io, path::PathBuf};
use thiserror::Error;
use zkvm_interface::zkVMError;
@@ -8,6 +9,12 @@ impl From<OpenVMError> for zkVMError {
}
}
impl From<CommonError> for zkVMError {
fn from(value: CommonError) -> Self {
zkVMError::Other(Box::new(value))
}
}
#[derive(Debug, Error)]
pub enum OpenVMError {
#[error(transparent)]
@@ -36,27 +43,50 @@ pub enum CompileError {
#[error("Failed to read OpenVM's config file at {path}: {source}")]
ReadConfigFailed { source: io::Error, path: PathBuf },
#[error("Failed to deserialize OpenVM's config file: {0}")]
DeserializeConfigFailed(Box<dyn std::error::Error + Send + Sync + 'static>),
#[error("Failed to decode elf: {0}")]
DecodeFailed(Box<dyn std::error::Error + Send + Sync + 'static>),
#[error("Failed to transpile elf: {0}")]
TranspileFailed(Box<dyn std::error::Error + Send + Sync + 'static>),
DeserializeConfigFailed(toml::de::Error),
}
#[derive(Debug, Error)]
pub enum ExecuteError {
#[error("OpenVM execute failed: {0}")]
Client(#[source] Box<dyn std::error::Error + Send + Sync + 'static>),
Execute(#[source] SdkError),
#[error(transparent)]
Common(#[from] CommonError),
}
#[derive(Debug, Error)]
pub enum ProveError {
#[error("OpenVM prove failed: {0}")]
Client(#[source] Box<dyn std::error::Error + Send + Sync + 'static>),
Prove(#[source] SdkError),
#[error("Unexpected app commit: {proved:?}, expected: {preprocessed:?}")]
UnexpectedAppCommit {
preprocessed: AppExecutionCommit,
proved: AppExecutionCommit,
},
#[error("Serialize proof failed: {0}")]
SerializeProof(io::Error),
#[error(transparent)]
Common(#[from] CommonError),
}
#[derive(Debug, Error)]
pub enum VerifyError {
#[error("OpenVM verification failed: {0}")]
Client(#[source] Box<dyn std::error::Error + Send + Sync + 'static>),
Verify(#[source] SdkError),
#[error("Deserialize proof failed: {0}")]
DeserializeProof(io::Error),
}
#[derive(Debug, Error)]
pub enum CommonError {
#[error("Initialize SDK failed: {0}")]
SdkInit(SdkError),
#[error("Decode elf failed: {0}")]
ElfDecode(Box<dyn std::error::Error + Send + Sync + 'static>),
#[error("Transpile elf failed: {0}")]
Transpile(SdkError),
#[error("Agg keygen failed: {0}")]
AggKeyGen(SdkError),
#[error("Initialize prover failed: {0}")]
ProverInit(SdkError),
}

View File

@@ -1,16 +1,15 @@
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
use crate::error::{CompileError, ExecuteError, OpenVMError, VerifyError};
use crate::error::{CommonError, CompileError, ExecuteError, OpenVMError, ProveError, VerifyError};
use openvm_build::GuestOptions;
use openvm_circuit::{
arch::{ContinuationVmProof, instructions::exe::VmExe},
system::program::trace::VmCommittedExe,
};
use openvm_circuit::arch::instructions::exe::VmExe;
use openvm_continuations::verifier::internal::types::VmStarkProof;
use openvm_sdk::{
F, SC, Sdk, StdIn,
codec::{Decode, Encode},
commit::AppExecutionCommit,
config::{AppConfig, DEFAULT_APP_LOG_BLOWUP, DEFAULT_LEAF_LOG_BLOWUP, SdkVmConfig},
keygen::AppProvingKey,
keygen::AggVerifyingKey,
};
use openvm_stark_sdk::config::FriParameters;
use openvm_transpiler::{elf::Elf, openvm_platform::memory::MEM_SIZE};
@@ -44,8 +43,8 @@ impl Compiler for OPENVM_TARGET {
let guest_opts = GuestOptions::default().with_profile("release".to_string());
let target_dir = match openvm_build::build_guest_package(&pkg, &guest_opts, None, &None) {
Ok(target_dir) => target_dir,
Err(Some(code)) => return Err(CompileError::BuildFailed(code).into()),
Err(None) => return Err(CompileError::BuildSkipped.into()),
Err(Some(code)) => return Err(CompileError::BuildFailed(code))?,
Err(None) => return Err(CompileError::BuildSkipped)?,
};
let elf_path = openvm_build::find_unique_executable(guest_directory, target_dir, &None)
@@ -63,8 +62,7 @@ impl Compiler for OPENVM_TARGET {
path: app_config_path.to_path_buf(),
}
})?;
toml::from_str(&toml)
.map_err(|err| CompileError::DeserializeConfigFailed(err.into()))?
toml::from_str(&toml).map_err(CompileError::DeserializeConfigFailed)?
} else {
// The default `AppConfig` copied from https://github.com/openvm-org/openvm/blob/ca36de3/crates/cli/src/default.rs#L31.
AppConfig {
@@ -93,56 +91,55 @@ impl Compiler for OPENVM_TARGET {
pub struct EreOpenVM {
app_config: AppConfig<SdkVmConfig>,
app_exe: VmExe<F>,
app_committed_exe: Arc<VmCommittedExe<SC>>,
app_pk: Arc<AppProvingKey<SdkVmConfig>>,
app_exe: Arc<VmExe<F>>,
agg_vk: AggVerifyingKey,
app_commit: AppExecutionCommit,
_resource: ProverResourceType,
}
impl EreOpenVM {
pub fn new(program: OpenVMProgram, _resource: ProverResourceType) -> Result<Self, zkVMError> {
let sdk = Sdk::new();
let sdk = Sdk::new(program.app_config.clone()).map_err(CommonError::SdkInit)?;
let elf = Elf::decode(&program.elf, MEM_SIZE as u32)
.map_err(|e| OpenVMError::from(CompileError::DecodeFailed(e.into())))?;
.map_err(|e| CommonError::ElfDecode(e.into()))?;
let app_exe = sdk
.transpile(elf, program.app_config.app_vm_config.transpiler())
.map_err(|e| OpenVMError::from(CompileError::TranspileFailed(e.into())))?;
let app_exe = sdk.convert_to_exe(elf).map_err(CommonError::Transpile)?;
let app_pk = sdk
.app_keygen(program.app_config.clone())
.map_err(|e| zkVMError::Other(e.into()))?;
let (_, agg_vk) = sdk.agg_keygen().map_err(CommonError::AggKeyGen)?;
let app_committed_exe = sdk
.commit_app_exe(app_pk.app_fri_params(), app_exe.clone())
.map_err(|e| zkVMError::Other(e.into()))?;
let app_commit = sdk
.prover(app_exe.clone())
.map_err(CommonError::ProverInit)?
.app_commit();
Ok(Self {
app_config: program.app_config,
app_exe,
app_committed_exe,
app_pk: Arc::new(app_pk),
agg_vk,
app_commit,
_resource,
})
}
fn sdk(&self) -> Result<Sdk, CommonError> {
Sdk::new_without_transpiler(self.app_config.clone()).map_err(CommonError::SdkInit)
}
}
impl zkVM for EreOpenVM {
fn execute(&self, inputs: &Input) -> Result<zkvm_interface::ProgramExecutionReport, zkVMError> {
let sdk = Sdk::new();
let sdk = self
.sdk()
.map_err(|e| OpenVMError::from(ExecuteError::from(e)))?;
let mut stdin = StdIn::default();
serialize_inputs(&mut stdin, inputs);
let start = Instant::now();
let _outputs = sdk
.execute(
self.app_exe.clone(),
self.app_config.app_vm_config.clone(),
stdin,
)
.map_err(|e| OpenVMError::from(ExecuteError::Client(e.into())))?;
.execute(self.app_exe.clone(), stdin)
.map_err(|e| OpenVMError::from(ExecuteError::Execute(e)))?;
Ok(ProgramExecutionReport {
execution_duration: start.elapsed(),
@@ -154,32 +151,41 @@ impl zkVM for EreOpenVM {
&self,
inputs: &Input,
) -> Result<(Vec<u8>, zkvm_interface::ProgramProvingReport), zkVMError> {
let sdk = Sdk::new();
let sdk = self
.sdk()
.map_err(|e| OpenVMError::from(ProveError::from(e)))?;
let mut stdin = StdIn::default();
serialize_inputs(&mut stdin, inputs);
let now = std::time::Instant::now();
let proof = sdk
.generate_app_proof(self.app_pk.clone(), self.app_committed_exe.clone(), stdin)
.unwrap();
let (proof, app_commit) = sdk
.prove(self.app_exe.clone(), stdin)
.map_err(|e| OpenVMError::from(ProveError::Prove(e)))?;
let elapsed = now.elapsed();
let proof_bytes = proof.encode_to_vec().unwrap();
if app_commit != self.app_commit {
return Err(OpenVMError::from(ProveError::UnexpectedAppCommit {
preprocessed: self.app_commit,
proved: app_commit,
}))?;
}
let proof_bytes = proof
.encode_to_vec()
.map_err(|e| OpenVMError::from(ProveError::SerializeProof(e)))?;
Ok((proof_bytes, ProgramProvingReport::new(elapsed)))
}
fn verify(&self, mut proof: &[u8]) -> Result<(), zkVMError> {
let sdk = Sdk::new();
let proof = VmStarkProof::<SC>::decode(&mut proof)
.map_err(|e| OpenVMError::from(VerifyError::DeserializeProof(e)))?;
let proof = ContinuationVmProof::<SC>::decode(&mut proof).unwrap();
Sdk::verify_proof(&self.agg_vk, self.app_commit, &proof)
.map_err(|e| OpenVMError::Verify(VerifyError::Verify(e)))?;
let app_vk = self.app_pk.get_app_vk();
sdk.verify_app_proof(&app_vk, &proof)
.map(|_payload| ())
.map_err(|e| OpenVMError::Verify(VerifyError::Client(e.into())))
.map_err(zkVMError::from)
Ok(())
}
fn name(&self) -> &'static str {
@@ -205,15 +211,14 @@ fn serialize_inputs(stdin: &mut StdIn, inputs: &Input) {
#[cfg(test)]
mod tests {
use super::*;
use std::{panic, sync::OnceLock};
use std::sync::OnceLock;
use test_utils::host::{
BasicProgramInputGen, run_zkvm_execute, run_zkvm_prove, testing_guest_directory,
};
static BASIC_PRORGAM: OnceLock<OpenVMProgram> = OnceLock::new();
fn basic_program() -> OpenVMProgram {
BASIC_PRORGAM
static PROGRAM: OnceLock<OpenVMProgram> = OnceLock::new();
PROGRAM
.get_or_init(|| {
OPENVM_TARGET
.compile(&testing_guest_directory("openvm", "basic"))
@@ -222,6 +227,11 @@ mod tests {
.clone()
}
fn basic_program_ere_openvm() -> &'static EreOpenVM {
static ERE_OPENVM: OnceLock<EreOpenVM> = OnceLock::new();
ERE_OPENVM.get_or_init(|| EreOpenVM::new(basic_program(), ProverResourceType::Cpu).unwrap())
}
#[test]
fn test_compiler_impl() {
let program = basic_program();
@@ -230,8 +240,7 @@ mod tests {
#[test]
fn test_execute() {
let program = basic_program();
let zkvm = EreOpenVM::new(program, ProverResourceType::Cpu).unwrap();
let zkvm = basic_program_ere_openvm();
let inputs = BasicProgramInputGen::valid();
run_zkvm_execute(&zkvm, &inputs);
@@ -239,8 +248,7 @@ mod tests {
#[test]
fn test_execute_invalid_inputs() {
let program = basic_program();
let zkvm = EreOpenVM::new(program, ProverResourceType::Cpu).unwrap();
let zkvm = basic_program_ere_openvm();
for inputs in [
BasicProgramInputGen::empty(),
@@ -253,8 +261,7 @@ mod tests {
#[test]
fn test_prove() {
let program = basic_program();
let zkvm = EreOpenVM::new(program, ProverResourceType::Cpu).unwrap();
let zkvm = basic_program_ere_openvm();
let inputs = BasicProgramInputGen::valid();
run_zkvm_prove(&zkvm, &inputs);
@@ -262,15 +269,14 @@ mod tests {
#[test]
fn test_prove_invalid_inputs() {
let program = basic_program();
let zkvm = EreOpenVM::new(program, ProverResourceType::Cpu).unwrap();
let zkvm = basic_program_ere_openvm();
for inputs_gen in [
BasicProgramInputGen::empty,
BasicProgramInputGen::invalid_string,
BasicProgramInputGen::invalid_type,
for inputs in [
BasicProgramInputGen::empty(),
BasicProgramInputGen::invalid_string(),
BasicProgramInputGen::invalid_type(),
] {
panic::catch_unwind(|| zkvm.prove(&inputs_gen()).unwrap_err()).unwrap_err();
zkvm.prove(&inputs).unwrap_err();
}
}
}

View File

@@ -29,8 +29,8 @@ RUN apt-get update && \
rm -rf /var/lib/apt/lists/*
# Install rustup.
# RUST_VERSION can be 1.85, stable, nightly, etc
ARG RUST_VERSION=1.85.0
# RUST_VERSION can be 1.86, stable, nightly, etc
ARG RUST_VERSION=1.86.0
ENV RUSTUP_HOME=/usr/local/rustup \
CARGO_HOME=/usr/local/cargo \

View File

@@ -14,11 +14,7 @@ RUN chmod +x /tmp/install_openvm_sdk.sh
# and installs cargo-openvm.
RUN /tmp/install_openvm_sdk.sh && rm /tmp/install_openvm_sdk.sh
# The specific Rust toolchain for OpenVM is now installed.
# cargo-openvm is installed in $CARGO_HOME/bin, which is already in PATH from ere-base.
ENV OPENVM_TOOLCHAIN_VERSION="nightly-2025-02-14"
# Verify cargo-openvm is accessible with the correct toolchain
RUN cargo "+${OPENVM_TOOLCHAIN_VERSION}" openvm --version
RUN cargo openvm --version
CMD ["/bin/bash"]

View File

@@ -28,22 +28,16 @@ ensure_tool_installed "rustup" "to manage Rust toolchains"
ensure_tool_installed "git" "to install cargo-openvm from a git repository"
ensure_tool_installed "cargo" "to build and install Rust packages"
OPENVM_TOOLCHAIN_VERSION="nightly-2025-02-14"
OPENVM_CLI_VERSION_TAG="v1.2.0"
# Install the specific nightly toolchain for OpenVM
echo "Installing OpenVM-specific Rust toolchain: ${OPENVM_TOOLCHAIN_VERSION}..."
rustup install "${OPENVM_TOOLCHAIN_VERSION}"
rustup component add rust-src --toolchain "${OPENVM_TOOLCHAIN_VERSION}"
OPENVM_CLI_VERSION_TAG="v1.4.0-rc.4"
# Install cargo-openvm using the specified toolchain and version tag
echo "Installing cargo-openvm (version ${OPENVM_CLI_VERSION_TAG}) from GitHub repository (openvm-org/openvm)..."
cargo "+${OPENVM_TOOLCHAIN_VERSION}" install --locked --git https://github.com/openvm-org/openvm.git --tag "${OPENVM_CLI_VERSION_TAG}" cargo-openvm
cargo install --locked --git https://github.com/openvm-org/openvm.git --tag "${OPENVM_CLI_VERSION_TAG}" cargo-openvm
# Verify cargo-openvm installation
echo "Verifying cargo-openvm installation..."
# The cargo-openvm is installed as `cargo-openvm`, so it's invoked as `cargo openvm`
if cargo "+${OPENVM_TOOLCHAIN_VERSION}" openvm --version; then
if cargo openvm --version; then
echo "cargo-openvm installation verified successfully."
else
echo "Error: 'cargo openvm --version' failed. cargo-openvm might not have installed correctly." >&2