From fe0c232d6d63dccd4c037a148b4e63850fde01fc Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 14 Jan 2022 07:56:06 +0100 Subject: [PATCH 1/6] Working (not yet for recursion) --- plonky2/src/fri/oracle.rs | 6 ++++++ plonky2/src/fri/verifier.rs | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/plonky2/src/fri/oracle.rs b/plonky2/src/fri/oracle.rs index 2d42e899..9c51bc91 100644 --- a/plonky2/src/fri/oracle.rs +++ b/plonky2/src/fri/oracle.rs @@ -154,6 +154,12 @@ impl, C: GenericConfig, const D: usize> alpha.shift_poly(&mut final_poly); final_poly += quotient; } + final_poly.trim(); + let mut final_poly_coeffs = final_poly.coeffs; + final_poly_coeffs.insert(0, F::Extension::ZERO); + final_poly = PolynomialCoeffs { + coeffs: final_poly_coeffs, + }; let lde_final_poly = final_poly.lde(fri_params.config.rate_bits); let lde_final_values = timed!( diff --git a/plonky2/src/fri/verifier.rs b/plonky2/src/fri/verifier.rs index e95cb80a..2a51f6d9 100644 --- a/plonky2/src/fri/verifier.rs +++ b/plonky2/src/fri/verifier.rs @@ -160,7 +160,7 @@ pub(crate) fn fri_combine_initial< sum += numerator / denominator; } - sum + sum * subgroup_x } fn fri_verifier_query_round< From ec474efe12bd81ac170be605b772b6f99ee32366 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 17 Jan 2022 06:25:03 +0100 Subject: [PATCH 2/6] Minor --- plonky2/src/fri/oracle.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/plonky2/src/fri/oracle.rs b/plonky2/src/fri/oracle.rs index 9c51bc91..27d3e129 100644 --- a/plonky2/src/fri/oracle.rs +++ b/plonky2/src/fri/oracle.rs @@ -155,11 +155,7 @@ impl, C: GenericConfig, const D: usize> final_poly += quotient; } final_poly.trim(); - let mut final_poly_coeffs = final_poly.coeffs; - final_poly_coeffs.insert(0, F::Extension::ZERO); - final_poly = PolynomialCoeffs { - coeffs: final_poly_coeffs, - }; + final_poly.coeffs.insert(0, F::Extension::ZERO); let lde_final_poly = final_poly.lde(fri_params.config.rate_bits); let lde_final_values = timed!( From 6f65620ff2b467b8824ebd61a005501dd1138fa9 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 17 Jan 2022 06:33:23 +0100 Subject: [PATCH 3/6] Add fix for recursive verifier. --- plonky2/src/fri/oracle.rs | 2 ++ plonky2/src/fri/recursive_verifier.rs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/plonky2/src/fri/oracle.rs b/plonky2/src/fri/oracle.rs index 27d3e129..88b0298b 100644 --- a/plonky2/src/fri/oracle.rs +++ b/plonky2/src/fri/oracle.rs @@ -155,6 +155,8 @@ impl, C: GenericConfig, const D: usize> final_poly += quotient; } final_poly.trim(); + // Multiply the final polynomial by `X`, so that `final_poly` has the maximum degree for + // which the LDT will pass. See github.com/mir-protocol/plonky2/pull/434 for details. final_poly.coeffs.insert(0, F::Extension::ZERO); let lde_final_poly = final_poly.lde(fri_params.config.rate_bits); diff --git a/plonky2/src/fri/recursive_verifier.rs b/plonky2/src/fri/recursive_verifier.rs index 526456b6..2a59d457 100644 --- a/plonky2/src/fri/recursive_verifier.rs +++ b/plonky2/src/fri/recursive_verifier.rs @@ -281,7 +281,7 @@ impl, const D: usize> CircuitBuilder { sum = self.div_add_extension(numerator, denominator, sum); } - sum + self.mul_extension(sum, subgroup_x) } fn fri_verifier_query_round>( From 2bb0c4f4e7dffc45a77111e7cc3545f34f6aa0a7 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 17 Jan 2022 06:44:05 +0100 Subject: [PATCH 4/6] Fix comment --- plonky2/src/fri/oracle.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plonky2/src/fri/oracle.rs b/plonky2/src/fri/oracle.rs index 88b0298b..f1dc84eb 100644 --- a/plonky2/src/fri/oracle.rs +++ b/plonky2/src/fri/oracle.rs @@ -156,7 +156,7 @@ impl, C: GenericConfig, const D: usize> } final_poly.trim(); // Multiply the final polynomial by `X`, so that `final_poly` has the maximum degree for - // which the LDT will pass. See github.com/mir-protocol/plonky2/pull/434 for details. + // which the LDT will pass. See github.com/mir-protocol/plonky2/pull/436 for details. final_poly.coeffs.insert(0, F::Extension::ZERO); let lde_final_poly = final_poly.lde(fri_params.config.rate_bits); From 27ebc21faff9f5287278d24a95fc23494d7d5233 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 19 Jan 2022 11:57:46 +0100 Subject: [PATCH 5/6] Add comments for LDT fix in verifier --- plonky2/src/fri/recursive_verifier.rs | 2 ++ plonky2/src/fri/verifier.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/plonky2/src/fri/recursive_verifier.rs b/plonky2/src/fri/recursive_verifier.rs index 2a59d457..63d07035 100644 --- a/plonky2/src/fri/recursive_verifier.rs +++ b/plonky2/src/fri/recursive_verifier.rs @@ -281,6 +281,8 @@ impl, const D: usize> CircuitBuilder { sum = self.div_add_extension(numerator, denominator, sum); } + // Multiply the final polynomial by `X`, so that `final_poly` has the maximum degree for + // which the LDT will pass. See github.com/mir-protocol/plonky2/pull/436 for details. self.mul_extension(sum, subgroup_x) } diff --git a/plonky2/src/fri/verifier.rs b/plonky2/src/fri/verifier.rs index 2a51f6d9..40d1ab25 100644 --- a/plonky2/src/fri/verifier.rs +++ b/plonky2/src/fri/verifier.rs @@ -160,6 +160,8 @@ pub(crate) fn fri_combine_initial< sum += numerator / denominator; } + // Multiply the final polynomial by `X`, so that `final_poly` has the maximum degree for + // which the LDT will pass. See github.com/mir-protocol/plonky2/pull/436 for details. sum * subgroup_x } From 5255c04c700c4cc4a63abf47353d8c92389cbbcc Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 19 Jan 2022 12:31:20 +0100 Subject: [PATCH 6/6] Remove `compute_quotient` and update division tests --- field/src/polynomial/division.rs | 52 +++++++------------------------- plonky2/src/fri/oracle.rs | 27 +---------------- 2 files changed, 12 insertions(+), 67 deletions(-) diff --git a/field/src/polynomial/division.rs b/field/src/polynomial/division.rs index 4f3cafae..d761ab50 100644 --- a/field/src/polynomial/division.rs +++ b/field/src/polynomial/division.rs @@ -67,9 +67,9 @@ impl PolynomialCoeffs { } } - /// Let `self=p(X)`, this returns `(p(X)-p(z))/(X-z)` and `p(z)`. + /// Let `self=p(X)`, this returns `(p(X)-p(z))/(X-z)`. /// See https://en.wikipedia.org/wiki/Horner%27s_method - pub fn divide_by_linear(&self, z: F) -> (PolynomialCoeffs, F) { + pub fn divide_by_linear(&self, z: F) -> PolynomialCoeffs { let mut bs = self .coeffs .iter() @@ -79,9 +79,9 @@ impl PolynomialCoeffs { Some(*acc) }) .collect::>(); - let ev = bs.pop().unwrap_or(F::ZERO); + bs.pop(); bs.reverse(); - (Self { coeffs: bs }, ev) + Self { coeffs: bs } } /// Computes the inverse of `self` modulo `x^n`. @@ -125,7 +125,7 @@ impl PolynomialCoeffs { #[cfg(test)] mod tests { - use std::time::Instant; + use rand::{thread_rng, Rng}; use crate::extension_field::quartic::QuarticExtension; use crate::field_types::Field; @@ -133,47 +133,17 @@ mod tests { use crate::polynomial::PolynomialCoeffs; #[test] - #[ignore] fn test_division_by_linear() { type F = QuarticExtension; - let n = 1_000_000; + let n = thread_rng().gen_range(1..1000); let poly = PolynomialCoeffs::new(F::rand_vec(n)); let z = F::rand(); let ev = poly.eval(z); - let timer = Instant::now(); - let (_quotient, ev2) = poly.div_rem(&PolynomialCoeffs::new(vec![-z, F::ONE])); - println!("{:.3}s for usual", timer.elapsed().as_secs_f32()); - assert_eq!(ev2.trimmed().coeffs, vec![ev]); - - let timer = Instant::now(); - let (quotient, ev3) = poly.div_rem_long_division(&PolynomialCoeffs::new(vec![-z, F::ONE])); - println!("{:.3}s for long division", timer.elapsed().as_secs_f32()); - assert_eq!(ev3.trimmed().coeffs, vec![ev]); - - let timer = Instant::now(); - let horn = poly.divide_by_linear(z); - println!("{:.3}s for Horner", timer.elapsed().as_secs_f32()); - assert_eq!((quotient, ev), horn); - } - - #[test] - #[ignore] - fn test_division_by_quadratic() { - type F = QuarticExtension; - let n = 1_000_000; - let poly = PolynomialCoeffs::new(F::rand_vec(n)); - let quad = PolynomialCoeffs::new(F::rand_vec(2)); - - let timer = Instant::now(); - let (quotient0, rem0) = poly.div_rem(&quad); - println!("{:.3}s for usual", timer.elapsed().as_secs_f32()); - - let timer = Instant::now(); - let (quotient1, rem1) = poly.div_rem_long_division(&quad); - println!("{:.3}s for long division", timer.elapsed().as_secs_f32()); - - assert_eq!(quotient0.trimmed(), quotient1.trimmed()); - assert_eq!(rem0.trimmed(), rem1.trimmed()); + let quotient = poly.divide_by_linear(z); + assert_eq!( + poly, + &("ient * &vec![-z, F::ONE].into()) + &vec![ev].into() // `quotient * (X-z) + ev` + ); } } diff --git a/plonky2/src/fri/oracle.rs b/plonky2/src/fri/oracle.rs index f1dc84eb..c705e125 100644 --- a/plonky2/src/fri/oracle.rs +++ b/plonky2/src/fri/oracle.rs @@ -150,11 +150,10 @@ impl, C: GenericConfig, const D: usize> &format!("reduce batch of {} polynomials", polynomials.len()), alpha.reduce_polys_base(polys_coeff) ); - let quotient = Self::compute_quotient([*point], composition_poly); + let quotient = composition_poly.divide_by_linear(*point); alpha.shift_poly(&mut final_poly); final_poly += quotient; } - final_poly.trim(); // Multiply the final polynomial by `X`, so that `final_poly` has the maximum degree for // which the LDT will pass. See github.com/mir-protocol/plonky2/pull/436 for details. final_poly.coeffs.insert(0, F::Extension::ZERO); @@ -180,28 +179,4 @@ impl, C: GenericConfig, const D: usize> fri_proof } - - /// Given `points=(x_i)`, `evals=(y_i)` and `poly=P` with `P(x_i)=y_i`, computes the polynomial - /// `Q=(P-I)/Z` where `I` interpolates `(x_i, y_i)` and `Z` is the vanishing polynomial on `(x_i)`. - fn compute_quotient( - points: [F::Extension; N], - poly: PolynomialCoeffs, - ) -> PolynomialCoeffs { - let quotient = if N == 1 { - poly.divide_by_linear(points[0]).0 - } else if N == 2 { - // The denominator is `(X - p0)(X - p1) = p0 p1 - (p0 + p1) X + X^2`. - let denominator = vec![ - points[0] * points[1], - -points[0] - points[1], - F::Extension::ONE, - ] - .into(); - poly.div_rem_long_division(&denominator).0 // Could also use `divide_by_linear` twice. - } else { - unreachable!("This shouldn't happen. Plonk should open polynomials at 1 or 2 points.") - }; - - quotient.padded(quotient.degree_plus_one().next_power_of_two()) - } }