diff --git a/ceno b/ceno index be7f34f4..93a74bb8 160000 --- a/ceno +++ b/ceno @@ -1 +1 @@ -Subproject commit be7f34f43c02cb68f0ef22a5cec84076b0aa2772 +Subproject commit 93a74bb82a17f5456bb0ab890dec62d9df107d6c diff --git a/run_sorting b/run_sorting new file mode 100755 index 00000000..55f6c3c3 --- /dev/null +++ b/run_sorting @@ -0,0 +1,50 @@ +#!/bin/bash +set -euxo pipefail + +# Prep +( + ( + cd ceno/examples + cargo build --release --example=quadratic_sorting + ) + ( + cd ceno + cargo build --release --bin e2e + ) + + mkdir --parents sorting-output/ceno + mkdir --parents sorting-output/sp1 +) + +( + cd sorting/program + cargo prove build +) +export MAX=12000 +# export MAX="$((1 << 14))" + +for N in $(shuf --input-range=1-${MAX}); do + for system in $(shuf --echo ceno sp1); do + output="sorting-output/${N}-$(date --iso-8601=ns --utc)/${system}" + mkdir --parents "${output}" + ./run_${system}_sorting "${N}" "${output}" + + done + +done + +output="output_time" + +( + cd sorting/script + + # export RUSTFLAGS="-C target-cpu=native -C target-feature=+avx512f" + # export RUSTFLAGS="-C target-cpu=native" + export RUST_LOG=info + # cargo clean + cargo build --release --bin sorting + /usr/bin/time --verbose --output="${output}" -- cargo run --release -- --n=$N --prove + echo "RUSTFLAGS=\'${RUSTFLAGS:-}\'" + echo "N=\'${N}'" + cat "${output}" +) diff --git a/run_sp1_sorting b/run_sp1_sorting index f39ccd33..4eac62d8 100755 --- a/run_sp1_sorting +++ b/run_sp1_sorting @@ -1,7 +1,14 @@ #!/bin/bash set -euxo pipefail -export N=$((1<<10)) -output="output_time" + +N="$1" + +# We assume that "${output_dir}" exists. +export output_dir="$2" +test -d "${output_dir}" + +output_time="$(realpath "${output_dir}/output_time")" +output_log="$(realpath "${output_dir}/log")" ( cd sorting/program @@ -9,14 +16,13 @@ output="output_time" ) ( cd sorting/script - - # export RUSTFLAGS="-C target-cpu=native -C target-feature=+avx512f" - # export RUSTFLAGS="-C target-cpu=native" + if grep --silent avx512 /proc/cpuinfo; then + export RUSTFLAGS="-C target-cpu=native -C target-feature=+avx512f" + else + export RUSTFLAGS="-C target-cpu=native" + fi export RUST_LOG=info # cargo clean cargo build --release --bin sorting - /usr/bin/time --verbose --output="${output}" -- cargo run --release -- --n=$N --prove - echo "RUSTFLAGS=\'${RUSTFLAGS:-}\'" - echo "N=\'${N}'" - cat "${output}" + /usr/bin/time --verbose --output="${output_time}" -- cargo run --release -- --n="${N}" --prove | tee "${output_log}" ) diff --git a/sorting/Cargo.lock b/sorting/Cargo.lock index 608ec4b6..e46318cb 100644 --- a/sorting/Cargo.lock +++ b/sorting/Cargo.lock @@ -4475,19 +4475,11 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "sorting-lib" -version = "0.1.0" -dependencies = [ - "alloy-sol-types", -] - [[package]] name = "sorting-program" version = "0.1.0" dependencies = [ - "alloy-sol-types", - "sorting-lib", + "rand", "sp1-zkvm", ] @@ -4495,12 +4487,10 @@ dependencies = [ name = "sorting-script" version = "0.1.0" dependencies = [ - "alloy-sol-types", "clap", "hex", "serde", "serde_json", - "sorting-lib", "sp1-helper", "sp1-sdk", "tracing", diff --git a/sorting/Cargo.toml b/sorting/Cargo.toml index d9a5e7ef..43355d45 100644 --- a/sorting/Cargo.toml +++ b/sorting/Cargo.toml @@ -1,10 +1,6 @@ [workspace] members = [ - "lib", "program", "script", ] resolver = "2" - -[workspace.dependencies] -alloy-sol-types = "0.7.7" diff --git a/sorting/lib/Cargo.toml b/sorting/lib/Cargo.toml deleted file mode 100644 index d62c00c7..00000000 --- a/sorting/lib/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "sorting-lib" -version = "0.1.0" -edition = "2021" - -[dependencies] -alloy-sol-types = { workspace = true } diff --git a/sorting/lib/src/lib.rs b/sorting/lib/src/lib.rs deleted file mode 100644 index 0d02f902..00000000 --- a/sorting/lib/src/lib.rs +++ /dev/null @@ -1,9 +0,0 @@ -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 median; - } -} diff --git a/sorting/program/Cargo.toml b/sorting/program/Cargo.toml index 5a3f1834..f0dc8ef7 100644 --- a/sorting/program/Cargo.toml +++ b/sorting/program/Cargo.toml @@ -4,6 +4,5 @@ name = "sorting-program" edition = "2021" [dependencies] -alloy-sol-types = { workspace = true } +rand = "0.8.5" sp1-zkvm = "3.0.0-rc4" -sorting-lib = { path = "../lib" } diff --git a/sorting/program/src/main.rs b/sorting/program/src/main.rs index 8d4f338e..b3d588fa 100644 --- a/sorting/program/src/main.rs +++ b/sorting/program/src/main.rs @@ -8,29 +8,13 @@ #![no_main] sp1_zkvm::entrypoint!(main); -use alloy_sol_types::SolType; -use sorting_lib::PublicValuesStruct; +use rand::Rng; 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 n_: usize = n.try_into().unwrap(); - // Sort a sequence of n pseudo-random numbers - let mut scratch: Vec = vec![1; n_]; - for i in 1..n_ { - scratch[i] = ((scratch[i - 1]) * 17 + 19) & ((1 << 20) - 1); - } - scratch.sort(); - - let median = scratch[n_ / 2]; + let n: usize = sp1_zkvm::io::read::().try_into().unwrap(); - // Encode the public values of the program. - let bytes = PublicValuesStruct::abi_encode(&PublicValuesStruct { n, median }); - - // 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); + // Provide some random numbers to sort. + let mut rng = rand::thread_rng(); + let mut scratch: Vec = (0..n).map(|_| rng.gen::()).collect::>(); + scratch.sort(); } diff --git a/sorting/rust-toolchain b/sorting/rust-toolchain.toml similarity index 100% rename from sorting/rust-toolchain rename to sorting/rust-toolchain.toml diff --git a/sorting/script/Cargo.toml b/sorting/script/Cargo.toml index bf1f1879..4450c2e0 100644 --- a/sorting/script/Cargo.toml +++ b/sorting/script/Cargo.toml @@ -8,10 +8,6 @@ default-run = "sorting" name = "sorting" path = "src/bin/main.rs" -[[bin]] -name = "evm" -path = "src/bin/evm.rs" - [dependencies] sp1-sdk = "3.0.0" serde_json = { version = "1.0", default-features = false, features = ["alloc"] } @@ -19,8 +15,6 @@ serde = { version = "1.0.200", 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 } -sorting-lib = { path = "../lib" } [build-dependencies] sp1-helper = "3.0.0" diff --git a/sorting/script/output_time b/sorting/script/output_time new file mode 100644 index 00000000..8b79c55b --- /dev/null +++ b/sorting/script/output_time @@ -0,0 +1,23 @@ + Command being timed: "cargo run --release -- --n=1024 --prove" + User time (seconds): 200.32 + System time (seconds): 4.19 + Percent of CPU this job got: 1904% + Elapsed (wall clock) time (h:mm:ss or m:ss): 0:10.73 + Average shared text size (kbytes): 0 + Average unshared data size (kbytes): 0 + Average stack size (kbytes): 0 + Average total size (kbytes): 0 + Maximum resident set size (kbytes): 4958420 + Average resident set size (kbytes): 0 + Major (requiring I/O) page faults: 0 + Minor (reclaiming a frame) page faults: 256198 + Voluntary context switches: 188637 + Involuntary context switches: 188596 + Swaps: 0 + File system inputs: 0 + File system outputs: 0 + Socket messages sent: 0 + Socket messages received: 0 + Signals delivered: 0 + Page size (bytes): 4096 + Exit status: 0 diff --git a/sorting/script/src/bin/evm.rs b/sorting/script/src/bin/evm.rs deleted file mode 100644 index 8fc17148..00000000 --- a/sorting/script/src/bin/evm.rs +++ /dev/null @@ -1,127 +0,0 @@ -//! 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 groth16 -//! ``` -//! or -//! ```shell -//! RUST_LOG=info cargo run --release --bin evm -- --system plonk -//! ``` - -use alloy_sol_types::SolType; -use clap::{Parser, ValueEnum}; -use serde::{Deserialize, Serialize}; -use sorting_lib::PublicValuesStruct; -use sp1_sdk::{ - include_elf, HashableKey, ProverClient, SP1ProofWithPublicValues, SP1Stdin, SP1VerifyingKey, -}; -use std::path::PathBuf; - -/// The ELF (executable and linkable format) file for the Succinct RISC-V zkVM. -pub const sorting_ELF: &[u8] = include_elf!("sorting-program"); - -/// 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 = "groth16")] - 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 SP1sortingProofFixture { - cnt_primes: 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(sorting_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, cnt_primes } = - PublicValuesStruct::abi_decode(bytes, false).unwrap(); - - // Create the testing fixture so we can test things end-to-end. - let fixture = SP1sortingProofFixture { - cnt_primes, - 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/sorting/script/src/bin/main.rs b/sorting/script/src/bin/main.rs index e282a7c1..554d5587 100644 --- a/sorting/script/src/bin/main.rs +++ b/sorting/script/src/bin/main.rs @@ -10,9 +10,7 @@ //! RUST_LOG=info cargo run --release -- --prove //! ``` -use alloy_sol_types::SolType; use clap::Parser; -use sorting_lib::PublicValuesStruct; use sp1_sdk::{include_elf, ProverClient, SP1Stdin}; /// The ELF (executable and linkable format) file for the Succinct RISC-V zkVM. @@ -58,12 +56,6 @@ fn main() { let (output, report) = client.execute(sorting_ELF, stdin).run().unwrap(); println!("Program executed successfully."); - // Read the output. - let decoded = PublicValuesStruct::abi_decode(output.as_slice(), true).unwrap(); - let PublicValuesStruct { n, median } = decoded; - println!("n: {}", n); - println!("median: {}", median); - // Record the number of cycles executed. println!("Number of cycles: {}", report.total_instruction_count()); } else {