mirror of
https://github.com/eth-act/ere.git
synced 2026-02-19 11:54:42 -05:00
Use test-utils for all zkvms (#88)
This commit is contained in:
7
Cargo.lock
generated
7
Cargo.lock
generated
@@ -2292,6 +2292,7 @@ dependencies = [
|
||||
"jolt-core",
|
||||
"jolt-sdk",
|
||||
"tempfile",
|
||||
"test-utils",
|
||||
"thiserror 2.0.12",
|
||||
"toml",
|
||||
"zkvm-interface",
|
||||
@@ -2301,10 +2302,10 @@ dependencies = [
|
||||
name = "ere-nexus"
|
||||
version = "0.0.11"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"build-utils",
|
||||
"nexus-sdk",
|
||||
"test-utils",
|
||||
"thiserror 2.0.12",
|
||||
"toml",
|
||||
"tracing",
|
||||
@@ -2322,6 +2323,7 @@ dependencies = [
|
||||
"openvm-stark-sdk",
|
||||
"openvm-transpiler",
|
||||
"serde",
|
||||
"test-utils",
|
||||
"thiserror 2.0.12",
|
||||
"toml",
|
||||
"zkvm-interface",
|
||||
@@ -2335,6 +2337,7 @@ dependencies = [
|
||||
"build-utils",
|
||||
"pico-sdk",
|
||||
"pico-vm",
|
||||
"test-utils",
|
||||
"thiserror 2.0.12",
|
||||
"zkvm-interface",
|
||||
]
|
||||
@@ -2355,6 +2358,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_yaml",
|
||||
"tempfile",
|
||||
"test-utils",
|
||||
"thiserror 2.0.12",
|
||||
"tracing",
|
||||
"zkvm-interface",
|
||||
@@ -2384,6 +2388,7 @@ dependencies = [
|
||||
"build-utils",
|
||||
"serde",
|
||||
"tempfile",
|
||||
"test-utils",
|
||||
"thiserror 2.0.12",
|
||||
"toml",
|
||||
"tracing",
|
||||
|
||||
@@ -467,42 +467,32 @@ mod test {
|
||||
fn dockerized_openvm() {
|
||||
let zkvm = ErezkVM::OpenVM;
|
||||
|
||||
let guest_directory = workspace_dir().join(format!("tests/{zkvm}/compile/basic"));
|
||||
let guest_directory = testing_guest_directory(zkvm.as_str(), "basic");
|
||||
let program = EreDockerizedCompiler::new(zkvm, workspace_dir())
|
||||
.compile(&guest_directory)
|
||||
.unwrap();
|
||||
|
||||
let zkvm = EreDockerizedzkVM::new(zkvm, program, ProverResourceType::Cpu).unwrap();
|
||||
|
||||
let mut inputs = Input::new();
|
||||
inputs.write(42u64);
|
||||
|
||||
let _report = zkvm.execute(&inputs).unwrap();
|
||||
|
||||
let (proof, _report) = zkvm.prove(&inputs).unwrap();
|
||||
|
||||
zkvm.verify(&proof).unwrap();
|
||||
let inputs = BasicProgramInputGen::valid();
|
||||
run_zkvm_execute(&zkvm, &inputs);
|
||||
run_zkvm_prove(&zkvm, &inputs);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dockerized_risc0() {
|
||||
let zkvm = ErezkVM::Risc0;
|
||||
|
||||
let guest_directory = workspace_dir().join(format!("tests/{zkvm}/compile/basic"));
|
||||
let guest_directory = testing_guest_directory(zkvm.as_str(), "basic");
|
||||
let program = EreDockerizedCompiler::new(zkvm, workspace_dir())
|
||||
.compile(&guest_directory)
|
||||
.unwrap();
|
||||
|
||||
let zkvm = EreDockerizedzkVM::new(zkvm, program, ProverResourceType::Cpu).unwrap();
|
||||
|
||||
let mut inputs = Input::new();
|
||||
inputs.write(42u32);
|
||||
|
||||
let _report = zkvm.execute(&inputs).unwrap();
|
||||
|
||||
let (proof, _report) = zkvm.prove(&inputs).unwrap();
|
||||
|
||||
zkvm.verify(&proof).unwrap();
|
||||
let inputs = BasicProgramInputGen::valid();
|
||||
run_zkvm_execute(&zkvm, &inputs);
|
||||
run_zkvm_prove(&zkvm, &inputs);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -525,21 +515,15 @@ mod test {
|
||||
fn dockerized_zisk() {
|
||||
let zkvm = ErezkVM::Zisk;
|
||||
|
||||
let guest_directory = workspace_dir().join(format!("tests/{zkvm}/prove/basic"));
|
||||
let guest_directory = testing_guest_directory(zkvm.as_str(), "basic");
|
||||
let program = EreDockerizedCompiler::new(zkvm, workspace_dir())
|
||||
.compile(&guest_directory)
|
||||
.unwrap();
|
||||
|
||||
let zkvm = EreDockerizedzkVM::new(zkvm, program, ProverResourceType::Cpu).unwrap();
|
||||
|
||||
let mut inputs = Input::new();
|
||||
inputs.write(42u32);
|
||||
inputs.write(42u16);
|
||||
|
||||
let _report = zkvm.execute(&inputs).unwrap();
|
||||
|
||||
let (proof, _report) = zkvm.prove(&inputs).unwrap();
|
||||
|
||||
zkvm.verify(&proof).unwrap();
|
||||
let inputs = BasicProgramInputGen::valid();
|
||||
run_zkvm_execute(&zkvm, &inputs);
|
||||
run_zkvm_prove(&zkvm, &inputs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,9 @@ jolt-sdk = { workspace = true, features = ["host"] }
|
||||
# Local dependencies
|
||||
zkvm-interface.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
test-utils = { workspace = true, features = ["host"] }
|
||||
|
||||
[build-dependencies]
|
||||
build-utils.workspace = true
|
||||
|
||||
|
||||
@@ -149,50 +149,25 @@ pub fn program(elf: &[u8]) -> Result<(TempDir, jolt::host::Program), zkVMError>
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{EreJolt, JOLT_TARGET};
|
||||
use std::path::PathBuf;
|
||||
use zkvm_interface::{Compiler, Input, ProverResourceType, zkVM};
|
||||
use super::*;
|
||||
use std::sync::OnceLock;
|
||||
use test_utils::host::testing_guest_directory;
|
||||
|
||||
// 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("jolt")
|
||||
.join("compile")
|
||||
.join("basic")
|
||||
.canonicalize()
|
||||
.expect("Failed to find or canonicalize test guest program at <CARGO_WORKSPACE_DIR>/tests/compile/jolt")
|
||||
static BASIC_PRORGAM: OnceLock<Vec<u8>> = OnceLock::new();
|
||||
|
||||
fn basic_program() -> Vec<u8> {
|
||||
BASIC_PRORGAM
|
||||
.get_or_init(|| {
|
||||
JOLT_TARGET
|
||||
.compile(&testing_guest_directory("jolt", "basic"))
|
||||
.unwrap()
|
||||
})
|
||||
.clone()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compile_trait() {
|
||||
let test_guest_path = get_compile_test_guest_program_path();
|
||||
let elf = JOLT_TARGET.compile(&test_guest_path).unwrap();
|
||||
assert!(!elf.is_empty(), "elf has not been compiled");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_execute() {
|
||||
let test_guest_path = get_compile_test_guest_program_path();
|
||||
let elf = JOLT_TARGET.compile(&test_guest_path).unwrap();
|
||||
let mut inputs = Input::new();
|
||||
inputs.write(1_u32);
|
||||
|
||||
let zkvm = EreJolt::new(elf, ProverResourceType::Cpu).unwrap();
|
||||
zkvm.execute(&inputs).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_prove_verify() {
|
||||
let test_guest_path = get_compile_test_guest_program_path();
|
||||
let elf = JOLT_TARGET.compile(&test_guest_path).unwrap();
|
||||
let mut inputs = Input::new();
|
||||
inputs.write(1_u32);
|
||||
|
||||
let zkvm = EreJolt::new(elf, ProverResourceType::Cpu).unwrap();
|
||||
let (proof, _) = zkvm.prove(&inputs).unwrap();
|
||||
zkvm.verify(&proof).unwrap();
|
||||
fn test_compiler_impl() {
|
||||
let elf_bytes = basic_program();
|
||||
assert!(!elf_bytes.is_empty(), "ELF bytes should not be empty.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ nexus-sdk.workspace = true
|
||||
zkvm-interface.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
anyhow.workspace = true
|
||||
test-utils = { workspace = true, features = ["host"] }
|
||||
|
||||
[build-dependencies]
|
||||
build-utils.workspace = true
|
||||
|
||||
@@ -139,59 +139,28 @@ impl zkVM for EreNexus {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use zkvm_interface::Compiler;
|
||||
|
||||
use crate::NEXUS_TARGET;
|
||||
|
||||
use super::*;
|
||||
use std::path::PathBuf;
|
||||
use std::{fs, sync::OnceLock};
|
||||
use test_utils::host::testing_guest_directory;
|
||||
|
||||
fn get_test_guest_program_path() -> PathBuf {
|
||||
let workspace_dir = env!("CARGO_WORKSPACE_DIR");
|
||||
PathBuf::from(workspace_dir)
|
||||
.join("tests")
|
||||
.join("nexus")
|
||||
.join("guest")
|
||||
.canonicalize()
|
||||
.expect("Failed to find or canonicalize test guest program at <CARGO_WORKSPACE_DIR>/tests/compile/nexus")
|
||||
static BASIC_PRORGAM: OnceLock<PathBuf> = OnceLock::new();
|
||||
|
||||
fn basic_program() -> PathBuf {
|
||||
BASIC_PRORGAM
|
||||
.get_or_init(|| {
|
||||
NEXUS_TARGET
|
||||
.compile(&testing_guest_directory("nexus", "basic"))
|
||||
.unwrap()
|
||||
})
|
||||
.to_path_buf()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compile() -> anyhow::Result<()> {
|
||||
let test_guest_path = get_test_guest_program_path();
|
||||
let elf_path = NEXUS_TARGET.compile(&test_guest_path)?;
|
||||
let prover: Stwo<Local> = Stwo::new_from_file(&elf_path.to_string_lossy().to_string())?;
|
||||
let elf = prover.elf.clone();
|
||||
fn test_compiler_impl() {
|
||||
let elf_path = basic_program();
|
||||
assert!(
|
||||
!elf.instructions.is_empty(),
|
||||
fs::metadata(&elf_path).unwrap().len() != 0,
|
||||
"ELF bytes should not be empty."
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_execute() {
|
||||
let test_guest_path = get_test_guest_program_path();
|
||||
let elf = NEXUS_TARGET
|
||||
.compile(&test_guest_path)
|
||||
.expect("compilation failed");
|
||||
let mut input = Input::new();
|
||||
input.write(10u64);
|
||||
|
||||
let zkvm = EreNexus::new(elf, ProverResourceType::Cpu);
|
||||
zkvm.execute(&input).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_prove_verify() -> anyhow::Result<()> {
|
||||
let test_guest_path = get_test_guest_program_path();
|
||||
let elf = NEXUS_TARGET.compile(&test_guest_path)?;
|
||||
let mut input = Input::new();
|
||||
input.write(10u64);
|
||||
|
||||
let zkvm = EreNexus::new(elf, ProverResourceType::Cpu);
|
||||
let (proof, _) = zkvm.prove(&input).unwrap();
|
||||
zkvm.verify(&proof).expect("proof should verify");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,9 @@ openvm-transpiler.workspace = true
|
||||
# Local dependencies
|
||||
zkvm-interface.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
test-utils = { workspace = true, features = ["host"] }
|
||||
|
||||
[build-dependencies]
|
||||
build-utils.workspace = true
|
||||
|
||||
|
||||
@@ -204,65 +204,73 @@ fn serialize_inputs(stdin: &mut StdIn, inputs: &Input) {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use zkvm_interface::Compiler;
|
||||
|
||||
use crate::OPENVM_TARGET;
|
||||
|
||||
use super::*;
|
||||
use std::path::PathBuf;
|
||||
use std::{panic, sync::OnceLock};
|
||||
use test_utils::host::{
|
||||
BasicProgramInputGen, run_zkvm_execute, run_zkvm_prove, testing_guest_directory,
|
||||
};
|
||||
|
||||
// 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("openvm")
|
||||
.join("compile")
|
||||
.join("basic")
|
||||
.canonicalize()
|
||||
.expect("Failed to find or canonicalize test guest program at <CARGO_WORKSPACE_DIR>/tests/compile/openvm")
|
||||
static BASIC_PRORGAM: OnceLock<OpenVMProgram> = OnceLock::new();
|
||||
|
||||
fn basic_program() -> OpenVMProgram {
|
||||
BASIC_PRORGAM
|
||||
.get_or_init(|| {
|
||||
OPENVM_TARGET
|
||||
.compile(&testing_guest_directory("openvm", "basic"))
|
||||
.unwrap()
|
||||
})
|
||||
.clone()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compile() {
|
||||
let test_guest_path = get_compile_test_guest_program_path();
|
||||
let program = OPENVM_TARGET.compile(&test_guest_path).unwrap();
|
||||
fn test_compiler_impl() {
|
||||
let program = basic_program();
|
||||
assert!(!program.elf.is_empty(), "ELF bytes should not be empty.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_execute_empty_input_panic() {
|
||||
// Panics because the program expects input arguments, but we supply none
|
||||
let test_guest_path = get_compile_test_guest_program_path();
|
||||
let program = OPENVM_TARGET.compile(&test_guest_path).unwrap();
|
||||
let empty_input = Input::new();
|
||||
let zkvm = EreOpenVM::new(program, ProverResourceType::Cpu).unwrap();
|
||||
|
||||
zkvm.execute(&empty_input).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_execute() {
|
||||
let test_guest_path = get_compile_test_guest_program_path();
|
||||
let program = OPENVM_TARGET.compile(&test_guest_path).unwrap();
|
||||
let mut input = Input::new();
|
||||
input.write(10u64);
|
||||
|
||||
let program = basic_program();
|
||||
let zkvm = EreOpenVM::new(program, ProverResourceType::Cpu).unwrap();
|
||||
zkvm.execute(&input).unwrap();
|
||||
|
||||
let inputs = BasicProgramInputGen::valid();
|
||||
run_zkvm_execute(&zkvm, &inputs);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_prove_verify() {
|
||||
let test_guest_path = get_compile_test_guest_program_path();
|
||||
let program = OPENVM_TARGET.compile(&test_guest_path).unwrap();
|
||||
let mut input = Input::new();
|
||||
input.write(10u64);
|
||||
|
||||
fn test_execute_invalid_inputs() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreOpenVM::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let (proof, _) = zkvm.prove(&input).unwrap();
|
||||
zkvm.verify(&proof).expect("proof should verify");
|
||||
|
||||
for inputs in [
|
||||
BasicProgramInputGen::empty(),
|
||||
BasicProgramInputGen::invalid_string(),
|
||||
BasicProgramInputGen::invalid_type(),
|
||||
] {
|
||||
zkvm.execute(&inputs).unwrap_err();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_prove() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreOpenVM::new(program, ProverResourceType::Cpu).unwrap();
|
||||
|
||||
let inputs = BasicProgramInputGen::valid();
|
||||
run_zkvm_prove(&zkvm, &inputs);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_prove_invalid_inputs() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreOpenVM::new(program, ProverResourceType::Cpu).unwrap();
|
||||
|
||||
for inputs_gen in [
|
||||
BasicProgramInputGen::empty,
|
||||
BasicProgramInputGen::invalid_string,
|
||||
BasicProgramInputGen::invalid_type,
|
||||
] {
|
||||
panic::catch_unwind(|| zkvm.prove(&inputs_gen()).unwrap_err()).unwrap_err();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@ pico-sdk.workspace = true
|
||||
# Local dependencies
|
||||
zkvm-interface.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
test-utils = { workspace = true, features = ["host"] }
|
||||
|
||||
[build-dependencies]
|
||||
build-utils.workspace = true
|
||||
|
||||
|
||||
@@ -144,41 +144,48 @@ fn serialize_inputs(stdin: &mut EmulatorStdinBuilder<Vec<u8>>, inputs: &Input) {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::PICO_TARGET;
|
||||
use std::path::PathBuf;
|
||||
use zkvm_interface::Compiler;
|
||||
use super::*;
|
||||
use std::{panic, sync::OnceLock};
|
||||
use test_utils::host::{BasicProgramInputGen, run_zkvm_execute, testing_guest_directory};
|
||||
|
||||
fn get_compile_test_guest_program_path() -> PathBuf {
|
||||
let workspace_dir = env!("CARGO_WORKSPACE_DIR");
|
||||
let path = PathBuf::from(workspace_dir)
|
||||
.join("tests")
|
||||
.join("pico")
|
||||
.join("compile")
|
||||
.join("basic")
|
||||
.join("app");
|
||||
static BASIC_PRORGAM: OnceLock<Vec<u8>> = OnceLock::new();
|
||||
|
||||
println!(
|
||||
"Attempting to find test guest program at: {}",
|
||||
path.display()
|
||||
);
|
||||
println!("Workspace dir is: {workspace_dir}");
|
||||
|
||||
path.canonicalize()
|
||||
.expect("Failed to find or canonicalize test guest program at <CARGO_WORKSPACE_DIR>/tests/pico/compile/basic/app")
|
||||
fn basic_program() -> Vec<u8> {
|
||||
BASIC_PRORGAM
|
||||
.get_or_init(|| {
|
||||
PICO_TARGET
|
||||
.compile(&testing_guest_directory("pico", "basic"))
|
||||
.unwrap()
|
||||
})
|
||||
.clone()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compile_trait() {
|
||||
let test_guest_path = get_compile_test_guest_program_path();
|
||||
println!("Using test guest path: {}", test_guest_path.display());
|
||||
fn test_compiler_impl() {
|
||||
let elf_bytes = basic_program();
|
||||
assert!(!elf_bytes.is_empty(), "ELF bytes should not be empty.");
|
||||
}
|
||||
|
||||
match PICO_TARGET.compile(&test_guest_path) {
|
||||
Ok(elf_bytes) => {
|
||||
assert!(!elf_bytes.is_empty(), "ELF bytes should not be empty.");
|
||||
}
|
||||
Err(err) => {
|
||||
panic!("compile_sp1_program direct call failed for dedicated guest: {err}");
|
||||
}
|
||||
#[test]
|
||||
fn test_execute() {
|
||||
let program = basic_program();
|
||||
let zkvm = ErePico::new(program, ProverResourceType::Cpu);
|
||||
|
||||
let inputs = BasicProgramInputGen::valid();
|
||||
run_zkvm_execute(&zkvm, &inputs);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_execute_invalid_inputs() {
|
||||
let program = basic_program();
|
||||
let zkvm = ErePico::new(program, ProverResourceType::Cpu);
|
||||
|
||||
for inputs_gen in [
|
||||
BasicProgramInputGen::empty,
|
||||
BasicProgramInputGen::invalid_string,
|
||||
BasicProgramInputGen::invalid_type,
|
||||
] {
|
||||
panic::catch_unwind(|| zkvm.execute(&inputs_gen()).unwrap_err()).unwrap_err();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,9 @@ bonsai-sdk.workspace = true
|
||||
# Local dependencies
|
||||
zkvm-interface.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
test-utils = { workspace = true, features = ["host"] }
|
||||
|
||||
[build-dependencies]
|
||||
build-utils.workspace = true
|
||||
|
||||
|
||||
@@ -45,31 +45,14 @@ pub fn compile_risc0_program(guest_directory: &Path) -> Result<Risc0Program, Com
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
mod compile {
|
||||
use crate::compile::compile_risc0_program;
|
||||
use std::path::PathBuf;
|
||||
use crate::RV32_IM_RISC0_ZKVM_ELF;
|
||||
use test_utils::host::testing_guest_directory;
|
||||
use zkvm_interface::Compiler;
|
||||
|
||||
fn get_test_risc0_methods_crate_path() -> PathBuf {
|
||||
let workspace_dir = env!("CARGO_WORKSPACE_DIR");
|
||||
PathBuf::from(workspace_dir)
|
||||
.join("tests")
|
||||
.join("risc0")
|
||||
.join("compile")
|
||||
.join("basic")
|
||||
.canonicalize()
|
||||
.expect("Failed to find or canonicalize test Risc0 methods crate")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compile_risc0_method() {
|
||||
let test_methods_path = get_test_risc0_methods_crate_path();
|
||||
|
||||
let program =
|
||||
compile_risc0_program(&test_methods_path).expect("risc0 compilation failed");
|
||||
assert!(
|
||||
!program.elf.is_empty(),
|
||||
"Risc0 ELF bytes should not be empty."
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn test_compiler_impl() {
|
||||
let guest_directory = testing_guest_directory("risc0", "basic");
|
||||
let program = RV32_IM_RISC0_ZKVM_ELF.compile(&guest_directory).unwrap();
|
||||
assert!(!program.elf.is_empty(), "ELF bytes should not be empty.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,138 +154,68 @@ fn serialize_inputs(env: &mut ExecutorEnvBuilder, inputs: &Input) -> Result<(),
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod prove_tests {
|
||||
use std::path::PathBuf;
|
||||
|
||||
mod tests {
|
||||
use super::*;
|
||||
use zkvm_interface::Input;
|
||||
use std::sync::OnceLock;
|
||||
use test_utils::host::{
|
||||
BasicProgramInputGen, run_zkvm_execute, run_zkvm_prove, testing_guest_directory,
|
||||
};
|
||||
|
||||
fn get_prove_test_guest_program_path() -> PathBuf {
|
||||
let workspace_dir = env!("CARGO_WORKSPACE_DIR");
|
||||
PathBuf::from(workspace_dir)
|
||||
.join("tests")
|
||||
.join("risc0")
|
||||
.join("compile")
|
||||
.join("basic")
|
||||
.canonicalize()
|
||||
.expect("Failed to find or canonicalize test Risc0 methods crate")
|
||||
}
|
||||
static BASIC_PRORGAM: OnceLock<Risc0Program> = OnceLock::new();
|
||||
|
||||
fn get_compiled_test_r0_elf_for_prove() -> Result<Risc0Program, Risc0Error> {
|
||||
let test_guest_path = get_prove_test_guest_program_path();
|
||||
RV32_IM_RISC0_ZKVM_ELF.compile(&test_guest_path)
|
||||
fn basic_program() -> Risc0Program {
|
||||
BASIC_PRORGAM
|
||||
.get_or_init(|| {
|
||||
RV32_IM_RISC0_ZKVM_ELF
|
||||
.compile(&testing_guest_directory("risc0", "basic"))
|
||||
.unwrap()
|
||||
})
|
||||
.clone()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_prove_r0_dummy_input() {
|
||||
let program = get_compiled_test_r0_elf_for_prove().unwrap();
|
||||
|
||||
let mut input_builder = Input::new();
|
||||
let n: u32 = 42;
|
||||
let a: u16 = 42;
|
||||
input_builder.write(n);
|
||||
input_builder.write(a);
|
||||
|
||||
fn test_execute() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreRisc0::new(program, ProverResourceType::Cpu).unwrap();
|
||||
|
||||
let (proof_bytes, _) = zkvm
|
||||
.prove(&input_builder)
|
||||
.unwrap_or_else(|err| panic!("Proving error in test: {err:?}"));
|
||||
|
||||
assert!(!proof_bytes.is_empty(), "Proof bytes should not be empty.");
|
||||
|
||||
let verify_results = zkvm.verify(&proof_bytes).is_ok();
|
||||
assert!(verify_results);
|
||||
|
||||
// TODO: Check public inputs
|
||||
let inputs = BasicProgramInputGen::valid();
|
||||
run_zkvm_execute(&zkvm, &inputs);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_prove_r0_fails_on_bad_input_causing_execution_failure() {
|
||||
let elf_bytes = get_compiled_test_r0_elf_for_prove().unwrap();
|
||||
fn test_execute_invalid_inputs() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreRisc0::new(program, ProverResourceType::Cpu).unwrap();
|
||||
|
||||
let empty_input = Input::new();
|
||||
|
||||
let zkvm = EreRisc0::new(elf_bytes, ProverResourceType::Cpu).unwrap();
|
||||
let prove_result = zkvm.prove(&empty_input);
|
||||
assert!(prove_result.is_err());
|
||||
for inputs in [
|
||||
BasicProgramInputGen::empty(),
|
||||
BasicProgramInputGen::invalid_string(),
|
||||
BasicProgramInputGen::invalid_type(),
|
||||
] {
|
||||
zkvm.execute(&inputs).unwrap_err();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "Requires GPU to run"]
|
||||
fn test_prove_r0_dummy_input_bento() {
|
||||
let program = get_compiled_test_r0_elf_for_prove().unwrap();
|
||||
fn test_prove() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreRisc0::new(program, ProverResourceType::Cpu).unwrap();
|
||||
|
||||
let mut input_builder = Input::new();
|
||||
let n: u32 = 42;
|
||||
let a: u16 = 42;
|
||||
input_builder.write(n);
|
||||
input_builder.write(a);
|
||||
let inputs = BasicProgramInputGen::valid();
|
||||
run_zkvm_prove(&zkvm, &inputs);
|
||||
}
|
||||
|
||||
let zkvm = EreRisc0::new(program, ProverResourceType::Gpu).unwrap();
|
||||
#[test]
|
||||
fn test_prove_invalid_inputs() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreRisc0::new(program, ProverResourceType::Cpu).unwrap();
|
||||
|
||||
let (proof_bytes, _) = zkvm
|
||||
.prove(&input_builder)
|
||||
.unwrap_or_else(|err| panic!("Proving error in test: {err:?}"));
|
||||
|
||||
assert!(!proof_bytes.is_empty(), "Proof bytes should not be empty.");
|
||||
|
||||
let verify_results = zkvm.verify(&proof_bytes).is_ok();
|
||||
assert!(verify_results);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod execute_tests {
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::*;
|
||||
use zkvm_interface::Input;
|
||||
|
||||
fn get_compiled_test_r0_elf() -> Result<Risc0Program, Risc0Error> {
|
||||
let test_guest_path = get_execute_test_guest_program_path();
|
||||
RV32_IM_RISC0_ZKVM_ELF.compile(&test_guest_path)
|
||||
}
|
||||
|
||||
fn get_execute_test_guest_program_path() -> PathBuf {
|
||||
let workspace_dir = env!("CARGO_WORKSPACE_DIR");
|
||||
PathBuf::from(workspace_dir)
|
||||
.join("tests")
|
||||
.join("risc0")
|
||||
.join("compile")
|
||||
.join("basic")
|
||||
.canonicalize()
|
||||
.expect("Failed to find or canonicalize test Risc0 methods crate")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_execute_r0_dummy_input() {
|
||||
let program = get_compiled_test_r0_elf().unwrap();
|
||||
|
||||
let mut input_builder = Input::new();
|
||||
let n: u32 = 42;
|
||||
let a: u16 = 42;
|
||||
input_builder.write(n);
|
||||
input_builder.write(a);
|
||||
|
||||
let zkvm = EreRisc0::new(program, ProverResourceType::Cpu).unwrap();
|
||||
|
||||
zkvm.execute(&input_builder)
|
||||
.unwrap_or_else(|err| panic!("Execution error: {err:?}"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_execute_r0_no_input_for_guest_expecting_input() {
|
||||
let program = get_compiled_test_r0_elf().unwrap();
|
||||
|
||||
let empty_input = Input::new();
|
||||
|
||||
let zkvm = EreRisc0::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let result = zkvm.execute(&empty_input);
|
||||
|
||||
assert!(
|
||||
result.is_err(),
|
||||
"execute should fail if guest expects input but none is provided."
|
||||
);
|
||||
for inputs in [
|
||||
BasicProgramInputGen::empty(),
|
||||
BasicProgramInputGen::invalid_string(),
|
||||
BasicProgramInputGen::invalid_type(),
|
||||
] {
|
||||
zkvm.prove(&inputs).unwrap_err();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,5 +17,9 @@ tracing.workspace = true
|
||||
# Local dependencies
|
||||
zkvm-interface.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
# Local dependencies
|
||||
test-utils = { workspace = true, features = ["host"] }
|
||||
|
||||
[build-dependencies]
|
||||
build-utils.workspace = true
|
||||
|
||||
@@ -117,50 +117,21 @@ pub fn compile_zisk_program(program_crate_path: &Path) -> Result<Vec<u8>, Compil
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{RV64_IMA_ZISK_ZKVM_ELF, compile::compile_zisk_program};
|
||||
use test_utils::host::testing_guest_directory;
|
||||
use zkvm_interface::Compiler;
|
||||
|
||||
use crate::RV64_IMA_ZISK_ZKVM_ELF;
|
||||
|
||||
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("zisk")
|
||||
.join("compile")
|
||||
.join("basic")
|
||||
.canonicalize()
|
||||
.expect("Failed to find or canonicalize test guest program at <CARGO_WORKSPACE_DIR>/tests/compile/zisk")
|
||||
#[test]
|
||||
fn test_compile() {
|
||||
let guest_directory = testing_guest_directory("zisk", "basic");
|
||||
let elf_bytes = compile_zisk_program(&guest_directory).unwrap();
|
||||
assert!(!elf_bytes.is_empty(), "ELF bytes should not be empty.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compile_zisk_program() {
|
||||
let test_guest_path = get_compile_test_guest_program_path();
|
||||
|
||||
match compile_zisk_program(&test_guest_path) {
|
||||
Ok(elf_bytes) => {
|
||||
assert!(!elf_bytes.is_empty(), "ELF bytes should not be empty.");
|
||||
}
|
||||
Err(e) => {
|
||||
panic!("compile failed for dedicated guest: {e:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compile_trait() {
|
||||
let test_guest_path = get_compile_test_guest_program_path();
|
||||
match RV64_IMA_ZISK_ZKVM_ELF.compile(&test_guest_path) {
|
||||
Ok(elf_bytes) => {
|
||||
assert!(!elf_bytes.is_empty(), "ELF bytes should not be empty.");
|
||||
}
|
||||
Err(e) => {
|
||||
panic!("compile_zisk_program direct call failed for dedicated guest: {e:?}");
|
||||
}
|
||||
}
|
||||
fn test_compiler_impl() {
|
||||
let guest_directory = testing_guest_directory("zisk", "basic");
|
||||
let elf_bytes = RV64_IMA_ZISK_ZKVM_ELF.compile(&guest_directory).unwrap();
|
||||
assert!(!elf_bytes.is_empty(), "ELF bytes should not be empty.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,6 +117,8 @@ pub enum ProveError {
|
||||
CargoZiskProveFailed { status: ExitStatus },
|
||||
#[error("Serialising proof with `bincode` failed: {0}")]
|
||||
Bincode(#[from] bincode::Error),
|
||||
#[error("Failed to obtain prove lock")]
|
||||
ProveLockPoisoned,
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
|
||||
@@ -11,6 +11,7 @@ use std::{
|
||||
os::unix::fs::symlink,
|
||||
path::{Path, PathBuf},
|
||||
process::{Command, Stdio},
|
||||
sync::Mutex,
|
||||
time,
|
||||
};
|
||||
use tempfile::{TempDir, tempdir};
|
||||
@@ -24,6 +25,10 @@ include!(concat!(env!("OUT_DIR"), "/name_and_sdk_version.rs"));
|
||||
mod compile;
|
||||
mod error;
|
||||
|
||||
/// It panics if `EreZisk::prove` is called concurrently, so we need a lock here
|
||||
/// to avoid that.
|
||||
static PROVE_LOCK: Mutex<()> = Mutex::new(());
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct RV64_IMA_ZISK_ZKVM_ELF;
|
||||
|
||||
@@ -114,6 +119,12 @@ impl zkVM for EreZisk {
|
||||
}
|
||||
|
||||
fn prove(&self, inputs: &Input) -> Result<(Vec<u8>, ProgramProvingReport), zkVMError> {
|
||||
// Obtain the prove lock to make sure proving can't be called concurrently.
|
||||
let _guard = PROVE_LOCK
|
||||
.lock()
|
||||
.map_err(|_| ProveError::ProveLockPoisoned)
|
||||
.map_err(ZiskError::Prove)?;
|
||||
|
||||
// Write ELF and serialized input to file.
|
||||
|
||||
let input_bytes = serialize_inputs(inputs)
|
||||
@@ -284,13 +295,17 @@ impl zkVM for EreZisk {
|
||||
}
|
||||
}
|
||||
|
||||
/// Serialize `Input` into sequence of bytes.
|
||||
///
|
||||
/// Because ZisK doesn't provide stdin API so we need to handle multiple inputs,
|
||||
/// the current approach naively serializes each `InputItem` individually, then
|
||||
/// concat them into single `Vec<u8>`.
|
||||
fn serialize_inputs(inputs: &Input) -> Result<Vec<u8>, bincode::Error> {
|
||||
inputs.iter().try_fold(Vec::new(), |mut acc, item| {
|
||||
match item {
|
||||
InputItem::Object(obj) => {
|
||||
bincode::serialize_into(&mut acc, &**obj)?;
|
||||
}
|
||||
InputItem::SerializedObject(bytes) | InputItem::Bytes(bytes) => acc.extend(bytes),
|
||||
InputItem::Object(obj) => bincode::serialize_into(&mut acc, &**obj)?,
|
||||
InputItem::SerializedObject(bytes) => acc.extend(bytes),
|
||||
InputItem::Bytes(bytes) => bincode::serialize_into(&mut acc, bytes)?,
|
||||
};
|
||||
Ok(acc)
|
||||
})
|
||||
@@ -444,124 +459,68 @@ impl ZiskTempDir {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod execute_tests {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::sync::OnceLock;
|
||||
use test_utils::host::{
|
||||
BasicProgramInputGen, run_zkvm_execute, run_zkvm_prove, testing_guest_directory,
|
||||
};
|
||||
|
||||
fn get_compiled_test_zisk_elf() -> Result<Vec<u8>, ZiskError> {
|
||||
let test_guest_path = get_execute_test_guest_program_path();
|
||||
RV64_IMA_ZISK_ZKVM_ELF.compile(&test_guest_path)
|
||||
}
|
||||
static BASIC_PRORGAM: OnceLock<Vec<u8>> = OnceLock::new();
|
||||
|
||||
fn get_execute_test_guest_program_path() -> PathBuf {
|
||||
let workspace_dir = env!("CARGO_WORKSPACE_DIR");
|
||||
PathBuf::from(workspace_dir)
|
||||
.join("tests")
|
||||
.join("zisk")
|
||||
.join("execute")
|
||||
.join("basic")
|
||||
.canonicalize()
|
||||
.expect("Failed to find or canonicalize test guest program at <CARGO_WORKSPACE_DIR>/tests/execute/zisk")
|
||||
fn basic_program() -> Vec<u8> {
|
||||
BASIC_PRORGAM
|
||||
.get_or_init(|| {
|
||||
RV64_IMA_ZISK_ZKVM_ELF
|
||||
.compile(&testing_guest_directory("zisk", "basic"))
|
||||
.unwrap()
|
||||
})
|
||||
.to_vec()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_execute_zisk_dummy_input() {
|
||||
let elf_bytes = get_compiled_test_zisk_elf()
|
||||
.expect("Failed to compile test ZisK guest for execution test");
|
||||
fn test_execute() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreZisk::new(program, ProverResourceType::Cpu);
|
||||
|
||||
let mut input_builder = Input::new();
|
||||
let n: u32 = 42;
|
||||
let a: u16 = 42;
|
||||
input_builder.write(n);
|
||||
input_builder.write(a);
|
||||
let inputs = BasicProgramInputGen::valid();
|
||||
run_zkvm_execute(&zkvm, &inputs);
|
||||
}
|
||||
|
||||
let zkvm = EreZisk::new(elf_bytes, ProverResourceType::Cpu);
|
||||
#[test]
|
||||
fn test_execute_invalid_inputs() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreZisk::new(program, ProverResourceType::Cpu);
|
||||
|
||||
let result = zkvm.execute(&input_builder);
|
||||
|
||||
if let Err(e) = &result {
|
||||
panic!("Execution error: {e:?}");
|
||||
for inputs in [
|
||||
BasicProgramInputGen::empty(),
|
||||
BasicProgramInputGen::invalid_string(),
|
||||
BasicProgramInputGen::invalid_type(),
|
||||
] {
|
||||
zkvm.execute(&inputs).unwrap_err();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_execute_zisk_no_input_for_guest_expecting_input() {
|
||||
let elf_bytes = get_compiled_test_zisk_elf()
|
||||
.expect("Failed to compile test ZisK guest for execution test");
|
||||
fn test_prove() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreZisk::new(program, ProverResourceType::Cpu);
|
||||
|
||||
let empty_input = Input::new();
|
||||
|
||||
let zkvm = EreZisk::new(elf_bytes, ProverResourceType::Cpu);
|
||||
assert!(zkvm.execute(&empty_input).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod prove_tests {
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::*;
|
||||
use zkvm_interface::Input;
|
||||
|
||||
fn get_prove_test_guest_program_path() -> PathBuf {
|
||||
let workspace_dir = env!("CARGO_WORKSPACE_DIR");
|
||||
PathBuf::from(workspace_dir)
|
||||
.join("tests")
|
||||
.join("zisk")
|
||||
.join("prove")
|
||||
.join("basic")
|
||||
.canonicalize()
|
||||
.expect("Failed to find or canonicalize test guest program at <CARGO_WORKSPACE_DIR>/tests/execute/zisk")
|
||||
}
|
||||
|
||||
fn get_compiled_test_zisk_elf_for_prove() -> Result<Vec<u8>, ZiskError> {
|
||||
let test_guest_path = get_prove_test_guest_program_path();
|
||||
RV64_IMA_ZISK_ZKVM_ELF.compile(&test_guest_path)
|
||||
let inputs = BasicProgramInputGen::valid();
|
||||
run_zkvm_prove(&zkvm, &inputs);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_prove_zisk_dummy_input() {
|
||||
let elf_path = get_compiled_test_zisk_elf_for_prove()
|
||||
.expect("Failed to compile test ZisK guest for proving test");
|
||||
fn test_prove_invalid_inputs() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreZisk::new(program, ProverResourceType::Cpu);
|
||||
|
||||
let mut input_builder = Input::new();
|
||||
let n: u32 = 42;
|
||||
let a: u16 = 42;
|
||||
input_builder.write(n);
|
||||
input_builder.write(a);
|
||||
|
||||
let zkvm = EreZisk::new(elf_path, ProverResourceType::Cpu);
|
||||
|
||||
let proof_bytes = match zkvm.prove(&input_builder) {
|
||||
Ok((prove_result, _)) => prove_result,
|
||||
Err(err) => {
|
||||
panic!("Proving error in test: {err:?}");
|
||||
}
|
||||
};
|
||||
|
||||
assert!(!proof_bytes.is_empty(), "Proof bytes should not be empty.");
|
||||
|
||||
assert!(zkvm.verify(&proof_bytes).is_ok());
|
||||
|
||||
let invalid_proof_bytes = {
|
||||
let mut invalid_proof: ZiskProofWithPublicValues =
|
||||
bincode::deserialize(&proof_bytes).unwrap();
|
||||
// alter the first digit of `evals[0][0]`
|
||||
invalid_proof.proof[40] = invalid_proof.proof[40].overflowing_add(1).0;
|
||||
bincode::serialize(&invalid_proof).unwrap()
|
||||
};
|
||||
assert!(zkvm.verify(&invalid_proof_bytes).is_err());
|
||||
|
||||
// TODO: Check public inputs
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_prove_zisk_fails_on_bad_input_causing_execution_failure() {
|
||||
let elf_path = get_compiled_test_zisk_elf_for_prove()
|
||||
.expect("Failed to compile test ZisK guest for proving test");
|
||||
|
||||
let empty_input = Input::new();
|
||||
|
||||
let zkvm = EreZisk::new(elf_path, ProverResourceType::Cpu);
|
||||
assert!(zkvm.prove(&empty_input).is_err());
|
||||
for inputs in [
|
||||
BasicProgramInputGen::empty(),
|
||||
BasicProgramInputGen::invalid_string(),
|
||||
BasicProgramInputGen::invalid_type(),
|
||||
] {
|
||||
zkvm.prove(&inputs).unwrap_err();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ echo "Installing Nexus CLI from GitHub repository..."
|
||||
cargo "+${NEXUS_TOOLCHAIN_VERSION}" install --git https://github.com/nexus-xyz/nexus-zkvm cargo-nexus --tag "$NEXUS_CLI_VERSION_TAG"
|
||||
|
||||
# Install Nexus's target
|
||||
rustup target add riscv32i-unknown-none-elf
|
||||
rustup "+${NEXUS_TOOLCHAIN_VERSION}" target add riscv32i-unknown-none-elf
|
||||
|
||||
# Verify Nexus installation
|
||||
echo "Verifying Nexus CLI installation..."
|
||||
@@ -51,7 +51,7 @@ else
|
||||
fi
|
||||
|
||||
echo "Verifying Nexus's target installation..."
|
||||
if rustup target list --installed | grep -q "riscv32i-unknown-none-elf"; then
|
||||
if rustup "+${NEXUS_TOOLCHAIN_VERSION}" target list --installed | grep -q "riscv32i-unknown-none-elf"; then
|
||||
echo "Target 'riscv32i-unknown-none-elf' installation verified successfully."
|
||||
else
|
||||
echo "Target 'riscv32i-unknown-none-elf' not installed correctly." >&2
|
||||
|
||||
@@ -7,3 +7,4 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
openvm = { git = "https://github.com/openvm-org/openvm.git", features = ["std"], tag = "v1.2.0" }
|
||||
test-utils = { path = "../../../crates/test-utils" }
|
||||
16
tests/openvm/basic/src/main.rs
Normal file
16
tests/openvm/basic/src/main.rs
Normal file
@@ -0,0 +1,16 @@
|
||||
use openvm::io::{read, read_vec, reveal_u32};
|
||||
use test_utils::guest::BasicStruct;
|
||||
|
||||
fn main() {
|
||||
// Read `Hello world` bytes.
|
||||
let bytes = read_vec();
|
||||
assert_eq!(String::from_utf8_lossy(&bytes), "Hello world");
|
||||
|
||||
// Read `BasicStruct`.
|
||||
let basic_struct = read::<BasicStruct>();
|
||||
let output = basic_struct.output();
|
||||
|
||||
output.chunks(4).enumerate().for_each(|(idx, bytes)| {
|
||||
reveal_u32(u32::from_le_bytes(bytes.try_into().unwrap()), idx);
|
||||
});
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
use openvm::io::{read, reveal_u32};
|
||||
|
||||
fn main() {
|
||||
let n: u64 = read();
|
||||
let mut a: u64 = 0;
|
||||
let mut b: u64 = 1;
|
||||
for _ in 0..n {
|
||||
let c: u64 = a.wrapping_add(b);
|
||||
a = b;
|
||||
b = c;
|
||||
}
|
||||
reveal_u32(a as u32, 0);
|
||||
reveal_u32((a >> 32) as u32, 1);
|
||||
}
|
||||
10
tests/pico/basic/Cargo.toml
Normal file
10
tests/pico/basic/Cargo.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "app"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[workspace]
|
||||
|
||||
[dependencies]
|
||||
pico-sdk = { git = "https://github.com/brevis-network/pico", tag = "v1.1.4" }
|
||||
test-utils = { path = "../../../crates/test-utils" }
|
||||
19
tests/pico/basic/src/main.rs
Normal file
19
tests/pico/basic/src/main.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
#![no_main]
|
||||
|
||||
use pico_sdk::io::{commit, read_as, read_vec};
|
||||
use test_utils::guest::BasicStruct;
|
||||
|
||||
pico_sdk::entrypoint!(main);
|
||||
|
||||
pub fn main() {
|
||||
// Read `Hello world` bytes.
|
||||
let bytes = read_vec();
|
||||
assert_eq!(String::from_utf8_lossy(&bytes), "Hello world");
|
||||
|
||||
// Read `BasicStruct`.
|
||||
let basic_struct = read_as::<BasicStruct>();
|
||||
let output = basic_struct.output();
|
||||
|
||||
// Write `output`
|
||||
commit(&output);
|
||||
}
|
||||
2
tests/pico/compile/basic/.gitignore
vendored
2
tests/pico/compile/basic/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
**/target
|
||||
**/elf
|
||||
@@ -1,7 +0,0 @@
|
||||
[workspace]
|
||||
members = ["lib", "app", "prover"]
|
||||
resolver = "2"
|
||||
|
||||
[workspace.dependencies]
|
||||
pico-sdk = { git = "https://github.com/brevis-network/pico", tag = "v1.1.4" }
|
||||
serde = { version = "1.0.205", features = ["derive"] }
|
||||
@@ -1,8 +0,0 @@
|
||||
[package]
|
||||
name = "app"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
pico-sdk = { workspace = true }
|
||||
fibonacci-lib ={ path = "../lib"}
|
||||
@@ -1,26 +0,0 @@
|
||||
#![no_main]
|
||||
|
||||
pico_sdk::entrypoint!(main);
|
||||
use fibonacci_lib::{FibonacciData, fibonacci};
|
||||
use pico_sdk::io::{commit, read_as};
|
||||
|
||||
pub fn main() {
|
||||
// Read inputs `n` from the environment
|
||||
let n: u32 = read_as();
|
||||
|
||||
let a: u32 = 0;
|
||||
let b: u32 = 1;
|
||||
|
||||
// Compute Fibonacci values starting from `a` and `b`
|
||||
let (a_result, b_result) = fibonacci(a, b, n);
|
||||
|
||||
// Commit the assembled Fibonacci data as the public values in the Pico proof.
|
||||
// This allows the values to be verified by others.
|
||||
let result = FibonacciData {
|
||||
n,
|
||||
a: a_result,
|
||||
b: b_result,
|
||||
};
|
||||
|
||||
commit(&result);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
[package]
|
||||
name = "fibonacci-lib"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
serde = { workspace = true }
|
||||
@@ -1,27 +0,0 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct FibonacciData {
|
||||
pub a: u32,
|
||||
pub b: u32,
|
||||
pub n: u32,
|
||||
}
|
||||
|
||||
/// Computes the Fibonacci sequence starting from `a` and `b` up to the `n`-th iteration.
|
||||
/// Returns the last two values in the sequence: (a, b).
|
||||
pub fn fibonacci(mut a: u32, mut b: u32, n: u32) -> (u32, u32) {
|
||||
for _ in 0..n {
|
||||
let next = a.wrapping_add(b);
|
||||
a = b;
|
||||
b = next;
|
||||
}
|
||||
(a, b)
|
||||
}
|
||||
|
||||
/// Loads an ELF file from the specified path.
|
||||
pub fn load_elf(path: &str) -> Vec<u8> {
|
||||
fs::read(path).unwrap_or_else(|err| {
|
||||
panic!("Failed to load ELF file from {}: {}", path, err);
|
||||
})
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
[package]
|
||||
name = "prover"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
pico-sdk = { workspace = true }
|
||||
bincode = "1.3.3"
|
||||
fibonacci-lib ={ path = "../lib"}
|
||||
serde = { workspace = true }
|
||||
@@ -1,49 +0,0 @@
|
||||
use fibonacci_lib::{FibonacciData, fibonacci, load_elf};
|
||||
use pico_sdk::{client::DefaultProverClient, init_logger};
|
||||
|
||||
fn main() {
|
||||
// Initialize logger
|
||||
init_logger();
|
||||
|
||||
// Load the ELF file
|
||||
let elf = load_elf("../elf/riscv32im-pico-zkvm-elf");
|
||||
|
||||
// Initialize the prover client
|
||||
let client = DefaultProverClient::new(&elf);
|
||||
// Initialize new stdin
|
||||
let mut stdin_builder = client.new_stdin_builder();
|
||||
|
||||
// Set up input
|
||||
let n = 100u32;
|
||||
stdin_builder.write(&n);
|
||||
|
||||
// Generate proof
|
||||
let proof = client
|
||||
.prove_fast(stdin_builder)
|
||||
.expect("Failed to generate proof");
|
||||
|
||||
// Decodes public values from the proof's public value stream.
|
||||
let public_buffer = proof.pv_stream.unwrap();
|
||||
|
||||
// Deserialize public_buffer into FibonacciData
|
||||
let public_values: FibonacciData =
|
||||
bincode::deserialize(&public_buffer).expect("Failed to deserialize");
|
||||
|
||||
// Verify the public values
|
||||
verify_public_values(n, &public_values);
|
||||
}
|
||||
|
||||
/// Verifies that the computed Fibonacci values match the public values.
|
||||
fn verify_public_values(n: u32, public_values: &FibonacciData) {
|
||||
println!(
|
||||
"Public value n: {:?}, a: {:?}, b: {:?}",
|
||||
public_values.n, public_values.a, public_values.b
|
||||
);
|
||||
|
||||
// Compute Fibonacci values locally
|
||||
let (result_a, result_b) = fibonacci(0, 1, n);
|
||||
|
||||
// Assert that the computed values match the public values
|
||||
assert_eq!(result_a, public_values.a, "Mismatch in value 'a'");
|
||||
assert_eq!(result_b, public_values.b, "Mismatch in value 'b'");
|
||||
}
|
||||
@@ -6,4 +6,5 @@ edition = "2021"
|
||||
[workspace]
|
||||
|
||||
[dependencies]
|
||||
risc0-zkvm = { version = "2.3.1", default-features = false, features = ['std'] }
|
||||
risc0-zkvm = { version = "2.3.1", default-features = false, features = ['std', 'unstable'] }
|
||||
test-utils = { path = "../../../crates/test-utils" }
|
||||
15
tests/risc0/basic/src/main.rs
Normal file
15
tests/risc0/basic/src/main.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
use risc0_zkvm::guest::env;
|
||||
use test_utils::guest::BasicStruct;
|
||||
|
||||
fn main() {
|
||||
// Read `Hello world` bytes.
|
||||
let bytes = env::read_frame();
|
||||
assert_eq!(String::from_utf8_lossy(&bytes), "Hello world");
|
||||
|
||||
// Read `BasicStruct`.
|
||||
let basic_struct = env::read::<BasicStruct>();
|
||||
let output = basic_struct.output();
|
||||
|
||||
// Write `output`
|
||||
env::commit(&output);
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
use risc0_zkvm::guest::env;
|
||||
|
||||
fn main() {
|
||||
// TODO: Implement your guest code here
|
||||
|
||||
// read the input
|
||||
let input: u32 = env::read();
|
||||
|
||||
// TODO: do something with the input
|
||||
|
||||
// write public output to the journal
|
||||
env::commit(&input);
|
||||
}
|
||||
@@ -6,4 +6,6 @@ edition = "2021"
|
||||
[workspace]
|
||||
|
||||
[dependencies]
|
||||
bincode = "1.3.3"
|
||||
ziskos = { git = "https://github.com/0xPolygonHermez/zisk.git", tag = "v0.9.0" }
|
||||
test-utils = { path = "../../../crates/test-utils" }
|
||||
22
tests/zisk/basic/src/main.rs
Normal file
22
tests/zisk/basic/src/main.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
#![no_main]
|
||||
|
||||
use test_utils::guest::BasicStruct;
|
||||
|
||||
ziskos::entrypoint!(main);
|
||||
|
||||
fn main() {
|
||||
let input = ziskos::read_input();
|
||||
let mut input = input.as_slice();
|
||||
|
||||
// Read `Hello world` bytes.
|
||||
let bytes: Vec<u8> = bincode::deserialize_from(&mut input).unwrap();
|
||||
assert_eq!(String::from_utf8_lossy(&bytes), "Hello world");
|
||||
|
||||
// Read `BasicStruct`.
|
||||
let basic_struct: BasicStruct = bincode::deserialize_from(&mut input).unwrap();
|
||||
let output = basic_struct.output();
|
||||
|
||||
output.chunks(4).enumerate().for_each(|(idx, bytes)| {
|
||||
ziskos::set_output(idx, u32::from_le_bytes(bytes.try_into().unwrap()));
|
||||
});
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
[package]
|
||||
name = "ere-test-zisk-guest"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[workspace]
|
||||
|
||||
[dependencies]
|
||||
ziskos = { git = "https://github.com/0xPolygonHermez/zisk.git", tag = "v0.9.0" }
|
||||
@@ -1,14 +0,0 @@
|
||||
#![no_main]
|
||||
|
||||
ziskos::entrypoint!(main);
|
||||
|
||||
fn main() {
|
||||
// Read an input
|
||||
let n = u32::from_le_bytes(
|
||||
ziskos::read_input()
|
||||
.try_into()
|
||||
.expect("input to be 4 bytes"),
|
||||
);
|
||||
// Write n*2 to output
|
||||
ziskos::set_output(0, n * 2);
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
[package]
|
||||
name = "ere-test-zisk-guest"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[workspace]
|
||||
|
||||
[dependencies]
|
||||
ziskos = { git = "https://github.com/0xPolygonHermez/zisk.git", tag = "v0.9.0" }
|
||||
@@ -1,16 +0,0 @@
|
||||
#![no_main]
|
||||
|
||||
ziskos::entrypoint!(main);
|
||||
|
||||
fn main() {
|
||||
let input = ziskos::read_input();
|
||||
if input.len() != 6 {
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
// Read an input
|
||||
let n = u32::from_le_bytes(input[..4].try_into().unwrap());
|
||||
let a = u16::from_le_bytes(input[4..6].try_into().unwrap()) as u32;
|
||||
|
||||
ziskos::set_output(0, (n + a) * 2);
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
#![no_main]
|
||||
|
||||
ziskos::entrypoint!(main);
|
||||
|
||||
fn main() {
|
||||
let input = ziskos::read_input();
|
||||
if input.len() != 6 {
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
// Read an input
|
||||
let n = u32::from_le_bytes(input[..4].try_into().unwrap());
|
||||
let a = u16::from_le_bytes(input[4..6].try_into().unwrap()) as u32;
|
||||
|
||||
ziskos::set_output(0, (n + a) * 2);
|
||||
}
|
||||
Reference in New Issue
Block a user