adding sp1, zkwasm, valida, nexus and risc0 guest program

This commit is contained in:
Oleksandr Pravdyvyi 2024-09-17 17:04:30 +03:00
parent cc239a14ab
commit 29d5fcbe1d
63 changed files with 1598 additions and 0 deletions

View File

@ -0,0 +1,5 @@
[target.riscv32i-unknown-none-elf]
rustflags = [
"-C", "link-arg=-Tlink.x",
]
runner="nexus-run"

View File

@ -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

View File

@ -0,0 +1,3 @@
[toolchain]
channel = "1.77.0"
targets = ["riscv32i-unknown-none-elf"]

View File

@ -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<usize>, 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);
}

View File

@ -0,0 +1,5 @@
[target.riscv32i-unknown-none-elf]
rustflags = [
"-C", "link-arg=-Tlink.x",
]
runner="nexus-run"

View File

@ -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

View File

@ -0,0 +1,3 @@
[toolchain]
channel = "1.77.0"
targets = ["riscv32i-unknown-none-elf"]

View File

@ -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);
}

View File

@ -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<Job> {
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
}

View File

@ -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<Job> {
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
}

View File

@ -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<usize>, 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
}

View File

@ -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
}

View File

@ -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]

View File

@ -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<usize, usize> {
BTreeMap::new()
}
pub fn insert_btree_map(mmap: &mut BTreeMap<usize, usize>) {
for i in 1..CAP_LIM {
mmap.insert(TO_INSERT_ITEM + i, TO_INSERT_ITEM);
}
}
pub fn remove_btree_map(mmap: &mut BTreeMap<usize, usize>) {
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<usize, usize>, alloc_hash_map, insert_hash_map, dyn_alloc_hash_map, remove_hash_map);
write_tests_sets!(HashSet<usize>, alloc_hash_set, insert_hash_set, dyn_alloc_hash_set, remove_hash_set);
write_tests_vec!(Vec<usize>, alloc_vec, push_vec, dyn_alloc_vec, pop_vec);
write_tests_vec!(BinaryHeap<usize>, 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);
}
}

View File

@ -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=

19
sp1/mem_alloc_vec_test/.gitignore vendored Normal file
View File

@ -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

View File

@ -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
},
}

View File

@ -0,0 +1,10 @@
[workspace]
members = [
"lib",
"program",
"script",
]
resolver = "2"
[workspace.dependencies]
alloy-sol-types = "0.7.7"

View File

@ -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.

View File

@ -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
```

Binary file not shown.

View File

@ -0,0 +1,7 @@
[package]
name = "mem_alloc_vec_test-lib"
version = "0.1.0"
edition = "2021"
[dependencies]
alloy-sol-types = { workspace = true }

View File

@ -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<usize>, 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)
}

View File

@ -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" }

View File

@ -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::<u32>();
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);
}

View File

@ -0,0 +1,3 @@
[toolchain]
channel = "1.79.0"
components = ["llvm-tools", "rustc-dev"]

View File

@ -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"

View File

@ -0,0 +1,5 @@
use sp1_helper::build_program_with_args;
fn main() {
build_program_with_args("../program", Default::default())
}

View File

@ -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");
}

View File

@ -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!");
}
}

View File

@ -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=

19
sp1/simple_arithmetic_test/.gitignore vendored Normal file
View File

@ -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

View File

@ -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
},
}

View File

@ -0,0 +1,10 @@
[workspace]
members = [
"lib",
"program",
"script",
]
resolver = "2"
[workspace.dependencies]
alloy-sol-types = "0.7.7"

View File

@ -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.

View File

@ -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
```

Binary file not shown.

View File

@ -0,0 +1,7 @@
[package]
name = "simple_arithmetic_test-lib"
version = "0.1.0"
edition = "2021"
[dependencies]
alloy-sol-types = { workspace = true }

View File

@ -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)
}

View File

@ -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" }

View File

@ -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::<u32>();
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);
}

View File

@ -0,0 +1,3 @@
[toolchain]
channel = "1.79.0"
components = ["llvm-tools", "rustc-dev"]

View File

@ -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"

View File

@ -0,0 +1,5 @@
use sp1_helper::build_program_with_args;
fn main() {
build_program_with_args("../program", Default::default())
}

View File

@ -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");
}

View File

@ -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!");
}
}

View File

@ -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

View File

@ -0,0 +1,3 @@
TEST_NAME=$1
./valida prove ./$TEST_NAME ./$TEST_NAME.proof

View File

@ -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

View File

@ -0,0 +1,3 @@
TEST_NAME=$1
./valida verify ./$TEST_NAME ./$TEST_NAME.proof

View File

@ -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
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -0,0 +1,5 @@
WASM_PATH=$1
cd zkWasm
./target/release/zkwasm-cli --params ./params testwasm prove --output ./output --wasm $WASM_PATH
cd ..

View File

@ -0,0 +1,6 @@
set -eo
git clone --recurse-submodules https://github.com/DelphinusLab/zkWasm.git
cd zkWasm
cargo build --release
cd ..

View File

@ -0,0 +1,5 @@
WASM_PATH=$1
cd zkWasm
cargo run --release -- --params params testwasm setup --host standard -k 18 --wasm $WASM_PATH
cd ..

View File

@ -0,0 +1,3 @@
cd zkWasm
./target/release/zkwasm-cli --params ./params testwasm verify --output ./output
cd ..

View File

@ -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"

View File

@ -0,0 +1,7 @@
#![no_main]
use zkwasm_rust_sdk::wasm_dbg;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn zkmain() {}

View File

@ -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"}

View File

@ -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);
}

View File

@ -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"

View File

@ -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;
}
}