move IPA-specific methods to the provider (#138)
Srinath Setty srinath@microsoft.com
Mon, 06 Feb 2023 18:07:14 -0800
7 files changed,
132 insertions(+),
114 deletions(-)
M
Cargo.toml
→
Cargo.toml
@@ -1,6 +1,6 @@
[package] name = "nova-snark" -version = "0.13.0" +version = "0.14.0" authors = ["Srinath Setty <srinath@microsoft.com>"] edition = "2021" description = "Recursive zkSNARKs without trusted setup"
M
src/bellperson/solver.rs
→
src/bellperson/solver.rs
@@ -32,7 +32,7 @@ impl<G: Group> fmt::Debug for SatisfyingAssignment<G>
where G::Scalar: PrimeField, { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt .debug_struct("SatisfyingAssignment") .field("a_aux_density", &self.a_aux_density)
M
src/lib.rs
→
src/lib.rs
@@ -1,7 +1,15 @@
//! This library implements Nova, a high-speed recursive SNARK. +#![deny( + warnings, + unused, + future_incompatible, + nonstandard_style, + rust_2018_idioms, + missing_docs +)] #![allow(non_snake_case)] #![allow(clippy::type_complexity)] -#![deny(missing_docs)] +#![forbid(unsafe_code)] // private modules mod bellperson;
M
src/provider/ipa_pc.rs
→
src/provider/ipa_pc.rs
@@ -2,6 +2,7 @@ //! This module implements `EvaluationEngine` using an IPA-based polynomial commitment scheme
#![allow(clippy::too_many_arguments)] use crate::{ errors::NovaError, + provider::pedersen::CommitmentGensExtTrait, spartan::polynomial::EqPolynomial, traits::{ commitment::{CommitmentEngineTrait, CommitmentGensTrait, CommitmentTrait},@@ -39,7 +40,11 @@ pub struct EvaluationEngine<G: Group> {
_p: PhantomData<G>, } -impl<G: Group> EvaluationEngineTrait<G> for EvaluationEngine<G> { +impl<G> EvaluationEngineTrait<G> for EvaluationEngine<G> +where + G: Group, + CommitmentGens<G>: CommitmentGensExtTrait<G, CE = G::CE>, +{ type CE = G::CE; type EvaluationGens = EvaluationGens<G>; type EvaluationArgument = EvaluationArgument<G>;@@ -99,7 +104,7 @@ /// A method to verify purported evaluations of a batch of polynomials
fn verify_batch( gens: &Self::EvaluationGens, transcript: &mut Transcript, - comms: &[<Self::CE as CommitmentEngineTrait<G>>::Commitment], + comms: &[Commitment<G>], points: &[Vec<G::Scalar>], evals: &[G::Scalar], arg: &Self::EvaluationArgument,@@ -324,7 +329,11 @@ a_hat: G::Scalar,
_p: PhantomData<G>, } -impl<G: Group> InnerProductArgument<G> { +impl<G> InnerProductArgument<G> +where + G: Group, + CommitmentGens<G>: CommitmentGensExtTrait<G, CE = G::CE>, +{ fn protocol_name() -> &'static [u8] { b"inner product argument" }
M
src/provider/pedersen.rs
→
src/provider/pedersen.rs
@@ -60,92 +60,6 @@ Commitment {
comm: G::vartime_multiscalar_mul(v, &self.gens[..v.len()]), } } - - fn split_at(&self, n: usize) -> (CommitmentGens<G>, CommitmentGens<G>) { - ( - CommitmentGens { - gens: self.gens[0..n].to_vec(), - _p: Default::default(), - }, - CommitmentGens { - gens: self.gens[n..].to_vec(), - _p: Default::default(), - }, - ) - } - - fn combine(&self, other: &CommitmentGens<G>) -> CommitmentGens<G> { - let gens = { - let mut c = self.gens.clone(); - c.extend(other.gens.clone()); - c - }; - CommitmentGens { - gens, - _p: Default::default(), - } - } - - // combines the left and right halves of `self` using `w1` and `w2` as the weights - fn fold(&self, w1: &G::Scalar, w2: &G::Scalar) -> CommitmentGens<G> { - let w = vec![*w1, *w2]; - let (L, R) = self.split_at(self.len() / 2); - - let gens = (0..self.len() / 2) - .into_par_iter() - .map(|i| { - let gens = CommitmentGens::<G> { - gens: [L.gens[i].clone(), R.gens[i].clone()].to_vec(), - _p: Default::default(), - }; - gens.commit(&w).comm.preprocessed() - }) - .collect(); - - CommitmentGens { - gens, - _p: Default::default(), - } - } - - /// Scales each element in `self` by `r` - fn scale(&self, r: &G::Scalar) -> Self { - let gens_scaled = self - .gens - .clone() - .into_par_iter() - .map(|g| { - let gens = CommitmentGens::<G> { - gens: vec![g], - _p: Default::default(), - }; - gens.commit(&[*r]).comm.preprocessed() - }) - .collect(); - - CommitmentGens { - gens: gens_scaled, - _p: Default::default(), - } - } - - /// reinterprets a vector of commitments as a set of generators - fn reinterpret_commitments_as_gens( - c: &[CompressedCommitment<G::CompressedGroupElement>], - ) -> Result<Self, NovaError> { - let d = (0..c.len()) - .into_par_iter() - .map(|i| c[i].decompress()) - .collect::<Result<Vec<Commitment<G>>, NovaError>>()?; - let gens = (0..d.len()) - .into_par_iter() - .map(|i| d[i].comm.preprocessed()) - .collect(); - Ok(CommitmentGens { - gens, - _p: Default::default(), - }) - } } impl<G: Group> CommitmentTrait<G> for Commitment<G> {@@ -302,3 +216,109 @@ fn commit(gens: &Self::CommitmentGens, v: &[G::Scalar]) -> Self::Commitment {
gens.commit(v) } } + +pub(crate) trait CommitmentGensExtTrait<G: Group>: CommitmentGensTrait<G> { + type CE: CommitmentEngineTrait<G>; + + /// Splits the commitment key into two pieces at a specified point + fn split_at(&self, n: usize) -> (Self, Self) + where + Self: Sized; + + /// Combines two commitment keys into one + fn combine(&self, other: &Self) -> Self; + + /// Folds the two commitment keys into one using the provided weights + fn fold(&self, w1: &G::Scalar, w2: &G::Scalar) -> Self; + + /// Scales the commitment key using the provided scalar + fn scale(&self, r: &G::Scalar) -> Self; + + /// Reinterprets commitments as commitment keys + fn reinterpret_commitments_as_gens( + c: &[<<Self as CommitmentGensExtTrait<G>>::CE as CommitmentEngineTrait<G>>::CompressedCommitment], + ) -> Result<Self, NovaError> + where + Self: Sized; +} + +impl<G: Group> CommitmentGensExtTrait<G> for CommitmentGens<G> { + type CE = CommitmentEngine<G>; + + fn split_at(&self, n: usize) -> (CommitmentGens<G>, CommitmentGens<G>) { + ( + CommitmentGens { + gens: self.gens[0..n].to_vec(), + _p: Default::default(), + }, + CommitmentGens { + gens: self.gens[n..].to_vec(), + _p: Default::default(), + }, + ) + } + + fn combine(&self, other: &CommitmentGens<G>) -> CommitmentGens<G> { + let gens = { + let mut c = self.gens.clone(); + c.extend(other.gens.clone()); + c + }; + CommitmentGens { + gens, + _p: Default::default(), + } + } + + // combines the left and right halves of `self` using `w1` and `w2` as the weights + fn fold(&self, w1: &G::Scalar, w2: &G::Scalar) -> CommitmentGens<G> { + let w = vec![*w1, *w2]; + let (L, R) = self.split_at(self.len() / 2); + + let gens = (0..self.len() / 2) + .into_par_iter() + .map(|i| { + let bases = [L.gens[i].clone(), R.gens[i].clone()].to_vec(); + G::vartime_multiscalar_mul(&w, &bases).preprocessed() + }) + .collect(); + + CommitmentGens { + gens, + _p: Default::default(), + } + } + + /// Scales each element in `self` by `r` + fn scale(&self, r: &G::Scalar) -> Self { + let gens_scaled = self + .gens + .clone() + .into_par_iter() + .map(|g| G::vartime_multiscalar_mul(&[*r], &[g]).preprocessed()) + .collect(); + + CommitmentGens { + gens: gens_scaled, + _p: Default::default(), + } + } + + /// reinterprets a vector of commitments as a set of generators + fn reinterpret_commitments_as_gens( + c: &[CompressedCommitment<G::CompressedGroupElement>], + ) -> Result<Self, NovaError> { + let d = (0..c.len()) + .into_par_iter() + .map(|i| c[i].decompress()) + .collect::<Result<Vec<Commitment<G>>, NovaError>>()?; + let gens = (0..d.len()) + .into_par_iter() + .map(|i| d[i].comm.preprocessed()) + .collect(); + Ok(CommitmentGens { + gens, + _p: Default::default(), + }) + } +}
M
src/r1cs.rs
→
src/r1cs.rs
@@ -247,7 +247,7 @@ res == 0
}; // verify if comm_W is a commitment to W - let res_comm: bool = U.comm_W == gens.gens.commit(&W.W); + let res_comm: bool = U.comm_W == CE::<G>::commit(&gens.gens, &W.W); if res_eq && res_comm { Ok(())@@ -301,7 +301,7 @@ .zip(&u_2_cdot_CZ_1)
.map(|(((a, b), c), d)| *a + *b - *c - *d) .collect::<Vec<G::Scalar>>(); - let comm_T = gens.gens.commit(&T); + let comm_T = CE::<G>::commit(&gens.gens, &T); Ok((T, comm_T)) }@@ -466,7 +466,7 @@ }
/// Commits to the witness using the supplied generators pub fn commit(&self, gens: &R1CSGens<G>) -> Commitment<G> { - gens.gens.commit(&self.W) + CE::<G>::commit(&gens.gens, &self.W) } }
M
src/traits/commitment.rs
→
src/traits/commitment.rs
@@ -29,25 +29,6 @@ fn len(&self) -> usize;
/// Commits to a vector using the commitment key fn commit(&self, v: &[G::Scalar]) -> Self::Commitment; - - /// Splits the commitment key into two pieces at a specified point - fn split_at(&self, n: usize) -> (Self, Self) - where - Self: Sized; - - /// Combines two commitment keys into one - fn combine(&self, other: &Self) -> Self; - - /// Folds the two commitment keys into one using the provided weights - fn fold(&self, w1: &G::Scalar, w2: &G::Scalar) -> Self; - - /// Scales the commitment key using the provided scalar - fn scale(&self, r: &G::Scalar) -> Self; - - /// Reinterprets commitments as commitment keys - fn reinterpret_commitments_as_gens(c: &[Self::CompressedCommitment]) -> Result<Self, NovaError> - where - Self: Sized; } /// Defines basic operations on commitments