From 7948d6538d2ad33faf4dba43e4870951e2714ad8 Mon Sep 17 00:00:00 2001 From: M Alghazwi Date: Tue, 17 Jun 2025 12:32:13 +0200 Subject: [PATCH] add wrap test --- proof-input/.gitignore | 0 proof-input/Cargo.toml | 0 proof-input/README.md | 0 proof-input/src/data_structs.rs | 0 proof-input/src/gen_input.rs | 0 proof-input/src/lib.rs | 0 proof-input/src/merkle_tree/key_compress.rs | 0 proof-input/src/merkle_tree/merkle_circuit.rs | 0 proof-input/src/merkle_tree/merkle_safe.rs | 0 proof-input/src/merkle_tree/mod.rs | 0 proof-input/src/merkle_tree/test.rs | 0 proof-input/src/params.rs | 10 +- proof-input/src/recursion/leaf_test.rs | 0 proof-input/src/recursion/mod.rs | 1 + proof-input/src/recursion/node_test.rs | 0 proof-input/src/recursion/tree_test.rs | 0 proof-input/src/recursion/wrap_test.rs | 117 ++++++ .../src/serialization/circuit_input.rs | 198 ++++++++-- proof-input/src/serialization/file_paths.rs | 12 - proof-input/src/serialization/json.rs | 371 ------------------ proof-input/src/serialization/mod.rs | 2 - proof-input/src/sponge.rs | 0 proof-input/src/utils.rs | 0 23 files changed, 286 insertions(+), 425 deletions(-) mode change 100644 => 100755 proof-input/.gitignore mode change 100644 => 100755 proof-input/Cargo.toml mode change 100644 => 100755 proof-input/README.md mode change 100644 => 100755 proof-input/src/data_structs.rs mode change 100644 => 100755 proof-input/src/gen_input.rs mode change 100644 => 100755 proof-input/src/lib.rs mode change 100644 => 100755 proof-input/src/merkle_tree/key_compress.rs mode change 100644 => 100755 proof-input/src/merkle_tree/merkle_circuit.rs mode change 100644 => 100755 proof-input/src/merkle_tree/merkle_safe.rs mode change 100644 => 100755 proof-input/src/merkle_tree/mod.rs mode change 100644 => 100755 proof-input/src/merkle_tree/test.rs mode change 100644 => 100755 proof-input/src/params.rs mode change 100644 => 100755 proof-input/src/recursion/leaf_test.rs mode change 100644 => 100755 proof-input/src/recursion/mod.rs mode change 100644 => 100755 proof-input/src/recursion/node_test.rs mode change 100644 => 100755 proof-input/src/recursion/tree_test.rs create mode 100755 proof-input/src/recursion/wrap_test.rs mode change 100644 => 100755 proof-input/src/serialization/circuit_input.rs delete mode 100644 proof-input/src/serialization/file_paths.rs delete mode 100644 proof-input/src/serialization/json.rs mode change 100644 => 100755 proof-input/src/serialization/mod.rs mode change 100644 => 100755 proof-input/src/sponge.rs mode change 100644 => 100755 proof-input/src/utils.rs diff --git a/proof-input/.gitignore b/proof-input/.gitignore old mode 100644 new mode 100755 diff --git a/proof-input/Cargo.toml b/proof-input/Cargo.toml old mode 100644 new mode 100755 diff --git a/proof-input/README.md b/proof-input/README.md old mode 100644 new mode 100755 diff --git a/proof-input/src/data_structs.rs b/proof-input/src/data_structs.rs old mode 100644 new mode 100755 diff --git a/proof-input/src/gen_input.rs b/proof-input/src/gen_input.rs old mode 100644 new mode 100755 diff --git a/proof-input/src/lib.rs b/proof-input/src/lib.rs old mode 100644 new mode 100755 diff --git a/proof-input/src/merkle_tree/key_compress.rs b/proof-input/src/merkle_tree/key_compress.rs old mode 100644 new mode 100755 diff --git a/proof-input/src/merkle_tree/merkle_circuit.rs b/proof-input/src/merkle_tree/merkle_circuit.rs old mode 100644 new mode 100755 diff --git a/proof-input/src/merkle_tree/merkle_safe.rs b/proof-input/src/merkle_tree/merkle_safe.rs old mode 100644 new mode 100755 diff --git a/proof-input/src/merkle_tree/mod.rs b/proof-input/src/merkle_tree/mod.rs old mode 100644 new mode 100755 diff --git a/proof-input/src/merkle_tree/test.rs b/proof-input/src/merkle_tree/test.rs old mode 100644 new mode 100755 diff --git a/proof-input/src/params.rs b/proof-input/src/params.rs old mode 100644 new mode 100755 index 6fffc86..d263761 --- a/proof-input/src/params.rs +++ b/proof-input/src/params.rs @@ -1,7 +1,7 @@ // params for generating input for proof circuit -// use plonky2::hash::poseidon::PoseidonHash; -// use plonky2::plonk::config::PoseidonGoldilocksConfig; +use plonky2::hash::poseidon::PoseidonHash; +use plonky2::plonk::config::PoseidonGoldilocksConfig; use plonky2::plonk::config::GenericConfig; use std::env; use anyhow::{Result, Context}; @@ -11,9 +11,11 @@ use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2Hash; // test types pub const D: usize = 2; -pub type C = Poseidon2GoldilocksConfig; +pub type C = PoseidonGoldilocksConfig; +pub type C2 = Poseidon2GoldilocksConfig; pub type F = >::F; // this is the goldilocks field -pub type HF = Poseidon2Hash; +pub type HF = PoseidonHash; +pub type HF2 = Poseidon2Hash; // hardcoded default params for generating proof input const DEFAULT_MAX_DEPTH: usize = 32; // depth of big tree (slot tree depth, includes block tree depth) diff --git a/proof-input/src/recursion/leaf_test.rs b/proof-input/src/recursion/leaf_test.rs old mode 100644 new mode 100755 diff --git a/proof-input/src/recursion/mod.rs b/proof-input/src/recursion/mod.rs old mode 100644 new mode 100755 index c900bb7..54b106a --- a/proof-input/src/recursion/mod.rs +++ b/proof-input/src/recursion/mod.rs @@ -8,6 +8,7 @@ use crate::params::{C, D, F, HF, Params}; pub mod tree_test; pub mod leaf_test; pub mod node_test; +pub mod wrap_test; pub fn run_sampling_circ() -> anyhow::Result<(ProofWithPublicInputs, ProverCircuitData, VerifierCircuitData)> { diff --git a/proof-input/src/recursion/node_test.rs b/proof-input/src/recursion/node_test.rs old mode 100644 new mode 100755 diff --git a/proof-input/src/recursion/tree_test.rs b/proof-input/src/recursion/tree_test.rs old mode 100644 new mode 100755 diff --git a/proof-input/src/recursion/wrap_test.rs b/proof-input/src/recursion/wrap_test.rs new file mode 100755 index 0000000..cd6b4d8 --- /dev/null +++ b/proof-input/src/recursion/wrap_test.rs @@ -0,0 +1,117 @@ + +#[cfg(test)] +mod tests { + use plonky2::field::types::Field; + use plonky2::gates::noop::NoopGate; + use plonky2::iop::witness::{PartialWitness, WitnessWrite}; + use plonky2::plonk::circuit_builder::CircuitBuilder; + use plonky2::plonk::circuit_data::{CircuitConfig, VerifierCircuitData}; + use plonky2::plonk::proof::ProofWithPublicInputs; + use codex_plonky2_circuits::bn254_wrapper::config::PoseidonBN254GoldilocksConfig; + use codex_plonky2_circuits::bn254_wrapper::wrap::{WrapCircuit, WrapInput}; + use codex_plonky2_circuits::circuit_helper::Plonky2Circuit; + use codex_plonky2_circuits::recursion::tree::TreeRecursion; + use crate::params::{D, C, F, HF}; + use crate::recursion::run_sampling_circ; + + type OuterParameters = PoseidonBN254GoldilocksConfig; + + fn bn254_wrap(proof: ProofWithPublicInputs, vd: VerifierCircuitData) -> anyhow::Result<()>{ + // wrap this in the outer circuit. + let wrapper = WrapCircuit::::new(vd); + 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, + }; + let proof = wrapper.prove(&targ, &wrap_input,&prover_data).unwrap(); + + assert!(verifier_data.verify(proof).is_ok()); + + Ok(()) + } + + #[test] + fn test_dummy_wrap() -> anyhow::Result<()>{ + + let conf = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(conf); + + for _ in 0..(4096+10) { + builder.add_gate(NoopGate, vec![]); + } + // Add one virtual public input so that the circuit has minimal structure. + let t = builder.add_virtual_public_input(); + + // Set up the dummy circuit and wrapper. + let dummy_circuit = builder.build::(); + let mut pw = PartialWitness::new(); + pw.set_target(t, F::ZERO).expect("faulty assign"); + println!( + "dummy circuit degree: {}", + dummy_circuit.common.degree_bits() + ); + let dummy_inner_proof = dummy_circuit.prove(pw).unwrap(); + assert!(dummy_circuit.verify(dummy_inner_proof.clone()).is_ok()); + println!("Verified dummy_circuit"); + + // wrap this in the outer circuit. + bn254_wrap(dummy_inner_proof, dummy_circuit.verifier_data())?; + Ok(()) + } + + fn run_tree_recursion(compress: bool) -> anyhow::Result<()> { + + //------------ sampling inner circuit ---------------------- + // Circuit that does the sampling - 100 samples + let (inner_proof, inner_prover_data, inner_verifier_data) = run_sampling_circ()?; + + let proofs: Vec> = (0..T).map(|_i| inner_proof.clone()).collect(); + + // ------------------- tree -------------------- + // N-to-1 tree aggregation + + let mut tree = TreeRecursion::::build_with_standard_config(inner_verifier_data.clone())?; + + // aggregate + let root = if !compress { + tree.prove_tree(&proofs)? + } else { + println!("Mode: tree with compression"); + tree.prove_tree_and_compress(&proofs)? + }; + println!("pub input size = {}", root.public_inputs.len()); + println!("pub input = {:?}", root.public_inputs); + println!("proof size = {:?} bytes", root.to_bytes().len()); + + // sanity check + let vd = if !compress { + tree.get_node_verifier_data()} + else{ + tree.get_compression_verifier_data()}; + assert!(vd.verify(root.clone()).is_ok()); + + bn254_wrap(root, vd)?; + + Ok(()) + } + + #[test] + fn test_wrap_tree_recursion() -> anyhow::Result<()> { + // total number of proofs to aggregate + const T:usize = 4; + run_tree_recursion::<2, T>(false) + } + + #[test] + fn test_wrap_tree_recursion_with_compression() -> anyhow::Result<()> { + // total number of proofs to aggregate + const T:usize = 4; + run_tree_recursion::<2, T>(true) + } +} diff --git a/proof-input/src/serialization/circuit_input.rs b/proof-input/src/serialization/circuit_input.rs old mode 100644 new mode 100755 index c7f4802..3f42787 --- a/proof-input/src/serialization/circuit_input.rs +++ b/proof-input/src/serialization/circuit_input.rs @@ -6,43 +6,12 @@ use anyhow::{anyhow, Error}; use codex_plonky2_circuits::circuits::sample_cells::{Cell, MerklePath, SampleCircuitInput}; use std::fs::File; use std::io::{BufReader, Write}; +use std::path::Path; use crate::gen_input::gen_testing_circuit_input; use crate::params::InputParams; -use crate::serialization::file_paths::CIRC_INPUT_JSON; -use crate::serialization::json::ensure_parent_directory_exists; - -/// export circuit input to json file -pub fn export_circ_input_to_json< - F: RichField + Extendable + Poseidon2 + Serialize, - const D: usize, -> (circ_input:SampleCircuitInput) -> anyhow::Result<()>{ - // Convert the circuit input to a serializable format - let serializable_circ_input = SerializableCircuitInput::from_circ_input(&circ_input); - - // Serialize to JSON - let json_data = serde_json::to_string_pretty(&serializable_circ_input)?; - - // Write to file - ensure_parent_directory_exists(CIRC_INPUT_JSON)?; - let mut file = File::create(CIRC_INPUT_JSON)?; - file.write_all(json_data.as_bytes())?; - Ok(()) -} - - -/// Function to generate circuit input and export to JSON -pub fn generate_and_export_circ_input_to_json< - F: RichField + Extendable + Poseidon2 + Serialize, - const D: usize, ->(params: &InputParams) -> anyhow::Result<()> { - - let circ_input = gen_testing_circuit_input::(params); - - export_circ_input_to_json(circ_input)?; - - Ok(()) -} +use codex_plonky2_circuits::serialization::ensure_parent_directory_exists; +pub const CIRC_INPUT_JSON: &str = "prover_data/input.json"; // Serializable versions of the circuit input // naming here is not Rust friendly but only so that its compatible with Nim code. @@ -268,12 +237,169 @@ impl<> SerializableCircuitInput { } } +/// export circuit input to json file +pub fn export_circ_input_to_json< + F: RichField + Extendable + Poseidon2 + Serialize, + const D: usize, + P: AsRef, +>( + circ_input: SampleCircuitInput, + base_path: P, +) -> anyhow::Result<()> { + // Convert the circuit input to a serializable format + let serializable_circ_input = SerializableCircuitInput::from_circ_input(&circ_input); + + // Serialize to JSON + let json_data = serde_json::to_string_pretty(&serializable_circ_input)?; + + let full_path = base_path.as_ref().join(CIRC_INPUT_JSON); + + // Write to file + ensure_parent_directory_exists(&full_path)?; + let mut file = File::create(&full_path)?; + file.write_all(json_data.as_bytes())?; + Ok(()) +} + + +/// Function to generate circuit input and export to JSON +pub fn generate_and_export_circ_input_to_json< + F: RichField + Extendable + Poseidon2 + Serialize, + const D: usize, + P: AsRef, +>( + params: &InputParams, + base_path: P, +) -> anyhow::Result<()> { + + let circ_input = gen_testing_circuit_input::(params); + + export_circ_input_to_json(circ_input, base_path)?; + + Ok(()) +} + /// reads the json file, converts it to circuit input (SampleCircuitInput) and returns it -pub fn import_circ_input_from_json + Poseidon2, const D: usize>() -> anyhow::Result> { - let file = File::open(CIRC_INPUT_JSON)?; +pub fn import_circ_input_from_json< + F: RichField + Extendable + Poseidon2, + const D: usize, + P: AsRef, +>( + base_path: P, +) -> anyhow::Result> { + let full_path = base_path.as_ref().join(CIRC_INPUT_JSON); + + let file = File::open(&full_path)?; let reader = BufReader::new(file); let serializable_circ_input: SerializableCircuitInput = serde_json::from_reader(reader)?; let circ_input = serializable_circ_input.to_circ_input()?; Ok(circ_input) } + +#[cfg(test)] +mod tests { + use crate::params::{C, D, F, HF, Params}; + use codex_plonky2_circuits::circuits::sample_cells::{SampleCircuit, SampleCircuitInput}; + use plonky2::plonk::circuit_data::{ProverCircuitData, VerifierCircuitData}; + use codex_plonky2_circuits::circuit_helper::Plonky2Circuit; + use crate::gen_input::{gen_testing_circuit_input, verify_circuit_input}; + use crate::serialization::circuit_input::{export_circ_input_to_json, generate_and_export_circ_input_to_json, import_circ_input_from_json}; + + // Test to generate the JSON file + #[test] + fn test_export_circ_input_to_json() -> anyhow::Result<()> { + // Create Params + let params = Params::default().input_params; + // Export the circuit input to JSON + generate_and_export_circ_input_to_json::(¶ms, "../output/test/")?; + + println!("Circuit input exported to input.json"); + + Ok(()) + } + + #[test] + fn test_import_circ_input_from_json() -> anyhow::Result<()> { + // Import the circuit input from the JSON file + // NOTE: MAKE SURE THE FILE EXISTS + let _circ_input: SampleCircuitInput = import_circ_input_from_json("../output/test/")?; + println!("circuit input imported successfully"); + + Ok(()) + } + + // export the circuit input and then import it and checks equality + #[test] + fn test_export_import_circ_input() -> anyhow::Result<()> { + // Create Params instance + let params = Params::default().input_params; + + // Export the circuit input to JSON + let original_circ_input = gen_testing_circuit_input(¶ms); + export_circ_input_to_json(original_circ_input.clone(), "../output/test/")?; + println!("circuit input exported to input.json"); + + // Import the circuit input from JSON + let imported_circ_input: SampleCircuitInput = import_circ_input_from_json("../output/test/")?; + println!("circuit input imported from input.json"); + + // Compare the original and imported circuit input + assert_eq!(original_circ_input, imported_circ_input, "circuit input are not equal"); + + // cleanup: Remove the generated JSON file + // fs::remove_file("input.json")?; + + println!("Test passed: Original and imported circuit input are equal."); + + Ok(()) + } + + // reads the json input from file and runs the circuit + #[test] + fn test_read_json_and_run_circuit() -> anyhow::Result<()> { + // Create the circuit + let circuit_params = Params::default().circuit_params; + + let circ = SampleCircuit::::new(circuit_params.clone()); + let (targets, data) = circ.build_with_standard_config()?; + + let verifier_data: VerifierCircuitData = data.verifier_data(); + let prover_data: ProverCircuitData = data.prover_data(); + println!("circuit size = {:?}", verifier_data.common.degree_bits()); + + // Import the circuit input from JSON + let imported_circ_input: SampleCircuitInput = import_circ_input_from_json("../output/test/")?; + println!("circuit input imported from input.json"); + + let proof = circ.prove(&targets, &imported_circ_input, &prover_data)?; + + // Verify the proof + assert!( + verifier_data.verify(proof).is_ok(), + "Merkle proof verification failed" + ); + + Ok(()) + } + + // reads the json input and verify (non-circuit) + // NOTE: expects that the json input proof uses the default params + #[test] + fn test_read_json_and_verify() -> anyhow::Result<()> { + let params = Params::default().input_params; + + // Import the circuit input from JSON + let imported_circ_input: SampleCircuitInput = import_circ_input_from_json("../output/test/")?; + println!("circuit input imported from input.json"); + + // Verify the proof + let ver = verify_circuit_input(imported_circ_input, ¶ms); + assert!( + ver, + "Merkle proof verification failed" + ); + + Ok(()) + } +} diff --git a/proof-input/src/serialization/file_paths.rs b/proof-input/src/serialization/file_paths.rs deleted file mode 100644 index 5cc4aeb..0000000 --- a/proof-input/src/serialization/file_paths.rs +++ /dev/null @@ -1,12 +0,0 @@ -/// File constants with full paths - Prover -pub const CIRC_INPUT_JSON: &str = "prover_data/input.json"; -pub const PROVER_CIRC_DATA_JSON: &str = "prover_data/prover_circ_data.bin"; -pub const TARGETS_JSON: &str = "prover_data/targets.json"; - -/// File constants with full paths - Verifier -pub const VERIFIER_CIRC_DATA_JSON: &str = "verifier_data/verifier_circ_data.bin"; -pub const PROOF_JSON: &str = "verifier_data/proof.json"; -pub const TREE_PROOF_JSON: &str = "verifier_data/tree_proof.json"; - - - diff --git a/proof-input/src/serialization/json.rs b/proof-input/src/serialization/json.rs deleted file mode 100644 index 7ec985d..0000000 --- a/proof-input/src/serialization/json.rs +++ /dev/null @@ -1,371 +0,0 @@ -use serde::Serialize; -use std::{fs, io}; -use std::path::Path; -use anyhow::Context; -use plonky2::hash::hash_types::RichField; -use plonky2::plonk::circuit_data::{CircuitData, ProverCircuitData, VerifierCircuitData}; -use plonky2::plonk::config::{AlgebraicHasher, GenericConfig}; -use plonky2_field::extension::Extendable; -use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2; -use plonky2::plonk::proof::ProofWithPublicInputs; -use serde::de::DeserializeOwned; -use plonky2_poseidon2::serialization::{DefaultGateSerializer, DefaultGeneratorSerializer}; -use crate::serialization::file_paths::{PROOF_JSON, PROVER_CIRC_DATA_JSON, TARGETS_JSON, TREE_PROOF_JSON, VERIFIER_CIRC_DATA_JSON}; - -/// Writes the provided bytes to the specified file path using `std::fs::write`. -pub fn write_bytes_to_file>(data: Vec, path: P) -> io::Result<()> { - fs::write(path, data) -} - -/// Reads the contents of the specified file and returns them as a vector of bytes using `std::fs::read`. -pub fn read_bytes_from_file>(path: P) -> io::Result> { - fs::read(path) -} - -/// Ensures that the parent directory of the given file path exists. -/// If it does not exist, the function creates the entire directory path. -pub fn ensure_parent_directory_exists(path: &str) -> anyhow::Result<()> { - if let Some(parent) = Path::new(path).parent() { - fs::create_dir_all(parent) - .with_context(|| format!("Failed to create directory {:?}", parent))?; - } - Ok(()) -} - -/// Export the circuit data to disk. This function serializes the prover data, -/// verifier data, and circuit targets, and then writes them to their respective files. -/// The function uses the file paths defined in file_paths.rs -pub fn export_circuit_data( - circ_data: CircuitData, - targets: &impl Serialize, -) -> anyhow::Result<()> - where - F: RichField + Extendable + Poseidon2 + Serialize, - C: GenericConfig + 'static + Serialize, C:Default, - >::Hasher: AlgebraicHasher -{ - // separate the prover and verifier data - let verifier_data: VerifierCircuitData = circ_data.verifier_data(); - let prover_data = circ_data.prover_data(); - - let gate_serializer = DefaultGateSerializer; - let generator_serializer =DefaultGeneratorSerializer::::default(); - - // Serialize the prover data. - let prover_data_bytes = prover_data - .to_bytes(&gate_serializer, &generator_serializer) - .map_err(|e| anyhow::anyhow!("Failed to serialize prover data: {:?}", e))?; - // Serialize the verifier data. - let verifier_data_bytes = verifier_data - .to_bytes(&gate_serializer) - .map_err(|e| anyhow::anyhow!("Failed to serialize verifier data: {:?}", e))?; - // Serialize the circuit targets using serde_json. - let targets_bytes = serde_json::to_vec(targets) - .context("Failed to serialize circuit targets")?; - - // Ensure that the parent directories exist. - ensure_parent_directory_exists(PROVER_CIRC_DATA_JSON)?; - ensure_parent_directory_exists(VERIFIER_CIRC_DATA_JSON)?; - ensure_parent_directory_exists(TARGETS_JSON)?; - - // Write all data to the corresponding files. - write_bytes_to_file(prover_data_bytes, PROVER_CIRC_DATA_JSON) - .with_context(|| format!("Failed to write prover data to {}", PROVER_CIRC_DATA_JSON))?; - write_bytes_to_file(verifier_data_bytes, VERIFIER_CIRC_DATA_JSON) - .with_context(|| format!("Failed to write verifier data to {}", VERIFIER_CIRC_DATA_JSON))?; - write_bytes_to_file(targets_bytes, TARGETS_JSON) - .with_context(|| format!("Failed to write circuit targets to {}", TARGETS_JSON))?; - - Ok(()) -} - -/// Import the prover circuit data from disk and deserialize it. -pub fn import_prover_circuit_data() -> anyhow::Result> - where - F: RichField + Extendable + Poseidon2 + Serialize, - C: GenericConfig + 'static + Serialize, C:Default, - >::Hasher: AlgebraicHasher -{ - let gate_serializer = DefaultGateSerializer; - let generator_serializer =DefaultGeneratorSerializer::::default(); - - let bytes = read_bytes_from_file(PROVER_CIRC_DATA_JSON) - .with_context(|| format!("Failed to read prover circuit data from {}", PROVER_CIRC_DATA_JSON))?; - let prover_data = ProverCircuitData::::from_bytes(&bytes, &gate_serializer, &generator_serializer) - .map_err(|e| anyhow::anyhow!("Failed to deserialize prover data: {:?}", e))?; - Ok(prover_data) -} - -/// Import the verifier circuit data from disk and deserialize it. -pub fn import_verifier_circuit_data( -) -> anyhow::Result> - where - F: RichField + Extendable + Poseidon2 + Serialize, - C: GenericConfig + Serialize, -{ - let gate_serializer = DefaultGateSerializer; - - let bytes = read_bytes_from_file(VERIFIER_CIRC_DATA_JSON) - .with_context(|| format!("Failed to read verifier circuit data from {}", VERIFIER_CIRC_DATA_JSON))?; - let verifier_data = VerifierCircuitData::::from_bytes(bytes, &gate_serializer) - .map_err(|e| anyhow::anyhow!("Failed to deserialize verifier data: {:?}", e))?; - Ok(verifier_data) -} - -/// Import the proof with public input from the JSON file. -pub fn import_proof_with_pi() -> anyhow::Result> - where - F: RichField + Extendable + Poseidon2, - C: GenericConfig, -{ - let proof_json = fs::read_to_string(PROOF_JSON) - .with_context(|| format!("Failed to read file {}", PROOF_JSON))?; - let proof = serde_json::from_str(&proof_json) - .context("Failed to deserialize proof with public input")?; - Ok(proof) -} - -/// Import the circuit targets from the JSON file. -/// This function is generic over the type `T` that represents the targets and -/// must implement `DeserializeOwned` so that it can be deserialized. -pub fn import_targets() -> anyhow::Result - where - T: DeserializeOwned, -{ - let targets_json = fs::read_to_string(TARGETS_JSON) - .with_context(|| format!("Failed to read file {}", TARGETS_JSON))?; - let targets = serde_json::from_str(&targets_json) - .context("Failed to deserialize targets")?; - Ok(targets) -} - -/// Function to export tree proof with public input to json file -pub fn export_tree_proof_with_pi( - proof_with_pis: &ProofWithPublicInputs, -) -> anyhow::Result<()> - where - F: RichField + Extendable + Poseidon2 + Serialize, - C: GenericConfig + Serialize, -{ - export_proof_with_pi_to_given_path(proof_with_pis, TREE_PROOF_JSON) -} - -/// Function to export proof with public input to json file -pub fn export_proof_with_pi( - proof_with_pis: &ProofWithPublicInputs, -) -> anyhow::Result<()> - where - F: RichField + Extendable + Poseidon2 + Serialize, - C: GenericConfig + Serialize, -{ - export_proof_with_pi_to_given_path(proof_with_pis, PROOF_JSON) -} - -/// Function to export proof with public input to json file -/// takes the path -fn export_proof_with_pi_to_given_path( - proof_with_pis: &ProofWithPublicInputs, - path: &str, -) -> anyhow::Result<()> - where - F: RichField + Extendable + Poseidon2 + Serialize, - C: GenericConfig + Serialize, -{ - let proof_serialized= serde_json::to_vec(&proof_with_pis) - .map_err(|e| anyhow::anyhow!("Failed to serialize proof with public input: {:?}", e))?; - fs::write(path , &proof_serialized).expect("Unable to write file"); - - Ok(()) -} - -#[cfg(test)] -mod tests { - use crate::params::{C, D, F, HF, Params}; - use std::time::Instant; - use codex_plonky2_circuits::circuits::sample_cells::{SampleCircuit, SampleCircuitInput}; - use plonky2::plonk::circuit_data::{ ProverCircuitData, VerifierCircuitData}; - use codex_plonky2_circuits::circuit_helper::Plonky2Circuit; - use codex_plonky2_circuits::circuits::utils::read_bytes_from_file; - use plonky2_poseidon2::serialization::{DefaultGateSerializer, DefaultGeneratorSerializer}; - use crate::gen_input::{gen_testing_circuit_input, verify_circuit_input}; - use crate::serialization::circuit_input::{export_circ_input_to_json, generate_and_export_circ_input_to_json, import_circ_input_from_json}; - use crate::serialization::json::{export_proof_with_pi, write_bytes_to_file}; - - // Test to generate the JSON file - #[test] - fn test_export_circ_input_to_json() -> anyhow::Result<()> { - // Create Params - let params = Params::default().input_params; - // Export the circuit input to JSON - generate_and_export_circ_input_to_json::(¶ms)?; - - println!("Circuit input exported to input.json"); - - Ok(()) - } - - #[test] - fn test_import_circ_input_from_json() -> anyhow::Result<()> { - // Import the circuit input from the JSON file - // NOTE: MAKE SURE THE FILE EXISTS - let _circ_input: SampleCircuitInput = import_circ_input_from_json()?; - println!("circuit input imported successfully"); - - Ok(()) - } - - // export the circuit input and then import it and checks equality - #[test] - fn test_export_import_circ_input() -> anyhow::Result<()> { - // Create Params instance - let params = Params::default().input_params; - - // Export the circuit input to JSON - let original_circ_input = gen_testing_circuit_input(¶ms); - export_circ_input_to_json(original_circ_input.clone())?; - println!("circuit input exported to input.json"); - - // Import the circuit input from JSON - let imported_circ_input: SampleCircuitInput = import_circ_input_from_json()?; - println!("circuit input imported from input.json"); - - // Compare the original and imported circuit input - assert_eq!(original_circ_input, imported_circ_input, "circuit input are not equal"); - - // cleanup: Remove the generated JSON file - // fs::remove_file("input.json")?; - - println!("Test passed: Original and imported circuit input are equal."); - - Ok(()) - } - - // reads the json input from file and runs the circuit - #[test] - fn test_read_json_and_run_circuit() -> anyhow::Result<()> { - // Create the circuit - let circuit_params = Params::default().circuit_params; - - let circ = SampleCircuit::::new(circuit_params.clone()); - let (targets, data) = circ.build_with_standard_config()?; - - let verifier_data: VerifierCircuitData = data.verifier_data(); - let prover_data: ProverCircuitData = data.prover_data(); - println!("circuit size = {:?}", verifier_data.common.degree_bits()); - - // Import the circuit input from JSON - let imported_circ_input: SampleCircuitInput = import_circ_input_from_json()?; - println!("circuit input imported from input.json"); - - let proof = circ.prove(&targets, &imported_circ_input, &prover_data)?; - - // Verify the proof - assert!( - verifier_data.verify(proof).is_ok(), - "Merkle proof verification failed" - ); - - Ok(()) - } - - // reads the json input and verify (non-circuit) - // NOTE: expects that the json input proof uses the default params - #[test] - fn test_read_json_and_verify() -> anyhow::Result<()> { - let params = Params::default().input_params; - - // Import the circuit input from JSON - let imported_circ_input: SampleCircuitInput = import_circ_input_from_json()?; - println!("circuit input imported from input.json"); - - // Verify the proof - let ver = verify_circuit_input(imported_circ_input, ¶ms); - assert!( - ver, - "Merkle proof verification failed" - ); - - Ok(()) - } - - // test out custom default gate and generator serializers to export/import circuit data - #[test] - fn test_circuit_data_serializer() -> anyhow::Result<()> { - let params = Params::default(); - let input_params = params.input_params; - - // Create the circuit - let circuit_params = params.circuit_params; - let circ = SampleCircuit::::new(circuit_params.clone()); - let (targets, data) = circ.build_with_standard_config()?; - println!("circuit size = {:?}", data.common.degree_bits()); - - let verifier_data: VerifierCircuitData = data.verifier_data(); - let prover_data: ProverCircuitData = data.prover_data(); - - // gen circ input - let imported_circ_input: SampleCircuitInput = gen_testing_circuit_input::(&input_params); - - let gate_serializer = DefaultGateSerializer; - let generator_serializer =DefaultGeneratorSerializer::::default(); - let data_bytes = prover_data.to_bytes(&gate_serializer, &generator_serializer).unwrap(); - - let file_path = "circ_data.bin"; - // Write data to the file - write_bytes_to_file(data_bytes.clone(), file_path).unwrap(); - println!("Data written to {}", file_path); - - // Read data back from the file - let read_data = read_bytes_from_file(file_path).unwrap(); - let prover_data = ProverCircuitData::::from_bytes(&read_data, &gate_serializer, &generator_serializer).unwrap(); - - // Prove the circuit with the assigned witness - let start_time = Instant::now(); - let proof_with_pis = circ.prove(&targets, &imported_circ_input, &prover_data)?; - println!("prove_time = {:?}", start_time.elapsed()); - - // Verify the proof - assert!( - verifier_data.verify(proof_with_pis).is_ok(), - "Merkle proof verification failed" - ); - - Ok(()) - } - - // test proof with public input serialization - #[test] - fn test_proof_with_pi_serializer() -> anyhow::Result<()> { - let params = Params::default(); - let input_params = params.input_params; - - // Create the circuit - let circuit_params = params.circuit_params; - let circ = SampleCircuit::::new(circuit_params.clone()); - let (targets, data) = circ.build_with_standard_config()?; - println!("circuit size = {:?}", data.common.degree_bits()); - - let verifier_data: VerifierCircuitData = data.verifier_data(); - let prover_data: ProverCircuitData = data.prover_data(); - - // gen circ input - let imported_circ_input: SampleCircuitInput = gen_testing_circuit_input::(&input_params); - - // Prove the circuit with the assigned witness - let start_time = Instant::now(); - let proof_with_pis = circ.prove(&targets, &imported_circ_input, &prover_data)?; - println!("prove_time = {:?}", start_time.elapsed()); - println!("Proof size: {} bytes", proof_with_pis.to_bytes().len()); - - export_proof_with_pi(&proof_with_pis)?; - println!("Proof size: {} bytes", proof_with_pis.to_bytes().len()); - - // Verify the proof - assert!( - verifier_data.verify(proof_with_pis).is_ok(), - "Merkle proof verification failed" - ); - - Ok(()) - } -} \ No newline at end of file diff --git a/proof-input/src/serialization/mod.rs b/proof-input/src/serialization/mod.rs old mode 100644 new mode 100755 index 6a1aacb..bb922ce --- a/proof-input/src/serialization/mod.rs +++ b/proof-input/src/serialization/mod.rs @@ -1,3 +1 @@ pub mod circuit_input; -pub mod json; -pub mod file_paths; diff --git a/proof-input/src/sponge.rs b/proof-input/src/sponge.rs old mode 100644 new mode 100755 diff --git a/proof-input/src/utils.rs b/proof-input/src/utils.rs old mode 100644 new mode 100755