diff --git a/src/commitments.rs b/src/commitments.rs index 89eae87..8d64f2b 100644 --- a/src/commitments.rs +++ b/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 { + type Output = Commitment; + fn mul(self, scalar: &'b G::Scalar) -> Commitment { + Commitment { + comm: self.comm * scalar, + } + } +} + impl Mul for Commitment { type Output = Commitment; + fn mul(self, scalar: G::Scalar) -> Commitment { Commitment { comm: self.comm * scalar, @@ -119,29 +129,40 @@ impl<'a, 'b, G: Group> Add<&'b Commitment> for &'a Commitment { } } -impl AddAssign> for Commitment { - fn add_assign(&mut self, rhs: Commitment) { - *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> for Commitment { - type Output = Commitment; - fn add(self, rhs: &'b Commitment) -> Commitment { - &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> for &'a Commitment { - type Output = Commitment; - fn add(self, rhs: Commitment) -> Commitment { - self + &rhs - } + impl Add<$rhs> for $lhs { + type Output = $out; + fn add(self, rhs: $rhs) -> $out { + &self + &rhs + } + } + }; } -impl Add> for Commitment { - type Output = Commitment; - fn add(self, rhs: Commitment) -> Commitment { - &self + &rhs - } +macro_rules! define_add_assign_variants { + (G = $g:path, LHS = $lhs:ty, RHS = $rhs:ty) => { + impl AddAssign<$rhs> for $lhs { + fn add_assign(&mut self, rhs: $rhs) { + *self += &rhs; + } + } + }; } + +define_add_assign_variants!(G = Group, LHS = Commitment, RHS = Commitment); +define_add_variants!(G = Group, LHS = Commitment, RHS = Commitment, Output = Commitment); diff --git a/src/lib.rs b/src/lib.rs index 0b5a4e1..a0768ac 100644 --- a/src/lib.rs +++ b/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 { - comm_T: Commitment, + comm_T: CompressedCommitment, + _p: PhantomData, } impl StepSNARK { @@ -52,13 +55,19 @@ impl StepSNARK { 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 @@ impl StepSNARK { 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) diff --git a/src/r1cs.rs b/src/r1cs.rs index 980b6df..bd95484 100644 --- a/src/r1cs.rs +++ b/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 @@ impl R1CSShape { W1: &R1CSWitness, U2: &R1CSInstance, W2: &R1CSWitness, - ) -> Result<(Vec, Commitment), NovaError> { + ) -> Result< + ( + Vec, + CompressedCommitment, + ), + 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 @@ impl R1CSShape { .map(|(((a, b), c), d)| *a + *b - *c - *d) .collect::>(); - 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 @@ impl R1CSInstance { pub fn fold( &self, U2: &R1CSInstance, - comm_T: &Commitment, + comm_T: &CompressedCommitment, r: &G::Scalar, - ) -> R1CSInstance { + ) -> Result, 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 @@ impl R1CSInstance { .zip(X2) .map(|(a, b)| *a + *r * *b) .collect::>(); - 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, - } + }) } } diff --git a/src/traits.rs b/src/traits.rs index 57ddc7e..15d4274 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -48,17 +48,13 @@ pub trait Group: + Debug + Eq + Sized - + Mul<::Scalar, Output = Self> - + MulAssign<::Scalar> - + for<'a> MulAssign<&'a ::Scalar> - + for<'a> Mul<&'a ::Scalar, Output = Self> - + Add - + AddAssign - + for<'a> AddAssign<&'a Self> - + for<'a> Add<&'a Self, Output = Self> + + GroupOps + + GroupOpsOwned + + ScalarMul<::Scalar> + + ScalarMulOwned<::Scalar> { type Scalar: PrimeField + ChallengeTrait; - type CompressedGroupElement: CompressedGroup; + type CompressedGroupElement: CompressedGroup; fn vartime_multiscalar_mul(scalars: I, points: J) -> Self where @@ -86,3 +82,28 @@ pub trait CompressedGroup: Clone + Copy + Debug + Eq + Sized + Send + Sync + 'st pub trait ChallengeTrait { fn challenge(label: &'static [u8], transcript: &mut Transcript) -> Self; } + +/// A helper trait for types with a group operation. +pub trait GroupOps: + Add + Sub + AddAssign + SubAssign +{ +} + +impl GroupOps for T where + T: Add + Sub + AddAssign + SubAssign +{ +} + +/// A helper trait for references with a group operation. +pub trait GroupOpsOwned: for<'r> GroupOps<&'r Rhs, Output> {} +impl GroupOpsOwned for T where T: for<'r> GroupOps<&'r Rhs, Output> {} + +/// A helper trait for types implementing group scalar multiplication. +pub trait ScalarMul: Mul + MulAssign {} + +impl ScalarMul for T where T: Mul + MulAssign +{} + +/// A helper trait for references implementing group scalar multiplication. +pub trait ScalarMulOwned: for<'r> ScalarMul<&'r Rhs, Output> {} +impl ScalarMulOwned for T where T: for<'r> ScalarMul<&'r Rhs, Output> {}