diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 00000000..65106950 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,2 @@ +unstable_features = true +group_imports = "StdExternalCrate" diff --git a/src/bin/bench_ldes.rs b/src/bin/bench_ldes.rs index 1fb02d65..e6d7c457 100644 --- a/src/bin/bench_ldes.rs +++ b/src/bin/bench_ldes.rs @@ -1,10 +1,9 @@ use std::time::Instant; -use rayon::prelude::*; - use plonky2::field::crandall_field::CrandallField; use plonky2::field::field::Field; use plonky2::polynomial::polynomial::PolynomialValues; +use rayon::prelude::*; type F = CrandallField; diff --git a/src/bin/bench_recursion.rs b/src/bin/bench_recursion.rs index 35ba280d..19f7716c 100644 --- a/src/bin/bench_recursion.rs +++ b/src/bin/bench_recursion.rs @@ -1,5 +1,4 @@ use env_logger::Env; - use plonky2::circuit_builder::CircuitBuilder; use plonky2::circuit_data::CircuitConfig; use plonky2::field::crandall_field::CrandallField; diff --git a/src/field/crandall_field.rs b/src/field/crandall_field.rs index 81a2c9e6..dbd29cb2 100644 --- a/src/field/crandall_field.rs +++ b/src/field/crandall_field.rs @@ -1,5 +1,7 @@ use std::fmt; use std::fmt::{Debug, Display, Formatter}; +use std::hash::{Hash, Hasher}; +use std::iter::{Product, Sum}; use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use num::Integer; @@ -8,8 +10,6 @@ use crate::field::extension_field::quadratic::QuadraticCrandallField; use crate::field::extension_field::quartic::QuarticCrandallField; use crate::field::extension_field::{Extendable, Frobenius}; use crate::field::field::Field; -use std::hash::{Hash, Hasher}; -use std::iter::{Product, Sum}; /// EPSILON = 9 * 2**28 - 1 const EPSILON: u64 = 2415919103; diff --git a/src/field/extension_field/algebra.rs b/src/field/extension_field/algebra.rs index f61f173b..fcd60185 100644 --- a/src/field/extension_field/algebra.rs +++ b/src/field/extension_field/algebra.rs @@ -1,8 +1,9 @@ -use crate::field::extension_field::OEF; use std::fmt::{Debug, Display, Formatter}; use std::iter::{Product, Sum}; use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; +use crate::field::extension_field::OEF; + /// Let `F_D` be the optimal extension field `F[X]/(X^D-W)`. Then `ExtensionAlgebra` is the quotient `F_D[X]/(X^D-W)`. /// It's a `D`-dimensional algebra over `F_D` useful to lift the multiplication over `F_D` to a multiplication over `(F_D)^D`. #[derive(Copy, Clone)] @@ -154,11 +155,12 @@ impl, const D: usize> PolynomialCoeffsAlgebra { #[cfg(test)] mod tests { + use itertools::Itertools; + use crate::field::crandall_field::CrandallField; use crate::field::extension_field::algebra::ExtensionAlgebra; use crate::field::extension_field::{Extendable, FieldExtension}; use crate::field::field::Field; - use itertools::Itertools; /// Tests that the multiplication on the extension algebra lifts that of the field extension. fn test_extension_algebra, const D: usize>() { diff --git a/src/field/extension_field/quadratic.rs b/src/field/extension_field/quadratic.rs index 4bf0c08d..4dc712af 100644 --- a/src/field/extension_field/quadratic.rs +++ b/src/field/extension_field/quadratic.rs @@ -1,12 +1,14 @@ -use crate::field::crandall_field::CrandallField; -use crate::field::extension_field::{FieldExtension, Frobenius, OEF}; -use crate::field::field::Field; -use rand::Rng; use std::fmt::{Debug, Display, Formatter}; use std::hash::Hash; use std::iter::{Product, Sum}; use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; +use rand::Rng; + +use crate::field::crandall_field::CrandallField; +use crate::field::extension_field::{FieldExtension, Frobenius, OEF}; +use crate::field::field::Field; + #[derive(Copy, Clone, Eq, PartialEq, Hash)] pub struct QuadraticCrandallField([CrandallField; 2]); diff --git a/src/field/extension_field/target.rs b/src/field/extension_field/target.rs index 9d078e15..0f9a7e24 100644 --- a/src/field/extension_field/target.rs +++ b/src/field/extension_field/target.rs @@ -1,12 +1,12 @@ +use std::convert::{TryFrom, TryInto}; +use std::ops::Range; + use crate::circuit_builder::CircuitBuilder; use crate::field::extension_field::algebra::ExtensionAlgebra; use crate::field::extension_field::{Extendable, FieldExtension, OEF}; use crate::field::field::Field; use crate::gates::mul_extension::MulExtensionGate; use crate::target::Target; -use num::traits::real::Real; -use std::convert::{TryFrom, TryInto}; -use std::ops::Range; /// `Target`s representing an element of an extension field. #[derive(Copy, Clone, Debug)] diff --git a/src/field/field_testing.rs b/src/field/field_testing.rs index 7d2339af..53e9c63c 100644 --- a/src/field/field_testing.rs +++ b/src/field/field_testing.rs @@ -142,9 +142,10 @@ pub fn run_binaryop_test_cases( macro_rules! test_arithmetic { ($field:ty) => { mod arithmetic { - use crate::field::field::Field; use std::ops::{Add, Mul, Neg, Sub}; + use crate::field::field::Field; + // Can be 32 or 64; doesn't have to be computer's actual word // bits. Choosing 32 gives more tests... const WORD_BITS: usize = 32; diff --git a/src/fri/verifier.rs b/src/fri/verifier.rs index f3d868ff..a135f5f0 100644 --- a/src/fri/verifier.rs +++ b/src/fri/verifier.rs @@ -1,5 +1,4 @@ use anyhow::{ensure, Result}; -use itertools::izip; use crate::field::extension_field::{flatten, Extendable, FieldExtension, Frobenius}; use crate::field::field::Field; @@ -155,31 +154,29 @@ fn fri_combine_initial, const D: usize>( let mut sum = F::Extension::ZERO; // We will add three terms to `sum`: - // - one for polynomials opened at `x` only - // - one for polynomials opened at `x` and `g x` - // - one for polynomials opened at `x` and its conjugate + // - one for various polynomials which are opened at a single point `x` + // - one for Zs, which are opened at `x` and `g x` + // - one for wire polynomials, which are opened at `x` and its conjugate - let evals = [0, 1, 4] + let single_evals = [0, 1, 4] .iter() .flat_map(|&i| proof.unsalted_evals(i, config)) .map(|&e| F::Extension::from_basefield(e)); - let openings = os + let single_openings = os .constants .iter() .chain(&os.plonk_s_sigmas) .chain(&os.quotient_polys); - let numerator = izip!(evals, openings, &mut alpha_powers) - .map(|(e, &o, a)| a * (e - o)) - .sum::(); - let denominator = subgroup_x - zeta; - sum += numerator / denominator; + let single_diffs = single_evals.zip(single_openings).map(|(e, &o)| e - o); + let single_numerator = reduce_with_iter(single_diffs, &mut alpha_powers); + let single_denominator = subgroup_x - zeta; + sum += single_numerator / single_denominator; - let ev: F::Extension = proof + let zs_evals = proof .unsalted_evals(3, config) .iter() - .zip(alpha_powers.clone()) - .map(|(&e, a)| a * e.into()) - .sum(); + .map(|&e| F::Extension::from_basefield(e)); + let zs_composition_eval = reduce_with_iter(zs_evals, alpha_powers.clone()); 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())), @@ -188,22 +185,21 @@ fn fri_combine_initial, const D: usize>( reduce_with_iter(&os.plonk_zs_right, &mut alpha_powers), ), ]); - let numerator = ev - zs_interpol.eval(subgroup_x); - let denominator = (subgroup_x - zeta) * (subgroup_x - zeta_right); - sum += numerator / denominator; + 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; - let ev: F::Extension = proof + let wire_evals = proof .unsalted_evals(2, config) .iter() - .zip(alpha_powers.clone()) - .map(|(&e, a)| a * e.into()) - .sum(); + .map(|&e| F::Extension::from_basefield(e)); + let wire_composition_eval = reduce_with_iter(wire_evals, alpha_powers.clone()); let zeta_frob = zeta.frobenius(); let wire_eval = reduce_with_iter(&os.wires, alpha_powers.clone()); let alpha_powers_frob = alpha_powers.repeated_frobenius(D - 1); let wire_eval_frob = reduce_with_iter(&os.wires, alpha_powers_frob).frobenius(); let wires_interpol = interpolant(&[(zeta, wire_eval), (zeta_frob, wire_eval_frob)]); - let numerator = ev - wires_interpol.eval(subgroup_x); + let numerator = wire_composition_eval - wires_interpol.eval(subgroup_x); let denominator = (subgroup_x - zeta) * (subgroup_x - zeta_frob); sum += numerator / denominator; diff --git a/src/gates/interpolation.rs b/src/gates/interpolation.rs index 8cea3328..ac2ca49f 100644 --- a/src/gates/interpolation.rs +++ b/src/gates/interpolation.rs @@ -209,11 +209,9 @@ impl, const D: usize> SimpleGenerator for InterpolationGener let mut deps = Vec::new(); deps.extend(local_targets(self.gate.wires_evaluation_point())); - deps.extend(local_targets(self.gate.wires_evaluation_value())); for i in 0..self.gate.num_points { deps.push(local_target(self.gate.wire_point(i))); deps.extend(local_targets(self.gate.wires_value(i))); - deps.extend(local_targets(self.gate.wires_coeff(i))); } deps } diff --git a/src/merkle_tree.rs b/src/merkle_tree.rs index db41b8a3..ed092cff 100644 --- a/src/merkle_tree.rs +++ b/src/merkle_tree.rs @@ -84,11 +84,10 @@ impl MerkleTree { mod tests { use anyhow::Result; + use super::*; use crate::field::crandall_field::CrandallField; use crate::merkle_proofs::verify_merkle_proof; - use super::*; - fn random_data(n: usize, k: usize) -> Vec> { (0..n).map(|_| F::rand_vec(k)).collect() } diff --git a/src/plonk_common.rs b/src/plonk_common.rs index 8ac34d29..5c881fb1 100644 --- a/src/plonk_common.rs +++ b/src/plonk_common.rs @@ -1,9 +1,12 @@ +use std::borrow::Borrow; + use crate::circuit_builder::CircuitBuilder; use crate::circuit_data::CommonCircuitData; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::field::field::Field; use crate::gates::gate::GateRef; +use crate::polynomial::polynomial::PolynomialCoeffs; use crate::target::Target; use crate::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; @@ -214,13 +217,26 @@ pub(crate) fn reduce_with_powers_recursive, const D: usize>( sum } -pub(crate) fn reduce_with_iter(terms: &[F], coeffs: I) -> F -where - I: IntoIterator, -{ - let mut sum = F::ZERO; - for (&term, coeff) in terms.iter().zip(coeffs) { - sum += coeff * term; - } - sum +/// Reduce a sequence of field elements by the given coefficients. +pub(crate) fn reduce_with_iter( + terms: impl IntoIterator>, + coeffs: impl IntoIterator>, +) -> F { + terms + .into_iter() + .zip(coeffs) + .map(|(t, c)| *t.borrow() * *c.borrow()) + .sum() +} + +/// Reduce a sequence of polynomials by the given coefficients. +pub(crate) fn reduce_polys_with_iter( + polys: impl IntoIterator>>, + coeffs: impl IntoIterator>, +) -> PolynomialCoeffs { + polys + .into_iter() + .zip(coeffs) + .map(|(p, c)| p.borrow() * *c.borrow()) + .sum() } diff --git a/src/polynomial/commitment.rs b/src/polynomial/commitment.rs index fe81f3c7..c1fd08eb 100644 --- a/src/polynomial/commitment.rs +++ b/src/polynomial/commitment.rs @@ -8,7 +8,7 @@ use crate::field::lagrange::interpolant; use crate::fri::{prover::fri_proof, verifier::verify_fri_proof, FriConfig}; use crate::merkle_tree::MerkleTree; use crate::plonk_challenger::Challenger; -use crate::plonk_common::reduce_with_powers; +use crate::plonk_common::{reduce_polys_with_iter, reduce_with_iter}; use crate::polynomial::polynomial::PolynomialCoeffs; use crate::proof::{FriProof, FriProofTarget, Hash, OpeningSet}; use crate::timed; @@ -90,7 +90,7 @@ impl ListPolynomialCommitment { assert!(D > 1, "Not implemented for D=1."); let degree_log = log2_strict(commitments[0].degree); let g = F::Extension::primitive_root_of_unity(degree_log); - for &p in &[zeta, g * zeta] { + for p in &[zeta, g * zeta] { assert_ne!( p.exp(1 << degree_log as u64), F::Extension::ONE, @@ -110,45 +110,34 @@ impl ListPolynomialCommitment { challenger.observe_opening_set(&os); let alpha = challenger.get_extension_challenge(); - let mut cur_alpha = F::Extension::ONE; + let mut alpha_powers = alpha.powers(); // Final low-degree polynomial that goes into FRI. let mut final_poly = PolynomialCoeffs::empty(); - // Count the total number of polynomials accumulated into `final_poly`. - let mut poly_count = 0; // Polynomials opened at a single point. - let composition_poly = [0, 1, 4] + let single_polys = [0, 1, 4] .iter() .flat_map(|&i| &commitments[i].polynomials) - .rev() - .fold(PolynomialCoeffs::empty(), |acc, p| { - poly_count += 1; - &(&acc * alpha) + &p.to_extension() - }); - let composition_eval = [&os.constants, &os.plonk_s_sigmas, &os.quotient_polys] - .iter() - .flat_map(|v| v.iter()) - .rev() - .fold(F::Extension::ZERO, |acc, &e| acc * alpha + e); + .map(|p| p.to_extension()); + let single_os = [&os.constants, &os.plonk_s_sigmas, &os.quotient_polys]; + let single_evals = single_os.iter().flat_map(|v| v.iter()); + let single_composition_poly = reduce_polys_with_iter(single_polys, alpha_powers.clone()); + let single_composition_eval = reduce_with_iter(single_evals, &mut alpha_powers); - let quotient = Self::compute_quotient(&[zeta], &[composition_eval], &composition_poly); - final_poly = &final_poly + &("ient * cur_alpha); - cur_alpha = alpha.exp(poly_count); + let single_quotient = Self::compute_quotient( + &[zeta], + &[single_composition_eval], + &single_composition_poly, + ); + final_poly = &final_poly + &single_quotient; // Zs polynomials are opened at `zeta` and `g*zeta`. - let zs_composition_poly = - commitments[3] - .polynomials - .iter() - .rev() - .fold(PolynomialCoeffs::empty(), |acc, p| { - poly_count += 1; - &(&acc * alpha) + &p.to_extension() - }); + let zs_polys = commitments[3].polynomials.iter().map(|p| p.to_extension()); + let zs_composition_poly = reduce_polys_with_iter(zs_polys, alpha_powers.clone()); let zs_composition_evals = [ - reduce_with_powers(&os.plonk_zs, alpha), - reduce_with_powers(&os.plonk_zs_right, alpha), + reduce_with_iter(&os.plonk_zs, alpha_powers.clone()), + reduce_with_iter(&os.plonk_zs_right, &mut alpha_powers), ]; let zs_quotient = Self::compute_quotient( @@ -156,33 +145,25 @@ impl ListPolynomialCommitment { &zs_composition_evals, &zs_composition_poly, ); - final_poly = &final_poly + &(&zs_quotient * cur_alpha); - cur_alpha = alpha.exp(poly_count); + final_poly = &final_poly + &zs_quotient; // When working in an extension field, need to check that wires are in the base field. // Check this by opening the wires polynomials at `zeta` and `zeta.frobenius()` and using the fact that // a polynomial `f` is over the base field iff `f(z).frobenius()=f(z.frobenius())` with high probability. - let wires_composition_poly = - commitments[2] - .polynomials - .iter() - .rev() - .fold(PolynomialCoeffs::empty(), |acc, p| { - poly_count += 1; - &(&acc * alpha) + &p.to_extension() - }); + let wire_polys = commitments[2].polynomials.iter().map(|p| p.to_extension()); + let wire_composition_poly = reduce_polys_with_iter(wire_polys, alpha_powers.clone()); let wire_evals_frob = os.wires.iter().map(|e| e.frobenius()).collect::>(); - let wires_composition_evals = [ - reduce_with_powers(&os.wires, alpha), - reduce_with_powers(&wire_evals_frob, alpha), + let wire_composition_evals = [ + reduce_with_iter(&os.wires, alpha_powers.clone()), + reduce_with_iter(&wire_evals_frob, alpha_powers), ]; let wires_quotient = Self::compute_quotient( &[zeta, zeta.frobenius()], - &wires_composition_evals, - &wires_composition_poly, + &wire_composition_evals, + &wire_composition_poly, ); - final_poly = &final_poly + &(&wires_quotient * cur_alpha); + final_poly = &final_poly + &wires_quotient; let lde_final_poly = final_poly.lde(config.rate_bits); let lde_final_values = lde_final_poly @@ -279,9 +260,9 @@ pub struct OpeningProofTarget { #[cfg(test)] mod tests { use anyhow::Result; + use rand::Rng; use super::*; - use rand::Rng; fn gen_random_test_case, const D: usize>( k: usize, @@ -365,6 +346,7 @@ mod tests { mod quadratic { use super::*; use crate::field::crandall_field::CrandallField; + #[test] fn test_batch_polynomial_commitment() -> Result<()> { check_batch_polynomial_commitment::() @@ -374,6 +356,7 @@ mod tests { mod quartic { use super::*; use crate::field::crandall_field::CrandallField; + #[test] fn test_batch_polynomial_commitment() -> Result<()> { check_batch_polynomial_commitment::() diff --git a/src/polynomial/polynomial.rs b/src/polynomial/polynomial.rs index 5e3dd9f0..9f605051 100644 --- a/src/polynomial/polynomial.rs +++ b/src/polynomial/polynomial.rs @@ -1,4 +1,5 @@ use std::cmp::max; +use std::iter::Sum; use std::ops::{Add, Mul, Sub}; use crate::field::extension_field::Extendable; @@ -222,6 +223,12 @@ impl Add for &PolynomialCoeffs { } } +impl Sum for PolynomialCoeffs { + fn sum>(iter: I) -> Self { + iter.fold(Self::empty(), |acc, p| &acc + &p) + } +} + impl Sub for &PolynomialCoeffs { type Output = PolynomialCoeffs; @@ -272,9 +279,8 @@ mod tests { use rand::{thread_rng, Rng}; - use crate::field::crandall_field::CrandallField; - use super::*; + use crate::field::crandall_field::CrandallField; #[test] fn test_trimmed() { diff --git a/src/proof.rs b/src/proof.rs index 04ddf06c..e05e4093 100644 --- a/src/proof.rs +++ b/src/proof.rs @@ -1,3 +1,5 @@ +use std::convert::TryInto; + use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::field::field::Field; @@ -7,7 +9,6 @@ use crate::merkle_proofs::{MerkleProof, MerkleProofTarget}; use crate::polynomial::commitment::{ListPolynomialCommitment, OpeningProof, OpeningProofTarget}; use crate::polynomial::polynomial::PolynomialCoeffs; use crate::target::Target; -use std::convert::TryInto; /// Represents a ~256 bit hash output. #[derive(Copy, Clone, Debug, Eq, PartialEq)]