diff --git a/codex-plonky2-circuits/.gitignore b/codex-plonky2-circuits/.gitignore index a3547b9..b109982 100644 --- a/codex-plonky2-circuits/.gitignore +++ b/codex-plonky2-circuits/.gitignore @@ -11,3 +11,7 @@ pgo-data.profdata # MacOS nuisances .DS_Store + +# circuit files +/prover_data +/verifier_data diff --git a/codex-plonky2-circuits/src/bundle/mod.rs b/codex-plonky2-circuits/src/bundle/mod.rs index 6d51996..0badcfe 100644 --- a/codex-plonky2-circuits/src/bundle/mod.rs +++ b/codex-plonky2-circuits/src/bundle/mod.rs @@ -30,7 +30,7 @@ impl< const D: usize, H: AlgebraicHasher, > Bundle { - pub fn new(bundle_size: usize, circuit_params: CircuitParams) -> Result<(Self)>{ + pub fn new(bundle_size: usize, circuit_params: CircuitParams) -> Result{ let samp_circ = SampleCircuit::::new(circuit_params.clone()); let (sample_targets, circuit_data) = samp_circ.build_with_standard_config()?; println!("sampling circuit built. Degree bits = {:?}", circuit_data.common.degree_bits()); diff --git a/codex-plonky2-circuits/src/recursion/leaf.rs b/codex-plonky2-circuits/src/recursion/leaf.rs index 890d570..738fd91 100644 --- a/codex-plonky2-circuits/src/recursion/leaf.rs +++ b/codex-plonky2-circuits/src/recursion/leaf.rs @@ -3,7 +3,7 @@ use plonky2::hash::hash_types::{HashOut, RichField}; use plonky2::iop::target::{BoolTarget, Target}; use plonky2::iop::witness::{PartialWitness, WitnessWrite}; use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2::plonk::circuit_data::{CommonCircuitData, VerifierOnlyCircuitData}; +use plonky2::plonk::circuit_data::VerifierCircuitData; use plonky2::plonk::config::{AlgebraicHasher, GenericConfig}; use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget}; use plonky2_field::extension::Extendable; @@ -15,8 +15,7 @@ use crate::recursion::utils::{bucket_count, compute_flag_buckets}; pub const BUCKET_SIZE: usize = 32; -/// recursion leaf circuit - verifies N inner proof -/// N: number of inner proofs +/// recursion leaf circuit - verifies 1 inner proof /// T: total number of sampling proofs #[derive(Clone, Debug)] pub struct LeafCircuit< @@ -24,13 +23,11 @@ pub struct LeafCircuit< const D: usize, C: GenericConfig, H: AlgebraicHasher, - const N: usize, const T: usize, > where >::Hasher: AlgebraicHasher { - inner_common_data: CommonCircuitData, - inner_verifier_data: VerifierOnlyCircuitData, + inner_verifier_data: VerifierCircuitData, phantom_data: PhantomData } @@ -42,9 +39,8 @@ pub struct LeafCircuit< pub struct LeafTargets < const D: usize, >{ - pub inner_proof: Vec>, + pub inner_proof: ProofWithPublicInputsTarget, pub index: Target, // public input - // TODO: change this to vec of size N so that one flag per inner-proof pub flag: BoolTarget, } @@ -54,7 +50,7 @@ pub struct LeafInput< const D: usize, C: GenericConfig, >{ - pub inner_proof: Vec>, + pub inner_proof: ProofWithPublicInputs, pub flag: bool, pub index: usize } @@ -64,17 +60,14 @@ impl< const D: usize, C: GenericConfig, H: AlgebraicHasher, - const N: usize, const T: usize, -> LeafCircuit where +> LeafCircuit where >::Hasher: AlgebraicHasher { pub fn new( - inner_common_data: CommonCircuitData, - inner_verifier_data: VerifierOnlyCircuitData, + inner_verifier_data: VerifierCircuitData, ) -> Self { Self { - inner_common_data, inner_verifier_data, phantom_data: PhantomData::default(), } @@ -87,9 +80,8 @@ impl< const D: usize, C: GenericConfig, H: AlgebraicHasher, - const N: usize, const T: usize, -> Plonky2Circuit for LeafCircuit where +> Plonky2Circuit for LeafCircuit where >::Hasher: AlgebraicHasher { type Targets = LeafTargets; @@ -97,21 +89,15 @@ impl< fn add_targets(&self, builder: &mut CircuitBuilder, register_pi: bool) -> Result> { - let inner_common = self.inner_common_data.clone(); + let inner_common = self.inner_verifier_data.common.clone(); let n_bucket: usize = bucket_count(T); - // the proof virtual targets - let mut pub_input = vec![]; - let mut vir_proofs = vec![]; - for _i in 0..N { - let vir_proof = builder.add_virtual_proof_with_pis(&inner_common); - let inner_pub_input = vir_proof.public_inputs.clone(); - vir_proofs.push(vir_proof); - pub_input.extend_from_slice(&inner_pub_input); - } + // the proof virtual target + let vir_proof = builder.add_virtual_proof_with_pis(&inner_common); + let inner_pub_input = vir_proof.public_inputs.clone(); // hash the public input & make it public - let hash_inner_pub_input = builder.hash_n_to_hash_no_pad::(pub_input); + let hash_inner_pub_input = builder.hash_n_to_hash_no_pad::(inner_pub_input); if register_pi { builder.register_public_inputs(&hash_inner_pub_input.elements); } @@ -123,11 +109,11 @@ impl< } // virtual constant target for the verifier data - let const_verifier_data = builder.constant_verifier_data(&self.inner_verifier_data); + let const_verifier_data = builder.constant_verifier_data(&self.inner_verifier_data.verifier_only); // virtual constant target for dummy verifier data let const_dummy_vd = builder.constant_verifier_data( - &DummyProofGen::::gen_dummy_verifier_data(&self.inner_common_data) + &DummyProofGen::::gen_dummy_verifier_data(&inner_common) ); // index: 0 <= index < T where T = total number of proofs @@ -137,7 +123,7 @@ impl< // Instead of taking flag_buckets as external public inputs, // compute them internally from the index and flag. let computed_flag_buckets = compute_flag_buckets(builder, index, flag, BUCKET_SIZE, n_bucket)?; - // Then, for example, you could register these outputs as part of your public input vector: + // register these outputs as part of your public input vector: if register_pi { builder.register_public_inputs(&computed_flag_buckets); } @@ -145,9 +131,7 @@ impl< // verify the proofs in-circuit based on the // true -> real proof, false -> dummy proof let selected_vd = builder.select_verifier_data(flag.clone(), &const_verifier_data, &const_dummy_vd); - for i in 0..N { - builder.verify_proof::(&vir_proofs[i], &selected_vd, &inner_common); - } + builder.verify_proof::(&vir_proof, &selected_vd, &inner_common); // Make sure we have every gate to match `common_data`. for g in &inner_common.gates { @@ -156,7 +140,7 @@ impl< // return targets let t = LeafTargets { - inner_proof: vir_proofs, + inner_proof: vir_proof, index, flag, }; @@ -169,15 +153,12 @@ impl< targets: &Self::Targets, input: &Self::Input, ) -> Result<()> { - assert_eq!(input.inner_proof.len(), N); - assert!(input.index <= T && input.index >= 0, "given index is not valid"); + assert!(input.index <= T, "given index is not valid"); // assign the proofs - for i in 0..N { - pw.set_proof_with_pis_target(&targets.inner_proof[i], &input.inner_proof[i]) - .map_err(|e| { - CircuitError::ProofTargetAssignmentError("inner-proof".to_string(), e.to_string()) - })?; - } + pw.set_proof_with_pis_target(&targets.inner_proof, &input.inner_proof) + .map_err(|e| { + CircuitError::ProofTargetAssignmentError("inner-proof".to_string(), e.to_string()) + })?; // Assign the global index. pw.set_target(targets.index, F::from_canonical_u64(input.index as u64)) @@ -197,7 +178,7 @@ mod tests { use plonky2::plonk::config::PoseidonGoldilocksConfig; use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::config::GenericConfig; - use plonky2_field::types::{Field, PrimeField64}; + use plonky2_field::types::PrimeField64; use plonky2::plonk::circuit_data::{CircuitConfig, CommonCircuitData}; use plonky2_poseidon2::poseidon2_hash::poseidon2::{Poseidon2, Poseidon2Hash}; @@ -221,17 +202,15 @@ mod tests { // End-to-End test for the entire leaf circuit. #[test] fn test_full_leaf_circuit() -> anyhow::Result<()> { - const N: usize = 1; - // get inner common let common_data = dummy_common_circuit_data(); // Generate a dummy inner proof for the leaf using DummyProofGen let (dummy_inner_proof, vd) = DummyProofGen::::gen_dummy_proof_and_vd_zero_pi(&common_data)?; - let dummy_verifier_data = DummyProofGen::::gen_dummy_verifier_data(&common_data); + // let dummy_verifier_data = DummyProofGen::::gen_dummy_verifier_data(&common_data); // the leaf circuit. - let leaf = LeafCircuit::::new(common_data.clone(), dummy_verifier_data); + let leaf = LeafCircuit::::new(vd.clone()); // Build the leaf circuit. let (targets, circuit_data) = leaf.build_with_standard_config()?; @@ -240,7 +219,7 @@ mod tests { // test leaf input let input = LeafInput { - inner_proof: vec![dummy_inner_proof], + inner_proof: dummy_inner_proof, flag: true, index: 45, }; diff --git a/codex-plonky2-circuits/src/recursion/node.rs b/codex-plonky2-circuits/src/recursion/node.rs index 43d7452..04b7009 100644 --- a/codex-plonky2-circuits/src/recursion/node.rs +++ b/codex-plonky2-circuits/src/recursion/node.rs @@ -3,19 +3,18 @@ use plonky2::hash::hash_types::RichField; use plonky2::iop::target::{BoolTarget, Target}; use plonky2::iop::witness::{PartialWitness, WitnessWrite}; use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2::plonk::circuit_data::{CommonCircuitData, VerifierCircuitTarget, VerifierOnlyCircuitData}; +use plonky2::plonk::circuit_data::{VerifierCircuitData, VerifierCircuitTarget, VerifierOnlyCircuitData}; use plonky2::plonk::config::{AlgebraicHasher, GenericConfig}; use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget}; use plonky2_field::extension::Extendable; use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2; use crate::{error::CircuitError,Result}; use crate::circuit_helper::Plonky2Circuit; -use crate::recursion::leaf::BUCKET_SIZE; use crate::recursion::dummy_gen::DummyProofGen; use crate::recursion::utils::bucket_count; /// recursion node circuit -/// M: number of leaf proofs +/// N: number of leaf proofs /// T: total number of sampling proofs #[derive(Clone, Debug)] pub struct NodeCircuit< @@ -23,13 +22,12 @@ pub struct NodeCircuit< const D: usize, C: GenericConfig, H: AlgebraicHasher, - const M: usize, + const N: usize, const T: usize, > where >::Hasher: AlgebraicHasher { - common_data: CommonCircuitData, - leaf_verifier_data: VerifierOnlyCircuitData, + leaf_verifier_data: VerifierCircuitData, phantom_data: PhantomData } @@ -43,8 +41,8 @@ pub struct NodeCircuit< pub struct NodeTargets< const D: usize, >{ - pub leaf_proofs: Vec>, - pub node_verifier_data: VerifierCircuitTarget, + pub inner_proofs: Vec>, + pub inner_verifier_data: VerifierCircuitTarget, pub condition: BoolTarget, pub index: Target, pub flags: Vec, @@ -56,7 +54,7 @@ pub struct NodeInput< const D: usize, C: GenericConfig, >{ - pub node_proofs: Vec>, + pub inner_proofs: Vec>, pub verifier_only_data: VerifierOnlyCircuitData, pub condition: bool, pub flags: Vec, @@ -68,19 +66,17 @@ impl< const D: usize, C: GenericConfig, H: AlgebraicHasher, - const M: usize, + const N: usize, const T: usize, -> NodeCircuit where +> NodeCircuit where >::Hasher: AlgebraicHasher { pub fn new( - common_data: CommonCircuitData, - leaf_verifier_data: VerifierOnlyCircuitData, + leaf_verifier_data: VerifierCircuitData, ) -> Self { - assert!(M.is_power_of_two(), "M is NOT a power of two"); + assert!(N.is_power_of_two(), "M is NOT a power of two"); Self{ - common_data, leaf_verifier_data, phantom_data:PhantomData::default(), } @@ -93,16 +89,16 @@ impl< const D: usize, C: GenericConfig, H: AlgebraicHasher, - const M: usize, + const N: usize, const T: usize, -> Plonky2Circuit for NodeCircuit where +> Plonky2Circuit for NodeCircuit where >::Hasher: AlgebraicHasher { type Targets = NodeTargets; type Input = NodeInput; fn add_targets(&self, builder: &mut CircuitBuilder, register_pi: bool) -> Result { - let inner_common = self.common_data.clone(); + let inner_common = self.leaf_verifier_data.common.clone(); let zero_target = builder.zero(); // assert public input is of size 8 + 1 (index) + B (flag buckets) @@ -114,7 +110,7 @@ impl< let mut pub_input = vec![]; let mut inner_flag_buckets = vec![]; let mut inner_indexes = vec![]; - for _i in 0..M { + for _i in 0..N { let vir_proof = builder.add_virtual_proof_with_pis(&inner_common); let inner_pub_input = vir_proof.public_inputs.clone(); vir_proofs.push(vir_proof); @@ -133,11 +129,11 @@ impl< let node_verifier_data = builder.add_virtual_verifier_data(inner_common.config.fri_config.cap_height); // virtual target for the verifier data - let const_leaf_verifier_data = builder.constant_verifier_data(&self.leaf_verifier_data); + let const_leaf_verifier_data = builder.constant_verifier_data(&self.leaf_verifier_data.verifier_only); // virtual constant target for dummy verifier data let const_dummy_vd = builder.constant_verifier_data( - &DummyProofGen::::gen_dummy_verifier_data(&self.common_data) + &DummyProofGen::::gen_dummy_verifier_data(&inner_common) ); // register only the node verifier data hash as public input. @@ -158,12 +154,12 @@ impl< let mut flag_buckets: Vec = (0..n_bucket).map(|_i| zero_target.clone()).collect(); // index: 0 <= index < T where T = total number of proofs let index = builder.add_virtual_public_input(); - let flags: Vec = (0..M).map(|_i| builder.add_virtual_bool_target_safe()).collect(); + let flags: Vec = (0..N).map(|_i| builder.add_virtual_bool_target_safe()).collect(); // condition: true -> node, false -> leaf let node_or_leaf_vd = builder.select_verifier_data(condition.clone(), &node_verifier_data, &const_leaf_verifier_data); // verify the proofs in-circuit - M proofs - for i in 0..M { + for i in 0..N { // flag: true -> real, false -> dummy let selected_vd = builder.select_verifier_data(flags[i].clone(), &node_or_leaf_vd, &const_dummy_vd); builder.verify_proof::(&vir_proofs[i], &selected_vd, &inner_common); @@ -172,7 +168,7 @@ impl< // Check flag buckets for dummy inner proofs: // For each inner proof, if its corresponding flag `flags[i]` is false, // then enforce that every bucket in inner_flag_buckets[i] is zero. - for i in 0..M { + for i in 0..N { let not_flag_i = builder.not(flags[i]); let not_flag_val = not_flag_i.target; for j in 0..n_bucket { @@ -184,9 +180,9 @@ impl< } // check inner proof indexes are correct - let m_const = builder.constant(F::from_canonical_u64(M as u64)); + let m_const = builder.constant(F::from_canonical_u64(N as u64)); let mut expected_inner_index = builder.mul(index, m_const); - for i in 0..M { + for i in 0..N { if i > 0 { let i_const = builder.constant(F::from_canonical_u64(i as u64)); expected_inner_index = builder.add(expected_inner_index, i_const); @@ -210,8 +206,8 @@ impl< // return targets let t = NodeTargets { - leaf_proofs: vir_proofs, - node_verifier_data, + inner_proofs: vir_proofs, + inner_verifier_data: node_verifier_data, condition, index, flags, @@ -222,20 +218,20 @@ impl< fn assign_targets(&self, pw: &mut PartialWitness, targets: &Self::Targets, input: &Self::Input) -> Result<()> { // assert size of proofs vec - assert_eq!(input.node_proofs.len(), M); - assert_eq!(input.flags.len(), M); - assert!(input.index <= T && input.index >= 0, "given index is not valid"); + assert_eq!(input.inner_proofs.len(), N); + assert_eq!(input.flags.len(), N); + assert!(input.index <= T, "given index is not valid"); // assign the proofs - for i in 0..M { - pw.set_proof_with_pis_target(&targets.leaf_proofs[i], &input.node_proofs[i]) + for i in 0..N { + pw.set_proof_with_pis_target(&targets.inner_proofs[i], &input.inner_proofs[i]) .map_err(|e| { CircuitError::ProofTargetAssignmentError("inner-proof".to_string(), e.to_string()) })?; } // assign the verifier data - pw.set_verifier_data_target(&targets.node_verifier_data, &input.verifier_only_data) + pw.set_verifier_data_target(&targets.inner_verifier_data, &input.verifier_only_data) .map_err(|e| { CircuitError::VerifierDataTargetAssignmentError(e.to_string()) })?; @@ -248,7 +244,7 @@ impl< pw.set_target(targets.index, F::from_canonical_u64(input.index as u64)) .map_err(|e| CircuitError::TargetAssignmentError(format!("index {}", input.index),e.to_string()))?; // Assign the flags - switch between real & fake proof - for i in 0..M { + for i in 0..N { pw.set_bool_target(targets.flags[i], input.flags[i]) .map_err(|e| CircuitError::TargetAssignmentError(format!("flag {}", input.flags[i]), e.to_string()))?; } @@ -263,10 +259,10 @@ mod tests { use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::config::GenericConfig; use plonky2_field::types::{Field, PrimeField64}; - use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, CommonCircuitData, VerifierCircuitData}; + use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData}; use plonky2_poseidon2::poseidon2_hash::poseidon2::{Poseidon2, Poseidon2Hash}; - use crate::recursion::leaf::{LeafCircuit, LeafInput}; - use crate::recursion::dummy_gen::DummyProofGen; + use crate::recursion::leaf::BUCKET_SIZE; + // For our tests, we define: const D: usize = 2; @@ -322,9 +318,9 @@ mod tests { /// End-to-End test for the entire node circuit. #[test] fn test_full_node_circuit() -> anyhow::Result<()> { - const M: usize = 2; + const N: usize = 2; const B: usize = 4; // bucket size - const T: usize = 2; + const T: usize = 128; let (leaf_data, leaf_pi) = dummy_leaf::(); let leaf_vd = leaf_data.verifier_data(); @@ -332,7 +328,7 @@ mod tests { let indices = vec![0,1]; let leaf_proofs = dummy_leaf_proofs::(leaf_data,leaf_pi,indices); - let node = NodeCircuit::::new(leaf_vd.common.clone(), leaf_vd.verifier_only.clone()); + let node = NodeCircuit::::new(leaf_vd.clone()); // Build the node circuit. let (targets, circuit_data) = node.build_with_standard_config()?; @@ -341,7 +337,7 @@ mod tests { // node input let input = NodeInput { - node_proofs: leaf_proofs, + inner_proofs: leaf_proofs, verifier_only_data: leaf_vd.verifier_only.clone(), condition: false, flags: vec![true, true], diff --git a/codex-plonky2-circuits/src/recursion/tree.rs b/codex-plonky2-circuits/src/recursion/tree.rs index 6654d01..91a785d 100644 --- a/codex-plonky2-circuits/src/recursion/tree.rs +++ b/codex-plonky2-circuits/src/recursion/tree.rs @@ -1,5 +1,5 @@ use std::marker::PhantomData; -use plonky2::hash::hash_types::{HashOut, RichField}; +use plonky2::hash::hash_types::RichField; use plonky2::iop::witness::PartialWitness; use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, CommonCircuitData, VerifierCircuitData, VerifierOnlyCircuitData}; use plonky2::plonk::config::{AlgebraicHasher, GenericConfig}; @@ -13,23 +13,22 @@ use crate::recursion::{leaf::{LeafTargets, LeafCircuit}, node::{NodeTargets, Nod use crate::recursion::compress::{CompressionCircuit, CompressionInput, CompressionTargets}; use crate::recursion::leaf::LeafInput; use crate::recursion::node::NodeInput; +use crate::recursion::utils::get_hash_of_verifier_data; /// tree recursion -/// - `N`: Number of inner-proofs aggregated at the leaf level. -/// - `M`: Number of leaf proofs aggregated at the node level. +/// - `N`: Number of leaf proofs aggregated at the node level. set to 2 for 2-to-1 tree pub struct TreeRecursion< F: RichField + Extendable + Poseidon2, const D: usize, C: GenericConfig, H: AlgebraicHasher, const N: usize, - const M: usize, const T: usize, > where >::Hasher: AlgebraicHasher { - leaf: LeafCircuit, - node: NodeCircuit, + leaf: LeafCircuit, + node: NodeCircuit, compression: CompressionCircuit, leaf_circ_data: CircuitData, node_circ_data: CircuitData, @@ -46,18 +45,15 @@ impl< C: GenericConfig, H: AlgebraicHasher, const N: usize, - const M: usize, const T: usize, -> TreeRecursion where +> TreeRecursion where >::Hasher: AlgebraicHasher { /// build with standard recursion config pub fn build_with_standard_config( - inner_common_data: CommonCircuitData, - inner_verifier_data: VerifierOnlyCircuitData, + inner_verifier_data: VerifierCircuitData, ) -> Result { Self::build( - inner_common_data, inner_verifier_data, CircuitConfig::standard_recursion_config() ) @@ -65,22 +61,20 @@ impl< /// build the tree with given config pub fn build( - inner_common_data: CommonCircuitData, - inner_verifier_data: VerifierOnlyCircuitData, + inner_verifier_data: VerifierCircuitData, config: CircuitConfig, ) -> Result { // build leaf with standard recursion config - let leaf = LeafCircuit::<_,D,_,_,N, T>::new(inner_common_data, inner_verifier_data); + let leaf = LeafCircuit::<_,D,_,_,T>::new(inner_verifier_data); let (leaf_targets, leaf_circ_data) = leaf.build(config.clone())?; println!("leaf circuit size = {:?}", leaf_circ_data.common.degree_bits()); // build node with standard recursion config - let node = NodeCircuit::<_,D,_,_,M, T>::new(leaf_circ_data.common.clone(), leaf_circ_data.verifier_only.clone()); + let node = NodeCircuit::<_,D,_,_,N, T>::new(leaf_circ_data.verifier_data()); let (node_targets, node_circ_data) = node.build(config.clone())?; println!("node circuit size = {:?}", node_circ_data.common.degree_bits()); // compression build - // let node_common = node_circ_data.common.clone(); let compression_circ = CompressionCircuit::new(node_circ_data.verifier_data()); let (compression_targets, compression_circ_data) = compression_circ.build(config.clone())?; println!("compress circuit size = {:?}", compression_circ_data.common.degree_bits()); @@ -115,8 +109,8 @@ impl< self.node_circ_data.verifier_data() } - pub fn prove_bundle(bundle: Bundle){ - + pub fn prove_bundle(_bundle: Bundle){ + todo!() } pub fn prove_tree_and_compress( @@ -170,9 +164,9 @@ impl< let mut leaf_proofs = vec![]; - for (i, proofs) in proofs_with_pi.chunks(N).enumerate(){ + for (i, proof) in proofs_with_pi.iter().enumerate(){ let leaf_input = LeafInput{ - inner_proof: proofs.to_vec(), + inner_proof: proof.clone(), flag: true, index: i, }; @@ -205,15 +199,15 @@ impl< let condition = if level == 0 {false} else {true}; - for (i, chunk) in proofs_with_pi.chunks(M).enumerate() { + for (i, chunk) in proofs_with_pi.chunks(N).enumerate() { let mut inner_pw = PartialWitness::new(); let node_input = NodeInput{ - node_proofs: chunk.to_vec().clone(), + inner_proofs: chunk.to_vec().clone(), verifier_only_data: verifier_only_data.clone(), condition, - flags: [true; M].to_vec(), + flags: [true; N].to_vec(), index: i, }; @@ -276,18 +270,14 @@ impl< let node_hash = get_hash_of_verifier_data::(&self.node_circ_data.verifier_data()); let mut pub_in_hashes = vec![]; - for pub_in in inner_public_input.chunks(N){ - let pub_in_flat: Vec = pub_in - .iter() - .flat_map(|v| v.iter().cloned()) - .collect(); - let hash = H::hash_no_pad(&pub_in_flat); + for pub_in in inner_public_input{ + let hash = H::hash_no_pad(&pub_in); pub_in_hashes.push(hash); } while pub_in_hashes.len() > 1 { let mut next_level_pi_hashes = Vec::new(); - for pi_chunk in pub_in_hashes.chunks(M) { + for pi_chunk in pub_in_hashes.chunks(N) { // collect field elements let pi_chunk_f: Vec = pi_chunk.iter() .flat_map(|h| h.elements.iter().cloned()) @@ -308,27 +298,6 @@ impl< } } -/// helper fn to generate hash of verifier data -pub fn get_hash_of_verifier_data< - F: RichField + Extendable + Poseidon2, - const D: usize, - C: GenericConfig, - H: AlgebraicHasher, ->(verifier_data: &VerifierCircuitData) -> HashOut where - >::Hasher: AlgebraicHasher -{ - let mut vd = vec![]; - let digest: &HashOut = &verifier_data.verifier_only.circuit_digest; - let caps = &verifier_data.verifier_only.constants_sigmas_cap; - vd.extend_from_slice(&digest.elements); - for i in 0..verifier_data.common.config.fri_config.num_cap_elements() { - let cap_hash = caps.0[i] as HashOut; - vd.extend_from_slice(&cap_hash.elements); - } - - H::hash_no_pad(&vd) -} - #[cfg(test)] mod tests { use plonky2::gates::noop::NoopGate; @@ -350,7 +319,7 @@ mod tests { fn dummy_proofs() -> (CircuitData, Vec>) { let config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::::new(config); - for _ in 0..8192 { + for _ in 0..(4096+10) { builder.add_gate(NoopGate, vec![]); } // Add one virtual public input so that the circuit has minimal structure. @@ -367,13 +336,12 @@ mod tests { // End-to-End test for the entire Tree circuit. #[test] fn test_full_tree_circuit() -> anyhow::Result<()> { - const N: usize = 1; - const M: usize = 2; - const T: usize = 4; + const N: usize = 2; + const T: usize = 128; let (data, proofs) = dummy_proofs::(); - let mut tree = TreeRecursion::::build_with_standard_config(data.common.clone(), data.verifier_only.clone())?; + let mut tree = TreeRecursion::::build_with_standard_config(data.verifier_data())?; // aggregate - no compression let root = tree.prove_tree(&proofs)?; diff --git a/codex-plonky2-circuits/src/recursion/utils.rs b/codex-plonky2-circuits/src/recursion/utils.rs index 8b0d840..e090b4b 100644 --- a/codex-plonky2-circuits/src/recursion/utils.rs +++ b/codex-plonky2-circuits/src/recursion/utils.rs @@ -1,9 +1,11 @@ -use plonky2::hash::hash_types::RichField; +use plonky2::hash::hash_types::{HashOut, RichField}; use plonky2::iop::target::{BoolTarget, Target}; use plonky2::plonk::circuit_builder::CircuitBuilder; +use plonky2::plonk::circuit_data::VerifierCircuitData; +use plonky2::plonk::config::{AlgebraicHasher, GenericConfig}; use plonky2_field::extension::Extendable; use plonky2_poseidon2::Poseidon2; -use crate::recursion::leaf::{BUCKET_SIZE, LeafCircuit}; +use crate::recursion::leaf::BUCKET_SIZE; /// Splits a target `index` which is known to lie in the range [0, T) /// where T = bucket_size * num_buckets @@ -135,6 +137,26 @@ pub fn bucket_count(t: usize) -> usize { (t + BUCKET_SIZE -1) / BUCKET_SIZE } +/// helper fn to generate hash of verifier data +pub fn get_hash_of_verifier_data< + F: RichField + Extendable + Poseidon2, + const D: usize, + C: GenericConfig, + H: AlgebraicHasher, +>(verifier_data: &VerifierCircuitData) -> HashOut where + >::Hasher: AlgebraicHasher +{ + let mut vd = vec![]; + let digest: &HashOut = &verifier_data.verifier_only.circuit_digest; + let caps = &verifier_data.verifier_only.constants_sigmas_cap; + vd.extend_from_slice(&digest.elements); + for i in 0..verifier_data.common.config.fri_config.num_cap_elements() { + let cap_hash = caps.0[i] as HashOut; + vd.extend_from_slice(&cap_hash.elements); + } + + H::hash_no_pad(&vd) +} #[cfg(test)] mod tests {