From 209eda82401616c14131d0438253b0e4bcbddc25 Mon Sep 17 00:00:00 2001 From: M Alghazwi Date: Tue, 14 Jan 2025 11:13:51 +0100 Subject: [PATCH] refactor tests to follow changes in circuit impl --- proof-input/src/data_structs.rs | 2 +- proof-input/src/gen_input.rs | 1 - proof-input/src/lib.rs | 2 +- proof-input/src/merkle_tree/merkle_circuit.rs | 14 +- proof-input/src/params.rs | 2 - proof-input/src/recursion/cyclic_recursion.rs | 42 ++-- proof-input/src/recursion/mod.rs | 5 +- proof-input/src/recursion/simple_recursion.rs | 220 ++++++++--------- proof-input/src/recursion/simple_tree.rs | 64 +++++ .../{tree_recursion1.rs => tree1.rs} | 74 ++---- .../{tree_recursion2.rs => tree2.rs} | 230 ++++++++++-------- proof-input/src/serialization/json.rs | 4 +- proof-input/src/utils.rs | 1 - 13 files changed, 347 insertions(+), 314 deletions(-) create mode 100644 proof-input/src/recursion/simple_tree.rs rename proof-input/src/recursion/{tree_recursion1.rs => tree1.rs} (63%) rename proof-input/src/recursion/{tree_recursion2.rs => tree2.rs} (57%) diff --git a/proof-input/src/data_structs.rs b/proof-input/src/data_structs.rs index 55e8134..1ecfee9 100644 --- a/proof-input/src/data_structs.rs +++ b/proof-input/src/data_structs.rs @@ -6,7 +6,7 @@ use codex_plonky2_circuits::circuits::sample_cells::Cell; use plonky2_field::types::Sample; use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2; use crate::merkle_tree::merkle_safe::{MerkleProof, MerkleTree}; -use crate::params::{InputParams,Params, HF}; +use crate::params::{InputParams, HF}; use crate::sponge::hash_bytes_no_padding; use crate::utils::{bits_le_padded_to_usize, calculate_cell_index_bits, usize_to_bits_le}; diff --git a/proof-input/src/gen_input.rs b/proof-input/src/gen_input.rs index 041ab8b..b1d854a 100644 --- a/proof-input/src/gen_input.rs +++ b/proof-input/src/gen_input.rs @@ -3,7 +3,6 @@ use plonky2::plonk::config::{GenericConfig, Hasher}; use plonky2_field::extension::Extendable; use plonky2_field::types::Field; use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2; -use codex_plonky2_circuits::circuits::params::CircuitParams; use crate::params::{Params,InputParams}; use crate::utils::{bits_le_padded_to_usize, calculate_cell_index_bits, ceiling_log2, usize_to_bits_le}; use crate::merkle_tree::merkle_safe::MerkleProof; diff --git a/proof-input/src/lib.rs b/proof-input/src/lib.rs index 5597e1b..ffd5eaa 100644 --- a/proof-input/src/lib.rs +++ b/proof-input/src/lib.rs @@ -2,7 +2,7 @@ pub mod gen_input; pub mod params; pub mod utils; -// pub mod recursion; +pub mod recursion; pub mod sponge; pub mod merkle_tree; pub mod data_structs; diff --git a/proof-input/src/merkle_tree/merkle_circuit.rs b/proof-input/src/merkle_tree/merkle_circuit.rs index 28b289a..83a27fa 100644 --- a/proof-input/src/merkle_tree/merkle_circuit.rs +++ b/proof-input/src/merkle_tree/merkle_circuit.rs @@ -38,9 +38,9 @@ pub fn build_circuit< const D: usize, H: AlgebraicHasher, >( - builder: &mut CircuitBuilder::, + builder: &mut CircuitBuilder, depth: usize, -) -> Result<(MerkleTreeTargets, HashOutTarget)> { +) -> (MerkleTreeTargets, HashOutTarget) { // Create virtual targets let leaf = builder.add_virtual_hash(); @@ -69,10 +69,10 @@ pub fn build_circuit< }; // Add Merkle proof verification constraints to the circuit - let reconstructed_root_target = MerkleTreeCircuit::::reconstruct_merkle_root_circuit_with_mask(builder, &mut targets, depth)?; + let reconstructed_root_target = MerkleTreeCircuit::::reconstruct_merkle_root_circuit_with_mask(builder, &mut targets, depth).unwrap(); // Return MerkleTreeTargets - Ok((targets, reconstructed_root_target)) + (targets, reconstructed_root_target) } /// assign the witness values in the circuit targets @@ -176,7 +176,7 @@ mod tests { // create the circuit let config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::::new(config); - let (mut targets, reconstructed_root_target) = build_circuit::(&mut builder, max_depth)?; + let (mut targets, reconstructed_root_target) = build_circuit::(&mut builder, max_depth); // expected Merkle root let expected_root = builder.add_virtual_hash(); @@ -252,7 +252,7 @@ mod tests { let config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::::new(config); - let (mut targets, reconstructed_root_target) = build_circuit::(&mut builder, max_depth)?; + let (mut targets, reconstructed_root_target) = build_circuit::(&mut builder, max_depth); // expected Merkle root let expected_root_target = builder.add_virtual_hash(); @@ -276,7 +276,7 @@ mod tests { let mut pw = PartialWitness::new(); let path_bits = usize_to_bits_le(leaf_index, max_depth); - let last_index = (nleaves - 1) as usize; + let last_index = nleaves - 1; let last_bits = usize_to_bits_le(last_index, max_depth); let mask_bits = usize_to_bits_le(last_index, max_depth+1); diff --git a/proof-input/src/params.rs b/proof-input/src/params.rs index 47a0796..ee914b8 100644 --- a/proof-input/src/params.rs +++ b/proof-input/src/params.rs @@ -5,8 +5,6 @@ use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; use std::env; use anyhow::{Result, Context}; use codex_plonky2_circuits::circuits::params::CircuitParams; -use plonky2_field::goldilocks_field::GoldilocksField; -use plonky2_poseidon2::config::Poseidon2GoldilocksConfig; // test types pub const D: usize = 2; diff --git a/proof-input/src/recursion/cyclic_recursion.rs b/proof-input/src/recursion/cyclic_recursion.rs index 1f6bf6e..9ac7c6f 100644 --- a/proof-input/src/recursion/cyclic_recursion.rs +++ b/proof-input/src/recursion/cyclic_recursion.rs @@ -10,34 +10,28 @@ mod tests { use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::circuit_data::CircuitConfig; use plonky2::plonk::config::GenericConfig; - use codex_plonky2_circuits::params::{F, D, C, Plonky2Proof}; + use crate::params::{F, D, C, HF}; use codex_plonky2_circuits::recursion::circuits::sampling_inner_circuit::SamplingRecursion; - use plonky2_poseidon2::poseidon2_hash::poseidon2::{Poseidon2, Poseidon2Hash}; use crate::gen_input::gen_testing_circuit_input; - use crate::params::TestParams; + use crate::params::Params; use codex_plonky2_circuits::recursion::cyclic::CyclicCircuit; /// Uses cyclic recursion to sample the dataset #[test] fn test_cyclic_recursion() -> Result<()> { - // const D: usize = 2; - // type C = PoseidonGoldilocksConfig; - // type F = >::F; let config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::::new(config); let one = builder.one(); - let inner_sampling_circuit = SamplingRecursion::default(); - let mut params = TestParams::default(); - params.n_samples = 10; - let circ_input = gen_testing_circuit_input::(¶ms); - let mut cyclic_circ = CyclicCircuit::new(inner_sampling_circuit); + let mut params = Params::default(); + let inner_sampling_circuit = SamplingRecursion::::new(params.circuit_params); + let circ_input = gen_testing_circuit_input::(¶ms.input_params); let s = Instant::now(); - cyclic_circ.build_circuit()?; + let mut cyclic_circ = CyclicCircuit::::build_circuit::(inner_sampling_circuit)?; println!("build = {:?}", s.elapsed()); let s = Instant::now(); let proof = cyclic_circ.prove_one_layer(&circ_input)?; @@ -51,12 +45,12 @@ mod tests { ); println!("verify = {:?}", s.elapsed()); + // check public input hash is correct let mut hash_input = vec![]; hash_input.push(circ_input.slot_index); hash_input.extend_from_slice(&circ_input.dataset_root.elements); hash_input.extend_from_slice(&circ_input.entropy.elements); - // let hash_res = PoseidonHash::hash_no_pad(&hash_input); let hash_res = hash_n_to_hash_no_pad::>(&hash_input); let zero_hash = HashOut::::ZERO; let mut hash_input2 = vec![]; @@ -65,7 +59,11 @@ mod tests { let hash_res = hash_n_to_hash_no_pad::>(&hash_input2); println!("hash input = {:?}", hash_res.elements); - + assert_eq!( + proof.public_inputs[0..4].to_vec(), + hash_res.elements.to_vec(), + "public input hash incorrect" + ); Ok(()) } @@ -73,30 +71,24 @@ mod tests { /// Uses cyclic recursion to sample the dataset n times #[test] fn test_cyclic_recursion_n_layers() -> Result<()> { - // const D: usize = 2; - // type C = PoseidonGoldilocksConfig; - // type F = >::F; const N : usize = 2; let config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::::new(config); let one = builder.one(); - let inner_sampling_circuit = SamplingRecursion::default(); - let mut params = TestParams::default(); - params.n_samples = 10; + let mut params = Params::default(); + let inner_sampling_circuit = SamplingRecursion::::new(params.circuit_params); let mut circ_inputs = vec![]; for i in 0..N { - circ_inputs.push(gen_testing_circuit_input::(¶ms)); + circ_inputs.push(gen_testing_circuit_input::(¶ms.input_params)); } - let mut cyclic_circ = CyclicCircuit::new(inner_sampling_circuit); - let s = Instant::now(); - cyclic_circ.build_circuit()?; + let mut cyclic_circ = CyclicCircuit::::build_circuit::(inner_sampling_circuit)?; println!("build = {:?}", s.elapsed()); let s = Instant::now(); - let proof = cyclic_circ.prove_n_layers(N,circ_inputs)?; + let proof = cyclic_circ.prove_n_layers(circ_inputs)?; println!("prove = {:?}", s.elapsed()); println!("num of pi = {}", proof.public_inputs.len()); println!("pub input: {:?}", proof.public_inputs); diff --git a/proof-input/src/recursion/mod.rs b/proof-input/src/recursion/mod.rs index 1c862c8..bc53c20 100644 --- a/proof-input/src/recursion/mod.rs +++ b/proof-input/src/recursion/mod.rs @@ -1,4 +1,5 @@ pub mod simple_recursion; +pub mod simple_tree; pub mod cyclic_recursion; -pub mod tree_recursion1; -pub mod tree_recursion2; +pub mod tree1; +pub mod tree2; diff --git a/proof-input/src/recursion/simple_recursion.rs b/proof-input/src/recursion/simple_recursion.rs index 6c40935..72bc43b 100644 --- a/proof-input/src/recursion/simple_recursion.rs +++ b/proof-input/src/recursion/simple_recursion.rs @@ -1,149 +1,43 @@ // tests for simple recursion approaches use std::time::Instant; -use plonky2::hash::hash_types::HashOut; +use plonky2::hash::hash_types::{HashOut, NUM_HASH_OUT_ELTS}; use plonky2::iop::witness::PartialWitness; use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData}; +use plonky2::plonk::config::AlgebraicHasher; use plonky2_field::types::Field; use codex_plonky2_circuits::recursion::circuits::sampling_inner_circuit::SamplingRecursion; -use codex_plonky2_circuits::recursion::simple::simple_recursion::{aggregate_sampling_proofs, SimpleRecursionCircuit, SimpleRecursionInput}; -use codex_plonky2_circuits::recursion::simple::simple_tree_recursion::aggregate_sampling_proofs_tree; -use plonky2_poseidon2::serialization::{DefaultGateSerializer, DefaultGeneratorSerializer}; +use codex_plonky2_circuits::recursion::simple::simple_recursion::{SimpleRecursionCircuit, SimpleRecursionInput}; +use codex_plonky2_circuits::recursion::simple::simple_recursion_hashed_pi::{SimpleRecursionCircuitHashedPI, SimpleRecursionInputHashedPI}; use crate::gen_input::{build_circuit, prove_circuit}; -use crate::json::write_bytes_to_file; -use crate::params::{C, D, F}; +use crate::params::{C, D, F, HF, Params}; -// Test simple recursion + +// test the simple recursion approach #[test] -fn test_simple_recursion() -> anyhow::Result<()> { - // number of samples in each proof - let n_samples = 10; - // number of inner proofs: - let n_inner = 4; - - let mut data: Option> = None; - - // get proofs - let mut proofs_with_pi = vec![]; - for i in 0..n_inner{ - // build the circuit - let (data_i, pw) = build_circuit(n_samples, i)?; - // prove - proofs_with_pi.push(prove_circuit(&data_i, &pw)?); - data = Some(data_i); - - } - - println!("num of public inputs inner proof = {}", proofs_with_pi[0].public_inputs.len()); - - // Create the circuit - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); - // Create a PartialWitness - let mut pw_agg = PartialWitness::new(); - // aggregate proofs - aggregate_sampling_proofs(&proofs_with_pi, &data.unwrap().verifier_data(), &mut builder, &mut pw_agg)?; - - let data_agg = builder.build::(); - - // Prove the circuit with the assigned witness - let start_time = Instant::now(); - let proof_with_pis_agg = data_agg.prove(pw_agg)?; - println!("prove_time = {:?}", start_time.elapsed()); - - println!("num of public inputs = {}", proof_with_pis_agg.public_inputs.len()); - - // Verify the proof - let verifier_data = data_agg.verifier_data(); - assert!( - verifier_data.verify(proof_with_pis_agg).is_ok(), - "Merkle proof verification failed" - ); - - Ok(()) -} - -// Test simple tree recursion -#[test] -fn test_simple_tree_recursion() -> anyhow::Result<()> { - // number of samples in each proof - let n_samples = 10; - // number of inner proofs: - let n_inner = 4; - let mut data: Option> = None; - - // get proofs - let mut proofs_with_pi = vec![]; - for i in 0..n_inner{ - // build the circuit - let (data_i, pw) = build_circuit(n_samples, i)?; - proofs_with_pi.push(prove_circuit(&data_i, &pw)?); - data = Some(data_i); - } - - let data = data.unwrap(); - println!("inner circuit size = {:?}", data.common.degree_bits()); - // serialization - // let gate_serializer = DefaultGateSerializer; - // let generator_serializer =DefaultGeneratorSerializer::::default(); - // let data_bytes = data.to_bytes(&gate_serializer, &generator_serializer).unwrap(); - // println!("inner proof circuit data size = {} bytes", data_bytes.len()); - // let file_path = "inner_circ_data.bin"; - // // Write data to the file - // write_bytes_to_file(data_bytes, file_path).unwrap(); - // println!("Data written to {}", file_path); - - let start_time = Instant::now(); - let (proof, vd_agg) = aggregate_sampling_proofs_tree(&proofs_with_pi, data)?; - println!("prove_time = {:?}", start_time.elapsed()); - println!("num of public inputs = {}", proof.public_inputs.len()); - println!("agg pub input = {:?}", proof.public_inputs); - println!("outer circuit size = {:?}", vd_agg.common.degree_bits()); - - // serialization - // // let gate_serializer = DefaultGateSerializer; - // // let generator_serializer =DefaultGeneratorSerializer::::default(); - // let outer_data_bytes = vd_agg.to_bytes(&gate_serializer, &generator_serializer).unwrap(); - // println!("outer proof circuit data size = {} bytes", outer_data_bytes.len()); - // let file_path = "outer_circ_data.bin"; - // // Write data to the file - // write_bytes_to_file(outer_data_bytes, file_path).unwrap(); - // println!("Data written to {}", file_path); - - // Verify the proof - let verifier_data = vd_agg.verifier_data(); - assert!( - verifier_data.verify(proof).is_ok(), - "Merkle proof verification failed" - ); - - Ok(()) -} - -// test another approach of the simple recursion -#[test] -pub fn test_simple_recursion_approach2()-> anyhow::Result<()>{ +pub fn test_simple_recursion()-> anyhow::Result<()>{ // number of samples in each proof let n_samples = 5; // number of inner proofs: - const n_inner: usize = 4; + const N_INNER: usize = 4; let mut data: Option> = None; // get proofs let mut proofs_with_pi = vec![]; - for i in 0..n_inner{ + for i in 0..N_INNER { // build the circuit let (data_i, pw) = build_circuit(n_samples, i)?; proofs_with_pi.push(prove_circuit(&data_i, &pw)?); data = Some(data_i); } let data = data.unwrap(); + println!("inner circuit size = {:?}", data.common.degree_bits()); // careful here, the sampling recursion is the default so proofs should be for circuit // with default params - let sampling_inner_circ = SamplingRecursion::default(); - let rec_circuit = SimpleRecursionCircuit::<_,n_inner>::new(sampling_inner_circ); + let sampling_inner_circ = SamplingRecursion::::new(Params::default().circuit_params); + let rec_circuit = SimpleRecursionCircuit::::new(sampling_inner_circ); // Create the circuit let config = CircuitConfig::standard_recursion_config(); @@ -156,7 +50,7 @@ pub fn test_simple_recursion_approach2()-> anyhow::Result<()>{ let start = Instant::now(); let agg_data = builder.build::(); println!("build time = {:?}", start.elapsed()); - println!("circuit size = {:?}", data.common.degree_bits()); + println!("agg circuit size = {:?}", agg_data.common.degree_bits()); let mut default_entropy = HashOut::ZERO; default_entropy.elements[0] = F::from_canonical_u64(1234567); @@ -172,13 +66,97 @@ pub fn test_simple_recursion_approach2()-> anyhow::Result<()>{ let start = Instant::now(); let proof = agg_data.prove(pw)?; println!("prove time = {:?}", start.elapsed()); + println!("public input count = {:?}", proof.public_inputs.len()); // Verify the proof let verifier_data = agg_data.verifier_data(); assert!( verifier_data.verify(proof).is_ok(), - "Merkle proof verification failed" + "proof verification failed" ); Ok(()) +} + +// test the simple recursion approach with hashed public input +#[test] +pub fn test_simple_recursion_with_hashed_pi()-> anyhow::Result<()>{ + // number of samples in each proof + let n_samples = 5; + // number of inner proofs: + const N_INNER: usize = 4; + let mut data: Option> = None; + + // get proofs + let mut proofs_with_pi = vec![]; + for i in 0..N_INNER { + // build the circuit + let (data_i, pw) = build_circuit(n_samples, i)?; + proofs_with_pi.push(prove_circuit(&data_i, &pw)?); + data = Some(data_i); + } + let data = data.unwrap(); + println!("inner circuit size = {:?}", data.common.degree_bits()); + + // careful here, the sampling recursion is the default so proofs should be for circuit + // with default params + let sampling_inner_circ = SamplingRecursion::::new(Params::default().circuit_params); + let rec_circuit = SimpleRecursionCircuitHashedPI::::new(sampling_inner_circ); + + // Create the circuit + let config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(config); + // Create a PartialWitness + let mut pw = PartialWitness::new(); + + let targets = rec_circuit.build_circuit::(&mut builder)?; + + let start = Instant::now(); + let agg_data = builder.build::(); + println!("build time = {:?}", start.elapsed()); + println!("agg circuit size = {:?}", agg_data.common.degree_bits()); + + let mut default_entropy = HashOut::ZERO; + default_entropy.elements[0] = F::from_canonical_u64(1234567); + + let w = SimpleRecursionInputHashedPI{ + proofs: proofs_with_pi.clone(), + verifier_data: data.verifier_data(), + }; + + rec_circuit.assign_witness(&mut pw,&targets,w)?; + + let start = Instant::now(); + let proof = agg_data.prove(pw)?; + println!("prove time = {:?}", start.elapsed()); + println!("public input count = {:?}", proof.public_inputs.len()); + + // Verify the proof + let verifier_data = agg_data.verifier_data(); + assert!( + verifier_data.verify(proof.clone()).is_ok(), + "proof verification failed" + ); + + let inner_pi: Vec = proofs_with_pi.iter() + .flat_map(|p| p.public_inputs.iter()) + .cloned() + .collect(); + + assert!( + check_agg_proof_hash::(inner_pi, proof.public_inputs), + "public input verification failed" + ); + + Ok(()) +} + +pub fn check_agg_proof_hash>(inner_pi: Vec, agg_pi: Vec) -> bool{ + + if agg_pi.len() != NUM_HASH_OUT_ELTS { + return false; + } + let expected = H::hash_no_pad(&inner_pi); + + expected == HashOut::from_vec(agg_pi) } \ No newline at end of file diff --git a/proof-input/src/recursion/simple_tree.rs b/proof-input/src/recursion/simple_tree.rs new file mode 100644 index 0000000..effe92b --- /dev/null +++ b/proof-input/src/recursion/simple_tree.rs @@ -0,0 +1,64 @@ +// tests for simple recursion approaches + +use std::time::Instant; +use plonky2::plonk::circuit_data::{CircuitData}; +use crate::gen_input::{build_circuit, prove_circuit}; +use codex_plonky2_circuits::recursion::simple::simple_tree_recursion::aggregate_sampling_proofs_tree; +use crate::params::{C, D, F,HF}; + +// Test simple tree recursion +#[test] +fn test_simple_tree_recursion() -> anyhow::Result<()> { + // number of samples in each proof + let n_samples = 5; + // number of inner proofs: + let n_inner = 4; + let mut data: Option> = None; + + // get proofs + let mut proofs_with_pi = vec![]; + for i in 0..n_inner{ + // build the circuit + let (data_i, pw) = build_circuit(n_samples, i)?; + proofs_with_pi.push(prove_circuit(&data_i, &pw)?); + data = Some(data_i); + } + + let data = data.unwrap(); + println!("inner circuit size = {:?}", data.common.degree_bits()); + // serialization + // let gate_serializer = DefaultGateSerializer; + // let generator_serializer =DefaultGeneratorSerializer::::default(); + // let data_bytes = data.to_bytes(&gate_serializer, &generator_serializer).unwrap(); + // println!("inner proof circuit data size = {} bytes", data_bytes.len()); + // let file_path = "inner_circ_data.bin"; + // // Write data to the file + // write_bytes_to_file(data_bytes, file_path).unwrap(); + // println!("Data written to {}", file_path); + + let start_time = Instant::now(); + let (proof, vd_agg) = aggregate_sampling_proofs_tree::(&proofs_with_pi, data.verifier_data())?; + println!("prove_time = {:?}", start_time.elapsed()); + println!("num of public inputs = {}", proof.public_inputs.len()); + println!("agg pub input = {:?}", proof.public_inputs); + println!("outer circuit size = {:?}", vd_agg.common.degree_bits()); + + // serialization + // // let gate_serializer = DefaultGateSerializer; + // // let generator_serializer =DefaultGeneratorSerializer::::default(); + // let outer_data_bytes = vd_agg.to_bytes(&gate_serializer, &generator_serializer).unwrap(); + // println!("outer proof circuit data size = {} bytes", outer_data_bytes.len()); + // let file_path = "outer_circ_data.bin"; + // // Write data to the file + // write_bytes_to_file(outer_data_bytes, file_path).unwrap(); + // println!("Data written to {}", file_path); + + // Verify the proof + let verifier_data = vd_agg;//.verifier_data(); + assert!( + verifier_data.verify(proof).is_ok(), + "Merkle proof verification failed" + ); + + Ok(()) +} diff --git a/proof-input/src/recursion/tree_recursion1.rs b/proof-input/src/recursion/tree1.rs similarity index 63% rename from proof-input/src/recursion/tree_recursion1.rs rename to proof-input/src/recursion/tree1.rs index 8585148..1f4b6c9 100644 --- a/proof-input/src/recursion/tree_recursion1.rs +++ b/proof-input/src/recursion/tree1.rs @@ -3,47 +3,35 @@ #[cfg(test)] mod tests { use std::time::Instant; - use anyhow::{anyhow, Result}; - use plonky2::hash::poseidon::PoseidonHash; - use plonky2::plonk::circuit_builder::CircuitBuilder; - use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, CommonCircuitData, VerifierCircuitData, VerifierCircuitTarget, VerifierOnlyCircuitData}; - use plonky2::plonk::config::{AlgebraicHasher, GenericConfig, GenericHashOut, Hasher, PoseidonGoldilocksConfig}; + use plonky2::plonk::config::{GenericConfig, GenericHashOut, Hasher}; use plonky2_field::types::Field; - use codex_plonky2_circuits::circuits::sample_cells::{SampleCircuit, SampleCircuitInput}; - use codex_plonky2_circuits::params::{F, D, C, Plonky2Proof}; + use codex_plonky2_circuits::circuits::sample_cells::SampleCircuitInput; + use crate::params::{C, D, F, HF, Params}; use codex_plonky2_circuits::recursion::circuits::sampling_inner_circuit::SamplingRecursion; use codex_plonky2_circuits::recursion::circuits::inner_circuit::InnerCircuit; - use plonky2_poseidon2::poseidon2_hash::poseidon2::{Poseidon2, Poseidon2Hash}; + use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2; use crate::gen_input::get_m_default_circ_input; - use codex_plonky2_circuits::recursion::tree_recursion::{NodeCircuit, TreeRecursion}; + use codex_plonky2_circuits::recursion::tree1::tree_circuit::TreeRecursion; /// Uses node recursion to sample the dataset #[test] - fn test_node_recursion() -> Result<()> { - // const D: usize = 2; - // type C = PoseidonGoldilocksConfig; - // type F = >::F; + fn test_tree1_node_recursion() -> anyhow::Result<()> { const M: usize = 1; const N: usize = 2; - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); - let one = builder.one(); + let default_params = Params::default().circuit_params; + let inner_sampling_circuit = SamplingRecursion::::new(default_params); - let inner_sampling_circuit = SamplingRecursion::default(); - - let mut node = NodeCircuit::<_,M,N>::new(inner_sampling_circuit); - let mut tree_circ = TreeRecursion::new(node); let circ_input = get_m_default_circ_input::(); let s = Instant::now(); - tree_circ.build()?; + let mut tree_circ = TreeRecursion::::build::(inner_sampling_circuit)?; println!("build = {:?}", s.elapsed()); + println!("tree circuit size = {:?}", tree_circ.node_circ.cyclic_circuit_data.common.degree_bits()); let s = Instant::now(); let proof = tree_circ.prove(&circ_input,None, true)?; println!("prove = {:?}", s.elapsed()); println!("num of pi = {}", proof.public_inputs.len()); - println!("pub input: {:?}", proof.public_inputs); let s = Instant::now(); assert!( tree_circ.verify_proof(proof).is_ok(), @@ -56,40 +44,32 @@ mod tests { /// Uses node recursion to sample the dataset #[test] - fn test_tree_recursion_approach1() -> Result<()> { - // const D: usize = 2; - // type C = PoseidonGoldilocksConfig; - // type F = >::F; + fn test_tree_recursion_approach1() -> anyhow::Result<()> { const M: usize = 1; const N: usize = 2; const DEPTH: usize = 3; const TOTAL_INPUT: usize = (N.pow(DEPTH as u32) - 1) / (N - 1); - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); - - let inner_sampling_circuit = SamplingRecursion::default(); - - let mut node = NodeCircuit::<_,M,N>::new(inner_sampling_circuit); - let mut tree_circ = TreeRecursion::new(node); + let default_params = Params::default().circuit_params; + let inner_sampling_circuit = SamplingRecursion::::new(default_params); let all_circ_input = get_m_default_circ_input::().to_vec(); let s = Instant::now(); - tree_circ.build()?; + let mut tree_circ = TreeRecursion::::build::(inner_sampling_circuit)?; println!("build = {:?}", s.elapsed()); + println!("tree circuit size = {:?}", tree_circ.node_circ.cyclic_circuit_data.common.degree_bits()); let s = Instant::now(); let proof = tree_circ.prove_tree(all_circ_input.clone(),DEPTH)?; println!("prove = {:?}", s.elapsed()); println!("num of pi = {}", proof.public_inputs.len()); - println!("pub input: {:?}", proof.public_inputs); // Extract the final public input hash from the proof let final_proof_hash = &proof.public_inputs[0..4]; // Recompute the expected final public input hash (outside the circuit) - let expected_hash = compute_expected_pub_input_hash::( + let expected_hash = compute_expected_pub_input_hash( &all_circ_input, DEPTH, M, @@ -112,8 +92,8 @@ mod tests { /// Recursively compute the final public input hash for a single node in the recursion tree. /// This is the same logic from `NodeCircuit::build_circuit` /// TODO: optimize this - fn compute_node_hash>>( - all_circ_inputs: &[I::Input], + fn compute_node_hash( + all_circ_inputs: &[SampleCircuitInput], depth: usize, current_depth: usize, node_idx: usize, @@ -133,12 +113,12 @@ mod tests { let mut pi_vec = vec![inp.slot_index]; pi_vec.extend_from_slice(&inp.dataset_root.elements); pi_vec.extend_from_slice(&inp.entropy.elements); - let hash_res = PoseidonHash::hash_no_pad(&pi_vec); + let hash_res = HF::hash_no_pad(&pi_vec); outer_pi_hashes.extend_from_slice(&hash_res.elements); } // hash all these M hashes into one - let outer_pi_hash = PoseidonHash::hash_no_pad(&outer_pi_hashes); + let outer_pi_hash = HF::hash_no_pad(&outer_pi_hashes); let is_leaf = current_depth == depth - 1; @@ -153,11 +133,11 @@ mod tests { let mut inner_pub_input_hashes = vec![]; for i in child_start..child_start + N { - let child_hash = compute_node_hash::(all_circ_inputs, depth, next_depth, i, M, N); + let child_hash = compute_node_hash(all_circ_inputs, depth, next_depth, i, M, N); inner_pub_input_hashes.extend_from_slice(&child_hash); } - let inner_pub_input_hash = PoseidonHash::hash_no_pad(&inner_pub_input_hashes); + let inner_pub_input_hash = HF::hash_no_pad(&inner_pub_input_hashes); inner_pub_input_hash.elements }; @@ -166,20 +146,20 @@ mod tests { final_input.extend_from_slice(&outer_pi_hash.elements); final_input.extend_from_slice(&inner_pi_hash_or_zero); - let final_hash = PoseidonHash::hash_no_pad(&final_input); + let final_hash = HF::hash_no_pad(&final_input); final_hash.elements } /// Compute the expected public input hash for the entire recursion tree. /// This function calls `compute_node_hash` starting from the root (layer 0, node 0). - pub fn compute_expected_pub_input_hash>>( - all_circ_inputs: &[I::Input], + pub fn compute_expected_pub_input_hash( + all_circ_inputs: &[SampleCircuitInput], depth: usize, M: usize, N: usize, - ) -> Result> { + ) -> anyhow::Result> { // The root node is at layer = 0 and node_idx = 0 - let final_hash = compute_node_hash::(all_circ_inputs, depth, 0, 0, M, N); + let final_hash = compute_node_hash(all_circ_inputs, depth, 0, 0, M, N); Ok(final_hash.to_vec()) } } \ No newline at end of file diff --git a/proof-input/src/recursion/tree_recursion2.rs b/proof-input/src/recursion/tree2.rs similarity index 57% rename from proof-input/src/recursion/tree_recursion2.rs rename to proof-input/src/recursion/tree2.rs index e4707ef..8bf683a 100644 --- a/proof-input/src/recursion/tree_recursion2.rs +++ b/proof-input/src/recursion/tree2.rs @@ -3,41 +3,38 @@ #[cfg(test)] mod tests { use std::time::Instant; - use anyhow::{anyhow, Result}; + use plonky2::hash::hash_types::HashOut; use plonky2::iop::witness::PartialWitness; use plonky2::plonk::circuit_builder::CircuitBuilder; - use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, CommonCircuitData, VerifierCircuitData, VerifierCircuitTarget, VerifierOnlyCircuitData}; - use plonky2::plonk::config::{AlgebraicHasher, GenericConfig, GenericHashOut, Hasher, PoseidonGoldilocksConfig}; - use plonky2::plonk::proof::ProofWithPublicInputs; - use codex_plonky2_circuits::circuits::params::CircuitParams; - use codex_plonky2_circuits::circuits::sample_cells::{SampleCircuit, SampleCircuitInput}; - use codex_plonky2_circuits::params::{F, D, C, Plonky2Proof}; + use plonky2::plonk::circuit_data::CircuitConfig; + use plonky2::plonk::config::{GenericConfig, Hasher}; + use plonky2::plonk::proof::{ProofWithPublicInputs}; + use codex_plonky2_circuits::circuits::sample_cells::SampleCircuit; + use crate::params::{F, D, C, HF}; use codex_plonky2_circuits::recursion::circuits::sampling_inner_circuit::SamplingRecursion; use codex_plonky2_circuits::recursion::circuits::inner_circuit::InnerCircuit; - use codex_plonky2_circuits::recursion::leaf_circuit::{LeafCircuit, LeafInput}; - use plonky2_poseidon2::poseidon2_hash::poseidon2::{Poseidon2, Poseidon2Hash}; + use codex_plonky2_circuits::recursion::tree2::leaf_circuit::{LeafCircuit, LeafInput}; + // use plonky2_poseidon2::poseidon2_hash::poseidon2::{Poseidon2, Poseidon2Hash}; use crate::gen_input::gen_testing_circuit_input; - use crate::params::TestParams; - use codex_plonky2_circuits::recursion::tree_recursion2::{NodeCircuit as nodeC, TreeRecursion as TR}; - use codex_plonky2_circuits::recursion::tree2::utils::{get_dummy_leaf_proof, get_dummy_node_proof}; - use crate::gen_input::get_m_default_circ_input; + use crate::params::Params; + use codex_plonky2_circuits::recursion::tree2::{node_circuit::NodeCircuit, tree_circuit::TreeRecursion}; + use codex_plonky2_circuits::recursion::tree2::dummy_gen::DummyProofGen; + use codex_plonky2_circuits::circuits::utils::vec_to_array; + /// Uses node recursion to sample the dataset #[test] - fn test_leaf_circuit() -> Result<()> { - // const D: usize = 2; - // type C = PoseidonGoldilocksConfig; - // type F = >::F; + fn test_leaf_circuit() -> anyhow::Result<()> { const M: usize = 1; const N: usize = 2; let config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::::new(config); - let params = TestParams::default(); + let params = Params::default(); - let one_circ_input = gen_testing_circuit_input::(¶ms); - let samp_circ = SampleCircuit::::new(CircuitParams::default()); - let inner_tar = samp_circ.sample_slot_circuit_with_public_input(&mut builder); + let one_circ_input = gen_testing_circuit_input::(¶ms.input_params); + let samp_circ = SampleCircuit::::new(params.circuit_params); + let inner_tar = samp_circ.sample_slot_circuit_with_public_input(&mut builder)?; let mut pw = PartialWitness::::new(); samp_circ.sample_slot_assign_witness(&mut pw,&inner_tar,&one_circ_input); let inner_d = builder.build::(); @@ -50,21 +47,20 @@ mod tests { let config2 = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::::new(config2); - let inner_circ = SamplingRecursion::default(); - let leaf_circuit = LeafCircuit::new(inner_circ); + let inner_circ = SamplingRecursion::::new(Params::default().circuit_params); + let leaf_circuit = LeafCircuit::::new(inner_circ); let s = Instant::now(); - let leaf_tar = leaf_circuit.build(&mut builder)?; + let leaf_tar = leaf_circuit.build::(&mut builder)?; let circ_data = builder.build::(); println!("build = {:?}", s.elapsed()); + println!("sampling circuit size = {:?}", circ_data.common.degree_bits()); let s = Instant::now(); - // let proof = tree_circ.prove(&[leaf_in],None, true)?; let mut pw = PartialWitness::::new(); - leaf_circuit.assign_targets(&mut pw, &leaf_tar, &leaf_in)?; + leaf_circuit.assign_targets::(&mut pw, &leaf_tar, &leaf_in)?; let proof = circ_data.prove(pw)?; println!("prove = {:?}", s.elapsed()); println!("num of pi = {}", proof.public_inputs.len()); - println!("pub input: {:?}", proof.public_inputs); let s = Instant::now(); assert!( circ_data.verify(proof).is_ok(), @@ -76,8 +72,7 @@ mod tests { } #[test] - fn test_node_circuit_approach2() -> Result<()> { - // use predefined: C, D, F c + fn test_node_circuit_approach2() -> anyhow::Result<()> { const N: usize = 2; // binary tree let config = CircuitConfig::standard_recursion_config(); @@ -85,11 +80,10 @@ mod tests { //------------ sampling inner circuit ---------------------- // Circuit that does the sampling - default input - let mut params = TestParams::default(); - // params.n_samples = 10; - let one_circ_input = gen_testing_circuit_input::(¶ms); - let samp_circ = SampleCircuit::::new(CircuitParams::default()); - let inner_tar = samp_circ.sample_slot_circuit_with_public_input(&mut sampling_builder); + let mut params = Params::default(); + let one_circ_input = gen_testing_circuit_input::(¶ms.input_params); + let samp_circ = SampleCircuit::::new(params.circuit_params); + let inner_tar = samp_circ.sample_slot_circuit_with_public_input(&mut sampling_builder)?; // get generate a sampling proof let mut pw = PartialWitness::::new(); samp_circ.sample_slot_assign_witness(&mut pw,&inner_tar,&one_circ_input); @@ -98,8 +92,8 @@ mod tests { // ------------------- leaf -------------------- // leaf circuit that verifies the sampling proof - let inner_circ = SamplingRecursion::default(); - let leaf_circuit = LeafCircuit::new(inner_circ); + let inner_circ = SamplingRecursion::::new(Params::default().circuit_params); + let leaf_circuit = LeafCircuit::::new(inner_circ); let leaf_in = LeafInput{ inner_proof, @@ -109,17 +103,17 @@ mod tests { let mut leaf_builder = CircuitBuilder::::new(config); // build let s = Instant::now(); - let leaf_targets = leaf_circuit.build(&mut leaf_builder)?; + let leaf_targets = leaf_circuit.build::(&mut leaf_builder)?; let leaf_circ_data = leaf_builder.build::(); println!("build = {:?}", s.elapsed()); + println!("leaf circuit size = {:?}", leaf_circ_data.common.degree_bits()); // prove let s = Instant::now(); let mut pw = PartialWitness::::new(); - leaf_circuit.assign_targets(&mut pw, &leaf_targets, &leaf_in)?; + leaf_circuit.assign_targets::(&mut pw, &leaf_targets, &leaf_in)?; let leaf_proof = leaf_circ_data.prove(pw)?; println!("prove = {:?}", s.elapsed()); println!("num of pi = {}", leaf_proof.public_inputs.len()); - println!("pub input: {:?}", leaf_proof.public_inputs); // verify let s = Instant::now(); assert!( @@ -132,34 +126,30 @@ mod tests { // node circuit that verifies leafs or itself // build let s = Instant::now(); - let mut node = nodeC::build_circuit()?; + let mut node = NodeCircuit::::build_circuit::<_,HF>(leaf_circuit)?; println!("build = {:?}", s.elapsed()); + println!("leaf circuit size = {:?}", node.node_data.node_circuit_data.common.degree_bits()); // prove leaf let s = Instant::now(); let mut pw = PartialWitness::::new(); - let leaf_proofs: [ProofWithPublicInputs; N] = (0..N) - .map(|_| { - leaf_proof.clone() - }) - .collect::>() - .try_into() - .map_err(|_| anyhow!("Expected exactly M inner circuits"))?; - let dummy_node_proof = get_dummy_node_proof( - &node.node_data.inner_node_common_data, - &node.node_data.node_circuit_data.verifier_only, - ); - let dummy_node_proofs: [ProofWithPublicInputs; N] = (0..N) - .map(|_| { - dummy_node_proof.clone() - }) - .collect::>() - .try_into() - .map_err(|_| anyhow!("Expected exactly M inner circuits"))?; - nodeC::::assign_targets( + let leaf_proofs: [ProofWithPublicInputs; N] = + vec_to_array::>( + (0..N) + .map(|_| { + leaf_proof.clone() + }) + .collect::>() + )?; + let dummy_node_proofs: [ProofWithPublicInputs; N] = + DummyProofGen::::gen_n_dummy_node_proofs::( + &node.node_data.inner_node_common_data, + &node.node_data.node_circuit_data.verifier_only, + )?; + NodeCircuit::::assign_targets( node.node_targets.clone(), //targets - Some(leaf_proofs), // leaf proofs - Some(dummy_node_proofs), // node proofs (dummy here) + leaf_proofs, // leaf proofs + dummy_node_proofs, // node proofs (dummy here) &node.node_data.leaf_circuit_data.verifier_only, // leaf verifier data &mut pw, // partial witness true // is leaf @@ -167,7 +157,6 @@ mod tests { let node_proof = node.node_data.node_circuit_data.prove(pw)?; println!("prove = {:?}", s.elapsed()); println!("num of pi = {}", node_proof.public_inputs.len()); - println!("pub input: {:?}", node_proof.public_inputs); let s = Instant::now(); assert!( node.node_data.node_circuit_data.verify(node_proof.clone()).is_ok(), @@ -175,30 +164,26 @@ mod tests { ); println!("verify = {:?}", s.elapsed()); + // prove node let s = Instant::now(); let mut pw = PartialWitness::::new(); - let node_proofs: [ProofWithPublicInputs; N] = (0..N) - .map(|_| { - node_proof.clone() - }) - .collect::>() - .try_into() - .map_err(|_| anyhow!("Expected exactly M inner circuits"))?; - let dummy_leaf_proof = get_dummy_leaf_proof( - &node.node_data.leaf_circuit_data.common - ); - let dummy_leaf_proofs: [ProofWithPublicInputs; N] = (0..N) - .map(|_| { - dummy_leaf_proof.clone() - }) - .collect::>() - .try_into() - .map_err(|_| anyhow!("Expected exactly M inner circuits"))?; - nodeC::::assign_targets( + let node_proofs: [ProofWithPublicInputs; N] = + vec_to_array::>( + (0..N) + .map(|_| { + node_proof.clone() + }) + .collect::>() + )?; + let dummy_leaf_proofs: [ProofWithPublicInputs; N] = + DummyProofGen::::gen_n_dummy_leaf_proofs::( + &node.node_data.leaf_circuit_data.common + )?; + NodeCircuit::::assign_targets( node.node_targets.clone(), //targets - Some(dummy_leaf_proofs), // leaf proofs - Some(node_proofs), // node proofs (dummy here) + dummy_leaf_proofs, // leaf proofs + node_proofs, // node proofs (dummy here) &node.node_data.leaf_circuit_data.verifier_only, // leaf verifier data &mut pw, // partial witness false // is leaf @@ -207,7 +192,6 @@ mod tests { // let node_proof = node_d.prove(pw)?; println!("prove = {:?}", s.elapsed()); println!("num of pi = {}", node_proof.public_inputs.len()); - println!("pub input: {:?}", node_proof.public_inputs); let s = Instant::now(); assert!( node.node_data.node_circuit_data.verify(node_proof.clone()).is_ok(), @@ -219,8 +203,7 @@ mod tests { } #[test] - fn test_tree_recursion_approach2() -> Result<()> { - // use predefined: C, D, F c + fn test_tree_recursion_approach2() -> anyhow::Result<()> { const N: usize = 2; // binary tree const K: usize = 4; // number of leaves/slots sampled - should be power of 2 @@ -229,22 +212,21 @@ mod tests { //------------ sampling inner circuit ---------------------- // Circuit that does the sampling - default input - let mut params = TestParams::default(); - params.n_samples = 10; - let one_circ_input = gen_testing_circuit_input::(¶ms); - let samp_circ = SampleCircuit::::new(CircuitParams::default()); - let inner_tar = samp_circ.sample_slot_circuit_with_public_input(&mut sampling_builder); + let mut params = Params::default(); + let one_circ_input = gen_testing_circuit_input::(¶ms.input_params); + let samp_circ = SampleCircuit::::new(params.circuit_params); + let inner_tar = samp_circ.sample_slot_circuit_with_public_input(&mut sampling_builder)?; // get generate a sampling proof let mut pw = PartialWitness::::new(); - samp_circ.sample_slot_assign_witness(&mut pw,&inner_tar,&one_circ_input); + samp_circ.sample_slot_assign_witness(&mut pw,&inner_tar,&one_circ_input)?; let inner_data = sampling_builder.build::(); println!("sampling circuit degree bits = {:?}", inner_data.common.degree_bits()); let inner_proof = inner_data.prove(pw)?; // ------------------- leaf -------------------- // leaf circuit that verifies the sampling proof - let inner_circ = SamplingRecursion::default(); - let leaf_circuit = LeafCircuit::new(inner_circ); + let inner_circ = SamplingRecursion::::new(Params::default().circuit_params); + let leaf_circuit = LeafCircuit::::new(inner_circ); let leaf_in = LeafInput{ inner_proof, @@ -254,18 +236,17 @@ mod tests { let mut leaf_builder = CircuitBuilder::::new(config); // build let s = Instant::now(); - let leaf_targets = leaf_circuit.build(&mut leaf_builder)?; + let leaf_targets = leaf_circuit.build::(&mut leaf_builder)?; let leaf_circ_data = leaf_builder.build::(); println!("build = {:?}", s.elapsed()); - println!("leaf circuit degree bits = {:?}", leaf_circ_data.common.degree_bits()); + println!("leaf circuit size = {:?}", leaf_circ_data.common.degree_bits()); // prove let s = Instant::now(); let mut pw = PartialWitness::::new(); - leaf_circuit.assign_targets(&mut pw, &leaf_targets, &leaf_in)?; + leaf_circuit.assign_targets::(&mut pw, &leaf_targets, &leaf_in)?; let leaf_proof = leaf_circ_data.prove(pw)?; println!("prove = {:?}", s.elapsed()); println!("num of pi = {}", leaf_proof.public_inputs.len()); - println!("pub input: {:?}", leaf_proof.public_inputs); // verify let s = Instant::now(); assert!( @@ -278,30 +259,73 @@ mod tests { // node circuit that verifies leafs or itself // build let s = Instant::now(); - let mut tree = TR::::build()?; + let mut tree = TreeRecursion::::build::<_,HF>(leaf_circuit)?; println!("build = {:?}", s.elapsed()); - println!("tree circuit degree bits = {:?}", tree.node.node_data.node_circuit_data.common.degree_bits()); + println!("node circuit degree bits = {:?}", tree.node.node_data.node_circuit_data.common.degree_bits()); // prove leaf let s = Instant::now(); - // let mut pw = PartialWitness::::new(); let leaf_proofs: Vec> = (0..K) .map(|_| { leaf_proof.clone() }) .collect::>(); - let tree_root_proof = tree.prove_tree(leaf_proofs)?; + let tree_root_proof = tree.prove_tree(leaf_proofs.clone())?; println!("prove = {:?}", s.elapsed()); println!("num of pi = {}", tree_root_proof.public_inputs.len()); - println!("pub input: {:?}", tree_root_proof.public_inputs); let s = Instant::now(); assert!( - tree.verify_proof(tree_root_proof.clone()).is_ok(), + tree.verify_proof(tree_root_proof.clone(),false).is_ok(), "proof verification failed" ); + + assert_eq!( + tree_root_proof.public_inputs[0..4].to_vec(), + get_expected_tree_root_pi_hash::(leaf_proofs), + "Public input of tree_root_proof does not match the expected root hash" + ); println!("verify = {:?}", s.elapsed()); Ok(()) } + + // ------------ Public Input Verification ------------ + /// Recompute the expected root public input hash outside the circuit + fn get_expected_tree_root_pi_hash(leaf_proofs: Vec>) + -> Vec{ + // Step 1: Extract relevant public inputs from each leaf proof + // Assuming the first public input is the hash used for tree hashing + let mut current_hashes: Vec> = leaf_proofs + .iter() + .map(|p|HashOut::from_vec(p.public_inputs.clone())) // Adjust index if different + .collect(); + + // Step 2: Iteratively compute parent hashes until one root hash remains + while current_hashes.len() > 1 { + let mut next_level_hashes = Vec::new(); + + for chunk in current_hashes.chunks(N) { + // Ensure each chunk has exactly N elements + assert!( + chunk.len() == N, + "Number of proofs is not divisible by N" + ); + + // collect field elements + let chunk_f: Vec = chunk.iter() + .flat_map(|h| h.elements.iter().cloned()) + .collect(); + + // Compute Poseidon2 hash of the concatenated chunk + let hash = HF::hash_no_pad(&chunk_f); + next_level_hashes.push(hash); + } + + current_hashes = next_level_hashes; + } + + // The final hash is the expected root hash + current_hashes[0].elements.to_vec() + } } \ No newline at end of file diff --git a/proof-input/src/serialization/json.rs b/proof-input/src/serialization/json.rs index be58739..5a5b41b 100644 --- a/proof-input/src/serialization/json.rs +++ b/proof-input/src/serialization/json.rs @@ -12,7 +12,6 @@ use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2; use codex_plonky2_circuits::circuits::sample_cells::SampleCircuitInput; use plonky2::plonk::proof::CompressedProofWithPublicInputs; use serde_json::to_writer_pretty; -use crate::params::InputParams; // Function to export proof with public input to json file fn export_proof_with_pi_to_json( @@ -46,9 +45,8 @@ pub fn read_bytes_from_file>(path: P) -> io::Result> { #[cfg(test)] mod tests { use super::*; - use crate::params::{C, D, F, HF, InputParams, Params}; + use crate::params::{C, D, F, HF, Params}; use std::time::Instant; - use codex_plonky2_circuits::circuits::params::CircuitParams; use codex_plonky2_circuits::circuits::sample_cells::SampleCircuit; use plonky2::iop::witness::PartialWitness; use plonky2::plonk::circuit_builder::CircuitBuilder; diff --git a/proof-input/src/utils.rs b/proof-input/src/utils.rs index 58eee67..e4b67cf 100644 --- a/proof-input/src/utils.rs +++ b/proof-input/src/utils.rs @@ -2,7 +2,6 @@ use plonky2::hash::hash_types::{HashOut, RichField}; use plonky2_field::extension::Extendable; use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2; use crate::params::HF; -use anyhow::Result; use plonky2::hash::hashing::PlonkyPermutation; use crate::sponge::hash_n_with_padding;