diff --git a/tests/pico/compile/basic/.gitignore b/tests/pico/compile/basic/.gitignore new file mode 100644 index 0000000..baa3726 --- /dev/null +++ b/tests/pico/compile/basic/.gitignore @@ -0,0 +1,2 @@ +**/target +**/elf \ No newline at end of file diff --git a/tests/pico/compile/basic/Cargo.toml b/tests/pico/compile/basic/Cargo.toml new file mode 100644 index 0000000..16ae2cb --- /dev/null +++ b/tests/pico/compile/basic/Cargo.toml @@ -0,0 +1,11 @@ +[workspace] +members = [ + "lib", + "app", + "prover", +] +resolver = "2" + +[workspace.dependencies] +pico-sdk = { git = "https://github.com/brevis-network/pico" } +serde = { version = "1.0.205", features = ["derive"] } \ No newline at end of file diff --git a/tests/pico/compile/basic/app/Cargo.toml b/tests/pico/compile/basic/app/Cargo.toml new file mode 100644 index 0000000..e7fbd2e --- /dev/null +++ b/tests/pico/compile/basic/app/Cargo.toml @@ -0,0 +1,8 @@ +[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 new file mode 100644 index 0000000..e3646e0 --- /dev/null +++ b/tests/pico/compile/basic/app/src/main.rs @@ -0,0 +1,26 @@ +#![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 new file mode 100644 index 0000000..c3638f4 --- /dev/null +++ b/tests/pico/compile/basic/lib/Cargo.toml @@ -0,0 +1,7 @@ +[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 new file mode 100644 index 0000000..a4d0bee --- /dev/null +++ b/tests/pico/compile/basic/lib/src/lib.rs @@ -0,0 +1,27 @@ +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 new file mode 100644 index 0000000..3352fc0 --- /dev/null +++ b/tests/pico/compile/basic/prover/Cargo.toml @@ -0,0 +1,10 @@ +[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 new file mode 100644 index 0000000..90eacbb --- /dev/null +++ b/tests/pico/compile/basic/prover/src/main.rs @@ -0,0 +1,49 @@ +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/pico/compile/basic/rust-toolchain b/tests/pico/compile/basic/rust-toolchain new file mode 100644 index 0000000..ca09122 --- /dev/null +++ b/tests/pico/compile/basic/rust-toolchain @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly-2024-11-27" \ No newline at end of file