Merge main

This commit is contained in:
wborgeaud 2021-06-15 09:20:00 +02:00
commit b44a01c975
15 changed files with 106 additions and 102 deletions

2
rustfmt.toml Normal file
View File

@ -0,0 +1,2 @@
unstable_features = true
group_imports = "StdExternalCrate"

View File

@ -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;

View File

@ -1,5 +1,4 @@
use env_logger::Env;
use plonky2::circuit_builder::CircuitBuilder;
use plonky2::circuit_data::CircuitConfig;
use plonky2::field::crandall_field::CrandallField;

View File

@ -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;

View File

@ -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<F_D>` 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<F: OEF<D>, const D: usize> PolynomialCoeffsAlgebra<F, D> {
#[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<F: Extendable<D>, const D: usize>() {

View File

@ -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]);

View File

@ -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)]

View File

@ -142,9 +142,10 @@ pub fn run_binaryop_test_cases<F, BinaryOp, ExpectedOp>(
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;

View File

@ -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<F: Field + Extendable<D>, 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::<F::Extension>();
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<F: Field + Extendable<D>, 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;

View File

@ -209,11 +209,9 @@ impl<F: Extendable<D>, const D: usize> SimpleGenerator<F> 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
}

View File

@ -84,11 +84,10 @@ impl<F: Field> MerkleTree<F> {
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<F: Field>(n: usize, k: usize) -> Vec<Vec<F>> {
(0..n).map(|_| F::rand_vec(k)).collect()
}

View File

@ -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<F: Extendable<D>, const D: usize>(
sum
}
pub(crate) fn reduce_with_iter<F: Field, I>(terms: &[F], coeffs: I) -> F
where
I: IntoIterator<Item = F>,
{
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<F: Field>(
terms: impl IntoIterator<Item = impl Borrow<F>>,
coeffs: impl IntoIterator<Item = impl Borrow<F>>,
) -> 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<F: Field>(
polys: impl IntoIterator<Item = impl Borrow<PolynomialCoeffs<F>>>,
coeffs: impl IntoIterator<Item = impl Borrow<F>>,
) -> PolynomialCoeffs<F> {
polys
.into_iter()
.zip(coeffs)
.map(|(p, c)| p.borrow() * *c.borrow())
.sum()
}

View File

@ -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<F: Field> ListPolynomialCommitment<F> {
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<F: Field> ListPolynomialCommitment<F> {
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 + &(&quotient * 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<F: Field> ListPolynomialCommitment<F> {
&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::<Vec<_>>();
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<const D: usize> {
#[cfg(test)]
mod tests {
use anyhow::Result;
use rand::Rng;
use super::*;
use rand::Rng;
fn gen_random_test_case<F: Field + Extendable<D>, 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::<CrandallField, 2>()
@ -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::<CrandallField, 4>()

View File

@ -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<F: Field> Add for &PolynomialCoeffs<F> {
}
}
impl<F: Field> Sum for PolynomialCoeffs<F> {
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
iter.fold(Self::empty(), |acc, p| &acc + &p)
}
}
impl<F: Field> Sub for &PolynomialCoeffs<F> {
type Output = PolynomialCoeffs<F>;
@ -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() {

View File

@ -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)]