mirror of
https://github.com/logos-storage/proof-aggregation.git
synced 2026-01-02 13:53:13 +00:00
122 lines
4.7 KiB
Rust
122 lines
4.7 KiB
Rust
|
|
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))
|
||
|
|
}
|