mirror of
https://github.com/eth-act/ere.git
synced 2026-04-03 03:00:17 -04:00
add initial pico compile code
This commit is contained in:
9
Cargo.lock
generated
9
Cargo.lock
generated
@@ -1791,6 +1791,15 @@ dependencies = [
|
||||
"zkvm-interface",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ere-pico"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"thiserror 2.0.12",
|
||||
"zkvm-interface",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ere-risczero"
|
||||
version = "0.1.0"
|
||||
|
||||
@@ -4,7 +4,7 @@ members = [
|
||||
"crates/zkvm-interface",
|
||||
# zkVMs
|
||||
"crates/ere-sp1",
|
||||
"crates/ere-risczero", "crates/ere-openvm",
|
||||
"crates/ere-risczero", "crates/ere-openvm", "crates/ere-pico",
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
|
||||
14
crates/ere-pico/Cargo.toml
Normal file
14
crates/ere-pico/Cargo.toml
Normal file
@@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "ere-pico"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
zkvm-interface = { workspace = true }
|
||||
thiserror = "2"
|
||||
anyhow = "*" #TOOD: remove for thiserror
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
29
crates/ere-pico/src/error.rs
Normal file
29
crates/ere-pico/src/error.rs
Normal file
@@ -0,0 +1,29 @@
|
||||
use std::{io, path::PathBuf, process::ExitStatus};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum PicoError {
|
||||
/// 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),
|
||||
|
||||
/// `cargo pico build` exited with a non-zero status.
|
||||
#[error("`cargo pico build` failed with status {status:?}")]
|
||||
CargoFailed { 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 {
|
||||
path: PathBuf,
|
||||
#[source]
|
||||
source: io::Error,
|
||||
},
|
||||
}
|
||||
91
crates/ere-pico/src/lib.rs
Normal file
91
crates/ere-pico/src/lib.rs
Normal file
@@ -0,0 +1,91 @@
|
||||
use std::process::Command;
|
||||
use zkvm_interface::Compiler;
|
||||
|
||||
mod error;
|
||||
use error::PicoError;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct PICO_TARGET;
|
||||
|
||||
impl Compiler for PICO_TARGET {
|
||||
type Error = PicoError;
|
||||
|
||||
type Program = Vec<u8>;
|
||||
|
||||
fn compile(path: &std::path::Path) -> Result<Self::Program, Self::Error> {
|
||||
// 1. Check guest path
|
||||
if !path.exists() {
|
||||
return Err(PicoError::PathNotFound(path.to_path_buf()));
|
||||
}
|
||||
|
||||
// 2. Run `cargo pico build`
|
||||
let status = Command::new("cargo")
|
||||
.current_dir(path)
|
||||
.env("RUST_LOG", "info")
|
||||
.args(["pico", "build"])
|
||||
.status()?; // From<io::Error> → Spawn
|
||||
|
||||
if !status.success() {
|
||||
return Err(PicoError::CargoFailed { status });
|
||||
}
|
||||
|
||||
// 3. Locate the ELF file
|
||||
let elf_path = path
|
||||
.parent()
|
||||
.expect("guest dir always has a parent")
|
||||
.join("elf/riscv32im-pico-zkvm-elf");
|
||||
|
||||
if !elf_path.exists() {
|
||||
return Err(PicoError::ElfNotFound(elf_path));
|
||||
}
|
||||
|
||||
// 4. Read the ELF file
|
||||
let elf_bytes = std::fs::read(&elf_path).map_err(|e| PicoError::ReadElf {
|
||||
path: elf_path,
|
||||
source: e,
|
||||
})?;
|
||||
|
||||
Ok(elf_bytes)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use zkvm_interface::Compiler;
|
||||
|
||||
use crate::PICO_TARGET;
|
||||
|
||||
use super::*;
|
||||
use std::path::PathBuf;
|
||||
|
||||
// TODO: for now, we just get one test file
|
||||
// TODO: but this should get the whole directory and compile each test
|
||||
fn get_compile_test_guest_program_path() -> PathBuf {
|
||||
let workspace_dir = env!("CARGO_WORKSPACE_DIR");
|
||||
PathBuf::from(workspace_dir)
|
||||
.join("tests")
|
||||
.join("pico")
|
||||
.join("compile")
|
||||
.join("basic")
|
||||
// TODO: Refactor the basic test to not have a lib and app dir
|
||||
.join("app")
|
||||
.canonicalize()
|
||||
.expect("Failed to find or canonicalize test guest program at <CARGO_WORKSPACE_DIR>/tests/compile/pico")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compile_trait() {
|
||||
let test_guest_path = get_compile_test_guest_program_path();
|
||||
match PICO_TARGET::compile(&test_guest_path) {
|
||||
Ok(elf_bytes) => {
|
||||
assert!(!elf_bytes.is_empty(), "ELF bytes should not be empty.");
|
||||
}
|
||||
Err(e) => {
|
||||
panic!(
|
||||
"compile_sp1_program direct call failed for dedicated guest: {:?}",
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user