diff --git a/halo2_proofs/src/plonk.rs b/halo2_proofs/src/plonk.rs index 78bfc21501..1248aaf122 100644 --- a/halo2_proofs/src/plonk.rs +++ b/halo2_proofs/src/plonk.rs @@ -8,7 +8,7 @@ use blake2b_simd::Params as Blake2bParams; use group::ff::{Field, FromUniformBytes, PrimeField}; -use crate::arithmetic::CurveAffine; +use crate::arithmetic::{parallelize, CurveAffine}; use crate::helpers::{ polynomial_slice_byte_length, read_polynomial_vec, write_polynomial_slice, SerdeCurveAffine, SerdePrimeField, @@ -387,12 +387,7 @@ where /// Does so by first writing the verifying key and then serializing the rest of the data (in the form of field polynomials) pub fn write(&self, writer: &mut W, format: SerdeFormat) -> io::Result<()> { self.vk.write(writer, format)?; - self.l0.write(writer, format)?; - self.l_last.write(writer, format)?; - self.l_active_row.write(writer, format)?; write_polynomial_slice(&self.fixed_values, writer, format)?; - write_polynomial_slice(&self.fixed_polys, writer, format)?; - write_polynomial_slice(&self.fixed_cosets, writer, format)?; self.permutation.write(writer, format)?; Ok(()) } @@ -419,13 +414,51 @@ where #[cfg(feature = "circuit-params")] params, )?; - let l0 = Polynomial::read(reader, format)?; - let l_last = Polynomial::read(reader, format)?; - let l_active_row = Polynomial::read(reader, format)?; + + // Compute l_0(X) + let mut l0 = vk.domain.empty_lagrange(); + l0[0] = C::Scalar::ONE; + let l0 = vk.domain.lagrange_to_coeff(l0); + let l0 = vk.domain.coeff_to_extended(l0); + + // Compute l_blind(X) which evaluates to 1 for each blinding factor row + // and 0 otherwise over the domain. + let mut l_blind = vk.domain.empty_lagrange(); + for evaluation in l_blind[..].iter_mut().rev().take(vk.cs.blinding_factors()) { + *evaluation = C::Scalar::ONE; + } + let l_blind = vk.domain.lagrange_to_coeff(l_blind); + let l_blind = vk.domain.coeff_to_extended(l_blind); + + // Compute l_last(X) which evaluates to 1 on the first inactive row (just + // before the blinding factors) and 0 otherwise over the domain + let mut l_last = vk.domain.empty_lagrange(); + let n = l_last.len(); + l_last[n - vk.cs.blinding_factors() - 1] = C::Scalar::ONE; + let l_last = vk.domain.lagrange_to_coeff(l_last); + let l_last = vk.domain.coeff_to_extended(l_last); + + // Compute l_active_row(X) + let one = C::Scalar::ONE; + let mut l_active_row = vk.domain.empty_extended(); + parallelize(&mut l_active_row, |values, start| { + for (i, value) in values.iter_mut().enumerate() { + let idx = i + start; + *value = one - (l_last[idx] + l_blind[idx]); + } + }); + let fixed_values = read_polynomial_vec(reader, format)?; - let fixed_polys = read_polynomial_vec(reader, format)?; - let fixed_cosets = read_polynomial_vec(reader, format)?; - let permutation = permutation::ProvingKey::read(reader, format)?; + let fixed_polys: Vec<_> = fixed_values + .iter() + .map(|poly| vk.domain.lagrange_to_coeff(poly.clone())) + .collect(); + let fixed_cosets = fixed_polys + .iter() + .map(|poly| vk.domain.coeff_to_extended(poly.clone())) + .collect(); + let permutation = + permutation::ProvingKey::read(reader, format, &vk.domain, &vk.cs.permutation)?; let ev = Evaluator::new(vk.cs()); Ok(Self { vk, diff --git a/halo2_proofs/src/plonk/permutation.rs b/halo2_proofs/src/plonk/permutation.rs index 22c1fad6c3..d237ea08eb 100644 --- a/halo2_proofs/src/plonk/permutation.rs +++ b/halo2_proofs/src/plonk/permutation.rs @@ -2,12 +2,12 @@ use super::circuit::{Any, Column}; use crate::{ - arithmetic::CurveAffine, + arithmetic::{parallelize, CurveAffine}, helpers::{ polynomial_slice_byte_length, read_polynomial_vec, write_polynomial_slice, SerdeCurveAffine, SerdePrimeField, }, - poly::{Coeff, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial}, + poly::{Coeff, EvaluationDomain, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial}, SerdeFormat, }; @@ -138,10 +138,33 @@ where C::Scalar: SerdePrimeField, { /// Reads proving key for a single permutation argument from buffer using `Polynomial::read`. - pub(super) fn read(reader: &mut R, format: SerdeFormat) -> io::Result { + pub(super) fn read( + reader: &mut R, + format: SerdeFormat, + domain: &EvaluationDomain, + p: &Argument, + ) -> io::Result { let permutations = read_polynomial_vec(reader, format)?; - let polys = read_polynomial_vec(reader, format)?; - let cosets = read_polynomial_vec(reader, format)?; + let mut polys = vec![domain.empty_coeff(); p.columns.len()]; + { + parallelize(&mut polys, |o, start| { + for (x, poly) in o.iter_mut().enumerate() { + let i = start + x; + let permutation_poly = permutations[i].clone(); + *poly = domain.lagrange_to_coeff(permutation_poly); + } + }); + } + let mut cosets = vec![domain.empty_extended(); p.columns.len()]; + { + parallelize(&mut cosets, |o, start| { + for (x, coset) in o.iter_mut().enumerate() { + let i = start + x; + let poly = polys[i].clone(); + *coset = domain.coeff_to_extended(poly); + } + }); + } Ok(ProvingKey { permutations, polys, @@ -156,8 +179,6 @@ where format: SerdeFormat, ) -> io::Result<()> { write_polynomial_slice(&self.permutations, writer, format)?; - write_polynomial_slice(&self.polys, writer, format)?; - write_polynomial_slice(&self.cosets, writer, format)?; Ok(()) } }