arnaucube
arnaucube/NovaPublic Self-hosted repository
refactor: bring back compressed snark

and cleanup some group op traits
dignifiedquire me@dignifiedquire.com
Wed, 01 Sep 2021 10:10:40 +0200
commit

3ba8fd28aa6a4e80357641eb38946faf7200dbdf

parent

732d937b09e8d286e5c72cade4c592d1a8b98f76

4 files changed, 103 insertions(+), 43 deletions(-)

jump to
M src/commitments.rs → src/commitments.rs

@@ -94,8 +94,18 @@ *self = Commitment { comm: result };

} } +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> { type Output = Commitment<G>; + fn mul(self, scalar: G::Scalar) -> Commitment<G> { Commitment { comm: self.comm * scalar,

@@ -119,29 +129,40 @@ }

} } -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<G: $g> Add<$rhs> for $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 - } +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; + } + } + }; } -impl<G: Group> Add<Commitment<G>> for Commitment<G> { - type Output = Commitment<G>; - fn add(self, rhs: Commitment<G>) -> Commitment<G> { - &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>);
M src/lib.rs → src/lib.rs

@@ -8,7 +8,9 @@ mod errors;

mod r1cs; mod traits; -use commitments::{AppendToTranscriptTrait, Commitment}; +use std::marker::PhantomData; + +use commitments::{AppendToTranscriptTrait, CompressedCommitment}; use errors::NovaError; use merlin::Transcript; 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 pub struct StepSNARK<G: Group> { - comm_T: Commitment<G>, + comm_T: CompressedCommitment<G::CompressedGroupElement>, + _p: PhantomData<G>, } impl<G: Group> StepSNARK<G> {

@@ -52,13 +55,19 @@ // compute a challenge from the transcript

let r = G::Scalar::challenge(b"r", transcript); // 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` let W = W1.fold(W2, &T, &r)?; // 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`

@@ -82,7 +91,7 @@ // compute a challenge from the transcript

let r = G::Scalar::challenge(b"r", transcript); // 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 Ok(U)
M src/r1cs.rs → src/r1cs.rs

@@ -1,4 +1,6 @@

#![allow(clippy::type_complexity)] +use crate::commitments::CompressedCommitment; + use super::commitments::{CommitGens, CommitTrait, Commitment}; use super::errors::NovaError; use super::traits::{Group, PrimeField};

@@ -182,7 +184,13 @@ U1: &R1CSInstance<G>,

W1: &R1CSWitness<G>, U2: &R1CSInstance<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 Z1 = concat(vec![W1.W.clone(), vec![U1.u], U1.X.clone()]); self.multiply_vec(&Z1)?

@@ -214,7 +222,7 @@ .zip(&u_2_cdot_CZ_1)

.map(|(((a, b), c), d)| *a + *b - *c - *d) .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)) }

@@ -291,9 +299,10 @@

pub fn fold( &self, U2: &R1CSInstance<G>, - comm_T: &Commitment<G>, + comm_T: &CompressedCommitment<G::CompressedGroupElement>, 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) = (&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);

@@ -304,15 +313,15 @@ .par_iter()

.zip(X2) .map(|(a, b)| *a + *r * *b) .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; - R1CSInstance { + Ok(R1CSInstance { comm_W, comm_E, X, u, - } + }) } }
M src/traits.rs → src/traits.rs

@@ -48,17 +48,13 @@ + Copy

+ Debug + Eq + 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 CompressedGroupElement: CompressedGroup; + type CompressedGroupElement: CompressedGroup<GroupElement = Self>; fn vartime_multiscalar_mul<I, J>(scalars: I, points: J) -> Self where

@@ -86,3 +82,28 @@ /// A helper trait to generate challenges using a transcript object

pub trait ChallengeTrait { 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> {}