add support for any generic hash function

This commit is contained in:
M Alghazwi 2025-01-30 10:28:33 +01:00
parent 909dba1b43
commit 46c947828f
No known key found for this signature in database
GPG Key ID: 646E567CAD7DB607
12 changed files with 214 additions and 110 deletions

View File

@ -141,7 +141,7 @@ impl<
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
{
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
let mut builder = CircuitBuilder::<F, D>::new(config.clone());
self.build::<C,H>(&mut builder)?;

View File

@ -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::<C>(
condition,
&inner_cyclic_proof_with_pis,
&common_data,
).map_err(|e| CircuitError::ConditionalVerificationError(e.to_string()))?;
builder.verify_proof::<C>(&inner_cyclic_proof_with_pis, &verifier_data_target, &common_data);
// build the cyclic circuit
let cyclic_circuit_data = builder.build::<C>();
@ -159,14 +156,17 @@ impl<
)?;
pw.set_proof_with_pis_target::<C, D>(
&cyc_targets.inner_cyclic_proof_with_pis,
&cyclic_base_proof(
&DummyProofGen::<F, D, C>::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::<F, C, D>(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())

View File

@ -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::<C,H>(
proofs_with_pi,
inner_verifier_data
inner_verifier_data,
)?;
// process nodes
let (root_proof, last_verifier_data) = self.prove::<C,H>(&leaf_proofs,leaf_data.verifier_data())?;
let (root_proof, last_verifier_data) =
self.prove::<C,H>(&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::<C,H>(&mut builder)?;
let leaf_data = builder.build::<C>();
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<F, C, D>],
verifier_data: VerifierCircuitData<F, C, D>,
node_target_options: Option<NodeCircuitTargets<D, N>>,
node_data_option: Option<CircuitData<F, C, D>>,
layer: usize,
) -> Result<(ProofWithPublicInputs<F, C, D>, VerifierCircuitData<F, C, D>)> where
<C as GenericConfig<D>>::Hasher: AlgebraicHasher<F>
{
@ -117,10 +122,15 @@ impl<
let mut new_proofs = vec![];
let node_config = CircuitConfig::standard_recursion_config();
let mut node_builder = CircuitBuilder::<F, D>::new(node_config);
let node_targets = NodeCircuit::<F,D,C,N>::build_circuit::<H>(&mut node_builder, &verifier_data.common)?;
let node_data = node_builder.build::<C>();
let (node_data, node_targets) = if layer<2 {
let node_config = CircuitConfig::standard_recursion_config();
let mut node_builder = CircuitBuilder::<F, D>::new(node_config);
let targets = NodeCircuit::<F, D, C, N>::build_circuit::<H>(&mut node_builder, &verifier_data.common)?;
let data = node_builder.build::<C>();
(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::<C,H>(&new_proofs, node_data.verifier_data())
self.prove::<C,H>(&new_proofs, node_data.verifier_data(), Some(node_targets),Some(node_data), layer+1)
}
}

View File

@ -4,3 +4,4 @@ pub mod simple;
pub mod tree1;
pub mod tree2;
pub mod hybrid;
pub mod utils;

View File

@ -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::<H>(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::<C>(
condition,
&inner_cyclic_proof_with_pis[i],
&common_data,
).map_err(|e| CircuitError::ConditionalVerificationError(e.to_string()))?;
builder.verify_proof::<C>(&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::<C, D>(
&cyc_targets.inner_proofs_with_pis[i],
&cyclic_base_proof(
&DummyProofGen::<F, D, C>::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::<F, C, D>(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::<C>(&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![]);
}

View File

@ -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()))?;

View File

@ -1,3 +1,2 @@
pub mod dummy_gen;
pub mod node_circuit;
pub mod tree_circuit;

View File

@ -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<D>; 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::<C>(
condition,
&leaf_proofs[i],
&leaf_verifier_data,
&leaf_common
).map_err(|e| CircuitError::ConditionalVerificationError(e.to_string()))?;
builder.verify_proof::<C>(&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<D>; N] =
vec_to_array::<N, ProofWithPublicInputsTarget<D>>(
(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::<C>(
flipped_condition,
&inner_cyclic_proof_with_pis[i],
&common_data,
).map_err(|e| CircuitError::ConditionalVerificationError(e.to_string()))?;
builder.verify_proof::<C>(&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<F, C, D>; N],
node_proofs: [ProofWithPublicInputs<F, C, D>; N],
leaf_verifier_only_data: &VerifierOnlyCircuitData<C, D>,
node_verifier_only_data: &VerifierOnlyCircuitData<C, D>,
pw: &mut PartialWitness<F>,
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::<C>(&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::<C>().common)

View File

@ -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()))?;

View File

@ -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<F: RichField + Extendable<D> + Poseidon2, const D: usize ,C: GenericConfig<D, F = F> + 'static>(
builder: &mut CircuitBuilder<F, D>,
condition: BoolTarget,
cyclic_proof_with_pis: &ProofWithPublicInputsTarget<D>,
verifier_data: &VerifierCircuitTarget,
common_data: &CommonCircuitData<F, D>,
) -> anyhow::Result<()>
where
C::Hasher: AlgebraicHasher<F>,
{
let (dummy_proof_with_pis_target, dummy_verifier_data_target) =
dummy_proof_and_vk_no_generator::<F, D, C>(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::<C>(
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<F: RichField + Extendable<D> + Poseidon2, const D: usize ,C: GenericConfig<D, F = F> + 'static>(
builder: &mut CircuitBuilder<F, D>,
condition: BoolTarget,
proof_with_pis: &ProofWithPublicInputsTarget<D>,
inner_verifier_data: &VerifierCircuitTarget,
inner_common_data: &CommonCircuitData<F, D>,
) -> anyhow::Result<()>
where
C::Hasher: AlgebraicHasher<F>,
{
let (dummy_proof_with_pis_target, dummy_verifier_data_target) =
dummy_proof_and_vk_no_generator::<F, D, C>(builder, inner_common_data)?;
builder.conditionally_verify_proof::<C>(
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<F: RichField + Extendable<D> + Poseidon2, C: GenericConfig<D, F = F>, const D: usize>(
common_data: &CommonCircuitData<F, D>,
) -> CircuitData<F, C, D> {
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::<F, D>::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::<C>();
assert_eq!(&circuit.common, common_data);
circuit
}
pub(crate) fn dummy_proof_and_vk_no_generator<F: RichField + Extendable<D> + Poseidon2, const D: usize ,C: GenericConfig<D, F = F> + 'static> (
builder: &mut CircuitBuilder<F, D>,
common_data: &CommonCircuitData<F, D>,
) -> anyhow::Result<(ProofWithPublicInputsTarget<D>, VerifierCircuitTarget)>
where
C::Hasher: AlgebraicHasher<F>,
{
let dummy_circuit = dummy_circuit::<F, C, D>(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))
}

View File

@ -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<F, D>,
node_verifier_only_data: &VerifierOnlyCircuitData<C, D>,
) -> ProofWithPublicInputs<F, C, D> {
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<F, D>,
mut nonzero_public_inputs: HashMap<usize, F>
) -> ProofWithPublicInputs<F, C, D>{
dummy_proof::<F, C, D>(
&dummy_circuit::<F, C, D>(common_data),
nonzero_public_inputs,
)
.unwrap()
}
/// Generates an array of `N` dummy leaf proofs.
@ -65,6 +77,3 @@ impl<
vec_to_array::<N, ProofWithPublicInputs<F, C, D>>(n_dummy_vec)
}
}

View File

@ -0,0 +1,2 @@
pub mod dummy_gen;
pub mod conditional_verifier;