diff --git a/nexus/mem_alloc_vec_test/.cargo/config.toml b/nexus/mem_alloc_vec_test/.cargo/config.toml new file mode 100644 index 0000000..80e2c50 --- /dev/null +++ b/nexus/mem_alloc_vec_test/.cargo/config.toml @@ -0,0 +1,5 @@ +[target.riscv32i-unknown-none-elf] +rustflags = [ + "-C", "link-arg=-Tlink.x", +] +runner="nexus-run" diff --git a/nexus/mem_alloc_vec_test/Cargo.toml b/nexus/mem_alloc_vec_test/Cargo.toml new file mode 100644 index 0000000..9e2e6f8 --- /dev/null +++ b/nexus/mem_alloc_vec_test/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "mem_alloc_vec_test" +version = "0.1.0" +edition = "2021" + +[dependencies] +nexus-rt = { git = "https://github.com/nexus-xyz/nexus-zkvm.git", version = "0.2.3" } + +# Generated by cargo-nexus, do not remove! +# +# This profile is used for generating proofs, as Nexus VM support for compiler optimizations is still under development. +[features] +cycles = [] # Enable cycle counting for run command + diff --git a/nexus/mem_alloc_vec_test/rust-toolchain.toml b/nexus/mem_alloc_vec_test/rust-toolchain.toml new file mode 100644 index 0000000..2121065 --- /dev/null +++ b/nexus/mem_alloc_vec_test/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "1.77.0" +targets = ["riscv32i-unknown-none-elf"] diff --git a/nexus/mem_alloc_vec_test/src/main.rs b/nexus/mem_alloc_vec_test/src/main.rs new file mode 100644 index 0000000..e5f94e6 --- /dev/null +++ b/nexus/mem_alloc_vec_test/src/main.rs @@ -0,0 +1,54 @@ +#![cfg_attr(target_arch = "riscv32", no_std, no_main)] + +extern crate alloc; + +use alloc::vec::Vec; + +pub const CAP_LIM: usize = 10000; +pub const TO_INSERT_ITEM: usize = 145; + +macro_rules! write_tests_vec { + ($t:ty, $fn_name_1:ident, $fn_name_2:ident, $fn_name_3:ident, $fn_name_4:ident) => { + pub fn $fn_name_1() -> $t { + <$t>::with_capacity(CAP_LIM) + } + + pub fn $fn_name_2(vecc: &mut $t) { + for _ in 1..CAP_LIM { + vecc.push(TO_INSERT_ITEM); + } + } + + pub fn $fn_name_3(vecc: &mut $t) { + for _ in 0..(CAP_LIM + 1) { + vecc.push(TO_INSERT_ITEM); + } + } + + pub fn $fn_name_4(vecc: &mut $t) { + for _ in 1..CAP_LIM { + vecc.pop(); + } + } + }; +} + +write_tests_vec!(Vec, alloc_vec, push_vec, dyn_alloc_vec, pop_vec); + +pub fn vec_alloc(n: u32) -> u32 { + + let mut vvec = alloc_vec(); + + push_vec(&mut vvec); + + pop_vec(&mut vvec); + + 0 +} + +#[nexus_rt::main] +fn main() { + let n = 7; + let result = vec_alloc(n); + assert_eq!(result, 13); +} \ No newline at end of file diff --git a/nexus/simple_arithmetic_test/.cargo/config.toml b/nexus/simple_arithmetic_test/.cargo/config.toml new file mode 100644 index 0000000..80e2c50 --- /dev/null +++ b/nexus/simple_arithmetic_test/.cargo/config.toml @@ -0,0 +1,5 @@ +[target.riscv32i-unknown-none-elf] +rustflags = [ + "-C", "link-arg=-Tlink.x", +] +runner="nexus-run" diff --git a/nexus/simple_arithmetic_test/Cargo.toml b/nexus/simple_arithmetic_test/Cargo.toml new file mode 100644 index 0000000..18c5659 --- /dev/null +++ b/nexus/simple_arithmetic_test/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "simple_arithmetic_test" +version = "0.1.0" +edition = "2021" + +[dependencies] +nexus-rt = { git = "https://github.com/nexus-xyz/nexus-zkvm.git", version = "0.2.3" } + +# Generated by cargo-nexus, do not remove! +# +# This profile is used for generating proofs, as Nexus VM support for compiler optimizations is still under development. +[features] +cycles = [] # Enable cycle counting for run command + diff --git a/nexus/simple_arithmetic_test/rust-toolchain.toml b/nexus/simple_arithmetic_test/rust-toolchain.toml new file mode 100644 index 0000000..2121065 --- /dev/null +++ b/nexus/simple_arithmetic_test/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "1.77.0" +targets = ["riscv32i-unknown-none-elf"] diff --git a/nexus/simple_arithmetic_test/src/main.rs b/nexus/simple_arithmetic_test/src/main.rs new file mode 100644 index 0000000..83e9764 --- /dev/null +++ b/nexus/simple_arithmetic_test/src/main.rs @@ -0,0 +1,24 @@ +#![cfg_attr(target_arch = "riscv32", no_std, no_main)] + +fn fib(n: u32) -> u32 { + match n { + 0 => 0, + 1 => 1, + _ => fib(n - 1) + fib(n - 2), + } +} + +pub fn hept(n: u32) -> u32 { + + for i in 0..100 { + let hept = (5*i*i - 3*i)/2; + } + 0 +} + +#[nexus_rt::main] +fn main() { + let n = 7; + let result = hept(n); + assert_eq!(result, 13); +} \ No newline at end of file diff --git a/risc0/benchmark_tests/bench_programs/mem_bench.rs b/risc0/benchmark_tests/bench_programs/mem_bench.rs new file mode 100644 index 0000000..fe0931a --- /dev/null +++ b/risc0/benchmark_tests/bench_programs/mem_bench.rs @@ -0,0 +1,31 @@ +// Copyright 2024 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use risc0_zkvm::serde::to_vec; + +use crate::Job; + +pub fn new_jobs() -> Vec { + let mut jobs = Vec::new(); + for iterations in [1] { + jobs.push(Job::new( + format!("mem_alloc_vec_test-{iterations}"), + risc0_benchmark_methods::MEM_ALLOC_VEC_TEST_ELF, + risc0_benchmark_methods::MEM_ALLOC_VEC_TEST_ID.into(), + to_vec(&iterations).unwrap(), + iterations as usize, + )); + } + jobs +} \ No newline at end of file diff --git a/risc0/benchmark_tests/bench_programs/perf_bench.rs b/risc0/benchmark_tests/bench_programs/perf_bench.rs new file mode 100644 index 0000000..f6bc0d2 --- /dev/null +++ b/risc0/benchmark_tests/bench_programs/perf_bench.rs @@ -0,0 +1,31 @@ +// Copyright 2024 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use risc0_zkvm::serde::to_vec; + +use crate::Job; + +pub fn new_jobs() -> Vec { + let mut jobs = Vec::new(); + for iterations in [100] { + jobs.push(Job::new( + format!("simlpe_arithmetic_test-{iterations}"), + risc0_benchmark_methods::SIMPLE_ARITHMETIC_TEST_ELF, + risc0_benchmark_methods::SIMPLE_ARITHMETIC_TEST_ID.into(), + to_vec(&iterations).unwrap(), + iterations as usize, + )); + } + jobs +} \ No newline at end of file diff --git a/risc0/benchmark_tests/guest_programs/mem_alloc_vec_test.rs b/risc0/benchmark_tests/guest_programs/mem_alloc_vec_test.rs new file mode 100644 index 0000000..15d715d --- /dev/null +++ b/risc0/benchmark_tests/guest_programs/mem_alloc_vec_test.rs @@ -0,0 +1,65 @@ +// Copyright 2024 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::vec::Vec; + +pub const CAP_LIM: usize = 10000; +pub const TO_INSERT_ITEM: usize = 145; + +macro_rules! write_tests_vec { + ($t:ty, $fn_name_1:ident, $fn_name_2:ident, $fn_name_3:ident, $fn_name_4:ident) => { + pub fn $fn_name_1() -> $t { + <$t>::with_capacity(CAP_LIM) + } + + pub fn $fn_name_2(vecc: &mut $t) { + for _ in 1..CAP_LIM { + vecc.push(TO_INSERT_ITEM); + } + } + + pub fn $fn_name_3(vecc: &mut $t) { + for _ in 0..(CAP_LIM + 1) { + vecc.push(TO_INSERT_ITEM); + } + } + + pub fn $fn_name_4(vecc: &mut $t) { + for _ in 1..CAP_LIM { + vecc.pop(); + } + } + }; +} + +write_tests_vec!(Vec, alloc_vec, push_vec, dyn_alloc_vec, pop_vec); + +use nalgebra::Matrix2; +use risc0_zkvm::guest::env; + +fn main() { + let iterations: u32 = env::read(); + let answer = vec_alloc(iterations); + env::commit(&answer); +} + +fn vec_alloc(n: u32) -> u64 { + let mut vvec = alloc_vec(); + + push_vec(&mut vvec); + + pop_vec(&mut vvec); + + 0 +} diff --git a/risc0/benchmark_tests/guest_programs/simple_arithmetic_test.rs b/risc0/benchmark_tests/guest_programs/simple_arithmetic_test.rs new file mode 100644 index 0000000..63ca1f9 --- /dev/null +++ b/risc0/benchmark_tests/guest_programs/simple_arithmetic_test.rs @@ -0,0 +1,30 @@ +// Copyright 2024 RISC Zero, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use nalgebra::Matrix2; +use risc0_zkvm::guest::env; + +fn main() { + let iterations: u32 = env::read(); + let answer = hept(iterations); + env::commit(&answer); +} + +fn hept(n: u32) -> u64 { + for i in 0..100 { + let hept = (5*i*i - 3*i)/2; + } + + 0 +} diff --git a/shared/memory_allocations/Cargo.toml b/shared/memory_allocations/Cargo.toml new file mode 100644 index 0000000..f813837 --- /dev/null +++ b/shared/memory_allocations/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "memory_allocations" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/shared/memory_allocations/src/lib.rs b/shared/memory_allocations/src/lib.rs new file mode 100644 index 0000000..c215d52 --- /dev/null +++ b/shared/memory_allocations/src/lib.rs @@ -0,0 +1,117 @@ +use std::collections::{BTreeMap, BinaryHeap, HashMap, HashSet}; + +pub const CAP_LIM: usize = 10000; +pub const TO_INSERT_ITEM: usize = 145; + +pub fn alloc_btree_map() -> BTreeMap { + BTreeMap::new() +} + +pub fn insert_btree_map(mmap: &mut BTreeMap) { + for i in 1..CAP_LIM { + mmap.insert(TO_INSERT_ITEM + i, TO_INSERT_ITEM); + } +} + +pub fn remove_btree_map(mmap: &mut BTreeMap) { + for i in 1..CAP_LIM { + mmap.remove(&(TO_INSERT_ITEM + i)); + } +} + +macro_rules! write_tests_maps { + ($t:ty, $fn_name_1:ident, $fn_name_2:ident, $fn_name_3:ident, $fn_name_4:ident) => { + pub fn $fn_name_1() -> $t { + <$t>::with_capacity(CAP_LIM) + } + + pub fn $fn_name_2(mmap: &mut $t) { + for i in 1..CAP_LIM { + mmap.insert(TO_INSERT_ITEM + i, TO_INSERT_ITEM); + } + } + + pub fn $fn_name_3(mmap: &mut $t) { + for i in 0..(CAP_LIM + 1) { + mmap.insert(TO_INSERT_ITEM + i, TO_INSERT_ITEM); + } + } + + pub fn $fn_name_4(mmap: &mut $t) { + for i in 1..CAP_LIM { + mmap.remove(&(TO_INSERT_ITEM + i)); + } + } + }; +} + +macro_rules! write_tests_sets { + ($t:ty, $fn_name_1:ident, $fn_name_2:ident, $fn_name_3:ident, $fn_name_4:ident) => { + pub fn $fn_name_1() -> $t { + <$t>::with_capacity(CAP_LIM) + } + + pub fn $fn_name_2(mmap: &mut $t) { + for i in 1..CAP_LIM { + mmap.insert(TO_INSERT_ITEM + i); + } + } + + pub fn $fn_name_3(mmap: &mut $t) { + for i in 0..(CAP_LIM + 1) { + mmap.insert(TO_INSERT_ITEM + i); + } + } + + pub fn $fn_name_4(mmap: &mut $t) { + for i in 1..CAP_LIM { + mmap.remove(&(TO_INSERT_ITEM + i)); + } + } + }; +} + +macro_rules! write_tests_vec { + ($t:ty, $fn_name_1:ident, $fn_name_2:ident, $fn_name_3:ident, $fn_name_4:ident) => { + pub fn $fn_name_1() -> $t { + <$t>::with_capacity(CAP_LIM) + } + + pub fn $fn_name_2(vecc: &mut $t) { + for _ in 1..CAP_LIM { + vecc.push(TO_INSERT_ITEM); + } + } + + pub fn $fn_name_3(vecc: &mut $t) { + for _ in 0..(CAP_LIM + 1) { + vecc.push(TO_INSERT_ITEM); + } + } + + pub fn $fn_name_4(vecc: &mut $t) { + for _ in 1..CAP_LIM { + vecc.pop(); + } + } + }; +} + +write_tests_maps!(HashMap, alloc_hash_map, insert_hash_map, dyn_alloc_hash_map, remove_hash_map); +write_tests_sets!(HashSet, alloc_hash_set, insert_hash_set, dyn_alloc_hash_set, remove_hash_set); +write_tests_vec!(Vec, alloc_vec, push_vec, dyn_alloc_vec, pop_vec); +write_tests_vec!(BinaryHeap, alloc_b_heap, push_b_heap, dyn_alloc_b_heap, pop_b_heap); + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test2() { + let mut mmap = alloc_hash_map(); + + insert_hash_map(&mut mmap); + + remove_hash_map(&mut mmap); + } +} diff --git a/sp1/mem_alloc_vec_test/.env.example b/sp1/mem_alloc_vec_test/.env.example new file mode 100644 index 0000000..48913a1 --- /dev/null +++ b/sp1/mem_alloc_vec_test/.env.example @@ -0,0 +1,5 @@ +# 'mock' for generating mock proofs locally, 'local' for generating proofs locally, 'network' for generating proofs using the proving network. +SP1_PROVER=local +# If using the proving network, set to your whitelisted private key. For more information, see: +# https://docs.succinct.xyz/prover-network/setup.html#key-setup +SP1_PRIVATE_KEY= \ No newline at end of file diff --git a/sp1/mem_alloc_vec_test/.gitignore b/sp1/mem_alloc_vec_test/.gitignore new file mode 100644 index 0000000..174aa94 --- /dev/null +++ b/sp1/mem_alloc_vec_test/.gitignore @@ -0,0 +1,19 @@ +# Cargo build +**/target + +# Cargo config +.cargo + +# Profile-guided optimization +/tmp +pgo-data.profdata + +# MacOS nuisances +.DS_Store + +# Proofs +**/proof-with-pis.json +**/proof-with-io.json + +# Env +.env \ No newline at end of file diff --git a/sp1/mem_alloc_vec_test/.vscode/settings.json b/sp1/mem_alloc_vec_test/.vscode/settings.json new file mode 100644 index 0000000..ca6a515 --- /dev/null +++ b/sp1/mem_alloc_vec_test/.vscode/settings.json @@ -0,0 +1,37 @@ +{ + "rust-analyzer.linkedProjects": [ + "program/Cargo.toml", + "script/Cargo.toml" + ], + "rust-analyzer.check.overrideCommand": [ + "cargo", + "clippy", + "--workspace", + "--message-format=json", + "--all-features", + "--all-targets", + "--", + "-A", + "incomplete-features" + ], + "rust-analyzer.runnables.extraEnv": { + "RUST_LOG": "debug", + "RUSTFLAGS": "-Ctarget-cpu=native" + }, + "rust-analyzer.runnables.extraArgs": [ + "--release", + "+nightly" + ], + "rust-analyzer.diagnostics.disabled": [ + "unresolved-proc-macro" + ], + "editor.rulers": [ + 100 + ], + "editor.inlineSuggest.enabled": true, + "[rust]": { + "editor.defaultFormatter": "rust-lang.rust-analyzer", + "editor.formatOnSave": true, + "editor.hover.enabled": true + }, +} \ No newline at end of file diff --git a/sp1/mem_alloc_vec_test/Cargo.toml b/sp1/mem_alloc_vec_test/Cargo.toml new file mode 100644 index 0000000..3915b20 --- /dev/null +++ b/sp1/mem_alloc_vec_test/Cargo.toml @@ -0,0 +1,10 @@ +[workspace] +members = [ + "lib", + "program", + "script", +] +resolver = "2" + +[workspace.dependencies] +alloy-sol-types = "0.7.7" \ No newline at end of file diff --git a/sp1/mem_alloc_vec_test/LICENSE-MIT b/sp1/mem_alloc_vec_test/LICENSE-MIT new file mode 100644 index 0000000..626685c --- /dev/null +++ b/sp1/mem_alloc_vec_test/LICENSE-MIT @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2024 Succinct Labs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/sp1/mem_alloc_vec_test/README.md b/sp1/mem_alloc_vec_test/README.md new file mode 100644 index 0000000..295787d --- /dev/null +++ b/sp1/mem_alloc_vec_test/README.md @@ -0,0 +1,92 @@ +# SP1 Project Template + +This is a template for creating an end-to-end [SP1](https://github.com/succinctlabs/sp1) project +that can generate a proof of any RISC-V program. + +## Requirements + +- [Rust](https://rustup.rs/) +- [SP1](https://docs.succinct.xyz/getting-started/install.html) + +## Running the Project + +There are four main ways to run this project: build a program, execute a program, generate a core proof, and +generate an EVM-compatible proof. + +### Build the Program + +To build the program, run the following command: + +```sh +cd program +cargo prove build +``` + +### Execute the Program + +To run the program without generating a proof: + +```sh +cd script +cargo run --release -- --execute +``` + +This will execute the program and display the output. + +### Generate a Core Proof + +To generate a core proof for your program: + +```sh +cd script +cargo run --release -- --prove +``` + +### Generate an EVM-Compatible Proof + +> [!WARNING] +> You will need at least 128GB RAM to generate a PLONK or Groth16 proof. + +To generate a proof that is small enough to be verified on-chain and verifiable by the EVM: + +```sh +cd script +cargo run --release --bin evm -- --system plonk +``` + +this will generate a PLONK proof. If you want to generate a Groth16 proof, run the following command: + +```sh +cargo run --release --bin evm -- --system groth16 +``` + +These commands will also generate fixtures that can be used to test the verification of SP1 zkVM proofs +inside Solidity. + +### Retrieve the Verification Key + +To retrieve your `programVKey` for your on-chain contract, run the following command: + +```sh +cargo prove vkey --elf elf/riscv32im-succinct-zkvm-elf +``` + +## Using the Prover Network + +We highly recommend using the Succinct prover network for any non-trivial programs or benchmarking purposes. For more information, see the [setup guide](https://docs.succinct.xyz/prover-network/setup.html). + +To get started, copy the example environment file: + +```sh +cp .env.example .env +``` + +Then, set the `SP1_PROVER` environment variable to `network` and set the `SP1_PRIVATE_KEY` +environment variable to your whitelisted private key. + +For example, to generate an EVM-compatible proof using the prover network, run the following +command: + +```sh +SP1_PROVER=network SP1_PRIVATE_KEY=... cargo run --release --bin evm +``` diff --git a/sp1/mem_alloc_vec_test/elf/riscv32im-succinct-zkvm-elf b/sp1/mem_alloc_vec_test/elf/riscv32im-succinct-zkvm-elf new file mode 100755 index 0000000..8aa13f8 Binary files /dev/null and b/sp1/mem_alloc_vec_test/elf/riscv32im-succinct-zkvm-elf differ diff --git a/sp1/mem_alloc_vec_test/lib/Cargo.toml b/sp1/mem_alloc_vec_test/lib/Cargo.toml new file mode 100644 index 0000000..23dc268 --- /dev/null +++ b/sp1/mem_alloc_vec_test/lib/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "mem_alloc_vec_test-lib" +version = "0.1.0" +edition = "2021" + +[dependencies] +alloy-sol-types = { workspace = true } diff --git a/sp1/mem_alloc_vec_test/lib/src/lib.rs b/sp1/mem_alloc_vec_test/lib/src/lib.rs new file mode 100644 index 0000000..8dfa1be --- /dev/null +++ b/sp1/mem_alloc_vec_test/lib/src/lib.rs @@ -0,0 +1,52 @@ +use alloy_sol_types::sol; + +sol! { + /// The public values encoded as a struct that can be easily deserialized inside Solidity. + struct PublicValuesStruct { + uint32 n; + uint32 a; + uint32 b; + } +} + +pub const CAP_LIM: usize = 10000; +pub const TO_INSERT_ITEM: usize = 145; + +macro_rules! write_tests_vec { + ($t:ty, $fn_name_1:ident, $fn_name_2:ident, $fn_name_3:ident, $fn_name_4:ident) => { + pub fn $fn_name_1() -> $t { + <$t>::with_capacity(CAP_LIM) + } + + pub fn $fn_name_2(vecc: &mut $t) { + for _ in 1..CAP_LIM { + vecc.push(TO_INSERT_ITEM); + } + } + + pub fn $fn_name_3(vecc: &mut $t) { + for _ in 0..(CAP_LIM + 1) { + vecc.push(TO_INSERT_ITEM); + } + } + + pub fn $fn_name_4(vecc: &mut $t) { + for _ in 1..CAP_LIM { + vecc.pop(); + } + } + }; +} + +write_tests_vec!(Vec, alloc_vec, push_vec, dyn_alloc_vec, pop_vec); + +pub fn vec_alloc(n: u32) -> (u32, u32) { + + let mut vecc = alloc_vec(); + + push_vec(&mut vecc); + + pop_vec(&mut vecc); + + (0, 0) +} \ No newline at end of file diff --git a/sp1/mem_alloc_vec_test/program/Cargo.toml b/sp1/mem_alloc_vec_test/program/Cargo.toml new file mode 100644 index 0000000..f92f254 --- /dev/null +++ b/sp1/mem_alloc_vec_test/program/Cargo.toml @@ -0,0 +1,9 @@ +[package] +version = "0.1.0" +name = "mem_alloc_vec_test-program" +edition = "2021" + +[dependencies] +alloy-sol-types = { workspace = true } +sp1-zkvm = "1.2.0" +mem_alloc_vec_test-lib = { path = "../lib" } diff --git a/sp1/mem_alloc_vec_test/program/src/main.rs b/sp1/mem_alloc_vec_test/program/src/main.rs new file mode 100644 index 0000000..cb31543 --- /dev/null +++ b/sp1/mem_alloc_vec_test/program/src/main.rs @@ -0,0 +1,29 @@ +//! A simple program that takes a number `n` as input, and writes the `n-1`th and `n`th fibonacci +//! number as an output. + +// These two lines are necessary for the program to properly compile. +// +// Under the hood, we wrap your main function with some extra code so that it behaves properly +// inside the zkVM. +#![no_main] +sp1_zkvm::entrypoint!(main); + +use alloy_sol_types::SolType; +use mem_alloc_vec_test_lib::{vec_alloc, PublicValuesStruct}; + +pub fn main() { + // Read an input to the program. + // + // Behind the scenes, this compiles down to a custom system call which handles reading inputs + // from the prover. + let n = sp1_zkvm::io::read::(); + + let (a, b) = vec_alloc(n); + + // Encode the public values of the program. + let bytes = PublicValuesStruct::abi_encode(&PublicValuesStruct { n, a, b }); + + // Commit to the public values of the program. The final proof will have a commitment to all the + // bytes that were committed to. + sp1_zkvm::io::commit_slice(&bytes); +} diff --git a/sp1/mem_alloc_vec_test/rust-toolchain b/sp1/mem_alloc_vec_test/rust-toolchain new file mode 100644 index 0000000..3415d6b --- /dev/null +++ b/sp1/mem_alloc_vec_test/rust-toolchain @@ -0,0 +1,3 @@ +[toolchain] +channel = "1.79.0" +components = ["llvm-tools", "rustc-dev"] \ No newline at end of file diff --git a/sp1/mem_alloc_vec_test/script/Cargo.toml b/sp1/mem_alloc_vec_test/script/Cargo.toml new file mode 100644 index 0000000..cb769c6 --- /dev/null +++ b/sp1/mem_alloc_vec_test/script/Cargo.toml @@ -0,0 +1,26 @@ +[package] +version = "0.1.0" +name = "mem_alloc_vec_test-script" +edition = "2021" +default-run = "mem_alloc_vec_test" + +[[bin]] +name = "mem_alloc_vec_test" +path = "src/bin/main.rs" + +[[bin]] +name = "evm" +path = "src/bin/evm.rs" + +[dependencies] +sp1-sdk = "1.2.0" +serde_json = { version = "1.0", default-features = false, features = ["alloc"] } +serde = { version = "1.0", default-features = false, features = ["derive"] } +clap = { version = "4.0", features = ["derive", "env"] } +tracing = "0.1.40" +hex = "0.4.3" +alloy-sol-types = { workspace = true } +mem_alloc_vec_test-lib = { path = "../lib" } + +[build-dependencies] +sp1-helper = "1.2.0" diff --git a/sp1/mem_alloc_vec_test/script/build.rs b/sp1/mem_alloc_vec_test/script/build.rs new file mode 100644 index 0000000..bc5f025 --- /dev/null +++ b/sp1/mem_alloc_vec_test/script/build.rs @@ -0,0 +1,5 @@ +use sp1_helper::build_program_with_args; + +fn main() { + build_program_with_args("../program", Default::default()) +} diff --git a/sp1/mem_alloc_vec_test/script/src/bin/evm.rs b/sp1/mem_alloc_vec_test/script/src/bin/evm.rs new file mode 100644 index 0000000..d39357c --- /dev/null +++ b/sp1/mem_alloc_vec_test/script/src/bin/evm.rs @@ -0,0 +1,126 @@ +//! An end-to-end example of using the SP1 SDK to generate a proof of a program that can have an +//! EVM-Compatible proof generated which can be verified on-chain. +//! +//! You can run this script using the following command: +//! ```shell +//! RUST_LOG=info cargo run --release --bin evm -- --system plonk +//! ``` +//! or +//! ```shell +//! RUST_LOG=info cargo run --release --bin evm -- --system groth16 +//! ``` + +use alloy_sol_types::SolType; +use clap::{Parser, ValueEnum}; +use mem_alloc_vec_test_lib::PublicValuesStruct; +use serde::{Deserialize, Serialize}; +use sp1_sdk::{HashableKey, ProverClient, SP1ProofWithPublicValues, SP1Stdin, SP1VerifyingKey}; +use std::path::PathBuf; + +/// The ELF (executable and linkable format) file for the Succinct RISC-V zkVM. +pub const MEM_ALLOC_VEC_TEST_ELF: &[u8] = include_bytes!("../../../elf/riscv32im-succinct-zkvm-elf"); + +/// The arguments for the EVM command. +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct EVMArgs { + #[clap(long, default_value = "20")] + n: u32, + #[clap(long, value_enum, default_value = "plonk")] + system: ProofSystem, +} + +/// Enum representing the available proof systems +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Debug)] +enum ProofSystem { + Plonk, + Groth16, +} + +/// A fixture that can be used to test the verification of SP1 zkVM proofs inside Solidity. +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct SP1SimpleArithmeticTestProofFixture { + a: u32, + b: u32, + n: u32, + vkey: String, + public_values: String, + proof: String, +} + +fn main() { + // Setup the logger. + sp1_sdk::utils::setup_logger(); + + // Parse the command line arguments. + let args = EVMArgs::parse(); + + // Setup the prover client. + let client = ProverClient::new(); + + // Setup the program. + let (pk, vk) = client.setup(MEM_ALLOC_VEC_TEST_ELF); + + // Setup the inputs. + let mut stdin = SP1Stdin::new(); + stdin.write(&args.n); + + println!("n: {}", args.n); + println!("Proof System: {:?}", args.system); + + // Generate the proof based on the selected proof system. + let proof = match args.system { + ProofSystem::Plonk => client.prove(&pk, stdin).plonk().run(), + ProofSystem::Groth16 => client.prove(&pk, stdin).groth16().run(), + } + .expect("failed to generate proof"); + + create_proof_fixture(&proof, &vk, args.system); +} + +/// Create a fixture for the given proof. +fn create_proof_fixture( + proof: &SP1ProofWithPublicValues, + vk: &SP1VerifyingKey, + system: ProofSystem, +) { + // Deserialize the public values. + let bytes = proof.public_values.as_slice(); + let PublicValuesStruct { n, a, b } = PublicValuesStruct::abi_decode(bytes, false).unwrap(); + + // Create the testing fixture so we can test things end-to-end. + let fixture = SP1MemAllocVecTestProofFixture { + a, + b, + n, + vkey: vk.bytes32().to_string(), + public_values: format!("0x{}", hex::encode(bytes)), + proof: format!("0x{}", hex::encode(proof.bytes())), + }; + + // The verification key is used to verify that the proof corresponds to the execution of the + // program on the given input. + // + // Note that the verification key stays the same regardless of the input. + println!("Verification Key: {}", fixture.vkey); + + // The public values are the values which are publicly committed to by the zkVM. + // + // If you need to expose the inputs or outputs of your program, you should commit them in + // the public values. + println!("Public Values: {}", fixture.public_values); + + // The proof proves to the verifier that the program was executed with some inputs that led to + // the give public values. + println!("Proof Bytes: {}", fixture.proof); + + // Save the fixture to a file. + let fixture_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../contracts/src/fixtures"); + std::fs::create_dir_all(&fixture_path).expect("failed to create fixture path"); + std::fs::write( + fixture_path.join(format!("{:?}-fixture.json", system).to_lowercase()), + serde_json::to_string_pretty(&fixture).unwrap(), + ) + .expect("failed to write fixture"); +} diff --git a/sp1/mem_alloc_vec_test/script/src/bin/main.rs b/sp1/mem_alloc_vec_test/script/src/bin/main.rs new file mode 100644 index 0000000..51defd9 --- /dev/null +++ b/sp1/mem_alloc_vec_test/script/src/bin/main.rs @@ -0,0 +1,91 @@ +//! An end-to-end example of using the SP1 SDK to generate a proof of a program that can be executed +//! or have a core proof generated. +//! +//! You can run this script using the following command: +//! ```shell +//! RUST_LOG=info cargo run --release -- --execute +//! ``` +//! or +//! ```shell +//! RUST_LOG=info cargo run --release -- --prove +//! ``` + +use alloy_sol_types::SolType; +use clap::Parser; +use simple_arithmetic_test_lib::PublicValuesStruct; +use sp1_sdk::{ProverClient, SP1Stdin}; + +/// The ELF (executable and linkable format) file for the Succinct RISC-V zkVM. +pub const MEM_ALLOC_VEC_TEST_ELF: &[u8] = include_bytes!("../../../elf/riscv32im-succinct-zkvm-elf"); + +/// The arguments for the command. +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct Args { + #[clap(long)] + execute: bool, + + #[clap(long)] + prove: bool, + + #[clap(long, default_value = "20")] + n: u32, +} + +fn main() { + // Setup the logger. + sp1_sdk::utils::setup_logger(); + + // Parse the command line arguments. + let args = Args::parse(); + + if args.execute == args.prove { + eprintln!("Error: You must specify either --execute or --prove"); + std::process::exit(1); + } + + // Setup the prover client. + let client = ProverClient::new(); + + // Setup the inputs. + let mut stdin = SP1Stdin::new(); + stdin.write(&args.n); + + println!("n: {}", args.n); + + if args.execute { + // Execute the program + let (output, report) = client.execute(MEM_ALLOC_VEC_TEST_ELF, stdin).run().unwrap(); + println!("Program executed successfully."); + + // Read the output. + let decoded = PublicValuesStruct::abi_decode(output.as_slice(), true).unwrap(); + let PublicValuesStruct { n, a, b } = decoded; + println!("n: {}", n); + println!("a: {}", a); + println!("b: {}", b); + + let (expected_a, expected_b) = fibonacci_lib::fibonacci(n); + assert_eq!(a, expected_a); + assert_eq!(b, expected_b); + println!("Values are correct!"); + + // Record the number of cycles executed. + println!("Number of cycles: {}", report.total_instruction_count()); + } else { + // Setup the program for proving. + let (pk, vk) = client.setup(FIBONACCI_ELF); + + // Generate the proof + let proof = client + .prove(&pk, stdin) + .run() + .expect("failed to generate proof"); + + println!("Successfully generated proof!"); + + // Verify the proof. + client.verify(&proof, &vk).expect("failed to verify proof"); + println!("Successfully verified proof!"); + } +} diff --git a/sp1/simple_arithmetic_test/.env.example b/sp1/simple_arithmetic_test/.env.example new file mode 100644 index 0000000..48913a1 --- /dev/null +++ b/sp1/simple_arithmetic_test/.env.example @@ -0,0 +1,5 @@ +# 'mock' for generating mock proofs locally, 'local' for generating proofs locally, 'network' for generating proofs using the proving network. +SP1_PROVER=local +# If using the proving network, set to your whitelisted private key. For more information, see: +# https://docs.succinct.xyz/prover-network/setup.html#key-setup +SP1_PRIVATE_KEY= \ No newline at end of file diff --git a/sp1/simple_arithmetic_test/.gitignore b/sp1/simple_arithmetic_test/.gitignore new file mode 100644 index 0000000..174aa94 --- /dev/null +++ b/sp1/simple_arithmetic_test/.gitignore @@ -0,0 +1,19 @@ +# Cargo build +**/target + +# Cargo config +.cargo + +# Profile-guided optimization +/tmp +pgo-data.profdata + +# MacOS nuisances +.DS_Store + +# Proofs +**/proof-with-pis.json +**/proof-with-io.json + +# Env +.env \ No newline at end of file diff --git a/sp1/simple_arithmetic_test/.vscode/settings.json b/sp1/simple_arithmetic_test/.vscode/settings.json new file mode 100644 index 0000000..ca6a515 --- /dev/null +++ b/sp1/simple_arithmetic_test/.vscode/settings.json @@ -0,0 +1,37 @@ +{ + "rust-analyzer.linkedProjects": [ + "program/Cargo.toml", + "script/Cargo.toml" + ], + "rust-analyzer.check.overrideCommand": [ + "cargo", + "clippy", + "--workspace", + "--message-format=json", + "--all-features", + "--all-targets", + "--", + "-A", + "incomplete-features" + ], + "rust-analyzer.runnables.extraEnv": { + "RUST_LOG": "debug", + "RUSTFLAGS": "-Ctarget-cpu=native" + }, + "rust-analyzer.runnables.extraArgs": [ + "--release", + "+nightly" + ], + "rust-analyzer.diagnostics.disabled": [ + "unresolved-proc-macro" + ], + "editor.rulers": [ + 100 + ], + "editor.inlineSuggest.enabled": true, + "[rust]": { + "editor.defaultFormatter": "rust-lang.rust-analyzer", + "editor.formatOnSave": true, + "editor.hover.enabled": true + }, +} \ No newline at end of file diff --git a/sp1/simple_arithmetic_test/Cargo.toml b/sp1/simple_arithmetic_test/Cargo.toml new file mode 100644 index 0000000..3915b20 --- /dev/null +++ b/sp1/simple_arithmetic_test/Cargo.toml @@ -0,0 +1,10 @@ +[workspace] +members = [ + "lib", + "program", + "script", +] +resolver = "2" + +[workspace.dependencies] +alloy-sol-types = "0.7.7" \ No newline at end of file diff --git a/sp1/simple_arithmetic_test/LICENSE-MIT b/sp1/simple_arithmetic_test/LICENSE-MIT new file mode 100644 index 0000000..626685c --- /dev/null +++ b/sp1/simple_arithmetic_test/LICENSE-MIT @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2024 Succinct Labs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/sp1/simple_arithmetic_test/README.md b/sp1/simple_arithmetic_test/README.md new file mode 100644 index 0000000..295787d --- /dev/null +++ b/sp1/simple_arithmetic_test/README.md @@ -0,0 +1,92 @@ +# SP1 Project Template + +This is a template for creating an end-to-end [SP1](https://github.com/succinctlabs/sp1) project +that can generate a proof of any RISC-V program. + +## Requirements + +- [Rust](https://rustup.rs/) +- [SP1](https://docs.succinct.xyz/getting-started/install.html) + +## Running the Project + +There are four main ways to run this project: build a program, execute a program, generate a core proof, and +generate an EVM-compatible proof. + +### Build the Program + +To build the program, run the following command: + +```sh +cd program +cargo prove build +``` + +### Execute the Program + +To run the program without generating a proof: + +```sh +cd script +cargo run --release -- --execute +``` + +This will execute the program and display the output. + +### Generate a Core Proof + +To generate a core proof for your program: + +```sh +cd script +cargo run --release -- --prove +``` + +### Generate an EVM-Compatible Proof + +> [!WARNING] +> You will need at least 128GB RAM to generate a PLONK or Groth16 proof. + +To generate a proof that is small enough to be verified on-chain and verifiable by the EVM: + +```sh +cd script +cargo run --release --bin evm -- --system plonk +``` + +this will generate a PLONK proof. If you want to generate a Groth16 proof, run the following command: + +```sh +cargo run --release --bin evm -- --system groth16 +``` + +These commands will also generate fixtures that can be used to test the verification of SP1 zkVM proofs +inside Solidity. + +### Retrieve the Verification Key + +To retrieve your `programVKey` for your on-chain contract, run the following command: + +```sh +cargo prove vkey --elf elf/riscv32im-succinct-zkvm-elf +``` + +## Using the Prover Network + +We highly recommend using the Succinct prover network for any non-trivial programs or benchmarking purposes. For more information, see the [setup guide](https://docs.succinct.xyz/prover-network/setup.html). + +To get started, copy the example environment file: + +```sh +cp .env.example .env +``` + +Then, set the `SP1_PROVER` environment variable to `network` and set the `SP1_PRIVATE_KEY` +environment variable to your whitelisted private key. + +For example, to generate an EVM-compatible proof using the prover network, run the following +command: + +```sh +SP1_PROVER=network SP1_PRIVATE_KEY=... cargo run --release --bin evm +``` diff --git a/sp1/simple_arithmetic_test/elf/riscv32im-succinct-zkvm-elf b/sp1/simple_arithmetic_test/elf/riscv32im-succinct-zkvm-elf new file mode 100755 index 0000000..8aa13f8 Binary files /dev/null and b/sp1/simple_arithmetic_test/elf/riscv32im-succinct-zkvm-elf differ diff --git a/sp1/simple_arithmetic_test/lib/Cargo.toml b/sp1/simple_arithmetic_test/lib/Cargo.toml new file mode 100644 index 0000000..fe5a39e --- /dev/null +++ b/sp1/simple_arithmetic_test/lib/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "simple_arithmetic_test-lib" +version = "0.1.0" +edition = "2021" + +[dependencies] +alloy-sol-types = { workspace = true } diff --git a/sp1/simple_arithmetic_test/lib/src/lib.rs b/sp1/simple_arithmetic_test/lib/src/lib.rs new file mode 100644 index 0000000..03d36ad --- /dev/null +++ b/sp1/simple_arithmetic_test/lib/src/lib.rs @@ -0,0 +1,19 @@ +use alloy_sol_types::sol; + +sol! { + /// The public values encoded as a struct that can be easily deserialized inside Solidity. + struct PublicValuesStruct { + uint32 n; + uint32 a; + uint32 b; + } +} + +pub fn hept(n: u32) -> (u32, u32) { + + for i in 0..100 { + let hept = (5*i*i - 3*i)/2; + } + + (0, 0) +} \ No newline at end of file diff --git a/sp1/simple_arithmetic_test/program/Cargo.toml b/sp1/simple_arithmetic_test/program/Cargo.toml new file mode 100644 index 0000000..3ffda43 --- /dev/null +++ b/sp1/simple_arithmetic_test/program/Cargo.toml @@ -0,0 +1,9 @@ +[package] +version = "0.1.0" +name = "simple_arithmetic_test-program" +edition = "2021" + +[dependencies] +alloy-sol-types = { workspace = true } +sp1-zkvm = "1.2.0" +simple_arithmetic_test-lib = { path = "../lib" } diff --git a/sp1/simple_arithmetic_test/program/src/main.rs b/sp1/simple_arithmetic_test/program/src/main.rs new file mode 100644 index 0000000..1a624b3 --- /dev/null +++ b/sp1/simple_arithmetic_test/program/src/main.rs @@ -0,0 +1,29 @@ +//! A simple program that takes a number `n` as input, and writes the `n-1`th and `n`th fibonacci +//! number as an output. + +// These two lines are necessary for the program to properly compile. +// +// Under the hood, we wrap your main function with some extra code so that it behaves properly +// inside the zkVM. +#![no_main] +sp1_zkvm::entrypoint!(main); + +use alloy_sol_types::SolType; +use simple_arithmetic_test_lib::{hept, PublicValuesStruct}; + +pub fn main() { + // Read an input to the program. + // + // Behind the scenes, this compiles down to a custom system call which handles reading inputs + // from the prover. + let n = sp1_zkvm::io::read::(); + + let (a, b) = hept(n); + + // Encode the public values of the program. + let bytes = PublicValuesStruct::abi_encode(&PublicValuesStruct { n, a, b }); + + // Commit to the public values of the program. The final proof will have a commitment to all the + // bytes that were committed to. + sp1_zkvm::io::commit_slice(&bytes); +} diff --git a/sp1/simple_arithmetic_test/rust-toolchain b/sp1/simple_arithmetic_test/rust-toolchain new file mode 100644 index 0000000..3415d6b --- /dev/null +++ b/sp1/simple_arithmetic_test/rust-toolchain @@ -0,0 +1,3 @@ +[toolchain] +channel = "1.79.0" +components = ["llvm-tools", "rustc-dev"] \ No newline at end of file diff --git a/sp1/simple_arithmetic_test/script/Cargo.toml b/sp1/simple_arithmetic_test/script/Cargo.toml new file mode 100644 index 0000000..4de789f --- /dev/null +++ b/sp1/simple_arithmetic_test/script/Cargo.toml @@ -0,0 +1,26 @@ +[package] +version = "0.1.0" +name = "simple_arithmetic_test-script" +edition = "2021" +default-run = "simple_arithmetic_test" + +[[bin]] +name = "simple_arithmetic_test" +path = "src/bin/main.rs" + +[[bin]] +name = "evm" +path = "src/bin/evm.rs" + +[dependencies] +sp1-sdk = "1.2.0" +serde_json = { version = "1.0", default-features = false, features = ["alloc"] } +serde = { version = "1.0", default-features = false, features = ["derive"] } +clap = { version = "4.0", features = ["derive", "env"] } +tracing = "0.1.40" +hex = "0.4.3" +alloy-sol-types = { workspace = true } +simple_arithmetic_test-lib = { path = "../lib" } + +[build-dependencies] +sp1-helper = "1.2.0" diff --git a/sp1/simple_arithmetic_test/script/build.rs b/sp1/simple_arithmetic_test/script/build.rs new file mode 100644 index 0000000..bc5f025 --- /dev/null +++ b/sp1/simple_arithmetic_test/script/build.rs @@ -0,0 +1,5 @@ +use sp1_helper::build_program_with_args; + +fn main() { + build_program_with_args("../program", Default::default()) +} diff --git a/sp1/simple_arithmetic_test/script/src/bin/evm.rs b/sp1/simple_arithmetic_test/script/src/bin/evm.rs new file mode 100644 index 0000000..88ff465 --- /dev/null +++ b/sp1/simple_arithmetic_test/script/src/bin/evm.rs @@ -0,0 +1,126 @@ +//! An end-to-end example of using the SP1 SDK to generate a proof of a program that can have an +//! EVM-Compatible proof generated which can be verified on-chain. +//! +//! You can run this script using the following command: +//! ```shell +//! RUST_LOG=info cargo run --release --bin evm -- --system plonk +//! ``` +//! or +//! ```shell +//! RUST_LOG=info cargo run --release --bin evm -- --system groth16 +//! ``` + +use alloy_sol_types::SolType; +use clap::{Parser, ValueEnum}; +use simple_arithmetic_test_lib::PublicValuesStruct; +use serde::{Deserialize, Serialize}; +use sp1_sdk::{HashableKey, ProverClient, SP1ProofWithPublicValues, SP1Stdin, SP1VerifyingKey}; +use std::path::PathBuf; + +/// The ELF (executable and linkable format) file for the Succinct RISC-V zkVM. +pub const SIMPLE_ARITHMETIC_TEST_ELF: &[u8] = include_bytes!("../../../elf/riscv32im-succinct-zkvm-elf"); + +/// The arguments for the EVM command. +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct EVMArgs { + #[clap(long, default_value = "20")] + n: u32, + #[clap(long, value_enum, default_value = "plonk")] + system: ProofSystem, +} + +/// Enum representing the available proof systems +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Debug)] +enum ProofSystem { + Plonk, + Groth16, +} + +/// A fixture that can be used to test the verification of SP1 zkVM proofs inside Solidity. +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct SP1SimpleArithmeticTestProofFixture { + a: u32, + b: u32, + n: u32, + vkey: String, + public_values: String, + proof: String, +} + +fn main() { + // Setup the logger. + sp1_sdk::utils::setup_logger(); + + // Parse the command line arguments. + let args = EVMArgs::parse(); + + // Setup the prover client. + let client = ProverClient::new(); + + // Setup the program. + let (pk, vk) = client.setup(SIMPLE_ARITHMETIC_TEST_ELF); + + // Setup the inputs. + let mut stdin = SP1Stdin::new(); + stdin.write(&args.n); + + println!("n: {}", args.n); + println!("Proof System: {:?}", args.system); + + // Generate the proof based on the selected proof system. + let proof = match args.system { + ProofSystem::Plonk => client.prove(&pk, stdin).plonk().run(), + ProofSystem::Groth16 => client.prove(&pk, stdin).groth16().run(), + } + .expect("failed to generate proof"); + + create_proof_fixture(&proof, &vk, args.system); +} + +/// Create a fixture for the given proof. +fn create_proof_fixture( + proof: &SP1ProofWithPublicValues, + vk: &SP1VerifyingKey, + system: ProofSystem, +) { + // Deserialize the public values. + let bytes = proof.public_values.as_slice(); + let PublicValuesStruct { n, a, b } = PublicValuesStruct::abi_decode(bytes, false).unwrap(); + + // Create the testing fixture so we can test things end-to-end. + let fixture = SP1SimpleArithmeticTestProofFixture { + a, + b, + n, + vkey: vk.bytes32().to_string(), + public_values: format!("0x{}", hex::encode(bytes)), + proof: format!("0x{}", hex::encode(proof.bytes())), + }; + + // The verification key is used to verify that the proof corresponds to the execution of the + // program on the given input. + // + // Note that the verification key stays the same regardless of the input. + println!("Verification Key: {}", fixture.vkey); + + // The public values are the values which are publicly committed to by the zkVM. + // + // If you need to expose the inputs or outputs of your program, you should commit them in + // the public values. + println!("Public Values: {}", fixture.public_values); + + // The proof proves to the verifier that the program was executed with some inputs that led to + // the give public values. + println!("Proof Bytes: {}", fixture.proof); + + // Save the fixture to a file. + let fixture_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../contracts/src/fixtures"); + std::fs::create_dir_all(&fixture_path).expect("failed to create fixture path"); + std::fs::write( + fixture_path.join(format!("{:?}-fixture.json", system).to_lowercase()), + serde_json::to_string_pretty(&fixture).unwrap(), + ) + .expect("failed to write fixture"); +} diff --git a/sp1/simple_arithmetic_test/script/src/bin/main.rs b/sp1/simple_arithmetic_test/script/src/bin/main.rs new file mode 100644 index 0000000..4e9eff4 --- /dev/null +++ b/sp1/simple_arithmetic_test/script/src/bin/main.rs @@ -0,0 +1,91 @@ +//! An end-to-end example of using the SP1 SDK to generate a proof of a program that can be executed +//! or have a core proof generated. +//! +//! You can run this script using the following command: +//! ```shell +//! RUST_LOG=info cargo run --release -- --execute +//! ``` +//! or +//! ```shell +//! RUST_LOG=info cargo run --release -- --prove +//! ``` + +use alloy_sol_types::SolType; +use clap::Parser; +use simple_arithmetic_test_lib::PublicValuesStruct; +use sp1_sdk::{ProverClient, SP1Stdin}; + +/// The ELF (executable and linkable format) file for the Succinct RISC-V zkVM. +pub const SIMPLE_ARITHMETIC_TEST_ELF: &[u8] = include_bytes!("../../../elf/riscv32im-succinct-zkvm-elf"); + +/// The arguments for the command. +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct Args { + #[clap(long)] + execute: bool, + + #[clap(long)] + prove: bool, + + #[clap(long, default_value = "20")] + n: u32, +} + +fn main() { + // Setup the logger. + sp1_sdk::utils::setup_logger(); + + // Parse the command line arguments. + let args = Args::parse(); + + if args.execute == args.prove { + eprintln!("Error: You must specify either --execute or --prove"); + std::process::exit(1); + } + + // Setup the prover client. + let client = ProverClient::new(); + + // Setup the inputs. + let mut stdin = SP1Stdin::new(); + stdin.write(&args.n); + + println!("n: {}", args.n); + + if args.execute { + // Execute the program + let (output, report) = client.execute(SIMPLE_ARITHMETIC_TEST_ELF, stdin).run().unwrap(); + println!("Program executed successfully."); + + // Read the output. + let decoded = PublicValuesStruct::abi_decode(output.as_slice(), true).unwrap(); + let PublicValuesStruct { n, a, b } = decoded; + println!("n: {}", n); + println!("a: {}", a); + println!("b: {}", b); + + let (expected_a, expected_b) = fibonacci_lib::fibonacci(n); + assert_eq!(a, expected_a); + assert_eq!(b, expected_b); + println!("Values are correct!"); + + // Record the number of cycles executed. + println!("Number of cycles: {}", report.total_instruction_count()); + } else { + // Setup the program for proving. + let (pk, vk) = client.setup(FIBONACCI_ELF); + + // Generate the proof + let proof = client + .prove(&pk, stdin) + .run() + .expect("failed to generate proof"); + + println!("Successfully generated proof!"); + + // Verify the proof. + client.verify(&proof, &vk).expect("failed to verify proof"); + println!("Successfully verified proof!"); + } +} diff --git a/valida/scripts_and_tools/build-rust.sh b/valida/scripts_and_tools/build-rust.sh new file mode 100755 index 0000000..e82ccb3 --- /dev/null +++ b/valida/scripts_and_tools/build-rust.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +TEST_NAME=$1 + +rustc --emit=llvm-ir -Cpanic="abort" -C opt-level=3 -C target-cpu=generic ../tests/$TEST_NAME.rs +./llc -march=delendum -filetype=obj $TEST_NAME.ll +./ld.lld --script=./valida.ld $TEST_NAME.o -L . -lstdio -o $TEST_NAME diff --git a/valida/scripts_and_tools/valida_prove.sh b/valida/scripts_and_tools/valida_prove.sh new file mode 100755 index 0000000..60e4025 --- /dev/null +++ b/valida/scripts_and_tools/valida_prove.sh @@ -0,0 +1,3 @@ +TEST_NAME=$1 + +./valida prove ./$TEST_NAME ./$TEST_NAME.proof \ No newline at end of file diff --git a/valida/scripts_and_tools/valida_setup.sh b/valida/scripts_and_tools/valida_setup.sh new file mode 100755 index 0000000..abb11e2 --- /dev/null +++ b/valida/scripts_and_tools/valida_setup.sh @@ -0,0 +1,15 @@ +set -eo + +wget https://github.com/lita-xyz/llvm-valida-releases/releases/latest/download/llvm-valida-v0.3.0-alpha-linux-x86_64.tar.gz +tar xzvf llvm-valida-v0.3.0-alpha-linux-x86_64.tar.gz +cd llvm-valida-release +mv clang .. +mv DelendumEntryPoint.o .. +mv ld.lld .. +mv llc .. +mv valida .. +mv valida.ld .. +mv libstdio.a .. +cd .. +rm -rf llvm-valida-release +rm -rf llvm-valida-v0.3.0-alpha-linux-x86_64.tar.gz \ No newline at end of file diff --git a/valida/scripts_and_tools/valida_verify.sh b/valida/scripts_and_tools/valida_verify.sh new file mode 100755 index 0000000..b00aee0 --- /dev/null +++ b/valida/scripts_and_tools/valida_verify.sh @@ -0,0 +1,3 @@ +TEST_NAME=$1 + +./valida verify ./$TEST_NAME ./$TEST_NAME.proof \ No newline at end of file diff --git a/valida/tests/empty_test.rs b/valida/tests/empty_test.rs new file mode 100644 index 0000000..0ae196c --- /dev/null +++ b/valida/tests/empty_test.rs @@ -0,0 +1,14 @@ +#![no_std] +#![feature(start)] + +use core::panic::PanicInfo; + +#[panic_handler] +fn panic(_info: &PanicInfo) -> ! { + loop {} +} + +#[start] +fn main(_argc: isize, _argv: *const *const u8) -> isize { + 0 +} \ No newline at end of file diff --git a/valida/tests/simple_arithmetic_test.rs b/valida/tests/simple_arithmetic_test.rs new file mode 100644 index 0000000..63585d9 --- /dev/null +++ b/valida/tests/simple_arithmetic_test.rs @@ -0,0 +1,23 @@ +#![no_std] +#![feature(start)] + +use core::panic::PanicInfo; + +#[panic_handler] +fn panic(_info: &PanicInfo) -> ! { + loop {} +} + +#[start] +fn main(_argc: isize, _argv: *const *const u8) -> isize { + let i = 11; + let hept = (5*i*i + 3*i)/2; + if hept == 286 { + return 1; + } + else { + return 0; + } +} + + diff --git a/zkwasm/scripts_and_tools/zkwasm_build.sh b/zkwasm/scripts_and_tools/zkwasm_build.sh new file mode 100755 index 0000000..a08d16e --- /dev/null +++ b/zkwasm/scripts_and_tools/zkwasm_build.sh @@ -0,0 +1,8 @@ +WASM_PATH=$1 + +pushd $WASM_PATH +wasm-pack build --release --out-name test.wasm --out-dir pkg +wasm-opt -Oz -o output.wasm pkg/test.wasm + +rm -rf pkg output params +popd \ No newline at end of file diff --git a/zkwasm/scripts_and_tools/zkwasm_prove.sh b/zkwasm/scripts_and_tools/zkwasm_prove.sh new file mode 100755 index 0000000..b80d253 --- /dev/null +++ b/zkwasm/scripts_and_tools/zkwasm_prove.sh @@ -0,0 +1,5 @@ +WASM_PATH=$1 + +cd zkWasm +./target/release/zkwasm-cli --params ./params testwasm prove --output ./output --wasm $WASM_PATH +cd .. \ No newline at end of file diff --git a/zkwasm/scripts_and_tools/zkwasm_setup.sh b/zkwasm/scripts_and_tools/zkwasm_setup.sh new file mode 100755 index 0000000..1976373 --- /dev/null +++ b/zkwasm/scripts_and_tools/zkwasm_setup.sh @@ -0,0 +1,6 @@ +set -eo + +git clone --recurse-submodules https://github.com/DelphinusLab/zkWasm.git +cd zkWasm +cargo build --release +cd .. \ No newline at end of file diff --git a/zkwasm/scripts_and_tools/zkwasm_setup_circuit.sh b/zkwasm/scripts_and_tools/zkwasm_setup_circuit.sh new file mode 100755 index 0000000..2591bc5 --- /dev/null +++ b/zkwasm/scripts_and_tools/zkwasm_setup_circuit.sh @@ -0,0 +1,5 @@ +WASM_PATH=$1 + +cd zkWasm +cargo run --release -- --params params testwasm setup --host standard -k 18 --wasm $WASM_PATH +cd .. \ No newline at end of file diff --git a/zkwasm/scripts_and_tools/zkwasm_verify.sh b/zkwasm/scripts_and_tools/zkwasm_verify.sh new file mode 100755 index 0000000..fa83a4c --- /dev/null +++ b/zkwasm/scripts_and_tools/zkwasm_verify.sh @@ -0,0 +1,3 @@ +cd zkWasm +./target/release/zkwasm-cli --params ./params testwasm verify --output ./output +cd .. \ No newline at end of file diff --git a/zkwasm/tests/empty_test/Cargo.toml b/zkwasm/tests/empty_test/Cargo.toml new file mode 100644 index 0000000..b2527bc --- /dev/null +++ b/zkwasm/tests/empty_test/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "simple_arithmetic_test" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +zkwasm-rust-sdk = { git = "https://github.com/DelphinusLab/zkWasm-rust.git" } +wasm-bindgen = "0.2.83" \ No newline at end of file diff --git a/zkwasm/tests/empty_test/src/lib.rs b/zkwasm/tests/empty_test/src/lib.rs new file mode 100644 index 0000000..bdefa2e --- /dev/null +++ b/zkwasm/tests/empty_test/src/lib.rs @@ -0,0 +1,7 @@ +#![no_main] + +use zkwasm_rust_sdk::wasm_dbg; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +pub fn zkmain() {} diff --git a/zkwasm/tests/mem_alloc_vec_test/Cargo.toml b/zkwasm/tests/mem_alloc_vec_test/Cargo.toml new file mode 100644 index 0000000..1698596 --- /dev/null +++ b/zkwasm/tests/mem_alloc_vec_test/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "mem_alloc_vec_test" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +zkwasm-rust-sdk = { git = "https://github.com/DelphinusLab/zkWasm-rust.git" } +wasm-bindgen = "0.2.83" +memory_allocations = { path = "../../../shared/memory_allocations"} \ No newline at end of file diff --git a/zkwasm/tests/mem_alloc_vec_test/src/lib.rs b/zkwasm/tests/mem_alloc_vec_test/src/lib.rs new file mode 100644 index 0000000..de0793d --- /dev/null +++ b/zkwasm/tests/mem_alloc_vec_test/src/lib.rs @@ -0,0 +1,14 @@ +#![no_main] + +use zkwasm_rust_sdk::wasm_dbg; +use wasm_bindgen::prelude::*; +use memory_allocations::{alloc_vec, push_vec, pop_vec}; + +#[wasm_bindgen] +pub fn zkmain() { + let mut vvec = alloc_vec(); + + push_vec(&mut vvec); + + pop_vec(&mut vvec); +} diff --git a/zkwasm/tests/simple_arithmetic_test/Cargo.toml b/zkwasm/tests/simple_arithmetic_test/Cargo.toml new file mode 100644 index 0000000..b2527bc --- /dev/null +++ b/zkwasm/tests/simple_arithmetic_test/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "simple_arithmetic_test" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +zkwasm-rust-sdk = { git = "https://github.com/DelphinusLab/zkWasm-rust.git" } +wasm-bindgen = "0.2.83" \ No newline at end of file diff --git a/zkwasm/tests/simple_arithmetic_test/src/lib.rs b/zkwasm/tests/simple_arithmetic_test/src/lib.rs new file mode 100644 index 0000000..8e7b81c --- /dev/null +++ b/zkwasm/tests/simple_arithmetic_test/src/lib.rs @@ -0,0 +1,11 @@ +#![no_main] + +use zkwasm_rust_sdk::wasm_dbg; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +pub fn zkmain() { + for i in 0..100 { + let hept = (5*i*i - 3*i)/2; + } +}