Skip to content

Commit

Permalink
Refactor traits that allows implementing different engines for the sa…
Browse files Browse the repository at this point in the history
…me curve cycle (microsoft#263)

* rename Group to Engine

* port tests

* checkpoint

* checkpoint

* compiles

* update benchmarks and tests to use Engine

* rename GroupExt to DlogGroup

* move get_curve_params to Group and rename

* fix doc test; cargo fmt

* inline single trait requirements; fix comments

* cut comment
  • Loading branch information
srinathsetty authored and huitseeker committed Nov 22, 2023
1 parent 0868e27 commit a1c5d66
Show file tree
Hide file tree
Showing 46 changed files with 2,534 additions and 2,856 deletions.
65 changes: 30 additions & 35 deletions benches/compressed-snark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,28 @@ use core::marker::PhantomData;
use criterion::*;
use ff::PrimeField;
use nova_snark::{
provider::pasta::{PallasEngine, VestaEngine},
traits::{
circuit::{StepCircuit, TrivialCircuit},
snark::RelaxedR1CSSNARKTrait,
Group,
Engine,
},
CompressedSNARK, PublicParams, RecursiveSNARK,
};
use std::time::Duration;

type G1 = pasta_curves::pallas::Point;
type G2 = pasta_curves::vesta::Point;
type EE1 = nova_snark::provider::ipa_pc::EvaluationEngine<G1>;
type EE2 = nova_snark::provider::ipa_pc::EvaluationEngine<G2>;
type E1 = PallasEngine;
type E2 = VestaEngine;
type EE1 = nova_snark::provider::ipa_pc::EvaluationEngine<E1>;
type EE2 = nova_snark::provider::ipa_pc::EvaluationEngine<E2>;
// SNARKs without computational commitments
type S1 = nova_snark::spartan::snark::RelaxedR1CSSNARK<G1, EE1>;
type S2 = nova_snark::spartan::snark::RelaxedR1CSSNARK<G2, EE2>;
type S1 = nova_snark::spartan::snark::RelaxedR1CSSNARK<E1, EE1>;
type S2 = nova_snark::spartan::snark::RelaxedR1CSSNARK<E2, EE2>;
// SNARKs with computational commitments
type SS1 = nova_snark::spartan::ppsnark::RelaxedR1CSSNARK<G1, EE1>;
type SS2 = nova_snark::spartan::ppsnark::RelaxedR1CSSNARK<G2, EE2>;
type C1 = NonTrivialCircuit<<G1 as Group>::Scalar>;
type C2 = TrivialCircuit<<G2 as Group>::Scalar>;
type SS1 = nova_snark::spartan::ppsnark::RelaxedR1CSSNARK<E1, EE1>;
type SS2 = nova_snark::spartan::ppsnark::RelaxedR1CSSNARK<E2, EE2>;
type C1 = NonTrivialCircuit<<E1 as Engine>::Scalar>;
type C2 = TrivialCircuit<<E2 as Engine>::Scalar>;

// To run these benchmarks, first download `criterion` with `cargo install cargo install cargo-criterion`.
// Then `cargo criterion --bench compressed-snark`. The results are located in `target/criterion/data/<name-of-benchmark>`.
Expand Down Expand Up @@ -66,7 +67,7 @@ fn bench_compressed_snark(c: &mut Criterion) {
let c_secondary = TrivialCircuit::default();

// Produce public parameters
let pp = PublicParams::<G1, G2, C1, C2>::setup(
let pp = PublicParams::<E1, E2, C1, C2>::setup(
&c_primary,
&c_secondary,
&*S1::ck_floor(),
Expand All @@ -78,12 +79,12 @@ fn bench_compressed_snark(c: &mut Criterion) {

// produce a recursive SNARK
let num_steps = 3;
let mut recursive_snark: RecursiveSNARK<G1, G2, C1, C2> = RecursiveSNARK::new(
let mut recursive_snark: RecursiveSNARK<E1, E2, C1, C2> = RecursiveSNARK::new(
&pp,
&c_primary,
&c_secondary,
&[<G1 as Group>::Scalar::from(2u64)],
&[<G2 as Group>::Scalar::from(2u64)],
&[<E1 as Engine>::Scalar::from(2u64)],
&[<E2 as Engine>::Scalar::from(2u64)],
)
.unwrap();

Expand All @@ -95,8 +96,8 @@ fn bench_compressed_snark(c: &mut Criterion) {
let res = recursive_snark.verify(
&pp,
i + 1,
&[<G1 as Group>::Scalar::from(2u64)],
&[<G2 as Group>::Scalar::from(2u64)],
&[<E1 as Engine>::Scalar::from(2u64)],
&[<E2 as Engine>::Scalar::from(2u64)],
);
assert!(res.is_ok());
}
Expand All @@ -123,8 +124,8 @@ fn bench_compressed_snark(c: &mut Criterion) {
.verify(
black_box(&vk),
black_box(num_steps),
black_box(&[<G1 as Group>::Scalar::from(2u64)]),
black_box(&[<G2 as Group>::Scalar::from(2u64)]),
black_box(&[<E1 as Engine>::Scalar::from(2u64)]),
black_box(&[<E2 as Engine>::Scalar::from(2u64)]),
)
.is_ok());
})
Expand Down Expand Up @@ -153,7 +154,7 @@ fn bench_compressed_snark_with_computational_commitments(c: &mut Criterion) {
let c_secondary = TrivialCircuit::default();

// Produce public parameters
let pp = PublicParams::<G1, G2, C1, C2>::setup(
let pp = PublicParams::<E1, E2, C1, C2>::setup(
&c_primary,
&c_secondary,
&*SS1::ck_floor(),
Expand All @@ -164,12 +165,12 @@ fn bench_compressed_snark_with_computational_commitments(c: &mut Criterion) {

// produce a recursive SNARK
let num_steps = 3;
let mut recursive_snark: RecursiveSNARK<G1, G2, C1, C2> = RecursiveSNARK::new(
let mut recursive_snark: RecursiveSNARK<E1, E2, C1, C2> = RecursiveSNARK::new(
&pp,
&c_primary,
&c_secondary,
&[<G1 as Group>::Scalar::from(2u64)],
&[<G2 as Group>::Scalar::from(2u64)],
&[<E1 as Engine>::Scalar::from(2u64)],
&[<E2 as Engine>::Scalar::from(2u64)],
)
.unwrap();

Expand All @@ -181,8 +182,8 @@ fn bench_compressed_snark_with_computational_commitments(c: &mut Criterion) {
let res = recursive_snark.verify(
&pp,
i + 1,
&[<G1 as Group>::Scalar::from(2u64)],
&[<G2 as Group>::Scalar::from(2u64)],
&[<E1 as Engine>::Scalar::from(2u64)],
&[<E2 as Engine>::Scalar::from(2u64)],
);
assert!(res.is_ok());
}
Expand All @@ -209,8 +210,8 @@ fn bench_compressed_snark_with_computational_commitments(c: &mut Criterion) {
.verify(
black_box(&vk),
black_box(num_steps),
black_box(&[<G1 as Group>::Scalar::from(2u64)]),
black_box(&[<G2 as Group>::Scalar::from(2u64)]),
black_box(&[<E1 as Engine>::Scalar::from(2u64)]),
black_box(&[<E2 as Engine>::Scalar::from(2u64)]),
)
.is_ok());
})
Expand All @@ -226,21 +227,15 @@ struct NonTrivialCircuit<F: PrimeField> {
_p: PhantomData<F>,
}

impl<F> NonTrivialCircuit<F>
where
F: PrimeField,
{
impl<F: PrimeField> NonTrivialCircuit<F> {
pub fn new(num_cons: usize) -> Self {
Self {
num_cons,
_p: PhantomData,
}
}
}
impl<F> StepCircuit<F> for NonTrivialCircuit<F>
where
F: PrimeField,
{
impl<F: PrimeField> StepCircuit<F> for NonTrivialCircuit<F> {
fn arity(&self) -> usize {
1
}
Expand Down
23 changes: 9 additions & 14 deletions benches/compute-digest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@ use bellpepper_core::{num::AllocatedNum, ConstraintSystem, SynthesisError};
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use ff::PrimeField;
use nova_snark::{
provider::pasta::{PallasEngine, VestaEngine},
traits::{
circuit::{StepCircuit, TrivialCircuit},
snark::default_ck_hint,
Group,
Engine,
},
PublicParams,
};

type G1 = pasta_curves::pallas::Point;
type G2 = pasta_curves::vesta::Point;
type C1 = NonTrivialCircuit<<G1 as Group>::Scalar>;
type C2 = TrivialCircuit<<G2 as Group>::Scalar>;
type E1 = PallasEngine;
type E2 = VestaEngine;
type C1 = NonTrivialCircuit<<E1 as Engine>::Scalar>;
type C2 = TrivialCircuit<<E2 as Engine>::Scalar>;

criterion_group! {
name = compute_digest;
Expand All @@ -28,7 +29,7 @@ criterion_main!(compute_digest);
fn bench_compute_digest(c: &mut Criterion) {
c.bench_function("compute_digest", |b| {
b.iter(|| {
PublicParams::<G1, G2, C1, C2>::setup(
PublicParams::<E1, E2, C1, C2>::setup(
black_box(&C1::new(10)),
black_box(&C2::default()),
black_box(&*default_ck_hint()),
Expand All @@ -44,21 +45,15 @@ struct NonTrivialCircuit<F: PrimeField> {
_p: PhantomData<F>,
}

impl<F> NonTrivialCircuit<F>
where
F: PrimeField,
{
impl<F: PrimeField> NonTrivialCircuit<F> {
pub fn new(num_cons: usize) -> Self {
Self {
num_cons,
_p: PhantomData,
}
}
}
impl<F> StepCircuit<F> for NonTrivialCircuit<F>
where
F: PrimeField,
{
impl<F: PrimeField> StepCircuit<F> for NonTrivialCircuit<F> {
fn arity(&self) -> usize {
1
}
Expand Down
74 changes: 39 additions & 35 deletions benches/recursive-snark-supernova.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,17 @@ use core::marker::PhantomData;
use criterion::*;
use ff::PrimeField;
use nova_snark::{
provider::pasta::{PallasEngine, VestaEngine},
supernova::NonUniformCircuit,
supernova::{PublicParams, RecursiveSNARK},
traits::{
circuit_supernova::{StepCircuit, TrivialTestCircuit},
snark::default_ck_hint,
Group,
Engine,
},
};
use std::time::Duration;

type G1 = pasta_curves::pallas::Point;
type G2 = pasta_curves::vesta::Point;

// To run these benchmarks, first download `criterion` with `cargo install cargo-criterion`.
// Then `cargo criterion --bench recursive-snark-supernova`. The results are located in `target/criterion/data/<name-of-benchmark>`.
// For flamegraphs, run `cargo criterion --bench recursive-snark-supernova --features flamegraph -- --profile-time <secs>`.
Expand All @@ -40,22 +38,22 @@ cfg_if::cfg_if! {

criterion_main!(recursive_snark_supernova);

struct NonUniformBench<G1, G2, S>
struct NonUniformBench<E1, E2, S>
where
G1: Group<Base = <G2 as Group>::Scalar>,
G2: Group<Base = <G1 as Group>::Scalar>,
S: StepCircuit<G2::Scalar> + Default,
E1: Engine<Base = <E2 as Engine>::Scalar>,
E2: Engine<Base = <E1 as Engine>::Scalar>,
S: StepCircuit<E2::Scalar> + Default,
{
num_circuits: usize,
num_cons: usize,
_p: PhantomData<(G1, G2, S)>,
_p: PhantomData<(E1, E2, S)>,
}

impl<G1, G2, S> NonUniformBench<G1, G2, S>
impl<E1, E2, S> NonUniformBench<E1, E2, S>
where
G1: Group<Base = <G2 as Group>::Scalar>,
G2: Group<Base = <G1 as Group>::Scalar>,
S: StepCircuit<G2::Scalar> + Default,
E1: Engine<Base = <E2 as Engine>::Scalar>,
E2: Engine<Base = <E1 as Engine>::Scalar>,
S: StepCircuit<E2::Scalar> + Default,
{
fn new(num_circuits: usize, num_cons: usize) -> Self {
Self {
Expand All @@ -66,25 +64,25 @@ where
}
}

impl<G1, G2, S>
NonUniformCircuit<G1, G2, NonTrivialTestCircuit<G1::Scalar>, TrivialTestCircuit<G2::Scalar>>
for NonUniformBench<G1, G2, S>
impl<E1, E2, S>
NonUniformCircuit<E1, E2, NonTrivialTestCircuit<E1::Scalar>, TrivialTestCircuit<E2::Scalar>>
for NonUniformBench<E1, E2, S>
where
G1: Group<Base = <G2 as Group>::Scalar>,
G2: Group<Base = <G1 as Group>::Scalar>,
S: StepCircuit<G2::Scalar> + Default,
E1: Engine<Base = <E2 as Engine>::Scalar>,
E2: Engine<Base = <E1 as Engine>::Scalar>,
S: StepCircuit<E2::Scalar> + Default,
{
fn num_circuits(&self) -> usize {
self.num_circuits
}

fn primary_circuit(&self, circuit_index: usize) -> NonTrivialTestCircuit<G1::Scalar> {
fn primary_circuit(&self, circuit_index: usize) -> NonTrivialTestCircuit<E1::Scalar> {
assert!(circuit_index < self.num_circuits);

NonTrivialTestCircuit::new(self.num_cons)
}

fn secondary_circuit(&self) -> TrivialTestCircuit<G2::Scalar> {
fn secondary_circuit(&self) -> TrivialTestCircuit<E2::Scalar> {
Default::default()
}
}
Expand All @@ -103,18 +101,21 @@ fn bench_one_augmented_circuit_recursive_snark(c: &mut Criterion) {
));
group.sample_size(10);

let bench: NonUniformBench<G1, G2, TrivialTestCircuit<<G2 as Group>::Scalar>> =
NonUniformBench::new(1, num_cons);
let bench = NonUniformBench::<
PallasEngine,
VestaEngine,
TrivialTestCircuit<<VestaEngine as Engine>::Scalar>,
>::new(1, num_cons);
let pp = PublicParams::setup(&bench, &*default_ck_hint(), &*default_ck_hint());

// Bench time to produce a recursive SNARK;
// we execute a certain number of warm-up steps since executing
// the first step is cheaper than other steps owing to the presence of
// a lot of zeros in the satisfying assignment
let num_warmup_steps = 10;
let z0_primary = vec![<G1 as Group>::Scalar::from(2u64)];
let z0_secondary = vec![<G2 as Group>::Scalar::from(2u64)];
let mut recursive_snark_option: Option<RecursiveSNARK<G1, G2>> = None;
let z0_primary = vec![<PallasEngine as Engine>::Scalar::from(2u64)];
let z0_secondary = vec![<VestaEngine as Engine>::Scalar::from(2u64)];
let mut recursive_snark_option: Option<RecursiveSNARK<PallasEngine, VestaEngine>> = None;

for _ in 0..num_warmup_steps {
let mut recursive_snark = recursive_snark_option.unwrap_or_else(|| {
Expand Down Expand Up @@ -167,8 +168,8 @@ fn bench_one_augmented_circuit_recursive_snark(c: &mut Criterion) {
.verify(
black_box(&pp),
black_box(0),
black_box(&[<G1 as Group>::Scalar::from(2u64)]),
black_box(&[<G2 as Group>::Scalar::from(2u64)]),
black_box(&[<PallasEngine as Engine>::Scalar::from(2u64)]),
black_box(&[<VestaEngine as Engine>::Scalar::from(2u64)]),
)
.is_ok());
});
Expand All @@ -191,18 +192,21 @@ fn bench_two_augmented_circuit_recursive_snark(c: &mut Criterion) {
));
group.sample_size(10);

let bench: NonUniformBench<G1, G2, TrivialTestCircuit<<G2 as Group>::Scalar>> =
NonUniformBench::new(2, num_cons);
let bench: NonUniformBench<
PallasEngine,
VestaEngine,
TrivialTestCircuit<<VestaEngine as Engine>::Scalar>,
> = NonUniformBench::new(2, num_cons);
let pp = PublicParams::setup(&bench, &*default_ck_hint(), &*default_ck_hint());

// Bench time to produce a recursive SNARK;
// we execute a certain number of warm-up steps since executing
// the first step is cheaper than other steps owing to the presence of
// a lot of zeros in the satisfying assignment
let num_warmup_steps = 10;
let z0_primary = vec![<G1 as Group>::Scalar::from(2u64)];
let z0_secondary = vec![<G2 as Group>::Scalar::from(2u64)];
let mut recursive_snark_option: Option<RecursiveSNARK<G1, G2>> = None;
let z0_primary = vec![<PallasEngine as Engine>::Scalar::from(2u64)];
let z0_secondary = vec![<VestaEngine as Engine>::Scalar::from(2u64)];
let mut recursive_snark_option: Option<RecursiveSNARK<PallasEngine, VestaEngine>> = None;
let mut selected_augmented_circuit = 0;

for _ in 0..num_warmup_steps {
Expand Down Expand Up @@ -273,8 +277,8 @@ fn bench_two_augmented_circuit_recursive_snark(c: &mut Criterion) {
.verify(
black_box(&pp),
black_box(0),
black_box(&[<G1 as Group>::Scalar::from(2u64)]),
black_box(&[<G2 as Group>::Scalar::from(2u64)]),
black_box(&[<PallasEngine as Engine>::Scalar::from(2u64)]),
black_box(&[<VestaEngine as Engine>::Scalar::from(2u64)]),
)
.is_ok());
});
Expand Down
Loading

0 comments on commit a1c5d66

Please sign in to comment.