diff --git a/src/bin/bench_recursion.rs b/src/bin/bench_recursion.rs index b361adbb..6e035112 100644 --- a/src/bin/bench_recursion.rs +++ b/src/bin/bench_recursion.rs @@ -8,6 +8,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::witness::PartialWitness; fn main() { @@ -40,7 +41,7 @@ fn bench_prove() { rate_bits: 3, reduction_arity_bits: vec![1], num_query_rounds: 1, - blinding: true, + blinding: PLONK_BLINDING.to_vec(), }, }; diff --git a/src/circuit_builder.rs b/src/circuit_builder.rs index 45e2b06a..18ff666c 100644 --- a/src/circuit_builder.rs +++ b/src/circuit_builder.rs @@ -274,14 +274,16 @@ impl CircuitBuilder { let constant_vecs = self.constant_polys(); let constants_commitment = ListPolynomialCommitment::new( constant_vecs.into_iter().map(|v| v.ifft()).collect(), - &self.config.fri_config, + self.config.fri_config.rate_bits, + false, ); let k_is = get_unique_coset_shifts(degree, self.config.num_routed_wires); let sigma_vecs = self.sigma_vecs(&k_is); let sigmas_commitment = ListPolynomialCommitment::new( sigma_vecs.into_iter().map(|v| v.ifft()).collect(), - &self.config.fri_config, + self.config.fri_config.rate_bits, + false, ); let constants_root = constants_commitment.merkle_tree.root; diff --git a/src/circuit_data.rs b/src/circuit_data.rs index 1c51e47d..07713e8d 100644 --- a/src/circuit_data.rs +++ b/src/circuit_data.rs @@ -35,7 +35,7 @@ impl Default for CircuitConfig { rate_bits: 1, reduction_arity_bits: vec![1], num_query_rounds: 1, - blinding: true, + blinding: vec![true], }, } } diff --git a/src/fri/mod.rs b/src/fri/mod.rs index 9633face..6c8401a2 100644 --- a/src/fri/mod.rs +++ b/src/fri/mod.rs @@ -20,8 +20,9 @@ pub struct FriConfig { /// Number of query rounds to perform. pub num_query_rounds: usize, - /// True if the last element of the Merkle trees' leaf vectors is a blinding element. - pub blinding: bool, + /// 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, } fn fri_delta(rate_log: usize, conjecture: bool) -> f64 { @@ -79,7 +80,7 @@ mod tests { rate_bits, proof_of_work_bits: 2, reduction_arity_bits, - blinding: false, + blinding: vec![false], }; let tree = { let mut leaves = coset_lde diff --git a/src/fri/verifier.rs b/src/fri/verifier.rs index 952ef1ce..9e2f0164 100644 --- a/src/fri/verifier.rs +++ b/src/fri/verifier.rs @@ -149,7 +149,8 @@ fn fri_combine_initial( let e = proof .evals_proofs .iter() - .flat_map(|(v, _)| &v[..v.len() - if config.blinding { SALT_SIZE } else { 0 }]) + .enumerate() + .flat_map(|(i, (v, _))| &v[..v.len() - if config.blinding[i] { SALT_SIZE } else { 0 }]) .rev() .fold(F::ZERO, |acc, &e| alpha * acc + e); let numerator = e - interpolant.eval(subgroup_x); diff --git a/src/polynomial/commitment.rs b/src/polynomial/commitment.rs index 21fdf971..e3fb61ee 100644 --- a/src/polynomial/commitment.rs +++ b/src/polynomial/commitment.rs @@ -15,27 +15,28 @@ pub const SALT_SIZE: usize = 2; pub struct ListPolynomialCommitment { pub polynomials: Vec>, - pub fri_config: FriConfig, pub merkle_tree: MerkleTree, pub degree: usize, + pub rate_bits: usize, + pub blinding: bool, } impl ListPolynomialCommitment { - pub fn new(polynomials: Vec>, fri_config: &FriConfig) -> Self { + pub fn new(polynomials: Vec>, rate_bits: usize, blinding: bool) -> Self { let degree = polynomials[0].len(); let lde_values = polynomials .par_iter() .map(|p| { assert_eq!(p.len(), degree, "Polynomial degree invalid."); p.clone() - .lde(fri_config.rate_bits) + .lde(rate_bits) .coset_fft(F::MULTIPLICATIVE_GROUP_GENERATOR) .values }) - .chain(if fri_config.blinding { + .chain(if blinding { // If blinding, salt with two random elements to each leaf vector. (0..SALT_SIZE) - .map(|_| F::rand_vec(degree << fri_config.rate_bits)) + .map(|_| F::rand_vec(degree << rate_bits)) .collect() } else { Vec::new() @@ -48,22 +49,27 @@ impl ListPolynomialCommitment { Self { polynomials, - fri_config: fri_config.clone(), merkle_tree, degree, + rate_bits, + blinding, } } pub fn leaf(&self, index: usize) -> &[F] { let leaf = &self.merkle_tree.leaves[index]; - &leaf[0..leaf.len() - if self.fri_config.blinding { 2 } else { 0 }] + &leaf[0..leaf.len() - if self.blinding { SALT_SIZE } else { 0 }] } pub fn open( &self, points: &[F], challenger: &mut Challenger, + config: &FriConfig, ) -> (OpeningProof, Vec>) { + assert_eq!(self.rate_bits, config.rate_bits); + assert_eq!(config.blinding.len(), 1); + assert_eq!(self.blinding, config.blinding[0]); for p in points { assert_ne!( p.exp_usize(self.degree), @@ -102,7 +108,7 @@ impl ListPolynomialCommitment { let quotient = Self::compute_quotient(points, &composition_evals, &composition_poly); - let lde_quotient = PolynomialCoeffs::from(quotient.clone()).lde(self.fri_config.rate_bits); + let lde_quotient = PolynomialCoeffs::from(quotient.clone()).lde(self.rate_bits); let lde_quotient_values = lde_quotient .clone() .coset_fft(F::MULTIPLICATIVE_GROUP_GENERATOR); @@ -112,7 +118,7 @@ impl ListPolynomialCommitment { &lde_quotient, &lde_quotient_values, challenger, - &self.fri_config, + &config, ); ( @@ -128,17 +134,21 @@ impl ListPolynomialCommitment { commitments: &[&Self], points: &[F], challenger: &mut Challenger, + config: &FriConfig, ) -> (OpeningProof, Vec>>) { let degree = commitments[0].degree; - assert!( - commitments.iter().all(|c| c.degree == degree), - "Trying to open polynomial commitments of different degrees." - ); - let fri_config = &commitments[0].fri_config; - assert!( - commitments.iter().all(|c| &c.fri_config == fri_config), - "Trying to open polynomial commitments with different config." - ); + assert_eq!(config.blinding.len(), commitments.len()); + for (i, commitment) in commitments.iter().enumerate() { + assert_eq!(commitment.rate_bits, config.rate_bits, "Invalid rate."); + assert_eq!( + commitment.blinding, config.blinding[i], + "Invalid blinding paramater." + ); + assert_eq!( + commitment.degree, degree, + "Trying to open polynomial commitments of different degrees." + ); + } for p in points { assert_ne!( p.exp_usize(degree), @@ -184,7 +194,7 @@ impl ListPolynomialCommitment { let quotient = Self::compute_quotient(points, &composition_evals, &composition_poly); - let lde_quotient = PolynomialCoeffs::from(quotient.clone()).lde(fri_config.rate_bits); + let lde_quotient = PolynomialCoeffs::from(quotient.clone()).lde(config.rate_bits); let lde_quotient_values = lde_quotient .clone() .coset_fft(F::MULTIPLICATIVE_GROUP_GENERATOR); @@ -197,7 +207,7 @@ impl ListPolynomialCommitment { &lde_quotient, &lde_quotient_values, challenger, - &fri_config, + &config, ); ( @@ -213,8 +223,9 @@ impl ListPolynomialCommitment { commitments: &[&Self; 5], points: &[F], challenger: &mut Challenger, + config: &FriConfig, ) -> (OpeningProof, Vec>) { - let (op, mut evaluations) = Self::batch_open(commitments, points, challenger); + let (op, mut evaluations) = Self::batch_open(commitments, points, challenger, config); let opening_sets = evaluations .par_iter_mut() .map(|evals| { @@ -343,12 +354,12 @@ mod tests { rate_bits: 2, reduction_arity_bits: vec![3, 2, 1, 2], num_query_rounds: 3, - blinding: false, + blinding: vec![false], }; let (polys, points) = gen_random_test_case::(k, degree_log, num_points); - let lpc = ListPolynomialCommitment::new(polys, &fri_config); - let (proof, evaluations) = lpc.open(&points, &mut Challenger::new()); + let lpc = ListPolynomialCommitment::new(polys, fri_config.rate_bits, false); + let (proof, evaluations) = lpc.open(&points, &mut Challenger::new(), &fri_config); proof.verify( &points, &evaluations.into_iter().map(|e| vec![e]).collect::>(), @@ -370,12 +381,12 @@ mod tests { rate_bits: 2, reduction_arity_bits: vec![3, 2, 1, 2], num_query_rounds: 3, - blinding: true, + blinding: vec![true], }; let (polys, points) = gen_random_test_case::(k, degree_log, num_points); - let lpc = ListPolynomialCommitment::new(polys, &fri_config); - let (proof, evaluations) = lpc.open(&points, &mut Challenger::new()); + let lpc = ListPolynomialCommitment::new(polys, fri_config.rate_bits, true); + let (proof, evaluations) = lpc.open(&points, &mut Challenger::new(), &fri_config); proof.verify( &points, &evaluations.into_iter().map(|e| vec![e]).collect::>(), @@ -399,20 +410,21 @@ mod tests { rate_bits: 2, reduction_arity_bits: vec![2, 3, 1, 2], num_query_rounds: 3, - blinding: false, + blinding: vec![false, false, false], }; let (polys0, _) = gen_random_test_case::(k0, degree_log, num_points); let (polys1, _) = gen_random_test_case::(k0, degree_log, num_points); let (polys2, points) = gen_random_test_case::(k0, degree_log, num_points); - let lpc0 = ListPolynomialCommitment::new(polys0, &fri_config); - let lpc1 = ListPolynomialCommitment::new(polys1, &fri_config); - let lpc2 = ListPolynomialCommitment::new(polys2, &fri_config); + let lpc0 = ListPolynomialCommitment::new(polys0, fri_config.rate_bits, false); + let lpc1 = ListPolynomialCommitment::new(polys1, fri_config.rate_bits, false); + let lpc2 = ListPolynomialCommitment::new(polys2, fri_config.rate_bits, false); let (proof, evaluations) = ListPolynomialCommitment::batch_open( &[&lpc0, &lpc1, &lpc2], &points, &mut Challenger::new(), + &fri_config, ); proof.verify( &points, @@ -441,20 +453,21 @@ mod tests { rate_bits: 2, reduction_arity_bits: vec![2, 3, 1, 2], num_query_rounds: 3, - blinding: true, + blinding: vec![true, false, true], }; let (polys0, _) = gen_random_test_case::(k0, degree_log, num_points); let (polys1, _) = gen_random_test_case::(k0, degree_log, num_points); let (polys2, points) = gen_random_test_case::(k0, degree_log, num_points); - let lpc0 = ListPolynomialCommitment::new(polys0, &fri_config); - let lpc1 = ListPolynomialCommitment::new(polys1, &fri_config); - let lpc2 = ListPolynomialCommitment::new(polys2, &fri_config); + let lpc0 = ListPolynomialCommitment::new(polys0, fri_config.rate_bits, true); + let lpc1 = ListPolynomialCommitment::new(polys1, fri_config.rate_bits, false); + let lpc2 = ListPolynomialCommitment::new(polys2, fri_config.rate_bits, true); let (proof, evaluations) = ListPolynomialCommitment::batch_open( &[&lpc0, &lpc1, &lpc2], &points, &mut Challenger::new(), + &fri_config, ); proof.verify( &points, diff --git a/src/prover.rs b/src/prover.rs index 72d386d7..0ec2fa9a 100644 --- a/src/prover.rs +++ b/src/prover.rs @@ -26,6 +26,10 @@ macro_rules! timed { res }}; } + +/// Corresponds to constants - sigmas - wires - zs - quotient — polynomial commitments. +pub const PLONK_BLINDING: [bool; 5] = [false, false, true, true, true]; + pub(crate) fn prove( prover_data: &ProverOnlyCircuitData, common_data: &CommonCircuitData, @@ -59,7 +63,7 @@ pub(crate) fn prove( // TODO: Could try parallelizing the transpose, or not doing it explicitly, instead having // merkle_root_bit_rev_order do it implicitly. let wires_commitment = timed!( - ListPolynomialCommitment::new(wires_polynomials, &fri_config), + ListPolynomialCommitment::new(wires_polynomials, fri_config.rate_bits, true), "to compute wires commitment" ); @@ -75,7 +79,7 @@ pub(crate) fn prove( let plonk_z_vecs = timed!(compute_zs(&common_data), "to compute Z's"); let plonk_zs_commitment = timed!( - ListPolynomialCommitment::new(plonk_z_vecs, &fri_config), + ListPolynomialCommitment::new(plonk_z_vecs, fri_config.rate_bits, true), "to commit to Z's" ); @@ -107,7 +111,7 @@ pub(crate) fn prove( let quotient_poly_coeff_chunks = quotient_poly_coeff.chunks(degree); all_quotient_poly_chunks.extend(quotient_poly_coeff_chunks); } - ListPolynomialCommitment::new(all_quotient_poly_chunks, &fri_config) + ListPolynomialCommitment::new(all_quotient_poly_chunks, fri_config.rate_bits, true) }, "to compute quotient polys and commit to them" ); @@ -129,6 +133,7 @@ pub(crate) fn prove( ], &zetas, &mut challenger, + &common_data.config.fri_config ), "to compute opening proofs" );