diff --git a/Cargo.lock b/Cargo.lock index 7616af5..d1b9922 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/crates/ere-dockerized/src/lib.rs b/crates/ere-dockerized/src/lib.rs index cbfbaa7..dfd299a 100644 --- a/crates/ere-dockerized/src/lib.rs +++ b/crates/ere-dockerized/src/lib.rs @@ -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); } } diff --git a/crates/ere-jolt/Cargo.toml b/crates/ere-jolt/Cargo.toml index f479653..7d2ddc4 100644 --- a/crates/ere-jolt/Cargo.toml +++ b/crates/ere-jolt/Cargo.toml @@ -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 diff --git a/crates/ere-jolt/src/lib.rs b/crates/ere-jolt/src/lib.rs index f1166e7..e7128ce 100644 --- a/crates/ere-jolt/src/lib.rs +++ b/crates/ere-jolt/src/lib.rs @@ -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 /tests/compile/jolt") + static BASIC_PRORGAM: OnceLock> = OnceLock::new(); + + fn basic_program() -> Vec { + 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."); } } diff --git a/crates/ere-nexus/Cargo.toml b/crates/ere-nexus/Cargo.toml index bd402ed..46fe998 100644 --- a/crates/ere-nexus/Cargo.toml +++ b/crates/ere-nexus/Cargo.toml @@ -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 diff --git a/crates/ere-nexus/src/lib.rs b/crates/ere-nexus/src/lib.rs index dd546b3..6390feb 100644 --- a/crates/ere-nexus/src/lib.rs +++ b/crates/ere-nexus/src/lib.rs @@ -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 /tests/compile/nexus") + static BASIC_PRORGAM: OnceLock = 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 = 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(()) } } diff --git a/crates/ere-openvm/Cargo.toml b/crates/ere-openvm/Cargo.toml index b1355ec..ff2ed4f 100644 --- a/crates/ere-openvm/Cargo.toml +++ b/crates/ere-openvm/Cargo.toml @@ -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 diff --git a/crates/ere-openvm/src/lib.rs b/crates/ere-openvm/src/lib.rs index ef2286e..f7511de 100644 --- a/crates/ere-openvm/src/lib.rs +++ b/crates/ere-openvm/src/lib.rs @@ -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 /tests/compile/openvm") + static BASIC_PRORGAM: OnceLock = 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(); + } } } diff --git a/crates/ere-pico/Cargo.toml b/crates/ere-pico/Cargo.toml index f291aca..4630042 100644 --- a/crates/ere-pico/Cargo.toml +++ b/crates/ere-pico/Cargo.toml @@ -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 diff --git a/crates/ere-pico/src/lib.rs b/crates/ere-pico/src/lib.rs index 24cc23b..0b550ac 100644 --- a/crates/ere-pico/src/lib.rs +++ b/crates/ere-pico/src/lib.rs @@ -144,41 +144,48 @@ fn serialize_inputs(stdin: &mut EmulatorStdinBuilder>, 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> = 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 /tests/pico/compile/basic/app") + fn basic_program() -> Vec { + 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(); } } } diff --git a/crates/ere-risc0/Cargo.toml b/crates/ere-risc0/Cargo.toml index 31d81be..1f5c387 100644 --- a/crates/ere-risc0/Cargo.toml +++ b/crates/ere-risc0/Cargo.toml @@ -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 diff --git a/crates/ere-risc0/src/compile.rs b/crates/ere-risc0/src/compile.rs index 296fdfa..b2f4b37 100644 --- a/crates/ere-risc0/src/compile.rs +++ b/crates/ere-risc0/src/compile.rs @@ -45,31 +45,14 @@ pub fn compile_risc0_program(guest_directory: &Path) -> Result 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."); } } diff --git a/crates/ere-risc0/src/lib.rs b/crates/ere-risc0/src/lib.rs index aaa9575..877ac2f 100644 --- a/crates/ere-risc0/src/lib.rs +++ b/crates/ere-risc0/src/lib.rs @@ -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 = OnceLock::new(); - fn get_compiled_test_r0_elf_for_prove() -> Result { - 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 { - 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(); + } } } diff --git a/crates/ere-zisk/Cargo.toml b/crates/ere-zisk/Cargo.toml index 0a2d6a3..fad91e8 100644 --- a/crates/ere-zisk/Cargo.toml +++ b/crates/ere-zisk/Cargo.toml @@ -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 diff --git a/crates/ere-zisk/src/compile.rs b/crates/ere-zisk/src/compile.rs index 1c04e00..94be97b 100644 --- a/crates/ere-zisk/src/compile.rs +++ b/crates/ere-zisk/src/compile.rs @@ -117,50 +117,21 @@ pub fn compile_zisk_program(program_crate_path: &Path) -> Result, 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 /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."); } } diff --git a/crates/ere-zisk/src/error.rs b/crates/ere-zisk/src/error.rs index c87aeb0..b6b2df9 100644 --- a/crates/ere-zisk/src/error.rs +++ b/crates/ere-zisk/src/error.rs @@ -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)] diff --git a/crates/ere-zisk/src/lib.rs b/crates/ere-zisk/src/lib.rs index 73b62c3..91dc244 100644 --- a/crates/ere-zisk/src/lib.rs +++ b/crates/ere-zisk/src/lib.rs @@ -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, 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`. fn serialize_inputs(inputs: &Input) -> Result, 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, ZiskError> { - let test_guest_path = get_execute_test_guest_program_path(); - RV64_IMA_ZISK_ZKVM_ELF.compile(&test_guest_path) - } + static BASIC_PRORGAM: OnceLock> = 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 /tests/execute/zisk") + fn basic_program() -> Vec { + 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 /tests/execute/zisk") - } - - fn get_compiled_test_zisk_elf_for_prove() -> Result, 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(); + } } } diff --git a/scripts/sdk_installers/install_nexus_sdk.sh b/scripts/sdk_installers/install_nexus_sdk.sh index cffa8a1..5bd5533 100755 --- a/scripts/sdk_installers/install_nexus_sdk.sh +++ b/scripts/sdk_installers/install_nexus_sdk.sh @@ -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 diff --git a/tests/jolt/compile/basic/Cargo.toml b/tests/jolt/basic/Cargo.toml similarity index 100% rename from tests/jolt/compile/basic/Cargo.toml rename to tests/jolt/basic/Cargo.toml diff --git a/tests/jolt/compile/basic/src/lib.rs b/tests/jolt/basic/src/lib.rs similarity index 100% rename from tests/jolt/compile/basic/src/lib.rs rename to tests/jolt/basic/src/lib.rs diff --git a/tests/jolt/compile/basic/src/main.rs b/tests/jolt/basic/src/main.rs similarity index 100% rename from tests/jolt/compile/basic/src/main.rs rename to tests/jolt/basic/src/main.rs diff --git a/tests/nexus/guest/.cargo/config.toml b/tests/nexus/basic/.cargo/config.toml similarity index 100% rename from tests/nexus/guest/.cargo/config.toml rename to tests/nexus/basic/.cargo/config.toml diff --git a/tests/nexus/guest/Cargo.toml b/tests/nexus/basic/Cargo.toml similarity index 100% rename from tests/nexus/guest/Cargo.toml rename to tests/nexus/basic/Cargo.toml diff --git a/tests/nexus/guest/src/main.rs b/tests/nexus/basic/src/main.rs similarity index 100% rename from tests/nexus/guest/src/main.rs rename to tests/nexus/basic/src/main.rs diff --git a/tests/openvm/compile/basic/Cargo.toml b/tests/openvm/basic/Cargo.toml similarity index 79% rename from tests/openvm/compile/basic/Cargo.toml rename to tests/openvm/basic/Cargo.toml index 7f7499a..3942440 100644 --- a/tests/openvm/compile/basic/Cargo.toml +++ b/tests/openvm/basic/Cargo.toml @@ -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" } diff --git a/tests/openvm/basic/src/main.rs b/tests/openvm/basic/src/main.rs new file mode 100644 index 0000000..237ca71 --- /dev/null +++ b/tests/openvm/basic/src/main.rs @@ -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::(); + let output = basic_struct.output(); + + output.chunks(4).enumerate().for_each(|(idx, bytes)| { + reveal_u32(u32::from_le_bytes(bytes.try_into().unwrap()), idx); + }); +} diff --git a/tests/openvm/compile/basic/src/main.rs b/tests/openvm/compile/basic/src/main.rs deleted file mode 100644 index 6cbd883..0000000 --- a/tests/openvm/compile/basic/src/main.rs +++ /dev/null @@ -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); -} diff --git a/tests/pico/basic/Cargo.toml b/tests/pico/basic/Cargo.toml new file mode 100644 index 0000000..0402723 --- /dev/null +++ b/tests/pico/basic/Cargo.toml @@ -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" } diff --git a/tests/pico/compile/basic/rust-toolchain b/tests/pico/basic/rust-toolchain.toml similarity index 100% rename from tests/pico/compile/basic/rust-toolchain rename to tests/pico/basic/rust-toolchain.toml diff --git a/tests/pico/basic/src/main.rs b/tests/pico/basic/src/main.rs new file mode 100644 index 0000000..179eb29 --- /dev/null +++ b/tests/pico/basic/src/main.rs @@ -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::(); + let output = basic_struct.output(); + + // Write `output` + commit(&output); +} diff --git a/tests/pico/compile/basic/.gitignore b/tests/pico/compile/basic/.gitignore deleted file mode 100644 index baa3726..0000000 --- a/tests/pico/compile/basic/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -**/target -**/elf \ No newline at end of file diff --git a/tests/pico/compile/basic/Cargo.toml b/tests/pico/compile/basic/Cargo.toml deleted file mode 100644 index ec51515..0000000 --- a/tests/pico/compile/basic/Cargo.toml +++ /dev/null @@ -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"] } diff --git a/tests/pico/compile/basic/app/Cargo.toml b/tests/pico/compile/basic/app/Cargo.toml deleted file mode 100644 index e7fbd2e..0000000 --- a/tests/pico/compile/basic/app/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "app" -version = "0.1.0" -edition = "2024" - -[dependencies] -pico-sdk = { workspace = true } -fibonacci-lib ={ path = "../lib"} \ No newline at end of file diff --git a/tests/pico/compile/basic/app/src/main.rs b/tests/pico/compile/basic/app/src/main.rs deleted file mode 100644 index e3646e0..0000000 --- a/tests/pico/compile/basic/app/src/main.rs +++ /dev/null @@ -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); -} diff --git a/tests/pico/compile/basic/lib/Cargo.toml b/tests/pico/compile/basic/lib/Cargo.toml deleted file mode 100644 index c3638f4..0000000 --- a/tests/pico/compile/basic/lib/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "fibonacci-lib" -version = "0.1.0" -edition = "2024" - -[dependencies] -serde = { workspace = true } \ No newline at end of file diff --git a/tests/pico/compile/basic/lib/src/lib.rs b/tests/pico/compile/basic/lib/src/lib.rs deleted file mode 100644 index a4d0bee..0000000 --- a/tests/pico/compile/basic/lib/src/lib.rs +++ /dev/null @@ -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 { - fs::read(path).unwrap_or_else(|err| { - panic!("Failed to load ELF file from {}: {}", path, err); - }) -} diff --git a/tests/pico/compile/basic/prover/Cargo.toml b/tests/pico/compile/basic/prover/Cargo.toml deleted file mode 100644 index 3352fc0..0000000 --- a/tests/pico/compile/basic/prover/Cargo.toml +++ /dev/null @@ -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 } \ No newline at end of file diff --git a/tests/pico/compile/basic/prover/src/main.rs b/tests/pico/compile/basic/prover/src/main.rs deleted file mode 100644 index 90eacbb..0000000 --- a/tests/pico/compile/basic/prover/src/main.rs +++ /dev/null @@ -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'"); -} diff --git a/tests/risc0/compile/basic/Cargo.toml b/tests/risc0/basic/Cargo.toml similarity index 67% rename from tests/risc0/compile/basic/Cargo.toml rename to tests/risc0/basic/Cargo.toml index 142202d..b0b5e77 100644 --- a/tests/risc0/compile/basic/Cargo.toml +++ b/tests/risc0/basic/Cargo.toml @@ -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" } diff --git a/tests/risc0/basic/src/main.rs b/tests/risc0/basic/src/main.rs new file mode 100644 index 0000000..a9d0214 --- /dev/null +++ b/tests/risc0/basic/src/main.rs @@ -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::(); + let output = basic_struct.output(); + + // Write `output` + env::commit(&output); +} diff --git a/tests/risc0/compile/basic/src/main.rs b/tests/risc0/compile/basic/src/main.rs deleted file mode 100644 index 65a3f64..0000000 --- a/tests/risc0/compile/basic/src/main.rs +++ /dev/null @@ -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); -} diff --git a/tests/zisk/prove/basic/Cargo.toml b/tests/zisk/basic/Cargo.toml similarity index 72% rename from tests/zisk/prove/basic/Cargo.toml rename to tests/zisk/basic/Cargo.toml index 6173c4a..aa06a37 100644 --- a/tests/zisk/prove/basic/Cargo.toml +++ b/tests/zisk/basic/Cargo.toml @@ -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" } diff --git a/tests/zisk/basic/src/main.rs b/tests/zisk/basic/src/main.rs new file mode 100644 index 0000000..074d218 --- /dev/null +++ b/tests/zisk/basic/src/main.rs @@ -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 = 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())); + }); +} diff --git a/tests/zisk/compile/basic/Cargo.toml b/tests/zisk/compile/basic/Cargo.toml deleted file mode 100644 index 6173c4a..0000000 --- a/tests/zisk/compile/basic/Cargo.toml +++ /dev/null @@ -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" } diff --git a/tests/zisk/compile/basic/src/main.rs b/tests/zisk/compile/basic/src/main.rs deleted file mode 100644 index 51730e7..0000000 --- a/tests/zisk/compile/basic/src/main.rs +++ /dev/null @@ -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); -} diff --git a/tests/zisk/execute/basic/Cargo.toml b/tests/zisk/execute/basic/Cargo.toml deleted file mode 100644 index 6173c4a..0000000 --- a/tests/zisk/execute/basic/Cargo.toml +++ /dev/null @@ -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" } diff --git a/tests/zisk/execute/basic/src/main.rs b/tests/zisk/execute/basic/src/main.rs deleted file mode 100644 index e3dad2a..0000000 --- a/tests/zisk/execute/basic/src/main.rs +++ /dev/null @@ -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); -} diff --git a/tests/zisk/prove/basic/src/main.rs b/tests/zisk/prove/basic/src/main.rs deleted file mode 100644 index e3dad2a..0000000 --- a/tests/zisk/prove/basic/src/main.rs +++ /dev/null @@ -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); -}