Merge pull request #88 from mir-protocol/finish-verifier

Working verifier
This commit is contained in:
wborgeaud 2021-07-08 15:23:36 +02:00 committed by GitHub
commit 7ab21a4f13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 51 additions and 26 deletions

View File

@ -392,6 +392,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Builds a "full circuit", with both prover and verifier data.
pub fn build(mut self) -> CircuitData<F, D> {
let quotient_degree_factor = 7; // TODO: add this as a parameter.
let start = Instant::now();
info!(
"Degree before blinding & padding: {}",
@ -403,7 +404,10 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let gates = self.gates.iter().cloned().collect();
let (gate_tree, max_filtered_constraint_degree, num_constants) = Tree::from_gates(gates);
let max_filtered_constraint_degree = max_filtered_constraint_degree.max(3);
assert!(
max_filtered_constraint_degree <= quotient_degree_factor + 1,
"Constraints are too high degree."
);
let prefixed_gates = PrefixedGate::from_tree(gate_tree);
let degree_bits = log2_strict(degree);
@ -446,10 +450,8 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
.max()
.expect("No gates?");
let num_partial_products = num_partial_products(
self.config.num_routed_wires,
max_filtered_constraint_degree - 1,
);
let num_partial_products =
num_partial_products(self.config.num_routed_wires, quotient_degree_factor);
// TODO: This should also include an encoding of gate constraints.
let circuit_digest_parts = [
@ -462,7 +464,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
config: self.config,
degree_bits,
gates: prefixed_gates,
max_filtered_constraint_degree,
quotient_degree_factor,
num_gate_constraints,
num_constants,
k_is,

View File

@ -145,8 +145,8 @@ pub struct CommonCircuitData<F: Extendable<D>, const D: usize> {
/// The types of gates used in this circuit, along with their prefixes.
pub(crate) gates: Vec<PrefixedGate<F, D>>,
/// The maximum degree of a filter times a constraint by any gate.
pub(crate) max_filtered_constraint_degree: usize,
/// The degree of the PLONK quotient polynomial.
pub(crate) quotient_degree_factor: usize,
/// The largest number of constraints imposed by any gate.
pub(crate) num_gate_constraints: usize,
@ -188,7 +188,7 @@ impl<F: Extendable<D>, const D: usize> CommonCircuitData<F, D> {
}
pub fn quotient_degree(&self) -> usize {
(self.max_filtered_constraint_degree - 1) * self.degree()
self.quotient_degree_factor * self.degree()
}
pub fn total_constraints(&self) -> usize {

View File

@ -438,6 +438,7 @@ mod tests {
use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::field::field::Field;
use crate::fri::FriConfig;
use crate::verifier::verify;
use crate::witness::PartialWitness;
#[test]
@ -461,5 +462,7 @@ mod tests {
let data = builder.build();
let proof = data.prove(PartialWitness::new());
verify(proof, &data.verifier_only, &data.common).unwrap();
}
}

View File

@ -78,6 +78,7 @@ mod tests {
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::field::field::Field;
use crate::verifier::verify;
use crate::witness::PartialWitness;
fn real_insert<const D: usize>(
@ -113,6 +114,8 @@ mod tests {
let data = builder.build();
let proof = data.prove(PartialWitness::new());
verify(proof, &data.verifier_only, &data.common).unwrap();
}
#[test]

View File

@ -66,6 +66,7 @@ mod tests {
use crate::field::extension_field::FieldExtension;
use crate::field::field::Field;
use crate::field::interpolation::{interpolant, interpolate};
use crate::verifier::verify;
use crate::witness::PartialWitness;
#[test]
@ -103,6 +104,8 @@ mod tests {
let data = builder.build();
let proof = data.prove(PartialWitness::new());
verify(proof, &data.verifier_only, &data.common).unwrap();
}
#[test]
@ -135,5 +138,7 @@ mod tests {
let data = builder.build();
let proof = data.prove(PartialWitness::new());
verify(proof, &data.verifier_only, &data.common).unwrap();
}
}

View File

@ -118,6 +118,7 @@ mod tests {
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::field::field::Field;
use crate::verifier::verify;
use crate::witness::PartialWitness;
fn real_rotate<const D: usize>(
@ -150,6 +151,8 @@ mod tests {
let data = builder.build();
let proof = data.prove(PartialWitness::new());
verify(proof, &data.verifier_only, &data.common).unwrap();
}
#[test]

View File

@ -41,6 +41,7 @@ mod tests {
use crate::circuit_data::CircuitConfig;
use crate::field::crandall_field::CrandallField;
use crate::field::field::Field;
use crate::verifier::verify;
use crate::witness::PartialWitness;
#[test]
@ -67,5 +68,7 @@ mod tests {
let data = builder.build();
let proof = data.prove(PartialWitness::new());
verify(proof, &data.verifier_only, &data.common).unwrap();
}
}

View File

@ -73,7 +73,7 @@ pub(crate) fn eval_vanishing_poly<F: Extendable<D>, const D: usize>(
gammas: &[F],
alphas: &[F],
) -> Vec<F::Extension> {
let max_degree = common_data.max_filtered_constraint_degree - 1;
let max_degree = common_data.quotient_degree_factor;
let (num_prods, final_num_prod) = common_data.num_partial_products;
let constraint_terms =
@ -160,7 +160,7 @@ pub(crate) fn eval_vanishing_poly_base<F: Extendable<D>, const D: usize>(
alphas: &[F],
z_h_on_coset: &ZeroPolyOnCoset<F>,
) -> Vec<F> {
let max_degree = common_data.max_filtered_constraint_degree - 1;
let max_degree = common_data.quotient_degree_factor;
let (num_prods, final_num_prod) = common_data.num_partial_products;
let constraint_terms =

View File

@ -331,7 +331,7 @@ mod tests {
},
degree_bits: 0,
gates: vec![],
max_filtered_constraint_degree: 0,
quotient_degree_factor: 0,
num_gate_constraints: 0,
num_constants: 4,
k_is: vec![F::ONE; 6],

View File

@ -80,7 +80,7 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
let gammas = challenger.get_n_challenges(num_challenges);
assert!(
common_data.max_filtered_constraint_degree<=common_data.config.num_routed_wires,
common_data.quotient_degree_factor + 1 <=common_data.config.num_routed_wires,
"When the number of routed wires is smaller that the degree, we should change the logic to avoid computing partial products."
);
let mut partial_products = timed!(
@ -213,7 +213,7 @@ fn wires_permutation_partial_products<F: Extendable<D>, const D: usize>(
prover_data: &ProverOnlyCircuitData<F, D>,
common_data: &CommonCircuitData<F, D>,
) -> Vec<PolynomialValues<F>> {
let degree = common_data.max_filtered_constraint_degree - 1;
let degree = common_data.quotient_degree_factor;
let subgroup = &prover_data.subgroup;
let k_is = &common_data.k_is;
let values = subgroup
@ -286,22 +286,21 @@ fn compute_quotient_polys<'a, F: Extendable<D>, const D: usize>(
alphas: &[F],
) -> Vec<PolynomialCoeffs<F>> {
let num_challenges = common_data.config.num_challenges;
let max_filtered_constraint_degree_bits = log2_ceil(common_data.max_filtered_constraint_degree);
let max_degree_bits = log2_ceil(common_data.quotient_degree_factor + 1);
assert!(
max_filtered_constraint_degree_bits <= common_data.config.rate_bits,
max_degree_bits <= common_data.config.rate_bits,
"Having constraints of degree higher than the rate is not supported yet. \
If we need this in the future, we can precompute the larger LDE before computing the `ListPolynomialCommitment`s."
);
// We reuse the LDE computed in `ListPolynomialCommitment` and extract every `step` points to get
// an LDE matching `max_filtered_constraint_degree`.
let step = 1 << (common_data.config.rate_bits - max_filtered_constraint_degree_bits);
let step = 1 << (common_data.config.rate_bits - max_degree_bits);
// When opening the `Z`s polys at the "next" point in Plonk, need to look at the point `next_step`
// steps away since we work on an LDE of degree `max_filtered_constraint_degree`.
let next_step = 1 << max_filtered_constraint_degree_bits;
let next_step = 1 << max_degree_bits;
let points =
F::two_adic_subgroup(common_data.degree_bits + max_filtered_constraint_degree_bits);
let points = F::two_adic_subgroup(common_data.degree_bits + max_degree_bits);
let lde_size = points.len();
// Retrieve the LDE values at index `i`.
@ -309,8 +308,7 @@ fn compute_quotient_polys<'a, F: Extendable<D>, const D: usize>(
comm.get_lde_values(i * step)
};
let z_h_on_coset =
ZeroPolyOnCoset::new(common_data.degree_bits, max_filtered_constraint_degree_bits);
let z_h_on_coset = ZeroPolyOnCoset::new(common_data.degree_bits, max_degree_bits);
let quotient_values: Vec<Vec<F>> = points
.into_par_iter()

View File

@ -174,6 +174,7 @@ mod tests {
use crate::circuit_data::CircuitConfig;
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::verifier::verify;
use crate::witness::PartialWitness;
fn test_reduce_gadget(n: usize) {
@ -205,6 +206,8 @@ mod tests {
let data = builder.build();
let proof = data.prove(PartialWitness::new());
verify(proof, &data.verifier_only, &data.common).unwrap();
}
#[test]

View File

@ -2,8 +2,9 @@ use anyhow::{ensure, Result};
use crate::circuit_data::{CommonCircuitData, VerifierOnlyCircuitData};
use crate::field::extension_field::Extendable;
use crate::field::field::Field;
use crate::plonk_challenger::Challenger;
use crate::plonk_common::{eval_vanishing_poly, eval_zero_poly};
use crate::plonk_common::{eval_vanishing_poly, eval_zero_poly, reduce_with_powers};
use crate::proof::Proof;
use crate::vars::EvaluationVars;
@ -57,9 +58,13 @@ pub(crate) fn verify<F: Extendable<D>, const D: usize>(
// Check each polynomial identity, of the form `vanishing(x) = Z_H(x) quotient(x)`, at zeta.
let quotient_polys_zeta = &proof.openings.quotient_polys;
let z_h_zeta = eval_zero_poly(common_data.degree(), zeta);
for i in 0..num_challenges {
ensure!(vanishing_polys_zeta[i] == z_h_zeta * quotient_polys_zeta[i]);
let zeta_pow_deg = zeta.exp_power_of_2(common_data.degree_bits);
let z_h_zeta = zeta_pow_deg - F::Extension::ONE;
for (i, chunk) in quotient_polys_zeta
.chunks(common_data.quotient_degree_factor)
.enumerate()
{
ensure!(vanishing_polys_zeta[i] == z_h_zeta * reduce_with_powers(chunk, zeta_pow_deg));
}
let evaluations = proof.openings.clone();