diff --git a/halo2_proofs/src/arithmetic.rs b/halo2_proofs/src/arithmetic.rs index f442223e..ada38277 100644 --- a/halo2_proofs/src/arithmetic.rs +++ b/halo2_proofs/src/arithmetic.rs @@ -1,6 +1,8 @@ //! This module provides common utilities, traits and structures for group, //! field and polynomial arithmetic. +use std::io; + use super::multicore; pub use ff::Field; use group::{ @@ -352,6 +354,42 @@ pub fn parallelize(v: &mu }); } +/// This simple utility function will parallelize an operation returning `io::Result` that is to be +/// performed over a mutable slice. +pub fn parallelize_is_ok< + T: Send, + F: Fn(&mut [T], usize) -> io::Result<()> + Send + Sync + Clone, +>( + v: &mut [T], + f: F, +) -> io::Result<()> { + let n = v.len(); + let num_threads = multicore::current_num_threads(); + let mut chunk = (n as usize) / num_threads; + if chunk < num_threads { + chunk = n as usize; + } + + let mut is_ok = true; + multicore::scope(|scope| { + for (chunk_num, v) in v.chunks_mut(chunk).enumerate() { + let f = f.clone(); + scope.spawn(move |_| { + let start = chunk_num * chunk; + is_ok = is_ok && f(v, start).is_ok(); + }); + } + }); + + match is_ok { + true => Ok(()), + false => Err(io::Error::new( + io::ErrorKind::Other, + "invalid point encoding in proof", + )), + } +} + fn log2_floor(num: usize) -> u32 { assert!(num > 0); diff --git a/halo2_proofs/src/helpers.rs b/halo2_proofs/src/helpers.rs index aca2ce14..2b216f9f 100644 --- a/halo2_proofs/src/helpers.rs +++ b/halo2_proofs/src/helpers.rs @@ -11,6 +11,11 @@ pub(crate) trait CurveRead: CurveAffine { Option::from(Self::from_bytes(&compressed)) .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "invalid point encoding in proof")) } + + fn convert_from_bytes(compressed: Self::Repr) -> io::Result { + Option::from(Self::from_bytes(&compressed)) + .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "invalid point encoding in proof")) + } } impl CurveRead for C {} diff --git a/halo2_proofs/src/poly/commitment.rs b/halo2_proofs/src/poly/commitment.rs index 4ee93723..507f53d3 100644 --- a/halo2_proofs/src/poly/commitment.rs +++ b/halo2_proofs/src/poly/commitment.rs @@ -5,7 +5,8 @@ use super::{Coeff, LagrangeCoeff, Polynomial, MSM}; use crate::arithmetic::{ - best_fft, best_multiexp, parallelize, CurveAffine, CurveExt, Engine, FieldExt, Group, + best_fft, best_multiexp, parallelize, parallelize_is_ok, CurveAffine, CurveExt, Engine, + FieldExt, Group, }; use crate::helpers::CurveRead; @@ -177,12 +178,45 @@ impl Params { let k = u32::from_le_bytes(k); let n = 1 << k; - let g: Vec = (0..n) - .map(|_| C::read(&mut reader)) - .collect::>()?; - let g_lagrange: Vec = (0..n) - .map(|_| C::read(&mut reader)) - .collect::>()?; + let mut g_compressed: Vec = vec![C::Repr::default(); n]; + for i in 0..n { + reader.read_exact(g_compressed[i].as_mut())?; + } + + let mut g_lagrange_compressed: Vec = vec![C::Repr::default(); n]; + for i in 0..n { + reader.read_exact(g_lagrange_compressed[i].as_mut())?; + } + + let g: Vec = { + let mut g = vec![C::default(); n]; + parallelize_is_ok(&mut g, |g, chunks| { + for (i, g) in g.iter_mut().enumerate() { + let tmp = C::convert_from_bytes(g_compressed[chunks + i]); + *g = match tmp { + Ok(ele) => ele, + Err(e) => return Err(e), + } + } + Ok(()) + })?; + g + }; + + let g_lagrange: Vec = { + let mut g_lagrange = vec![C::default(); n]; + parallelize_is_ok(&mut g_lagrange, |g_lagrange, chunks| { + for (i, g_lagrange) in g_lagrange.iter_mut().enumerate() { + let tmp = C::convert_from_bytes(g_lagrange_compressed[chunks + i]); + *g_lagrange = match tmp { + Ok(ele) => ele, + Err(e) => return Err(e), + } + } + Ok(()) + })?; + g_lagrange + }; let mut additional_data_len = [0u8; 4]; reader.read_exact(&mut additional_data_len[..])?; @@ -193,7 +227,7 @@ impl Params { Ok(Params { k, - n, + n: n as u64, g, g_lagrange, additional_data,