diff --git a/plonky2/src/fri/challenges.rs b/plonky2/src/fri/challenges.rs index ad1cfa5c..82438383 100644 --- a/plonky2/src/fri/challenges.rs +++ b/plonky2/src/fri/challenges.rs @@ -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> Challenger { @@ -78,4 +82,50 @@ impl, H: AlgebraicHasher, const D: usize> self.observe_extension_elements(&v.values); } } + + pub fn fri_challenges>( + &mut self, + builder: &mut CircuitBuilder, + commit_phase_merkle_caps: &[MerkleCapTarget], + final_poly: &PolynomialCoeffsExtTarget, + pow_witness: Target, + inner_common_data: &CommonCircuitData, + ) -> FriChallengesTarget { + 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::(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, + } + } } diff --git a/plonky2/src/fri/proof.rs b/plonky2/src/fri/proof.rs index 1f9e6b16..44f74cba 100644 --- a/plonky2/src/fri/proof.rs +++ b/plonky2/src/fri/proof.rs @@ -375,3 +375,10 @@ pub struct FriChallenges, const D: usize> { // Indices at which the oracle is queried in FRI. pub fri_query_indices: Vec, } + +pub struct FriChallengesTarget { + pub fri_alpha: ExtensionTarget, + pub fri_betas: Vec>, + pub fri_pow_response: Target, + pub fri_query_indices: Vec, +} diff --git a/plonky2/src/plonk/get_challenges.rs b/plonky2/src/plonk/get_challenges.rs index fb1517e4..59701a55 100644 --- a/plonky2/src/plonk/get_challenges.rs +++ b/plonky2/src/plonk/get_challenges.rs @@ -5,14 +5,17 @@ use plonky2_field::polynomial::PolynomialCoeffs; use crate::fri::proof::{CompressedFriProof, FriChallenges, FriProof}; 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, ProofWithPublicInputs, }; use crate::util::reverse_bits; @@ -219,3 +222,58 @@ impl, C: GenericConfig, const D: usize> FriInferredElements(fri_inferred_elements) } } + +impl, const D: usize> CircuitBuilder { + pub(crate) fn get_challenges>( + &mut self, + public_inputs_hash: HashOutTarget, + wires_cap: &MerkleCapTarget, + plonk_zs_partial_products_cap: &MerkleCapTarget, + quotient_polys_cap: &MerkleCapTarget, + openings: &OpeningSetTarget, + commit_phase_merkle_caps: &[MerkleCapTarget], + final_poly: &PolynomialCoeffsExtTarget, + pow_witness: Target, + inner_common_data: &CommonCircuitData, + ) -> ProofChallengesTarget + where + C::Hasher: AlgebraicHasher, + { + let config = &inner_common_data.config; + let num_challenges = config.num_challenges; + + let mut challenger = RecursiveChallenger::::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::( + self, + commit_phase_merkle_caps, + final_poly, + pow_witness, + inner_common_data, + ), + } + } +} diff --git a/plonky2/src/plonk/proof.rs b/plonky2/src/plonk/proof.rs index 2cf0a885..a9bb1210 100644 --- a/plonky2/src/plonk/proof.rs +++ b/plonky2/src/plonk/proof.rs @@ -3,7 +3,9 @@ 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, }; @@ -242,6 +244,14 @@ pub(crate) struct ProofChallenges, const D: usize> pub fri_challenges: FriChallenges, } +pub(crate) struct ProofChallengesTarget { + pub plonk_betas: Vec, + pub plonk_gammas: Vec, + pub plonk_alphas: Vec, + pub plonk_zeta: ExtensionTarget, + pub fri_challenges: FriChallengesTarget, +} + /// Coset elements that can be inferred in the FRI reduction steps. pub(crate) struct FriInferredElements, const D: usize>( pub Vec, diff --git a/plonky2/src/plonk/verifier.rs b/plonky2/src/plonk/verifier.rs index 46d41bfe..da5c9718 100644 --- a/plonky2/src/plonk/verifier.rs +++ b/plonky2/src/plonk/verifier.rs @@ -30,9 +30,9 @@ pub(crate) fn verify_with_challenges< verifier_data: &VerifierOnlyCircuitData, common_data: &CommonCircuitData, ) -> Result<()> { - assert_eq!( - proof_with_pis.public_inputs.len(), - common_data.num_public_inputs + 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();