Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dedupe (Working) #37

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
24 changes: 21 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! This library implements Spartan, a high-speed SNARK.
#![deny(
warnings,
// warnings,
// unused,
future_incompatible,
nonstandard_style,
Expand Down Expand Up @@ -88,8 +88,8 @@ impl<G: Group, S: RelaxedR1CSSNARKTrait<G> + UniformSNARKTrait<G> + Precommitted
}

/// Produces prover and verifier keys for the direct SNARK
pub fn setup_precommitted(circuit: C, n: usize) -> Result<(ProverKey<G, S>, VerifierKey<G, S>), SpartanError> {
let (pk, vk) = S::setup_precommitted(circuit, n)?;
pub fn setup_precommitted(circuit: C, n: usize, ck: CommitmentKey::<G>) -> Result<(ProverKey<G, S>, VerifierKey<G, S>), SpartanError> {
let (pk, vk) = S::setup_precommitted(circuit, n, ck)?;
Ok((ProverKey { pk }, VerifierKey { vk }))
}

Expand All @@ -105,11 +105,29 @@ impl<G: Group, S: RelaxedR1CSSNARKTrait<G> + UniformSNARKTrait<G> + Precommitted
})
}

/// Produces a proof of satisfiability of the provided circuit
pub fn prove_precommitted(pk: &ProverKey<G, S>, circuit: C, w_segments: Vec<Vec<G::Scalar>>, comm_w_vec: Vec<Commitment<G>> ) -> Result<Self, SpartanError> {
// prove the instance using Spartan
let snark = S::prove_precommitted(&pk.pk, circuit, w_segments, comm_w_vec)?;

Ok(SNARK {
snark,
_p: Default::default(),
_p2: Default::default(),
})
}

/// Verifies a proof of satisfiability
pub fn verify(&self, vk: &VerifierKey<G, S>, io: &[G::Scalar]) -> Result<(), SpartanError> {
// verify the snark using the constructed instance
self.snark.verify(&vk.vk, io)
}

/// Verifies a proof of satisfiability
pub fn verify_precommitted(&self, vk: &VerifierKey<G, S>, io: &[G::Scalar]) -> Result<(), SpartanError> {
// verify the snark using the constructed instance
self.snark.verify_precommitted(&vk.vk, io)
}
}

type CommitmentKey<G> = <<G as traits::Group>::CE as CommitmentEngineTrait<G>>::CommitmentKey;
Expand Down
31 changes: 25 additions & 6 deletions src/provider/hyrax_pc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::{
Commitment, CommitmentKey,
};
use core::ops::{Add, AddAssign, Mul, MulAssign};
use crate::provider::bn256_grumpkin::bn256;
use itertools::{
EitherOrBoth::{Both, Left, Right},
Itertools,
Expand All @@ -31,7 +32,8 @@ use std::marker::PhantomData;
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(bound = "")]
pub struct HyraxCommitmentKey<G: Group> {
ck: PedersenCommitmentKey<G>,
/// ck
pub ck: PedersenCommitmentKey<G>,
}

/// Structure that holds commitments
Expand Down Expand Up @@ -59,6 +61,16 @@ impl<G: Group> Default for HyraxCommitment<G> {
}
}

impl From<Vec<bn256::Affine>> for HyraxCommitment<bn256::Point> {
fn from(v: Vec<bn256::Affine>) -> Self {

HyraxCommitment {
comm: v.iter().map(|x| PedersenCommitment::from(*x)).collect_vec(),
is_default: false,
}
}
}

impl<G: Group> CommitmentTrait<G> for HyraxCommitment<G> {
type CompressedCommitment = HyraxCompressedCommitment<G>;

Expand All @@ -83,12 +95,13 @@ impl<G: Group> CommitmentTrait<G> for HyraxCommitment<G> {
}

impl<G: Group> MulAssign<G::Scalar> for HyraxCommitment<G> {
#[tracing::instrument(skip_all)]
fn mul_assign(&mut self, scalar: G::Scalar) {
let result = (self as &HyraxCommitment<G>)
.comm
.iter()
.par_iter()
.map(|c| c * &scalar)
.collect();
.collect::<Vec<_>>();
*self = HyraxCommitment {
comm: result,
is_default: self.is_default,
Expand All @@ -98,8 +111,10 @@ impl<G: Group> MulAssign<G::Scalar> for HyraxCommitment<G> {

impl<'a, 'b, G: Group> Mul<&'b G::Scalar> for &'a HyraxCommitment<G> {
type Output = HyraxCommitment<G>;

#[tracing::instrument(name="HyraxCommitment::mul(&scalar)", skip_all)]
fn mul(self, scalar: &'b G::Scalar) -> HyraxCommitment<G> {
let result = self.comm.iter().map(|c| c * scalar).collect();
let result = self.comm.par_iter().map(|c| c * scalar).collect::<Vec<_>>();
HyraxCommitment {
comm: result,
is_default: self.is_default,
Expand All @@ -110,8 +125,9 @@ impl<'a, 'b, G: Group> Mul<&'b G::Scalar> for &'a HyraxCommitment<G> {
impl<G: Group> Mul<G::Scalar> for HyraxCommitment<G> {
type Output = HyraxCommitment<G>;

#[tracing::instrument(name="HyraxCommitment::mul(scalar)", skip_all)]
fn mul(self, scalar: G::Scalar) -> HyraxCommitment<G> {
let result = self.comm.iter().map(|c| c * &scalar).collect();
let result = self.comm.par_iter().map(|c| c * &scalar).collect::<Vec<_>>();
HyraxCommitment {
comm: result,
is_default: self.is_default,
Expand All @@ -120,6 +136,7 @@ impl<G: Group> Mul<G::Scalar> for HyraxCommitment<G> {
}

impl<'b, G: Group> AddAssign<&'b HyraxCommitment<G>> for HyraxCommitment<G> {
#[tracing::instrument(skip_all)]
fn add_assign(&mut self, other: &'b HyraxCommitment<G>) {
if self.is_default {
*self = other.clone();
Expand All @@ -135,7 +152,7 @@ impl<'b, G: Group> AddAssign<&'b HyraxCommitment<G>> for HyraxCommitment<G> {
Left(a) => *a,
Right(b) => *b,
})
.collect();
.collect::<Vec<_>>();
*self = HyraxCommitment {
comm: result,
is_default: self.is_default,
Expand All @@ -146,6 +163,8 @@ impl<'b, G: Group> AddAssign<&'b HyraxCommitment<G>> for HyraxCommitment<G> {

impl<'a, 'b, G: Group> Add<&'b HyraxCommitment<G>> for &'a HyraxCommitment<G> {
type Output = HyraxCommitment<G>;

#[tracing::instrument(skip_all)]
fn add(self, other: &'b HyraxCommitment<G>) -> HyraxCommitment<G> {
if self.is_default {
other.clone()
Expand Down
36 changes: 35 additions & 1 deletion src/provider/pedersen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,38 @@ use core::{
};
use rayon::prelude::*;
use serde::{Deserialize, Serialize};
use super::bn256_grumpkin::bn256;

/// A type that holds commitment generators
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct CommitmentKey<G: Group> {
ck: Vec<G::PreprocessedGroupElement>,
/// Commitment key
pub ck: Vec<G::PreprocessedGroupElement>,
}

/// Generators ck for the bn256 curve
pub fn from_preprocessed_gens<SpartanAffine: halo2curves::CurveAffine>(generators: Vec<SpartanAffine>) -> CommitmentKey<bn256::Point>
where SpartanAffine: halo2curves::CurveAffine<Base = bn256::Base>,
{
let ck: Vec<<bn256::Point as Group>::PreprocessedGroupElement> = generators.into_iter().map(|g| {
let (x, y) = (*g.coordinates().unwrap().x(), *g.coordinates().unwrap().y());
(bn256::Affine {x: x, y: y}).into()
}).collect();

CommitmentKey {
ck,
}
}

/// Generators ck for the bn256 curve
pub fn from_gens_bn256(generators: Vec<bn256::Affine>) -> CommitmentKey<bn256::Point>
{
CommitmentKey {
ck: generators
}
}


/// A type that holds a commitment
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(bound = "")]
Expand Down Expand Up @@ -60,6 +85,15 @@ impl<G: Group> Default for Commitment<G> {
}
}

impl From<bn256::Affine> for Commitment<bn256::Point> {
fn from(v: bn256::Affine) -> Self {

Commitment {
comm: v.into(),
}
}
}

impl<G: Group> TranscriptReprTrait<G> for Commitment<G> {
fn to_transcript_bytes(&self) -> Vec<u8> {
let (x, y, is_infinity) = self.comm.to_coordinates();
Expand Down
52 changes: 52 additions & 0 deletions src/r1cs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -785,3 +785,55 @@ impl<G: Group> TranscriptReprTrait<G> for RelaxedR1CSInstance<G> {
.concat()
}
}

// Segmented structs for Precommitted version

/// A type that holds a witness for a given R1CS instance
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct PrecommittedR1CSWitness<G: Group> {
pub(crate) W: Vec<Vec<G::Scalar>>,
}

/// A type that holds an R1CS instance
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(bound = "")]
pub struct PrecommittedR1CSInstance<G: Group> {
pub(crate) comm_W: Vec<Commitment<G>>,
pub(crate) X: Vec<G::Scalar>,
}


impl<G: Group> PrecommittedR1CSWitness<G> {
/// A method to create a witness object using a vector of scalars
pub fn new(_S: &R1CSShape<G>, W: Vec<Vec<G::Scalar>>) -> Result<PrecommittedR1CSWitness<G>, SpartanError> {
let w = PrecommittedR1CSWitness { W: W };
Ok(w)
}
}

impl<G: Group> PrecommittedR1CSInstance<G> {
/// A method to create an instance object using consitituent elements
pub fn new(
S: &R1CSShape<G>,
comm_W: Vec<Commitment<G>>,
X: &[G::Scalar],
) -> Result<PrecommittedR1CSInstance<G>, SpartanError> {
if S.num_io != X.len() {
Err(SpartanError::InvalidInputLength)
} else {
Ok(PrecommittedR1CSInstance{
comm_W: comm_W,
X: X.to_owned(),
})
}
}
}

impl<G: Group> TranscriptReprTrait<G> for PrecommittedR1CSInstance<G> {
fn to_transcript_bytes(&self) -> Vec<u8> {
self.comm_W.iter()
.flat_map(|elem| elem.to_transcript_bytes())
.chain(self.X.as_slice().to_transcript_bytes())
.collect::<Vec<_>>()
}
}
36 changes: 27 additions & 9 deletions src/spartan/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,17 @@ impl<G: Group> PolyEvalWitness<G> {
PolyEvalWitness { p }
}

#[tracing::instrument(skip_all)]
fn batch(p_vec: &[&Vec<G::Scalar>], s: &G::Scalar) -> PolyEvalWitness<G> {
let powers_of_s = powers::<G>(s, p_vec.len());
let mut p = vec![G::Scalar::ZERO; p_vec[0].len()];
for i in 0..p_vec.len() {
for (j, item) in p.iter_mut().enumerate().take(p_vec[i].len()) {
*item += p_vec[i][j] * powers_of_s[i]
let mut p: Vec<<G as Group>::Scalar> = vec![G::Scalar::ZERO; p_vec[0].len()];
p.par_iter_mut().enumerate().for_each(|(j, item)| {
for i in 0..p_vec.len() {
if j < p_vec[i].len() {
*item += p_vec[i][j] * powers_of_s[i];
}
}
}
});
PolyEvalWitness { p }
}
}
Expand Down Expand Up @@ -106,28 +109,43 @@ impl<G: Group> PolyEvalInstance<G> {
}
}

#[tracing::instrument(skip_all)]
fn batch(
c_vec: &[Commitment<G>],
x: &[G::Scalar],
e_vec: &[G::Scalar],
s: &G::Scalar,
) -> PolyEvalInstance<G> {
let span = tracing::span!(tracing::Level::INFO, "powers_of_s_calculation");
let _guard = span.enter();
let powers_of_s = powers::<G>(s, c_vec.len());
drop(_guard);
println!("c_vec len {:?}", c_vec.len());
let e = e_vec
.iter()
.zip(powers_of_s.iter())
.map(|(e, p)| *e * p)
.sum();
let span_compute_RLC = tracing::span!(tracing::Level::INFO, "compute_RLC");
let _guard_compute_RLC = span_compute_RLC.enter();

let c = c_vec
.iter()
.zip(powers_of_s.iter())
.par_iter()
.zip(powers_of_s.par_iter())
.map(|(c, p)| c.clone() * *p)
.fold(Commitment::<G>::default(), |acc, item| acc + item);
.reduce_with(|acc, item| acc + item)
.unwrap_or_else(Commitment::<G>::default);
// let c = G::vartime_multiscalar_mul(&powers_of_s, c_vec.iter().map(|c| c.preprocessed()).collect());
// use crate::traits::commitment::CommitmentTrait;
// let raw_gs: Vec<G> = c_vec.iter().map(|c| c.raw()).collect();
// let pre_processed = c_vec.iter().map(|c| c.clone().raw().preprocessed()).collect();
// let c = G::vartime_multiscalar_mul(&powers_of_s, &pre_processed);
drop(_guard_compute_RLC);

PolyEvalInstance {
c,
x: x.to_vec(),
e,
e
}
}
}
11 changes: 10 additions & 1 deletion src/spartan/polys/eq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
use ff::PrimeField;
use rayon::prelude::{IndexedParallelIterator, IntoParallelRefMutIterator, ParallelIterator};

use crate::spartan::math::Math;

/// Represents the multilinear extension polynomial (MLE) of the equality polynomial $eq(x,e)$, denoted as $\tilde{eq}(x, e)$.
///
/// The polynomial is defined by the formula:
Expand Down Expand Up @@ -69,8 +71,15 @@ impl<Scalar: PrimeField> EqPolynomial<Scalar> {
}

/// Computes the lengths of the left and right halves of the `EqPolynomial`'s vector `r`.
/// Note: Using Jolt implementation with matrix_aspect_ratio = 1
pub fn compute_factored_lens(ell: usize) -> (usize, usize) {
(ell / 2, ell - ell / 2)
let mut row_size = (ell/ 2).pow2();
row_size = row_size.next_power_of_two();

let right_num_vars = std::cmp::min(row_size.log_2(), ell - 1);
let left_num_vars = ell - right_num_vars;

(left_num_vars, right_num_vars)
}

/// Computes the left and right halves of the `EqPolynomial`.
Expand Down
13 changes: 13 additions & 0 deletions src/spartan/polys/multilinear.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,19 @@ impl<Scalar: PrimeField> MultilinearPolynomial<Scalar> {
.sum()
}

/// Evaluates |Zs| different polynomials at a single point r.
pub fn batch_evaluate(Zs: &[Vec<Scalar>], r: &[Scalar]) -> Vec<Scalar> {
let chi = EqPolynomial::new(r.to_vec()).evals();

let results: Vec<Scalar> = Zs.par_iter()
.map(|Z| {
chi.par_iter().zip(Z.into_par_iter())
.map(|(a, b)| *a * b)
.sum()
}).collect();
results
}

/// Evaluates polynomial given lagrange basis
#[tracing::instrument(skip_all, name = "MultilinearPolynomial::evaluate_with_chi")]
pub fn evaluate_with_chi(&self, chis: &[Scalar]) -> Scalar {
Expand Down
Loading