diff --git a/src/provider/hyperkzg.rs b/src/provider/hyperkzg.rs index 4bd8802a..31442b39 100644 --- a/src/provider/hyperkzg.rs +++ b/src/provider/hyperkzg.rs @@ -444,6 +444,27 @@ where } } + fn batch_commit( + ck: &Self::CommitmentKey, + v: &[Vec<::Scalar>], + r: &[::Scalar], + ) -> Vec { + assert!(v.len() == r.len()); + + let max = v.iter().map(|v| v.len()).max().unwrap_or(0); + assert!(ck.ck.len() >= max); + + let h = ::group(&ck.h); + + E::GE::batch_vartime_multiscalar_mul(v, &ck.ck[..max]) + .iter() + .zip(r.iter()) + .map(|(commit, r_i)| Commitment { + comm: *commit + (h * r_i), + }) + .collect() + } + fn derandomize( dk: &Self::DerandKey, commit: &Self::Commitment, @@ -735,9 +756,10 @@ where // We do not need to commit to the first polynomial as it is already committed. // Compute commitments in parallel - let com: Vec> = (1..polys.len()) - .into_par_iter() - .map(|i| E::CE::commit(ck, &polys[i], &E::Scalar::ZERO).comm.affine()) + let r = vec![E::Scalar::ZERO; ell - 1]; + let com: Vec> = E::CE::batch_commit(ck, &polys[1..], r.as_slice()) + .iter() + .map(|i| i.comm.affine()) .collect(); // Phase 2 diff --git a/src/provider/traits.rs b/src/provider/traits.rs index 11721548..6b67a86a 100644 --- a/src/provider/traits.rs +++ b/src/provider/traits.rs @@ -4,6 +4,7 @@ use core::{ ops::{Add, AddAssign, Sub, SubAssign}, }; use halo2curves::{serde::SerdeObject, CurveAffine}; +use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use serde::{Deserialize, Serialize}; /// A helper trait for types with a group operation. @@ -51,6 +52,17 @@ pub trait DlogGroup: /// A method to compute a multiexponentation fn vartime_multiscalar_mul(scalars: &[Self::Scalar], bases: &[Self::AffineGroupElement]) -> Self; + /// A method to compute a batch of multiexponentations + fn batch_vartime_multiscalar_mul( + scalars: &[Vec], + bases: &[Self::AffineGroupElement], + ) -> Vec { + scalars + .par_iter() + .map(|scalar| Self::vartime_multiscalar_mul(scalar, &bases[..scalar.len()])) + .collect::>() + } + /// Produce a vector of group elements using a static label fn from_label(label: &'static [u8], n: usize) -> Vec; diff --git a/src/traits/commitment.rs b/src/traits/commitment.rs index 7162eee5..398dc620 100644 --- a/src/traits/commitment.rs +++ b/src/traits/commitment.rs @@ -8,6 +8,7 @@ use core::{ fmt::Debug, ops::{Add, Mul, MulAssign}, }; +use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; use serde::{Deserialize, Serialize}; /// A helper trait for types implementing scalar multiplication. @@ -71,6 +72,19 @@ pub trait CommitmentEngineTrait: Clone + Send + Sync { /// Commits to the provided vector using the provided generators and random blind fn commit(ck: &Self::CommitmentKey, v: &[E::Scalar], r: &E::Scalar) -> Self::Commitment; + /// Batch commits to the provided vectors using the provided generators and random blind + fn batch_commit( + ck: &Self::CommitmentKey, + v: &[Vec], + r: &[E::Scalar], + ) -> Vec { + assert!(v.len() == r.len()); + v.par_iter() + .zip(r.par_iter()) + .map(|(v_i, r_i)| Self::commit(ck, v_i, r_i)) + .collect() + } + /// Remove given blind from commitment fn derandomize( dk: &Self::DerandKey,