diff --git a/codex-plonky2-circuits/src/recursion/circuits/leaf_circuit.rs b/codex-plonky2-circuits/src/recursion/circuits/leaf_circuit.rs index 17bd06d..0a2e4ef 100644 --- a/codex-plonky2-circuits/src/recursion/circuits/leaf_circuit.rs +++ b/codex-plonky2-circuits/src/recursion/circuits/leaf_circuit.rs @@ -141,7 +141,7 @@ impl< >::Hasher: AlgebraicHasher { let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); + let mut builder = CircuitBuilder::::new(config.clone()); self.build::(&mut builder)?; diff --git a/codex-plonky2-circuits/src/recursion/cyclic/mod.rs b/codex-plonky2-circuits/src/recursion/cyclic/mod.rs index 70ad20f..25be599 100644 --- a/codex-plonky2-circuits/src/recursion/cyclic/mod.rs +++ b/codex-plonky2-circuits/src/recursion/cyclic/mod.rs @@ -2,7 +2,6 @@ // and run the inner circuit -> resulting in one proof that again can be fed // into another cyclic circle. -use hashbrown::HashMap; use plonky2::hash::hash_types::{HashOutTarget, RichField}; use plonky2::iop::target::{BoolTarget}; use plonky2::iop::witness::{PartialWitness, WitnessWrite}; @@ -10,14 +9,14 @@ use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, CommonCircuitData, VerifierCircuitTarget}; use plonky2::plonk::config::{AlgebraicHasher, GenericConfig}; use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget}; -use plonky2::recursion::dummy_circuit::cyclic_base_proof; use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2; use crate::recursion::circuits::inner_circuit::InnerCircuit; use plonky2::gates::noop::NoopGate; -use plonky2::recursion::cyclic_recursion::check_cyclic_proof_verifier_data; use plonky2_field::extension::Extendable; use crate::circuits::utils::select_hash; use crate::error::CircuitError; +use crate::recursion::utils::conditional_verifier::{dummy_circuit}; +use crate::recursion::utils::dummy_gen::DummyProofGen; use crate::Result; /// cyclic circuit struct @@ -80,7 +79,9 @@ impl< // the hash of the public input let pub_input_hash = builder.add_virtual_hash_public_input(); // verifier data for inner proofs - let verifier_data_target = builder.add_verifier_data_public_inputs(); + // TODO: make verifier data public + // let verifier_data_target = builder.add_verifier_data_public_inputs(); + let verifier_data_target = builder.add_virtual_verifier_data(builder.config.fri_config.cap_height); // common data should have same num of public input as inner proofs common_data.num_public_inputs = builder.num_public_inputs(); @@ -107,11 +108,7 @@ impl< builder.connect_hashes(pub_input_hash,outer_pi_hash); // verify proof in-circuit - builder.conditionally_verify_cyclic_proof_or_dummy::( - condition, - &inner_cyclic_proof_with_pis, - &common_data, - ).map_err(|e| CircuitError::ConditionalVerificationError(e.to_string()))?; + builder.verify_proof::(&inner_cyclic_proof_with_pis, &verifier_data_target, &common_data); // build the cyclic circuit let cyclic_circuit_data = builder.build::(); @@ -159,14 +156,17 @@ impl< )?; pw.set_proof_with_pis_target::( &cyc_targets.inner_cyclic_proof_with_pis, - &cyclic_base_proof( + &DummyProofGen::::get_dummy_node_proof( common_data, &circ_data.verifier_only, - HashMap::new(), ), ).map_err(|e| CircuitError::ProofTargetAssignmentError("cyclic proof".to_string(),e.to_string()), )?; + // assign verifier data + let dummy_ver = dummy_circuit::(common_data).verifier_only; + pw.set_verifier_data_target(&cyc_targets.verifier_data, &dummy_ver) + .map_err(|e| CircuitError::VerifierDataTargetAssignmentError(e.to_string()))?; }else{ // else add last proof pw.set_bool_target(cyc_targets.condition, true) .map_err(|e| @@ -182,23 +182,15 @@ impl< .map_err(|e| CircuitError::ProofTargetAssignmentError("cyclic proof".to_string(),e.to_string()), )?; + // assign verifier data + pw.set_verifier_data_target(&cyc_targets.verifier_data, &circ_data.verifier_only) + .map_err(|e| CircuitError::VerifierDataTargetAssignmentError(e.to_string()))?; } - // assign verifier data - pw.set_verifier_data_target(&cyc_targets.verifier_data, &circ_data.verifier_only) - .map_err(|e| CircuitError::VerifierDataTargetAssignmentError(e.to_string()))?; // prove let proof = circ_data.prove(pw).map_err( |e| CircuitError::InvalidProofError(e.to_string()) )?; - // check that the correct verifier data is consistent - check_cyclic_proof_verifier_data( - &proof, - &circ_data.verifier_only, - &circ_data.common, - ).map_err( - |e| CircuitError::RecursiveProofVerifierDataCheckError(e.to_string()) - )?; self.latest_proof = Some(proof.clone()); self.layer = self.layer + 1; @@ -232,16 +224,7 @@ impl< .ok_or_else(|| CircuitError::OptionError("cyclic proof".to_string()))? .clone(); - // check that the correct verifier data is consistent - //TODO: test if it works with only one layer proof - check_cyclic_proof_verifier_data( - &proof, - &self.cyclic_circuit_data.verifier_only, - &self.cyclic_circuit_data.common, - ).map_err( - |e| CircuitError::RecursiveProofVerifierDataCheckError(e.to_string()) - )?; - + // TODO: check that the correct verifier data is consistent self.cyclic_circuit_data.verify(proof).map_err( |e| CircuitError::InvalidProofError(e.to_string()) diff --git a/codex-plonky2-circuits/src/recursion/hybrid/tree_circuit.rs b/codex-plonky2-circuits/src/recursion/hybrid/tree_circuit.rs index 3756481..7a38564 100644 --- a/codex-plonky2-circuits/src/recursion/hybrid/tree_circuit.rs +++ b/codex-plonky2-circuits/src/recursion/hybrid/tree_circuit.rs @@ -10,7 +10,7 @@ use plonky2_field::extension::Extendable; use crate::{error::CircuitError, Result}; use crate::circuits::utils::vec_to_array; use crate::recursion::circuits::leaf_circuit::{LeafCircuit, LeafInput}; -use crate::recursion::hybrid::node_circuit::NodeCircuit; +use crate::recursion::hybrid::node_circuit::{NodeCircuit, NodeCircuitTargets}; /// Hybrid tree recursion - combines simple and tree recursion /// - N: number of leaf proofs to verify in the node circuit @@ -55,11 +55,12 @@ impl< // process leaves let (leaf_proofs, leaf_data) = self.get_leaf_proofs::( proofs_with_pi, - inner_verifier_data + inner_verifier_data, )?; // process nodes - let (root_proof, last_verifier_data) = self.prove::(&leaf_proofs,leaf_data.verifier_data())?; + let (root_proof, last_verifier_data) = + self.prove::(&leaf_proofs,leaf_data.verifier_data(), None, None, 0)?; Ok((root_proof, last_verifier_data)) } @@ -80,6 +81,7 @@ impl< let leaf_targets = self.leaf.build::(&mut builder)?; let leaf_data = builder.build::(); + println!("leaf circuit size = {:?}", leaf_data.common.degree_bits()); let mut leaf_proofs = vec![]; @@ -107,6 +109,9 @@ impl< &mut self, proofs_with_pi: &[ProofWithPublicInputs], verifier_data: VerifierCircuitData, + node_target_options: Option>, + node_data_option: Option>, + layer: usize, ) -> Result<(ProofWithPublicInputs, VerifierCircuitData)> where >::Hasher: AlgebraicHasher { @@ -117,10 +122,15 @@ impl< let mut new_proofs = vec![]; - let node_config = CircuitConfig::standard_recursion_config(); - let mut node_builder = CircuitBuilder::::new(node_config); - let node_targets = NodeCircuit::::build_circuit::(&mut node_builder, &verifier_data.common)?; - let node_data = node_builder.build::(); + let (node_data, node_targets) = if layer<2 { + let node_config = CircuitConfig::standard_recursion_config(); + let mut node_builder = CircuitBuilder::::new(node_config); + let targets = NodeCircuit::::build_circuit::(&mut node_builder, &verifier_data.common)?; + let data = node_builder.build::(); + (data, targets) + }else{ + (node_data_option.unwrap(), node_target_options.unwrap()) + }; for chunk in proofs_with_pi.chunks(N) { @@ -135,7 +145,7 @@ impl< new_proofs.push(proof); } - self.prove::(&new_proofs, node_data.verifier_data()) + self.prove::(&new_proofs, node_data.verifier_data(), Some(node_targets),Some(node_data), layer+1) } } diff --git a/codex-plonky2-circuits/src/recursion/mod.rs b/codex-plonky2-circuits/src/recursion/mod.rs index 482bdbf..070e087 100644 --- a/codex-plonky2-circuits/src/recursion/mod.rs +++ b/codex-plonky2-circuits/src/recursion/mod.rs @@ -4,3 +4,4 @@ pub mod simple; pub mod tree1; pub mod tree2; pub mod hybrid; +pub mod utils; diff --git a/codex-plonky2-circuits/src/recursion/tree1/node_circuit.rs b/codex-plonky2-circuits/src/recursion/tree1/node_circuit.rs index ef3c1b3..e4cf226 100644 --- a/codex-plonky2-circuits/src/recursion/tree1/node_circuit.rs +++ b/codex-plonky2-circuits/src/recursion/tree1/node_circuit.rs @@ -5,14 +5,14 @@ use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, CommonCircuitData use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget}; use plonky2::iop::witness::{PartialWitness, WitnessWrite}; -use plonky2::recursion::dummy_circuit::cyclic_base_proof; -use hashbrown::HashMap; use plonky2::gates::noop::NoopGate; use plonky2::iop::target::BoolTarget; use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2; use crate::circuits::utils::{select_hash, vec_to_array}; use crate::{error::CircuitError, Result}; use crate::recursion::circuits::inner_circuit::InnerCircuit; +use crate::recursion::utils::conditional_verifier::dummy_circuit; +use crate::recursion::utils::dummy_gen::DummyProofGen; /// Node circuit struct /// contains necessary data @@ -84,7 +84,9 @@ impl< let mut common_data = Self::common_data_for_node()?; let pub_input_hash = builder.add_virtual_hash_public_input(); - let verifier_data_target = builder.add_verifier_data_public_inputs(); + // TODO: make verifier data public + // let verifier_data_target = builder.add_verifier_data_public_inputs(); + let verifier_data_target = builder.add_virtual_verifier_data(builder.config.fri_config.cap_height); common_data.num_public_inputs = builder.num_public_inputs(); // condition @@ -113,8 +115,6 @@ impl< outer_pis.push( I::get_pub_input_targets(&inner_t[i])); } // hash all the public input -> generate one HashOut at the end - // this is not an optimal way to do it, verification might be ugly if M > 1 - // TODO: optimize this let mut outer_pi_hashes = vec![]; for i in 0..M { let hash_res = builder.hash_n_to_hash_no_pad::(outer_pis[i].clone()); @@ -137,11 +137,8 @@ impl< // verify all N proofs in-circuit for i in 0..N { - builder.conditionally_verify_cyclic_proof_or_dummy::( - condition, - &inner_cyclic_proof_with_pis[i], - &common_data, - ).map_err(|e| CircuitError::ConditionalVerificationError(e.to_string()))?; + builder.verify_proof::(&inner_cyclic_proof_with_pis[i], &verifier_data_target, &common_data); + } // build the cyclic circuit @@ -188,13 +185,16 @@ impl< for i in 0..N { pw.set_proof_with_pis_target::( &cyc_targets.inner_proofs_with_pis[i], - &cyclic_base_proof( + &DummyProofGen::::get_dummy_node_proof( common_data, &circ_data.verifier_only, - HashMap::new(), ), ).map_err(|e| CircuitError::ProofTargetAssignmentError("inner proofs".to_string(),e.to_string()))?; } + // assign verifier data + let dummy_ver = dummy_circuit::(common_data).verifier_only; + pw.set_verifier_data_target(&cyc_targets.verifier_data, &dummy_ver) + .map_err(|e| CircuitError::VerifierDataTargetAssignmentError(e.to_string()))?; }else{ pw.set_bool_target(cyc_targets.condition, true) .map_err(|e| CircuitError::BoolTargetAssignmentError("condition".to_string(),e.to_string()))?; @@ -204,11 +204,11 @@ impl< pw.set_proof_with_pis_target(&cyc_targets.inner_proofs_with_pis[i], &proofs[i]) .map_err(|e| CircuitError::ProofTargetAssignmentError("inner proofs".to_string(),e.to_string()))?; } + // assign verifier data + pw.set_verifier_data_target(&cyc_targets.verifier_data, &circ_data.verifier_only) + .map_err(|e| CircuitError::VerifierDataTargetAssignmentError(e.to_string()))?; } - pw.set_verifier_data_target(&cyc_targets.verifier_data, &circ_data.verifier_only) - .map_err(|e| CircuitError::VerifierDataTargetAssignmentError(e.to_string()))?; - Ok(()) } @@ -249,7 +249,7 @@ impl< let proof = builder.add_virtual_proof_with_pis(&data.common); builder.verify_proof::(&proof, &verifier_data, &data.common); } - // pad. TODO: optimize this padding to only needed number of gates + // pad - padding depends on the inner circuit size while builder.num_gates() < 1 << 13 { builder.add_gate(NoopGate, vec![]); } diff --git a/codex-plonky2-circuits/src/recursion/tree1/tree_circuit.rs b/codex-plonky2-circuits/src/recursion/tree1/tree_circuit.rs index 463b0e4..e5fe006 100644 --- a/codex-plonky2-circuits/src/recursion/tree1/tree_circuit.rs +++ b/codex-plonky2-circuits/src/recursion/tree1/tree_circuit.rs @@ -1,12 +1,11 @@ use std::array::from_fn; use plonky2::hash::hash_types::RichField; -use plonky2::iop::witness::{PartialWitness, WitnessWrite}; +use plonky2::iop::witness::{PartialWitness}; use plonky2::plonk::config::{AlgebraicHasher, GenericConfig}; use plonky2::plonk::proof::ProofWithPublicInputs; use plonky2_field::extension::Extendable; use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2; use crate::recursion::circuits::inner_circuit::InnerCircuit; -use plonky2::recursion::cyclic_recursion::check_cyclic_proof_verifier_data; use crate::{error::CircuitError, Result}; use crate::recursion::tree1::node_circuit::NodeCircuit; @@ -70,10 +69,6 @@ impl< )?; let circ_data = &self.node_circ.cyclic_circuit_data; - let cyc_targets = &self.node_circ.cyclic_target; - - pw.set_verifier_data_target(&cyc_targets.verifier_data, &circ_data.verifier_only) - .map_err(|e| CircuitError::VerifierDataTargetAssignmentError(e.to_string()))?; let proof = circ_data.prove(pw) .map_err(|e| CircuitError::InvalidProofError(e.to_string()))?; @@ -150,11 +145,7 @@ impl< let circ_data = &self.node_circ.cyclic_circuit_data; - check_cyclic_proof_verifier_data( - &proof, - &circ_data.verifier_only, - &circ_data.common, - ).map_err(|e| CircuitError::RecursiveProofVerifierDataCheckError(e.to_string()))?; + // TODO: check verifier_data circ_data.verify(proof).map_err(|e|CircuitError::InvalidProofError(e.to_string()))?; diff --git a/codex-plonky2-circuits/src/recursion/tree2/mod.rs b/codex-plonky2-circuits/src/recursion/tree2/mod.rs index 571a038..f81ad84 100644 --- a/codex-plonky2-circuits/src/recursion/tree2/mod.rs +++ b/codex-plonky2-circuits/src/recursion/tree2/mod.rs @@ -1,3 +1,2 @@ -pub mod dummy_gen; pub mod node_circuit; pub mod tree_circuit; diff --git a/codex-plonky2-circuits/src/recursion/tree2/node_circuit.rs b/codex-plonky2-circuits/src/recursion/tree2/node_circuit.rs index fd48c0c..85f1b6e 100644 --- a/codex-plonky2-circuits/src/recursion/tree2/node_circuit.rs +++ b/codex-plonky2-circuits/src/recursion/tree2/node_circuit.rs @@ -10,7 +10,7 @@ use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget}; use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2; use crate::recursion::circuits::inner_circuit::InnerCircuit; use plonky2_field::extension::Extendable; -use crate::circuits::utils::{select_hash, select_vec, vec_to_array}; +use crate::circuits::utils::{select_vec, vec_to_array}; use crate::{error::CircuitError, Result}; use crate::recursion::circuits::leaf_circuit::LeafCircuit; @@ -38,6 +38,7 @@ pub struct NodeCircuitTargets< pub condition: BoolTarget, pub node_proofs: [ProofWithPublicInputsTarget; N], pub leaf_verifier_data: VerifierCircuitTarget, + pub node_verifier_data: VerifierCircuitTarget, } /// Node common data and verifier data @@ -98,7 +99,7 @@ impl< } // leaf verifier data - // TODO: double check that it is ok for this verifier data to be private/witness + // TODO: make verifier data public let leaf_verifier_data = builder.add_virtual_verifier_data(leaf_common.config.fri_config.cap_height); // condition @@ -107,26 +108,19 @@ impl< // verify leaf proofs in-circuit if it is a leaf node, // meaning that we are on bottom layer of the tree for i in 0..N{ - builder.conditionally_verify_proof_or_dummy::( - condition, - &leaf_proofs[i], - &leaf_verifier_data, - &leaf_common - ).map_err(|e| CircuitError::ConditionalVerificationError(e.to_string()))?; + builder.verify_proof::(&leaf_proofs[i], &leaf_verifier_data, &leaf_common); + } // common data for recursion let mut common_data = Self::get_common_data_for_node()?; // public input hash. defined here so that is public_input[0..4] let pub_input_hash = builder.add_virtual_hash_public_input(); - // verifier data for the recursion. - let _verifier_data_target = builder.add_verifier_data_public_inputs(); + // TODO: make verifier data public + // let _verifier_data_target = builder.add_verifier_data_public_inputs(); + let verifier_data_target = builder.add_virtual_verifier_data(builder.config.fri_config.cap_height); common_data.num_public_inputs = builder.num_public_inputs(); - // flipped condition. used to conditionally verify the node proofs (recursive proofs) - let one = builder.one(); - let flipped_condition = BoolTarget::new_unsafe(builder.sub(one,condition.target)); - let inner_cyclic_proof_with_pis: [ProofWithPublicInputsTarget; N] = vec_to_array::>( (0..N) @@ -150,11 +144,8 @@ impl< // verify all N proofs in-circuit for i in 0..N { - builder.conditionally_verify_cyclic_proof_or_dummy::( - flipped_condition, - &inner_cyclic_proof_with_pis[i], - &common_data, - ).map_err(|e| CircuitError::ConditionalVerificationError(e.to_string()))?; + builder.verify_proof::(&inner_cyclic_proof_with_pis[i], &verifier_data_target, &common_data); + } // build the node circuit @@ -173,7 +164,8 @@ impl< leaf_proofs, condition, node_proofs: inner_cyclic_proof_with_pis, - leaf_verifier_data + leaf_verifier_data, + node_verifier_data: verifier_data_target }; let node_data = NodeData{ @@ -200,6 +192,7 @@ impl< leaf_proofs: [ProofWithPublicInputs; N], node_proofs: [ProofWithPublicInputs; N], leaf_verifier_only_data: &VerifierOnlyCircuitData, + node_verifier_only_data: &VerifierOnlyCircuitData, pw: &mut PartialWitness, is_leaf: bool, ) -> Result<()>{ @@ -240,9 +233,11 @@ impl< ).map_err(|e| CircuitError::ProofTargetAssignmentError("dummy leaf proofs".to_string(),e.to_string()))?; } } - // assign the verifier data (only for the leaf proofs) + // assign the verifier data pw.set_verifier_data_target(&node_targets.leaf_verifier_data, leaf_verifier_only_data) .map_err(|e| CircuitError::VerifierDataTargetAssignmentError(e.to_string()))?; + pw.set_verifier_data_target(&node_targets.node_verifier_data, node_verifier_only_data) + .map_err(|e| CircuitError::VerifierDataTargetAssignmentError(e.to_string()))?; Ok(()) } @@ -284,8 +279,8 @@ impl< let proof = builder.add_virtual_proof_with_pis(&data.common); builder.verify_proof::(&proof, &verifier_data, &data.common); } - // pad. TODO: optimize this padding to only needed number of gates - while builder.num_gates() < 1 << 14 { + // pad. + while builder.num_gates() < 1 << 12 { builder.add_gate(NoopGate, vec![]); } Ok(builder.build::().common) diff --git a/codex-plonky2-circuits/src/recursion/tree2/tree_circuit.rs b/codex-plonky2-circuits/src/recursion/tree2/tree_circuit.rs index 538e6b0..d6b878d 100644 --- a/codex-plonky2-circuits/src/recursion/tree2/tree_circuit.rs +++ b/codex-plonky2-circuits/src/recursion/tree2/tree_circuit.rs @@ -1,12 +1,11 @@ use plonky2::hash::hash_types::RichField; -use plonky2::iop::witness::PartialWitness; +use plonky2::iop::witness::{PartialWitness}; use plonky2::plonk::config::{AlgebraicHasher, GenericConfig}; use plonky2::plonk::proof::ProofWithPublicInputs; use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2; use crate::recursion::circuits::inner_circuit::InnerCircuit; -use plonky2::recursion::cyclic_recursion::check_cyclic_proof_verifier_data; use plonky2_field::extension::Extendable; -use crate::recursion::tree2::dummy_gen::DummyProofGen; +use crate::recursion::utils::dummy_gen::DummyProofGen; use crate::{error::CircuitError, Result}; use crate::circuits::utils::vec_to_array; use crate::recursion::circuits::leaf_circuit::LeafCircuit; @@ -67,13 +66,13 @@ impl< leaf_proofs, node_proofs, &self.node.node_data.leaf_circuit_data.verifier_only, + &self.node.node_data.node_circuit_data.verifier_only, &mut pw, is_leaf, )?; let proof = self.node.node_data.node_circuit_data.prove(pw) .map_err(|e| CircuitError::ProofGenerationError(e.to_string()))?; - Ok(proof) } @@ -158,13 +157,7 @@ impl< is_leaf: bool, ) -> Result<()>{ - if !is_leaf { - check_cyclic_proof_verifier_data( - &proof, - &self.node.node_data.node_circuit_data.verifier_only, - &self.node.node_data.node_circuit_data.common, - ).map_err(|e| CircuitError::InvalidProofError(e.to_string()))?; - } + // TODO: if !is_leaf check verifier data self.node.node_data.node_circuit_data.verify(proof) .map_err(|e| CircuitError::InvalidProofError(e.to_string()))?; diff --git a/codex-plonky2-circuits/src/recursion/utils/conditional_verifier.rs b/codex-plonky2-circuits/src/recursion/utils/conditional_verifier.rs new file mode 100644 index 0000000..2956e67 --- /dev/null +++ b/codex-plonky2-circuits/src/recursion/utils/conditional_verifier.rs @@ -0,0 +1,121 @@ +use plonky2::gates::noop::NoopGate; +use plonky2::hash::hash_types::RichField; +use plonky2::iop::target::BoolTarget; +use plonky2::plonk::circuit_builder::CircuitBuilder; +use plonky2::plonk::circuit_data::{CircuitData, CommonCircuitData, VerifierCircuitTarget}; +use plonky2::plonk::config::{AlgebraicHasher, GenericConfig}; +use plonky2::plonk::proof::ProofWithPublicInputsTarget; +use plonky2_field::extension::Extendable; +use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2; + +/// this takes verifier data (not public) and doesn't check the verifier data for consistency +pub fn conditionally_verify_recursion_proof_or_dummy + Poseidon2, const D: usize ,C: GenericConfig + 'static>( + builder: &mut CircuitBuilder, + condition: BoolTarget, + cyclic_proof_with_pis: &ProofWithPublicInputsTarget, + verifier_data: &VerifierCircuitTarget, + common_data: &CommonCircuitData, +) -> anyhow::Result<()> + where + C::Hasher: AlgebraicHasher, +{ + let (dummy_proof_with_pis_target, dummy_verifier_data_target) = + dummy_proof_and_vk_no_generator::(builder, common_data)?; + + // TODO: make verifier data public + // // Connect previous verifier data to current one. This guarantees that every proof in the cycle uses the same verifier data. + // self.connect_hashes( + // inner_cyclic_pis.circuit_digest, + // verifier_data.circuit_digest, + // ); + // self.connect_merkle_caps( + // &inner_cyclic_pis.constants_sigmas_cap, + // &verifier_data.constants_sigmas_cap, + // ); + + // Verify the cyclic proof if `condition` is set to true, otherwise verify the other proof. + builder.conditionally_verify_proof::( + condition, + cyclic_proof_with_pis, + verifier_data, + &dummy_proof_with_pis_target, + &dummy_verifier_data_target, + common_data, + ); + + // Make sure we have every gate to match `common_data`. + for g in &common_data.gates { + builder.add_gate_to_gate_set(g.clone()); + } + + Ok(()) +} + +/// Conditionally verify a proof with a new generated dummy proof. +pub fn conditionally_verify_proof_or_dummy + Poseidon2, const D: usize ,C: GenericConfig + 'static>( + builder: &mut CircuitBuilder, + condition: BoolTarget, + proof_with_pis: &ProofWithPublicInputsTarget, + inner_verifier_data: &VerifierCircuitTarget, + inner_common_data: &CommonCircuitData, +) -> anyhow::Result<()> + where + C::Hasher: AlgebraicHasher, +{ + let (dummy_proof_with_pis_target, dummy_verifier_data_target) = + dummy_proof_and_vk_no_generator::(builder, inner_common_data)?; + builder.conditionally_verify_proof::( + condition, + proof_with_pis, + inner_verifier_data, + &dummy_proof_with_pis_target, + &dummy_verifier_data_target, + inner_common_data, + ); + Ok(()) +} + +/// Generate a circuit matching a given `CommonCircuitData`. +pub(crate) fn dummy_circuit + Poseidon2, C: GenericConfig, const D: usize>( + common_data: &CommonCircuitData, +) -> CircuitData { + let config = common_data.config.clone(); + assert!( + !common_data.config.zero_knowledge, + "Degree calculation can be off if zero-knowledge is on." + ); + + // Number of `NoopGate`s to add to get a circuit of size `degree` in the end. + // Need to account for public input hashing, a `PublicInputGate` and a `ConstantGate`. + let degree = common_data.degree(); + let num_noop_gate = degree - common_data.num_public_inputs.div_ceil(8) - 2; + + let mut builder = CircuitBuilder::::new(config); + for _ in 0..num_noop_gate { + builder.add_gate(NoopGate, vec![]); + } + for gate in &common_data.gates { + builder.add_gate_to_gate_set(gate.clone()); + } + for _ in 0..common_data.num_public_inputs { + builder.add_virtual_public_input(); + } + + let circuit = builder.build::(); + assert_eq!(&circuit.common, common_data); + circuit +} + +pub(crate) fn dummy_proof_and_vk_no_generator + Poseidon2, const D: usize ,C: GenericConfig + 'static> ( + builder: &mut CircuitBuilder, + common_data: &CommonCircuitData, +) -> anyhow::Result<(ProofWithPublicInputsTarget, VerifierCircuitTarget)> + where + C::Hasher: AlgebraicHasher, +{ + let dummy_circuit = dummy_circuit::(common_data); + let dummy_proof_with_pis_target = builder.add_virtual_proof_with_pis(common_data); + let dummy_verifier_data_target = builder.constant_verifier_data(&dummy_circuit.verifier_only); + + Ok((dummy_proof_with_pis_target, dummy_verifier_data_target)) +} diff --git a/codex-plonky2-circuits/src/recursion/tree2/dummy_gen.rs b/codex-plonky2-circuits/src/recursion/utils/dummy_gen.rs similarity index 79% rename from codex-plonky2-circuits/src/recursion/tree2/dummy_gen.rs rename to codex-plonky2-circuits/src/recursion/utils/dummy_gen.rs index a051d29..7b412d6 100644 --- a/codex-plonky2-circuits/src/recursion/tree2/dummy_gen.rs +++ b/codex-plonky2-circuits/src/recursion/utils/dummy_gen.rs @@ -1,9 +1,10 @@ use std::marker::PhantomData; use plonky2::plonk::circuit_data::{CommonCircuitData, VerifierOnlyCircuitData}; -use plonky2::plonk::proof::ProofWithPublicInputs; -use plonky2::recursion::dummy_circuit::{cyclic_base_proof, dummy_circuit, dummy_proof}; +use plonky2::plonk::proof::{ProofWithPublicInputs}; +use plonky2::recursion::dummy_circuit::{dummy_proof}; +use crate::recursion::utils::conditional_verifier::dummy_circuit; use hashbrown::HashMap; -use plonky2::hash::hash_types::RichField; +use plonky2::hash::hash_types::{ RichField}; use plonky2::plonk::config::{AlgebraicHasher, GenericConfig}; use plonky2_field::extension::Extendable; use plonky2_poseidon2::poseidon2_hash::poseidon2::Poseidon2; @@ -43,7 +44,18 @@ impl< node_common: &CommonCircuitData, node_verifier_only_data: &VerifierOnlyCircuitData, ) -> ProofWithPublicInputs { - cyclic_base_proof(node_common, node_verifier_only_data, HashMap::new()) + Self::recursion_base_proof(node_common, HashMap::new()) + } + + fn recursion_base_proof( + common_data: &CommonCircuitData, + mut nonzero_public_inputs: HashMap + ) -> ProofWithPublicInputs{ + dummy_proof::( + &dummy_circuit::(common_data), + nonzero_public_inputs, + ) + .unwrap() } /// Generates an array of `N` dummy leaf proofs. @@ -65,6 +77,3 @@ impl< vec_to_array::>(n_dummy_vec) } } - - - diff --git a/codex-plonky2-circuits/src/recursion/utils/mod.rs b/codex-plonky2-circuits/src/recursion/utils/mod.rs new file mode 100644 index 0000000..09b3dd3 --- /dev/null +++ b/codex-plonky2-circuits/src/recursion/utils/mod.rs @@ -0,0 +1,2 @@ +pub mod dummy_gen; +pub mod conditional_verifier;