Improve performance of recursive (#163)

* Improve performance of recursive

* Fix the test after rebase

* Fix CI/CD warnings

* Update benchmark to work with new interface of RecursiveSNARK

* Fix example to make sure step 1 is correct

* refactor: Removes unneeded pass-by value in verification

- Update function arguments to use borrowing instead of passing ownership

* Resolve the conflict with upstream branch

* refactor: Avoid extra input cloning in RecursiveSNARK::new

* Update criterion to 0.5.1 to prevent the panic with its plot

* Fix benchmark issue with new recursive_snark instance

* Fix CI/CD warning with

* refactor: Make mutation easier to observe

- Utilize mutable references to Points for better memory management

* chore: Downgrade clippy dependency for compatibility

---------

Co-authored-by: François Garillot <francois@garillot.net>
This commit is contained in:
Chiro Hiro
2023-06-20 02:52:57 +07:00
committed by GitHub
parent 031738de51
commit af886d6ce7
7 changed files with 372 additions and 351 deletions

View File

@@ -43,46 +43,46 @@ fn bench_compressed_snark(c: &mut Criterion) {
let mut group = c.benchmark_group(format!("CompressedSNARK-StepCircuitSize-{num_cons}"));
group.sample_size(num_samples);
let c_primary = NonTrivialTestCircuit::new(num_cons);
let c_secondary = TrivialTestCircuit::default();
// Produce public parameters
let pp = PublicParams::<G1, G2, C1, C2>::setup(
NonTrivialTestCircuit::new(num_cons),
TrivialTestCircuit::default(),
);
let pp = PublicParams::<G1, G2, C1, C2>::setup(c_primary.clone(), c_secondary.clone());
// Produce prover and verifier keys for CompressedSNARK
let (pk, vk) = CompressedSNARK::<_, _, _, _, S1, S2>::setup(&pp).unwrap();
// produce a recursive SNARK
let num_steps = 3;
let mut recursive_snark: Option<RecursiveSNARK<G1, G2, C1, C2>> = None;
let mut recursive_snark: RecursiveSNARK<G1, G2, C1, C2> = RecursiveSNARK::new(
&pp,
&c_primary,
&c_secondary,
vec![<G1 as Group>::Scalar::from(2u64)],
vec![<G2 as Group>::Scalar::from(2u64)],
);
for i in 0..num_steps {
let res = RecursiveSNARK::prove_step(
let res = recursive_snark.prove_step(
&pp,
recursive_snark,
NonTrivialTestCircuit::new(num_cons),
TrivialTestCircuit::default(),
&c_primary,
&c_secondary,
vec![<G1 as Group>::Scalar::from(2u64)],
vec![<G2 as Group>::Scalar::from(2u64)],
);
assert!(res.is_ok());
let recursive_snark_unwrapped = res.unwrap();
// verify the recursive snark at each step of recursion
let res = recursive_snark_unwrapped.verify(
let res = recursive_snark.verify(
&pp,
i + 1,
vec![<G1 as Group>::Scalar::from(2u64)],
vec![<G2 as Group>::Scalar::from(2u64)],
&vec![<G1 as Group>::Scalar::from(2u64)][..],
&vec![<G2 as Group>::Scalar::from(2u64)][..],
);
assert!(res.is_ok());
// set the running variable for the next iteration
recursive_snark = Some(recursive_snark_unwrapped);
}
// Bench time to produce a compressed SNARK
let recursive_snark = recursive_snark.unwrap();
group.bench_function("Prove", |b| {
b.iter(|| {
assert!(CompressedSNARK::<_, _, _, _, S1, S2>::prove(

View File

@@ -38,61 +38,60 @@ fn bench_recursive_snark(c: &mut Criterion) {
let mut group = c.benchmark_group(format!("RecursiveSNARK-StepCircuitSize-{num_cons}"));
group.sample_size(10);
let c_primary = NonTrivialTestCircuit::new(num_cons);
let c_secondary = TrivialTestCircuit::default();
// Produce public parameters
let pp = PublicParams::<G1, G2, C1, C2>::setup(
NonTrivialTestCircuit::new(num_cons),
TrivialTestCircuit::default(),
);
let pp = PublicParams::<G1, G2, C1, C2>::setup(c_primary.clone(), c_secondary.clone());
// 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 mut recursive_snark: Option<RecursiveSNARK<G1, G2, C1, C2>> = None;
let mut recursive_snark: RecursiveSNARK<G1, G2, C1, C2> = RecursiveSNARK::new(
&pp,
&c_primary,
&c_secondary,
vec![<G1 as Group>::Scalar::from(2u64)],
vec![<G2 as Group>::Scalar::from(2u64)],
);
for i in 0..num_warmup_steps {
let res = RecursiveSNARK::prove_step(
let res = recursive_snark.prove_step(
&pp,
recursive_snark,
NonTrivialTestCircuit::new(num_cons),
TrivialTestCircuit::default(),
&c_primary,
&c_secondary,
vec![<G1 as Group>::Scalar::from(2u64)],
vec![<G2 as Group>::Scalar::from(2u64)],
);
assert!(res.is_ok());
let recursive_snark_unwrapped = res.unwrap();
// verify the recursive snark at each step of recursion
let res = recursive_snark_unwrapped.verify(
let res = recursive_snark.verify(
&pp,
i + 1,
vec![<G1 as Group>::Scalar::from(2u64)],
vec![<G2 as Group>::Scalar::from(2u64)],
&[<G1 as Group>::Scalar::from(2u64)],
&[<G2 as Group>::Scalar::from(2u64)],
);
assert!(res.is_ok());
// set the running variable for the next iteration
recursive_snark = Some(recursive_snark_unwrapped);
}
group.bench_function("Prove", |b| {
b.iter(|| {
// produce a recursive SNARK for a step of the recursion
assert!(RecursiveSNARK::prove_step(
black_box(&pp),
black_box(recursive_snark.clone()),
black_box(NonTrivialTestCircuit::new(num_cons)),
black_box(TrivialTestCircuit::default()),
black_box(vec![<G1 as Group>::Scalar::from(2u64)]),
black_box(vec![<G2 as Group>::Scalar::from(2u64)]),
)
.is_ok());
assert!(black_box(&mut recursive_snark.clone())
.prove_step(
black_box(&pp),
black_box(&c_primary),
black_box(&c_secondary),
black_box(vec![<G1 as Group>::Scalar::from(2u64)]),
black_box(vec![<G2 as Group>::Scalar::from(2u64)]),
)
.is_ok());
})
});
let recursive_snark = recursive_snark.unwrap();
// Benchmark the verification time
group.bench_function("Verify", |b| {
b.iter(|| {
@@ -100,8 +99,8 @@ fn bench_recursive_snark(c: &mut Criterion) {
.verify(
black_box(&pp),
black_box(num_warmup_steps),
black_box(vec![<G1 as Group>::Scalar::from(2u64)]),
black_box(vec![<G2 as Group>::Scalar::from(2u64)]),
black_box(&vec![<G1 as Group>::Scalar::from(2u64)][..]),
black_box(&vec![<G2 as Group>::Scalar::from(2u64)][..]),
)
.is_ok());
});