Input structure to support composition proof (#230)

This commit is contained in:
Han
2025-12-04 09:39:41 +09:00
committed by GitHub
parent 6266b242ed
commit 3d844b9f8b
31 changed files with 367 additions and 187 deletions

2
Cargo.lock generated
View File

@@ -3933,7 +3933,7 @@ name = "ere-risc0"
version = "0.0.15"
dependencies = [
"anyhow",
"borsh",
"bincode 2.0.1",
"ere-build-utils",
"ere-compile-utils",
"ere-io",

View File

@@ -48,7 +48,6 @@ anyhow = "1.0.98"
auto_impl = "1.3.0"
bincode = { version = "2.0.1", default-features = false }
blake3 = "1.8.2"
borsh = "1.5.7"
bytemuck = "1.23.1"
cargo_metadata = "0.19.0"
clap = "4.5.42"

View File

@@ -84,7 +84,7 @@ ere-sp1 = { git = "https://github.com/eth-act/ere.git", tag = "v0.0.12" }
use ere_sp1::{EreSP1, RV32_IM_SUCCINCT_ZKVM_ELF};
use ere_zkvm_interface::{
compiler::Compiler,
zkvm::{ProofKind, ProverResourceType, zkVM},
zkvm::{Input, ProofKind, ProverResourceType, zkVM},
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -98,7 +98,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let zkvm = EreSP1::new(program, ProverResourceType::Cpu)?;
// Serialize input
let input = 42u32.to_le_bytes();
let input = Input::new(42u32.to_le_bytes().to_vec());
// Execute
let (public_values, report) = zkvm.execute(&input)?;
@@ -133,7 +133,7 @@ ere-dockerized = { git = "https://github.com/eth-act/ere.git", tag = "v0.0.12" }
use ere_dockerized::{CompilerKind, DockerizedCompiler, DockerizedzkVM, zkVMKind};
use ere_zkvm_interface::{
compiler::Compiler,
zkvm::{ProofKind, ProverResourceType, zkVM},
zkvm::{Input, ProofKind, ProverResourceType, zkVM},
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -151,7 +151,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let zkvm = DockerizedzkVM::new(zkVMKind::SP1, program, ProverResourceType::Cpu)?;
// Serialize input
let input = 42u32.to_le_bytes();
let input = Input::new(42u32.to_le_bytes().to_vec());
// Execute
let (public_values, report) = zkvm.execute(&input)?;

View File

@@ -14,7 +14,8 @@ service ZkvmService {
}
message ExecuteRequest {
bytes input = 1;
bytes input_stdin = 1;
optional bytes input_proofs = 2;
}
message ExecuteResponse {
@@ -30,8 +31,9 @@ message ExecuteOk {
}
message ProveRequest {
bytes input = 1;
ProofKind proof_kind = 2;
bytes input_stdin = 1;
optional bytes input_proofs = 2;
ProofKind proof_kind = 3;
}
message ProveResponse {

View File

@@ -4,7 +4,7 @@ use crate::api::{
verify_response::Result as VerifyResult,
};
use ere_zkvm_interface::zkvm::{
ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind, PublicValues,
Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind, PublicValues,
};
use std::time::{Duration, Instant};
use thiserror::Error;
@@ -56,9 +56,12 @@ impl zkVMClient {
pub async fn execute(
&self,
input: Vec<u8>,
input: &Input,
) -> Result<(PublicValues, ProgramExecutionReport), Error> {
let request = Request::new(ExecuteRequest { input });
let request = Request::new(ExecuteRequest {
input_stdin: input.stdin.clone(),
input_proofs: input.proofs.clone(),
});
let response = self.client.execute(request).await?;
@@ -75,11 +78,12 @@ impl zkVMClient {
pub async fn prove(
&self,
input: Vec<u8>,
input: &Input,
proof_kind: ProofKind,
) -> Result<(PublicValues, Proof, ProgramProvingReport), Error> {
let request = Request::new(ProveRequest {
input,
input_stdin: input.stdin.clone(),
input_proofs: input.proofs.clone(),
proof_kind: proof_kind as i32,
});

View File

@@ -6,7 +6,7 @@ use crate::api::{
};
use anyhow::Context;
use ere_zkvm_interface::zkvm::{
ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind, PublicValues, zkVM,
Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind, PublicValues, zkVM,
};
use std::sync::Arc;
use twirp::{
@@ -31,7 +31,7 @@ impl<T: 'static + zkVM + Send + Sync> zkVMServer<T> {
async fn execute(
&self,
input: Vec<u8>,
input: Input,
) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
let zkvm = Arc::clone(&self.zkvm);
tokio::task::spawn_blocking(move || zkvm.execute(&input))
@@ -41,7 +41,7 @@ impl<T: 'static + zkVM + Send + Sync> zkVMServer<T> {
async fn prove(
&self,
input: Vec<u8>,
input: Input,
proof_kind: ProofKind,
) -> anyhow::Result<(PublicValues, Proof, ProgramProvingReport)> {
let zkvm = Arc::clone(&self.zkvm);
@@ -64,9 +64,12 @@ impl<T: 'static + zkVM + Send + Sync> ZkvmService for zkVMServer<T> {
&self,
request: Request<ExecuteRequest>,
) -> twirp::Result<Response<ExecuteResponse>> {
let request = request.into_body();
let ExecuteRequest {
input_stdin: stdin,
input_proofs: proofs,
} = request.into_body();
let input = request.input;
let input = Input { stdin, proofs };
let result = match self.execute(input).await {
Ok((public_values, report)) => ExecuteResult::Ok(ExecuteOk {
@@ -86,11 +89,15 @@ impl<T: 'static + zkVM + Send + Sync> ZkvmService for zkVMServer<T> {
&self,
request: Request<ProveRequest>,
) -> twirp::Result<Response<ProveResponse>> {
let request = request.into_body();
let ProveRequest {
input_stdin: stdin,
input_proofs: proofs,
proof_kind,
} = request.into_body();
let input = request.input;
let proof_kind = ProofKind::from_repr(request.proof_kind as usize)
.ok_or_else(|| invalid_proof_kind_err(request.proof_kind))?;
let input = Input { stdin, proofs };
let proof_kind = ProofKind::from_repr(proof_kind as usize)
.ok_or_else(|| invalid_proof_kind_err(proof_kind))?;
let result = match self.prove(input, proof_kind).await {
Ok((public_values, proof, report)) => ProveResult::Ok(ProveOk {

View File

@@ -29,7 +29,7 @@
//! use ere_dockerized::{CompilerKind, DockerizedCompiler, DockerizedzkVM, zkVMKind};
//! use ere_zkvm_interface::{
//! compiler::Compiler,
//! zkvm::{ProofKind, ProverResourceType, zkVM},
//! zkvm::{Input, ProofKind, ProverResourceType, zkVM},
//! };
//! use std::path::Path;
//!
@@ -49,7 +49,7 @@
//! let zkvm = DockerizedzkVM::new(zkvm_kind, program, resource)?;
//!
//! // Serialize input
//! let input = 42u32.to_le_bytes();
//! let input = Input::new(42u32.to_le_bytes().to_vec());
//!
//! // Execute program
//! let (public_values, execution_report) = zkvm.execute(&input)?;

View File

@@ -16,7 +16,7 @@ use ere_server::client::{Url, zkVMClient};
use ere_zkvm_interface::{
CommonError,
zkvm::{
ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind, ProverResourceType,
Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind, ProverResourceType,
PublicValues, zkVM,
},
};
@@ -308,23 +308,20 @@ impl DockerizedzkVM {
}
impl zkVM for DockerizedzkVM {
fn execute(&self, input: &[u8]) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
let input = input.to_vec();
self.with_retry(|client| block_on(client.execute(input.clone())))
fn execute(&self, input: &Input) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
self.with_retry(|client| block_on(client.execute(input)))
}
fn prove(
&self,
input: &[u8],
input: &Input,
proof_kind: ProofKind,
) -> anyhow::Result<(PublicValues, Proof, ProgramProvingReport)> {
let input = input.to_vec();
self.with_retry(|client| block_on(client.prove(input.clone(), proof_kind)))
self.with_retry(|client| block_on(client.prove(input, proof_kind)))
}
fn verify(&self, proof: &Proof) -> anyhow::Result<PublicValues> {
let proof = proof.clone();
self.with_retry(|client| block_on(client.verify(&proof)))
self.with_retry(|client| block_on(client.verify(proof)))
}
fn name(&self) -> &'static str {
@@ -354,7 +351,7 @@ mod test {
use ere_test_utils::{
host::*, io::serde::bincode::BincodeLegacy, program::basic::BasicProgram,
};
use ere_zkvm_interface::zkvm::{ProofKind, ProverResourceType, zkVM};
use ere_zkvm_interface::zkvm::{Input, ProofKind, ProverResourceType, zkVM};
fn zkvm(
zkvm_kind: zkVMKind,
@@ -409,8 +406,8 @@ mod test {
"basic",
[BasicProgram::<BincodeLegacy>::valid_test_case().into_output_sha256()],
[
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input()
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input()
]
);
}
@@ -423,8 +420,8 @@ mod test {
"basic",
[BasicProgram::<BincodeLegacy>::valid_test_case()],
[
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input()
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input()
]
);
}
@@ -437,8 +434,8 @@ mod test {
"basic",
[BasicProgram::<BincodeLegacy>::valid_test_case()],
[
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input()
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input()
]
);
}
@@ -451,8 +448,8 @@ mod test {
"basic",
[BasicProgram::<BincodeLegacy>::valid_test_case().into_output_sha256()],
[
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input()
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input()
]
);
}
@@ -465,8 +462,8 @@ mod test {
"basic",
[BasicProgram::<BincodeLegacy>::valid_test_case()],
[
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input()
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input()
]
);
}
@@ -479,8 +476,8 @@ mod test {
"basic",
[BasicProgram::<BincodeLegacy>::valid_test_case()],
[
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input()
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input()
]
);
}
@@ -493,8 +490,8 @@ mod test {
"basic",
[BasicProgram::<BincodeLegacy>::valid_test_case()],
[
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input()
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input()
]
);
}
@@ -507,8 +504,8 @@ mod test {
"basic",
[BasicProgram::<BincodeLegacy>::valid_test_case()],
[
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input()
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input()
]
);
}
@@ -521,8 +518,8 @@ mod test {
"basic_rust",
[BasicProgram::<BincodeLegacy>::valid_test_case()],
[
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input()
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input()
]
);
}

View File

@@ -1,7 +1,10 @@
use crate::program::Program;
use core::ops::Deref;
use ere_io::Io;
use ere_zkvm_interface::zkvm::{ProofKind, PublicValues, zkVM};
use ere_zkvm_interface::{
Input,
zkvm::{ProofKind, PublicValues, zkVM},
};
use sha2::{Digest, Sha256};
use std::{marker::PhantomData, path::PathBuf};
@@ -18,7 +21,7 @@ pub fn testing_guest_directory(zkvm_name: &str, program: &str) -> PathBuf {
pub fn run_zkvm_execute(zkvm: &impl zkVM, test_case: &impl TestCase) -> PublicValues {
let (public_values, _report) = zkvm
.execute(&test_case.serialized_input())
.execute(&test_case.input())
.expect("execute should not fail with valid input");
test_case.assert_output(&public_values);
@@ -28,7 +31,7 @@ pub fn run_zkvm_execute(zkvm: &impl zkVM, test_case: &impl TestCase) -> PublicVa
pub fn run_zkvm_prove(zkvm: &impl zkVM, test_case: &impl TestCase) -> PublicValues {
let (prover_public_values, proof, _report) = zkvm
.prove(&test_case.serialized_input(), ProofKind::default())
.prove(&test_case.input(), ProofKind::default())
.expect("prove should not fail with valid input");
let verifier_public_values = zkvm
@@ -46,7 +49,7 @@ pub fn run_zkvm_prove(zkvm: &impl zkVM, test_case: &impl TestCase) -> PublicValu
/// [`Program::Input`], and is able to assert if the [`PublicValues`] returned
/// by [`zkVM`] methods is correct or not.
pub trait TestCase {
fn serialized_input(&self) -> Vec<u8>;
fn input(&self) -> Input;
fn assert_output(&self, public_values: &[u8]);
}
@@ -80,8 +83,8 @@ impl<P: Program> Deref for ProgramTestCase<P> {
}
impl<P: Program> TestCase for ProgramTestCase<P> {
fn serialized_input(&self) -> Vec<u8> {
P::Io::serialize_input(&self.input).unwrap()
fn input(&self) -> Input {
Input::new(P::Io::serialize_input(&self.input).unwrap())
}
fn assert_output(&self, public_values: &[u8]) {
@@ -112,8 +115,8 @@ where
P: Program,
D: Digest,
{
fn serialized_input(&self) -> Vec<u8> {
self.test_case.serialized_input()
fn input(&self) -> Input {
self.test_case.input()
}
fn assert_output(&self, public_values: &[u8]) {

View File

@@ -8,6 +8,7 @@ license.workspace = true
[dependencies]
anyhow.workspace = true
auto_impl.workspace = true
bincode = { workspace = true, features = ["alloc", "serde"] }
indexmap = { workspace = true, features = ["serde"] }
serde = { workspace = true, features = ["derive"] }
strum = { workspace = true, features = ["derive"] }

View File

@@ -1,5 +1,6 @@
#![allow(non_camel_case_types)]
use bincode::error::{DecodeError, EncodeError};
use serde::{Serialize, de::DeserializeOwned};
mod error;
@@ -12,6 +13,63 @@ pub use proof::{Proof, ProofKind};
pub use report::{ProgramExecutionReport, ProgramProvingReport};
pub use resource::{NetworkProverConfig, ProverResourceType};
/// Input for the prover to execute/prove a guest program.
#[derive(Clone, Debug, Default)]
pub struct Input {
pub stdin: Vec<u8>,
/// Serialized proofs to be verified in guest program for proof composition.
pub proofs: Option<Vec<u8>>,
}
impl Input {
/// Creates a new `Input` with the given stdin.
pub fn new(stdin: Vec<u8>) -> Self {
Self {
stdin,
proofs: None,
}
}
/// Returns a reference to the stdin as a byte slice.
pub fn stdin(&self) -> &[u8] {
&self.stdin
}
/// Deserializes and returns the proofs if present.
///
/// # Returns
///
/// - `None` if no proofs are set
/// - `Some(Ok(..))` if the proofs were successfully deserialized
/// - `Some(Err(..))` if deserialization failed
pub fn proofs<T: DeserializeOwned>(&self) -> Option<Result<Vec<T>, DecodeError>> {
self.proofs.as_ref().map(|proofs| {
bincode::serde::decode_from_slice(proofs, bincode::config::legacy())
.map(|(proofs, _)| proofs)
})
}
/// Serializes the given proofs and returns a new `Input` with them set.
///
/// Consumes `self` and returns an error if serialization fails.
pub fn with_proofs<T: Serialize>(mut self, proofs: &[T]) -> Result<Self, EncodeError> {
self.proofs = Some(bincode::serde::encode_to_vec(
proofs,
bincode::config::legacy(),
)?);
Ok(self)
}
/// Sets serialized proofs and returns a new `Input`.
///
/// The proofs must be serialized using [`bincode::serde`] with
/// [`bincode::config::legacy`] configuration.
pub fn with_serialized_proofs(mut self, proofs: Vec<u8>) -> Self {
self.proofs = Some(proofs);
self
}
}
/// Public values committed/revealed by guest program.
///
/// Use [`zkVM::deserialize_from`] to deserialize object from the bytes.
@@ -29,12 +87,12 @@ pub type PublicValues = Vec<u8>;
#[auto_impl::auto_impl(&, Arc, Box)]
pub trait zkVM {
/// Executes the program with the given input.
fn execute(&self, input: &[u8]) -> anyhow::Result<(PublicValues, ProgramExecutionReport)>;
fn execute(&self, input: &Input) -> anyhow::Result<(PublicValues, ProgramExecutionReport)>;
/// Creates a proof of the program execution with given input.
fn prove(
&self,
input: &[u8],
input: &Input,
proof_kind: ProofKind,
) -> anyhow::Result<(PublicValues, Proof, ProgramProvingReport)>;

View File

@@ -48,6 +48,9 @@ pub enum CommonError {
stderr: String,
},
#[error("Unsupported input: {0}")]
UnsupportedInput(String),
#[error("Unsupported proof kind {unsupported:?}, expect one of {supported:?}")]
UnsupportedProofKind {
unsupported: ProofKind,
@@ -134,6 +137,10 @@ impl CommonError {
}
}
pub fn unsupported_input(reason: impl AsRef<str>) -> Self {
Self::UnsupportedInput(reason.as_ref().to_string())
}
pub fn unsupported_proof_kind(
unsupported: ProofKind,
supported: impl IntoIterator<Item = ProofKind>,

View File

@@ -2,7 +2,7 @@ use crate::{program::AirbenderProgram, zkvm::sdk::AirbenderSdk};
use airbender_execution_utils::ProgramProof;
use anyhow::bail;
use ere_zkvm_interface::zkvm::{
CommonError, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
CommonError, Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
ProverResourceType, PublicValues, zkVM, zkVMProgramDigest,
};
use std::time::Instant;
@@ -28,9 +28,13 @@ impl EreAirbender {
}
impl zkVM for EreAirbender {
fn execute(&self, input: &[u8]) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
fn execute(&self, input: &Input) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
if input.proofs.is_some() {
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
}
let start = Instant::now();
let (public_values, cycles) = self.sdk.execute(input)?;
let (public_values, cycles) = self.sdk.execute(input.stdin())?;
let execution_duration = start.elapsed();
Ok((
@@ -45,9 +49,12 @@ impl zkVM for EreAirbender {
fn prove(
&self,
input: &[u8],
input: &Input,
proof_kind: ProofKind,
) -> anyhow::Result<(PublicValues, Proof, ProgramProvingReport)> {
if input.proofs.is_some() {
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
}
if proof_kind != ProofKind::Compressed {
bail!(CommonError::unsupported_proof_kind(
proof_kind,
@@ -55,7 +62,7 @@ impl zkVM for EreAirbender {
))
}
let start = Instant::now();
let (public_values, proof) = self.sdk.prove(input)?;
let (public_values, proof) = self.sdk.prove(input.stdin())?;
let proving_time = start.elapsed();
let proof_bytes = bincode::serde::encode_to_vec(&proof, bincode::config::legacy())
@@ -112,7 +119,7 @@ mod tests {
};
use ere_zkvm_interface::{
compiler::Compiler,
zkvm::{ProofKind, ProverResourceType, zkVM},
zkvm::{Input, ProofKind, ProverResourceType, zkVM},
};
use std::sync::OnceLock;
@@ -142,8 +149,8 @@ mod tests {
let zkvm = EreAirbender::new(program, ProverResourceType::Cpu).unwrap();
for input in [
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input(),
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input(),
] {
zkvm.execute(&input).unwrap_err();
}
@@ -164,8 +171,8 @@ mod tests {
let zkvm = EreAirbender::new(program, ProverResourceType::Cpu).unwrap();
for input in [
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input(),
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input(),
] {
zkvm.prove(&input, ProofKind::default()).unwrap_err();
}

View File

@@ -60,6 +60,7 @@ mod tests {
use crate::{compiler::RustRv64imac, zkvm::EreJolt};
use ere_test_utils::host::testing_guest_directory;
use ere_zkvm_interface::{
Input,
compiler::Compiler,
zkvm::{ProverResourceType, zkVM},
};
@@ -77,6 +78,6 @@ mod tests {
let program = RustRv64imac.compile(&guest_directory).unwrap();
let zkvm = EreJolt::new(program, ProverResourceType::Cpu).unwrap();
zkvm.execute(&[]).unwrap();
zkvm.execute(&Input::default()).unwrap();
}
}

View File

@@ -4,7 +4,7 @@ use crate::{
};
use anyhow::bail;
use ere_zkvm_interface::zkvm::{
CommonError, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
CommonError, Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
ProverResourceType, PublicValues, zkVM,
};
use jolt_ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
@@ -32,9 +32,13 @@ impl EreJolt {
}
impl zkVM for EreJolt {
fn execute(&self, input: &[u8]) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
fn execute(&self, input: &Input) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
if input.proofs.is_some() {
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
}
let start = Instant::now();
let (public_values, total_num_cycles) = self.sdk.execute(input)?;
let (public_values, total_num_cycles) = self.sdk.execute(input.stdin())?;
let execution_duration = start.elapsed();
Ok((
@@ -49,17 +53,21 @@ impl zkVM for EreJolt {
fn prove(
&self,
input: &[u8],
input: &Input,
proof_kind: ProofKind,
) -> anyhow::Result<(PublicValues, Proof, ProgramProvingReport)> {
if input.proofs.is_some() {
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
}
if proof_kind != ProofKind::Compressed {
bail!(CommonError::unsupported_proof_kind(
proof_kind,
[ProofKind::Compressed]
))
}
let start = Instant::now();
let (public_values, proof) = self.sdk.prove(input)?;
let (public_values, proof) = self.sdk.prove(input.stdin())?;
let proving_time = start.elapsed();
let mut proof_bytes = Vec::new();
@@ -108,6 +116,7 @@ mod tests {
program::basic::BasicProgram,
};
use ere_zkvm_interface::{
Input,
compiler::Compiler,
zkvm::{ProofKind, ProverResourceType, zkVM},
};
@@ -144,8 +153,8 @@ mod tests {
let zkvm = EreJolt::new(program, ProverResourceType::Cpu).unwrap();
for input in [
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input(),
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input(),
] {
zkvm.execute(&input).unwrap_err();
}
@@ -170,8 +179,8 @@ mod tests {
let _guard = PROVE_LOCK.lock().unwrap();
for input in [
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input(),
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input(),
] {
zkvm.prove(&input, ProofKind::default()).unwrap_err();
}

View File

@@ -1,7 +1,7 @@
use crate::program::{MidenProgram, MidenProgramInfo, MidenSerdeWrapper};
use anyhow::bail;
use ere_zkvm_interface::zkvm::{
CommonError, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
CommonError, Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
ProverResourceType, PublicValues, zkVM, zkVMProgramDigest,
};
use miden_core::{
@@ -56,9 +56,13 @@ impl EreMiden {
}
impl zkVM for EreMiden {
fn execute(&self, input: &[u8]) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
fn execute(&self, input: &Input) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
if input.proofs.is_some() {
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
}
let stack_inputs = StackInputs::default();
let advice_inputs = AdviceInputs::default().with_stack(bytes_to_felts(input)?);
let advice_inputs = AdviceInputs::default().with_stack(bytes_to_felts(input.stdin())?);
let mut host = Self::setup_host()?;
let start = Instant::now();
@@ -84,9 +88,12 @@ impl zkVM for EreMiden {
fn prove(
&self,
input: &[u8],
input: &Input,
proof_kind: ProofKind,
) -> anyhow::Result<(PublicValues, Proof, ProgramProvingReport)> {
if input.proofs.is_some() {
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
}
if proof_kind != ProofKind::Compressed {
bail!(CommonError::unsupported_proof_kind(
proof_kind,
@@ -95,7 +102,7 @@ impl zkVM for EreMiden {
}
let stack_inputs = StackInputs::default();
let advice_inputs = AdviceInputs::default().with_stack(bytes_to_felts(input)?);
let advice_inputs = AdviceInputs::default().with_stack(bytes_to_felts(input.stdin())?);
let mut host = Self::setup_host()?;
let proving_options = ProvingOptions::with_128_bit_security(HashFunction::Blake3_256);
@@ -191,6 +198,7 @@ mod tests {
};
use ere_test_utils::host::testing_guest_directory;
use ere_zkvm_interface::{
Input,
compiler::Compiler,
zkvm::{ProofKind, ProverResourceType, zkVM},
};
@@ -213,7 +221,9 @@ mod tests {
let input = felts_to_bytes(&[const_a, const_b]);
// Prove
let (prover_public_values, proof, _) = zkvm.prove(&input, ProofKind::default()).unwrap();
let (prover_public_values, proof, _) = zkvm
.prove(&Input::new(input), ProofKind::default())
.unwrap();
// Verify
let verifier_public_values = zkvm.verify(&proof).unwrap();
@@ -235,7 +245,9 @@ mod tests {
let input = felts_to_bytes(&[Felt::from(0u32), Felt::from(1u32), Felt::from(n_iterations)]);
// Prove
let (prover_public_values, proof, _) = zkvm.prove(&input, ProofKind::default()).unwrap();
let (prover_public_values, proof, _) = zkvm
.prove(&Input::new(input), ProofKind::default())
.unwrap();
// Verify
let verifier_public_values = zkvm.verify(&proof).unwrap();
@@ -251,10 +263,10 @@ mod tests {
let program = load_miden_program("add");
let zkvm = EreMiden::new(program, ProverResourceType::Cpu).unwrap();
let empty_inputs = Vec::new();
let empty_inputs = Input::new(Vec::new());
assert!(zkvm.execute(&empty_inputs).is_err());
let insufficient_inputs = felts_to_bytes(&[Felt::from(5u32)]);
let insufficient_inputs = Input::new(felts_to_bytes(&[Felt::from(5u32)]));
assert!(zkvm.execute(&insufficient_inputs).is_err());
}
}

View File

@@ -1,7 +1,7 @@
use crate::program::NexusProgram;
use anyhow::bail;
use ere_zkvm_interface::zkvm::{
CommonError, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
CommonError, Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
ProverResourceType, PublicValues, zkVM,
};
use nexus_core::nvm::{self, ElfFile};
@@ -40,15 +40,19 @@ impl EreNexus {
}
impl zkVM for EreNexus {
fn execute(&self, input: &[u8]) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
fn execute(&self, input: &Input) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
if input.proofs.is_some() {
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
}
let elf = ElfFile::from_bytes(self.program.elf()).map_err(Error::ParseElf)?;
// Nexus sdk does not provide a trace, so we need to use core `nvm`
// Encoding is copied directly from `prove_with_input`
let mut private_encoded = if input.is_empty() {
let mut private_encoded = if input.stdin().is_empty() {
Vec::new()
} else {
postcard::to_stdvec_cobs(&input)
postcard::to_stdvec_cobs(&input.stdin())
.map_err(|err| CommonError::serialize("input", "postcard", err))?
};
@@ -79,9 +83,12 @@ impl zkVM for EreNexus {
fn prove(
&self,
input: &[u8],
input: &Input,
proof_kind: ProofKind,
) -> anyhow::Result<(PublicValues, Proof, ProgramProvingReport)> {
if input.proofs.is_some() {
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
}
if proof_kind != ProofKind::Compressed {
bail!(CommonError::unsupported_proof_kind(
proof_kind,
@@ -94,7 +101,9 @@ impl zkVM for EreNexus {
let prover = Stwo::new(&elf).map_err(Error::Prove)?;
let start = Instant::now();
let (view, proof) = prover.prove_with_input(&input, &()).map_err(Error::Prove)?;
let (view, proof) = prover
.prove_with_input(&input.stdin(), &())
.map_err(Error::Prove)?;
let proving_time = start.elapsed();
let public_values = view
@@ -164,6 +173,7 @@ mod tests {
program::basic::BasicProgram,
};
use ere_zkvm_interface::{
Input,
compiler::Compiler,
zkvm::{ProofKind, ProverResourceType, zkVM},
};
@@ -195,8 +205,8 @@ mod tests {
let zkvm = EreNexus::new(program, ProverResourceType::Cpu).unwrap();
for input in [
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input(),
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input(),
] {
zkvm.execute(&input).unwrap_err();
}
@@ -217,8 +227,8 @@ mod tests {
let zkvm = EreNexus::new(program, ProverResourceType::Cpu).unwrap();
for input in [
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input(),
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input(),
] {
zkvm.prove(&input, ProofKind::default()).unwrap_err();
}

View File

@@ -61,6 +61,7 @@ mod tests {
use crate::{compiler::RustRv32ima, zkvm::EreOpenVM};
use ere_test_utils::host::testing_guest_directory;
use ere_zkvm_interface::{
Input,
compiler::Compiler,
zkvm::{ProverResourceType, zkVM},
};
@@ -78,6 +79,6 @@ mod tests {
let program = RustRv32ima.compile(&guest_directory).unwrap();
let zkvm = EreOpenVM::new(program, ProverResourceType::Cpu).unwrap();
zkvm.execute(&[]).unwrap();
zkvm.execute(&Input::default()).unwrap();
}
}

View File

@@ -1,7 +1,7 @@
use crate::program::OpenVMProgram;
use anyhow::bail;
use ere_zkvm_interface::zkvm::{
CommonError, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
CommonError, Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
ProverResourceType, PublicValues, zkVM, zkVMProgramDigest,
};
use openvm_circuit::arch::instructions::exe::VmExe;
@@ -122,9 +122,13 @@ impl EreOpenVM {
}
impl zkVM for EreOpenVM {
fn execute(&self, input: &[u8]) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
fn execute(&self, input: &Input) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
if input.proofs.is_some() {
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
}
let mut stdin = StdIn::default();
stdin.write_bytes(input);
stdin.write_bytes(input.stdin());
let start = Instant::now();
let public_values = self
@@ -143,9 +147,12 @@ impl zkVM for EreOpenVM {
fn prove(
&self,
input: &[u8],
input: &Input,
proof_kind: ProofKind,
) -> anyhow::Result<(PublicValues, Proof, ProgramProvingReport)> {
if input.proofs.is_some() {
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
}
if proof_kind != ProofKind::Compressed {
bail!(CommonError::unsupported_proof_kind(
proof_kind,
@@ -154,7 +161,7 @@ impl zkVM for EreOpenVM {
}
let mut stdin = StdIn::default();
stdin.write_bytes(input);
stdin.write_bytes(input.stdin());
let now = std::time::Instant::now();
let (proof, app_commit) = match self.resource {
@@ -255,7 +262,7 @@ mod tests {
};
use ere_zkvm_interface::{
compiler::Compiler,
zkvm::{ProofKind, ProverResourceType, zkVM},
zkvm::{Input, ProofKind, ProverResourceType, zkVM},
};
use std::sync::OnceLock;
@@ -285,8 +292,8 @@ mod tests {
let zkvm = EreOpenVM::new(program, ProverResourceType::Cpu).unwrap();
for input in [
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input(),
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input(),
] {
zkvm.execute(&input).unwrap_err();
}
@@ -307,8 +314,8 @@ mod tests {
let zkvm = EreOpenVM::new(program, ProverResourceType::Cpu).unwrap();
for input in [
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input(),
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input(),
] {
zkvm.prove(&input, ProofKind::default()).unwrap_err();
}

View File

@@ -52,6 +52,7 @@ mod tests {
use crate::{compiler::RustRv32ima, zkvm::ErePico};
use ere_test_utils::host::testing_guest_directory;
use ere_zkvm_interface::{
Input,
compiler::Compiler,
zkvm::{ProverResourceType, zkVM},
};
@@ -69,6 +70,6 @@ mod tests {
let program = RustRv32ima.compile(&guest_directory).unwrap();
let zkvm = ErePico::new(program, ProverResourceType::Cpu).unwrap();
zkvm.execute(&[]).unwrap();
zkvm.execute(&Input::default()).unwrap();
}
}

View File

@@ -4,7 +4,7 @@ use crate::{
};
use anyhow::bail;
use ere_zkvm_interface::zkvm::{
CommonError, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
CommonError, Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
ProverResourceType, PublicValues, zkVM, zkVMProgramDigest,
};
use pico_p3_field::PrimeField32;
@@ -44,9 +44,13 @@ impl ErePico {
}
impl zkVM for ErePico {
fn execute(&self, input: &[u8]) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
fn execute(&self, input: &Input) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
if input.proofs.is_some() {
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
}
let mut stdin = EmulatorStdinBuilder::default();
stdin.write_slice(input);
stdin.write_slice(input.stdin());
let ((total_num_cycles, region_cycles, public_values), execution_duration) =
panic::catch_unwind(|| {
@@ -69,9 +73,12 @@ impl zkVM for ErePico {
fn prove(
&self,
input: &[u8],
input: &Input,
proof_kind: ProofKind,
) -> anyhow::Result<(PublicValues, Proof, ProgramProvingReport)> {
if input.proofs.is_some() {
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
}
if proof_kind != ProofKind::Compressed {
bail!(CommonError::unsupported_proof_kind(
proof_kind,
@@ -80,7 +87,7 @@ impl zkVM for ErePico {
}
let mut stdin = EmulatorStdinBuilder::default();
stdin.write_slice(input);
stdin.write_slice(input.stdin());
let ((public_values, proof), proving_time) = panic::catch_unwind(|| {
let client = self.client();
@@ -188,7 +195,7 @@ mod tests {
};
use ere_zkvm_interface::{
compiler::Compiler,
zkvm::{ProofKind, ProverResourceType, zkVM},
zkvm::{Input, ProofKind, ProverResourceType, zkVM},
};
use std::sync::OnceLock;
@@ -218,8 +225,8 @@ mod tests {
let zkvm = ErePico::new(program, ProverResourceType::Cpu).unwrap();
for input in [
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input(),
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input(),
] {
zkvm.execute(&input).unwrap_err();
}
@@ -240,8 +247,8 @@ mod tests {
let zkvm = ErePico::new(program, ProverResourceType::Cpu).unwrap();
for input in [
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input(),
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input(),
] {
zkvm.prove(&input, ProofKind::default()).unwrap_err();
}

View File

@@ -7,7 +7,7 @@ license.workspace = true
[dependencies]
anyhow.workspace = true
borsh.workspace = true
bincode.workspace = true
serde = { workspace = true, features = ["derive"] }
thiserror.workspace = true
tracing.workspace = true

View File

@@ -64,6 +64,7 @@ mod tests {
use crate::{compiler::RustRv32ima, zkvm::EreRisc0};
use ere_test_utils::host::testing_guest_directory;
use ere_zkvm_interface::{
Input,
compiler::Compiler,
zkvm::{ProverResourceType, zkVM},
};
@@ -81,6 +82,6 @@ mod tests {
let program = RustRv32ima.compile(&guest_directory).unwrap();
let zkvm = EreRisc0::new(program, ProverResourceType::Cpu).unwrap();
zkvm.execute(&[]).unwrap();
zkvm.execute(&Input::default()).unwrap();
}
}

View File

@@ -1,12 +1,12 @@
use crate::program::Risc0Program;
use anyhow::bail;
use ere_zkvm_interface::zkvm::{
CommonError, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
CommonError, Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
ProverResourceType, PublicValues, zkVM, zkVMProgramDigest,
};
use risc0_zkvm::{
DEFAULT_MAX_PO2, DefaultProver, Digest, ExecutorEnv, ExternalProver, InnerReceipt, ProverOpts,
Receipt, default_executor, default_prover,
AssumptionReceipt, DEFAULT_MAX_PO2, DefaultProver, Digest, ExecutorEnv, ExternalProver,
InnerReceipt, ProverOpts, Receipt, default_executor, default_prover,
};
use std::{env, ops::RangeInclusive, rc::Rc, time::Instant};
@@ -82,13 +82,10 @@ impl EreRisc0 {
}
impl zkVM for EreRisc0 {
fn execute(&self, input: &[u8]) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
fn execute(&self, input: &Input) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
let env = self.input_to_env(input)?;
let executor = default_executor();
let env = ExecutorEnv::builder()
.write_slice(&(input.len() as u32).to_le_bytes())
.write_slice(input)
.build()
.map_err(Error::BuildExecutorEnv)?;
let start = Instant::now();
let session_info = executor
@@ -109,9 +106,11 @@ impl zkVM for EreRisc0 {
fn prove(
&self,
input: &[u8],
input: &Input,
proof_kind: ProofKind,
) -> anyhow::Result<(PublicValues, Proof, ProgramProvingReport)> {
let env = self.input_to_env(input)?;
let prover = match self.resource {
ProverResourceType::Cpu => Rc::new(ExternalProver::new("ipc", "r0vm")),
ProverResourceType::Gpu => {
@@ -135,14 +134,6 @@ impl zkVM for EreRisc0 {
}
};
let env = ExecutorEnv::builder()
.write_slice(&(input.len() as u32).to_le_bytes())
.write_slice(input)
.segment_limit_po2(self.segment_po2 as _)
.keccak_max_po2(self.keccak_po2 as _)
.and_then(|builder| builder.build())
.map_err(Error::BuildExecutorEnv)?;
let opts = match proof_kind {
ProofKind::Compressed => ProverOpts::succinct(),
ProofKind::Groth16 => ProverOpts::groth16(),
@@ -157,8 +148,8 @@ impl zkVM for EreRisc0 {
let public_values = prove_info.receipt.journal.bytes.clone();
let proof = Proof::new(
proof_kind,
borsh::to_vec(&prove_info.receipt)
.map_err(|err| CommonError::serialize("proof", "borsh", err))?,
bincode::serde::encode_to_vec(&prove_info.receipt, bincode::config::legacy())
.map_err(|err| CommonError::serialize("proof", "bincode", err))?,
);
Ok((
@@ -171,8 +162,9 @@ impl zkVM for EreRisc0 {
fn verify(&self, proof: &Proof) -> anyhow::Result<PublicValues> {
let proof_kind = proof.kind();
let receipt: Receipt = borsh::from_slice(proof.as_bytes())
.map_err(|err| CommonError::deserialize("proof", "borsh", err))?;
let (receipt, _): (Receipt, _) =
bincode::serde::decode_from_slice(proof.as_bytes(), bincode::config::legacy())
.map_err(|err| CommonError::deserialize("proof", "bincode", err))?;
if !matches!(
(proof_kind, &receipt.inner),
@@ -215,6 +207,23 @@ impl zkVMProgramDigest for EreRisc0 {
}
}
impl EreRisc0 {
fn input_to_env(&self, input: &Input) -> Result<ExecutorEnv<'static>, Error> {
let mut env = ExecutorEnv::builder();
env.segment_limit_po2(self.segment_po2 as _)
.keccak_max_po2(self.keccak_po2 as _)
.expect("keccak_po2 in valid range");
env.write_slice(&(input.stdin().len() as u32).to_le_bytes())
.write_slice(input.stdin());
if let Some(receipts) = input.proofs() {
for receipt in receipts.map_err(Error::DeserializeInputProofs)? {
env.add_assumption(AssumptionReceipt::Proven(receipt));
}
}
env.build().map_err(Error::BuildExecutorEnv)
}
}
#[cfg(test)]
mod tests {
use crate::{compiler::RustRv32imaCustomized, program::Risc0Program, zkvm::EreRisc0};
@@ -224,6 +233,7 @@ mod tests {
program::basic::BasicProgram,
};
use ere_zkvm_interface::{
Input,
compiler::Compiler,
zkvm::{ProofKind, ProverResourceType, zkVM},
};
@@ -255,8 +265,8 @@ mod tests {
let zkvm = EreRisc0::new(program, ProverResourceType::Cpu).unwrap();
for input in [
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input(),
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input(),
] {
zkvm.execute(&input).unwrap_err();
}
@@ -277,8 +287,8 @@ mod tests {
let zkvm = EreRisc0::new(program, ProverResourceType::Cpu).unwrap();
for input in [
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input(),
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input(),
] {
zkvm.prove(&input, ProofKind::default()).unwrap_err();
}
@@ -293,7 +303,7 @@ mod tests {
for i in 1..=16_u32 {
let zkvm = EreRisc0::new(program.clone(), ProverResourceType::Cpu).unwrap();
let input = i.to_le_bytes();
let input = Input::new(i.to_le_bytes().to_vec());
if i.is_power_of_two() {
zkvm.execute(&input)

View File

@@ -4,6 +4,9 @@ use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {
#[error("Deserialize proofs in Input failed: {0:?}")]
DeserializeInputProofs(bincode::error::DecodeError),
// Execute
#[error("Failed to build `ExecutorEnv`: {0}")]
BuildExecutorEnv(anyhow::Error),

View File

@@ -52,6 +52,7 @@ mod tests {
use crate::{compiler::RustRv32ima, zkvm::EreSP1};
use ere_test_utils::host::testing_guest_directory;
use ere_zkvm_interface::{
Input,
compiler::Compiler,
zkvm::{ProverResourceType, zkVM},
};
@@ -69,6 +70,6 @@ mod tests {
let program = RustRv32ima.compile(&guest_directory).unwrap();
let zkvm = EreSP1::new(program, ProverResourceType::Cpu).unwrap();
zkvm.execute(&[]).unwrap();
zkvm.execute(&Input::default()).unwrap();
}
}

View File

@@ -1,7 +1,7 @@
use crate::{program::SP1Program, zkvm::sdk::Prover};
use anyhow::bail;
use ere_zkvm_interface::zkvm::{
CommonError, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
CommonError, Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
ProverResourceType, PublicValues, zkVM, zkVMProgramDigest,
};
use sp1_sdk::{SP1ProofMode, SP1ProofWithPublicValues, SP1ProvingKey, SP1Stdin, SP1VerifyingKey};
@@ -61,9 +61,8 @@ impl EreSP1 {
}
impl zkVM for EreSP1 {
fn execute(&self, input: &[u8]) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
let mut stdin = SP1Stdin::new();
stdin.write_slice(input);
fn execute(&self, input: &Input) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
let stdin = input_to_stdin(input)?;
let prover = self.prover()?;
@@ -83,13 +82,12 @@ impl zkVM for EreSP1 {
fn prove(
&self,
input: &[u8],
input: &Input,
proof_kind: ProofKind,
) -> anyhow::Result<(PublicValues, Proof, ProgramProvingReport)> {
info!("Generating proof…");
let mut stdin = SP1Stdin::new();
stdin.write_slice(input);
let stdin = input_to_stdin(input)?;
let mode = match proof_kind {
ProofKind::Compressed => SP1ProofMode::Compressed,
@@ -169,6 +167,17 @@ impl zkVMProgramDigest for EreSP1 {
}
}
fn input_to_stdin(input: &Input) -> Result<SP1Stdin, Error> {
let mut stdin = SP1Stdin::new();
stdin.write_slice(input.stdin());
if let Some(proofs) = input.proofs() {
for (proof, vk) in proofs.map_err(Error::DeserializeInputProofs)? {
stdin.write_proof(proof, vk);
}
}
Ok(stdin)
}
fn panic_msg(err: Box<dyn std::any::Any + Send + 'static>) -> String {
None.or_else(|| err.downcast_ref::<String>().cloned())
.or_else(|| err.downcast_ref::<&'static str>().map(ToString::to_string))
@@ -184,6 +193,7 @@ mod tests {
program::basic::BasicProgram,
};
use ere_zkvm_interface::{
Input,
compiler::Compiler,
zkvm::{NetworkProverConfig, ProofKind, ProverResourceType, zkVM},
};
@@ -215,8 +225,8 @@ mod tests {
let zkvm = EreSP1::new(program, ProverResourceType::Cpu).unwrap();
for input in [
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input(),
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input(),
] {
zkvm.execute(&input).unwrap_err();
}
@@ -237,8 +247,8 @@ mod tests {
let zkvm = EreSP1::new(program, ProverResourceType::Cpu).unwrap();
for input in [
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input(),
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input(),
] {
zkvm.prove(&input, ProofKind::default()).unwrap_err();
}

View File

@@ -10,6 +10,9 @@ pub enum Error {
#[error("Prover RwLock posioned, panic not catched properly")]
RwLockPosioned,
#[error("Deserialize proofs in Input failed: {0:?}")]
DeserializeInputProofs(bincode::error::DecodeError),
// Execute
#[error("SP1 execution failed: {0}")]
Execute(#[source] anyhow::Error),

View File

@@ -1,7 +1,7 @@
use crate::program::ZirenProgram;
use anyhow::bail;
use ere_zkvm_interface::zkvm::{
CommonError, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
CommonError, Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
ProverResourceType, PublicValues, zkVM, zkVMProgramDigest,
};
use std::{panic, time::Instant};
@@ -37,9 +37,8 @@ impl EreZiren {
}
impl zkVM for EreZiren {
fn execute(&self, input: &[u8]) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
let mut stdin = ZKMStdin::new();
stdin.write_slice(input);
fn execute(&self, input: &Input) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
let stdin = input_to_stdin(input)?;
let start = Instant::now();
let (public_inputs, exec_report) = CpuProver::new()
@@ -59,13 +58,12 @@ impl zkVM for EreZiren {
fn prove(
&self,
input: &[u8],
input: &Input,
proof_kind: ProofKind,
) -> anyhow::Result<(PublicValues, Proof, ProgramProvingReport)> {
info!("Generating proof…");
let mut stdin = ZKMStdin::new();
stdin.write_slice(input);
let stdin = input_to_stdin(input)?;
let inner_proof_kind = match proof_kind {
ProofKind::Compressed => ZKMProofKind::Compressed,
@@ -135,6 +133,17 @@ impl zkVMProgramDigest for EreZiren {
}
}
fn input_to_stdin(input: &Input) -> Result<ZKMStdin, Error> {
let mut stdin = ZKMStdin::new();
stdin.write_slice(input.stdin());
if let Some(proofs) = input.proofs() {
for (proof, vk) in proofs.map_err(Error::DeserializeInputProofs)? {
stdin.write_proof(proof, vk);
}
}
Ok(stdin)
}
fn panic_msg(err: Box<dyn std::any::Any + Send + 'static>) -> String {
None.or_else(|| err.downcast_ref::<String>().cloned())
.or_else(|| err.downcast_ref::<&'static str>().map(ToString::to_string))
@@ -151,7 +160,7 @@ mod tests {
};
use ere_zkvm_interface::{
compiler::Compiler,
zkvm::{ProofKind, ProverResourceType, zkVM},
zkvm::{Input, ProofKind, ProverResourceType, zkVM},
};
use std::sync::OnceLock;
@@ -181,8 +190,8 @@ mod tests {
let zkvm = EreZiren::new(program, ProverResourceType::Cpu).unwrap();
for input in [
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input(),
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input(),
] {
zkvm.execute(&input).unwrap_err();
}
@@ -203,8 +212,8 @@ mod tests {
let zkvm = EreZiren::new(program, ProverResourceType::Cpu).unwrap();
for input in [
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input(),
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input(),
] {
zkvm.prove(&input, ProofKind::default()).unwrap_err();
}

View File

@@ -8,6 +8,9 @@ pub enum Error {
#[error("Ziren execution failed: {0}")]
Execute(#[source] anyhow::Error),
#[error("Deserialize proofs in Input failed: {0:?}")]
DeserializeInputProofs(bincode::error::DecodeError),
// Prove
#[error("Ziren proving failed: {0}")]
Prove(#[source] anyhow::Error),

View File

@@ -4,7 +4,7 @@ use crate::{
};
use anyhow::bail;
use ere_zkvm_interface::zkvm::{
CommonError, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
CommonError, Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
ProverResourceType, PublicValues, zkVM, zkVMProgramDigest,
};
use std::{
@@ -68,9 +68,13 @@ impl EreZisk {
}
impl zkVM for EreZisk {
fn execute(&self, input: &[u8]) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
fn execute(&self, input: &Input) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
if input.proofs.is_some() {
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
}
let start = Instant::now();
let (public_values, total_num_cycles) = self.sdk.execute(input)?;
let (public_values, total_num_cycles) = self.sdk.execute(input.stdin())?;
let execution_duration = start.elapsed();
Ok((
@@ -85,9 +89,12 @@ impl zkVM for EreZisk {
fn prove(
&self,
input: &[u8],
input: &Input,
proof_kind: ProofKind,
) -> anyhow::Result<(PublicValues, Proof, ProgramProvingReport)> {
if input.proofs.is_some() {
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
}
if proof_kind != ProofKind::Compressed {
bail!(CommonError::unsupported_proof_kind(
proof_kind,
@@ -99,7 +106,7 @@ impl zkVM for EreZisk {
let server = server.as_mut().expect("server initialized");
let start = Instant::now();
let (public_values, proof) = server.prove(input)?;
let (public_values, proof) = server.prove(input.stdin())?;
let proving_time = start.elapsed();
Ok((
@@ -147,7 +154,7 @@ mod tests {
};
use ere_zkvm_interface::{
compiler::Compiler,
zkvm::{ProofKind, ProverResourceType, zkVM},
zkvm::{Input, ProofKind, ProverResourceType, zkVM},
};
use std::sync::{Mutex, OnceLock};
@@ -181,8 +188,8 @@ mod tests {
let zkvm = EreZisk::new(program, ProverResourceType::Cpu).unwrap();
for input in [
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input(),
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input(),
] {
zkvm.execute(&input).unwrap_err();
}
@@ -207,8 +214,8 @@ mod tests {
let _guard = PROVE_LOCK.lock().unwrap();
for input in [
Vec::new(),
BasicProgram::<BincodeLegacy>::invalid_test_case().serialized_input(),
Input::default(),
BasicProgram::<BincodeLegacy>::invalid_test_case().input(),
] {
zkvm.prove(&input, ProofKind::default()).unwrap_err();
}