From b97786d291acdb6f6b36dbb8b94c66d1f569d53a Mon Sep 17 00:00:00 2001 From: Srinath Setty Date: Mon, 6 Feb 2023 18:07:14 -0800 Subject: [PATCH] move IPA-specific methods to the provider (#138) --- Cargo.toml | 2 +- src/bellperson/solver.rs | 2 +- src/lib.rs | 10 +- src/provider/ipa_pc.rs | 15 ++- src/provider/pedersen.rs | 192 +++++++++++++++++++++------------------ src/r1cs.rs | 6 +- src/traits/commitment.rs | 19 ---- 7 files changed, 132 insertions(+), 114 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d466d9e..7402559 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nova-snark" -version = "0.13.0" +version = "0.14.0" authors = ["Srinath Setty "] edition = "2021" description = "Recursive zkSNARKs without trusted setup" diff --git a/src/bellperson/solver.rs b/src/bellperson/solver.rs index 0d16645..c350d66 100644 --- a/src/bellperson/solver.rs +++ b/src/bellperson/solver.rs @@ -32,7 +32,7 @@ impl fmt::Debug for SatisfyingAssignment 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) diff --git a/src/lib.rs b/src/lib.rs index dc3cfcf..d0d9697 100644 --- a/src/lib.rs +++ b/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; diff --git a/src/provider/ipa_pc.rs b/src/provider/ipa_pc.rs index 44467ff..8884475 100644 --- a/src/provider/ipa_pc.rs +++ b/src/provider/ipa_pc.rs @@ -2,6 +2,7 @@ #![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 { _p: PhantomData, } -impl EvaluationEngineTrait for EvaluationEngine { +impl EvaluationEngineTrait for EvaluationEngine +where + G: Group, + CommitmentGens: CommitmentGensExtTrait, +{ type CE = G::CE; type EvaluationGens = EvaluationGens; type EvaluationArgument = EvaluationArgument; @@ -99,7 +104,7 @@ impl EvaluationEngineTrait for EvaluationEngine { fn verify_batch( gens: &Self::EvaluationGens, transcript: &mut Transcript, - comms: &[>::Commitment], + comms: &[Commitment], points: &[Vec], evals: &[G::Scalar], arg: &Self::EvaluationArgument, @@ -324,7 +329,11 @@ struct InnerProductArgument { _p: PhantomData, } -impl InnerProductArgument { +impl InnerProductArgument +where + G: Group, + CommitmentGens: CommitmentGensExtTrait, +{ fn protocol_name() -> &'static [u8] { b"inner product argument" } diff --git a/src/provider/pedersen.rs b/src/provider/pedersen.rs index ba15496..14d79e2 100644 --- a/src/provider/pedersen.rs +++ b/src/provider/pedersen.rs @@ -60,92 +60,6 @@ impl CommitmentGensTrait for CommitmentGens { comm: G::vartime_multiscalar_mul(v, &self.gens[..v.len()]), } } - - fn split_at(&self, n: usize) -> (CommitmentGens, CommitmentGens) { - ( - 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) -> CommitmentGens { - 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 { - 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:: { - 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:: { - 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], - ) -> Result { - let d = (0..c.len()) - .into_par_iter() - .map(|i| c[i].decompress()) - .collect::>, NovaError>>()?; - let gens = (0..d.len()) - .into_par_iter() - .map(|i| d[i].comm.preprocessed()) - .collect(); - Ok(CommitmentGens { - gens, - _p: Default::default(), - }) - } } impl CommitmentTrait for Commitment { @@ -302,3 +216,109 @@ impl CommitmentEngineTrait for CommitmentEngine { gens.commit(v) } } + +pub(crate) trait CommitmentGensExtTrait: CommitmentGensTrait { + type CE: CommitmentEngineTrait; + + /// 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: &[<>::CE as CommitmentEngineTrait>::CompressedCommitment], + ) -> Result + where + Self: Sized; +} + +impl CommitmentGensExtTrait for CommitmentGens { + type CE = CommitmentEngine; + + fn split_at(&self, n: usize) -> (CommitmentGens, CommitmentGens) { + ( + 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) -> CommitmentGens { + 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 { + 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], + ) -> Result { + let d = (0..c.len()) + .into_par_iter() + .map(|i| c[i].decompress()) + .collect::>, NovaError>>()?; + let gens = (0..d.len()) + .into_par_iter() + .map(|i| d[i].comm.preprocessed()) + .collect(); + Ok(CommitmentGens { + gens, + _p: Default::default(), + }) + } +} diff --git a/src/r1cs.rs b/src/r1cs.rs index a6de17f..a5a1b78 100644 --- a/src/r1cs.rs +++ b/src/r1cs.rs @@ -247,7 +247,7 @@ impl R1CSShape { }; // 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::::commit(&gens.gens, &W.W); if res_eq && res_comm { Ok(()) @@ -301,7 +301,7 @@ impl R1CSShape { .map(|(((a, b), c), d)| *a + *b - *c - *d) .collect::>(); - let comm_T = gens.gens.commit(&T); + let comm_T = CE::::commit(&gens.gens, &T); Ok((T, comm_T)) } @@ -466,7 +466,7 @@ impl R1CSWitness { /// Commits to the witness using the supplied generators pub fn commit(&self, gens: &R1CSGens) -> Commitment { - gens.gens.commit(&self.W) + CE::::commit(&gens.gens, &self.W) } } diff --git a/src/traits/commitment.rs b/src/traits/commitment.rs index 8dc1ef2..0a10f4f 100644 --- a/src/traits/commitment.rs +++ b/src/traits/commitment.rs @@ -29,25 +29,6 @@ pub trait CommitmentGensTrait: /// 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 - where - Self: Sized; } /// Defines basic operations on commitments