Skip to content

Commit

Permalink
Move to bellpepper (#3)
Browse files Browse the repository at this point in the history
* cosmetic change from bellperson to bellpepper_core

* add ec_gpu_gen for DensityTracking in solver.rs

* changed module name to bellpepper

* added macro for SpartanShape impl

* updated solver.rs, removed DensityTracker

* copied over test_shape_cs from nova

* cargo fmt

* Update Cargo.toml dependencies

* Update Cargo.toml

---------

Co-authored-by: Srinath Setty <[email protected]>
  • Loading branch information
arasuarun and srinathsetty authored Sep 29, 2023
1 parent b813727 commit 880541e
Show file tree
Hide file tree
Showing 7 changed files with 442 additions and 112 deletions.
5 changes: 1 addition & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ license-file = "LICENSE"
keywords = ["zkSNARKs", "cryptography", "proofs"]

[dependencies]
bellperson = { version = "0.25", default-features = false }
bellpepper-core = "0.2.1"
ff = { version = "0.13.0", features = ["derive"] }
digest = "0.10"
sha3 = "0.10"
Expand All @@ -21,7 +21,6 @@ rand_chacha = "0.3"
itertools = "0.11"
subtle = "2.5"
pasta_curves = { version = "0.5", features = ["repr-c", "serde"] }
neptune = { version = "10.0.0", default-features = false }
generic-array = "0.14"
num-bigint = { version = "0.4", features = ["serde", "rand"] }
num-traits = "0.2"
Expand Down Expand Up @@ -54,6 +53,4 @@ proptest = "1.2.0"
default = []
# Compiles in portable mode, w/o ISA extensions => binary can be executed on all systems.
portable = ["pasta-msm/portable"]
cuda = ["neptune/cuda", "neptune/pasta", "neptune/arity24"]
opencl = ["neptune/opencl", "neptune/pasta", "neptune/arity24"]
flamegraph = ["pprof/flamegraph", "pprof/criterion"]
5 changes: 3 additions & 2 deletions src/bellperson/mod.rs → src/bellpepper/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@
pub mod r1cs;
pub mod shape_cs;
pub mod solver;
pub mod test_shape_cs;

#[cfg(test)]
mod tests {
use crate::{
bellperson::{
bellpepper::{
r1cs::{SpartanShape, SpartanWitness},
shape_cs::ShapeCS,
solver::SatisfyingAssignment,
},
traits::Group,
};
use bellperson::{gadgets::num::AllocatedNum, ConstraintSystem, SynthesisError};
use bellpepper_core::{num::AllocatedNum, ConstraintSystem, SynthesisError};
use ff::PrimeField;

fn synthesize_alloc_bit<Fr: PrimeField, CS: ConstraintSystem<Fr>>(
Expand Down
85 changes: 46 additions & 39 deletions src/bellperson/r1cs.rs → src/bellpepper/r1cs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

#![allow(non_snake_case)]

use super::{shape_cs::ShapeCS, solver::SatisfyingAssignment};
use super::{shape_cs::ShapeCS, solver::SatisfyingAssignment, test_shape_cs::TestShapeCS};
use crate::{
errors::SpartanError,
r1cs::{R1CSInstance, R1CSShape, R1CSWitness, R1CS},
traits::Group,
CommitmentKey,
};
use bellperson::{Index, LinearCombination};
use bellpepper_core::{Index, LinearCombination};
use ff::PrimeField;

/// `SpartanWitness` provide a method for acquiring an `R1CSInstance` and `R1CSWitness` from implementers.
Expand Down Expand Up @@ -48,46 +48,53 @@ where
}
}

impl<G: Group> SpartanShape<G> for ShapeCS<G>
where
G::Scalar: PrimeField,
{
fn r1cs_shape(&self) -> (R1CSShape<G>, CommitmentKey<G>) {
let mut A: Vec<(usize, usize, G::Scalar)> = Vec::new();
let mut B: Vec<(usize, usize, G::Scalar)> = Vec::new();
let mut C: Vec<(usize, usize, G::Scalar)> = Vec::new();

let mut num_cons_added = 0;
let mut X = (&mut A, &mut B, &mut C, &mut num_cons_added);

let num_inputs = self.num_inputs();
let num_constraints = self.num_constraints();
let num_vars = self.num_aux();

for constraint in self.constraints.iter() {
add_constraint(
&mut X,
num_vars,
&constraint.0,
&constraint.1,
&constraint.2,
);
macro_rules! impl_spartan_shape {
( $name:ident) => {
impl<G: Group> SpartanShape<G> for $name<G>
where
G::Scalar: PrimeField,
{
fn r1cs_shape(&self) -> (R1CSShape<G>, CommitmentKey<G>) {
let mut A: Vec<(usize, usize, G::Scalar)> = Vec::new();
let mut B: Vec<(usize, usize, G::Scalar)> = Vec::new();
let mut C: Vec<(usize, usize, G::Scalar)> = Vec::new();

let mut num_cons_added = 0;
let mut X = (&mut A, &mut B, &mut C, &mut num_cons_added);

let num_inputs = self.num_inputs();
let num_constraints = self.num_constraints();
let num_vars = self.num_aux();

for constraint in self.constraints.iter() {
add_constraint(
&mut X,
num_vars,
&constraint.0,
&constraint.1,
&constraint.2,
);
}

assert_eq!(num_cons_added, num_constraints);

let S: R1CSShape<G> = {
// Don't count One as an input for shape's purposes.
let res = R1CSShape::new(num_constraints, num_vars, num_inputs - 1, &A, &B, &C);
res.unwrap()
};

let ck = R1CS::<G>::commitment_key(&S);

(S, ck)
}
}

assert_eq!(num_cons_added, num_constraints);

let S: R1CSShape<G> = {
// Don't count One as an input for shape's purposes.
let res = R1CSShape::new(num_constraints, num_vars, num_inputs - 1, &A, &B, &C);
res.unwrap()
};

let ck = R1CS::<G>::commitment_key(&S);

(S, ck)
}
};
}

impl_spartan_shape!(ShapeCS);
impl_spartan_shape!(TestShapeCS);

fn add_constraint<S: PrimeField>(
X: &mut (
&mut Vec<(usize, usize, S)>,
Expand Down
2 changes: 1 addition & 1 deletion src/bellperson/shape_cs.rs → src/bellpepper/shape_cs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{
};

use crate::traits::Group;
use bellperson::{ConstraintSystem, Index, LinearCombination, SynthesisError, Variable};
use bellpepper_core::{ConstraintSystem, Index, LinearCombination, SynthesisError, Variable};
use core::fmt::Write;
use ff::{Field, PrimeField};

Expand Down
122 changes: 60 additions & 62 deletions src/bellperson/solver.rs → src/bellpepper/solver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,13 @@
use crate::traits::Group;
use ff::{Field, PrimeField};

use bellperson::{
multiexp::DensityTracker, ConstraintSystem, Index, LinearCombination, SynthesisError, Variable,
};
use bellpepper_core::{ConstraintSystem, Index, LinearCombination, SynthesisError, Variable};

/// A `ConstraintSystem` which calculates witness values for a concrete instance of an R1CS circuit.
#[derive(PartialEq)]
pub struct SatisfyingAssignment<G: Group>
where
G::Scalar: PrimeField,
{
// Density of queries
a_aux_density: DensityTracker,
b_input_density: DensityTracker,
b_aux_density: DensityTracker,

// Evaluations of A, B, C polynomials
a: Vec<G::Scalar>,
b: Vec<G::Scalar>,
c: Vec<G::Scalar>,

// Assignments of variables
pub(crate) input_assignment: Vec<G::Scalar>,
pub(crate) aux_assignment: Vec<G::Scalar>,
Expand All @@ -36,39 +23,18 @@ where
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt
.debug_struct("SatisfyingAssignment")
.field("a_aux_density", &self.a_aux_density)
.field("b_input_density", &self.b_input_density)
.field("b_aux_density", &self.b_aux_density)
.field(
"a",
&self
.a
.iter()
.map(|v| format!("Fr({v:?})"))
.collect::<Vec<_>>(),
)
.field(
"b",
&self
.b
.iter()
.map(|v| format!("Fr({v:?})"))
.collect::<Vec<_>>(),
)
.field(
"c",
&self
.c
.iter()
.map(|v| format!("Fr({v:?})"))
.collect::<Vec<_>>(),
)
.field("input_assignment", &self.input_assignment)
.field("aux_assignment", &self.aux_assignment)
.finish()
}
}

impl<G: Group> PartialEq for SatisfyingAssignment<G> {
fn eq(&self, other: &SatisfyingAssignment<G>) -> bool {
self.input_assignment == other.input_assignment && self.aux_assignment == other.aux_assignment
}
}

impl<G: Group> ConstraintSystem<G::Scalar> for SatisfyingAssignment<G>
where
G::Scalar: PrimeField,
Expand All @@ -77,16 +43,8 @@ where

fn new() -> Self {
let input_assignment = vec![G::Scalar::ONE];
let mut d = DensityTracker::new();
d.add_element();

Self {
a_aux_density: DensityTracker::new(),
b_input_density: d,
b_aux_density: DensityTracker::new(),
a: vec![],
b: vec![],
c: vec![],
input_assignment,
aux_assignment: vec![],
}
Expand All @@ -99,8 +57,6 @@ where
AR: Into<String>,
{
self.aux_assignment.push(f()?);
self.a_aux_density.add_element();
self.b_aux_density.add_element();

Ok(Variable(Index::Aux(self.aux_assignment.len() - 1)))
}
Expand All @@ -112,7 +68,6 @@ where
AR: Into<String>,
{
self.input_assignment.push(f()?);
self.b_input_density.add_element();

Ok(Variable(Index::Input(self.input_assignment.len() - 1)))
}
Expand Down Expand Up @@ -148,18 +103,61 @@ where
true
}

fn extend(&mut self, other: Self) {
self.a_aux_density.extend(other.a_aux_density, false);
self.b_input_density.extend(other.b_input_density, true);
self.b_aux_density.extend(other.b_aux_density, false);

self.a.extend(other.a);
self.b.extend(other.b);
self.c.extend(other.c);

fn extend(&mut self, other: &Self) {
self.input_assignment
// Skip first input, which must have been a temporarily allocated one variable.
.extend(&other.input_assignment[1..]);
self.aux_assignment.extend(other.aux_assignment);
self.aux_assignment.extend(other.aux_assignment.clone());
}

fn is_witness_generator(&self) -> bool {
true
}

fn extend_inputs(&mut self, new_inputs: &[G::Scalar]) {
self.input_assignment.extend(new_inputs);
}

fn extend_aux(&mut self, new_aux: &[G::Scalar]) {
self.aux_assignment.extend(new_aux);
}

fn allocate_empty(
&mut self,
aux_n: usize,
inputs_n: usize,
) -> (&mut [G::Scalar], &mut [G::Scalar]) {
let allocated_aux = {
let i = self.aux_assignment.len();
self.aux_assignment.resize(aux_n + i, G::Scalar::ZERO);
&mut self.aux_assignment[i..]
};

let allocated_inputs = {
let i = self.input_assignment.len();
self.input_assignment.resize(inputs_n + i, G::Scalar::ZERO);
&mut self.input_assignment[i..]
};

(allocated_aux, allocated_inputs)
}

fn inputs_slice(&self) -> &[G::Scalar] {
&self.input_assignment
}

fn aux_slice(&self) -> &[G::Scalar] {
&self.aux_assignment
}
}

#[allow(dead_code)]
impl<G: Group> SatisfyingAssignment<G> {
pub fn scalar_inputs(&self) -> Vec<G::Scalar> {
self.input_assignment.clone()
}

pub fn scalar_aux(&self) -> Vec<G::Scalar> {
self.aux_assignment.clone()
}
}
Loading

0 comments on commit 880541e

Please sign in to comment.