mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-06 15:53:10 +00:00
Merge pull request #474 from mir-protocol/match_recursive_verifier
Match native and recursive verifier structures
This commit is contained in:
commit
8a07d7af41
@ -1,12 +1,16 @@
|
||||
use plonky2_field::extension_field::Extendable;
|
||||
use plonky2_field::polynomial::PolynomialCoeffs;
|
||||
|
||||
use crate::fri::proof::FriChallenges;
|
||||
use crate::fri::proof::{FriChallenges, FriChallengesTarget};
|
||||
use crate::fri::structure::{FriOpenings, FriOpeningsTarget};
|
||||
use crate::fri::FriConfig;
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::gadgets::polynomial::PolynomialCoeffsExtTarget;
|
||||
use crate::hash::hash_types::{MerkleCapTarget, RichField};
|
||||
use crate::hash::merkle_tree::MerkleCap;
|
||||
use crate::iop::challenger::{Challenger, RecursiveChallenger};
|
||||
use crate::iop::target::Target;
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::circuit_data::CommonCircuitData;
|
||||
use crate::plonk::config::{AlgebraicHasher, GenericConfig, Hasher};
|
||||
|
||||
impl<F: RichField, H: Hasher<F>> Challenger<F, H> {
|
||||
@ -78,4 +82,50 @@ impl<F: RichField + Extendable<D>, H: AlgebraicHasher<F>, const D: usize>
|
||||
self.observe_extension_elements(&v.values);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fri_challenges<C: GenericConfig<D, F = F>>(
|
||||
&mut self,
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
commit_phase_merkle_caps: &[MerkleCapTarget],
|
||||
final_poly: &PolynomialCoeffsExtTarget<D>,
|
||||
pow_witness: Target,
|
||||
inner_common_data: &CommonCircuitData<F, C, D>,
|
||||
) -> FriChallengesTarget<D> {
|
||||
let num_fri_queries = inner_common_data.config.fri_config.num_query_rounds;
|
||||
// Scaling factor to combine polynomials.
|
||||
let fri_alpha = self.get_extension_challenge(builder);
|
||||
|
||||
// Recover the random betas used in the FRI reductions.
|
||||
let fri_betas = commit_phase_merkle_caps
|
||||
.iter()
|
||||
.map(|cap| {
|
||||
self.observe_cap(cap);
|
||||
self.get_extension_challenge(builder)
|
||||
})
|
||||
.collect();
|
||||
|
||||
self.observe_extension_elements(&final_poly.0);
|
||||
|
||||
let pow_inputs = self
|
||||
.get_hash(builder)
|
||||
.elements
|
||||
.iter()
|
||||
.copied()
|
||||
.chain(Some(pow_witness))
|
||||
.collect();
|
||||
let fri_pow_response = builder
|
||||
.hash_n_to_hash_no_pad::<C::InnerHasher>(pow_inputs)
|
||||
.elements[0];
|
||||
|
||||
let fri_query_indices = (0..num_fri_queries)
|
||||
.map(|_| self.get_challenge(builder))
|
||||
.collect();
|
||||
|
||||
FriChallengesTarget {
|
||||
fri_alpha,
|
||||
fri_betas,
|
||||
fri_pow_response,
|
||||
fri_query_indices,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -375,3 +375,10 @@ pub struct FriChallenges<F: RichField + Extendable<D>, const D: usize> {
|
||||
// Indices at which the oracle is queried in FRI.
|
||||
pub fri_query_indices: Vec<usize>,
|
||||
}
|
||||
|
||||
pub struct FriChallengesTarget<const D: usize> {
|
||||
pub fri_alpha: ExtensionTarget<D>,
|
||||
pub fri_betas: Vec<ExtensionTarget<D>>,
|
||||
pub fri_pow_response: Target,
|
||||
pub fri_query_indices: Vec<Target>,
|
||||
}
|
||||
|
||||
@ -3,7 +3,8 @@ use plonky2_field::extension_field::Extendable;
|
||||
use plonky2_util::{log2_strict, reverse_index_bits_in_place};
|
||||
|
||||
use crate::fri::proof::{
|
||||
FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget, FriQueryStepTarget,
|
||||
FriChallengesTarget, FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget,
|
||||
FriQueryStepTarget,
|
||||
};
|
||||
use crate::fri::structure::{FriBatchInfoTarget, FriInstanceInfoTarget, FriOpeningsTarget};
|
||||
use crate::fri::{FriConfig, FriParams};
|
||||
@ -14,12 +15,10 @@ use crate::gates::low_degree_interpolation::LowDegreeInterpolationGate;
|
||||
use crate::gates::random_access::RandomAccessGate;
|
||||
use crate::hash::hash_types::MerkleCapTarget;
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::iop::challenger::RecursiveChallenger;
|
||||
use crate::iop::ext_target::{flatten_target, ExtensionTarget};
|
||||
use crate::iop::target::{BoolTarget, Target};
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::config::{AlgebraicHasher, GenericConfig};
|
||||
use crate::plonk::proof::OpeningSetTarget;
|
||||
use crate::util::reducing::ReducingFactorTarget;
|
||||
use crate::with_context;
|
||||
|
||||
@ -107,16 +106,11 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
|
||||
fn fri_verify_proof_of_work<H: AlgebraicHasher<F>>(
|
||||
&mut self,
|
||||
proof: &FriProofTarget<D>,
|
||||
challenger: &mut RecursiveChallenger<F, H, D>,
|
||||
fri_pow_response: Target,
|
||||
config: &FriConfig,
|
||||
) {
|
||||
let mut inputs = challenger.get_hash(self).elements.to_vec();
|
||||
inputs.push(proof.pow_witness);
|
||||
|
||||
let hash = self.hash_n_to_m_no_pad::<H>(inputs, 1)[0];
|
||||
self.assert_leading_zeros(
|
||||
hash,
|
||||
fri_pow_response,
|
||||
config.proof_of_work_bits + (64 - F::order().bits()) as u32,
|
||||
);
|
||||
}
|
||||
@ -124,11 +118,10 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
pub fn verify_fri_proof<C: GenericConfig<D, F = F>>(
|
||||
&mut self,
|
||||
instance: &FriInstanceInfoTarget<D>,
|
||||
// Openings of the PLONK polynomials.
|
||||
os: &OpeningSetTarget<D>,
|
||||
openings: &FriOpeningsTarget<D>,
|
||||
challenges: &FriChallengesTarget<D>,
|
||||
initial_merkle_caps: &[MerkleCapTarget],
|
||||
proof: &FriProofTarget<D>,
|
||||
challenger: &mut RecursiveChallenger<F, C::Hasher, D>,
|
||||
params: &FriParams,
|
||||
) where
|
||||
C::Hasher: AlgebraicHasher<F>,
|
||||
@ -146,29 +139,10 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
// Size of the LDE domain.
|
||||
let n = params.lde_size();
|
||||
|
||||
challenger.observe_openings(&os.to_fri_openings());
|
||||
|
||||
// Scaling factor to combine polynomials.
|
||||
let alpha = challenger.get_extension_challenge(self);
|
||||
|
||||
let betas = with_context!(
|
||||
self,
|
||||
"recover the random betas used in the FRI reductions.",
|
||||
proof
|
||||
.commit_phase_merkle_caps
|
||||
.iter()
|
||||
.map(|cap| {
|
||||
challenger.observe_cap(cap);
|
||||
challenger.get_extension_challenge(self)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
challenger.observe_extension_elements(&proof.final_poly.0);
|
||||
|
||||
with_context!(
|
||||
self,
|
||||
"check PoW",
|
||||
self.fri_verify_proof_of_work::<C::Hasher>(proof, challenger, ¶ms.config)
|
||||
self.fri_verify_proof_of_work::<C::Hasher>(challenges.fri_pow_response, ¶ms.config)
|
||||
);
|
||||
|
||||
// Check that parameters are coherent.
|
||||
@ -181,7 +155,11 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
let precomputed_reduced_evals = with_context!(
|
||||
self,
|
||||
"precompute reduced evaluations",
|
||||
PrecomputedReducedOpeningsTarget::from_os_and_alpha(&os.to_fri_openings(), alpha, self)
|
||||
PrecomputedReducedOpeningsTarget::from_os_and_alpha(
|
||||
openings,
|
||||
challenges.fri_alpha,
|
||||
self
|
||||
)
|
||||
);
|
||||
|
||||
for (i, round_proof) in proof.query_round_proofs.iter().enumerate() {
|
||||
@ -201,13 +179,12 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
&format!("verify one (of {}) query rounds", num_queries),
|
||||
self.fri_verifier_query_round::<C>(
|
||||
instance,
|
||||
alpha,
|
||||
challenges,
|
||||
&precomputed_reduced_evals,
|
||||
initial_merkle_caps,
|
||||
proof,
|
||||
challenger,
|
||||
challenges.fri_query_indices[i],
|
||||
n,
|
||||
&betas,
|
||||
round_proof,
|
||||
params,
|
||||
)
|
||||
@ -291,13 +268,12 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
fn fri_verifier_query_round<C: GenericConfig<D, F = F>>(
|
||||
&mut self,
|
||||
instance: &FriInstanceInfoTarget<D>,
|
||||
alpha: ExtensionTarget<D>,
|
||||
challenges: &FriChallengesTarget<D>,
|
||||
precomputed_reduced_evals: &PrecomputedReducedOpeningsTarget<D>,
|
||||
initial_merkle_caps: &[MerkleCapTarget],
|
||||
proof: &FriProofTarget<D>,
|
||||
challenger: &mut RecursiveChallenger<F, C::Hasher, D>,
|
||||
x_index: Target,
|
||||
n: usize,
|
||||
betas: &[ExtensionTarget<D>],
|
||||
round_proof: &FriQueryRoundTarget<D>,
|
||||
params: &FriParams,
|
||||
) where
|
||||
@ -308,7 +284,6 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
// Note that this `low_bits` decomposition permits non-canonical binary encodings. Here we
|
||||
// verify that this has a negligible impact on soundness error.
|
||||
Self::assert_noncanonical_indices_ok(¶ms.config);
|
||||
let x_index = challenger.get_challenge(self);
|
||||
let mut x_index_bits = self.low_bits(x_index, n_log, F::BITS);
|
||||
|
||||
let cap_index =
|
||||
@ -341,7 +316,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
self.fri_combine_initial::<C>(
|
||||
instance,
|
||||
&round_proof.initial_trees_proof,
|
||||
alpha,
|
||||
challenges.fri_alpha,
|
||||
subgroup_x,
|
||||
precomputed_reduced_evals,
|
||||
params,
|
||||
@ -368,7 +343,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
x_index_within_coset_bits,
|
||||
arity_bits,
|
||||
evals,
|
||||
betas[i],
|
||||
challenges.fri_betas[i],
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
@ -3,16 +3,20 @@ use std::collections::HashSet;
|
||||
use plonky2_field::extension_field::Extendable;
|
||||
use plonky2_field::polynomial::PolynomialCoeffs;
|
||||
|
||||
use crate::fri::proof::{CompressedFriProof, FriChallenges, FriProof};
|
||||
use crate::fri::proof::{CompressedFriProof, FriChallenges, FriProof, FriProofTarget};
|
||||
use crate::fri::verifier::{compute_evaluation, fri_combine_initial, PrecomputedReducedOpenings};
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::gadgets::polynomial::PolynomialCoeffsExtTarget;
|
||||
use crate::hash::hash_types::{HashOutTarget, MerkleCapTarget, RichField};
|
||||
use crate::hash::merkle_tree::MerkleCap;
|
||||
use crate::iop::challenger::Challenger;
|
||||
use crate::iop::challenger::{Challenger, RecursiveChallenger};
|
||||
use crate::iop::target::Target;
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::circuit_data::CommonCircuitData;
|
||||
use crate::plonk::config::{GenericConfig, Hasher};
|
||||
use crate::plonk::config::{AlgebraicHasher, GenericConfig, Hasher};
|
||||
use crate::plonk::proof::{
|
||||
CompressedProof, CompressedProofWithPublicInputs, FriInferredElements, OpeningSet, Proof,
|
||||
ProofChallenges, ProofWithPublicInputs,
|
||||
CompressedProof, CompressedProofWithPublicInputs, FriInferredElements, OpeningSet,
|
||||
OpeningSetTarget, Proof, ProofChallenges, ProofChallengesTarget, ProofTarget,
|
||||
ProofWithPublicInputs, ProofWithPublicInputsTarget,
|
||||
};
|
||||
use crate::util::reverse_bits;
|
||||
|
||||
@ -71,7 +75,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
|
||||
common_data: &CommonCircuitData<F, C, D>,
|
||||
) -> anyhow::Result<Vec<usize>> {
|
||||
Ok(self
|
||||
.get_challenges(common_data)?
|
||||
.get_challenges(self.get_public_inputs_hash(), common_data)?
|
||||
.fri_challenges
|
||||
.fri_query_indices)
|
||||
}
|
||||
@ -79,6 +83,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
|
||||
/// Computes all Fiat-Shamir challenges used in the Plonk proof.
|
||||
pub(crate) fn get_challenges(
|
||||
&self,
|
||||
public_inputs_hash: <<C as GenericConfig<D>>::InnerHasher as Hasher<F>>::Hash,
|
||||
common_data: &CommonCircuitData<F, C, D>,
|
||||
) -> anyhow::Result<ProofChallenges<F, D>> {
|
||||
let Proof {
|
||||
@ -96,7 +101,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
|
||||
} = &self.proof;
|
||||
|
||||
get_challenges(
|
||||
self.get_public_inputs_hash(),
|
||||
public_inputs_hash,
|
||||
wires_cap,
|
||||
plonk_zs_partial_products_cap,
|
||||
quotient_polys_cap,
|
||||
@ -115,6 +120,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
|
||||
/// Computes all Fiat-Shamir challenges used in the Plonk proof.
|
||||
pub(crate) fn get_challenges(
|
||||
&self,
|
||||
public_inputs_hash: <<C as GenericConfig<D>>::InnerHasher as Hasher<F>>::Hash,
|
||||
common_data: &CommonCircuitData<F, C, D>,
|
||||
) -> anyhow::Result<ProofChallenges<F, D>> {
|
||||
let CompressedProof {
|
||||
@ -132,7 +138,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
|
||||
} = &self.proof;
|
||||
|
||||
get_challenges(
|
||||
self.get_public_inputs_hash(),
|
||||
public_inputs_hash,
|
||||
wires_cap,
|
||||
plonk_zs_partial_products_cap,
|
||||
quotient_polys_cap,
|
||||
@ -219,3 +225,96 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
|
||||
FriInferredElements(fri_inferred_elements)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
fn get_challenges<C: GenericConfig<D, F = F>>(
|
||||
&mut self,
|
||||
public_inputs_hash: HashOutTarget,
|
||||
wires_cap: &MerkleCapTarget,
|
||||
plonk_zs_partial_products_cap: &MerkleCapTarget,
|
||||
quotient_polys_cap: &MerkleCapTarget,
|
||||
openings: &OpeningSetTarget<D>,
|
||||
commit_phase_merkle_caps: &[MerkleCapTarget],
|
||||
final_poly: &PolynomialCoeffsExtTarget<D>,
|
||||
pow_witness: Target,
|
||||
inner_common_data: &CommonCircuitData<F, C, D>,
|
||||
) -> ProofChallengesTarget<D>
|
||||
where
|
||||
C::Hasher: AlgebraicHasher<F>,
|
||||
{
|
||||
let config = &inner_common_data.config;
|
||||
let num_challenges = config.num_challenges;
|
||||
|
||||
let mut challenger = RecursiveChallenger::<F, C::Hasher, D>::new(self);
|
||||
|
||||
// Observe the instance.
|
||||
let digest =
|
||||
HashOutTarget::from_vec(self.constants(&inner_common_data.circuit_digest.elements));
|
||||
challenger.observe_hash(&digest);
|
||||
challenger.observe_hash(&public_inputs_hash);
|
||||
|
||||
challenger.observe_cap(wires_cap);
|
||||
let plonk_betas = challenger.get_n_challenges(self, num_challenges);
|
||||
let plonk_gammas = challenger.get_n_challenges(self, num_challenges);
|
||||
|
||||
challenger.observe_cap(plonk_zs_partial_products_cap);
|
||||
let plonk_alphas = challenger.get_n_challenges(self, num_challenges);
|
||||
|
||||
challenger.observe_cap(quotient_polys_cap);
|
||||
let plonk_zeta = challenger.get_extension_challenge(self);
|
||||
|
||||
challenger.observe_openings(&openings.to_fri_openings());
|
||||
|
||||
ProofChallengesTarget {
|
||||
plonk_betas,
|
||||
plonk_gammas,
|
||||
plonk_alphas,
|
||||
plonk_zeta,
|
||||
fri_challenges: challenger.fri_challenges::<C>(
|
||||
self,
|
||||
commit_phase_merkle_caps,
|
||||
final_poly,
|
||||
pow_witness,
|
||||
inner_common_data,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<const D: usize> ProofWithPublicInputsTarget<D> {
|
||||
pub(crate) fn get_challenges<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>>(
|
||||
&self,
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
public_inputs_hash: HashOutTarget,
|
||||
inner_common_data: &CommonCircuitData<F, C, D>,
|
||||
) -> ProofChallengesTarget<D>
|
||||
where
|
||||
C::Hasher: AlgebraicHasher<F>,
|
||||
{
|
||||
let ProofTarget {
|
||||
wires_cap,
|
||||
plonk_zs_partial_products_cap,
|
||||
quotient_polys_cap,
|
||||
openings,
|
||||
opening_proof:
|
||||
FriProofTarget {
|
||||
commit_phase_merkle_caps,
|
||||
final_poly,
|
||||
pow_witness,
|
||||
..
|
||||
},
|
||||
} = &self.proof;
|
||||
|
||||
builder.get_challenges(
|
||||
public_inputs_hash,
|
||||
wires_cap,
|
||||
plonk_zs_partial_products_cap,
|
||||
quotient_polys_cap,
|
||||
openings,
|
||||
commit_phase_merkle_caps,
|
||||
final_poly,
|
||||
*pow_witness,
|
||||
inner_common_data,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
use anyhow::ensure;
|
||||
use plonky2_field::extension_field::Extendable;
|
||||
use rayon::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::fri::oracle::PolynomialBatch;
|
||||
use crate::fri::proof::{CompressedFriProof, FriChallenges, FriProof, FriProofTarget};
|
||||
use crate::fri::proof::{
|
||||
CompressedFriProof, FriChallenges, FriChallengesTarget, FriProof, FriProofTarget,
|
||||
};
|
||||
use crate::fri::structure::{
|
||||
FriOpeningBatch, FriOpeningBatchTarget, FriOpenings, FriOpeningsTarget,
|
||||
};
|
||||
@ -172,7 +175,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
|
||||
self,
|
||||
common_data: &CommonCircuitData<F, C, D>,
|
||||
) -> anyhow::Result<ProofWithPublicInputs<F, C, D>> {
|
||||
let challenges = self.get_challenges(common_data)?;
|
||||
let challenges = self.get_challenges(self.get_public_inputs_hash(), common_data)?;
|
||||
let fri_inferred_elements = self.get_inferred_elements(&challenges, common_data);
|
||||
let decompressed_proof =
|
||||
self.proof
|
||||
@ -188,16 +191,19 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
|
||||
verifier_data: &VerifierOnlyCircuitData<C, D>,
|
||||
common_data: &CommonCircuitData<F, C, D>,
|
||||
) -> anyhow::Result<()> {
|
||||
let challenges = self.get_challenges(common_data)?;
|
||||
ensure!(
|
||||
self.public_inputs.len() == common_data.num_public_inputs,
|
||||
"Number of public inputs doesn't match circuit data."
|
||||
);
|
||||
let public_inputs_hash = self.get_public_inputs_hash();
|
||||
let challenges = self.get_challenges(public_inputs_hash, common_data)?;
|
||||
let fri_inferred_elements = self.get_inferred_elements(&challenges, common_data);
|
||||
let decompressed_proof =
|
||||
self.proof
|
||||
.decompress(&challenges, fri_inferred_elements, &common_data.fri_params);
|
||||
verify_with_challenges(
|
||||
ProofWithPublicInputs {
|
||||
public_inputs: self.public_inputs,
|
||||
proof: decompressed_proof,
|
||||
},
|
||||
decompressed_proof,
|
||||
public_inputs_hash,
|
||||
challenges,
|
||||
verifier_data,
|
||||
common_data,
|
||||
@ -242,6 +248,14 @@ pub(crate) struct ProofChallenges<F: RichField + Extendable<D>, const D: usize>
|
||||
pub fri_challenges: FriChallenges<F, D>,
|
||||
}
|
||||
|
||||
pub(crate) struct ProofChallengesTarget<const D: usize> {
|
||||
pub plonk_betas: Vec<Target>,
|
||||
pub plonk_gammas: Vec<Target>,
|
||||
pub plonk_alphas: Vec<Target>,
|
||||
pub plonk_zeta: ExtensionTarget<D>,
|
||||
pub fri_challenges: FriChallengesTarget<D>,
|
||||
}
|
||||
|
||||
/// Coset elements that can be inferred in the FRI reduction steps.
|
||||
pub(crate) struct FriInferredElements<F: RichField + Extendable<D>, const D: usize>(
|
||||
pub Vec<F::Extension>,
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
use plonky2_field::extension_field::Extendable;
|
||||
|
||||
use crate::hash::hash_types::{HashOutTarget, RichField};
|
||||
use crate::iop::challenger::RecursiveChallenger;
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::circuit_data::{CommonCircuitData, VerifierCircuitTarget};
|
||||
use crate::plonk::config::{AlgebraicHasher, GenericConfig};
|
||||
use crate::plonk::proof::{OpeningSetTarget, ProofTarget, ProofWithPublicInputsTarget};
|
||||
use crate::plonk::proof::{
|
||||
OpeningSetTarget, ProofChallengesTarget, ProofTarget, ProofWithPublicInputsTarget,
|
||||
};
|
||||
use crate::plonk::vanishing_poly::eval_vanishing_poly_recursively;
|
||||
use crate::plonk::vars::EvaluationTargets;
|
||||
use crate::util::reducing::ReducingFactorTarget;
|
||||
@ -13,7 +14,7 @@ use crate::with_context;
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
/// Recursively verifies an inner proof.
|
||||
pub fn verify_proof_with_pis<C: GenericConfig<D, F = F>>(
|
||||
pub fn verify_proof<C: GenericConfig<D, F = F>>(
|
||||
&mut self,
|
||||
proof_with_pis: ProofWithPublicInputsTarget<D>,
|
||||
inner_verifier_data: &VerifierCircuitTarget,
|
||||
@ -21,27 +22,29 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
) where
|
||||
C::Hasher: AlgebraicHasher<F>,
|
||||
{
|
||||
let ProofWithPublicInputsTarget {
|
||||
proof,
|
||||
public_inputs,
|
||||
} = proof_with_pis;
|
||||
assert_eq!(
|
||||
proof_with_pis.public_inputs.len(),
|
||||
inner_common_data.num_public_inputs
|
||||
);
|
||||
let public_inputs_hash =
|
||||
self.hash_n_to_hash_no_pad::<C::InnerHasher>(proof_with_pis.public_inputs.clone());
|
||||
let challenges = proof_with_pis.get_challenges(self, public_inputs_hash, inner_common_data);
|
||||
|
||||
assert_eq!(public_inputs.len(), inner_common_data.num_public_inputs);
|
||||
let public_inputs_hash = self.hash_n_to_hash_no_pad::<C::InnerHasher>(public_inputs);
|
||||
|
||||
self.verify_proof(
|
||||
proof,
|
||||
self.verify_proof_with_challenges(
|
||||
proof_with_pis.proof,
|
||||
public_inputs_hash,
|
||||
challenges,
|
||||
inner_verifier_data,
|
||||
inner_common_data,
|
||||
);
|
||||
}
|
||||
|
||||
/// Recursively verifies an inner proof.
|
||||
pub fn verify_proof<C: GenericConfig<D, F = F>>(
|
||||
fn verify_proof_with_challenges<C: GenericConfig<D, F = F>>(
|
||||
&mut self,
|
||||
proof: ProofTarget<D>,
|
||||
public_inputs_hash: HashOutTarget,
|
||||
challenges: ProofChallengesTarget<D>,
|
||||
inner_verifier_data: &VerifierCircuitTarget,
|
||||
inner_common_data: &CommonCircuitData<F, C, D>,
|
||||
) where
|
||||
@ -49,32 +52,6 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
{
|
||||
let one = self.one_extension();
|
||||
|
||||
let num_challenges = inner_common_data.config.num_challenges;
|
||||
|
||||
let mut challenger = RecursiveChallenger::<F, C::Hasher, D>::new(self);
|
||||
|
||||
let (betas, gammas, alphas, zeta) =
|
||||
with_context!(self, "observe proof and generates challenges", {
|
||||
// Observe the instance.
|
||||
let digest = HashOutTarget::from_vec(
|
||||
self.constants(&inner_common_data.circuit_digest.elements),
|
||||
);
|
||||
challenger.observe_hash(&digest);
|
||||
challenger.observe_hash(&public_inputs_hash);
|
||||
|
||||
challenger.observe_cap(&proof.wires_cap);
|
||||
let betas = challenger.get_n_challenges(self, num_challenges);
|
||||
let gammas = challenger.get_n_challenges(self, num_challenges);
|
||||
|
||||
challenger.observe_cap(&proof.plonk_zs_partial_products_cap);
|
||||
let alphas = challenger.get_n_challenges(self, num_challenges);
|
||||
|
||||
challenger.observe_cap(&proof.quotient_polys_cap);
|
||||
let zeta = challenger.get_extension_challenge(self);
|
||||
|
||||
(betas, gammas, alphas, zeta)
|
||||
});
|
||||
|
||||
let local_constants = &proof.openings.constants;
|
||||
let local_wires = &proof.openings.wires;
|
||||
let vars = EvaluationTargets {
|
||||
@ -87,23 +64,24 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
let s_sigmas = &proof.openings.plonk_sigmas;
|
||||
let partial_products = &proof.openings.partial_products;
|
||||
|
||||
let zeta_pow_deg = self.exp_power_of_2_extension(zeta, inner_common_data.degree_bits);
|
||||
let zeta_pow_deg =
|
||||
self.exp_power_of_2_extension(challenges.plonk_zeta, inner_common_data.degree_bits);
|
||||
let vanishing_polys_zeta = with_context!(
|
||||
self,
|
||||
"evaluate the vanishing polynomial at our challenge point, zeta.",
|
||||
eval_vanishing_poly_recursively(
|
||||
self,
|
||||
inner_common_data,
|
||||
zeta,
|
||||
challenges.plonk_zeta,
|
||||
zeta_pow_deg,
|
||||
vars,
|
||||
local_zs,
|
||||
next_zs,
|
||||
partial_products,
|
||||
s_sigmas,
|
||||
&betas,
|
||||
&gammas,
|
||||
&alphas,
|
||||
&challenges.plonk_betas,
|
||||
&challenges.plonk_gammas,
|
||||
&challenges.plonk_alphas,
|
||||
)
|
||||
);
|
||||
|
||||
@ -128,16 +106,16 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
proof.quotient_polys_cap,
|
||||
];
|
||||
|
||||
let fri_instance = inner_common_data.get_fri_instance_target(self, zeta);
|
||||
let fri_instance = inner_common_data.get_fri_instance_target(self, challenges.plonk_zeta);
|
||||
with_context!(
|
||||
self,
|
||||
"verify FRI proof",
|
||||
self.verify_fri_proof::<C>(
|
||||
&fri_instance,
|
||||
&proof.openings,
|
||||
&proof.openings.to_fri_openings(),
|
||||
&challenges.fri_challenges,
|
||||
merkle_caps,
|
||||
&proof.opening_proof,
|
||||
&mut challenger,
|
||||
&inner_common_data.fri_params,
|
||||
)
|
||||
);
|
||||
@ -392,7 +370,7 @@ mod tests {
|
||||
&inner_vd.constants_sigmas_cap,
|
||||
);
|
||||
|
||||
builder.verify_proof_with_pis(pt, &inner_data, &inner_cd);
|
||||
builder.verify_proof(pt, &inner_data, &inner_cd);
|
||||
|
||||
if print_gate_counts {
|
||||
builder.print_gate_counts(0);
|
||||
|
||||
@ -5,9 +5,9 @@ use plonky2_field::field_types::Field;
|
||||
use crate::fri::verifier::verify_fri_proof;
|
||||
use crate::hash::hash_types::RichField;
|
||||
use crate::plonk::circuit_data::{CommonCircuitData, VerifierOnlyCircuitData};
|
||||
use crate::plonk::config::GenericConfig;
|
||||
use crate::plonk::config::{GenericConfig, Hasher};
|
||||
use crate::plonk::plonk_common::reduce_with_powers;
|
||||
use crate::plonk::proof::{ProofChallenges, ProofWithPublicInputs};
|
||||
use crate::plonk::proof::{Proof, ProofChallenges, ProofWithPublicInputs};
|
||||
use crate::plonk::vanishing_poly::eval_vanishing_poly;
|
||||
use crate::plonk::vars::EvaluationVars;
|
||||
|
||||
@ -16,8 +16,20 @@ pub(crate) fn verify<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, c
|
||||
verifier_data: &VerifierOnlyCircuitData<C, D>,
|
||||
common_data: &CommonCircuitData<F, C, D>,
|
||||
) -> Result<()> {
|
||||
let challenges = proof_with_pis.get_challenges(common_data)?;
|
||||
verify_with_challenges(proof_with_pis, challenges, verifier_data, common_data)
|
||||
ensure!(
|
||||
proof_with_pis.public_inputs.len() == common_data.num_public_inputs,
|
||||
"Number of public inputs doesn't match circuit data."
|
||||
);
|
||||
let public_inputs_hash = proof_with_pis.get_public_inputs_hash();
|
||||
let challenges = proof_with_pis.get_challenges(public_inputs_hash, common_data)?;
|
||||
|
||||
verify_with_challenges(
|
||||
proof_with_pis.proof,
|
||||
public_inputs_hash,
|
||||
challenges,
|
||||
verifier_data,
|
||||
common_data,
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn verify_with_challenges<
|
||||
@ -25,25 +37,18 @@ pub(crate) fn verify_with_challenges<
|
||||
C: GenericConfig<D, F = F>,
|
||||
const D: usize,
|
||||
>(
|
||||
proof_with_pis: ProofWithPublicInputs<F, C, D>,
|
||||
proof: Proof<F, C, D>,
|
||||
public_inputs_hash: <<C as GenericConfig<D>>::InnerHasher as Hasher<F>>::Hash,
|
||||
challenges: ProofChallenges<F, D>,
|
||||
verifier_data: &VerifierOnlyCircuitData<C, D>,
|
||||
common_data: &CommonCircuitData<F, C, D>,
|
||||
) -> Result<()> {
|
||||
assert_eq!(
|
||||
proof_with_pis.public_inputs.len(),
|
||||
common_data.num_public_inputs
|
||||
);
|
||||
let public_inputs_hash = &proof_with_pis.get_public_inputs_hash();
|
||||
|
||||
let ProofWithPublicInputs { proof, .. } = proof_with_pis;
|
||||
|
||||
let local_constants = &proof.openings.constants;
|
||||
let local_wires = &proof.openings.wires;
|
||||
let vars = EvaluationVars {
|
||||
local_constants,
|
||||
local_wires,
|
||||
public_inputs_hash,
|
||||
public_inputs_hash: &public_inputs_hash,
|
||||
};
|
||||
let local_zs = &proof.openings.plonk_zs;
|
||||
let next_zs = &proof.openings.plonk_zs_right;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user