mirror of
https://github.com/logos-storage/proof-aggregation.git
synced 2026-01-02 13:53:13 +00:00
add support for any generic hash function
This commit is contained in:
parent
909dba1b43
commit
46c947828f
@ -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)?;
|
||||
|
||||
|
||||
@ -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())
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -4,3 +4,4 @@ pub mod simple;
|
||||
pub mod tree1;
|
||||
pub mod tree2;
|
||||
pub mod hybrid;
|
||||
pub mod utils;
|
||||
|
||||
@ -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![]);
|
||||
}
|
||||
|
||||
@ -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()))?;
|
||||
|
||||
|
||||
@ -1,3 +1,2 @@
|
||||
pub mod dummy_gen;
|
||||
pub mod node_circuit;
|
||||
pub mod tree_circuit;
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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()))?;
|
||||
|
||||
@ -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))
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
2
codex-plonky2-circuits/src/recursion/utils/mod.rs
Normal file
2
codex-plonky2-circuits/src/recursion/utils/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod dummy_gen;
|
||||
pub mod conditional_verifier;
|
||||
Loading…
x
Reference in New Issue
Block a user