diff --git a/hash/risc0/bench/README.md b/hash/risc0/bench/README.md index f1d1022..936cb1a 100644 --- a/hash/risc0/bench/README.md +++ b/hash/risc0/bench/README.md @@ -1,101 +1,12 @@ -# RISC Zero Rust Starter Template +Benchmarking different hashes inside risc'0 zkvm +----------------------------------------------- -Welcome to the RISC Zero Rust Starter Template! This template is intended to -give you a starting point for building a project using the RISC Zero zkVM. -Throughout the template (including in this README), you'll find comments -labelled `TODO` in places where you'll need to make changes. To better -understand the concepts behind this template, check out the [zkVM -Overview][zkvm-overview]. +The benchmark is defined by the following shell scripts: -## Quick Start +- `build.sh` - build the code. you can set the number of threads by setting the environment variable `CARGO_BUILD_JOBS` otherwise the code will build using default number of threads. -First, make sure [rustup] is installed. The -[`rust-toolchain.toml`][rust-toolchain] file will be used by `cargo` to -automatically install the correct version. +- `run.sh` and `run2.sh` - run the benchmark itself (`run.sh` for sha256, keccak, blake2b, blake3 and `run2.sh` for poseidon2 over bn128 and babybear) -To build all methods and execute the method within the zkVM, run the following -command: +Benchmarks can be parameterized using environment variables. By convention, we start the names of these environment variables with the `ZKBENCH_` prefix. -```bash -cargo run -``` - -This is an empty template, and so there is no expected output (until you modify -the code). - -### Running proofs remotely on Bonsai - -_Note: The Bonsai proving service is still in early Alpha; an API key is -required for access. [Click here to request access][bonsai access]._ - -If you have access to the URL and API key to Bonsai you can run your proofs -remotely. To prove in Bonsai mode, invoke `cargo run` with two additional -environment variables: - -```bash -BONSAI_API_KEY="YOUR_API_KEY" BONSAI_API_URL="BONSAI_URL" cargo run -``` - -## How to create a project based on this template - -Search this template for the string `TODO`, and make the necessary changes to -implement the required feature described by the `TODO` comment. Some of these -changes will be complex, and so we have a number of instructional resources to -assist you in learning how to write your own code for the RISC Zero zkVM: - -- The [RISC Zero Developer Docs][dev-docs] is a great place to get started. -- Example projects are available in the [examples folder][examples] of - [`risc0`][risc0-repo] repository. -- Reference documentation is available at [https://docs.rs][docs.rs], including - [`risc0-zkvm`][risc0-zkvm], [`cargo-risczero`][cargo-risczero], - [`risc0-build`][risc0-build], and [others][crates]. - -## Directory Structure - -It is possible to organize the files for these components in various ways. -However, in this starter template we use a standard directory structure for zkVM -applications, which we think is a good starting point for your applications. - -```text -project_name -├── Cargo.toml -├── host -│ ├── Cargo.toml -│ └── src -│ └── main.rs <-- [Host code goes here] -└── methods - ├── Cargo.toml - ├── build.rs - ├── guest - │ ├── Cargo.toml - │ └── src - │ └── bin - │ └── method_name.rs <-- [Guest code goes here] - └── src - └── lib.rs -``` - -## Video Tutorial - -For a walk-through of how to build with this template, check out this [excerpt -from our workshop at ZK HACK III][zkhack-iii]. - -## Questions, Feedback, and Collaborations - -We'd love to hear from you on [Discord][discord] or [Twitter][twitter]. - -[bonsai access]: https://bonsai.xyz/apply -[cargo-risczero]: https://docs.rs/cargo-risczero -[crates]: https://github.com/risc0/risc0/blob/main/README.md#rust-binaries -[dev-docs]: https://dev.risczero.com -[discord]: https://discord.gg/risczero -[docs.rs]: https://docs.rs/releases/search?query=risc0 -[examples]: https://github.com/risc0/risc0/tree/main/examples -[risc0-build]: https://docs.rs/risc0-build -[risc0-repo]: https://www.github.com/risc0/risc0 -[risc0-zkvm]: https://docs.rs/risc0-zkvm -[rustup]: https://rustup.rs -[rust-toolchain]: rust-toolchain.toml -[twitter]: https://twitter.com/risczero -[zkvm-overview]: https://dev.risczero.com/zkvm -[zkhack-iii]: https://www.youtube.com/watch?v=Yg_BGqj_6lg&list=PLcPzhUaCxlCgig7ofeARMPwQ8vbuD6hC5&index=5 +Additional files `bench.cfg` and `bench_tree.cfg` specifies the configurations and parameters. diff --git a/hash/risc0/bench/bench.cfg b/hash/risc0/bench/bench.cfg index 5e47ea2..a5a366f 100644 --- a/hash/risc0/bench/bench.cfg +++ b/hash/risc0/bench/bench.cfg @@ -1,12 +1,11 @@ name: "Hashes benchmarking using risc0 prover" author: -timeout: 100 +timeout: 200 params: - [ PROVER: [ risc0 ] - , INPUT_SIZE: [ 256, 512, 1024, 2048 ] - , WHICH: [ LINEAR ] + [ HASH_TYPE: [ "sha256", "keccak", "blake2b", "blake3"] + , INPUT_SIZE_BYTES: [ 256, 512, 1024, 2048 ] ] -tags: CPU, SHA256, KECCAK, BLAKE2B, BLAKE3, POSEIDON2, BN128, BABYBEAR +tags: risc0, $HASH_TYPE comments: - The benchmarks includes for sha256, keccak, blake2b, blake3 & poseidon2(merkle hashing). + The benchmarks includes for sha256, keccak, blake2b, blake3. the hashing is done inside the guest and receipt is received which is verified. diff --git a/hash/risc0/bench/bench_tree.cfg b/hash/risc0/bench/bench_tree.cfg new file mode 100644 index 0000000..529f0fb --- /dev/null +++ b/hash/risc0/bench/bench_tree.cfg @@ -0,0 +1,11 @@ +name: "Hashes benchmarking using risc0 prover" +author: +timeout: 1000 +params: + [ HASH_TYPE: [ "poseidon2_babybear", "poseidon2_babybear_native", "poseidon2_bn128"] + , TREE_DEPTH: [ 2, 4, 8, 16 ] + ] +tags: risc0, $HASH_TYPE +comments: + The benchmarks includes for poseidon2(merkle hashing) over bn128 and babybear. + the hashing is done inside the guest and receipt is received which is verified. diff --git a/hash/risc0/bench/build.sh b/hash/risc0/bench/build.sh index 26156ef..d1cf927 100755 --- a/hash/risc0/bench/build.sh +++ b/hash/risc0/bench/build.sh @@ -1,3 +1,7 @@ #!/bin/bash -cargo build --release +if [ -z ${ZKBENCH_NTHREADS} ]; then +ZKBENCH_NTHREADS="default" # https://doc.rust-lang.org/cargo/reference/config.html#buildjobs +fi + +CARGO_BUILD_JOBS=$ZKBENCH_NTHREADS cargo build --release diff --git a/hash/risc0/bench/methods/guest/src/bin/sha256.rs b/hash/risc0/bench/methods/guest/src/bin/sha256.rs index d67a766..d13074c 100644 --- a/hash/risc0/bench/methods/guest/src/bin/sha256.rs +++ b/hash/risc0/bench/methods/guest/src/bin/sha256.rs @@ -11,17 +11,3 @@ pub fn main() { env::commit(&hash) } -// accelerated sha2 crate -// #![no_main] - -// use risc0_zkvm::{guest::env}; -// use sha2::{Sha256, Digest}; -// // use base16ct::lower::encode_str; -// risc0_zkvm::guest::entry!(main); - -// pub fn main() { - -// let data: Vec = env::read(); -// let result: [u8;32] = Sha256::digest(data).into(); -// env::commit(&result) -// } diff --git a/hash/risc0/bench/run.sh b/hash/risc0/bench/run.sh index b3e6f11..79b7df8 100755 --- a/hash/risc0/bench/run.sh +++ b/hash/risc0/bench/run.sh @@ -3,35 +3,13 @@ if [ -z ${ZKBENCH_HASH_TYPE} ]; then ZKBENCH_HASH_TYPE="sha256" fi -if [ -z ${ZKBENCH_WHICH} ]; then -ZKBENCH_WHICH="LINEAR" +if [ -z ${ZKBENCH_INPUT_SIZE_BYTES} ]; then +ZKBENCH_INPUT_SIZE_BYTES=1024 fi -if [ -z ${ZKBENCH_NTHREADS} ]; then -ZKBENCH_NTHREADS=1 -fi - -if [ -z ${ZKBENCH_INPUT_SIZE_KB} ]; then -ZKBENCH_INPUT_SIZE_KB=1024 -fi - -if [ -z ${ZKBENCH_TREE_DEPTH} ]; then -ZKBENCH_TREE_DEPTH=4 -fi - - echo "Running benchmarks with the following configurations:" echo "HASH = $ZKBENCH_HASH_TYPE" -# echo "WHICH = $ZKBENCH_WHICH" -echo "NTHREADS = $ZKBENCH_NTHREADS" -echo "Input Size (KB) = $ZKBENCH_INPUT_SIZE_KB" +echo "Input Size (Bytes) = $ZKBENCH_INPUT_SIZE_BYTES" -# Run the benchmarks using cargo run -# Check if the environment variable is set to "poseidon2_bn128" -if [[ "$ZKBENCH_HASH_TYPE" == "poseidon2_bn128" || "$ZKBENCH_HASH_TYPE" == "poseidon2_babybear" || "$ZKBENCH_HASH_TYPE" == "poseidon2_babybear_native" ]]; then - # echo "Running Poseidon2 benchmark over bn128 field" - CARGO_BUILD_JOBS=$ZKBENCH_NTHREADS cargo run $ZKBENCH_HASH_TYPE $ZKBENCH_TREE_DEPTH -else - CARGO_BUILD_JOBS=$ZKBENCH_NTHREADS cargo run $ZKBENCH_HASH_TYPE $ZKBENCH_INPUT_SIZE_KB - -fi \ No newline at end of file +# Run the benchmarks +./target/release/benchmark $ZKBENCH_HASH_TYPE $ZKBENCH_INPUT_SIZE_BYTES \ No newline at end of file diff --git a/hash/risc0/bench/run_tree.sh b/hash/risc0/bench/run_tree.sh new file mode 100755 index 0000000..cdd865e --- /dev/null +++ b/hash/risc0/bench/run_tree.sh @@ -0,0 +1,15 @@ +#!/bin/bash +if [ -z ${ZKBENCH_HASH_TYPE} ]; then +ZKBENCH_HASH_TYPE="poseidon2_babybear_native" +fi + +if [ -z ${ZKBENCH_TREE_DEPTH} ]; then +ZKBENCH_TREE_DEPTH=2 +fi + +echo "Running benchmarks with the following configurations:" +echo "HASH = $ZKBENCH_HASH_TYPE" +echo "Tree Depth = $ZKBENCH_TREE_DEPTH" + +# Run the benchmarks +./target/release/benchmark $ZKBENCH_HASH_TYPE $ZKBENCH_TREE_DEPTH \ No newline at end of file diff --git a/hash/risc0/bench/src/benches/poseidon2_babybear.rs b/hash/risc0/bench/src/benches/poseidon2_babybear.rs index 73cf58b..b3ae1f1 100644 --- a/hash/risc0/bench/src/benches/poseidon2_babybear.rs +++ b/hash/risc0/bench/src/benches/poseidon2_babybear.rs @@ -42,6 +42,11 @@ pub fn poseidon2_babybear_bench(mt_depth: usize) { let receipt = prover.prove_elf(env, POSEIDON2_BABYBEAR_ELF).unwrap(); let elapsed_time = start_time.elapsed(); + // verify your receipt + receipt.verify(POSEIDON2_BABYBEAR_ID).unwrap(); + + let elapsed_time2 = start_time.elapsed(); + // For example: let output: Vec> = receipt.journal.decode().unwrap(); @@ -52,12 +57,9 @@ pub fn poseidon2_babybear_bench(mt_depth: usize) { } eprintln!("hash: {:?}", output_deseralised); + eprintln!("Total time: {:?}", elapsed_time2); + eprintln!("Verification time: {:?}", elapsed_time2 - elapsed_time); - // verify your receipt - receipt.verify(POSEIDON2_BABYBEAR_ID).unwrap(); - - - eprintln!("Total time: {:?}", elapsed_time); // eprintln!("Hash: {:?}", hash_final); diff --git a/hash/risc0/bench/src/benches/poseidon2_babybear_native.rs b/hash/risc0/bench/src/benches/poseidon2_babybear_native.rs index d1c7a61..9b92da3 100644 --- a/hash/risc0/bench/src/benches/poseidon2_babybear_native.rs +++ b/hash/risc0/bench/src/benches/poseidon2_babybear_native.rs @@ -8,7 +8,6 @@ use risc0_zkvm::{ ExecutorEnv }; use std::time::Instant; -// use risc0_core::field::baby_bear::BabyBearElem; use rand::Rng; pub fn poseidon2_babybear_native_bench(mt_depth: usize) { @@ -33,24 +32,16 @@ pub fn poseidon2_babybear_native_bench(mt_depth: usize) { let receipt = prover.prove_elf(env, POSEIDON2_BABYBEAR_NATIVE_ELF).unwrap(); let elapsed_time = start_time.elapsed(); - // For example: - let output: Vec = receipt.journal.decode().unwrap(); - - // let mut output_deseralised: Vec = Vec::new(); - - // for i in 0..output.len() { - // output_deseralised.push(Scalar::deserialize_uncompressed(&**output.get(i).unwrap()).unwrap()); - // } - - eprintln!("hash: {:?}", output); - // let hash_final = FpBabyBear::deserialize_uncompressed(&*output).unwrap(); - // verify your receipt receipt.verify(POSEIDON2_BABYBEAR_NATIVE_ID).unwrap(); - - eprintln!("Total time: {:?}", elapsed_time); - // eprintln!("Hash: {:?}", hash_final); + let elapsed_time2 = start_time.elapsed(); + let output: Vec = receipt.journal.decode().unwrap(); + + eprintln!("hash: {:?}", output); + + eprintln!("Total time: {:?}", elapsed_time2); + eprintln!("Verification time: {:?}", elapsed_time2 - elapsed_time); } \ No newline at end of file diff --git a/hash/risc0/bench/src/benches/poseidon2_bn128.rs b/hash/risc0/bench/src/benches/poseidon2_bn128.rs index 9583eec..8bb4b25 100644 --- a/hash/risc0/bench/src/benches/poseidon2_bn128.rs +++ b/hash/risc0/bench/src/benches/poseidon2_bn128.rs @@ -30,16 +30,19 @@ pub fn poseidon2_bn128_bench(mt_depth: usize) { let receipt = prover.prove_elf(env, POSEIDON2_BN128_ELF).unwrap(); let elapsed_time = start_time.elapsed(); + + // verify your receipt + receipt.verify(POSEIDON2_BN128_ID).unwrap(); + + let elapsed_time2 = start_time.elapsed(); + // For example: let output: Vec = receipt.journal.decode().unwrap(); let hash_final = Scalar::deserialize_uncompressed(&*output).unwrap(); - // verify your receipt - receipt.verify(POSEIDON2_BN128_ID).unwrap(); - - - eprintln!("Total time: {:?}", elapsed_time); eprintln!("Hash: {:?}", hash_final); + eprintln!("Total time: {:?}", elapsed_time2); + eprintln!("Verification time: {:?}", elapsed_time2 - elapsed_time); } \ No newline at end of file diff --git a/hash/risc0/bench/src/benches/sha256.rs b/hash/risc0/bench/src/benches/sha256.rs index 46a0489..44527ea 100644 --- a/hash/risc0/bench/src/benches/sha256.rs +++ b/hash/risc0/bench/src/benches/sha256.rs @@ -3,34 +3,35 @@ use methods::{ }; use risc0_zkvm::{default_prover, ExecutorEnv}; use risc0_zkvm::{ sha}; -// use sha2; -// use rand::RngCore; use std::time::Instant; - +use hex::encode; pub fn sha_bench(input: Vec) { - let env = ExecutorEnv::builder().write(&input).unwrap().build().unwrap(); // Obtain the default prover. let prover = default_prover(); - eprintln!("------risc0_zkvm sha hashing------"); + eprintln!("\n------risc0_zkvm sha hashing------\n"); + let start_time = Instant::now(); // Produce a receipt by proving the specified ELF binary. let receipt = prover.prove_elf(env, SHA256_ELF).unwrap(); let elapsed_time = start_time.elapsed(); - // For example: - let _output: sha::Digest = receipt.journal.decode().unwrap(); - // verify your receipt receipt.verify(SHA256_ID).unwrap(); - eprintln!("Total time: {:?}", elapsed_time); + let elapsed_time2 = start_time.elapsed(); + + let _output: sha::Digest = receipt.journal.decode().unwrap(); + + eprintln!("Total time: {:?}", elapsed_time2); + eprintln!("Verification time: {:?}", elapsed_time2 - elapsed_time); + eprintln!("Hash: {:?}", _output); let env = ExecutorEnv::builder().write(&input).unwrap().build().unwrap(); - eprintln!("------RustCrypto sha hashing------"); + eprintln!("\n------RustCrypto sha hashing(accelerated)------\n"); // Obtain the default prover. let prover = default_prover(); @@ -39,12 +40,15 @@ pub fn sha_bench(input: Vec) { let receipt = prover.prove_elf(env, SHA256_ACCELERATED_ELF).unwrap(); let elapsed_time = start_time.elapsed(); - // For example: - let _output: [u8;32] = receipt.journal.decode().unwrap(); - // verify your receipt receipt.verify(SHA256_ACCELERATED_ID).unwrap(); - eprintln!("Total time: {:?}", elapsed_time); - eprintln!("Hash: {:?}", _output); + let elapsed_time2 = start_time.elapsed(); + + let _output: [u8;32] = receipt.journal.decode().unwrap(); + let hash = encode(_output); + eprintln!("Total time: {:?}", elapsed_time2); + eprintln!("Verification time: {:?}", elapsed_time2 - elapsed_time); + + eprintln!("Hash: {:?}", hash); } \ No newline at end of file diff --git a/hash/risc0/bench/src/main.rs b/hash/risc0/bench/src/main.rs index 801e862..bee3f3a 100644 --- a/hash/risc0/bench/src/main.rs +++ b/hash/risc0/bench/src/main.rs @@ -9,6 +9,7 @@ use benches::{ poseidon2_babybear_native::poseidon2_babybear_native_bench, }; use rand::Rng; +use std::process; fn generate_bytes(size: usize) -> Vec { let mut rng = rand::thread_rng(); @@ -19,56 +20,62 @@ fn generate_bytes(size: usize) -> Vec { fn main() { let args: Vec = std::env::args().collect(); + + if args.len() != 3 { + println!("Wrong number of arguments"); + // Exit the program with a non-zero exit code + process::exit(1); + } let hash_type = &args[1]; - let size_kb = args[2].parse::().unwrap(); + let size = args[2].parse::().unwrap(); match hash_type.as_str() { "sha256" => { println!("SHA256 Benchmarking: "); - eprintln!("data size(bytes): {:?}", size_kb); - let input = generate_bytes(size_kb); + eprintln!("data size(bytes): {:?}", size); + let input = generate_bytes(size); sha_bench(input.clone()); } "keccak" => { println!("KECCAK Benchmarking: "); - eprintln!("data size(bytes): {:?}", size_kb); - let input = generate_bytes(size_kb); + eprintln!("data size(bytes): {:?}", size); + let input = generate_bytes(size); keccak_bench(input.clone()); } "blake2b" => { println!("Blake2b Benchmarking: "); - eprintln!("data size(bytes): {:?}", size_kb); - let input = generate_bytes(size_kb); + eprintln!("data size(bytes): {:?}", size); + let input = generate_bytes(size); blake2b_bench(input.clone()); } "blake3" => { println!("Blake3 Benchmarking: "); - eprintln!("data size(bytes): {:?}", size_kb); - let input = generate_bytes(size_kb); + eprintln!("data size(bytes): {:?}", size); + let input = generate_bytes(size); blake3_bench(input.clone()); } "poseidon2_bn128" => { println!("Poseidon2 Benchmarking on the BN128 field: "); - eprintln!("Tree Depth: {:?}", size_kb); - poseidon2_bn128_bench(size_kb); + eprintln!("Tree Depth: {:?}", size); + poseidon2_bn128_bench(size); } "poseidon2_babybear" => { println!("Poseidon2 Benchmarking on the BabyBear field: "); - eprintln!("Tree Depth: {:?}", size_kb); - eprintln!("number of inputs {:?}", (1 << size_kb) * 8); - poseidon2_babybear_bench(size_kb); + eprintln!("Tree Depth: {:?}", size); + eprintln!("number of inputs {:?}", (1 << size) * 8); + poseidon2_babybear_bench(size); } "poseidon2_babybear_native" => { println!("Poseidon2 Benchmarking on the BabyBear field: "); - eprintln!("Tree Depth: {:?}", size_kb); - eprintln!("number of inputs {:?}", (1 << size_kb) * 8); - poseidon2_babybear_native_bench(size_kb); + eprintln!("Tree Depth: {:?}", size); + eprintln!("number of inputs {:?}", (1 << size) * 8); + poseidon2_babybear_native_bench(size); } _ => {