mirror of
https://github.com/arnaucube/Nova.git
synced 2026-01-11 08:31:29 +01:00
refactor: bring back compressed snark
and cleanup some group op traits
This commit is contained in:
committed by
Srinath Setty
parent
732d937b09
commit
3ba8fd28aa
@@ -94,8 +94,18 @@ impl<'b, G: Group> MulAssign<&'b G::Scalar> for Commitment<G> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<G>> for &'a Commitment<G> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G: Group> AddAssign<Commitment<G>> for Commitment<G> {
|
macro_rules! define_add_variants {
|
||||||
fn add_assign(&mut self, rhs: Commitment<G>) {
|
(G = $g:path, LHS = $lhs:ty, RHS = $rhs:ty, Output = $out:ty) => {
|
||||||
*self += &rhs;
|
impl<'b, G: $g> Add<&'b $rhs> for $lhs {
|
||||||
}
|
type Output = $out;
|
||||||
}
|
fn add(self, rhs: &'b $rhs) -> $out {
|
||||||
|
|
||||||
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
|
&self + rhs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, G: Group> Add<Commitment<G>> for &'a Commitment<G> {
|
impl<'a, G: $g> Add<$rhs> for &'a $lhs {
|
||||||
type Output = Commitment<G>;
|
type Output = $out;
|
||||||
fn add(self, rhs: Commitment<G>) -> Commitment<G> {
|
fn add(self, rhs: $rhs) -> $out {
|
||||||
self + &rhs
|
self + &rhs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G: Group> Add<Commitment<G>> for Commitment<G> {
|
impl<G: $g> Add<$rhs> for $lhs {
|
||||||
type Output = Commitment<G>;
|
type Output = $out;
|
||||||
fn add(self, rhs: Commitment<G>) -> Commitment<G> {
|
fn add(self, rhs: $rhs) -> $out {
|
||||||
&self + &rhs
|
&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>);
|
||||||
|
|||||||
19
src/lib.rs
19
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<G: Group> StepSNARK<G> {
|
|||||||
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<G: Group> StepSNARK<G> {
|
|||||||
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)
|
||||||
|
|||||||
25
src/r1cs.rs
25
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<G: Group> R1CSShape<G> {
|
|||||||
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<G: Group> R1CSShape<G> {
|
|||||||
.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<G: Group> R1CSInstance<G> {
|
|||||||
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<G: Group> R1CSInstance<G> {
|
|||||||
.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_W = comm_W_1 + comm_W_2 * r;
|
||||||
let comm_E = *comm_E_1 + *comm_T * *r + *comm_E_2 * *r * *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,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,17 +48,13 @@ pub trait Group:
|
|||||||
+ Debug
|
+ Debug
|
||||||
+ Eq
|
+ Eq
|
||||||
+ Sized
|
+ Sized
|
||||||
+ Mul<<Self as Group>::Scalar, Output = Self>
|
+ GroupOps
|
||||||
+ MulAssign<<Self as Group>::Scalar>
|
+ GroupOpsOwned
|
||||||
+ for<'a> MulAssign<&'a <Self as Group>::Scalar>
|
+ ScalarMul<<Self as Group>::Scalar>
|
||||||
+ for<'a> Mul<&'a <Self as Group>::Scalar, Output = Self>
|
+ ScalarMulOwned<<Self as Group>::Scalar>
|
||||||
+ Add<Self, Output = Self>
|
|
||||||
+ AddAssign<Self>
|
|
||||||
+ for<'a> AddAssign<&'a Self>
|
|
||||||
+ for<'a> Add<&'a Self, Output = Self>
|
|
||||||
{
|
{
|
||||||
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> {}
|
||||||
|
|||||||
Reference in New Issue
Block a user