From 20e6d6540f0e90d0bc0136e3647fde5ce83ef958 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 1 Jul 2021 17:28:30 +0200 Subject: [PATCH] Add comments --- src/circuit_data.rs | 2 +- src/prover.rs | 34 ++++++++++++++++++++-------------- src/util/partial_products.rs | 10 ++++++++++ 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/circuit_data.rs b/src/circuit_data.rs index 0e48b171..22ef8ead 100644 --- a/src/circuit_data.rs +++ b/src/circuit_data.rs @@ -158,7 +158,7 @@ pub struct CommonCircuitData, const D: usize> { pub(crate) k_is: Vec, /// 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), /// A digest of the "circuit" (i.e. the instance, minus public inputs), which can be used to diff --git a/src/prover.rs b/src/prover.rs index 8aa1d979..0a1c7886 100644 --- a/src/prover.rs +++ b/src/prover.rs @@ -85,17 +85,16 @@ pub(crate) fn prove, const D: usize>( "to compute partial products" ); - let plonk_z_vecs = timed!( - compute_zs(&partial_products, prover_data, common_data), - "to compute Z's" - ); + let plonk_z_vecs = timed!(compute_zs(&partial_products, 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| { part.drain(0..2); }); let zs_partial_products = [plonk_z_vecs, partial_products.concat()].concat(); - let plonk_zs_commitment = timed!( + let zs_partial_products_commitment = timed!( ListPolynomialCommitment::new( zs_partial_products, fri_config.rate_bits, @@ -104,7 +103,7 @@ pub(crate) fn prove, const D: usize>( "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); @@ -113,7 +112,7 @@ pub(crate) fn prove, const D: usize>( common_data, prover_data, &wires_commitment, - &plonk_zs_commitment, + &zs_partial_products_commitment, &betas, &gammas, &alphas, @@ -156,7 +155,7 @@ pub(crate) fn prove, const D: usize>( &[ &prover_data.constants_sigmas_commitment, &wires_commitment, - &plonk_zs_commitment, + &zs_partial_products_commitment, "ient_polys_commitment, ], zeta, @@ -173,13 +172,14 @@ pub(crate) fn prove, const D: usize>( Proof { 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, openings, opening_proof, } } +/// Compute the partial products used in the `Z` polynomials. fn all_wires_permutation_partial_products, const D: usize>( witness: &Witness, betas: &[F], @@ -200,6 +200,9 @@ fn all_wires_permutation_partial_products, const D: usize>( .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, const D: usize>( witness: &Witness, beta: F, @@ -230,19 +233,25 @@ fn wires_permutation_partial_products, const D: usize>( wire_value + beta * s_sigma + gamma }) .collect::>(); + let numerator_partials = partial_products(&numerator_values, degree); let denominator_partials = partial_products(&denominator_values, degree); + + // This is the final product for the numerator. let numerator = numerator_partials [common_data.num_partial_products.0 - common_data.num_partial_products.1..] .iter() .copied() .product(); + // This is the final product for the denominator. let denominator = denominator_partials [common_data.num_partial_products.0 - common_data.num_partial_products.1..] .iter() .copied() .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![denominator], @@ -261,23 +270,20 @@ fn wires_permutation_partial_products, const D: usize>( fn compute_zs, const D: usize>( partial_products: &[Vec>], - prover_data: &ProverOnlyCircuitData, common_data: &CommonCircuitData, ) -> Vec> { (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() } +/// Compute the `Z` polynomial by reusing the computations done in `wires_permutation_partial_products`. fn compute_z, const D: usize>( partial_products: &[PolynomialValues], - prover_data: &ProverOnlyCircuitData, common_data: &CommonCircuitData, ) -> PolynomialValues { - let subgroup = &prover_data.subgroup; let mut plonk_z_points = vec![F::ONE]; for i in 1..common_data.degree() { - let x = subgroup[i - 1]; let numerator = partial_products[0].values[i - 1]; let denominator = partial_products[1].values[i - 1]; let last = *plonk_z_points.last().unwrap(); diff --git a/src/util/partial_products.rs b/src/util/partial_products.rs index f22ba01e..2eefdd1d 100644 --- a/src/util/partial_products.rs +++ b/src/util/partial_products.rs @@ -3,12 +3,17 @@ use std::ops::Sub; 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(v: &[T], max_degree: usize) -> Vec { let mut res = Vec::new(); let mut remainder = v.to_vec(); while remainder.len() >= max_degree { let new_partials = remainder .chunks(max_degree) + // No need to compute the product if the chunk has size 1. .filter(|chunk| chunk.len() != 1) .map(|chunk| chunk.iter().copied().product()) .collect::>(); @@ -19,12 +24,15 @@ pub fn partial_products(v: &[T], max_degree: usize) -> Vec vec![] }; remainder = new_partials; + // If there were a chunk of size 1, add it back to the remainder. remainder.extend(addendum); } 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) { let mut res = 0; let mut remainder = n; @@ -38,6 +46,8 @@ pub fn num_partial_products(n: usize, max_degree: usize) -> (usize, usize) { (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>( v: &[T], partials: &[T],