Browse Source

refactor: bring back compressed snark

and cleanup some group op traits
main
dignifiedquire 3 years ago
committed by Srinath Setty
parent
commit
3ba8fd28aa
4 changed files with 103 additions and 43 deletions
  1. +42
    -21
      src/commitments.rs
  2. +14
    -5
      src/lib.rs
  3. +17
    -8
      src/r1cs.rs
  4. +30
    -9
      src/traits.rs

+ 42
- 21
src/commitments.rs

@ -94,8 +94,18 @@ impl<'b, G: Group> MulAssign<&'b G::Scalar> for Commitment {
} }
} }
impl<'a, 'b, G: Group> Mul<&'b G::Scalar> for &'a Commitment<G> {
type Output = Commitment<G>;
fn mul(self, scalar: &'b G::Scalar) -> Commitment<G> {
Commitment {
comm: self.comm * scalar,
}
}
}
impl<G: Group> Mul<G::Scalar> for Commitment<G> { impl<G: Group> Mul<G::Scalar> for Commitment<G> {
type Output = Commitment<G>; type Output = Commitment<G>;
fn mul(self, scalar: G::Scalar) -> Commitment<G> { fn mul(self, scalar: G::Scalar) -> Commitment<G> {
Commitment { Commitment {
comm: self.comm * scalar, comm: self.comm * scalar,
@ -119,29 +129,40 @@ impl<'a, 'b, G: Group> Add<&'b Commitment> for &'a Commitment {
} }
} }
impl<G: Group> AddAssign<Commitment<G>> for Commitment<G> {
fn add_assign(&mut self, rhs: Commitment<G>) {
*self += &rhs;
}
}
macro_rules! define_add_variants {
(G = $g:path, LHS = $lhs:ty, RHS = $rhs:ty, Output = $out:ty) => {
impl<'b, G: $g> Add<&'b $rhs> for $lhs {
type Output = $out;
fn add(self, rhs: &'b $rhs) -> $out {
&self + rhs
}
}
impl<'b, G: Group> Add<&'b Commitment<G>> for Commitment<G> {
type Output = Commitment<G>;
fn add(self, rhs: &'b Commitment<G>) -> Commitment<G> {
&self + rhs
}
}
impl<'a, G: $g> Add<$rhs> for &'a $lhs {
type Output = $out;
fn add(self, rhs: $rhs) -> $out {
self + &rhs
}
}
impl<'a, G: Group> Add<Commitment<G>> for &'a Commitment<G> {
type Output = Commitment<G>;
fn add(self, rhs: Commitment<G>) -> Commitment<G> {
self + &rhs
}
impl<G: $g> Add<$rhs> for $lhs {
type Output = $out;
fn add(self, rhs: $rhs) -> $out {
&self + &rhs
}
}
};
} }
impl<G: Group> Add<Commitment<G>> for Commitment<G> {
type Output = Commitment<G>;
fn add(self, rhs: Commitment<G>) -> Commitment<G> {
&self + &rhs
}
macro_rules! define_add_assign_variants {
(G = $g:path, LHS = $lhs:ty, RHS = $rhs:ty) => {
impl<G: $g> AddAssign<$rhs> for $lhs {
fn add_assign(&mut self, rhs: $rhs) {
*self += &rhs;
}
}
};
} }
define_add_assign_variants!(G = Group, LHS = Commitment<G>, RHS = Commitment<G>);
define_add_variants!(G = Group, LHS = Commitment<G>, RHS = Commitment<G>, Output = Commitment<G>);

+ 14
- 5
src/lib.rs

@ -8,7 +8,9 @@ mod errors;
mod r1cs; mod r1cs;
mod traits; mod traits;
use commitments::{AppendToTranscriptTrait, Commitment};
use std::marker::PhantomData;
use commitments::{AppendToTranscriptTrait, CompressedCommitment};
use errors::NovaError; use errors::NovaError;
use merlin::Transcript; use merlin::Transcript;
use r1cs::{R1CSGens, R1CSInstance, R1CSShape, R1CSWitness}; use r1cs::{R1CSGens, R1CSInstance, R1CSShape, R1CSWitness};
@ -16,7 +18,8 @@ use traits::{ChallengeTrait, Group};
/// A SNARK that holds the proof of a step of an incremental computation /// A SNARK that holds the proof of a step of an incremental computation
pub struct StepSNARK<G: Group> { pub struct StepSNARK<G: Group> {
comm_T: Commitment<G>,
comm_T: CompressedCommitment<G::CompressedGroupElement>,
_p: PhantomData<G>,
} }
impl<G: Group> StepSNARK<G> { impl<G: Group> StepSNARK<G> {
@ -52,13 +55,19 @@ impl StepSNARK {
let r = G::Scalar::challenge(b"r", transcript); let r = G::Scalar::challenge(b"r", transcript);
// fold the instance using `r` and `comm_T` // fold the instance using `r` and `comm_T`
let U = U1.fold(U2, &comm_T, &r);
let U = U1.fold(U2, &comm_T, &r)?;
// fold the witness using `r` and `T` // fold the witness using `r` and `T`
let W = W1.fold(W2, &T, &r)?; let W = W1.fold(W2, &T, &r)?;
// return the folded instance and witness // return the folded instance and witness
Ok((StepSNARK { comm_T }, (U, W)))
Ok((
StepSNARK {
comm_T,
_p: Default::default(),
},
(U, W),
))
} }
/// Takes as input two relaxed R1CS instances `U1` and `U2` /// Takes as input two relaxed R1CS instances `U1` and `U2`
@ -82,7 +91,7 @@ impl StepSNARK {
let r = G::Scalar::challenge(b"r", transcript); let r = G::Scalar::challenge(b"r", transcript);
// fold the instance using `r` and `comm_T` // fold the instance using `r` and `comm_T`
let U = U1.fold(U2, &self.comm_T, &r);
let U = U1.fold(U2, &self.comm_T, &r)?;
// return the folded instance // return the folded instance
Ok(U) Ok(U)

+ 17
- 8
src/r1cs.rs

@ -1,4 +1,6 @@
#![allow(clippy::type_complexity)] #![allow(clippy::type_complexity)]
use crate::commitments::CompressedCommitment;
use super::commitments::{CommitGens, CommitTrait, Commitment}; use super::commitments::{CommitGens, CommitTrait, Commitment};
use super::errors::NovaError; use super::errors::NovaError;
use super::traits::{Group, PrimeField}; use super::traits::{Group, PrimeField};
@ -182,7 +184,13 @@ impl R1CSShape {
W1: &R1CSWitness<G>, W1: &R1CSWitness<G>,
U2: &R1CSInstance<G>, U2: &R1CSInstance<G>,
W2: &R1CSWitness<G>, W2: &R1CSWitness<G>,
) -> Result<(Vec<G::Scalar>, Commitment<G>), NovaError> {
) -> Result<
(
Vec<G::Scalar>,
CompressedCommitment<G::CompressedGroupElement>,
),
NovaError,
> {
let (AZ_1, BZ_1, CZ_1) = { let (AZ_1, BZ_1, CZ_1) = {
let Z1 = concat(vec![W1.W.clone(), vec![U1.u], U1.X.clone()]); let Z1 = concat(vec![W1.W.clone(), vec![U1.u], U1.X.clone()]);
self.multiply_vec(&Z1)? self.multiply_vec(&Z1)?
@ -214,7 +222,7 @@ impl R1CSShape {
.map(|(((a, b), c), d)| *a + *b - *c - *d) .map(|(((a, b), c), d)| *a + *b - *c - *d)
.collect::<Vec<G::Scalar>>(); .collect::<Vec<G::Scalar>>();
let comm_T = T.commit(&gens.gens_E);
let comm_T = T.commit(&gens.gens_E).compress();
Ok((T, comm_T)) Ok((T, comm_T))
} }
@ -291,9 +299,10 @@ impl R1CSInstance {
pub fn fold( pub fn fold(
&self, &self,
U2: &R1CSInstance<G>, U2: &R1CSInstance<G>,
comm_T: &Commitment<G>,
comm_T: &CompressedCommitment<G::CompressedGroupElement>,
r: &G::Scalar, r: &G::Scalar,
) -> R1CSInstance<G> {
) -> Result<R1CSInstance<G>, NovaError> {
let comm_T_unwrapped = comm_T.decompress()?;
let (X1, u1, comm_W_1, comm_E_1) = let (X1, u1, comm_W_1, comm_E_1) =
(&self.X, &self.u, &self.comm_W.clone(), &self.comm_E.clone()); (&self.X, &self.u, &self.comm_W.clone(), &self.comm_E.clone());
let (X2, u2, comm_W_2, comm_E_2) = (&U2.X, &U2.u, &U2.comm_W, &U2.comm_E); let (X2, u2, comm_W_2, comm_E_2) = (&U2.X, &U2.u, &U2.comm_W, &U2.comm_E);
@ -304,15 +313,15 @@ impl R1CSInstance {
.zip(X2) .zip(X2)
.map(|(a, b)| *a + *r * *b) .map(|(a, b)| *a + *r * *b)
.collect::<Vec<G::Scalar>>(); .collect::<Vec<G::Scalar>>();
let comm_W = comm_W_1 + *comm_W_2 * *r;
let comm_E = *comm_E_1 + *comm_T * *r + *comm_E_2 * *r * *r;
let comm_W = comm_W_1 + comm_W_2 * r;
let comm_E = *comm_E_1 + comm_T_unwrapped * *r + comm_E_2 * r * *r;
let u = *u1 + *r * *u2; let u = *u1 + *r * *u2;
R1CSInstance {
Ok(R1CSInstance {
comm_W, comm_W,
comm_E, comm_E,
X, X,
u, u,
}
})
} }
} }

+ 30
- 9
src/traits.rs

@ -48,17 +48,13 @@ pub trait Group:
+ Debug + Debug
+ Eq + Eq
+ Sized + Sized
+ Mul<<Self as Group>::Scalar, Output = Self>
+ MulAssign<<Self as Group>::Scalar>
+ for<'a> MulAssign<&'a <Self as Group>::Scalar>
+ for<'a> Mul<&'a <Self as Group>::Scalar, Output = Self>
+ Add<Self, Output = Self>
+ AddAssign<Self>
+ for<'a> AddAssign<&'a Self>
+ for<'a> Add<&'a Self, Output = Self>
+ GroupOps
+ GroupOpsOwned
+ ScalarMul<<Self as Group>::Scalar>
+ ScalarMulOwned<<Self as Group>::Scalar>
{ {
type Scalar: PrimeField + ChallengeTrait; type Scalar: PrimeField + ChallengeTrait;
type CompressedGroupElement: CompressedGroup;
type CompressedGroupElement: CompressedGroup<GroupElement = Self>;
fn vartime_multiscalar_mul<I, J>(scalars: I, points: J) -> Self fn vartime_multiscalar_mul<I, J>(scalars: I, points: J) -> Self
where where
@ -86,3 +82,28 @@ pub trait CompressedGroup: Clone + Copy + Debug + Eq + Sized + Send + Sync + 'st
pub trait ChallengeTrait { pub trait ChallengeTrait {
fn challenge(label: &'static [u8], transcript: &mut Transcript) -> Self; fn challenge(label: &'static [u8], transcript: &mut Transcript) -> Self;
} }
/// A helper trait for types with a group operation.
pub trait GroupOps<Rhs = Self, Output = Self>:
Add<Rhs, Output = Output> + Sub<Rhs, Output = Output> + AddAssign<Rhs> + SubAssign<Rhs>
{
}
impl<T, Rhs, Output> GroupOps<Rhs, Output> for T where
T: Add<Rhs, Output = Output> + Sub<Rhs, Output = Output> + AddAssign<Rhs> + SubAssign<Rhs>
{
}
/// A helper trait for references with a group operation.
pub trait GroupOpsOwned<Rhs = Self, Output = Self>: for<'r> GroupOps<&'r Rhs, Output> {}
impl<T, Rhs, Output> GroupOpsOwned<Rhs, Output> for T where T: for<'r> GroupOps<&'r Rhs, Output> {}
/// A helper trait for types implementing group scalar multiplication.
pub trait ScalarMul<Rhs, Output = Self>: Mul<Rhs, Output = Output> + MulAssign<Rhs> {}
impl<T, Rhs, Output> ScalarMul<Rhs, Output> for T where T: Mul<Rhs, Output = Output> + MulAssign<Rhs>
{}
/// A helper trait for references implementing group scalar multiplication.
pub trait ScalarMulOwned<Rhs, Output = Self>: for<'r> ScalarMul<&'r Rhs, Output> {}
impl<T, Rhs, Output> ScalarMulOwned<Rhs, Output> for T where T: for<'r> ScalarMul<&'r Rhs, Output> {}

Loading…
Cancel
Save