Add benchmark scripts and refactor.

This commit is contained in:
M Alghazwi 2025-03-10 14:49:13 +01:00
parent 30b7a6ae03
commit 0a5bb1b52e
No known key found for this signature in database
GPG Key ID: 646E567CAD7DB607
22 changed files with 234 additions and 163 deletions

View File

@ -6,7 +6,7 @@ resolver = "2"
[workspace.dependencies] [workspace.dependencies]
anyhow = { version = "1.0.89"} anyhow = { version = "1.0.89"}
unroll = { version = "0.1.5"} unroll = { version = "0.1.5"}
plonky2 = { version = "1.0.0" } plonky2 = { version = "1.0.0" , default-features = false}
plonky2_field = { version = "1.0.0" } plonky2_field = { version = "1.0.0" }
plonky2_maybe_rayon = { version = "1.0.0"} plonky2_maybe_rayon = { version = "1.0.0"}
itertools = { version = "0.12.1"} itertools = { version = "0.12.1"}

View File

@ -4,63 +4,30 @@ In here we show the preliminary benchmarks of codex storage proofs circuits.
## Running Benchmarks ## Running Benchmarks
To run the benchmarks for safe merkle tree circuit, you can use the following command: **Runtime Benchmarks**
To run the benchmarks for sampling circuit and aggregation, you can use the following commands:
```bash ```bash
cargo bench --bench safe_circuit cd bench_scripts
bash ./bench_runtime
``` ```
To run the benchmarks for sampling circuit, you can use the following command: The following operations were benchmarked for sampling and recursion circuits (both single-thread and multi-thread):
Note: make sure to adjust the parameters as need in ....
```bash
cargo bench --bench sample_cells
```
The following operations were benchmarked:
- **Build Circuit**: Time taken to construct the circuit for the specified params. - **Build Circuit**: Time taken to construct the circuit for the specified params.
- **Prove Circuit**: Time taken to generate a proof for the constructed circuit. - **Prove Circuit**: Time taken to generate a proof for the constructed circuit.
- **Verify Circuit**: Time taken to verify the generated proof. - **Verify Circuit**: Time taken to verify the generated proof.
## Bench Results **Memory Benchmarks**
The following is the result of running the codex storage proof circuit (sample_cells). To run the memory benchmarks for sampling circuit and aggregation, you can use the following commands:
The bench uses the Goldilocks field and Poseidon2 Hash. All results were run on Mac Mini with M2 Pro and 16GB RAM.
### Bench params
The benchmark runs with the default params which are the following:
```bash ```bash
export MAXDEPTH=32 # Maximum depth of the slot tree cd bench_scripts
export MAXSLOTS=256 # Maximum number of slots bash ./bench_memory
export CELLSIZE=2048 # Cell size in bytes
export BLOCKSIZE=65536 # Block size in bytes
export NSAMPLES=5 # Number of samples to prove
export ENTROPY=1234567 # External randomness
export SEED=12345 # Seed for creating fake data
export NSLOTS=11 # Number of slots in the dataset
export SLOTINDEX=3 # Which slot to prove (0..NSLOTS-1)
export NCELLS=512 # Number of cells in this slot
``` ```
Note: The memory usage is quite difficult to replicate as it depends on the operating system,
but on macOS look for the "maximum resident set size" to get the peak memory usage.
### Build Time ## Bench Results
Build time for plonky2 circuits is 39.644 ms. See this [document](https://hackmd.io/@NQdG6IOmQE6astjwhJ6ACw/Bk-SopNj1g) for full benchmark results.
Baseline Groth16 with same params: 61 seconds for the circuit specific setup.
### Prove Time
Prove time for plonky2 circuits is 53.940 ms.
Baseline Groth16 with same params: 4.56 seconds using snarkjs
improvement: approx 80x
### Verify Time
To be done once recursion is added to the codebase.
### Proof Size
Plonky Proof size: 116008 bytes
This is without recursion or Groth16 wrapper.
### Peak Memory Usage
To be done.

View File

@ -22,6 +22,10 @@ proof-input = { path = "../proof-input" }
criterion = { version = "0.5.1", default-features = false } criterion = { version = "0.5.1", default-features = false }
tynm = { version = "0.1.6", default-features = false } tynm = { version = "0.1.6", default-features = false }
[features]
default = []
parallel = ["plonky2/parallel"]
[[bin]] [[bin]]
name = "prove_and_verify" name = "prove_and_verify"
path = "src/bin/prove_and_verify.rs" path = "src/bin/prove_and_verify.rs"
@ -38,6 +42,10 @@ path = "src/bin/build_circ.rs"
name = "prove" name = "prove"
path = "src/bin/prove.rs" path = "src/bin/prove.rs"
[[bin]]
name = "aggregate"
path = "src/bin/aggregate.rs"
[[bench]] [[bench]]
name = "merkle_circuit" name = "merkle_circuit"
harness = false harness = false
@ -48,4 +56,8 @@ harness = false
[[bench]] [[bench]]
name = "uniform_recursion" name = "uniform_recursion"
harness = false
[[bench]]
name = "compression"
harness = false harness = false

View File

@ -22,6 +22,7 @@ This crate can be used to:
- [`prove_and_verify`](./src/bin/prove_and_verify.rs) contains the main function to generated input with the given params as environment variables. - [`prove_and_verify`](./src/bin/prove_and_verify.rs) contains the main function to generated input with the given params as environment variables.
- [`aggregate`](./src/bin/aggregate.rs) contains the main function to generate the sampling proofs and aggregate `k` of them.
## Usage ## Usage
@ -45,7 +46,7 @@ rustup override set nightly
The steps to generate circuit input with **fake data** are the following: The steps to generate circuit input with **fake data** are the following:
#### Step 1: Setting Up Parameters #### Step 1: Setting Up Parameters
Parameters for generating the circuit input can be defined in [`params.sh`](./params.sh). Parameters for generating the circuit input can be defined in [`params.sh`](scripts/params.sh).
You can customize the test parameters by setting the following environment variables: You can customize the test parameters by setting the following environment variables:
```bash ```bash
@ -75,13 +76,13 @@ fn main() {
Once the params are set, you can run the script to generate the [`JSON file`](./input.json). Once the params are set, you can run the script to generate the [`JSON file`](./input.json).
```bash ```bash
sudo bash ./gen_input.sh sudo bash ./scripts/gen_input.sh
``` ```
### Build the Circuit ### Build the Circuit
To build the circuit and measure the time to build, you can simply run the script: To build the circuit and measure the time to build, you can simply run the script:
```bash ```bash
sudo bash ./build_circuit.sh sudo bash ./scripts/build_circuit.sh
``` ```
To see the source code of how to build the circuit, see [`build_circ`](./src/bin/build_circ.rs). To see the source code of how to build the circuit, see [`build_circ`](./src/bin/build_circ.rs).
@ -91,7 +92,7 @@ you can run the circuits to generate the proofs.
First make sure you have the [`JSON file`](./input.json), then follow the steps: First make sure you have the [`JSON file`](./input.json), then follow the steps:
#### Step 1: Setting Up Circuit Parameters #### Step 1: Setting Up Circuit Parameters
Parameters for the circuit can be defined in [`circ_params.sh`](./circ_params.sh). Parameters for the circuit can be defined in [`circ_params.sh`](scripts/circ_params.sh).
You can customize the test parameters by setting the following environment variables: You can customize the test parameters by setting the following environment variables:
```bash ```bash
export MAX_DEPTH=32 # maximum depth of the slot tree export MAX_DEPTH=32 # maximum depth of the slot tree
@ -106,16 +107,31 @@ Once the params are set, you can run the script to generate the proof.
You can also see the time taken to generate the proof. You can also see the time taken to generate the proof.
```bash ```bash
sudo bash ./prove.sh sudo bash ./scripts/prove.sh
``` ```
### Build, Prove, and Verify ### Build, Prove, and Verify
To automate the whole process, you can run the following script To automate the whole process, you can run the following script
the script builds the circuit, loads the JSON circuit input, generates the proof, and verifies it. the script builds the circuit, loads the JSON circuit input, generates the proof, and verifies it.
It also shows the time taken for each step. It also shows the time taken for each step.
Make sure that you generate the circuit input prior to this so that you have the [`JSON input file`](./input.json) and set the [`circ_params.sh`](./circ_params.sh). Make sure that you generate the circuit input prior to this so that you have the [`JSON input file`](./input.json) and set the [`circ_params.sh`](scripts/circ_params.sh).
```bash ```bash
sudo bash ./prove_and_verify.sh sudo bash ./scripts/prove_and_verify.sh
``` ```
To inspect the source code, see [`prove_and_verify`](./src/bin/prove_and_verify.rs). To inspect the source code, see [`prove_and_verify`](./src/bin/prove_and_verify.rs).
### Generate K Proofs and aggregate them
To do this, you can run the following script:
```bash
sudo bash ./scripts/aggregate.sh
```
or the following if you want to specify the number of proofs to be aggregated
```bash
sudo bash ./scripts/aggregate.sh -- "$K_VALUE"
```

View File

@ -1,77 +0,0 @@
## Benchmarks
In here we show the benchmarks results when using Plonky2 recursion for the codex storage proofs.
## Running Benchmarks
To run the benchmarks, you can use the following command with `x` replaced with the benchmark name (for the list of all benchmarks, see [benches](./benches)):
```bash
cargo bench --bench x
```
## Benchmark Results:
We implemented and experimented with various recursion approaches:
- Simple Recursion
- Simple Tree Recursion
- Cyclic Recursion
- Tree Recursion (Approach1)
- Tree Recursion (Approach2)
- Hybrid Recursion (Simple + Tree)
For more details on each of these approaches see this [writeup](https://hackmd.io/@NQdG6IOmQE6astjwhJ6ACw/rk85D2HX1e)
Here we show the benchmark results of running Hybrid recursion approaches and compare it to simple recursion.
Based on our experimentation, the hybrid approach gives the best results, compared to others.
The Params for the hybrid approach must be adjusted based on the number of proofs to be aggregated to give optimal results.
There are various parameters to consider before benchmarking.
First the circuit and test parameters we used are the following:
```bash
export MAXDEPTH=32 # Maximum depth of the slot tree
export MAXSLOTS=256 # Maximum number of slots
export CELLSIZE=2048 # Cell size in bytes
export BLOCKSIZE=65536 # Block size in bytes
export NSAMPLES=100 # Number of samples to prove
export ENTROPY=1234567 # External randomness
export SEED=12345 # Seed for creating fake data
export NSLOTS=11 # Number of slots in the dataset
export SLOTINDEX=3 # Which slot to prove (0..NSLOTS-1)
export NCELLS=512 # Number of cells in this slot
```
As can be seen above we set the number of samples (`NSAMPLES=100`) which should be sufficient.
Additionally, we vary the number of proofs to be aggregated (`P = {4,8,16,32,64,128}`).
There are also the `N` and `M` parameters for the tree-structure recursion.
These params mean different things for each approach (refer to [writeup](https://hackmd.io/@NQdG6IOmQE6astjwhJ6ACw/rk85D2HX1e))
In the Hybrid approach, these values are
- `M`: Number of proof aggregated in the leaf
- `N`: Number of proofs aggregated in the nodes of the tree
**Build Circuit**
| **P** | ** Recursion Build time (s)** |
|---------|-------------------------------|
| **4** | 0.967 |
| **8** | 1.613 |
| **16** | 2.977 |
| **32** | 5.847 |
| **64** | 12.533 |
| **128** | 26.930 |
**Prove Circuit**
| **P** | **Simple Recursion (s)** | **Hybrid Recursion (s)** |
|-------|--------------------------|--------------------------|
| **4** | 0.769 | 0.612 |
| **8** | 1.549 | 1.227 |
| **16** | 3.212 | 2.691 |
| **32** | 6.574 | 6.225 |
| **64** | 15.107 | 14.654 |
| **128** | 34.617 | 29.189 |

View File

@ -0,0 +1,25 @@
#!/bin/bash
# Source parameters
source "params.sh"
# Move to the project root
cd "$(dirname "$0")/.." || { echo "Failed to change directory"; exit 1; }
# Build silently
cargo build --release > /dev/null 2>&1 || { echo "cargo build failed"; exit 101; }
# 1) sampling circuit - build
echo "Running sampling circuit - build..."
/usr/bin/time -l bash -c 'cargo run --bin build_circ --features "parallel" >/dev/null 2>/dev/null'
# 2) sampling circuit - prove
echo "Running sampling circuit - prove..."
cargo run --bin gen_input >/dev/null 2>/dev/null || { echo "gen_input.sh: cargo run failed"; exit 102; }
/usr/bin/time -l bash -c 'cargo run --bin prove --features "parallel" >/dev/null 2>/dev/null'
# 3) sampling circuit - aggregate
K_VALUE=${1:-128}
echo "Running sampling circuit - aggregate (${K_VALUE} proofs)..."
/usr/bin/time -l bash -c "cargo run --bin aggregate --features 'parallel' -- '${K_VALUE}' >/dev/null 2>/dev/null"

View File

@ -0,0 +1,16 @@
#!/bin/bash
# Change to the parent directory of the script
cd "$(dirname "$0")/.." || { echo "Failed to change directory"; exit 1; }
echo "Running bench for the sampling circuit with multithreading..."
cargo bench --bench sample_cells --features "parallel" || { echo "Benchmark 'sample_cells' with multithreading failed"; exit 101; }
echo "Running bench for the sampling circuit with single-thread..."
cargo bench --bench sample_cells || { echo "Benchmark 'sample_cells' with single-thread failed"; exit 102; }
echo "Running bench for the tree recursion circuit with multithreading..."
cargo bench --bench uniform_recursion --features "parallel" || { echo "Benchmark 'uniform_recursion' with multithreading failed"; exit 103; }
echo "Running bench for the tree recursion circuit with single-thread..."
cargo bench --bench uniform_recursion || { echo "Benchmark 'uniform_recursion' with single-thread failed"; exit 104; }

View File

@ -0,0 +1,7 @@
#!/bin/bash
export MAX_DEPTH=32 # maximum depth of the slot tree
export MAX_LOG2_N_SLOTS=8 # Depth of the dataset tree = ceiling_log2(max_slots)
export BLOCK_TREE_DEPTH=5 # depth of the mini tree (block tree)
export N_FIELD_ELEMS_PER_CELL=272 # number of field elements per cell
export N_SAMPLES=100 # number of samples to prove

View File

@ -4,7 +4,7 @@ export MAXDEPTH=32 # maximum depth of the slot tree
export MAXSLOTS=256 # maximum number of slots export MAXSLOTS=256 # maximum number of slots
export CELLSIZE=2048 # cell size in bytes export CELLSIZE=2048 # cell size in bytes
export BLOCKSIZE=65536 # block size in bytes export BLOCKSIZE=65536 # block size in bytes
export NSAMPLES=5 # number of samples to prove export NSAMPLES=100 # number of samples to prove
export ENTROPY=1234567 # external randomness export ENTROPY=1234567 # external randomness
export SEED=12345 # seed for creating fake data export SEED=12345 # seed for creating fake data

View File

@ -2,7 +2,6 @@ use criterion::{criterion_group, criterion_main, Criterion};
use anyhow::Result; use anyhow::Result;
use proof_input::merkle_tree::merkle_safe::{MerkleTree}; use proof_input::merkle_tree::merkle_safe::{MerkleTree};
// use codex_plonky2_circuits::{circuits::merkle_circuit::MerkleTreeCircuit};
use plonky2::field::types::Field; use plonky2::field::types::Field;
use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData}; use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData};
use plonky2::plonk::config::{AlgebraicHasher, GenericConfig, Hasher, PoseidonGoldilocksConfig}; use plonky2::plonk::config::{AlgebraicHasher, GenericConfig, Hasher, PoseidonGoldilocksConfig};
@ -13,8 +12,6 @@ use plonky2::field::extension::Extendable;
use plonky2::hash::hash_types::RichField; use plonky2::hash::hash_types::RichField;
use plonky2_poseidon2::poseidon2_hash::poseidon2::{Poseidon2, Poseidon2Hash}; use plonky2_poseidon2::poseidon2_hash::poseidon2::{Poseidon2, Poseidon2Hash};
use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::circuit_builder::CircuitBuilder;
// use codex_plonky2_circuits::merkle_tree::merkle_safe::MerkleProof;
// use plonky2_field::goldilocks_field::GoldilocksField;
use proof_input::merkle_tree::merkle_circuit; use proof_input::merkle_tree::merkle_circuit;
use proof_input::merkle_tree::merkle_circuit::{assign_witness, MerkleTreeCircuitInput}; use proof_input::merkle_tree::merkle_circuit::{assign_witness, MerkleTreeCircuitInput};
use proof_input::utils::usize_to_bits_le; use proof_input::utils::usize_to_bits_le;

View File

@ -1,5 +1,5 @@
use anyhow::Result; use anyhow::Result;
use criterion::{criterion_group, criterion_main, Criterion}; use criterion::{criterion_group, criterion_main, BatchSize, Criterion};
use plonky2::iop::witness::PartialWitness; use plonky2::iop::witness::PartialWitness;
use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2::plonk::circuit_data::CircuitConfig; use plonky2::plonk::circuit_data::CircuitConfig;
@ -10,9 +10,9 @@ use proof_input::gen_input::gen_testing_circuit_input;
use proof_input::params::{D, C, F, HF, Params}; use proof_input::params::{D, C, F, HF, Params};
/// Benchmark for building, proving, and verifying the Plonky2 circuit. /// Benchmark for building, proving, and verifying the Plonky2 circuit.
fn bench_prove_verify(c: &mut Criterion) -> Result<()>{ fn bench_prove_verify<const N: usize>(c: &mut Criterion) -> Result<()>{
let n_samples = 100; let n_samples = N;
// get default parameters // get default parameters
let params = Params::default(); let params = Params::default();
let mut test_params = params.input_params; let mut test_params = params.input_params;
@ -21,6 +21,9 @@ fn bench_prove_verify(c: &mut Criterion) -> Result<()>{
let mut circuit_params = params.circuit_params; let mut circuit_params = params.circuit_params;
circuit_params.n_samples = n_samples; circuit_params.n_samples = n_samples;
#[cfg(feature = "parallel")]
println!("Parallel feature is ENABLED");
// gen the circuit input // gen the circuit input
let circ_input = gen_testing_circuit_input::<F,D>(&test_params); let circ_input = gen_testing_circuit_input::<F,D>(&test_params);
@ -37,7 +40,7 @@ fn bench_prove_verify(c: &mut Criterion) -> Result<()>{
circ.sample_slot_assign_witness(&mut pw, &targets, &circ_input.clone()); circ.sample_slot_assign_witness(&mut pw, &targets, &circ_input.clone());
// Benchmark Group: Separate benchmarks for building, proving, and verifying // Benchmark Group: Separate benchmarks for building, proving, and verifying
let mut group = c.benchmark_group("Sampling Circuit Benchmark"); let mut group = c.benchmark_group(format!("Sampling Circuit Benchmark for N= {}", N));
// Benchmark the Circuit Building Phase // Benchmark the Circuit Building Phase
group.bench_function("Build Circuit", |b| { group.bench_function("Build Circuit", |b| {
@ -45,9 +48,6 @@ fn bench_prove_verify(c: &mut Criterion) -> Result<()>{
let config = CircuitConfig::standard_recursion_config(); let config = CircuitConfig::standard_recursion_config();
let mut local_builder = CircuitBuilder::<F, D>::new(config); let mut local_builder = CircuitBuilder::<F, D>::new(config);
let _targets = circ.sample_slot_circuit_with_public_input(&mut local_builder); let _targets = circ.sample_slot_circuit_with_public_input(&mut local_builder);
// let local_targets = targets.clone();
// let mut local_pw = pw.clone();
// circ.sample_slot_assign_witness(&mut local_pw, &local_targets, &circ_input.clone());
let _data = local_builder.build::<C>(); let _data = local_builder.build::<C>();
}) })
}); });
@ -68,12 +68,12 @@ fn bench_prove_verify(c: &mut Criterion) -> Result<()>{
// println!("Number of constraints: {}", num_constr); // println!("Number of constraints: {}", num_constr);
// println!("Number of gates used: {}", data.common.gates.len()); // println!("Number of gates used: {}", data.common.gates.len());
// Benchmark the Proving Phase
group.bench_function("Prove Circuit", |b| { group.bench_function("Prove Circuit", |b| {
b.iter(|| { b.iter_batched(
let local_pw = pw.clone(); || pw.clone(),
data.prove(local_pw).expect("Failed to prove circuit") |local_pw| data.prove(local_pw).expect("Failed to prove circuit"),
}) BatchSize::SmallInput,
)
}); });
// Generate the proof once for verification benchmarking // Generate the proof once for verification benchmarking
@ -96,10 +96,17 @@ fn bench_prove_verify(c: &mut Criterion) -> Result<()>{
Ok(()) Ok(())
} }
fn bench_sampling(c: &mut Criterion) -> Result<()>{
bench_prove_verify::<10>(c)?;
bench_prove_verify::<50>(c)?;
bench_prove_verify::<100>(c)?;
Ok(())
}
/// Criterion benchmark group /// Criterion benchmark group
criterion_group!{ criterion_group!{
name = prove_verify_benches; name = benches;
config = Criterion::default().sample_size(10); config = Criterion::default().sample_size(10);
targets = bench_prove_verify targets = bench_sampling
} }
criterion_main!(prove_verify_benches); criterion_main!(benches);

View File

@ -31,7 +31,7 @@ fn bench_uniform_recursion<const K: usize,const N: usize,const M: usize,>(c: &mu
let inner_data = sampling_builder.build::<C>(); let inner_data = sampling_builder.build::<C>();
let inner_proof = inner_data.prove(pw.clone())?; let inner_proof = inner_data.prove(pw.clone())?;
let proofs: Vec<ProofWithPublicInputs<F, C, D>> = (0..N).map(|i| inner_proof.clone()).collect(); let proofs: Vec<ProofWithPublicInputs<F, C, D>> = (0..K).map(|i| inner_proof.clone()).collect();
// ------------------- tree -------------------- // ------------------- tree --------------------

View File

@ -1,10 +0,0 @@
#!/bin/bash
# Source the parameters from params.sh
source ./params.sh
# Build
cargo build --release || { echo "build_circuit.sh: cargo build failed"; exit 101; }
# Run the Rust executable
cargo run --bin build_circ || { echo "build_circuit.sh: cargo run failed"; exit 102; }

View File

@ -0,0 +1,14 @@
#!/bin/bash
# Source the parameters from the scripts directory
source "params.sh"
# Change to the parent directory of the script
cd "$(dirname "$0")/.." || { echo "Failed to change directory"; exit 1; }
# Build
cargo build --release || { echo "prove.sh: cargo build failed"; exit 101; }
# Run the Rust executable
K_VALUE=${1:-4}
cargo run --bin aggregate --features "parallel" -- "$K_VALUE" || { echo "prove.sh: cargo run failed"; exit 102; }

View File

@ -0,0 +1,14 @@
#!/bin/bash
# Source the parameters from the scripts directory
source "params.sh"
# Change to the parent directory of the script
cd "$(dirname "$0")/.." || { echo "Failed to change directory"; exit 1; }
# Build
cargo build --release || { echo "build_circuit.sh: cargo build failed"; exit 101; }
# Run the Rust executable
cargo run --bin build_circ || { echo "build_circuit.sh: cargo run failed"; exit 102; }

View File

@ -3,6 +3,9 @@
# Source the parameters from params.sh # Source the parameters from params.sh
source ./params.sh source ./params.sh
# Change to the parent directory of the script
cd "$(dirname "$0")/.." || { echo "Failed to change directory"; exit 1; }
# Build # Build
cargo build --release || { echo "gen_input.sh: cargo build failed"; exit 101; } cargo build --release || { echo "gen_input.sh: cargo build failed"; exit 101; }

14
workflow/scripts/params.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/bash
export MAXDEPTH=32 # maximum depth of the slot tree
export MAXSLOTS=256 # maximum number of slots
export CELLSIZE=2048 # cell size in bytes
export BLOCKSIZE=65536 # block size in bytes
export NSAMPLES=100 # number of samples to prove
export ENTROPY=1234567 # external randomness
export SEED=12345 # seed for creating fake data
export NSLOTS=11 # number of slots in the dataset
export SLOTINDEX=3 # which slot we prove (0..NSLOTS-1)
export NCELLS=512 # number of cells in this slot

View File

@ -3,6 +3,9 @@
# Source the parameters from params.sh # Source the parameters from params.sh
source ./circ_params.sh source ./circ_params.sh
# Change to the parent directory of the script
cd "$(dirname "$0")/.." || { echo "Failed to change directory"; exit 1; }
# Build # Build
cargo build --release || { echo "prove.sh: cargo build failed"; exit 101; } cargo build --release || { echo "prove.sh: cargo build failed"; exit 101; }

View File

@ -3,6 +3,9 @@
# Source the parameters from params.sh # Source the parameters from params.sh
source ./circ_params.sh source ./circ_params.sh
# Change to the parent directory of the script
cd "$(dirname "$0")/.." || { echo "Failed to change directory"; exit 1; }
# Build # Build
cargo build --release || { echo "prove_and_verify.sh: cargo build failed"; exit 101; } cargo build --release || { echo "prove_and_verify.sh: cargo build failed"; exit 101; }

View File

@ -0,0 +1,60 @@
use std::env;
use plonky2::plonk::circuit_data::CircuitConfig;
use plonky2::plonk::config::GenericConfig;
use plonky2::iop::witness::PartialWitness;
use plonky2::plonk::circuit_builder::CircuitBuilder;
use anyhow::Result;
use plonky2::plonk::proof::ProofWithPublicInputs;
use codex_plonky2_circuits::circuits::sample_cells::SampleCircuit;
use codex_plonky2_circuits::recursion::uniform::tree::TreeRecursion;
use proof_input::gen_input::gen_testing_circuit_input;
use proof_input::params::{D, C, F, HF, Params};
fn main() -> Result<()> {
// load the parameters from environment variables
let params = Params::from_env()?;
const N: usize = 1;
const M: usize = 2;
// take k = "number of proofs" from env arguments; default to 4 if not there
let args: Vec<String> = env::args().collect();
let k: usize = if args.len() > 1 {
args[1]
.parse()
.expect("k not valid")
} else {
4
};
// generate circuit input with given parameters
let circ_input = gen_testing_circuit_input::<F,D>(&params.input_params);
// create the circuit
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
let circ = SampleCircuit::<F,D,HF>::new(params.circuit_params);
let mut targets = circ.sample_slot_circuit_with_public_input(&mut builder)?;
// create a PartialWitness and assign
let mut pw = PartialWitness::new();
circ.sample_slot_assign_witness(&mut pw, &targets, &circ_input)?;
// Build the circuit
let data = builder.build::<C>();
// Prove the inner-circuit with the assigned witness
let inner_proof = data.prove(pw)?;
// dummy proofs
let proofs: Vec<ProofWithPublicInputs<F, C, D>> = (0..k).map(|i| inner_proof.clone()).collect();
let mut tree = TreeRecursion::<F,D,C,HF, N, M>::build(data.common.clone()).unwrap();
let tree_proof = tree.prove_tree(&proofs, &data.verifier_only).unwrap();
let inner_pi: Vec<Vec<F>> = proofs.iter().map(|p| p.public_inputs.clone()).collect();
assert!(tree.verify_proof_and_public_input(tree_proof,inner_pi.clone(),&data.verifier_data(), false).is_ok());
Ok(())
}

View File

@ -26,7 +26,7 @@ fn main() -> Result<()> {
// Create a PartialWitness and assign // Create a PartialWitness and assign
let mut pw = PartialWitness::new(); let mut pw = PartialWitness::new();
circ.sample_slot_assign_witness(&mut pw, &targets, &circ_input); circ.sample_slot_assign_witness(&mut pw, &targets, &circ_input)?;
// Build the circuit // Build the circuit
let build_time = Instant::now(); let build_time = Instant::now();