From 35ee544e689814cb068094af710776a03e4dd9d7 Mon Sep 17 00:00:00 2001 From: M Alghazwi Date: Tue, 17 Jun 2025 12:43:53 +0200 Subject: [PATCH] improve workflow bash script, and update readme --- workflow/.gitignore | 1 + workflow/README.md | 122 ++++++++++----------------- workflow/scripts/aggregate.sh | 14 --- workflow/scripts/build_circuit.sh | 14 --- workflow/scripts/circ_params.sh | 4 +- workflow/scripts/gen_input.sh | 13 --- workflow/scripts/gnark_params.sh | 8 ++ workflow/scripts/prove.sh | 13 --- workflow/scripts/prove_and_verify.sh | 42 --------- workflow/scripts/run_cli.sh | 98 +++++++++++++++++++++ workflow/scripts/run_gnark_cli.sh | 31 +++++++ workflow/scripts/verify.sh | 13 --- workflow/src/aggregate.rs | 76 +++++++++++++++++ workflow/src/bin/aggregate.rs | 59 ------------- workflow/src/bin/verify.rs | 23 ----- workflow/src/bn254_wrap.rs | 51 +++++++++++ workflow/src/{bin => }/build_circ.rs | 12 ++- workflow/src/file_paths.rs | 4 + workflow/src/{bin => }/gen_input.rs | 8 +- workflow/src/main.rs | 71 ++++++++++++++++ workflow/src/{bin => }/prove.rs | 25 +++--- workflow/src/verify.rs | 27 ++++++ 22 files changed, 437 insertions(+), 292 deletions(-) mode change 100644 => 100755 workflow/.gitignore mode change 100644 => 100755 workflow/README.md delete mode 100644 workflow/scripts/aggregate.sh delete mode 100755 workflow/scripts/build_circuit.sh delete mode 100755 workflow/scripts/gen_input.sh create mode 100755 workflow/scripts/gnark_params.sh delete mode 100755 workflow/scripts/prove.sh delete mode 100755 workflow/scripts/prove_and_verify.sh create mode 100755 workflow/scripts/run_cli.sh create mode 100755 workflow/scripts/run_gnark_cli.sh delete mode 100755 workflow/scripts/verify.sh create mode 100755 workflow/src/aggregate.rs delete mode 100644 workflow/src/bin/aggregate.rs delete mode 100644 workflow/src/bin/verify.rs create mode 100755 workflow/src/bn254_wrap.rs rename workflow/src/{bin => }/build_circ.rs (63%) mode change 100644 => 100755 create mode 100755 workflow/src/file_paths.rs rename workflow/src/{bin => }/gen_input.rs (74%) mode change 100644 => 100755 create mode 100755 workflow/src/main.rs rename workflow/src/{bin => }/prove.rs (54%) mode change 100644 => 100755 create mode 100755 workflow/src/verify.rs diff --git a/workflow/.gitignore b/workflow/.gitignore old mode 100644 new mode 100755 index 88ac17f..0a3fec3 --- a/workflow/.gitignore +++ b/workflow/.gitignore @@ -8,6 +8,7 @@ Cargo.lock # Profile-guided optimization /tmp pgo-data.profdata +/output # MacOS nuisances .DS_Store diff --git a/workflow/README.md b/workflow/README.md old mode 100644 new mode 100755 index 328f7e2..9be69af --- a/workflow/README.md +++ b/workflow/README.md @@ -10,20 +10,10 @@ This crate can be used to: - Generate circuit input from **fake data** with given params. - Build the Plonky2 codex storage proof circuits. - Generate a proof with given proof input in JSON file. -- Aggregate multiple proofs with 2-to-1 tree like aggregation to generate a final proof. +- Aggregate multiple proofs with 2-to-1 tree like aggregation to generate a final proof (with optional compression). +- Wrapping proof with BN254 Poseidon Hash. - Verify the proof. - -## Code organization - -- [`gen_input`](./src/bin/gen_input.rs) contains the main function to generate input with the given params as environment variables. - -- [`build_circ`](./src/bin/build_circ.rs) contains the main function to build the storage proof (Sampling) circuits. - -- [`prove`](./src/bin/prove.rs) contains the main function to generate a single proof. - -- [`aggregate`](./src/bin/aggregate.rs) contains the main function to aggregate `k` (default = 4) proofs. - -- [`verify`](./src/bin/verify) contains the main function to verify the storage proof (Sampling) proof. +- Wrap the proof with Gnark-plonky2-verifier to get a final succinct Groth16 proof. ## Usage @@ -43,11 +33,13 @@ To ensure that the nightly toolchain is used when building this crate, you can s rustup override set nightly ``` +- Go 1.22+ (for the GNARK-based verifier) + ### Generate Circuit Input The steps to generate circuit input with **fake data** are the following: #### Step 1: Setting Up Parameters -Parameters for generating the circuit input can be defined in [`params.sh`](scripts/params.sh). +- Input params: 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: ```bash @@ -64,76 +56,54 @@ 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 ``` - -#### Step 2: Run the Script -Once the params are set, you can run the script to generate the circuit input (with fake data). +- Circuit parameters: Edit [`circ_params.sh`](./scripts/circ_params.sh) for: ```bash -sudo bash ./scripts/gen_input.sh -``` +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 -### Build the Circuit -To build the circuit and measure the time to build, you can simply run the script: +export T=4 # number of proofs to aggregate +``` +- GNARK-verifier params [`gnark_params.sh`](./scripts/gnark_params.sh): ```bash -sudo bash ./scripts/build_circuit.sh +export CIRCUIT_DIR="$BASE_DIR/../output/wrap/verifier_data" +export DATA_DIR="$BASE_DIR/../output/gnark_output" +export PROOF_SYSTEM="groth16" +export DUMMY="false" ``` -To see the source code of how to build the circuit, see [`build_circ`](./src/bin/build_circ.rs). -### Generate the Proof -After generating the circuit input (in a JSON file), you can run the circuits to generate the proofs. -First make sure you have the circuit data and input from previous scripts then follow the steps: - -#### Step 1: Setting Up Circuit Parameters -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: +#### Step 2: Run the Rust CLI +All steps are unified under [`run_cli.sh`](./scripts/run_cli.sh) By default, it will run nothing until you specify the operations. ```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 +# Show help and list all available flags +./scripts/run_cli.sh -h + +# Generate inputs, build, prove, aggregate, wrap & verify—all in one: +./scripts/run_cli.sh --all + +# Or pick individual operations: +./scripts/run_cli.sh \ + --gen-input \ + --build \ + --prove \ + --aggregate \ + --wrap-tree \ + --verify-tree ``` -#### Step 2: Run the Script -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. - +#### Step 3: Go/GNARK CLI workflow +To compile, prove, or verify wrapped Plonky2 circuits via GNARK, use: ```bash -sudo bash ./scripts/prove.sh +./scripts/run_gnark_cli.sh -h + +# run all steps (compile, prove, verify) with defaults: +./scripts/run_gnark_cli.sh + +# or individually: +./scripts/run_gnark_cli.sh --compile +./scripts/run_gnark_cli.sh --prove +./scripts/run_gnark_cli.sh --verify ``` - -### Verify the proof -To verify the generated proof, run the following script. -Make sure that you generate the circuit data and proof prior to this. - -```bash -sudo bash ./scripts/verify.sh -``` - -### Build, Prove, and Verify -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. -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`](scripts/circ_params.sh). - -```bash -sudo bash ./scripts/prove_and_verify.sh -``` -This script simply runs all previous scripts. - -### Aggregate K Proofs -To do this, you can run the following script. -Note that we don't actually generate `K` proofs but rather just clone the single generated proof which is enough for testing. -Make sure a proof is already generated using the script for proving above. - -```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" -``` - - diff --git a/workflow/scripts/aggregate.sh b/workflow/scripts/aggregate.sh deleted file mode 100644 index f2351e0..0000000 --- a/workflow/scripts/aggregate.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/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; } diff --git a/workflow/scripts/build_circuit.sh b/workflow/scripts/build_circuit.sh deleted file mode 100755 index 1190fa9..0000000 --- a/workflow/scripts/build_circuit.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/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 --features "parallel" || { echo "build_circuit.sh: cargo run failed"; exit 102; } - diff --git a/workflow/scripts/circ_params.sh b/workflow/scripts/circ_params.sh index bae02b0..5c04aa0 100755 --- a/workflow/scripts/circ_params.sh +++ b/workflow/scripts/circ_params.sh @@ -4,4 +4,6 @@ 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 \ No newline at end of file +export N_SAMPLES=100 # number of samples to prove + +export T=4 # number of proofs to aggregate \ No newline at end of file diff --git a/workflow/scripts/gen_input.sh b/workflow/scripts/gen_input.sh deleted file mode 100755 index 7eb5afa..0000000 --- a/workflow/scripts/gen_input.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -# Source the parameters from params.sh -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 "gen_input.sh: cargo build failed"; exit 101; } - -# Run the Rust executable -cargo run --bin gen_input --features "parallel" || { echo "gen_input.sh: cargo run failed"; exit 102; } diff --git a/workflow/scripts/gnark_params.sh b/workflow/scripts/gnark_params.sh new file mode 100755 index 0000000..75653de --- /dev/null +++ b/workflow/scripts/gnark_params.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +# current dir +BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +export CIRCUIT_DIR="$BASE_DIR/../output/wrap/verifier_data" +export DATA_DIR="$BASE_DIR/../output/gnark_output" +export PROOF_SYSTEM="groth16" +export DUMMY="false" diff --git a/workflow/scripts/prove.sh b/workflow/scripts/prove.sh deleted file mode 100755 index dcdf01f..0000000 --- a/workflow/scripts/prove.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -# Source the parameters from 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 -cargo build --release || { echo "prove.sh: cargo build failed"; exit 101; } - -# Run the Rust executable -cargo run --bin prove --features "parallel" || { echo "prove.sh: cargo run failed"; exit 102; } diff --git a/workflow/scripts/prove_and_verify.sh b/workflow/scripts/prove_and_verify.sh deleted file mode 100755 index 6e70ae7..0000000 --- a/workflow/scripts/prove_and_verify.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash - -# Source the parameters -source ./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 -cargo build --release > /dev/null 2>&1 || { echo "prove_and_verify.sh: cargo build failed"; exit 101; } - -# Run all steps -echo "START" - -echo "Generating Input" -start=$(date +%s) -cargo run --bin gen_input --features "parallel" > /dev/null 2>&1 || { echo "gen_input.sh: cargo run failed"; exit 102; } -end=$(date +%s) -echo "Generating Input took $((end - start)) seconds." - -echo "Building the circuit" -start=$(date +%s) -cargo run --bin build_circ --features "parallel" > /dev/null 2>&1 || { echo "build_circuit.sh: cargo run failed"; exit 102; } -end=$(date +%s) -echo "Building the circuit took $((end - start)) seconds." - -echo "Generating a proof" -start=$(date +%s) -cargo run --bin prove --features "parallel" > /dev/null 2>&1 || { echo "prove.sh: cargo run failed"; exit 102; } -end=$(date +%s) -echo "Generating a proof took $((end - start)) seconds." - -echo "Verifying the proof" -start=$(date +%s) -cargo run --bin verify --features "parallel" > /dev/null 2>&1 || { echo "verify.sh: cargo run failed"; exit 102; } -end=$(date +%s) -echo "Verifying the proof took $((end - start)) seconds." - -echo "DONE" - - diff --git a/workflow/scripts/run_cli.sh b/workflow/scripts/run_cli.sh new file mode 100755 index 0000000..006d343 --- /dev/null +++ b/workflow/scripts/run_cli.sh @@ -0,0 +1,98 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Load global and circuit-specific parameters +source "$(dirname "$0")/params.sh" +source "$(dirname "$0")/circ_params.sh" + +usage() { + cat < /dev/null + echo "[$name] Completed" +} + +$DO_GEN && run_cmd "GenInput" gen-input +$DO_BUILD && run_cmd "Build" build +$DO_PROVE && run_cmd "Prove" prove +$DO_AGG && run_cmd "Aggregate" aggregate +$DO_AGG_COMP && run_cmd "AggregateAndCompress" aggregate-and-compress +$DO_WRAP_SAMP && run_cmd "WrapSampling" wrap +$DO_WRAP_TREE && run_cmd "WrapTree" wrap-tree +$DO_WRAP_COMP && run_cmd "WrapCompress" wrap-compress +$DO_VER_SAMP && run_cmd "VerifySampling" verify +$DO_VER_TREE && run_cmd "VerifyTree" verify-tree +$DO_VER_COMP && run_cmd "VerifyCompressed" verify-compressed +$DO_VER_WRAP && run_cmd "VerifyWrapped" verify-wrapped + +echo "All requested steps done." diff --git a/workflow/scripts/run_gnark_cli.sh b/workflow/scripts/run_gnark_cli.sh new file mode 100755 index 0000000..df87acb --- /dev/null +++ b/workflow/scripts/run_gnark_cli.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +set -euo pipefail + +# script to invoke run_gnark_cli.sh + +# path to this directory +WRAPPER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Path to run_gnark_cli.sh +SCRIPT="$WRAPPER_DIR/../../gnark-wrapper/run_gnark_cli.sh" + +if [[ ! -x "$SCRIPT" ]]; then + echo "Error: Cannot find or execute run_gnark_cli.sh at $SCRIPT" >&2 + exit 1 +fi + +# params file in current working directory +PARAMS_FILE="$(pwd)/gnark_params.sh" +if [[ ! -f "$PARAMS_FILE" ]]; then + echo "Error: params.sh not found in current directory ($PARAMS_FILE)" >&2 + exit 1 +fi + +# Save CWD and switch into gnark-wrapper directory +TARGET_DIR="$(dirname "$SCRIPT")" +cd "$TARGET_DIR" + +# Build and run the command +cmd=("$SCRIPT" -P "$PARAMS_FILE" "$@") +echo "Running in $TARGET_DIR: ${cmd[*]}" +exec "${cmd[@]}" diff --git a/workflow/scripts/verify.sh b/workflow/scripts/verify.sh deleted file mode 100755 index 3b994aa..0000000 --- a/workflow/scripts/verify.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -# Source the parameters from 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 -cargo build --release || { echo "prove.sh: cargo build failed"; exit 101; } - -# Run the Rust executable -cargo run --bin verify --features "parallel" || { echo "prove.sh: cargo run failed"; exit 102; } diff --git a/workflow/src/aggregate.rs b/workflow/src/aggregate.rs new file mode 100755 index 0000000..85d08ac --- /dev/null +++ b/workflow/src/aggregate.rs @@ -0,0 +1,76 @@ +use std::env; +use std::time::Instant; +use anyhow::{Context, Result}; +use plonky2::plonk::proof::ProofWithPublicInputs; +use codex_plonky2_circuits::recursion::tree::TreeRecursion; +use proof_input::params::{D, C, F, HF}; +use codex_plonky2_circuits::serialization::{export_proof_with_pi, export_verifier_circuit_data, import_proof_with_pi, import_verifier_circuit_data}; +use crate::file_paths::{SAMPLING_CIRC_BASE_PATH, TREE_CIRC_BASE_PATH, COMPRESS_CIRC_BASE_PATH}; +pub fn run(compress: bool) -> Result<()> { + // load the parameters from environment variables + const N: usize = 2; + + // take k = "number of proofs" from env + let t: usize = env::var("T") + .context("T not set")? + .parse::() + .context("Invalid T")?; + + match t { + 2 => run_tree::(compress)?, + 4 => run_tree::(compress)?, + 8 => run_tree::(compress)?, + 16 => run_tree::(compress)?, + 32 => run_tree::(compress)?, + 64 => run_tree::(compress)?, + 128 => run_tree::(compress)?, + 256 => run_tree::(compress)?, + 512 => run_tree::(compress)?, + 1024 => run_tree::(compress)?, + other => panic!("unsupported proof count: {}", other), + } + + Ok(()) +} + +fn run_tree(compress: bool) -> Result<()> { + let circuit_path = SAMPLING_CIRC_BASE_PATH; + // Read the proof + let proof_with_pi = import_proof_with_pi::(circuit_path)?; + println!("Proof with public input imported from: {}", circuit_path); + + // read the circuit data + let verifier_data = import_verifier_circuit_data::(circuit_path)?; + println!("Verifier circuit data imported from: {}", circuit_path); + + // duplicate the proof to get k proofs + // this is just for testing - in real scenario we would need to load k proofs + let proofs: Vec> = (0..T).map(|_i| proof_with_pi.clone()).collect(); + + let start_time = Instant::now(); + let mut tree = TreeRecursion::::build_with_standard_config(verifier_data.clone()).unwrap(); + println!("build tree time: {:?}", start_time.elapsed()); + + let start_time = Instant::now(); + let tree_proof = if !compress { + tree.prove_tree(&proofs)? + } else { tree.prove_tree_and_compress(&proofs)? }; + println!("aggregate time: {:?}", start_time.elapsed()); + + //export the proof to json file + let dis_path = if !compress {TREE_CIRC_BASE_PATH} else { COMPRESS_CIRC_BASE_PATH }; + export_proof_with_pi(&tree_proof, dis_path)?; + println!("Tree proof written to: {}", dis_path); + + let node_ver_data = tree.get_node_verifier_data(); + export_verifier_circuit_data(node_ver_data, TREE_CIRC_BASE_PATH)?; + + let compression_ver_data = tree.get_compression_verifier_data(); + export_verifier_circuit_data(compression_ver_data, COMPRESS_CIRC_BASE_PATH)?; + + let inner_pi: Vec> = proofs.iter().map(|p| p.public_inputs.clone()).collect(); + + assert!(tree.verify_proof_and_public_input(tree_proof,inner_pi.clone(),compress).is_ok()); + + Ok(()) +} \ No newline at end of file diff --git a/workflow/src/bin/aggregate.rs b/workflow/src/bin/aggregate.rs deleted file mode 100644 index f9caa3b..0000000 --- a/workflow/src/bin/aggregate.rs +++ /dev/null @@ -1,59 +0,0 @@ -use std::env; -use anyhow::Result; -use plonky2::plonk::proof::ProofWithPublicInputs; -use codex_plonky2_circuits::recursion::tree::TreeRecursion; -use proof_input::params::{D, C, F, HF}; -use proof_input::serialization::file_paths::{PROOF_JSON, TREE_PROOF_JSON, VERIFIER_CIRC_DATA_JSON}; -use proof_input::serialization::json::{export_tree_proof_with_pi, import_proof_with_pi, import_verifier_circuit_data}; - -fn main() -> Result<()> { - // load the parameters from environment variables - const N: usize = 2; - - // take k = "number of proofs" from env arguments; default to 4 if not there - let args: Vec = env::args().collect(); - let t: usize = args.get(1).and_then(|s| s.parse().ok()).unwrap_or(4); - - match t { - 2 => run_tree::()?, - 4 => run_tree::()?, - 8 => run_tree::()?, - 16 => run_tree::()?, - 32 => run_tree::()?, - 64 => run_tree::()?, - 128 => run_tree::()?, - 256 => run_tree::()?, - 512 => run_tree::()?, - 1024 => run_tree::()?, - other => panic!("unsupported proof count: {}", other), - } - - Ok(()) -} - -fn run_tree() -> Result<()> { - // Read the proof - let proof_with_pi = import_proof_with_pi::()?; - println!("Proof with public input imported from: {}", PROOF_JSON); - - // read the circuit data - let verifier_data = import_verifier_circuit_data::()?; - println!("Verifier circuit data imported from: {}", VERIFIER_CIRC_DATA_JSON); - - // duplicate the proof to get k proofs - // this is just for testing - in real scenario we would need to load k proofs - let proofs: Vec> = (0..T).map(|_i| proof_with_pi.clone()).collect(); - - let mut tree = TreeRecursion::::build_with_standard_config(verifier_data.clone()).unwrap(); - - let tree_proof = tree.prove_tree_and_compress(&proofs).unwrap(); - //export the proof to json file - export_tree_proof_with_pi(&tree_proof)?; - println!("Tree proof written to: {}", TREE_PROOF_JSON); - - let inner_pi: Vec> = proofs.iter().map(|p| p.public_inputs.clone()).collect(); - - assert!(tree.verify_proof_and_public_input(tree_proof,inner_pi.clone(),false).is_ok()); - - Ok(()) -} \ No newline at end of file diff --git a/workflow/src/bin/verify.rs b/workflow/src/bin/verify.rs deleted file mode 100644 index fdf3ee4..0000000 --- a/workflow/src/bin/verify.rs +++ /dev/null @@ -1,23 +0,0 @@ -use std::time::Instant; -use anyhow::Result; -use proof_input::params::{D, C, F}; -use proof_input::serialization::file_paths::{PROOF_JSON, VERIFIER_CIRC_DATA_JSON}; -use proof_input::serialization::json::{import_proof_with_pi, import_verifier_circuit_data}; - -fn main() -> Result<()> { - - // read the circuit data - let verifier_data = import_verifier_circuit_data::()?; - println!("Verifier circuit data imported from: {}", VERIFIER_CIRC_DATA_JSON); - - // Read the proof - let proof_with_pi = import_proof_with_pi::()?; - println!("Proof with public input imported from: {}", PROOF_JSON); - - // verify the proof - let start_time = Instant::now(); - assert!(verifier_data.verify(proof_with_pi).is_ok(), "proof is NOT VALID"); - println!("Verifying time: {:?}", start_time.elapsed()); - - Ok(()) -} diff --git a/workflow/src/bn254_wrap.rs b/workflow/src/bn254_wrap.rs new file mode 100755 index 0000000..686624f --- /dev/null +++ b/workflow/src/bn254_wrap.rs @@ -0,0 +1,51 @@ +use std::time::Instant; +use anyhow::Result; +use codex_plonky2_circuits::bn254_wrapper::config::PoseidonBN254GoldilocksConfig; +use codex_plonky2_circuits::bn254_wrapper::wrap::{WrapCircuit, WrapInput, WrappedOutput}; +use codex_plonky2_circuits::circuit_helper::Plonky2Circuit; +use codex_plonky2_circuits::serialization::{export_verifier_circuit_data, import_proof_with_pi, import_verifier_circuit_data}; +use proof_input::params::{D, C, F}; +use crate::file_paths::WRAP_CIRC_BASE_PATH; + +type OuterParameters = PoseidonBN254GoldilocksConfig; + +pub fn run(circuit_path: &str) -> Result<()> { + + // Read the proof + let proof_with_pi = import_proof_with_pi::(&circuit_path)?; + println!("Proof with public input imported from: {}", &circuit_path); + + // read the circuit data + let verifier_data = import_verifier_circuit_data::(&circuit_path)?; + println!("Verifier circuit data imported from: {}", &circuit_path); + + let wrapper = WrapCircuit::::new(verifier_data); + let (targ, data) = wrapper.build_with_standard_config().unwrap(); + println!( + "wrapper circuit degree: {}", + data.common.degree_bits() + ); + let verifier_data = data.verifier_data(); + let prover_data = data.prover_data(); + let wrap_input = WrapInput{ + inner_proof: proof_with_pi, + }; + let start_time = Instant::now(); + let proof = wrapper.prove(&targ, &wrap_input,&prover_data).unwrap(); + println!("Wrap time: {:?}", start_time.elapsed()); + + let wrap_circ = WrappedOutput::{ + proof, + common_data: verifier_data.common.clone(), + verifier_data: verifier_data.verifier_only.clone(), + }; + + // export the circuit data + export_verifier_circuit_data::(verifier_data, WRAP_CIRC_BASE_PATH)?; + println!("all data written to {}", WRAP_CIRC_BASE_PATH); + + wrap_circ.save(WRAP_CIRC_BASE_PATH).unwrap(); + println!("Saved wrapped circuit"); + + Ok(()) +} diff --git a/workflow/src/bin/build_circ.rs b/workflow/src/build_circ.rs old mode 100644 new mode 100755 similarity index 63% rename from workflow/src/bin/build_circ.rs rename to workflow/src/build_circ.rs index 8d1d39a..75b58e6 --- a/workflow/src/bin/build_circ.rs +++ b/workflow/src/build_circ.rs @@ -2,12 +2,12 @@ use std::time::Instant; use anyhow::Result; use codex_plonky2_circuits::circuit_helper::Plonky2Circuit; use codex_plonky2_circuits::circuits::sample_cells::SampleCircuit; -use proof_input::serialization::json::export_circuit_data; +use codex_plonky2_circuits::serialization::export_circuit_data; use proof_input::params::Params; use proof_input::params::{D, C, F,HF}; -use proof_input::serialization::file_paths::{PROVER_CIRC_DATA_JSON, TARGETS_JSON, VERIFIER_CIRC_DATA_JSON}; +use crate::file_paths::SAMPLING_CIRC_BASE_PATH; -fn main() -> Result<()> { +pub fn run() -> Result<()> { // Load the parameters from environment variables let params = Params::from_env()?; @@ -20,10 +20,8 @@ fn main() -> Result<()> { println!("Circuit size (degree bits): {:?}", data.common.degree_bits()); // export the circuit data - export_circuit_data::(data, &targets)?; - println!("Prover Data written to {}", PROVER_CIRC_DATA_JSON); - println!("Verifier Data written to {}", VERIFIER_CIRC_DATA_JSON); - println!("Targets written to {}", TARGETS_JSON); + export_circuit_data::(data, &targets, SAMPLING_CIRC_BASE_PATH)?; + println!("all data written to {}", SAMPLING_CIRC_BASE_PATH); Ok(()) } diff --git a/workflow/src/file_paths.rs b/workflow/src/file_paths.rs new file mode 100755 index 0000000..e6cc208 --- /dev/null +++ b/workflow/src/file_paths.rs @@ -0,0 +1,4 @@ +pub(crate) const SAMPLING_CIRC_BASE_PATH: &str = "../output/sampling_circuit/"; +pub(crate) const TREE_CIRC_BASE_PATH: &str = "../output/tree/"; +pub(crate) const COMPRESS_CIRC_BASE_PATH: &str = "../output/compression/"; +pub(crate) const WRAP_CIRC_BASE_PATH: &str = "../output/wrap/"; \ No newline at end of file diff --git a/workflow/src/bin/gen_input.rs b/workflow/src/gen_input.rs old mode 100644 new mode 100755 similarity index 74% rename from workflow/src/bin/gen_input.rs rename to workflow/src/gen_input.rs index 51c3dbc..ca92e49 --- a/workflow/src/bin/gen_input.rs +++ b/workflow/src/gen_input.rs @@ -4,9 +4,9 @@ use proof_input::serialization::circuit_input::export_circ_input_to_json; use proof_input::gen_input::gen_testing_circuit_input; use proof_input::params::Params; use proof_input::params::{D, F}; -use proof_input::serialization::file_paths::CIRC_INPUT_JSON; +use crate::file_paths::SAMPLING_CIRC_BASE_PATH; -fn main() -> Result<()> { +pub fn run() -> Result<()> { // Load the parameters from environment variables let params = Params::from_env()?; @@ -16,8 +16,8 @@ fn main() -> Result<()> { println!("Generating input time: {:?}", start_time.elapsed()); // export circuit parameters to json file - export_circ_input_to_json(circ_input)?; - println!("proof input written to {}", CIRC_INPUT_JSON); + export_circ_input_to_json(circ_input, SAMPLING_CIRC_BASE_PATH)?; + println!("proof input written to {}", SAMPLING_CIRC_BASE_PATH); Ok(()) } diff --git a/workflow/src/main.rs b/workflow/src/main.rs new file mode 100755 index 0000000..0bdec35 --- /dev/null +++ b/workflow/src/main.rs @@ -0,0 +1,71 @@ +use anyhow::Result; +use clap::{Parser, Subcommand}; +use codex_plonky2_circuits::bn254_wrapper::config::PoseidonBN254GoldilocksConfig; +use crate::file_paths::{COMPRESS_CIRC_BASE_PATH, SAMPLING_CIRC_BASE_PATH, TREE_CIRC_BASE_PATH, WRAP_CIRC_BASE_PATH}; +use proof_input::params::C; +type OuterParameters = PoseidonBN254GoldilocksConfig; + +mod build_circ; +mod prove; +mod verify; +mod gen_input; +mod aggregate; +mod bn254_wrap; +mod file_paths; + +/// Codex_zk_cli: unified CLI for all zk operations +#[derive(Parser)] +#[command(name = "codex_zk_cli", version, about = "gen_input, build, prove, aggregate, wrap, verify")] +struct Cli { + #[command(subcommand)] + command: Commands, +} + +#[derive(Subcommand)] +enum Commands { + /// Generate witness inputs + GenInput, + /// build the circuit + Build, + /// Run the prover + Prove, + /// Aggregate proofs + Aggregate, + /// Aggregate and compress proofs + AggregateAndCompress, + /// Wrap sampling proof + Wrap, + /// Wrap aggregated tree proof + WrapTree, + /// Wrap compressed proof + WrapCompress, + /// Verify a sampling proof + Verify, + /// Verify a tree proof + VerifyTree, + /// Verify a compressed tree proof + VerifyCompressed, + /// Verify a wrapped proof + VerifyWrapped, +} + +fn main() -> Result<()> { + let cli = Cli::parse(); + + match cli.command { + Commands::GenInput => gen_input::run()?, + Commands::Build => build_circ::run()?, + Commands::Prove => prove::run()?, + Commands::Aggregate => aggregate::run(false)?, + Commands::AggregateAndCompress => aggregate::run(true)?, + Commands::Wrap => bn254_wrap::run(SAMPLING_CIRC_BASE_PATH)?, + Commands::WrapTree => bn254_wrap::run(TREE_CIRC_BASE_PATH)?, + Commands::WrapCompress => bn254_wrap::run(COMPRESS_CIRC_BASE_PATH)?, + Commands::Verify => verify::run::(SAMPLING_CIRC_BASE_PATH)?, + Commands::VerifyTree => verify::run::(TREE_CIRC_BASE_PATH)?, + Commands::VerifyCompressed => verify::run::(COMPRESS_CIRC_BASE_PATH)?, + Commands::VerifyWrapped => verify::run::(WRAP_CIRC_BASE_PATH)?, + } + + Ok(()) +} \ No newline at end of file diff --git a/workflow/src/bin/prove.rs b/workflow/src/prove.rs old mode 100644 new mode 100755 similarity index 54% rename from workflow/src/bin/prove.rs rename to workflow/src/prove.rs index 94faa1f..fc00b2b --- a/workflow/src/bin/prove.rs +++ b/workflow/src/prove.rs @@ -1,28 +1,27 @@ use anyhow::Result; use std::time::Instant; use codex_plonky2_circuits::circuit_helper::Plonky2Circuit; -use proof_input::serialization::circuit_input::import_circ_input_from_json; +use proof_input::serialization::circuit_input::{import_circ_input_from_json}; use codex_plonky2_circuits::circuits::sample_cells::{SampleCircuit, SampleCircuitInput, SampleTargets}; use codex_plonky2_circuits::circuits::params::CircuitParams; use proof_input::params::{D, C, F, HF}; -use proof_input::serialization::file_paths::{CIRC_INPUT_JSON, PROVER_CIRC_DATA_JSON, TARGETS_JSON, TREE_PROOF_JSON}; -use proof_input::serialization::json::{export_proof_with_pi, import_prover_circuit_data, import_targets}; - -fn main() -> Result<()> { +use codex_plonky2_circuits::serialization::{export_proof_with_pi, import_prover_circuit_data, import_targets}; +use crate::file_paths::SAMPLING_CIRC_BASE_PATH; +pub fn run() -> Result<()> { // Load the parameters from environment variables let circuit_params = CircuitParams::from_env()?; // Read the witness from input.json - let circ_input: SampleCircuitInput = import_circ_input_from_json()?; - println!("Witness imported from: {}", CIRC_INPUT_JSON); + let circ_input: SampleCircuitInput = import_circ_input_from_json(SAMPLING_CIRC_BASE_PATH)?; + println!("Witness imported from: {}", SAMPLING_CIRC_BASE_PATH); // read the targets - let circ_targets: SampleTargets = import_targets()?; - println!("circuit targets imported from: {}", TARGETS_JSON); + let circ_targets: SampleTargets = import_targets(SAMPLING_CIRC_BASE_PATH)?; + println!("circuit targets imported from: {}", SAMPLING_CIRC_BASE_PATH); // read the circuit data - let prover_data = import_prover_circuit_data::()?; - println!("Prover circuit data imported from: {}", PROVER_CIRC_DATA_JSON); + let prover_data = import_prover_circuit_data::(SAMPLING_CIRC_BASE_PATH)?; + println!("Prover circuit data imported from: {}", SAMPLING_CIRC_BASE_PATH); println!("Circuit size (degree bits): {:?}", prover_data.common.degree_bits()); // Prove the circuit with the assigned witness @@ -32,8 +31,8 @@ fn main() -> Result<()> { println!("Proving time: {:?}", start_time.elapsed()); //export the proof to json file - export_proof_with_pi(&proof_with_pis)?; - println!("Tree proof written to: {}", TREE_PROOF_JSON); + export_proof_with_pi(&proof_with_pis, SAMPLING_CIRC_BASE_PATH)?; + println!("proof written to: {}", SAMPLING_CIRC_BASE_PATH); Ok(()) } diff --git a/workflow/src/verify.rs b/workflow/src/verify.rs new file mode 100755 index 0000000..762d353 --- /dev/null +++ b/workflow/src/verify.rs @@ -0,0 +1,27 @@ +use std::time::Instant; +use anyhow::Result; +use plonky2::plonk::config::GenericConfig; +use serde::Serialize; +use proof_input::params::{D, F}; +use codex_plonky2_circuits::serialization::{import_proof_with_pi, import_verifier_circuit_data}; + +pub fn run< + // F: RichField + Extendable + Poseidon2 + Serialize, + C: GenericConfig + Serialize, +>(circuit_path: &str) -> Result<()> { + + // read the circuit data + let verifier_data = import_verifier_circuit_data::(circuit_path)?; + println!("Verifier circuit data imported from: {}", circuit_path); + + // Read the proof + let proof_with_pi = import_proof_with_pi::(circuit_path)?; + println!("Proof with public input imported from: {}", circuit_path); + + // verify the proof + let start_time = Instant::now(); + assert!(verifier_data.verify(proof_with_pi).is_ok(), "proof is NOT VALID"); + println!("Verifying time: {:?}", start_time.elapsed()); + + Ok(()) +}