mirror of
https://github.com/eth-act/ere.git
synced 2026-04-03 03:00:17 -04:00
Complete ere-pico (#139)
This commit is contained in:
39
Cargo.lock
generated
39
Cargo.lock
generated
@@ -3696,9 +3696,11 @@ dependencies = [
|
||||
"bincode 1.3.3",
|
||||
"build-utils",
|
||||
"cargo_metadata 0.19.2",
|
||||
"pico-sdk",
|
||||
"p3-field 0.1.0 (git+https://github.com/brevis-network/Plonky3.git?rev=a4d376b)",
|
||||
"pico-vm",
|
||||
"serde",
|
||||
"sha2",
|
||||
"tempfile",
|
||||
"test-utils",
|
||||
"thiserror 2.0.12",
|
||||
"zkvm-interface",
|
||||
@@ -9628,41 +9630,6 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pico-patch-libs"
|
||||
version = "1.1.6"
|
||||
source = "git+https://github.com/brevis-network/pico.git?tag=v1.1.7#79b10e613c3a0dd2a92d2a65a149d853f4aface2"
|
||||
dependencies = [
|
||||
"bincode 1.3.3",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pico-sdk"
|
||||
version = "1.1.6"
|
||||
source = "git+https://github.com/brevis-network/pico.git?tag=v1.1.7#79b10e613c3a0dd2a92d2a65a149d853f4aface2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode 1.3.3",
|
||||
"cfg-if",
|
||||
"env_logger",
|
||||
"getrandom 0.2.16",
|
||||
"hex",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"p3-baby-bear 0.1.0 (git+https://github.com/brevis-network/Plonky3.git?rev=a4d376b)",
|
||||
"p3-challenger 0.1.0 (git+https://github.com/brevis-network/Plonky3.git?rev=a4d376b)",
|
||||
"p3-field 0.1.0 (git+https://github.com/brevis-network/Plonky3.git?rev=a4d376b)",
|
||||
"p3-koala-bear 0.1.0 (git+https://github.com/brevis-network/Plonky3.git?rev=a4d376b)",
|
||||
"p3-mersenne-31 0.1.0 (git+https://github.com/brevis-network/Plonky3.git?rev=a4d376b)",
|
||||
"pico-patch-libs",
|
||||
"pico-vm",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pico-vm"
|
||||
version = "1.1.6"
|
||||
|
||||
@@ -78,8 +78,8 @@ openvm-stark-sdk = { git = "https://github.com/openvm-org/stark-backend.git", ta
|
||||
openvm-transpiler = { git = "https://github.com/openvm-org/openvm.git", tag = "v1.4.0" }
|
||||
|
||||
# Pico dependencies
|
||||
pico-p3-field = { git = "https://github.com/brevis-network/Plonky3.git", package = "p3-field", rev = "a4d376b" }
|
||||
pico-vm = { git = "https://github.com/brevis-network/pico.git", tag = "v1.1.7" }
|
||||
pico-sdk = { git = "https://github.com/brevis-network/pico.git", tag = "v1.1.7" }
|
||||
|
||||
# Risc0 dependencies
|
||||
risc0-build = "3.0.3"
|
||||
|
||||
@@ -31,7 +31,7 @@ fn generate_zkvm_sdk_version_impl() {
|
||||
"jolt-sdk",
|
||||
"nexus-sdk",
|
||||
"openvm-sdk",
|
||||
"pico-sdk",
|
||||
"pico-vm",
|
||||
"risc0-zkvm",
|
||||
"sp1-sdk",
|
||||
"zkm-sdk",
|
||||
|
||||
@@ -9,12 +9,14 @@ license.workspace = true
|
||||
anyhow.workspace = true
|
||||
bincode.workspace = true
|
||||
cargo_metadata.workspace = true
|
||||
sha2.workspace = true
|
||||
serde.workspace = true
|
||||
tempfile.workspace = true
|
||||
thiserror.workspace = true
|
||||
|
||||
# Pico dependencies
|
||||
pico-p3-field.workspace = true
|
||||
pico-vm.workspace = true
|
||||
pico-sdk.workspace = true
|
||||
|
||||
# Local dependencies
|
||||
zkvm-interface.workspace = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use build_utils::detect_and_generate_name_and_sdk_version;
|
||||
|
||||
fn main() {
|
||||
detect_and_generate_name_and_sdk_version("pico", "pico-sdk");
|
||||
detect_and_generate_name_and_sdk_version("pico", "pico-vm");
|
||||
}
|
||||
|
||||
99
crates/ere-pico/src/client.rs
Normal file
99
crates/ere-pico/src/client.rs
Normal file
@@ -0,0 +1,99 @@
|
||||
// Copied and modified from https://github.com/brevis-network/pico/blob/v1.1.7/sdk/sdk/src/client.rs.
|
||||
// The `EmbedProver` is removed because we don't need the proof to be verified
|
||||
// on chain. Issue for tracking: https://github.com/eth-act/ere/issues/140.
|
||||
|
||||
use anyhow::{Error, Ok, Result};
|
||||
use pico_vm::{
|
||||
compiler::riscv::program::Program,
|
||||
configs::{config::StarkGenericConfig, stark_config::KoalaBearPoseidon2},
|
||||
emulator::stdin::EmulatorStdinBuilder,
|
||||
instances::compiler::shapes::{
|
||||
recursion_shape::RecursionShapeConfig, riscv_shape::RiscvShapeConfig,
|
||||
},
|
||||
machine::proof,
|
||||
proverchain::{
|
||||
CombineProver, CompressProver, ConvertProver, InitialProverSetup, MachineProver,
|
||||
ProverChain, RiscvProver,
|
||||
},
|
||||
};
|
||||
use zkvm_interface::PublicValues;
|
||||
|
||||
pub type SC = KoalaBearPoseidon2;
|
||||
pub type MetaProof = proof::MetaProof<SC>;
|
||||
|
||||
pub struct ProverClient {
|
||||
riscv: RiscvProver<SC, Program>,
|
||||
convert: ConvertProver<SC, SC>,
|
||||
combine: CombineProver<SC, SC>,
|
||||
compress: CompressProver<SC, SC>,
|
||||
}
|
||||
|
||||
impl ProverClient {
|
||||
pub fn new(elf: &[u8]) -> Self {
|
||||
let riscv = RiscvProver::new_initial_prover(
|
||||
(SC::new(), elf),
|
||||
Default::default(),
|
||||
Some(RiscvShapeConfig::default()),
|
||||
);
|
||||
let convert = ConvertProver::new_with_prev(
|
||||
&riscv,
|
||||
Default::default(),
|
||||
Some(RecursionShapeConfig::default()),
|
||||
);
|
||||
let combine = CombineProver::new_with_prev(
|
||||
&convert,
|
||||
Default::default(),
|
||||
Some(RecursionShapeConfig::default()),
|
||||
);
|
||||
let compress = CompressProver::new_with_prev(&combine, (), None);
|
||||
Self {
|
||||
riscv,
|
||||
convert,
|
||||
combine,
|
||||
compress,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_stdin_builder(&self) -> EmulatorStdinBuilder<Vec<u8>, SC> {
|
||||
EmulatorStdinBuilder::default()
|
||||
}
|
||||
|
||||
/// Execute the program and return the cycles and public values
|
||||
pub fn execute(&self, stdin: EmulatorStdinBuilder<Vec<u8>, SC>) -> (u64, Vec<u8>) {
|
||||
let (stdin, _) = stdin.finalize();
|
||||
self.riscv.emulate(stdin)
|
||||
}
|
||||
|
||||
/// Prove until `CompressProver`.
|
||||
pub fn prove(
|
||||
&self,
|
||||
stdin: EmulatorStdinBuilder<Vec<u8>, SC>,
|
||||
) -> Result<(PublicValues, MetaProof), Error> {
|
||||
let (stdin, _) = stdin.finalize();
|
||||
let riscv_proof = self.riscv.prove(stdin);
|
||||
if !self.riscv.verify(&riscv_proof.clone(), self.riscv.vk()) {
|
||||
return Err(Error::msg("verify riscv proof failed"));
|
||||
}
|
||||
let proof = self.convert.prove(riscv_proof.clone());
|
||||
if !self.convert.verify(&proof, self.riscv.vk()) {
|
||||
return Err(Error::msg("verify convert proof failed"));
|
||||
}
|
||||
let proof = self.combine.prove(proof);
|
||||
if !self.combine.verify(&proof, self.riscv.vk()) {
|
||||
return Err(Error::msg("verify combine proof failed"));
|
||||
}
|
||||
let proof = self.compress.prove(proof);
|
||||
if !self.compress.verify(&proof, self.riscv.vk()) {
|
||||
return Err(Error::msg("verify compress proof failed"));
|
||||
}
|
||||
Ok((riscv_proof.pv_stream.clone().unwrap_or_default(), proof))
|
||||
}
|
||||
|
||||
/// Verify a compressed proof.
|
||||
pub fn verify(&self, proof: &MetaProof) -> Result<(), Error> {
|
||||
if !self.compress.verify(proof, self.riscv.vk()) {
|
||||
return Err(Error::msg("verify compress proof failed"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::error::PicoError;
|
||||
use crate::error::CompileError;
|
||||
use cargo_metadata::MetadataCommand;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
@@ -38,18 +38,18 @@ const CARGO_ARGS: &[&str] = &[
|
||||
pub fn compile_pico_program_stock_rust(
|
||||
guest_directory: &Path,
|
||||
toolchain: &String,
|
||||
) -> Result<Vec<u8>, PicoError> {
|
||||
) -> Result<Vec<u8>, CompileError> {
|
||||
compile_program_stock_rust(guest_directory, toolchain)
|
||||
}
|
||||
|
||||
fn compile_program_stock_rust(
|
||||
guest_directory: &Path,
|
||||
toolchain: &String,
|
||||
) -> Result<Vec<u8>, PicoError> {
|
||||
) -> Result<Vec<u8>, CompileError> {
|
||||
let metadata = MetadataCommand::new().current_dir(guest_directory).exec()?;
|
||||
let package = metadata
|
||||
.root_package()
|
||||
.ok_or_else(|| PicoError::MissingPackageName {
|
||||
.ok_or_else(|| CompileError::MissingPackageName {
|
||||
path: guest_directory.to_path_buf(),
|
||||
})?;
|
||||
|
||||
@@ -76,7 +76,7 @@ fn compile_program_stock_rust(
|
||||
.stdout(std::process::Stdio::inherit())
|
||||
.stderr(std::process::Stdio::inherit())
|
||||
.status()
|
||||
.map_err(|source| PicoError::BuildFailure {
|
||||
.map_err(|source| CompileError::BuildFailure {
|
||||
source: source.into(),
|
||||
crate_path: guest_directory.to_path_buf(),
|
||||
});
|
||||
@@ -87,7 +87,7 @@ fn compile_program_stock_rust(
|
||||
|
||||
let elf_path = target_direcotry.join(&package.name);
|
||||
|
||||
fs::read(&elf_path).map_err(|e| PicoError::ReadFile {
|
||||
fs::read(&elf_path).map_err(|e| CompileError::ReadFile {
|
||||
path: elf_path,
|
||||
source: e,
|
||||
})
|
||||
|
||||
@@ -10,22 +10,35 @@ impl From<PicoError> for zkVMError {
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum PicoError {
|
||||
#[error(transparent)]
|
||||
Compile(#[from] CompileError),
|
||||
|
||||
#[error(transparent)]
|
||||
Execute(#[from] ExecuteError),
|
||||
|
||||
#[error(transparent)]
|
||||
Prove(#[from] ProveError),
|
||||
|
||||
#[error(transparent)]
|
||||
Verify(#[from] VerifyError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum CompileError {
|
||||
#[error("Failed to create temporary directory: {0}")]
|
||||
Tempdir(io::Error),
|
||||
/// Guest program directory does not exist.
|
||||
#[error("guest program directory not found: {0}")]
|
||||
PathNotFound(PathBuf),
|
||||
|
||||
/// Failed to spawn or run `cargo pico build`.
|
||||
#[error("failed to run `cargo pico build`: {0}")]
|
||||
Spawn(#[from] io::Error),
|
||||
|
||||
CargoPicoBuild(#[from] io::Error),
|
||||
/// `cargo pico build` exited with a non-zero status.
|
||||
#[error("`cargo pico build` failed with status {status:?}")]
|
||||
CargoFailed { status: ExitStatus },
|
||||
|
||||
CargoPicoBuildFailed { status: ExitStatus },
|
||||
/// Expected ELF file was not produced.
|
||||
#[error("ELF file not found at {0}")]
|
||||
ElfNotFound(PathBuf),
|
||||
|
||||
/// Reading the ELF file failed.
|
||||
#[error("failed to read ELF file at {path}: {source}")]
|
||||
ReadElf {
|
||||
@@ -50,3 +63,33 @@ pub enum PicoError {
|
||||
#[error("`cargo metadata` failed: {0}")]
|
||||
MetadataCommand(#[from] cargo_metadata::Error),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ExecuteError {
|
||||
#[error("Pico execution failed: {0}")]
|
||||
Client(anyhow::Error),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ProveError {
|
||||
#[error("Pico proving failed: {0}")]
|
||||
Client(anyhow::Error),
|
||||
#[error("Serialising proof with `bincode` failed: {0}")]
|
||||
Bincode(#[from] bincode::Error),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum VerifyError {
|
||||
#[error("Pico verifying failed: {0}")]
|
||||
Client(anyhow::Error),
|
||||
#[error("Deserialising proof with `bincode` failed: {0}")]
|
||||
Bincode(#[from] bincode::Error),
|
||||
#[error("Invalid base proof length {0}, expected 1")]
|
||||
InvalidBaseProofLength(usize),
|
||||
#[error("Invalid public values length {0}, expected at least 32")]
|
||||
InvalidPublicValuesLength(usize),
|
||||
#[error("First 32 public values are expected in byte")]
|
||||
InvalidPublicValues,
|
||||
#[error("Public values digest are expected in bytes")]
|
||||
InvalidPublicValuesDigest,
|
||||
}
|
||||
|
||||
@@ -1,20 +1,32 @@
|
||||
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
|
||||
|
||||
use compile_stock_rust::compile_pico_program_stock_rust;
|
||||
use pico_sdk::client::DefaultProverClient;
|
||||
use crate::{
|
||||
client::{MetaProof, ProverClient},
|
||||
compile_stock_rust::compile_pico_program_stock_rust,
|
||||
error::{CompileError, PicoError, ProveError, VerifyError},
|
||||
};
|
||||
use pico_p3_field::PrimeField32;
|
||||
use pico_vm::{configs::stark_config::KoalaBearPoseidon2, emulator::stdin::EmulatorStdinBuilder};
|
||||
use serde::de::DeserializeOwned;
|
||||
use std::{env, io::Read, path::Path, process::Command, time::Instant};
|
||||
use serde::{Deserialize, Serialize, de::DeserializeOwned};
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::{
|
||||
env, fs,
|
||||
io::Read,
|
||||
path::Path,
|
||||
process::Command,
|
||||
time::{self, Instant},
|
||||
};
|
||||
use tempfile::tempdir;
|
||||
use zkvm_interface::{
|
||||
Compiler, Input, InputItem, ProgramExecutionReport, ProgramProvingReport, Proof,
|
||||
ProverResourceType, PublicValues, zkVM, zkVMError,
|
||||
};
|
||||
|
||||
mod compile_stock_rust;
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/name_and_sdk_version.rs"));
|
||||
|
||||
mod client;
|
||||
mod compile_stock_rust;
|
||||
mod error;
|
||||
use error::PicoError;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct PICO_TARGET;
|
||||
@@ -36,32 +48,36 @@ impl Compiler for PICO_TARGET {
|
||||
}
|
||||
}
|
||||
|
||||
fn compile_pico_program(guest_directory: &Path) -> Result<Vec<u8>, PicoError> {
|
||||
fn compile_pico_program(guest_directory: &Path) -> Result<Vec<u8>, CompileError> {
|
||||
let tempdir = tempdir().map_err(CompileError::Tempdir)?;
|
||||
|
||||
// 1. Check guest path
|
||||
if !guest_directory.exists() {
|
||||
return Err(PicoError::PathNotFound(guest_directory.to_path_buf()));
|
||||
return Err(CompileError::PathNotFound(guest_directory.to_path_buf()));
|
||||
}
|
||||
|
||||
// 2. Run `cargo pico build`
|
||||
let status = Command::new("cargo")
|
||||
.current_dir(guest_directory)
|
||||
.env("RUST_LOG", "info")
|
||||
.args(["pico", "build"])
|
||||
.status()?; // From<io::Error> → Spawn
|
||||
.args(["pico", "build", "--output-directory"])
|
||||
.arg(tempdir.path())
|
||||
.status()
|
||||
.map_err(CompileError::CargoPicoBuild)?;
|
||||
|
||||
if !status.success() {
|
||||
return Err(PicoError::CargoFailed { status });
|
||||
return Err(CompileError::CargoPicoBuildFailed { status });
|
||||
}
|
||||
|
||||
// 3. Locate the ELF file
|
||||
let elf_path = guest_directory.join("elf/riscv32im-pico-zkvm-elf");
|
||||
let elf_path = tempdir.path().join("riscv32im-pico-zkvm-elf");
|
||||
|
||||
if !elf_path.exists() {
|
||||
return Err(PicoError::ElfNotFound(elf_path));
|
||||
return Err(CompileError::ElfNotFound(elf_path));
|
||||
}
|
||||
|
||||
// 4. Read the ELF file
|
||||
let elf_bytes = std::fs::read(&elf_path).map_err(|e| PicoError::ReadElf {
|
||||
let elf_bytes = fs::read(&elf_path).map_err(|e| CompileError::ReadElf {
|
||||
path: elf_path,
|
||||
source: e,
|
||||
})?;
|
||||
@@ -69,29 +85,38 @@ fn compile_pico_program(guest_directory: &Path) -> Result<Vec<u8>, PicoError> {
|
||||
Ok(elf_bytes)
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct PicoProofWithPublicValues {
|
||||
proof: MetaProof,
|
||||
public_values: Vec<u8>,
|
||||
}
|
||||
|
||||
pub struct ErePico {
|
||||
program: <PICO_TARGET as Compiler>::Program,
|
||||
}
|
||||
|
||||
impl ErePico {
|
||||
pub fn new(
|
||||
program_bytes: <PICO_TARGET as Compiler>::Program,
|
||||
_resource_type: ProverResourceType,
|
||||
) -> Self {
|
||||
ErePico {
|
||||
program: program_bytes,
|
||||
pub fn new(program: <PICO_TARGET as Compiler>::Program, resource: ProverResourceType) -> Self {
|
||||
if !matches!(resource, ProverResourceType::Cpu) {
|
||||
panic!("Network or GPU proving not yet implemented for Pico. Use CPU resource type.");
|
||||
}
|
||||
ErePico { program }
|
||||
}
|
||||
|
||||
pub fn client(&self) -> ProverClient {
|
||||
ProverClient::new(&self.program)
|
||||
}
|
||||
}
|
||||
|
||||
impl zkVM for ErePico {
|
||||
fn execute(&self, inputs: &Input) -> Result<(PublicValues, ProgramExecutionReport), zkVMError> {
|
||||
let client = DefaultProverClient::new(&self.program);
|
||||
let client = self.client();
|
||||
|
||||
let mut stdin = client.new_stdin_builder();
|
||||
serialize_inputs(&mut stdin, inputs);
|
||||
|
||||
let start = Instant::now();
|
||||
let (total_num_cycles, public_values) = client.emulate(stdin);
|
||||
let (total_num_cycles, public_values) = client.execute(stdin);
|
||||
|
||||
Ok((
|
||||
public_values,
|
||||
@@ -107,47 +132,47 @@ impl zkVM for ErePico {
|
||||
&self,
|
||||
inputs: &Input,
|
||||
) -> Result<(PublicValues, Proof, zkvm_interface::ProgramProvingReport), zkVMError> {
|
||||
let client = DefaultProverClient::new(&self.program);
|
||||
let client = self.client();
|
||||
|
||||
let mut stdin = client.new_stdin_builder();
|
||||
serialize_inputs(&mut stdin, inputs);
|
||||
|
||||
let now = std::time::Instant::now();
|
||||
let meta_proof = client.prove(stdin).expect("Failed to generate proof");
|
||||
let now = time::Instant::now();
|
||||
let (public_values, proof) = client
|
||||
.prove(stdin)
|
||||
.map_err(|err| PicoError::Prove(ProveError::Client(err)))?;
|
||||
let elapsed = now.elapsed();
|
||||
|
||||
let mut proof_serialized = Vec::new();
|
||||
for p in meta_proof.0.proofs().iter() {
|
||||
bincode::serialize_into(&mut proof_serialized, p).unwrap();
|
||||
}
|
||||
for p in meta_proof.1.proofs().iter() {
|
||||
bincode::serialize_into(&mut proof_serialized, p).unwrap();
|
||||
}
|
||||
|
||||
for p in meta_proof.0.pv_stream.iter() {
|
||||
bincode::serialize_into(&mut proof_serialized, p).unwrap();
|
||||
}
|
||||
for p in meta_proof.1.pv_stream.iter() {
|
||||
bincode::serialize_into(&mut proof_serialized, p).unwrap();
|
||||
}
|
||||
|
||||
// TODO: Public values
|
||||
let public_values = Vec::new();
|
||||
let proof_bytes = bincode::serialize(&PicoProofWithPublicValues {
|
||||
proof,
|
||||
public_values: public_values.clone(),
|
||||
})
|
||||
.map_err(|err| PicoError::Prove(ProveError::Bincode(err)))?;
|
||||
|
||||
Ok((
|
||||
public_values,
|
||||
proof_serialized,
|
||||
proof_bytes,
|
||||
ProgramProvingReport::new(elapsed),
|
||||
))
|
||||
}
|
||||
|
||||
fn verify(&self, _proof: &[u8]) -> Result<PublicValues, zkVMError> {
|
||||
let client = DefaultProverClient::new(&self.program);
|
||||
let _vk = client.riscv_vk();
|
||||
// TODO: Verification method missing from sdk
|
||||
// TODO: Public values
|
||||
let public_values = Vec::new();
|
||||
Ok(public_values)
|
||||
fn verify(&self, proof: &[u8]) -> Result<PublicValues, zkVMError> {
|
||||
let client = self.client();
|
||||
|
||||
let proof: PicoProofWithPublicValues = bincode::deserialize(proof)
|
||||
.map_err(|err| PicoError::Verify(VerifyError::Bincode(err)))?;
|
||||
|
||||
client
|
||||
.verify(&proof.proof)
|
||||
.map_err(|err| PicoError::Verify(VerifyError::Client(err)))?;
|
||||
|
||||
if extract_public_values_sha256_digest(&proof.proof).map_err(PicoError::Verify)?
|
||||
!= <[u8; 32]>::from(Sha256::digest(&proof.public_values))
|
||||
{
|
||||
return Err(PicoError::Verify(VerifyError::InvalidPublicValuesDigest))?;
|
||||
}
|
||||
|
||||
Ok(proof.public_values)
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
@@ -174,11 +199,36 @@ fn serialize_inputs(stdin: &mut EmulatorStdinBuilder<Vec<u8>, KoalaBearPoseidon2
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract public values sha256 digest from base proof of compressed proof.
|
||||
/// The sha256 digest will be placed at the first 32 field elements of the
|
||||
/// public values of the only base proof.
|
||||
fn extract_public_values_sha256_digest(proof: &MetaProof) -> Result<[u8; 32], VerifyError> {
|
||||
if proof.proofs().len() != 1 {
|
||||
return Err(VerifyError::InvalidBaseProofLength(proof.proofs().len()));
|
||||
}
|
||||
|
||||
if proof.proofs()[0].public_values.len() < 32 {
|
||||
return Err(VerifyError::InvalidPublicValuesLength(
|
||||
proof.proofs()[0].public_values.len(),
|
||||
));
|
||||
}
|
||||
|
||||
Ok(proof.proofs()[0].public_values[..32]
|
||||
.iter()
|
||||
.map(|value| u8::try_from(value.as_canonical_u32()))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(|_| VerifyError::InvalidPublicValues)?
|
||||
.try_into()
|
||||
.unwrap())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::{panic, sync::OnceLock};
|
||||
use test_utils::host::{BasicProgramIo, run_zkvm_execute, testing_guest_directory};
|
||||
use test_utils::host::{
|
||||
BasicProgramIo, run_zkvm_execute, run_zkvm_prove, testing_guest_directory,
|
||||
};
|
||||
|
||||
static BASIC_PROGRAM: OnceLock<Vec<u8>> = OnceLock::new();
|
||||
|
||||
@@ -228,7 +278,30 @@ mod tests {
|
||||
BasicProgramIo::invalid_type,
|
||||
BasicProgramIo::invalid_data,
|
||||
] {
|
||||
panic::catch_unwind(|| zkvm.execute(&inputs_gen()).unwrap_err()).unwrap_err();
|
||||
panic::catch_unwind(|| zkvm.execute(&inputs_gen())).unwrap_err();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_prove() {
|
||||
let program = basic_program();
|
||||
let zkvm = ErePico::new(program, ProverResourceType::Cpu);
|
||||
|
||||
let io = BasicProgramIo::valid();
|
||||
run_zkvm_prove(&zkvm, &io);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_prove_invalid_inputs() {
|
||||
let program = basic_program();
|
||||
let zkvm = ErePico::new(program, ProverResourceType::Cpu);
|
||||
|
||||
for inputs_gen in [
|
||||
BasicProgramIo::empty,
|
||||
BasicProgramIo::invalid_type,
|
||||
BasicProgramIo::invalid_data,
|
||||
] {
|
||||
panic::catch_unwind(|| zkvm.prove(&inputs_gen())).unwrap_err();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ fn __start(_argc: isize, _argv: *const *const u8) -> isize {
|
||||
main();
|
||||
|
||||
syscall_halt(0);
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
/// Halts the program with the given exit code.
|
||||
|
||||
Reference in New Issue
Block a user