Browse Source

move IPA-specific methods to the provider (#138)

main
Srinath Setty 1 year ago
committed by GitHub
parent
commit
b97786d291
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 132 additions and 114 deletions
  1. +1
    -1
      Cargo.toml
  2. +1
    -1
      src/bellperson/solver.rs
  3. +9
    -1
      src/lib.rs
  4. +12
    -3
      src/provider/ipa_pc.rs
  5. +106
    -86
      src/provider/pedersen.rs
  6. +3
    -3
      src/r1cs.rs
  7. +0
    -19
      src/traits/commitment.rs

+ 1
- 1
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"

+ 1
- 1
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)

+ 9
- 1
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;

+ 12
- 3
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<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 @@ impl EvaluationEngineTrait for EvaluationEngine {
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 @@ struct InnerProductArgument {
_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"
}

+ 106
- 86
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<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 @@ impl CommitmentEngineTrait for CommitmentEngine {
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(),
})
}
}

+ 3
- 3
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::<G>::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::<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 @@ impl R1CSWitness {
/// 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)
}
}

+ 0
- 19
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<Self, NovaError>
where
Self: Sized;
}
/// Defines basic operations on commitments

Loading…
Cancel
Save