diff --git a/src/poly/commitment.rs b/src/poly/commitment.rs index 73572ed1..15e089e3 100644 --- a/src/poly/commitment.rs +++ b/src/poly/commitment.rs @@ -8,113 +8,13 @@ use crate::arithmetic::{best_fft, best_multiexp, parallelize, Curve, CurveAffine use crate::transcript::Hasher; use std::ops::{Add, AddAssign, Mul, MulAssign}; +mod msm; mod prover; mod verifier; +pub use msm::MSM; pub use verifier::{Accumulator, Guard}; -/// This is a proof object for the polynomial commitment scheme opening. -#[derive(Debug, Clone)] -pub struct Proof { - rounds: Vec<(C, C)>, - delta: C, - z1: C::Scalar, - z2: C::Scalar, -} - -/// A multiscalar multiplication in the polynomial commitment scheme -#[derive(Debug, Clone)] -pub struct MSM<'a, C: CurveAffine> { - params: &'a Params, - g_scalars: Option>, - h_scalar: Option, - other_scalars: Vec, - other_bases: Vec, -} - -impl<'a, C: CurveAffine> MSM<'a, C> { - /// Add another multiexp into this one - pub fn add_msm(&mut self, other: &Self) { - self.other_scalars.extend(other.other_scalars.iter()); - self.other_bases.extend(other.other_bases.iter()); - - if let Some(g_scalars) = &other.g_scalars { - self.add_to_g(&g_scalars); - } - - if let Some(h_scalar) = &other.h_scalar { - self.add_to_h(*h_scalar); - } - } - - /// Add arbitrary term (the scalar and the point) - pub fn add_term(&mut self, scalar: C::Scalar, point: C) { - self.other_scalars.push(scalar); - self.other_bases.push(point); - } - - /// Add a vector of scalars to `g_scalars`. This function will panic if the - /// caller provides a slice of scalars that is not of length `params.n`. - // TODO: parallelize - pub fn add_to_g(&mut self, scalars: &[C::Scalar]) { - assert_eq!(scalars.len(), self.params.n as usize); - if let Some(g_scalars) = &mut self.g_scalars { - for (g_scalar, scalar) in g_scalars.iter_mut().zip(scalars.iter()) { - *g_scalar += &scalar; - } - } else { - self.g_scalars = Some(scalars.to_vec()); - } - } - - /// Add term to h - pub fn add_to_h(&mut self, scalar: C::Scalar) { - self.h_scalar = self.h_scalar.map_or(Some(scalar), |a| Some(a + &scalar)); - } - - /// Scale all scalars in the MSM by some scaling factor - // TODO: parallelize - pub fn scale(&mut self, factor: C::Scalar) { - if let Some(g_scalars) = &mut self.g_scalars { - for g_scalar in g_scalars.iter_mut() { - *g_scalar *= &factor; - } - } - - // TODO: parallelize - for other_scalar in self.other_scalars.iter_mut() { - *other_scalar *= &factor; - } - self.h_scalar = self.h_scalar.map(|a| a * &factor); - } - - /// Perform multiexp and check that it results in zero - pub fn eval(self) -> bool { - let len = self.g_scalars.as_ref().map(|v| v.len()).unwrap_or(0) - + self.h_scalar.map(|_| 1).unwrap_or(0) - + self.other_scalars.len(); - let mut scalars: Vec = Vec::with_capacity(len); - let mut bases: Vec = Vec::with_capacity(len); - - scalars.extend(&self.other_scalars); - bases.extend(&self.other_bases); - - if let Some(h_scalar) = self.h_scalar { - scalars.push(h_scalar); - bases.push(self.params.h); - } - - if let Some(g_scalars) = &self.g_scalars { - scalars.extend(g_scalars); - bases.extend(self.params.g.iter()); - } - - assert_eq!(scalars.len(), len); - - bool::from(best_multiexp(&scalars, &bases).is_zero()) - } -} - /// These are the public parameters for the polynomial commitment scheme. #[derive(Debug)] pub struct Params { @@ -125,6 +25,15 @@ pub struct Params { pub(crate) h: C, } +/// This is a proof object for the polynomial commitment scheme opening. +#[derive(Debug, Clone)] +pub struct Proof { + rounds: Vec<(C, C)>, + delta: C, + z1: C::Scalar, + z2: C::Scalar, +} + impl Params { /// Initializes parameters for the curve, given a random oracle to draw /// points from. @@ -250,18 +159,7 @@ impl Params { /// Generates an empty multiscalar multiplication struct using the /// appropriate params. pub fn empty_msm(&self) -> MSM { - let g_scalars = None; - let h_scalar = None; - let other_scalars = vec![]; - let other_bases = vec![]; - - MSM { - params: &self, - g_scalars, - h_scalar, - other_scalars, - other_bases, - } + MSM::new(self) } /// Getter for g generators diff --git a/src/poly/commitment/msm.rs b/src/poly/commitment/msm.rs new file mode 100644 index 00000000..7e04d923 --- /dev/null +++ b/src/poly/commitment/msm.rs @@ -0,0 +1,111 @@ +use super::Params; +use crate::arithmetic::{best_multiexp, Curve, CurveAffine}; + +/// A multiscalar multiplication in the polynomial commitment scheme +#[derive(Debug, Clone)] +pub struct MSM<'a, C: CurveAffine> { + pub(crate) params: &'a Params, + g_scalars: Option>, + h_scalar: Option, + other_scalars: Vec, + other_bases: Vec, +} + +impl<'a, C: CurveAffine> MSM<'a, C> { + /// Create a new, empty MSM using the provided parameters. + pub fn new(params: &'a Params) -> Self { + let g_scalars = None; + let h_scalar = None; + let other_scalars = vec![]; + let other_bases = vec![]; + + MSM { + params, + g_scalars, + h_scalar, + other_scalars, + other_bases, + } + } + + /// Add another multiexp into this one + pub fn add_msm(&mut self, other: &Self) { + self.other_scalars.extend(other.other_scalars.iter()); + self.other_bases.extend(other.other_bases.iter()); + + if let Some(g_scalars) = &other.g_scalars { + self.add_to_g(&g_scalars); + } + + if let Some(h_scalar) = &other.h_scalar { + self.add_to_h(*h_scalar); + } + } + + /// Add arbitrary term (the scalar and the point) + pub fn add_term(&mut self, scalar: C::Scalar, point: C) { + self.other_scalars.push(scalar); + self.other_bases.push(point); + } + + /// Add a vector of scalars to `g_scalars`. This function will panic if the + /// caller provides a slice of scalars that is not of length `params.n`. + // TODO: parallelize + pub fn add_to_g(&mut self, scalars: &[C::Scalar]) { + assert_eq!(scalars.len(), self.params.n as usize); + if let Some(g_scalars) = &mut self.g_scalars { + for (g_scalar, scalar) in g_scalars.iter_mut().zip(scalars.iter()) { + *g_scalar += &scalar; + } + } else { + self.g_scalars = Some(scalars.to_vec()); + } + } + + /// Add term to h + pub fn add_to_h(&mut self, scalar: C::Scalar) { + self.h_scalar = self.h_scalar.map_or(Some(scalar), |a| Some(a + &scalar)); + } + + /// Scale all scalars in the MSM by some scaling factor + // TODO: parallelize + pub fn scale(&mut self, factor: C::Scalar) { + if let Some(g_scalars) = &mut self.g_scalars { + for g_scalar in g_scalars.iter_mut() { + *g_scalar *= &factor; + } + } + + // TODO: parallelize + for other_scalar in self.other_scalars.iter_mut() { + *other_scalar *= &factor; + } + self.h_scalar = self.h_scalar.map(|a| a * &factor); + } + + /// Perform multiexp and check that it results in zero + pub fn eval(self) -> bool { + let len = self.g_scalars.as_ref().map(|v| v.len()).unwrap_or(0) + + self.h_scalar.map(|_| 1).unwrap_or(0) + + self.other_scalars.len(); + let mut scalars: Vec = Vec::with_capacity(len); + let mut bases: Vec = Vec::with_capacity(len); + + scalars.extend(&self.other_scalars); + bases.extend(&self.other_bases); + + if let Some(h_scalar) = self.h_scalar { + scalars.push(h_scalar); + bases.push(self.params.h); + } + + if let Some(g_scalars) = &self.g_scalars { + scalars.extend(g_scalars); + bases.extend(self.params.g.iter()); + } + + assert_eq!(scalars.len(), len); + + bool::from(best_multiexp(&scalars, &bases).is_zero()) + } +}