diff --git a/src/circuit_builder.rs b/src/circuit_builder.rs index 1bf938a0..912fb146 100644 --- a/src/circuit_builder.rs +++ b/src/circuit_builder.rs @@ -280,48 +280,48 @@ impl, const D: usize> CircuitBuilder { } fn blind_and_pad(&mut self) { - let (regular_poly_openings, z_openings) = self.blinding_counts(); - - let num_routed_wires = self.config.num_routed_wires; - let num_wires = self.config.num_wires; - - // For each "regular" blinding factor, we simply add a no-op gate, and insert a random value - // for each wire. - for _ in 0..regular_poly_openings { - let gate = self.add_gate_no_constants(NoopGate::get()); - for w in 0..num_wires { - self.add_generator(RandomValueGenerator { - target: Target::Wire(Wire { gate, input: w }), - }); - } - } - - // For each z poly blinding factor, we add two new gates with the same random value, and - // enforce a copy constraint between them. - // See https://mirprotocol.org/blog/Adding-zero-knowledge-to-Plonk-Halo - for _ in 0..z_openings { - let gate_1 = self.add_gate_no_constants(NoopGate::get()); - let gate_2 = self.add_gate_no_constants(NoopGate::get()); - - for w in 0..num_routed_wires { - self.add_generator(RandomValueGenerator { - target: Target::Wire(Wire { - gate: gate_1, - input: w, - }), - }); - self.add_generator(CopyGenerator { - src: Target::Wire(Wire { - gate: gate_1, - input: w, - }), - dst: Target::Wire(Wire { - gate: gate_2, - input: w, - }), - }); - } - } + // let (regular_poly_openings, z_openings) = self.blinding_counts(); + // + // let num_routed_wires = self.config.num_routed_wires; + // let num_wires = self.config.num_wires; + // + // // For each "regular" blinding factor, we simply add a no-op gate, and insert a random value + // // for each wire. + // for _ in 0..regular_poly_openings { + // let gate = self.add_gate_no_constants(NoopGate::get()); + // for w in 0..num_wires { + // self.add_generator(RandomValueGenerator { + // target: Target::Wire(Wire { gate, input: w }), + // }); + // } + // } + // + // // For each z poly blinding factor, we add two new gates with the same random value, and + // // enforce a copy constraint between them. + // // See https://mirprotocol.org/blog/Adding-zero-knowledge-to-Plonk-Halo + // for _ in 0..z_openings { + // let gate_1 = self.add_gate_no_constants(NoopGate::get()); + // let gate_2 = self.add_gate_no_constants(NoopGate::get()); + // + // for w in 0..num_routed_wires { + // self.add_generator(RandomValueGenerator { + // target: Target::Wire(Wire { + // gate: gate_1, + // input: w, + // }), + // }); + // self.add_generator(CopyGenerator { + // src: Target::Wire(Wire { + // gate: gate_1, + // input: w, + // }), + // dst: Target::Wire(Wire { + // gate: gate_2, + // input: w, + // }), + // }); + // } + // } while !self.gate_instances.len().is_power_of_two() { self.add_gate_no_constants(NoopGate::get()); diff --git a/src/prover.rs b/src/prover.rs index 76b69e10..e909c923 100644 --- a/src/prover.rs +++ b/src/prover.rs @@ -13,6 +13,7 @@ use crate::polynomial::commitment::ListPolynomialCommitment; use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues}; use crate::proof::Proof; use crate::timed; +use crate::util::partial_products::partial_products; use crate::util::{ceil_div_usize, log2_ceil, transpose}; use crate::vars::EvaluationVarsBase; use crate::witness::{PartialWitness, Witness}; @@ -89,10 +90,9 @@ pub(crate) fn prove, const D: usize>( "to compute Z's" ); - let zs_partial_products = [partial_products.concat(), plonk_z_vecs].concat(); let plonk_zs_commitment = timed!( ListPolynomialCommitment::new( - zs_partial_products, + plonk_z_vecs, fri_config.rate_bits, PlonkPolynomials::ZS.blinding ), @@ -206,37 +206,33 @@ fn wires_permutation_partial_products, const D: usize>( .max_filtered_constraint_degree .next_power_of_two(); let num_polys = ceil_div_usize(common_data.config.num_routed_wires, vanish_degree); - assert!( - num_polys <= vanish_degree, - "Not supported yet. would need to add partial products of partial products for this." - ); let subgroup = &prover_data.subgroup; let mut values = vec![vec![F::ONE; 2 * num_polys]]; let k_is = &common_data.k_is; for i in 1..common_data.degree() { let x = subgroup[i - 1]; let s_sigmas = &prover_data.sigmas[i - 1]; - let mut partials_numerator = Vec::with_capacity(2 * num_polys); - let mut partials_denominator = Vec::with_capacity(num_polys); - for chunk in (0..common_data.config.num_routed_wires) - .collect::>() - .chunks(vanish_degree) - { - let (numerator, denominator) = chunk.iter().fold((F::ONE, F::ONE), |acc, &j| { + let numerator_values = (0..common_data.config.num_routed_wires) + .map(|j| { let wire_value = witness.get_wire(i - 1, j); let k_i = k_is[j]; let s_id = k_i * x; + wire_value + beta * s_id + gamma + }) + .collect::>(); + let denominator_values = (0..common_data.config.num_routed_wires) + .map(|j| { + let wire_value = witness.get_wire(i - 1, j); let s_sigma = s_sigmas[j]; - ( - acc.0 * wire_value + beta * s_id + gamma, - acc.1 * wire_value + beta * s_sigma + gamma, - ) - }); - partials_numerator.push(numerator); - partials_denominator.push(denominator); - } - partials_numerator.append(&mut partials_denominator); - values.push(partials_numerator); + wire_value + beta * s_sigma + gamma + }) + .collect::>(); + let partials = [ + partial_products(numerator_values, vanish_degree), + partial_products(denominator_values, vanish_degree), + ] + .concat(); + values.push(partials); } transpose(&values) diff --git a/src/util/mod.rs b/src/util/mod.rs index f901b0af..3fb38c05 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,3 +1,4 @@ +pub mod partial_products; pub mod scaling; pub(crate) mod timing; diff --git a/src/util/partial_products.rs b/src/util/partial_products.rs new file mode 100644 index 00000000..0546d133 --- /dev/null +++ b/src/util/partial_products.rs @@ -0,0 +1,30 @@ +use std::iter::Product; + +pub fn partial_products(v: Vec, max_degree: usize) -> Vec { + let mut res = Vec::new(); + let mut remainder = v; + while remainder.len() > max_degree { + let new_partials = remainder + .chunks(max_degree) + .filter(|chunk| chunk.len() != 1) // Don't need to compute the product in this case. + .map(|chunk| chunk.iter().copied().product()) + .collect::>(); + res.extend_from_slice(&new_partials); + remainder = new_partials; + } + + res +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_partial_products() { + assert_eq!( + partial_products(vec![1, 2, 3, 4, 5, 6], 2), + vec![2, 12, 30, 24] + ); + } +}