From bf30fed70158ab0c3a5586c93d39ffa38f54eb95 Mon Sep 17 00:00:00 2001 From: Daniel Lubarov Date: Thu, 6 Jan 2022 11:40:08 -0800 Subject: [PATCH] Make FRI more generic (#419) * Make FRI more generic * PR feedback --- plonky2/src/fri/mod.rs | 3 +- plonky2/src/fri/{commitment.rs => oracle.rs} | 98 ++++---------- plonky2/src/fri/proof.rs | 33 +++-- plonky2/src/fri/recursive_verifier.rs | 132 +++++++------------ plonky2/src/fri/structure.rs | 83 ++++++++++++ plonky2/src/fri/verifier.rs | 101 +++++++------- plonky2/src/plonk/circuit_builder.rs | 8 +- plonky2/src/plonk/circuit_data.rs | 100 +++++++++++++- plonky2/src/plonk/get_challenges.rs | 12 +- plonky2/src/plonk/plonk_common.rs | 66 ++++++---- plonky2/src/plonk/proof.rs | 69 ++++++++-- plonky2/src/plonk/prover.rs | 58 +++++--- plonky2/src/plonk/recursive_verifier.rs | 3 +- plonky2/src/plonk/verifier.rs | 1 + plonky2/src/util/reducing.rs | 9 +- 15 files changed, 476 insertions(+), 300 deletions(-) rename plonky2/src/fri/{commitment.rs => oracle.rs} (69%) create mode 100644 plonky2/src/fri/structure.rs diff --git a/plonky2/src/fri/mod.rs b/plonky2/src/fri/mod.rs index c50d1ff7..d59310de 100644 --- a/plonky2/src/fri/mod.rs +++ b/plonky2/src/fri/mod.rs @@ -1,10 +1,11 @@ use crate::fri::reduction_strategies::FriReductionStrategy; -pub mod commitment; +pub mod oracle; pub mod proof; pub mod prover; pub mod recursive_verifier; pub mod reduction_strategies; +pub mod structure; pub mod verifier; #[derive(Debug, Clone, Eq, PartialEq)] diff --git a/plonky2/src/fri/commitment.rs b/plonky2/src/fri/oracle.rs similarity index 69% rename from plonky2/src/fri/commitment.rs rename to plonky2/src/fri/oracle.rs index 9d7ecf43..ee391953 100644 --- a/plonky2/src/fri/commitment.rs +++ b/plonky2/src/fri/oracle.rs @@ -7,13 +7,12 @@ use rayon::prelude::*; use crate::fri::proof::FriProof; use crate::fri::prover::fri_proof; +use crate::fri::structure::{FriBatchInfo, FriInstanceInfo}; use crate::hash::hash_types::RichField; use crate::hash::merkle_tree::MerkleTree; use crate::iop::challenger::Challenger; use crate::plonk::circuit_data::CommonCircuitData; use crate::plonk::config::GenericConfig; -use crate::plonk::plonk_common::PlonkPolynomials; -use crate::plonk::proof::OpeningSet; use crate::timed; use crate::util::reducing::ReducingFactor; use crate::util::reverse_bits; @@ -23,12 +22,9 @@ use crate::util::transpose; /// Four (~64 bit) field elements gives ~128 bit security. pub const SALT_SIZE: usize = 4; -/// Represents a batch FRI based commitment to a list of polynomials. -pub struct PolynomialBatchCommitment< - F: RichField + Extendable, - C: GenericConfig, - const D: usize, -> { +/// Represents a FRI oracle, i.e. a batch of polynomials which have been Merklized. +pub struct PolynomialBatch, C: GenericConfig, const D: usize> +{ pub polynomials: Vec>, pub merkle_tree: MerkleTree, pub degree_log: usize, @@ -37,7 +33,7 @@ pub struct PolynomialBatchCommitment< } impl, C: GenericConfig, const D: usize> - PolynomialBatchCommitment + PolynomialBatch { /// Creates a list polynomial commitment for the polynomials interpolating the values in `values`. pub(crate) fn from_values( @@ -130,78 +126,36 @@ impl, C: GenericConfig, const D: usize> &slice[..slice.len() - if self.blinding { SALT_SIZE } else { 0 }] } - /// Takes the commitments to the constants - sigmas - wires - zs - quotient — polynomials, - /// and an opening point `zeta` and produces a batched opening proof + opening set. - pub(crate) fn open_plonk( - commitments: &[&Self; 4], - zeta: F::Extension, + /// Produces a batch opening proof. + pub(crate) fn prove_openings( + instance: &FriInstanceInfo, + oracles: &[&Self], challenger: &mut Challenger, common_data: &CommonCircuitData, timing: &mut TimingTree, - ) -> (FriProof, OpeningSet) { - let config = &common_data.config; + ) -> FriProof { assert!(D > 1, "Not implemented for D=1."); - let degree_log = commitments[0].degree_log; - let g = F::Extension::primitive_root_of_unity(degree_log); - for p in &[zeta, g * zeta] { - assert_ne!( - p.exp_u64(1 << degree_log as u64), - F::Extension::ONE, - "Opening point is in the subgroup." - ); - } - - let os = timed!( - timing, - "construct the opening set", - OpeningSet::new( - zeta, - g, - commitments[0], - commitments[1], - commitments[2], - commitments[3], - common_data, - ) - ); - challenger.observe_opening_set(&os); - let alpha = challenger.get_extension_challenge::(); let mut alpha = ReducingFactor::new(alpha); // Final low-degree polynomial that goes into FRI. let mut final_poly = PolynomialCoeffs::empty(); - // All polynomials are opened at `zeta`. - let single_polys = [ - PlonkPolynomials::CONSTANTS_SIGMAS, - PlonkPolynomials::WIRES, - PlonkPolynomials::ZS_PARTIAL_PRODUCTS, - PlonkPolynomials::QUOTIENT, - ] - .iter() - .flat_map(|&p| &commitments[p.index].polynomials); - let single_composition_poly = timed!( - timing, - "reduce single polys", - alpha.reduce_polys_base(single_polys) - ); + for FriBatchInfo { point, polynomials } in &instance.batches { + let polys_coeff = polynomials.iter().map(|fri_poly| { + &oracles[fri_poly.oracle_index].polynomials[fri_poly.polynomial_index] + }); + let composition_poly = timed!( + timing, + &format!("reduce batch of {} polynomials", polynomials.len()), + alpha.reduce_polys_base(polys_coeff) + ); + let quotient = Self::compute_quotient([*point], composition_poly); + alpha.shift_poly(&mut final_poly); + final_poly += quotient; + } - let single_quotient = Self::compute_quotient([zeta], single_composition_poly); - final_poly += single_quotient; - alpha.reset(); - - // Z polynomials have an additional opening at `g zeta`. - let zs_polys = &commitments[PlonkPolynomials::ZS_PARTIAL_PRODUCTS.index].polynomials - [common_data.zs_range()]; - let zs_composition_poly = - timed!(timing, "reduce Z polys", alpha.reduce_polys_base(zs_polys)); - - let zs_quotient = Self::compute_quotient([g * zeta], zs_composition_poly); - alpha.shift_poly(&mut final_poly); - final_poly += zs_quotient; - - let lde_final_poly = final_poly.lde(config.fri_config.rate_bits); + let lde_final_poly = final_poly.lde(common_data.config.fri_config.rate_bits); let lde_final_values = timed!( timing, &format!("perform final FFT {}", lde_final_poly.len()), @@ -209,7 +163,7 @@ impl, C: GenericConfig, const D: usize> ); let fri_proof = fri_proof::( - &commitments + &oracles .par_iter() .map(|c| &c.merkle_tree) .collect::>(), @@ -220,7 +174,7 @@ impl, C: GenericConfig, const D: usize> timing, ); - (fri_proof, os) + fri_proof } /// Given `points=(x_i)`, `evals=(y_i)` and `poly=P` with `P(x_i)=y_i`, computes the polynomial diff --git a/plonky2/src/fri/proof.rs b/plonky2/src/fri/proof.rs index 784f3286..720ae378 100644 --- a/plonky2/src/fri/proof.rs +++ b/plonky2/src/fri/proof.rs @@ -15,7 +15,7 @@ use crate::iop::ext_target::ExtensionTarget; use crate::iop::target::Target; use crate::plonk::circuit_data::CommonCircuitData; use crate::plonk::config::{GenericConfig, Hasher}; -use crate::plonk::plonk_common::PolynomialsIndexBlinding; +use crate::plonk::plonk_common::salt_size; use crate::plonk::proof::{FriInferredElements, ProofChallenges}; /// Evaluations and Merkle proof produced by the prover in a FRI query step. @@ -41,13 +41,13 @@ pub struct FriInitialTreeProof> { } impl> FriInitialTreeProof { - pub(crate) fn unsalted_evals( - &self, - polynomials: PolynomialsIndexBlinding, - zero_knowledge: bool, - ) -> &[F] { - let evals = &self.evals_proofs[polynomials.index].0; - &evals[..evals.len() - polynomials.salt_size(zero_knowledge)] + pub(crate) fn unsalted_eval(&self, oracle_index: usize, poly_index: usize, salted: bool) -> F { + self.unsalted_evals(oracle_index, salted)[poly_index] + } + + fn unsalted_evals(&self, oracle_index: usize, salted: bool) -> &[F] { + let evals = &self.evals_proofs[oracle_index].0; + &evals[..evals.len() - salt_size(salted)] } } @@ -57,13 +57,18 @@ pub struct FriInitialTreeProofTarget { } impl FriInitialTreeProofTarget { - pub(crate) fn unsalted_evals( + pub(crate) fn unsalted_eval( &self, - polynomials: PolynomialsIndexBlinding, - zero_knowledge: bool, - ) -> &[Target] { - let evals = &self.evals_proofs[polynomials.index].0; - &evals[..evals.len() - polynomials.salt_size(zero_knowledge)] + oracle_index: usize, + poly_index: usize, + salted: bool, + ) -> Target { + self.unsalted_evals(oracle_index, salted)[poly_index] + } + + fn unsalted_evals(&self, oracle_index: usize, salted: bool) -> &[Target] { + let evals = &self.evals_proofs[oracle_index].0; + &evals[..evals.len() - salt_size(salted)] } } diff --git a/plonky2/src/fri/recursive_verifier.rs b/plonky2/src/fri/recursive_verifier.rs index 276adc2c..447b045e 100644 --- a/plonky2/src/fri/recursive_verifier.rs +++ b/plonky2/src/fri/recursive_verifier.rs @@ -1,8 +1,9 @@ +use itertools::Itertools; use plonky2_field::extension_field::Extendable; -use plonky2_field::field_types::Field; use plonky2_util::{log2_strict, reverse_index_bits_in_place}; use crate::fri::proof::{FriInitialTreeProofTarget, FriProofTarget, FriQueryRoundTarget}; +use crate::fri::structure::{FriBatchInfoTarget, FriInstanceInfoTarget, FriOpeningsTarget}; use crate::fri::FriConfig; use crate::gadgets::interpolation::InterpolationGate; use crate::gates::gate::Gate; @@ -17,7 +18,6 @@ use crate::iop::target::{BoolTarget, Target}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::{CircuitConfig, CommonCircuitData}; use crate::plonk::config::{AlgebraicConfig, AlgebraicHasher, GenericConfig}; -use crate::plonk::plonk_common::PlonkPolynomials; use crate::plonk::proof::OpeningSetTarget; use crate::util::reducing::ReducingFactorTarget; use crate::with_context; @@ -127,10 +127,9 @@ impl, const D: usize> CircuitBuilder { pub fn verify_fri_proof>( &mut self, + instance: &FriInstanceInfoTarget, // Openings of the PLONK polynomials. os: &OpeningSetTarget, - // Point at which the PLONK polynomials are opened. - zeta: ExtensionTarget, initial_merkle_caps: &[MerkleCapTarget], proof: &FriProofTarget, challenger: &mut RecursiveChallenger, @@ -186,13 +185,7 @@ impl, const D: usize> CircuitBuilder { let precomputed_reduced_evals = with_context!( self, "precompute reduced evaluations", - PrecomputedReducedEvalsTarget::from_os_and_alpha( - os, - alpha, - common_data.degree_bits, - zeta, - self - ) + PrecomputedReducedOpeningsTarget::from_os_and_alpha(&os.to_fri_openings(), alpha, self) ); for (i, round_proof) in proof.query_round_proofs.iter().enumerate() { @@ -211,9 +204,9 @@ impl, const D: usize> CircuitBuilder { level, &format!("verify one (of {}) query rounds", num_queries), self.fri_verifier_query_round( - zeta, + instance, alpha, - precomputed_reduced_evals, + &precomputed_reduced_evals, initial_merkle_caps, proof, challenger, @@ -255,11 +248,11 @@ impl, const D: usize> CircuitBuilder { fn fri_combine_initial>( &mut self, + instance: &FriInstanceInfoTarget, proof: &FriInitialTreeProofTarget, alpha: ExtensionTarget, subgroup_x: Target, - vanish_zeta: ExtensionTarget, - precomputed_reduced_evals: PrecomputedReducedEvalsTarget, + precomputed_reduced_evals: &PrecomputedReducedOpeningsTarget, common_data: &CommonCircuitData, ) -> ExtensionTarget { assert!(D > 1, "Not implemented for D=1."); @@ -274,47 +267,35 @@ impl, const D: usize> CircuitBuilder { let mut alpha = ReducingFactorTarget::new(alpha); let mut sum = self.zero_extension(); - // We will add two terms to `sum`: one for openings at `x`, and one for openings at `g x`. - // All polynomials are opened at `x`. - let single_evals = [ - PlonkPolynomials::CONSTANTS_SIGMAS, - PlonkPolynomials::WIRES, - PlonkPolynomials::ZS_PARTIAL_PRODUCTS, - PlonkPolynomials::QUOTIENT, - ] - .iter() - .flat_map(|&p| proof.unsalted_evals(p, config.zero_knowledge)) - .copied() - .collect::>(); - let single_composition_eval = alpha.reduce_base(&single_evals, self); - let single_numerator = - self.sub_extension(single_composition_eval, precomputed_reduced_evals.single); - sum = self.div_add_extension(single_numerator, vanish_zeta, sum); - alpha.reset(); - - // Polynomials opened at `x` and `g x`, i.e., the Zs polynomials. - let zs_evals = proof - .unsalted_evals(PlonkPolynomials::ZS_PARTIAL_PRODUCTS, config.zero_knowledge) + for (batch, reduced_openings) in instance + .batches .iter() - .take(common_data.zs_range().end) - .copied() - .collect::>(); - let zs_composition_eval = alpha.reduce_base(&zs_evals, self); - - let zs_numerator = - self.sub_extension(zs_composition_eval, precomputed_reduced_evals.zs_right); - let zs_denominator = self.sub_extension(subgroup_x, precomputed_reduced_evals.zeta_right); - sum = alpha.shift(sum, self); // TODO: alpha^count could be precomputed. - sum = self.div_add_extension(zs_numerator, zs_denominator, sum); + .zip(&precomputed_reduced_evals.reduced_openings_at_point) + { + let FriBatchInfoTarget { point, polynomials } = batch; + let evals = polynomials + .iter() + .map(|p| { + let poly_blinding = instance.oracles[p.oracle_index].blinding; + let salted = config.zero_knowledge && poly_blinding; + proof.unsalted_eval(p.oracle_index, p.polynomial_index, salted) + }) + .collect_vec(); + let reduced_evals = alpha.reduce_base(&evals, self); + let numerator = self.sub_extension(reduced_evals, *reduced_openings); + let denominator = self.sub_extension(subgroup_x, *point); + sum = alpha.shift(sum, self); + sum = self.div_add_extension(numerator, denominator, sum); + } sum } fn fri_verifier_query_round>( &mut self, - zeta: ExtensionTarget, + instance: &FriInstanceInfoTarget, alpha: ExtensionTarget, - precomputed_reduced_evals: PrecomputedReducedEvalsTarget, + precomputed_reduced_evals: &PrecomputedReducedOpeningsTarget, initial_merkle_caps: &[MerkleCapTarget], proof: &FriProofTarget, challenger: &mut RecursiveChallenger, @@ -346,16 +327,12 @@ impl, const D: usize> CircuitBuilder { ); // `subgroup_x` is `subgroup[x_index]`, i.e., the actual field element in the domain. - let (mut subgroup_x, vanish_zeta) = with_context!(self, "compute x from its index", { + let mut subgroup_x = with_context!(self, "compute x from its index", { let g = self.constant(F::coset_shift()); let phi = F::primitive_root_of_unity(n_log); let phi = self.exp_from_bits_const_base(phi, x_index_bits.iter().rev()); - let g_ext = self.convert_to_ext(g); - let phi_ext = self.convert_to_ext(phi); - // `subgroup_x = g*phi, vanish_zeta = g*phi - zeta` - let subgroup_x = self.mul(g, phi); - let vanish_zeta = self.mul_sub_extension(g_ext, phi_ext, zeta); - (subgroup_x, vanish_zeta) + // subgroup_x = g * phi + self.mul(g, phi) }); // old_eval is the last derived evaluation; it will be checked for consistency with its @@ -364,10 +341,10 @@ impl, const D: usize> CircuitBuilder { self, "combine initial oracles", self.fri_combine_initial( + instance, &round_proof.initial_trees_proof, alpha, subgroup_x, - vanish_zeta, precomputed_reduced_evals, common_data, ) @@ -455,43 +432,26 @@ impl, const D: usize> CircuitBuilder { } } -#[derive(Copy, Clone)] -struct PrecomputedReducedEvalsTarget { - pub single: ExtensionTarget, - pub zs_right: ExtensionTarget, - pub zeta_right: ExtensionTarget, +/// For each opening point, holds the reduced (by `alpha`) evaluations of each polynomial that's +/// opened at that point. +#[derive(Clone)] +struct PrecomputedReducedOpeningsTarget { + reduced_openings_at_point: Vec>, } -impl PrecomputedReducedEvalsTarget { +impl PrecomputedReducedOpeningsTarget { fn from_os_and_alpha>( - os: &OpeningSetTarget, + openings: &FriOpeningsTarget, alpha: ExtensionTarget, - degree_log: usize, - zeta: ExtensionTarget, builder: &mut CircuitBuilder, ) -> Self { - let mut alpha = ReducingFactorTarget::new(alpha); - let single = alpha.reduce( - &os.constants - .iter() - .chain(&os.plonk_sigmas) - .chain(&os.wires) - .chain(&os.plonk_zs) - .chain(&os.partial_products) - .chain(&os.quotient_polys) - .copied() - .collect::>(), - builder, - ); - let zs_right = alpha.reduce(&os.plonk_zs_right, builder); - - let g = builder.constant_extension(F::Extension::primitive_root_of_unity(degree_log)); - let zeta_right = builder.mul_extension(g, zeta); - + let reduced_openings_at_point = openings + .batches + .iter() + .map(|batch| ReducingFactorTarget::new(alpha).reduce(&batch.values, builder)) + .collect(); Self { - single, - zs_right, - zeta_right, + reduced_openings_at_point, } } } diff --git a/plonky2/src/fri/structure.rs b/plonky2/src/fri/structure.rs new file mode 100644 index 00000000..240abd5d --- /dev/null +++ b/plonky2/src/fri/structure.rs @@ -0,0 +1,83 @@ +//! Information about the structure of a FRI instance, in terms of the oracles and polynomials +//! involved, and the points they are opened at. + +use std::ops::Range; + +use crate::field::extension_field::Extendable; +use crate::hash::hash_types::RichField; +use crate::iop::ext_target::ExtensionTarget; + +/// Describes an instance of a FRI-based batch opening. +pub struct FriInstanceInfo, const D: usize> { + /// The oracles involved, not counting oracles created during the commit phase. + pub oracles: Vec, + /// Batches of openings, where each batch is associated with a particular point. + pub batches: Vec>, +} + +/// Describes an instance of a FRI-based batch opening. +pub struct FriInstanceInfoTarget { + /// The oracles involved, not counting oracles created during the commit phase. + pub oracles: Vec, + /// Batches of openings, where each batch is associated with a particular point. + pub batches: Vec>, +} + +#[derive(Copy, Clone)] +pub struct FriOracleInfo { + pub blinding: bool, +} + +/// A batch of openings at a particular point. +pub struct FriBatchInfo, const D: usize> { + pub point: F::Extension, + pub polynomials: Vec, +} + +/// A batch of openings at a particular point. +pub struct FriBatchInfoTarget { + pub point: ExtensionTarget, + pub polynomials: Vec, +} + +#[derive(Copy, Clone, Debug)] +pub struct FriPolynomialInfo { + /// Index into `FriInstanceInfoTarget`'s `oracles` list. + pub oracle_index: usize, + /// Index of the polynomial within the oracle. + pub polynomial_index: usize, +} + +impl FriPolynomialInfo { + pub fn from_range( + oracle_index: usize, + polynomial_indices: Range, + ) -> Vec { + polynomial_indices + .map(|polynomial_index| FriPolynomialInfo { + oracle_index, + polynomial_index, + }) + .collect() + } +} + +/// Opened values of each polynomial. +pub struct FriOpenings, const D: usize> { + pub batches: Vec>, +} + +/// Opened values of each polynomial that's opened at a particular point. +pub struct FriOpeningBatch, const D: usize> { + pub values: Vec, +} + +/// Opened values of each polynomial. +pub struct FriOpeningsTarget { + pub batches: Vec>, +} + +/// Opened values of each polynomial that's opened at a particular point. +pub struct FriOpeningBatchTarget { + pub values: Vec>, +} diff --git a/plonky2/src/fri/verifier.rs b/plonky2/src/fri/verifier.rs index 4c14f32a..34f7a3dd 100644 --- a/plonky2/src/fri/verifier.rs +++ b/plonky2/src/fri/verifier.rs @@ -5,13 +5,13 @@ use plonky2_field::interpolation::{barycentric_weights, interpolate}; use plonky2_util::{log2_strict, reverse_index_bits_in_place}; use crate::fri::proof::{FriInitialTreeProof, FriProof, FriQueryRound}; +use crate::fri::structure::{FriBatchInfo, FriInstanceInfo, FriOpenings}; use crate::fri::FriConfig; use crate::hash::hash_types::RichField; use crate::hash::merkle_proofs::verify_merkle_proof; use crate::hash::merkle_tree::MerkleCap; use crate::plonk::circuit_data::CommonCircuitData; use crate::plonk::config::{GenericConfig, Hasher}; -use crate::plonk::plonk_common::PlonkPolynomials; use crate::plonk::proof::{OpeningSet, ProofChallenges}; use crate::util::reducing::ReducingFactor; use crate::util::reverse_bits; @@ -63,6 +63,7 @@ pub(crate) fn verify_fri_proof< C: GenericConfig, const D: usize, >( + instance: &FriInstanceInfo, // Openings of the PLONK polynomials. os: &OpeningSet, challenges: &ProofChallenges, @@ -89,15 +90,16 @@ pub(crate) fn verify_fri_proof< ); let precomputed_reduced_evals = - PrecomputedReducedEvals::from_os_and_alpha(os, challenges.fri_alpha); + PrecomputedReducedOpenings::from_os_and_alpha(&os.to_fri_openings(), challenges.fri_alpha); for (&x_index, round_proof) in challenges .fri_query_indices .iter() .zip(&proof.query_round_proofs) { fri_verifier_query_round::( + instance, challenges, - precomputed_reduced_evals, + &precomputed_reduced_evals, initial_merkle_caps, proof, x_index, @@ -127,49 +129,39 @@ pub(crate) fn fri_combine_initial< C: GenericConfig, const D: usize, >( + instance: &FriInstanceInfo, proof: &FriInitialTreeProof, alpha: F::Extension, - zeta: F::Extension, subgroup_x: F, - precomputed_reduced_evals: PrecomputedReducedEvals, + precomputed_reduced_evals: &PrecomputedReducedOpenings, common_data: &CommonCircuitData, ) -> F::Extension { let config = &common_data.config; assert!(D > 1, "Not implemented for D=1."); - let degree_log = common_data.degree_bits; let subgroup_x = F::Extension::from_basefield(subgroup_x); let mut alpha = ReducingFactor::new(alpha); let mut sum = F::Extension::ZERO; - // We will add two terms to `sum`: one for openings at `x`, and one for openings at `g x`. - // All polynomials are opened at `x`. - let single_evals = [ - PlonkPolynomials::CONSTANTS_SIGMAS, - PlonkPolynomials::WIRES, - PlonkPolynomials::ZS_PARTIAL_PRODUCTS, - PlonkPolynomials::QUOTIENT, - ] - .iter() - .flat_map(|&p| proof.unsalted_evals(p, config.zero_knowledge)) - .map(|&e| F::Extension::from_basefield(e)); - let single_composition_eval = alpha.reduce(single_evals); - let single_numerator = single_composition_eval - precomputed_reduced_evals.single; - let single_denominator = subgroup_x - zeta; - sum += single_numerator / single_denominator; - alpha.reset(); - - // Z polynomials have an additional opening at `g x`. - let zs_evals = proof - .unsalted_evals(PlonkPolynomials::ZS_PARTIAL_PRODUCTS, config.zero_knowledge) + for (batch, reduced_openings) in instance + .batches .iter() - .map(|&e| F::Extension::from_basefield(e)) - .take(common_data.zs_range().end); - let zs_composition_eval = alpha.reduce(zs_evals); - let zeta_right = F::Extension::primitive_root_of_unity(degree_log) * zeta; - let zs_numerator = zs_composition_eval - precomputed_reduced_evals.zs_right; - let zs_denominator = subgroup_x - zeta_right; - sum = alpha.shift(sum); - sum += zs_numerator / zs_denominator; + .zip(&precomputed_reduced_evals.reduced_openings_at_point) + { + let FriBatchInfo { point, polynomials } = batch; + let evals = polynomials + .iter() + .map(|p| { + let poly_blinding = instance.oracles[p.oracle_index].blinding; + let salted = config.zero_knowledge && poly_blinding; + proof.unsalted_eval(p.oracle_index, p.polynomial_index, salted) + }) + .map(F::Extension::from_basefield); + let reduced_evals = alpha.reduce(evals); + let numerator = reduced_evals - *reduced_openings; + let denominator = subgroup_x - *point; + sum = alpha.shift(sum); + sum += numerator / denominator; + } sum } @@ -179,8 +171,9 @@ fn fri_verifier_query_round< C: GenericConfig, const D: usize, >( + instance: &FriInstanceInfo, challenges: &ProofChallenges, - precomputed_reduced_evals: PrecomputedReducedEvals, + precomputed_reduced_evals: &PrecomputedReducedOpenings, initial_merkle_caps: &[MerkleCap], proof: &FriProof, mut x_index: usize, @@ -201,9 +194,9 @@ fn fri_verifier_query_round< // old_eval is the last derived evaluation; it will be checked for consistency with its // committed "parent" value in the next iteration. let mut old_eval = fri_combine_initial( + instance, &round_proof.initial_trees_proof, challenges.fri_alpha, - challenges.plonk_zeta, subgroup_x, precomputed_reduced_evals, common_data, @@ -257,28 +250,22 @@ fn fri_verifier_query_round< Ok(()) } -/// Holds the reduced (by `alpha`) evaluations at `zeta` for the polynomial opened just at -/// zeta, for `Z` at zeta and for `Z` at `g*zeta`. -#[derive(Copy, Clone, Debug)] -pub(crate) struct PrecomputedReducedEvals, const D: usize> { - pub single: F::Extension, - pub zs_right: F::Extension, +/// For each opening point, holds the reduced (by `alpha`) evaluations of each polynomial that's +/// opened at that point. +#[derive(Clone, Debug)] +pub(crate) struct PrecomputedReducedOpenings, const D: usize> { + pub reduced_openings_at_point: Vec, } -impl, const D: usize> PrecomputedReducedEvals { - pub(crate) fn from_os_and_alpha(os: &OpeningSet, alpha: F::Extension) -> Self { - let mut alpha = ReducingFactor::new(alpha); - let single = alpha.reduce( - os.constants - .iter() - .chain(&os.plonk_sigmas) - .chain(&os.wires) - .chain(&os.plonk_zs) - .chain(&os.partial_products) - .chain(&os.quotient_polys), - ); - let zs_right = alpha.reduce(os.plonk_zs_right.iter()); - - Self { single, zs_right } +impl, const D: usize> PrecomputedReducedOpenings { + pub(crate) fn from_os_and_alpha(openings: &FriOpenings, alpha: F::Extension) -> Self { + let reduced_openings_at_point = openings + .batches + .iter() + .map(|batch| ReducingFactor::new(alpha).reduce(batch.values.iter())) + .collect(); + Self { + reduced_openings_at_point, + } } } diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index 2456d6fd..ca9f5a6b 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -10,7 +10,7 @@ use plonky2_field::field_types::Field; use plonky2_field::polynomial::PolynomialValues; use plonky2_util::{log2_ceil, log2_strict}; -use crate::fri::commitment::PolynomialBatchCommitment; +use crate::fri::oracle::PolynomialBatch; use crate::fri::{FriConfig, FriParams}; use crate::gadgets::arithmetic::BaseArithmeticOperation; use crate::gadgets::arithmetic_extension::ExtensionArithmeticOperation; @@ -41,7 +41,7 @@ use crate::plonk::circuit_data::{ use crate::plonk::config::{GenericConfig, Hasher}; use crate::plonk::copy_constraint::CopyConstraint; use crate::plonk::permutation_argument::Forest; -use crate::plonk::plonk_common::PlonkPolynomials; +use crate::plonk::plonk_common::PlonkOracle; use crate::util::context_tree::ContextTree; use crate::util::marking::{Markable, MarkedTargets}; use crate::util::partial_products::num_partial_products; @@ -641,10 +641,10 @@ impl, const D: usize> CircuitBuilder { let fft_root_table = fft_root_table(max_fft_points); let constants_sigmas_vecs = [constant_vecs, sigma_vecs.clone()].concat(); - let constants_sigmas_commitment = PolynomialBatchCommitment::from_values( + let constants_sigmas_commitment = PolynomialBatch::from_values( constants_sigmas_vecs, rate_bits, - self.config.zero_knowledge & PlonkPolynomials::CONSTANTS_SIGMAS.blinding, + PlonkOracle::CONSTANTS_SIGMAS.blinding, self.config.fri_config.cap_height, &mut timing, Some(&fft_root_table), diff --git a/plonky2/src/plonk/circuit_data.rs b/plonky2/src/plonk/circuit_data.rs index 74308fc3..a0ef65e4 100644 --- a/plonky2/src/plonk/circuit_data.rs +++ b/plonky2/src/plonk/circuit_data.rs @@ -5,16 +5,23 @@ use anyhow::Result; use plonky2_field::extension_field::Extendable; use plonky2_field::fft::FftRootTable; -use crate::fri::commitment::PolynomialBatchCommitment; +use crate::field::field_types::Field; +use crate::fri::oracle::PolynomialBatch; use crate::fri::reduction_strategies::FriReductionStrategy; +use crate::fri::structure::{ + FriBatchInfo, FriBatchInfoTarget, FriInstanceInfo, FriInstanceInfoTarget, FriPolynomialInfo, +}; use crate::fri::{FriConfig, FriParams}; use crate::gates::gate::PrefixedGate; use crate::hash::hash_types::{MerkleCapTarget, RichField}; use crate::hash::merkle_tree::MerkleCap; +use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::WitnessGenerator; use crate::iop::target::Target; use crate::iop::witness::PartialWitness; +use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::config::{GenericConfig, Hasher}; +use crate::plonk::plonk_common::{PlonkOracle, FRI_ORACLES}; use crate::plonk::proof::{CompressedProofWithPublicInputs, ProofWithPublicInputs}; use crate::plonk::prover::prove; use crate::plonk::verifier::verify; @@ -178,7 +185,7 @@ pub(crate) struct ProverOnlyCircuitData< /// they watch. pub generator_indices_by_watches: BTreeMap>, /// Commitments to the constants polynomials and sigma polynomials. - pub constants_sigmas_commitment: PolynomialBatchCommitment, + pub constants_sigmas_commitment: PolynomialBatch, /// The transpose of the list of sigma polynomials. pub sigmas: Vec>, /// Subgroup of order `degree`. @@ -286,6 +293,95 @@ impl, C: GenericConfig, const D: usize> pub fn partial_products_range(&self) -> RangeFrom { self.config.num_challenges.. } + + pub(crate) fn get_fri_instance(&self, zeta: F::Extension) -> FriInstanceInfo { + // All polynomials are opened at zeta. + let zeta_batch = FriBatchInfo { + point: zeta, + polynomials: self.fri_all_polys(), + }; + + // The Z polynomials are also opened at g * zeta. + let g = F::Extension::primitive_root_of_unity(self.degree_bits); + let zeta_right = g * zeta; + let zeta_right_batch = FriBatchInfo { + point: zeta_right, + polynomials: self.fri_zs_polys(), + }; + + let openings = vec![zeta_batch, zeta_right_batch]; + FriInstanceInfo { + oracles: FRI_ORACLES.to_vec(), + batches: openings, + } + } + + pub(crate) fn get_fri_instance_target( + &self, + builder: &mut CircuitBuilder, + zeta: ExtensionTarget, + ) -> FriInstanceInfoTarget { + // All polynomials are opened at zeta. + let zeta_batch = FriBatchInfoTarget { + point: zeta, + polynomials: self.fri_all_polys(), + }; + + // The Z polynomials are also opened at g * zeta. + let g = F::primitive_root_of_unity(self.degree_bits); + let zeta_right = builder.mul_const_extension(g, zeta); + let zeta_right_batch = FriBatchInfoTarget { + point: zeta_right, + polynomials: self.fri_zs_polys(), + }; + + let openings = vec![zeta_batch, zeta_right_batch]; + FriInstanceInfoTarget { + oracles: FRI_ORACLES.to_vec(), + batches: openings, + } + } + + fn fri_preprocessed_polys(&self) -> Vec { + let num_preprocessed_polys = self.sigmas_range().end; + FriPolynomialInfo::from_range( + PlonkOracle::CONSTANTS_SIGMAS.index, + 0..num_preprocessed_polys, + ) + } + + fn fri_wire_polys(&self) -> Vec { + let num_wire_polys = self.config.num_wires; + FriPolynomialInfo::from_range(PlonkOracle::WIRES.index, 0..num_wire_polys) + } + + fn fri_zs_partial_products_polys(&self) -> Vec { + let num_zs_partial_products_polys = + self.config.num_challenges * (1 + self.num_partial_products.0); + FriPolynomialInfo::from_range( + PlonkOracle::ZS_PARTIAL_PRODUCTS.index, + 0..num_zs_partial_products_polys, + ) + } + + fn fri_zs_polys(&self) -> Vec { + FriPolynomialInfo::from_range(PlonkOracle::ZS_PARTIAL_PRODUCTS.index, self.zs_range()) + } + + fn fri_quotient_polys(&self) -> Vec { + let num_quotient_polys = self.config.num_challenges * self.quotient_degree_factor; + FriPolynomialInfo::from_range(PlonkOracle::QUOTIENT.index, 0..num_quotient_polys) + } + + fn fri_all_polys(&self) -> Vec { + [ + self.fri_preprocessed_polys(), + self.fri_wire_polys(), + self.fri_zs_partial_products_polys(), + self.fri_quotient_polys(), + ] + .concat() + } } /// The `Target` version of `VerifierCircuitData`, for use inside recursive circuits. Note that this diff --git a/plonky2/src/plonk/get_challenges.rs b/plonky2/src/plonk/get_challenges.rs index 23e7f454..bbb91d79 100644 --- a/plonky2/src/plonk/get_challenges.rs +++ b/plonky2/src/plonk/get_challenges.rs @@ -4,7 +4,7 @@ use plonky2_field::extension_field::Extendable; use plonky2_field::polynomial::PolynomialCoeffs; use crate::fri::proof::{CompressedFriProof, FriProof}; -use crate::fri::verifier::{compute_evaluation, fri_combine_initial, PrecomputedReducedEvals}; +use crate::fri::verifier::{compute_evaluation, fri_combine_initial, PrecomputedReducedOpenings}; use crate::hash::hash_types::RichField; use crate::hash::merkle_tree::MerkleCap; use crate::iop::challenger::Challenger; @@ -187,8 +187,10 @@ impl, C: GenericConfig, const D: usize> // Holds the indices that have already been seen at each reduction depth. let mut seen_indices_by_depth = vec![HashSet::new(); common_data.fri_params.reduction_arity_bits.len()]; - let precomputed_reduced_evals = - PrecomputedReducedEvals::from_os_and_alpha(&self.proof.openings, *fri_alpha); + let precomputed_reduced_evals = PrecomputedReducedOpenings::from_os_and_alpha( + &self.proof.openings.to_fri_openings(), + *fri_alpha, + ); let log_n = common_data.degree_bits + common_data.config.fri_config.rate_bits; // Simulate the proof verification and collect the inferred elements. // The content of the loop is basically the same as the `fri_verifier_query_round` function. @@ -196,15 +198,15 @@ impl, C: GenericConfig, const D: usize> let mut subgroup_x = F::MULTIPLICATIVE_GROUP_GENERATOR * F::primitive_root_of_unity(log_n).exp_u64(reverse_bits(x_index, log_n) as u64); let mut old_eval = fri_combine_initial( + &common_data.get_fri_instance(*plonk_zeta), &self .proof .opening_proof .query_round_proofs .initial_trees_proofs[&x_index], *fri_alpha, - *plonk_zeta, subgroup_x, - precomputed_reduced_evals, + &precomputed_reduced_evals, common_data, ); for (i, &arity_bits) in common_data diff --git a/plonky2/src/plonk/plonk_common.rs b/plonky2/src/plonk/plonk_common.rs index 5b8119aa..92c4168d 100644 --- a/plonky2/src/plonk/plonk_common.rs +++ b/plonky2/src/plonk/plonk_common.rs @@ -2,49 +2,59 @@ use plonky2_field::extension_field::Extendable; use plonky2_field::field_types::Field; use plonky2_field::packed_field::PackedField; -use crate::fri::commitment::SALT_SIZE; +use crate::fri::oracle::SALT_SIZE; +use crate::fri::structure::FriOracleInfo; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::reducing::ReducingFactorTarget; +pub(crate) const FRI_ORACLES: [FriOracleInfo; 4] = [ + PlonkOracle::CONSTANTS_SIGMAS.as_fri_oracle(), + PlonkOracle::WIRES.as_fri_oracle(), + PlonkOracle::ZS_PARTIAL_PRODUCTS.as_fri_oracle(), + PlonkOracle::QUOTIENT.as_fri_oracle(), +]; + /// Holds the Merkle tree index and blinding flag of a set of polynomials used in FRI. #[derive(Debug, Copy, Clone)] -pub struct PolynomialsIndexBlinding { +pub struct PlonkOracle { pub(crate) index: usize, pub(crate) blinding: bool, } -impl PolynomialsIndexBlinding { - pub fn salt_size(&self, zero_knowledge: bool) -> usize { - if zero_knowledge & self.blinding { - SALT_SIZE - } else { - 0 + +impl PlonkOracle { + pub const CONSTANTS_SIGMAS: PlonkOracle = PlonkOracle { + index: 0, + blinding: false, + }; + pub const WIRES: PlonkOracle = PlonkOracle { + index: 1, + blinding: true, + }; + pub const ZS_PARTIAL_PRODUCTS: PlonkOracle = PlonkOracle { + index: 2, + blinding: true, + }; + pub const QUOTIENT: PlonkOracle = PlonkOracle { + index: 3, + blinding: true, + }; + + pub(crate) const fn as_fri_oracle(&self) -> FriOracleInfo { + FriOracleInfo { + blinding: self.blinding, } } } -/// Holds the indices and blinding flags of the Plonk polynomials. -pub struct PlonkPolynomials; - -impl PlonkPolynomials { - pub const CONSTANTS_SIGMAS: PolynomialsIndexBlinding = PolynomialsIndexBlinding { - index: 0, - blinding: false, - }; - pub const WIRES: PolynomialsIndexBlinding = PolynomialsIndexBlinding { - index: 1, - blinding: true, - }; - pub const ZS_PARTIAL_PRODUCTS: PolynomialsIndexBlinding = PolynomialsIndexBlinding { - index: 2, - blinding: true, - }; - pub const QUOTIENT: PolynomialsIndexBlinding = PolynomialsIndexBlinding { - index: 3, - blinding: true, - }; +pub fn salt_size(salted: bool) -> usize { + if salted { + SALT_SIZE + } else { + 0 + } } /// Evaluate the polynomial which vanishes on any multiplicative subgroup of a given order `n`. diff --git a/plonky2/src/plonk/proof.rs b/plonky2/src/plonk/proof.rs index 91db2b25..c2dd47f3 100644 --- a/plonky2/src/plonk/proof.rs +++ b/plonky2/src/plonk/proof.rs @@ -2,8 +2,11 @@ use plonky2_field::extension_field::Extendable; use rayon::prelude::*; use serde::{Deserialize, Serialize}; -use crate::fri::commitment::PolynomialBatchCommitment; +use crate::fri::oracle::PolynomialBatch; use crate::fri::proof::{CompressedFriProof, FriProof, FriProofTarget}; +use crate::fri::structure::{ + FriOpeningBatch, FriOpeningBatchTarget, FriOpenings, FriOpeningsTarget, +}; use crate::hash::hash_types::{MerkleCapTarget, RichField}; use crate::hash::merkle_tree::MerkleCap; use crate::iop::ext_target::ExtensionTarget; @@ -274,33 +277,53 @@ pub struct OpeningSet, const D: usize> { impl, const D: usize> OpeningSet { pub fn new>( - z: F::Extension, + zeta: F::Extension, g: F::Extension, - constants_sigmas_commitment: &PolynomialBatchCommitment, - wires_commitment: &PolynomialBatchCommitment, - zs_partial_products_commitment: &PolynomialBatchCommitment, - quotient_polys_commitment: &PolynomialBatchCommitment, + constants_sigmas_commitment: &PolynomialBatch, + wires_commitment: &PolynomialBatch, + zs_partial_products_commitment: &PolynomialBatch, + quotient_polys_commitment: &PolynomialBatch, common_data: &CommonCircuitData, ) -> Self { - let eval_commitment = |z: F::Extension, c: &PolynomialBatchCommitment| { + let eval_commitment = |z: F::Extension, c: &PolynomialBatch| { c.polynomials .par_iter() .map(|p| p.to_extension().eval(z)) .collect::>() }; - let constants_sigmas_eval = eval_commitment(z, constants_sigmas_commitment); - let zs_partial_products_eval = eval_commitment(z, zs_partial_products_commitment); + let constants_sigmas_eval = eval_commitment(zeta, constants_sigmas_commitment); + let zs_partial_products_eval = eval_commitment(zeta, zs_partial_products_commitment); Self { constants: constants_sigmas_eval[common_data.constants_range()].to_vec(), plonk_sigmas: constants_sigmas_eval[common_data.sigmas_range()].to_vec(), - wires: eval_commitment(z, wires_commitment), + wires: eval_commitment(zeta, wires_commitment), plonk_zs: zs_partial_products_eval[common_data.zs_range()].to_vec(), - plonk_zs_right: eval_commitment(g * z, zs_partial_products_commitment) + plonk_zs_right: eval_commitment(g * zeta, zs_partial_products_commitment) [common_data.zs_range()] .to_vec(), partial_products: zs_partial_products_eval[common_data.partial_products_range()] .to_vec(), - quotient_polys: eval_commitment(z, quotient_polys_commitment), + quotient_polys: eval_commitment(zeta, quotient_polys_commitment), + } + } + + pub(crate) fn to_fri_openings(&self) -> FriOpenings { + let zeta_batch = FriOpeningBatch { + values: [ + self.constants.as_slice(), + self.plonk_sigmas.as_slice(), + self.wires.as_slice(), + self.plonk_zs.as_slice(), + self.partial_products.as_slice(), + self.quotient_polys.as_slice(), + ] + .concat(), + }; + let zeta_right_batch = FriOpeningBatch { + values: self.plonk_zs_right.clone(), + }; + FriOpenings { + batches: vec![zeta_batch, zeta_right_batch], } } } @@ -317,6 +340,28 @@ pub struct OpeningSetTarget { pub quotient_polys: Vec>, } +impl OpeningSetTarget { + pub(crate) fn to_fri_openings(&self) -> FriOpeningsTarget { + let zeta_batch = FriOpeningBatchTarget { + values: [ + self.constants.as_slice(), + self.plonk_sigmas.as_slice(), + self.wires.as_slice(), + self.plonk_zs.as_slice(), + self.partial_products.as_slice(), + self.quotient_polys.as_slice(), + ] + .concat(), + }; + let zeta_right_batch = FriOpeningBatchTarget { + values: self.plonk_zs_right.clone(), + }; + FriOpeningsTarget { + batches: vec![zeta_batch, zeta_right_batch], + } + } +} + #[cfg(test)] mod tests { use anyhow::Result; diff --git a/plonky2/src/plonk/prover.rs b/plonky2/src/plonk/prover.rs index f7196270..abd2c552 100644 --- a/plonky2/src/plonk/prover.rs +++ b/plonky2/src/plonk/prover.rs @@ -1,20 +1,22 @@ use std::mem::swap; +use anyhow::ensure; use anyhow::Result; use plonky2_field::extension_field::Extendable; use plonky2_field::polynomial::{PolynomialCoeffs, PolynomialValues}; use plonky2_util::log2_ceil; use rayon::prelude::*; -use crate::fri::commitment::PolynomialBatchCommitment; +use crate::field::field_types::Field; +use crate::fri::oracle::PolynomialBatch; use crate::hash::hash_types::RichField; use crate::iop::challenger::Challenger; use crate::iop::generator::generate_partial_witness; use crate::iop::witness::{MatrixWitness, PartialWitness, Witness}; use crate::plonk::circuit_data::{CommonCircuitData, ProverOnlyCircuitData}; use crate::plonk::config::{GenericConfig, Hasher}; -use crate::plonk::plonk_common::PlonkPolynomials; -use crate::plonk::plonk_common::ZeroPolyOnCoset; +use crate::plonk::plonk_common::{PlonkOracle, ZeroPolyOnCoset}; +use crate::plonk::proof::OpeningSet; use crate::plonk::proof::{Proof, ProofWithPublicInputs}; use crate::plonk::vanishing_poly::eval_vanishing_poly_base_batch; use crate::plonk::vars::EvaluationVarsBaseBatch; @@ -69,10 +71,10 @@ pub(crate) fn prove, C: GenericConfig, co let wires_commitment = timed!( timing, "compute wires commitment", - PolynomialBatchCommitment::from_values( + PolynomialBatch::from_values( wires_values, config.fri_config.rate_bits, - config.zero_knowledge & PlonkPolynomials::WIRES.blinding, + config.zero_knowledge && PlonkOracle::WIRES.blinding, config.fri_config.cap_height, timing, prover_data.fft_root_table.as_ref(), @@ -109,10 +111,10 @@ pub(crate) fn prove, C: GenericConfig, co let partial_products_and_zs_commitment = timed!( timing, "commit to partial products and Z's", - PolynomialBatchCommitment::from_values( + PolynomialBatch::from_values( zs_partial_products, config.fri_config.rate_bits, - config.zero_knowledge & PlonkPolynomials::ZS_PARTIAL_PRODUCTS.blinding, + config.zero_knowledge && PlonkOracle::ZS_PARTIAL_PRODUCTS.blinding, config.fri_config.cap_height, timing, prover_data.fft_root_table.as_ref(), @@ -158,10 +160,10 @@ pub(crate) fn prove, C: GenericConfig, co let quotient_polys_commitment = timed!( timing, "commit to quotient polys", - PolynomialBatchCommitment::from_coeffs( + PolynomialBatch::from_coeffs( all_quotient_poly_chunks, config.fri_config.rate_bits, - config.zero_knowledge & PlonkPolynomials::QUOTIENT.blinding, + config.zero_knowledge && PlonkOracle::QUOTIENT.blinding, config.fri_config.cap_height, timing, prover_data.fft_root_table.as_ref(), @@ -171,18 +173,41 @@ pub(crate) fn prove, C: GenericConfig, co challenger.observe_cap("ient_polys_commitment.merkle_tree.cap); let zeta = challenger.get_extension_challenge::(); + // To avoid leaking witness data, we want to ensure that our opening locations, `zeta` and + // `g * zeta`, are not in our subgroup `H`. It suffices to check `zeta` only, since + // `(g * zeta)^n = zeta^n`, where `n` is the order of `g`. + let g = F::Extension::primitive_root_of_unity(common_data.degree_bits); + ensure!( + zeta.exp_power_of_2(common_data.degree_bits) != F::Extension::ONE, + "Opening point is in the subgroup." + ); - let (opening_proof, openings) = timed!( + let openings = timed!( + timing, + "construct the opening set", + OpeningSet::new( + zeta, + g, + &prover_data.constants_sigmas_commitment, + &wires_commitment, + &partial_products_and_zs_commitment, + "ient_polys_commitment, + common_data, + ) + ); + challenger.observe_opening_set(&openings); + + let opening_proof = timed!( timing, "compute opening proofs", - PolynomialBatchCommitment::open_plonk( + PolynomialBatch::prove_openings( + &common_data.get_fri_instance(zeta), &[ &prover_data.constants_sigmas_commitment, &wires_commitment, &partial_products_and_zs_commitment, "ient_polys_commitment, ], - zeta, &mut challenger, common_data, timing, @@ -300,8 +325,8 @@ fn compute_quotient_polys< common_data: &CommonCircuitData, prover_data: &'a ProverOnlyCircuitData, public_inputs_hash: &<>::InnerHasher as Hasher>::Hash, - wires_commitment: &'a PolynomialBatchCommitment, - zs_partial_products_commitment: &'a PolynomialBatchCommitment, + wires_commitment: &'a PolynomialBatch, + zs_partial_products_commitment: &'a PolynomialBatch, betas: &[F], gammas: &[F], alphas: &[F], @@ -325,9 +350,8 @@ fn compute_quotient_polys< let lde_size = points.len(); // Retrieve the LDE values at index `i`. - let get_at_index = |comm: &'a PolynomialBatchCommitment, i: usize| -> &'a [F] { - comm.get_lde_values(i * step) - }; + let get_at_index = + |comm: &'a PolynomialBatch, i: usize| -> &'a [F] { comm.get_lde_values(i * step) }; let z_h_on_coset = ZeroPolyOnCoset::new(common_data.degree_bits, max_degree_bits); diff --git a/plonky2/src/plonk/recursive_verifier.rs b/plonky2/src/plonk/recursive_verifier.rs index dc6f5039..ba653e22 100644 --- a/plonky2/src/plonk/recursive_verifier.rs +++ b/plonky2/src/plonk/recursive_verifier.rs @@ -107,12 +107,13 @@ impl, const D: usize> CircuitBuilder { proof.quotient_polys_cap, ]; + let fri_instance = inner_common_data.get_fri_instance_target(self, zeta); with_context!( self, "verify FRI proof", self.verify_fri_proof( + &fri_instance, &proof.openings, - zeta, merkle_caps, &proof.opening_proof, &mut challenger, diff --git a/plonky2/src/plonk/verifier.rs b/plonky2/src/plonk/verifier.rs index c3cf4988..3dca02a7 100644 --- a/plonky2/src/plonk/verifier.rs +++ b/plonky2/src/plonk/verifier.rs @@ -86,6 +86,7 @@ pub(crate) fn verify_with_challenges< ]; verify_fri_proof( + &common_data.get_fri_instance(challenges.plonk_zeta), &proof.openings, &challenges, merkle_caps, diff --git a/plonky2/src/util/reducing.rs b/plonky2/src/util/reducing.rs index 8bfe45d1..b4e8d8cf 100644 --- a/plonky2/src/util/reducing.rs +++ b/plonky2/src/util/reducing.rs @@ -238,7 +238,14 @@ impl ReducingFactorTarget { where F: RichField + Extendable, { - let exp = builder.exp_u64_extension(self.base, self.count); + let zero_ext = builder.zero_extension(); + let exp = if x == zero_ext { + // The result will get zeroed out, so don't actually compute the exponentiation. + zero_ext + } else { + builder.exp_u64_extension(self.base, self.count) + }; + self.count = 0; builder.mul_extension(exp, x) }