Add comments

This commit is contained in:
wborgeaud 2021-07-01 17:28:30 +02:00
parent 1858a869a7
commit 20e6d6540f
3 changed files with 31 additions and 15 deletions

View File

@ -158,7 +158,7 @@ pub struct CommonCircuitData<F: Extendable<D>, const D: usize> {
pub(crate) k_is: Vec<F>, pub(crate) k_is: Vec<F>,
/// The number of partial products needed to compute the `Z` polynomials, as well as the number /// The number of partial products needed to compute the `Z` polynomials, as well as the number
/// of partial products needed to compute the last product. /// of partial products needed to compute the final product.
pub(crate) num_partial_products: (usize, usize), pub(crate) num_partial_products: (usize, usize),
/// A digest of the "circuit" (i.e. the instance, minus public inputs), which can be used to /// A digest of the "circuit" (i.e. the instance, minus public inputs), which can be used to

View File

@ -85,17 +85,16 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
"to compute partial products" "to compute partial products"
); );
let plonk_z_vecs = timed!( let plonk_z_vecs = timed!(compute_zs(&partial_products, common_data), "to compute Z's");
compute_zs(&partial_products, prover_data, common_data),
"to compute Z's"
);
// The first two polynomials in `partial_products` represent the final products used in the
// computation of `Z`. They aren't needed anymore so we discard them.
partial_products.iter_mut().for_each(|part| { partial_products.iter_mut().for_each(|part| {
part.drain(0..2); part.drain(0..2);
}); });
let zs_partial_products = [plonk_z_vecs, partial_products.concat()].concat(); let zs_partial_products = [plonk_z_vecs, partial_products.concat()].concat();
let plonk_zs_commitment = timed!( let zs_partial_products_commitment = timed!(
ListPolynomialCommitment::new( ListPolynomialCommitment::new(
zs_partial_products, zs_partial_products,
fri_config.rate_bits, fri_config.rate_bits,
@ -104,7 +103,7 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
"to commit to Z's" "to commit to Z's"
); );
challenger.observe_hash(&plonk_zs_commitment.merkle_tree.root); challenger.observe_hash(&zs_partial_products_commitment.merkle_tree.root);
let alphas = challenger.get_n_challenges(num_challenges); let alphas = challenger.get_n_challenges(num_challenges);
@ -113,7 +112,7 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
common_data, common_data,
prover_data, prover_data,
&wires_commitment, &wires_commitment,
&plonk_zs_commitment, &zs_partial_products_commitment,
&betas, &betas,
&gammas, &gammas,
&alphas, &alphas,
@ -156,7 +155,7 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
&[ &[
&prover_data.constants_sigmas_commitment, &prover_data.constants_sigmas_commitment,
&wires_commitment, &wires_commitment,
&plonk_zs_commitment, &zs_partial_products_commitment,
&quotient_polys_commitment, &quotient_polys_commitment,
], ],
zeta, zeta,
@ -173,13 +172,14 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
Proof { Proof {
wires_root: wires_commitment.merkle_tree.root, wires_root: wires_commitment.merkle_tree.root,
plonk_zs_root: plonk_zs_commitment.merkle_tree.root, plonk_zs_root: zs_partial_products_commitment.merkle_tree.root,
quotient_polys_root: quotient_polys_commitment.merkle_tree.root, quotient_polys_root: quotient_polys_commitment.merkle_tree.root,
openings, openings,
opening_proof, opening_proof,
} }
} }
/// Compute the partial products used in the `Z` polynomials.
fn all_wires_permutation_partial_products<F: Extendable<D>, const D: usize>( fn all_wires_permutation_partial_products<F: Extendable<D>, const D: usize>(
witness: &Witness<F>, witness: &Witness<F>,
betas: &[F], betas: &[F],
@ -200,6 +200,9 @@ fn all_wires_permutation_partial_products<F: Extendable<D>, const D: usize>(
.collect() .collect()
} }
/// Compute the partial products used in the `Z` polynomial.
/// Returns the polynomials interpolating `partial_products(f) + partial_products(g)`
/// where `f, g` are the products in the definition of `Z`: `Z(g^i) = n / d`.
fn wires_permutation_partial_products<F: Extendable<D>, const D: usize>( fn wires_permutation_partial_products<F: Extendable<D>, const D: usize>(
witness: &Witness<F>, witness: &Witness<F>,
beta: F, beta: F,
@ -230,19 +233,25 @@ fn wires_permutation_partial_products<F: Extendable<D>, const D: usize>(
wire_value + beta * s_sigma + gamma wire_value + beta * s_sigma + gamma
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let numerator_partials = partial_products(&numerator_values, degree); let numerator_partials = partial_products(&numerator_values, degree);
let denominator_partials = partial_products(&denominator_values, degree); let denominator_partials = partial_products(&denominator_values, degree);
// This is the final product for the numerator.
let numerator = numerator_partials let numerator = numerator_partials
[common_data.num_partial_products.0 - common_data.num_partial_products.1..] [common_data.num_partial_products.0 - common_data.num_partial_products.1..]
.iter() .iter()
.copied() .copied()
.product(); .product();
// This is the final product for the denominator.
let denominator = denominator_partials let denominator = denominator_partials
[common_data.num_partial_products.0 - common_data.num_partial_products.1..] [common_data.num_partial_products.0 - common_data.num_partial_products.1..]
.iter() .iter()
.copied() .copied()
.product(); .product();
// We add the numerator and denominator at the beginning of the vector to reuse them
// later in the computation of `Z`.
[ [
vec![numerator], vec![numerator],
vec![denominator], vec![denominator],
@ -261,23 +270,20 @@ fn wires_permutation_partial_products<F: Extendable<D>, const D: usize>(
fn compute_zs<F: Extendable<D>, const D: usize>( fn compute_zs<F: Extendable<D>, const D: usize>(
partial_products: &[Vec<PolynomialValues<F>>], partial_products: &[Vec<PolynomialValues<F>>],
prover_data: &ProverOnlyCircuitData<F, D>,
common_data: &CommonCircuitData<F, D>, common_data: &CommonCircuitData<F, D>,
) -> Vec<PolynomialValues<F>> { ) -> Vec<PolynomialValues<F>> {
(0..common_data.config.num_challenges) (0..common_data.config.num_challenges)
.map(|i| compute_z(&partial_products[i], prover_data, common_data)) .map(|i| compute_z(&partial_products[i], common_data))
.collect() .collect()
} }
/// Compute the `Z` polynomial by reusing the computations done in `wires_permutation_partial_products`.
fn compute_z<F: Extendable<D>, const D: usize>( fn compute_z<F: Extendable<D>, const D: usize>(
partial_products: &[PolynomialValues<F>], partial_products: &[PolynomialValues<F>],
prover_data: &ProverOnlyCircuitData<F, D>,
common_data: &CommonCircuitData<F, D>, common_data: &CommonCircuitData<F, D>,
) -> PolynomialValues<F> { ) -> PolynomialValues<F> {
let subgroup = &prover_data.subgroup;
let mut plonk_z_points = vec![F::ONE]; let mut plonk_z_points = vec![F::ONE];
for i in 1..common_data.degree() { for i in 1..common_data.degree() {
let x = subgroup[i - 1];
let numerator = partial_products[0].values[i - 1]; let numerator = partial_products[0].values[i - 1];
let denominator = partial_products[1].values[i - 1]; let denominator = partial_products[1].values[i - 1];
let last = *plonk_z_points.last().unwrap(); let last = *plonk_z_points.last().unwrap();

View File

@ -3,12 +3,17 @@ use std::ops::Sub;
use crate::util::ceil_div_usize; use crate::util::ceil_div_usize;
/// Compute partial products of the original vector `v` such that no products are of `max_degree` or
/// less elements. This is done until we've computed the product `P` of all elements in the vector.
/// The final product resulting in `P` has `max_degree-1` elements at most since `P` is multiplied
/// by the `Z` polynomial in the Plonk check.
pub fn partial_products<T: Product + Copy>(v: &[T], max_degree: usize) -> Vec<T> { pub fn partial_products<T: Product + Copy>(v: &[T], max_degree: usize) -> Vec<T> {
let mut res = Vec::new(); let mut res = Vec::new();
let mut remainder = v.to_vec(); let mut remainder = v.to_vec();
while remainder.len() >= max_degree { while remainder.len() >= max_degree {
let new_partials = remainder let new_partials = remainder
.chunks(max_degree) .chunks(max_degree)
// No need to compute the product if the chunk has size 1.
.filter(|chunk| chunk.len() != 1) .filter(|chunk| chunk.len() != 1)
.map(|chunk| chunk.iter().copied().product()) .map(|chunk| chunk.iter().copied().product())
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -19,12 +24,15 @@ pub fn partial_products<T: Product + Copy>(v: &[T], max_degree: usize) -> Vec<T>
vec![] vec![]
}; };
remainder = new_partials; remainder = new_partials;
// If there were a chunk of size 1, add it back to the remainder.
remainder.extend(addendum); remainder.extend(addendum);
} }
res res
} }
/// Returns a tuple `(a,b)`, where `a` is the length of the output of `partial_products()` on a
/// vector of length `n`, and `b` is the number of elements needed to compute the final product.
pub fn num_partial_products(n: usize, max_degree: usize) -> (usize, usize) { pub fn num_partial_products(n: usize, max_degree: usize) -> (usize, usize) {
let mut res = 0; let mut res = 0;
let mut remainder = n; let mut remainder = n;
@ -38,6 +46,8 @@ pub fn num_partial_products(n: usize, max_degree: usize) -> (usize, usize) {
(res, remainder) (res, remainder)
} }
/// Checks that the partial products of `v` are coherent with those in `partials` by only computing
/// products of size `max_degree` or less.
pub fn check_partial_products<T: Product + Copy + Sub<Output = T>>( pub fn check_partial_products<T: Product + Copy + Sub<Output = T>>(
v: &[T], v: &[T],
partials: &[T], partials: &[T],