You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

139 lines
3.4 KiB

  1. #![allow(non_snake_case)]
  2. use nova_snark::{
  3. traits::{Group, StepCircuit},
  4. CompressedSNARK, PublicParams, RecursiveSNARK,
  5. };
  6. type G1 = pasta_curves::pallas::Point;
  7. type G2 = pasta_curves::vesta::Point;
  8. type S1 = nova_snark::spartan_with_ipa_pc::RelaxedR1CSSNARK<G1>;
  9. type S2 = nova_snark::spartan_with_ipa_pc::RelaxedR1CSSNARK<G2>;
  10. #[derive(Clone, Debug)]
  11. struct TrivialTestCircuit<F: PrimeField> {
  12. _p: PhantomData<F>,
  13. }
  14. impl<F> StepCircuit<F> for TrivialTestCircuit<F>
  15. where
  16. F: PrimeField,
  17. {
  18. fn synthesize<CS: ConstraintSystem<F>>(
  19. &self,
  20. _cs: &mut CS,
  21. z: AllocatedNum<F>,
  22. ) -> Result<AllocatedNum<F>, SynthesisError> {
  23. Ok(z)
  24. }
  25. fn compute(&self, z: &F) -> F {
  26. *z
  27. }
  28. }
  29. type C1 = TrivialTestCircuit<<G1 as Group>::Scalar>;
  30. type C2 = TrivialTestCircuit<<G2 as Group>::Scalar>;
  31. use bellperson::{gadgets::num::AllocatedNum, ConstraintSystem, SynthesisError};
  32. use core::marker::PhantomData;
  33. use criterion::*;
  34. use ff::PrimeField;
  35. use std::time::Duration;
  36. fn compressed_snark_benchmark(c: &mut Criterion) {
  37. let num_samples = 10;
  38. bench_compressed_snark(c, num_samples);
  39. }
  40. fn set_duration() -> Criterion {
  41. Criterion::default().warm_up_time(Duration::from_millis(3000))
  42. }
  43. criterion_group! {
  44. name = compressed_snark;
  45. config = set_duration();
  46. targets = compressed_snark_benchmark
  47. }
  48. criterion_main!(compressed_snark);
  49. fn bench_compressed_snark(c: &mut Criterion, num_samples: usize) {
  50. let mut group = c.benchmark_group("CompressedSNARK");
  51. group.sample_size(num_samples);
  52. // Produce public parameters
  53. let pp = PublicParams::<G1, G2, C1, C2>::setup(
  54. TrivialTestCircuit {
  55. _p: Default::default(),
  56. },
  57. TrivialTestCircuit {
  58. _p: Default::default(),
  59. },
  60. );
  61. // produce a recursive SNARK
  62. let num_steps = 3;
  63. let mut recursive_snark: Option<RecursiveSNARK<G1, G2, C1, C2>> = None;
  64. for i in 0..num_steps {
  65. let res = RecursiveSNARK::prove_step(
  66. &pp,
  67. recursive_snark,
  68. TrivialTestCircuit {
  69. _p: Default::default(),
  70. },
  71. TrivialTestCircuit {
  72. _p: Default::default(),
  73. },
  74. <G1 as Group>::Scalar::one(),
  75. <G2 as Group>::Scalar::zero(),
  76. );
  77. assert!(res.is_ok());
  78. let recursive_snark_unwrapped = res.unwrap();
  79. // verify the recursive snark at each step of recursion
  80. let res = recursive_snark_unwrapped.verify(
  81. &pp,
  82. i + 1,
  83. <G1 as Group>::Scalar::one(),
  84. <G2 as Group>::Scalar::zero(),
  85. );
  86. assert!(res.is_ok());
  87. // set the running variable for the next iteration
  88. recursive_snark = Some(recursive_snark_unwrapped);
  89. }
  90. // Bench time to produce a compressed SNARK
  91. let recursive_snark = recursive_snark.unwrap();
  92. group.bench_function("Prove", |b| {
  93. b.iter(|| {
  94. assert!(CompressedSNARK::<_, _, _, _, S1, S2>::prove(
  95. black_box(&pp),
  96. black_box(&recursive_snark)
  97. )
  98. .is_ok());
  99. })
  100. });
  101. let res = CompressedSNARK::<_, _, _, _, S1, S2>::prove(&pp, &recursive_snark);
  102. assert!(res.is_ok());
  103. let compressed_snark = res.unwrap();
  104. // Benchmark the verification time
  105. let name = "Verify";
  106. group.bench_function(name, |b| {
  107. b.iter(|| {
  108. assert!(black_box(&compressed_snark)
  109. .verify(
  110. black_box(&pp),
  111. black_box(num_steps),
  112. black_box(<G1 as Group>::Scalar::zero()),
  113. black_box(<G2 as Group>::Scalar::zero()),
  114. )
  115. .is_ok());
  116. })
  117. });
  118. group.finish();
  119. }