Working base field check for (non-batch) opening

This commit is contained in:
wborgeaud 2021-05-27 17:20:26 +02:00
parent 5a261332d9
commit 845382b472
8 changed files with 79 additions and 13 deletions

View File

@ -9,7 +9,7 @@ use plonky2::fri::FriConfig;
use plonky2::gates::constant::ConstantGate;
use plonky2::gates::gmimc::GMiMCGate;
use plonky2::hash::GMIMC_ROUNDS;
use plonky2::prover::PLONK_BLINDING;
use plonky2::prover::{PLONK_BLINDING, PLONK_CHECK_BASEFIELD};
use plonky2::witness::PartialWitness;
fn main() {
@ -43,6 +43,7 @@ fn bench_prove<F: Field + Extendable<D>, const D: usize>() {
reduction_arity_bits: vec![1],
num_query_rounds: 1,
blinding: PLONK_BLINDING.to_vec(),
check_basefield: PLONK_CHECK_BASEFIELD.to_vec(),
},
};

View File

@ -38,6 +38,7 @@ impl Default for CircuitConfig {
reduction_arity_bits: vec![1],
num_query_rounds: 1,
blinding: vec![true],
check_basefield: vec![false],
},
}
}

View File

@ -23,6 +23,10 @@ pub struct FriConfig {
/// Vector of the same length as the number of initial Merkle trees.
/// `blinding[i]==true` iff the i-th tree is salted.
pub blinding: Vec<bool>,
/// Vector of the same length as the number of initial Merkle trees.
/// `check_basefield[i]==true` iff the polynomials in the i-th tree are checked to be in the base field.
pub check_basefield: Vec<bool>,
}
fn fri_delta(rate_log: usize, conjecture: bool) -> f64 {
@ -82,6 +86,7 @@ mod tests {
proof_of_work_bits: 2,
reduction_arity_bits,
blinding: vec![false],
check_basefield: vec![false],
};
let tree = {
let mut leaves = coset_lde

View File

@ -1,4 +1,4 @@
use crate::field::extension_field::{flatten, Extendable, FieldExtension};
use crate::field::extension_field::{flatten, Extendable, FieldExtension, OEF};
use crate::field::field::Field;
use crate::field::lagrange::{barycentric_weights, interpolant, interpolate};
use crate::fri::FriConfig;
@ -159,7 +159,23 @@ fn fri_combine_initial<F: Field + Extendable<D>, const D: usize>(
.iter()
.map(|&(x, _)| F::Extension::from_basefield(subgroup_x) - x)
.product();
numerator / denominator
let quotient = numerator / denominator;
let quotient = if config.check_basefield[0] {
let alpha_conj = alpha.frobenius();
let comp_conj = proof
.evals_proofs
.iter()
.enumerate()
.flat_map(|(i, (v, _))| &v[..v.len() - if config.blinding[i] { SALT_SIZE } else { 0 }])
.rev()
.fold(F::Extension::ZERO, |acc, &e| alpha_conj * acc + e.into());
let numerator = comp_conj - points[0].1.frobenius();
let denominator = F::Extension::from_basefield(subgroup_x) - points[0].0.frobenius();
quotient + (numerator / denominator) * alpha.exp(proof.evals_proofs[0].0.len() as u64)
} else {
quotient
};
quotient
}
fn fri_verifier_query_round<F: Field + Extendable<D>, const D: usize>(

View File

@ -1,6 +1,8 @@
use crate::circuit_builder::CircuitBuilder;
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};
@ -80,6 +82,18 @@ pub(crate) fn reduce_with_powers<F: Field>(terms: &[F], alpha: F) -> F {
sum
}
pub(crate) fn reduce_polys_with_powers<F: Field + Extendable<D>, const D: usize>(
polynomials: &[PolynomialCoeffs<F>],
alpha: F::Extension,
) -> PolynomialCoeffs<F::Extension> {
polynomials
.iter()
.rev()
.fold(PolynomialCoeffs::empty(), |acc, p| {
&(&acc * alpha) + &p.to_extension()
})
}
pub(crate) fn reduce_with_powers_recursive<F: Field>(
builder: &mut CircuitBuilder<F>,
terms: Vec<Target>,

View File

@ -1,14 +1,14 @@
use anyhow::Result;
use rayon::prelude::*;
use crate::field::extension_field::Extendable;
use crate::field::extension_field::FieldExtension;
use crate::field::extension_field::{Extendable, OEF};
use crate::field::field::Field;
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_powers, reduce_with_powers};
use crate::polynomial::polynomial::PolynomialCoeffs;
use crate::proof::{FriProof, Hash, OpeningSet};
use crate::timed;
@ -86,6 +86,7 @@ impl<F: Field> ListPolynomialCommitment<F> {
F: Extendable<D>,
{
assert_eq!(self.rate_bits, config.rate_bits);
assert_eq!(config.check_basefield.len(), 1);
assert_eq!(config.blinding.len(), 1);
assert_eq!(self.blinding, config.blinding[0]);
for p in points {
@ -114,13 +115,7 @@ impl<F: Field> ListPolynomialCommitment<F> {
let alpha = challenger.get_extension_challenge();
// Scale polynomials by `alpha`.
let composition_poly = self
.polynomials
.iter()
.rev()
.fold(PolynomialCoeffs::zero(self.degree), |acc, p| {
&(&acc * alpha) + &p.to_extension()
});
let composition_poly = reduce_polys_with_powers(&self.polynomials, alpha);
// Scale evaluations by `alpha`.
let composition_evals = evaluations
.par_iter()
@ -129,6 +124,24 @@ impl<F: Field> ListPolynomialCommitment<F> {
let quotient = Self::compute_quotient(points, &composition_evals, &composition_poly);
let quotient = if config.check_basefield[0] {
let composition_poly_conj = PolynomialCoeffs::<F>::frobenius(&composition_poly);
// This equality holds iff the polynomials in `self.polynomials` are defined over `F` and not `F::Extension`.
debug_assert_eq!(
composition_poly_conj.eval(points[0].frobenius()),
composition_evals[0].frobenius()
);
let quotient_conj = Self::compute_quotient(
&[points[0].frobenius()],
&[composition_evals[0].frobenius()],
&composition_poly_conj,
);
&(&quotient_conj * alpha.exp(self.polynomials.len() as u64)) + &quotient
} else {
quotient
};
let lde_quotient = PolynomialCoeffs::from(quotient.clone()).lde(self.rate_bits);
let lde_quotient_values = lde_quotient
.clone()
@ -391,6 +404,7 @@ mod tests {
reduction_arity_bits: vec![3, 2, 1, 2],
num_query_rounds: 3,
blinding: vec![false],
check_basefield: vec![true],
};
let (polys, points) = gen_random_test_case::<F, D>(k, degree_log, num_points);
@ -416,6 +430,7 @@ mod tests {
reduction_arity_bits: vec![3, 2, 1, 2],
num_query_rounds: 3,
blinding: vec![true],
check_basefield: vec![false],
};
let (polys, points) = gen_random_test_case::<F, D>(k, degree_log, num_points);
@ -442,6 +457,7 @@ mod tests {
reduction_arity_bits: vec![2, 3, 1, 2],
num_query_rounds: 3,
blinding: vec![false, false, false],
check_basefield: vec![false, false, false],
};
let (polys0, _) = gen_random_test_case::<F, D>(k0, degree_log, num_points);
let (polys1, _) = gen_random_test_case::<F, D>(k1, degree_log, num_points);
@ -483,6 +499,7 @@ mod tests {
reduction_arity_bits: vec![2, 3, 1, 2],
num_query_rounds: 3,
blinding: vec![true, false, true],
check_basefield: vec![true, false, true],
};
let (polys0, _) = gen_random_test_case::<F, D>(k0, degree_log, num_points);
let (polys1, _) = gen_random_test_case::<F, D>(k1, degree_log, num_points);

View File

@ -1,7 +1,7 @@
use std::cmp::max;
use std::ops::{Add, Mul, Sub};
use crate::field::extension_field::Extendable;
use crate::field::extension_field::{Extendable, OEF};
use crate::field::fft::{fft, ifft};
use crate::field::field::Field;
use crate::util::log2_strict;
@ -186,6 +186,15 @@ impl<F: Field> PolynomialCoeffs<F> {
{
PolynomialCoeffs::new(self.coeffs.iter().map(|&c| c.into()).collect())
}
pub fn frobenius<const D: usize>(
poly: &PolynomialCoeffs<F::Extension>,
) -> PolynomialCoeffs<F::Extension>
where
F: Extendable<D>,
{
PolynomialCoeffs::new(poly.coeffs.iter().map(|&c| c.frobenius()).collect())
}
}
impl<F: Field> PartialEq for PolynomialCoeffs<F> {

View File

@ -22,6 +22,9 @@ use crate::witness::PartialWitness;
/// Corresponds to constants - sigmas - wires - zs - quotient — polynomial commitments.
pub const PLONK_BLINDING: [bool; 5] = [false, false, true, true, true];
/// Corresponds to constants - sigmas - wires - zs - quotient — polynomial commitments.
pub const PLONK_CHECK_BASEFIELD: [bool; 5] = [false, false, true, false, false];
pub(crate) fn prove<F: Field + Extendable<D>, const D: usize>(
prover_data: &ProverOnlyCircuitData<F>,
common_data: &CommonCircuitData<F>,