From 76374f084b2d9a8ec670569f26f3ee32fc2385b7 Mon Sep 17 00:00:00 2001 From: M Alghazwi Date: Tue, 8 Apr 2025 12:02:22 +0200 Subject: [PATCH] use the circuit helper, clean up, and small refactoring. --- .../src/circuit_helper/mod.rs | 3 +- .../src/recursion/uniform/compress.rs | 64 ++++++++------- .../src/recursion/uniform/leaf.rs | 68 +++++++++------- .../src/recursion/uniform/node.rs | 77 +++++++++--------- .../src/recursion/uniform/pi_verifier.rs | 59 ++++++++++---- .../src/recursion/uniform/tree.rs | 80 +++++++++++-------- 6 files changed, 206 insertions(+), 145 deletions(-) diff --git a/codex-plonky2-circuits/src/circuit_helper/mod.rs b/codex-plonky2-circuits/src/circuit_helper/mod.rs index e12c947..d16aac4 100644 --- a/codex-plonky2-circuits/src/circuit_helper/mod.rs +++ b/codex-plonky2-circuits/src/circuit_helper/mod.rs @@ -33,6 +33,7 @@ pub trait Plonky2Circuit< ) -> Result<(Self::Targets,CircuitData)>{ let mut builder = CircuitBuilder::::new(circuit_config); + // NOTE: register public input is set to TRUE as default. let targets = self.add_targets(&mut builder, true)?; Ok((targets,builder.build::())) @@ -80,7 +81,7 @@ pub trait Plonky2Circuit< &self, targets: &Self::Targets, input: &Self::Input, - prover_circuit_data: ProverCircuitData + prover_circuit_data: &ProverCircuitData )-> Result>{ let mut pw = PartialWitness::new(); self.assign_targets(&mut pw, targets, input)?; diff --git a/codex-plonky2-circuits/src/recursion/uniform/compress.rs b/codex-plonky2-circuits/src/recursion/uniform/compress.rs index 727062d..4c38e8c 100644 --- a/codex-plonky2-circuits/src/recursion/uniform/compress.rs +++ b/codex-plonky2-circuits/src/recursion/uniform/compress.rs @@ -2,14 +2,16 @@ use std::marker::PhantomData; use plonky2::hash::hash_types::{HashOutTarget, RichField}; use plonky2::iop::witness::{PartialWitness, WitnessWrite}; use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, CommonCircuitData, VerifierOnlyCircuitData}; +use plonky2::plonk::circuit_data::{CommonCircuitData, 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; -/// recursion compression circuit - verifies 1 inner proof +/// recursion compression circuit +/// verifies 1 inner proof and as result should shrink it #[derive(Clone, Debug)] pub struct CompressionCircuit< F: RichField + Extendable + Poseidon2, @@ -31,6 +33,15 @@ pub struct CompressionTargets< pub inner_proof: ProofWithPublicInputsTarget, } +#[derive(Clone, Debug)] +pub struct CompressionInput< + F: RichField + Extendable + Poseidon2, + const D: usize, + C: GenericConfig, +>{ + pub inner_proof: ProofWithPublicInputs +} + impl< F: RichField + Extendable + Poseidon2, const D: usize, @@ -50,9 +61,20 @@ impl< } } - /// build the compression circuit - pub fn build(&self, builder: &mut CircuitBuilder) -> Result> { +} +impl< + F: RichField + Extendable + Poseidon2, + const D: usize, + C: GenericConfig, + H: AlgebraicHasher, +> Plonky2Circuit for CompressionCircuit where + >::Hasher: AlgebraicHasher +{ + type Targets = CompressionTargets; + type Input = CompressionInput; + + fn add_targets(&self, builder: &mut CircuitBuilder, register_pi: bool) -> Result { let inner_common = self.inner_common_data.clone(); // the proof virtual targets @@ -61,7 +83,9 @@ impl< // take the public input from inner proof & make it public assert_eq!(inner_pub_input.len(), 8); - builder.register_public_inputs(&inner_pub_input[0..4]); + if register_pi { + builder.register_public_inputs(&inner_pub_input[0..4]); + } // constant target for the verifier data let const_verifier_data = builder.constant_verifier_data(&self.inner_verifier_data); @@ -78,7 +102,9 @@ impl< // make sure the VerifierData we use is the same as the tree root hash of the VerifierData builder.connect_hashes(hash_inner_vd_pub_input,HashOutTarget::from_vec(inner_pub_input[4..8].to_vec())); - builder.register_public_inputs(&hash_inner_vd_pub_input.elements); + if register_pi { + builder.register_public_inputs(&hash_inner_vd_pub_input.elements); + } // verify the proofs in-circuit builder.verify_proof::(&vir_proof, &const_verifier_data, &inner_common); @@ -88,39 +114,17 @@ impl< inner_proof: vir_proof, }; Ok(t) - } - /// assign the compression targets with given input - pub fn assign_targets( - &self, pw: &mut PartialWitness, - targets: &CompressionTargets, - inner_proof: ProofWithPublicInputs, - ) -> Result<()> { + fn assign_targets(&self, pw: &mut PartialWitness, targets: &Self::Targets, input: &Self::Input) -> Result<()> { // assign the proof - pw.set_proof_with_pis_target(&targets.inner_proof, &inner_proof) + pw.set_proof_with_pis_target(&targets.inner_proof, &input.inner_proof) .map_err(|e| { CircuitError::ProofTargetAssignmentError("inner-proof".to_string(), e.to_string()) })?; Ok(()) } - - /// returns the compression circuit data - pub fn get_circuit_data (&self) -> Result> - where - >::Hasher: AlgebraicHasher - { - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config.clone()); - - self.build(&mut builder)?; - - let circ_data = builder.build::(); - - Ok(circ_data) - } - } diff --git a/codex-plonky2-circuits/src/recursion/uniform/leaf.rs b/codex-plonky2-circuits/src/recursion/uniform/leaf.rs index b7f940f..111f005 100644 --- a/codex-plonky2-circuits/src/recursion/uniform/leaf.rs +++ b/codex-plonky2-circuits/src/recursion/uniform/leaf.rs @@ -2,12 +2,13 @@ use std::marker::PhantomData; use plonky2::hash::hash_types::{HashOut, RichField}; use plonky2::iop::witness::{PartialWitness, WitnessWrite}; use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, CommonCircuitData, VerifierOnlyCircuitData}; +use plonky2::plonk::circuit_data::{CommonCircuitData, 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; /// recursion leaf circuit - verifies N inner proof #[derive(Clone, Debug)] @@ -32,6 +33,15 @@ pub struct LeafTargets < pub inner_proof: Vec>, } +#[derive(Clone, Debug)] +pub struct LeafInput< + F: RichField + Extendable + Poseidon2, + const D: usize, + C: GenericConfig, +>{ + pub inner_proof: Vec> +} + impl< F: RichField + Extendable + Poseidon2, const D: usize, @@ -42,18 +52,30 @@ impl< >::Hasher: AlgebraicHasher { pub fn new( - inner_common_data: CommonCircuitData, + inner_common_data: CommonCircuitData, inner_verifier_data: VerifierOnlyCircuitData, ) -> Self { - Self{ + Self { inner_common_data, inner_verifier_data, - phantom_data:PhantomData::default(), + phantom_data: PhantomData::default(), } } +} - /// build the leaf circuit - pub fn build(&self, builder: &mut CircuitBuilder) -> Result> { +impl< + F: RichField + Extendable + Poseidon2, + const D: usize, + C: GenericConfig, + H: AlgebraicHasher, + const N: usize, +> Plonky2Circuit for LeafCircuit where + >::Hasher: AlgebraicHasher +{ + type Targets = LeafTargets; + type Input = LeafInput; + + fn add_targets(&self, builder: &mut CircuitBuilder, register_pi: bool) -> Result> { let inner_common = self.inner_common_data.clone(); @@ -69,11 +91,15 @@ impl< // hash the public input & make it public let hash_inner_pub_input = builder.hash_n_to_hash_no_pad::(pub_input); - builder.register_public_inputs(&hash_inner_pub_input.elements); + if register_pi { + builder.register_public_inputs(&hash_inner_pub_input.elements); + } // pad the public input with constants so that it shares the same structure as the node let zero_hash = builder.constant_hash(HashOut::::default()); - builder.register_public_inputs(&zero_hash.elements); + if register_pi { + builder.register_public_inputs(&zero_hash.elements); + } // virtual constant target for the verifier data let const_verifier_data = builder.constant_verifier_data(&self.inner_verifier_data); @@ -91,16 +117,15 @@ impl< } - /// assign the leaf targets with given input - pub fn assign_targets( + fn assign_targets( &self, pw: &mut PartialWitness, - targets: &LeafTargets, - inner_proof: &[ProofWithPublicInputs], + targets: &Self::Targets, + input: &Self::Input, ) -> Result<()> { - assert_eq!(inner_proof.len(), N); + assert_eq!(input.inner_proof.len(), N); // assign the proofs for i in 0..N { - pw.set_proof_with_pis_target(&targets.inner_proof[i], &inner_proof[i]) + 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()) })?; @@ -109,21 +134,6 @@ impl< Ok(()) } - /// returns the leaf circuit data - pub fn get_circuit_data (&self) -> Result> - where - >::Hasher: AlgebraicHasher - { - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config.clone()); - - self.build(&mut builder)?; - - let circ_data = builder.build::(); - - Ok(circ_data) - } - } diff --git a/codex-plonky2-circuits/src/recursion/uniform/node.rs b/codex-plonky2-circuits/src/recursion/uniform/node.rs index b3d4518..445ba62 100644 --- a/codex-plonky2-circuits/src/recursion/uniform/node.rs +++ b/codex-plonky2-circuits/src/recursion/uniform/node.rs @@ -3,13 +3,13 @@ use plonky2::hash::hash_types::RichField; use plonky2::iop::target::BoolTarget; use plonky2::iop::witness::{PartialWitness, WitnessWrite}; use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, CommonCircuitData, VerifierCircuitTarget, VerifierOnlyCircuitData}; +use plonky2::plonk::circuit_data::{CommonCircuitData, 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::circuits::utils::vec_to_array; +use crate::circuit_helper::Plonky2Circuit; /// recursion node circuit - verifies M leaf proofs #[derive(Clone, Debug)] @@ -36,6 +36,17 @@ pub struct NodeTargets< pub condition: BoolTarget, } +#[derive(Clone, Debug)] +pub struct NodeInput< + F: RichField + Extendable + Poseidon2, + const D: usize, + C: GenericConfig, +>{ + pub node_proofs: Vec>, + pub verifier_only_data: VerifierOnlyCircuitData, + pub condition: bool, +} + impl< F: RichField + Extendable + Poseidon2, const D: usize, @@ -57,9 +68,21 @@ impl< } } - /// build the leaf circuit - pub fn build(&self, builder: &mut CircuitBuilder) -> Result> { +} +impl< + F: RichField + Extendable + Poseidon2, + const D: usize, + C: GenericConfig, + H: AlgebraicHasher, + const M: usize, +> 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(); // assert public input is of size 8 - 2 hashout @@ -77,7 +100,9 @@ impl< // hash the public input & make it public let hash_inner_pub_input = builder.hash_n_to_hash_no_pad::(pub_input); - builder.register_public_inputs(&hash_inner_pub_input.elements); + if register_pi{ + builder.register_public_inputs(&hash_inner_pub_input.elements); + } // virtual target for the verifier data let node_verifier_data = builder.add_virtual_verifier_data(inner_common.config.fri_config.cap_height); @@ -92,7 +117,9 @@ impl< vd_pub_input.extend_from_slice(&node_verifier_data.constants_sigmas_cap.0[i].elements); } let vd_hash = builder.hash_n_to_hash_no_pad::(vd_pub_input); - builder.register_public_inputs(&vd_hash.elements); + if register_pi { + builder.register_public_inputs(&vd_hash.elements); + } // condition for switching between node and leaf let condition = builder.add_virtual_bool_target_safe(); @@ -102,7 +129,7 @@ impl< // verify the proofs in-circuit - M proofs for i in 0..M { - builder.verify_proof::(&vir_proofs[i], &selected_vd, &inner_common); + builder.verify_proof::(&vir_proofs[i], &selected_vd, &inner_common); } // Make sure we have every gate to match `common_data`. @@ -110,8 +137,6 @@ impl< builder.add_gate_to_gate_set(g.clone()); } - // let proofs = vec_to_array::<2, ProofWithPublicInputsTarget>(vir_proofs)?; - // return targets let t = NodeTargets { leaf_proofs: vir_proofs, @@ -119,56 +144,32 @@ impl< condition, }; Ok(t) - } - /// assign the leaf targets with given input - pub fn assign_targets( - &self, pw: &mut PartialWitness, - targets: &NodeTargets, - node_proofs: &[ProofWithPublicInputs], - verifier_only_data: &VerifierOnlyCircuitData, - condition: bool, - ) -> Result<()> { + fn assign_targets(&self, pw: &mut PartialWitness, targets: &Self::Targets, input: &Self::Input) -> Result<()> { // assert size of proofs vec - assert_eq!(node_proofs.len(), M); + assert_eq!(input.node_proofs.len(), M); // assign the proofs for i in 0..M { - pw.set_proof_with_pis_target(&targets.leaf_proofs[i], &node_proofs[i]) + pw.set_proof_with_pis_target(&targets.leaf_proofs[i], &input.node_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, &verifier_only_data) + pw.set_verifier_data_target(&targets.node_verifier_data, &input.verifier_only_data) .map_err(|e| { CircuitError::VerifierDataTargetAssignmentError(e.to_string()) })?; // assign the condition - pw.set_bool_target(targets.condition, condition) + pw.set_bool_target(targets.condition, input.condition) .map_err(|e| CircuitError::BoolTargetAssignmentError("condition".to_string(), e.to_string()))?; Ok(()) } - - /// returns the leaf circuit data - pub fn get_circuit_data (&self) -> Result> - where - >::Hasher: AlgebraicHasher - { - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config.clone()); - - self.build(&mut builder)?; - - let circ_data = builder.build::(); - - Ok(circ_data) - } - } diff --git a/codex-plonky2-circuits/src/recursion/uniform/pi_verifier.rs b/codex-plonky2-circuits/src/recursion/uniform/pi_verifier.rs index bea8126..790f5c2 100644 --- a/codex-plonky2-circuits/src/recursion/uniform/pi_verifier.rs +++ b/codex-plonky2-circuits/src/recursion/uniform/pi_verifier.rs @@ -9,6 +9,7 @@ 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; /// A circuit that verifies the aggregated public inputs from inner circuits. /// @@ -16,6 +17,7 @@ use crate::{error::CircuitError, Result}; /// - `M`: Number of leaf proofs aggregated at the node level. /// - `T`: Total Number of inner-proofs. /// - `K`: Number of public input field elements per inner-proof (sampling proof). +#[derive(Clone, Debug)] pub struct PublicInputVerificationCircuit< F: RichField + Extendable + Poseidon2, const D: usize, @@ -36,11 +38,25 @@ pub struct PublicInputVerificationCircuit< /// Holds the virtual targets for the circuit. /// - `inner_proof`: the proof to be verified and contains the public input to be verified. /// - `inner_pub_inputs`: A nested vector of targets with dimensions T×K. +#[derive(Clone, Debug)] pub struct PublicInputVerificationTargets { pub inner_proof: ProofWithPublicInputsTarget, pub inner_pub_inputs: Vec>, } +/// input to the circuit for public input verification +/// - `inner_proof`: The tree root proof with 2 hash digests (8 Goldilocks field elements) public inputs [pi_hash, vd_hash]. +/// - `inner_pub_inputs_vals`: T×K public input values from inner proofs. +#[derive(Clone, Debug)] +pub struct PublicInputVerificationInput< + F: RichField + Extendable + Poseidon2, + const D: usize, + C: GenericConfig, +>{ + pub inner_proof: ProofWithPublicInputs, + pub inner_pub_inputs_vals: Vec>, +} + impl PublicInputVerificationCircuit where @@ -64,12 +80,23 @@ PublicInputVerificationCircuit phantom: PhantomData, } } +} +impl +Plonky2Circuit for PublicInputVerificationCircuit + where + F: RichField + Extendable + Poseidon2, + C: GenericConfig, + H: AlgebraicHasher, + >::Hasher: AlgebraicHasher, +{ + type Targets = PublicInputVerificationTargets; + type Input = PublicInputVerificationInput; /// Builds the circuit by: /// 1. Verifies a proof target with 8 public inputs (the final [pi_hash, vd_hash]). /// 2. verifies correct tree hashing of all T×K targets to represent all inner public inputs. /// 3. verifies correct node_verifier_date used is the same as in public input (last 4 field elements). - pub fn build(&self, builder: &mut CircuitBuilder) -> Result> { + fn add_targets(&self, builder: &mut CircuitBuilder, register_pi: bool) -> Result> { // Add a virtual proof with 8 public inputs. This is the final root proof whose // public inputs we want to check in-circuit. let inner_proof = builder.add_virtual_proof_with_pis(&self.node_common_data); @@ -85,7 +112,11 @@ PublicInputVerificationCircuit for _ in 0..T { let mut row = Vec::with_capacity(K); for _ in 0..K { - row.push(builder.add_virtual_public_input()); // public input + if register_pi { + row.push(builder.add_virtual_public_input()); // public input + } else{ + row.push(builder.add_virtual_target()); + } } inner_pub_inputs.push(row); } @@ -115,7 +146,9 @@ PublicInputVerificationCircuit let node_hash_t = builder.hash_n_to_hash_no_pad::(node_vd_input_t); // make sure the VerifierData we use is the same as the tree root hash of the VerifierData builder.connect_hashes(node_hash_t,HashOutTarget::from_vec(node_vd_hash_t.to_vec())); - builder.register_public_inputs(&node_hash_t.elements); // public input + if register_pi { + builder.register_public_inputs(&node_hash_t.elements); // public input + } let mut pub_in_hashes_t = Vec::new(); @@ -174,31 +207,27 @@ PublicInputVerificationCircuit }) } - /// Assigns witness values to the targets. - /// - `inner_proof`: The tree root proof with 8 public inputs [pi_hash, vd_hash]. - /// - `inner_pub_inputs_vals`: T×K public input values from inner proofs. - pub fn assign_targets( + fn assign_targets( &self, pw: &mut PartialWitness, - targets: &PublicInputVerificationTargets, - inner_proof: ProofWithPublicInputs, - inner_pub_inputs_vals: Vec>, + targets: &Self::Targets, + input: &Self::Input, ) -> Result<()> { // Assign the final proof - it should have 8 public inputs - pw.set_proof_with_pis_target(&targets.inner_proof, &inner_proof) + pw.set_proof_with_pis_target(&targets.inner_proof, &input.inner_proof) .map_err(|e| { CircuitError::ProofTargetAssignmentError("final-proof".to_string(), e.to_string()) })?; // Assign T×K inner public inputs - if inner_pub_inputs_vals.len() != T { + if input.inner_pub_inputs_vals.len() != T { return Err(CircuitError::InvalidArgument(format!( "Expected T={} rows of inner_pub_inputs_vals, got {}", T, - inner_pub_inputs_vals.len() + input.inner_pub_inputs_vals.len() ))); } - for (i, row_vals) in inner_pub_inputs_vals.into_iter().enumerate() { + for (i, row_vals) in input.inner_pub_inputs_vals.iter().enumerate() { if row_vals.len() != K { return Err(CircuitError::InvalidArgument(format!( "Expected K={} values in row {}, got {}", @@ -207,7 +236,7 @@ PublicInputVerificationCircuit row_vals.len() ))); } - for (j, val) in row_vals.into_iter().enumerate() { + for (j, &val) in row_vals.into_iter().enumerate() { pw.set_target(targets.inner_pub_inputs[i][j], val).map_err(|e| { CircuitError::TargetAssignmentError(format!("inner public input index [{}][{}]", i,j), e.to_string()) })?; diff --git a/codex-plonky2-circuits/src/recursion/uniform/tree.rs b/codex-plonky2-circuits/src/recursion/uniform/tree.rs index 0997cb7..c265cd8 100644 --- a/codex-plonky2-circuits/src/recursion/uniform/tree.rs +++ b/codex-plonky2-circuits/src/recursion/uniform/tree.rs @@ -1,17 +1,21 @@ use std::marker::PhantomData; use plonky2::hash::hash_types::{HashOut, RichField}; use plonky2::iop::witness::PartialWitness; -use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, CommonCircuitData, VerifierCircuitData, VerifierOnlyCircuitData}; use plonky2::plonk::config::{AlgebraicHasher, GenericConfig}; use plonky2::plonk::proof::ProofWithPublicInputs; use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2; use plonky2_field::extension::Extendable; use crate::{error::CircuitError, Result}; +use crate::circuit_helper::Plonky2Circuit; use crate::recursion::uniform::{leaf::{LeafTargets,LeafCircuit},node::{NodeTargets,NodeCircuit}}; -use crate::recursion::uniform::compress::{CompressionCircuit, CompressionTargets}; +use crate::recursion::uniform::compress::{CompressionCircuit, CompressionInput, CompressionTargets}; +use crate::recursion::uniform::leaf::LeafInput; +use crate::recursion::uniform::node::NodeInput; /// tree recursion +/// - `N`: Number of inner-proofs aggregated at the leaf level. +/// - `M`: Number of leaf proofs aggregated at the node level. pub struct TreeRecursion< F: RichField + Extendable + Poseidon2, const D: usize, @@ -31,7 +35,7 @@ pub struct TreeRecursion< leaf_targets: LeafTargets, node_targets: NodeTargets, compression_targets: CompressionTargets, - phantom_data: PhantomData<(H)> + phantom_data: PhantomData } impl< @@ -44,36 +48,38 @@ impl< > TreeRecursion where >::Hasher: AlgebraicHasher { - - pub fn build( + /// build with standard recursion config + pub fn build_with_standard_config( inner_common_data: CommonCircuitData, inner_verifier_data: VerifierOnlyCircuitData, ) -> Result { - // build leaf with standard recursion config - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); + Self::build( + inner_common_data, + inner_verifier_data, + CircuitConfig::standard_recursion_config() + ) + } - let leaf = LeafCircuit::<_,D,_,_,N>::new(inner_common_data.clone(), inner_verifier_data.clone()); - let leaf_targets = leaf.build(&mut builder)?; - let leaf_circ_data = builder.build::(); + /// build the tree with given config + pub fn build( + inner_common_data: CommonCircuitData, + inner_verifier_data: VerifierOnlyCircuitData, + config: CircuitConfig, + ) -> Result { + // build leaf with standard recursion config + let leaf = LeafCircuit::<_,D,_,_,N>::new(inner_common_data, 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 config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); - let node = NodeCircuit::<_,D,_,_,M>::new(leaf_circ_data.common.clone(), leaf_circ_data.verifier_only.clone()); - let node_targets = node.build(&mut builder)?; - let node_circ_data = builder.build::(); + let (node_targets, node_circ_data) = node.build(config.clone())?; // println!("node circuit size = {:?}", node_circ_data.common.degree_bits()); // compression build - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); let node_common = node_circ_data.common.clone(); let compression_circ = CompressionCircuit::new(node_common, node_circ_data.verifier_only.clone()); - let compression_targets = compression_circ.build(&mut builder)?; - let compression_circ_data = builder.build::(); + let (compression_targets, compression_circ_data) = compression_circ.build(config.clone())?; // println!("compress circuit size = {:?}", compression_circ_data.common.degree_bits()); Ok(Self{ @@ -109,12 +115,16 @@ impl< pub fn prove_tree_and_compress( &mut self, proofs_with_pi: &[ProofWithPublicInputs], - ) -> Result<(ProofWithPublicInputs)> + ) -> Result> { let proof = self.prove_tree(proofs_with_pi)?; let mut pw = PartialWitness::::new(); - self.compression.assign_targets(&mut pw, &self.compression_targets, proof)?; + self.compression.assign_targets( + &mut pw, + &self.compression_targets, + &CompressionInput{ inner_proof: proof}, + )?; self.compression_circ_data.prove(pw).map_err( |e| CircuitError::InvalidProofError(e.to_string()) @@ -125,7 +135,7 @@ impl< ( &mut self, proofs_with_pi: &[ProofWithPublicInputs], - ) -> Result<(ProofWithPublicInputs)> + ) -> Result> { if proofs_with_pi.len() % 2 != 0 { return @@ -135,7 +145,7 @@ impl< } // process leaves let leaf_proofs = self.get_leaf_proofs( - proofs_with_pi, + &proofs_with_pi, )?; // process nodes @@ -149,14 +159,18 @@ impl< ( &mut self, proofs_with_pi: &[ProofWithPublicInputs], - ) -> Result<(Vec>)> { + ) -> Result>> { let mut leaf_proofs = vec![]; - for proof in proofs_with_pi.chunks(N){ + for proofs in proofs_with_pi.chunks(N){ + let leaf_input = LeafInput{ + inner_proof: proofs.to_vec(), + }; + let mut pw = PartialWitness::::new(); - self.leaf.assign_targets(&mut pw,&self.leaf_targets,proof)?; + self.leaf.assign_targets(&mut pw,&self.leaf_targets,&leaf_input)?; let proof = self.leaf_circ_data.prove(pw).unwrap(); leaf_proofs.push(proof); } @@ -186,12 +200,16 @@ impl< let mut inner_pw = PartialWitness::new(); + let node_input = NodeInput{ + node_proofs: chunk.to_vec().clone(), + verifier_only_data: verifier_only_data.clone(), + condition, + }; + self.node.assign_targets( &mut inner_pw, &self.node_targets, - chunk, - verifier_only_data, - condition + &node_input )?; let proof = self.node_circ_data.prove(inner_pw) @@ -256,7 +274,6 @@ impl< pub_in_hashes.push(hash); } - let mut level = 0; while pub_in_hashes.len() > 1 { let mut next_level_pi_hashes = Vec::new(); for pi_chunk in pub_in_hashes.chunks(M) { @@ -269,7 +286,6 @@ impl< next_level_pi_hashes.push(pi_hash); } pub_in_hashes = next_level_pi_hashes; - level +=1; } //check expected hash