From f27620ca901c55f4b5ec71bb8e36476d998802d7 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 17 Jun 2021 19:40:41 +0200 Subject: [PATCH] First impl --- src/fri/verifier.rs | 44 ++++++++++++++++++++++++-------------------- src/proof.rs | 4 ++-- src/util/mod.rs | 1 + src/util/scaling.rs | 41 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 22 deletions(-) create mode 100644 src/util/scaling.rs diff --git a/src/fri/verifier.rs b/src/fri/verifier.rs index b5a650bb..2ce33bd0 100644 --- a/src/fri/verifier.rs +++ b/src/fri/verifier.rs @@ -9,6 +9,7 @@ use crate::merkle_proofs::verify_merkle_proof; use crate::plonk_challenger::Challenger; use crate::plonk_common::reduce_with_iter; use crate::proof::{FriInitialTreeProof, FriProof, FriQueryRound, Hash, OpeningSet}; +use crate::util::scaling::ScalingFactor; use crate::util::{log2_strict, reverse_bits, reverse_index_bits_in_place}; /// Computes P'(x^arity) from {P(x*g^i)}_(i=0..arity), where g is a `arity`-th root of unity @@ -151,7 +152,7 @@ fn fri_combine_initial, const D: usize>( assert!(D > 1, "Not implemented for D=1."); let degree_log = proof.evals_proofs[0].1.siblings.len() - config.rate_bits; let subgroup_x = F::Extension::from_basefield(subgroup_x); - let mut alpha_powers = alpha.powers(); + let mut alpha = ScalingFactor::new(alpha); let mut sum = F::Extension::ZERO; // We will add three terms to `sum`: @@ -160,53 +161,56 @@ fn fri_combine_initial, const D: usize>( // - one for wire polynomials, which are opened at `x` and its conjugate // Polynomials opened at `x`, i.e., the constants, sigmas and quotient polynomials. - let single_evals = [0, 1, 4] - .iter() - .flat_map(|&i| proof.unsalted_evals(i, config)) - .map(|&e| F::Extension::from_basefield(e)); + let single_evals = &proof + .unsalted_evals(0, config) + .into_iter() + .chain(proof.unsalted_evals(1, config)) + .chain(proof.unsalted_evals(4, config)) + .map(|e| F::Extension::from_basefield(e)); let single_openings = os .constants - .iter() - .chain(&os.plonk_s_sigmas) - .chain(&os.quotient_polys); - let single_diffs = single_evals.zip(single_openings).map(|(e, &o)| e - o); - let single_numerator = reduce_with_iter(single_diffs, &mut alpha_powers); + .clone() + .into_iter() + .chain(os.plonk_s_sigmas.clone()) + .chain(os.quotient_polys.clone()); + let single_diffs = single_evals.zip(single_openings).map(|(e, o)| e - o); + dbg!(single_diffs.rev()); + let single_numerator = alpha.scale(single_diffs); let single_denominator = subgroup_x - zeta; sum += single_numerator / single_denominator; + alpha.shift(sum); // Polynomials opened at `x` and `g x`, i.e., the Zs polynomials. let zs_evals = proof .unsalted_evals(3, config) .iter() .map(|&e| F::Extension::from_basefield(e)); - let zs_composition_eval = reduce_with_iter(zs_evals, alpha_powers.clone()); + let zs_composition_eval = alpha.clone().scale(zs_evals); let zeta_right = F::Extension::primitive_root_of_unity(degree_log) * zeta; let zs_interpol = interpolant(&[ - (zeta, reduce_with_iter(&os.plonk_zs, alpha_powers.clone())), - ( - zeta_right, - reduce_with_iter(&os.plonk_zs_right, &mut alpha_powers), - ), + (zeta, alpha.clone().scale(&os.plonk_zs)), + (zeta_right, alpha.scale(&os.plonk_zs_right)), ]); let zs_numerator = zs_composition_eval - zs_interpol.eval(subgroup_x); let zs_denominator = (subgroup_x - zeta) * (subgroup_x - zeta_right); sum += zs_numerator / zs_denominator; + alpha.shift(sum); // Polynomials opened at `x` and `x.frobenius()`, i.e., the wires polynomials. let wire_evals = proof .unsalted_evals(2, config) .iter() .map(|&e| F::Extension::from_basefield(e)); - let wire_composition_eval = reduce_with_iter(wire_evals, alpha_powers.clone()); + let wire_composition_eval = alpha.clone().scale(wire_evals); let zeta_frob = zeta.frobenius(); - let wire_eval = reduce_with_iter(&os.wires, alpha_powers.clone()); + let wire_eval = alpha.clone().scale(&os.wires); // We want to compute `sum a^i*phi(w_i)`, where `phi` denotes the Frobenius automorphism. // Since `phi^D=id` and `phi` is a field automorphism, we have the following equalities: // `sum a^i*phi(w_i) = sum phi(phi^(D-1)(a^i)*w_i) = phi(sum phi^(D-1)(a)^i*w_i)` // So we can compute the original sum using only one call to the `D-1`-repeated Frobenius of alpha, // and one call at the end of the sum. - let alpha_powers_frob = alpha_powers.repeated_frobenius(D - 1); - let wire_eval_frob = reduce_with_iter(&os.wires, alpha_powers_frob).frobenius(); + let mut alpha_frob = alpha.repeated_frobenius(D - 1); + let wire_eval_frob = alpha_frob.scale(&os.wires).frobenius(); let wire_interpol = interpolant(&[(zeta, wire_eval), (zeta_frob, wire_eval_frob)]); let wire_numerator = wire_composition_eval - wire_interpol.eval(subgroup_x); let wire_denominator = (subgroup_x - zeta) * (subgroup_x - zeta_frob); diff --git a/src/proof.rs b/src/proof.rs index e05e4093..a029114a 100644 --- a/src/proof.rs +++ b/src/proof.rs @@ -99,9 +99,9 @@ pub struct FriInitialTreeProof { } impl FriInitialTreeProof { - pub(crate) fn unsalted_evals(&self, i: usize, config: &FriConfig) -> &[F] { + pub(crate) fn unsalted_evals(&self, i: usize, config: &FriConfig) -> Vec { let evals = &self.evals_proofs[i].0; - &evals[..evals.len() - config.salt_size(i)] + evals[..evals.len() - config.salt_size(i)].to_vec() } } diff --git a/src/util/mod.rs b/src/util/mod.rs index 09bd4e72..f901b0af 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,3 +1,4 @@ +pub mod scaling; pub(crate) mod timing; use crate::field::field::Field; diff --git a/src/util/scaling.rs b/src/util/scaling.rs new file mode 100644 index 00000000..36148d85 --- /dev/null +++ b/src/util/scaling.rs @@ -0,0 +1,41 @@ +use std::borrow::Borrow; + +use crate::field::extension_field::Frobenius; +use crate::field::field::Field; + +#[derive(Copy, Clone)] +pub struct ScalingFactor { + base: F, + count: u64, +} + +impl ScalingFactor { + pub fn new(base: F) -> Self { + Self { base, count: 0 } + } + + pub fn mul(&mut self, x: F) -> F { + self.count += 1; + self.base * x + } + + pub fn scale(&mut self, iter: impl DoubleEndedIterator>) -> F { + iter.rev().fold(F::ZERO, |acc, x| self.mul(acc) + x) + } + + pub fn shift(&mut self, x: F) -> F { + let tmp = self.base.exp(self.count) * x; + self.count = 0; + tmp + } + + pub fn repeated_frobenius(&self, count: usize) -> Self + where + F: Frobenius, + { + Self { + base: self.base.repeated_frobenius(count), + count: self.count, + } + } +}