diff --git a/Cargo.toml b/Cargo.toml index e1be4e2..7a2c53f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ thiserror = "1.0" pasta-msm = { version = "0.1.4" } [dev-dependencies] -criterion = "0.3.1" +criterion = { version = "0.4", features = ["html_reports"] } rand = "0.8.4" hex = "0.4.3" diff --git a/benches/compressed-snark.rs b/benches/compressed-snark.rs index 595bb34..4a06b6d 100644 --- a/benches/compressed-snark.rs +++ b/benches/compressed-snark.rs @@ -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::::setup( - NonTrivialTestCircuit::new(num_cons), - TrivialTestCircuit::default(), - ); + let pp = PublicParams::::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> = None; + let mut recursive_snark: RecursiveSNARK = RecursiveSNARK::new( + &pp, + &c_primary, + &c_secondary, + vec![::Scalar::from(2u64)], + vec![::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![::Scalar::from(2u64)], vec![::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![::Scalar::from(2u64)], - vec![::Scalar::from(2u64)], + &vec![::Scalar::from(2u64)][..], + &vec![::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( diff --git a/benches/recursive-snark.rs b/benches/recursive-snark.rs index 3cf520a..aec865d 100644 --- a/benches/recursive-snark.rs +++ b/benches/recursive-snark.rs @@ -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::::setup( - NonTrivialTestCircuit::new(num_cons), - TrivialTestCircuit::default(), - ); + let pp = PublicParams::::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> = None; + let mut recursive_snark: RecursiveSNARK = RecursiveSNARK::new( + &pp, + &c_primary, + &c_secondary, + vec![::Scalar::from(2u64)], + vec![::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![::Scalar::from(2u64)], vec![::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![::Scalar::from(2u64)], - vec![::Scalar::from(2u64)], + &[::Scalar::from(2u64)], + &[::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![::Scalar::from(2u64)]), - black_box(vec![::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![::Scalar::from(2u64)]), + black_box(vec![::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![::Scalar::from(2u64)]), - black_box(vec![::Scalar::from(2u64)]), + black_box(&vec![::Scalar::from(2u64)][..]), + black_box(&vec![::Scalar::from(2u64)][..]), ) .is_ok()); }); diff --git a/examples/minroot.rs b/examples/minroot.rs index 52162a4..3220417 100644 --- a/examples/minroot.rs +++ b/examples/minroot.rs @@ -172,7 +172,7 @@ fn main() { G2, MinRootCircuit<::Scalar>, TrivialTestCircuit<::Scalar>, - >::setup(circuit_primary, circuit_secondary.clone()); + >::setup(circuit_primary.clone(), circuit_secondary.clone()); println!("PublicParams::setup, took {:?} ", start.elapsed()); println!( @@ -218,15 +218,20 @@ fn main() { type C2 = TrivialTestCircuit<::Scalar>; // produce a recursive SNARK println!("Generating a RecursiveSNARK..."); - let mut recursive_snark: Option> = None; + let mut recursive_snark: RecursiveSNARK = RecursiveSNARK::::new( + &pp, + &minroot_circuits[0], + &circuit_secondary, + z0_primary.clone(), + z0_secondary.clone(), + ); for (i, circuit_primary) in minroot_circuits.iter().take(num_steps).enumerate() { let start = Instant::now(); - let res = RecursiveSNARK::prove_step( + let res = recursive_snark.prove_step( &pp, - recursive_snark, - circuit_primary.clone(), - circuit_secondary.clone(), + circuit_primary, + &circuit_secondary, z0_primary.clone(), z0_secondary.clone(), ); @@ -237,16 +242,12 @@ fn main() { res.is_ok(), start.elapsed() ); - recursive_snark = Some(res.unwrap()); } - assert!(recursive_snark.is_some()); - let recursive_snark = recursive_snark.unwrap(); - // verify the recursive SNARK println!("Verifying a RecursiveSNARK..."); let start = Instant::now(); - let res = recursive_snark.verify(&pp, num_steps, z0_primary.clone(), z0_secondary.clone()); + let res = recursive_snark.verify(&pp, num_steps, &z0_primary, &z0_secondary); println!( "RecursiveSNARK::verify: {:?}, took {:?}", res.is_ok(), diff --git a/src/gadgets/ecc.rs b/src/gadgets/ecc.rs index 677b6cd..997180d 100644 --- a/src/gadgets/ecc.rs +++ b/src/gadgets/ecc.rs @@ -1067,13 +1067,13 @@ mod tests { { let a = alloc_random_point(cs.namespace(|| "a")).unwrap(); inputize_allocted_point(&a, cs.namespace(|| "inputize a")).unwrap(); - let mut b = a.clone(); + let mut b = &mut a.clone(); b.y = AllocatedNum::alloc(cs.namespace(|| "allocate negation of a"), || { Ok(G::Base::ZERO) }) .unwrap(); - inputize_allocted_point(&b, cs.namespace(|| "inputize b")).unwrap(); - let e = a.add(cs.namespace(|| "add a to b"), &b).unwrap(); + inputize_allocted_point(b, cs.namespace(|| "inputize b")).unwrap(); + let e = a.add(cs.namespace(|| "add a to b"), b).unwrap(); e } diff --git a/src/lib.rs b/src/lib.rs index 930ae1f..57b0c18 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -192,197 +192,207 @@ where C1: StepCircuit, C2: StepCircuit, { + /// Create new instance of recursive SNARK + pub fn new( + pp: &PublicParams, + c_primary: &C1, + c_secondary: &C2, + z0_primary: Vec, + z0_secondary: Vec, + ) -> Self { + // Expected outputs of the two circuits + let zi_primary = c_primary.output(&z0_primary); + let zi_secondary = c_secondary.output(&z0_secondary); + + // base case for the primary + let mut cs_primary: SatisfyingAssignment = SatisfyingAssignment::new(); + let inputs_primary: NovaAugmentedCircuitInputs = NovaAugmentedCircuitInputs::new( + scalar_as_base::(pp.digest), + G1::Scalar::ZERO, + z0_primary, + None, + None, + None, + None, + ); + + let circuit_primary: NovaAugmentedCircuit = NovaAugmentedCircuit::new( + pp.augmented_circuit_params_primary.clone(), + Some(inputs_primary), + c_primary.clone(), + pp.ro_consts_circuit_primary.clone(), + ); + let _ = circuit_primary.synthesize(&mut cs_primary); + let (u_primary, w_primary) = cs_primary + .r1cs_instance_and_witness(&pp.r1cs_shape_primary, &pp.ck_primary) + .map_err(|_e| NovaError::UnSat) + .expect("Nova error unsat"); + + // base case for the secondary + let mut cs_secondary: SatisfyingAssignment = SatisfyingAssignment::new(); + let inputs_secondary: NovaAugmentedCircuitInputs = NovaAugmentedCircuitInputs::new( + pp.digest, + G2::Scalar::ZERO, + z0_secondary, + None, + None, + Some(u_primary.clone()), + None, + ); + let circuit_secondary: NovaAugmentedCircuit = NovaAugmentedCircuit::new( + pp.augmented_circuit_params_secondary.clone(), + Some(inputs_secondary), + c_secondary.clone(), + pp.ro_consts_circuit_secondary.clone(), + ); + let _ = circuit_secondary.synthesize(&mut cs_secondary); + let (u_secondary, w_secondary) = cs_secondary + .r1cs_instance_and_witness(&pp.r1cs_shape_secondary, &pp.ck_secondary) + .map_err(|_e| NovaError::UnSat) + .expect("Nova error unsat"); + + // IVC proof for the primary circuit + let l_w_primary = w_primary; + let l_u_primary = u_primary; + let r_W_primary = RelaxedR1CSWitness::from_r1cs_witness(&pp.r1cs_shape_primary, &l_w_primary); + let r_U_primary = + RelaxedR1CSInstance::from_r1cs_instance(&pp.ck_primary, &pp.r1cs_shape_primary, &l_u_primary); + + // IVC proof of the secondary circuit + let l_w_secondary = w_secondary; + let l_u_secondary = u_secondary; + let r_W_secondary = RelaxedR1CSWitness::::default(&pp.r1cs_shape_secondary); + let r_U_secondary = + RelaxedR1CSInstance::::default(&pp.ck_secondary, &pp.r1cs_shape_secondary); + + if zi_primary.len() != pp.F_arity_primary || zi_secondary.len() != pp.F_arity_secondary { + panic!("Invalid step length"); + } + + Self { + r_W_primary, + r_U_primary, + r_W_secondary, + r_U_secondary, + l_w_secondary, + l_u_secondary, + i: 0, + zi_primary, + zi_secondary, + _p_c1: Default::default(), + _p_c2: Default::default(), + } + } + /// Create a new `RecursiveSNARK` (or updates the provided `RecursiveSNARK`) /// by executing a step of the incremental computation pub fn prove_step( + &mut self, pp: &PublicParams, - recursive_snark: Option, - c_primary: C1, - c_secondary: C2, + c_primary: &C1, + c_secondary: &C2, z0_primary: Vec, z0_secondary: Vec, - ) -> Result { + ) -> Result<(), NovaError> { if z0_primary.len() != pp.F_arity_primary || z0_secondary.len() != pp.F_arity_secondary { return Err(NovaError::InvalidInitialInputLength); } - match recursive_snark { - None => { - // base case for the primary - let mut cs_primary: SatisfyingAssignment = SatisfyingAssignment::new(); - let inputs_primary: NovaAugmentedCircuitInputs = NovaAugmentedCircuitInputs::new( - scalar_as_base::(pp.digest), - G1::Scalar::ZERO, - z0_primary.clone(), - None, - None, - None, - None, - ); + // Frist step was already done in the constructor + if self.i == 0 { + self.i = 1; + return Ok(()); + } - let circuit_primary: NovaAugmentedCircuit = NovaAugmentedCircuit::new( - pp.augmented_circuit_params_primary.clone(), - Some(inputs_primary), - c_primary.clone(), - pp.ro_consts_circuit_primary.clone(), - ); - let _ = circuit_primary.synthesize(&mut cs_primary); - let (u_primary, w_primary) = cs_primary - .r1cs_instance_and_witness(&pp.r1cs_shape_primary, &pp.ck_primary) - .map_err(|_e| NovaError::UnSat)?; - - // base case for the secondary - let mut cs_secondary: SatisfyingAssignment = SatisfyingAssignment::new(); - let inputs_secondary: NovaAugmentedCircuitInputs = NovaAugmentedCircuitInputs::new( - pp.digest, - G2::Scalar::ZERO, - z0_secondary.clone(), - None, - None, - Some(u_primary.clone()), - None, - ); - let circuit_secondary: NovaAugmentedCircuit = NovaAugmentedCircuit::new( - pp.augmented_circuit_params_secondary.clone(), - Some(inputs_secondary), - c_secondary.clone(), - pp.ro_consts_circuit_secondary.clone(), - ); - let _ = circuit_secondary.synthesize(&mut cs_secondary); - let (u_secondary, w_secondary) = cs_secondary - .r1cs_instance_and_witness(&pp.r1cs_shape_secondary, &pp.ck_secondary) - .map_err(|_e| NovaError::UnSat)?; - - // IVC proof for the primary circuit - let l_w_primary = w_primary; - let l_u_primary = u_primary; - let r_W_primary = - RelaxedR1CSWitness::from_r1cs_witness(&pp.r1cs_shape_primary, &l_w_primary); - let r_U_primary = RelaxedR1CSInstance::from_r1cs_instance( - &pp.ck_primary, - &pp.r1cs_shape_primary, - &l_u_primary, - ); + // fold the secondary circuit's instance + let (nifs_secondary, (r_U_secondary, r_W_secondary)) = NIFS::prove( + &pp.ck_secondary, + &pp.ro_consts_secondary, + &scalar_as_base::(pp.digest), + &pp.r1cs_shape_secondary, + &self.r_U_secondary, + &self.r_W_secondary, + &self.l_u_secondary, + &self.l_w_secondary, + ) + .expect("Unable to fold secondary"); + + let mut cs_primary: SatisfyingAssignment = SatisfyingAssignment::new(); + let inputs_primary: NovaAugmentedCircuitInputs = NovaAugmentedCircuitInputs::new( + scalar_as_base::(pp.digest), + G1::Scalar::from(self.i as u64), + z0_primary, + Some(self.zi_primary.clone()), + Some(self.r_U_secondary.clone()), + Some(self.l_u_secondary.clone()), + Some(Commitment::::decompress(&nifs_secondary.comm_T)?), + ); - // IVC proof of the secondary circuit - let l_w_secondary = w_secondary; - let l_u_secondary = u_secondary; - let r_W_secondary = RelaxedR1CSWitness::::default(&pp.r1cs_shape_secondary); - let r_U_secondary = - RelaxedR1CSInstance::::default(&pp.ck_secondary, &pp.r1cs_shape_secondary); + let circuit_primary: NovaAugmentedCircuit = NovaAugmentedCircuit::new( + pp.augmented_circuit_params_primary.clone(), + Some(inputs_primary), + c_primary.clone(), + pp.ro_consts_circuit_primary.clone(), + ); + let _ = circuit_primary.synthesize(&mut cs_primary); + + let (l_u_primary, l_w_primary) = cs_primary + .r1cs_instance_and_witness(&pp.r1cs_shape_primary, &pp.ck_primary) + .map_err(|_e| NovaError::UnSat) + .expect("Nova error unsat"); + + // fold the primary circuit's instance + let (nifs_primary, (r_U_primary, r_W_primary)) = NIFS::prove( + &pp.ck_primary, + &pp.ro_consts_primary, + &pp.digest, + &pp.r1cs_shape_primary, + &self.r_U_primary, + &self.r_W_primary, + &l_u_primary, + &l_w_primary, + ) + .expect("Unable to fold primary"); + + let mut cs_secondary: SatisfyingAssignment = SatisfyingAssignment::new(); + let inputs_secondary: NovaAugmentedCircuitInputs = NovaAugmentedCircuitInputs::new( + pp.digest, + G2::Scalar::from(self.i as u64), + z0_secondary, + Some(self.zi_secondary.clone()), + Some(self.r_U_primary.clone()), + Some(l_u_primary), + Some(Commitment::::decompress(&nifs_primary.comm_T)?), + ); - // Outputs of the two circuits thus far - let zi_primary = c_primary.output(&z0_primary); - let zi_secondary = c_secondary.output(&z0_secondary); + let circuit_secondary: NovaAugmentedCircuit = NovaAugmentedCircuit::new( + pp.augmented_circuit_params_secondary.clone(), + Some(inputs_secondary), + c_secondary.clone(), + pp.ro_consts_circuit_secondary.clone(), + ); + let _ = circuit_secondary.synthesize(&mut cs_secondary); - if zi_primary.len() != pp.F_arity_primary || zi_secondary.len() != pp.F_arity_secondary { - return Err(NovaError::InvalidStepOutputLength); - } + let (l_u_secondary, l_w_secondary) = cs_secondary + .r1cs_instance_and_witness(&pp.r1cs_shape_secondary, &pp.ck_secondary) + .map_err(|_e| NovaError::UnSat)?; - Ok(Self { - r_W_primary, - r_U_primary, - r_W_secondary, - r_U_secondary, - l_w_secondary, - l_u_secondary, - i: 1_usize, - zi_primary, - zi_secondary, - _p_c1: Default::default(), - _p_c2: Default::default(), - }) - } - Some(r_snark) => { - // fold the secondary circuit's instance - let (nifs_secondary, (r_U_secondary, r_W_secondary)) = NIFS::prove( - &pp.ck_secondary, - &pp.ro_consts_secondary, - &scalar_as_base::(pp.digest), - &pp.r1cs_shape_secondary, - &r_snark.r_U_secondary, - &r_snark.r_W_secondary, - &r_snark.l_u_secondary, - &r_snark.l_w_secondary, - )?; - - let mut cs_primary: SatisfyingAssignment = SatisfyingAssignment::new(); - let inputs_primary: NovaAugmentedCircuitInputs = NovaAugmentedCircuitInputs::new( - scalar_as_base::(pp.digest), - G1::Scalar::from(r_snark.i as u64), - z0_primary, - Some(r_snark.zi_primary.clone()), - Some(r_snark.r_U_secondary.clone()), - Some(r_snark.l_u_secondary.clone()), - Some(Commitment::::decompress(&nifs_secondary.comm_T)?), - ); + // update the running instances and witnesses + self.zi_primary = c_primary.output(&self.zi_primary); + self.zi_secondary = c_secondary.output(&self.zi_secondary); - let circuit_primary: NovaAugmentedCircuit = NovaAugmentedCircuit::new( - pp.augmented_circuit_params_primary.clone(), - Some(inputs_primary), - c_primary.clone(), - pp.ro_consts_circuit_primary.clone(), - ); - let _ = circuit_primary.synthesize(&mut cs_primary); + self.l_u_secondary = l_u_secondary; + self.l_w_secondary = l_w_secondary; - let (l_u_primary, l_w_primary) = cs_primary - .r1cs_instance_and_witness(&pp.r1cs_shape_primary, &pp.ck_primary) - .map_err(|_e| NovaError::UnSat)?; + self.r_U_primary = r_U_primary; + self.r_W_primary = r_W_primary; - // fold the primary circuit's instance - let (nifs_primary, (r_U_primary, r_W_primary)) = NIFS::prove( - &pp.ck_primary, - &pp.ro_consts_primary, - &pp.digest, - &pp.r1cs_shape_primary, - &r_snark.r_U_primary, - &r_snark.r_W_primary, - &l_u_primary, - &l_w_primary, - )?; - - let mut cs_secondary: SatisfyingAssignment = SatisfyingAssignment::new(); - let inputs_secondary: NovaAugmentedCircuitInputs = NovaAugmentedCircuitInputs::new( - pp.digest, - G2::Scalar::from(r_snark.i as u64), - z0_secondary, - Some(r_snark.zi_secondary.clone()), - Some(r_snark.r_U_primary.clone()), - Some(l_u_primary), - Some(Commitment::::decompress(&nifs_primary.comm_T)?), - ); + self.i += 1; - let circuit_secondary: NovaAugmentedCircuit = NovaAugmentedCircuit::new( - pp.augmented_circuit_params_secondary.clone(), - Some(inputs_secondary), - c_secondary.clone(), - pp.ro_consts_circuit_secondary.clone(), - ); - let _ = circuit_secondary.synthesize(&mut cs_secondary); - - let (l_u_secondary, l_w_secondary) = cs_secondary - .r1cs_instance_and_witness(&pp.r1cs_shape_secondary, &pp.ck_secondary) - .map_err(|_e| NovaError::UnSat)?; - - // update the running instances and witnesses - let zi_primary = c_primary.output(&r_snark.zi_primary); - let zi_secondary = c_secondary.output(&r_snark.zi_secondary); - - Ok(Self { - r_W_primary, - r_U_primary, - r_W_secondary, - r_U_secondary, - l_w_secondary, - l_u_secondary, - i: r_snark.i + 1, - zi_primary, - zi_secondary, - _p_c1: Default::default(), - _p_c2: Default::default(), - }) - } - } + self.r_U_secondary = r_U_secondary; + self.r_W_secondary = r_W_secondary; + + Ok(()) } /// Verify the correctness of the `RecursiveSNARK` @@ -390,8 +400,8 @@ where &self, pp: &PublicParams, num_steps: usize, - z0_primary: Vec, - z0_secondary: Vec, + z0_primary: &[G1::Scalar], + z0_secondary: &[G2::Scalar], ) -> Result<(Vec, Vec), NovaError> { // number of steps cannot be zero if num_steps == 0 { @@ -419,7 +429,7 @@ where ); hasher.absorb(pp.digest); hasher.absorb(G1::Scalar::from(num_steps as u64)); - for e in &z0_primary { + for e in z0_primary { hasher.absorb(*e); } for e in &self.zi_primary { @@ -433,7 +443,7 @@ where ); hasher2.absorb(scalar_as_base::(pp.digest)); hasher2.absorb(G2::Scalar::from(num_steps as u64)); - for e in &z0_secondary { + for e in z0_secondary { hasher2.absorb(*e); } for e in &self.zi_secondary { @@ -906,23 +916,30 @@ mod tests { let num_steps = 1; // produce a recursive SNARK - let res = RecursiveSNARK::prove_step( + let mut recursive_snark = RecursiveSNARK::new( &pp, - None, - test_circuit1, - test_circuit2, + &test_circuit1, + &test_circuit2, + vec![::Scalar::ZERO], + vec![::Scalar::ZERO], + ); + + let res = recursive_snark.prove_step( + &pp, + &test_circuit1, + &test_circuit2, vec![::Scalar::ZERO], vec![::Scalar::ZERO], ); + assert!(res.is_ok()); - let recursive_snark = res.unwrap(); // verify the recursive SNARK let res = recursive_snark.verify( &pp, num_steps, - vec![::Scalar::ZERO], - vec![::Scalar::ZERO], + &vec![::Scalar::ZERO][..], + &vec![::Scalar::ZERO][..], ); assert!(res.is_ok()); } @@ -953,49 +970,45 @@ mod tests { let num_steps = 3; // produce a recursive SNARK - let mut recursive_snark: Option< - RecursiveSNARK< - G1, - G2, - TrivialTestCircuit<::Scalar>, - CubicCircuit<::Scalar>, - >, - > = None; + let mut recursive_snark = RecursiveSNARK::< + G1, + G2, + TrivialTestCircuit<::Scalar>, + CubicCircuit<::Scalar>, + >::new( + &pp, + &circuit_primary, + &circuit_secondary, + vec![::Scalar::ONE], + vec![::Scalar::ZERO], + ); for i in 0..num_steps { - let res = RecursiveSNARK::prove_step( + let res = recursive_snark.prove_step( &pp, - recursive_snark, - circuit_primary.clone(), - circuit_secondary.clone(), + &circuit_primary, + &circuit_secondary, vec![::Scalar::ONE], vec![::Scalar::ZERO], ); 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![::Scalar::ONE], - vec![::Scalar::ZERO], + &vec![::Scalar::ONE][..], + &vec![::Scalar::ZERO][..], ); assert!(res.is_ok()); - - // set the running variable for the next iteration - recursive_snark = Some(recursive_snark_unwrapped); } - assert!(recursive_snark.is_some()); - let recursive_snark = recursive_snark.unwrap(); - // verify the recursive SNARK let res = recursive_snark.verify( &pp, num_steps, - vec![::Scalar::ONE], - vec![::Scalar::ZERO], + &vec![::Scalar::ONE][..], + &vec![::Scalar::ZERO][..], ); assert!(res.is_ok()); @@ -1043,37 +1056,36 @@ mod tests { let num_steps = 3; // produce a recursive SNARK - let mut recursive_snark: Option< - RecursiveSNARK< - G1, - G2, - TrivialTestCircuit<::Scalar>, - CubicCircuit<::Scalar>, - >, - > = None; + let mut recursive_snark = RecursiveSNARK::< + G1, + G2, + TrivialTestCircuit<::Scalar>, + CubicCircuit<::Scalar>, + >::new( + &pp, + &circuit_primary, + &circuit_secondary, + vec![::Scalar::ONE], + vec![::Scalar::ZERO], + ); for _i in 0..num_steps { - let res = RecursiveSNARK::prove_step( + let res = recursive_snark.prove_step( &pp, - recursive_snark, - circuit_primary.clone(), - circuit_secondary.clone(), + &circuit_primary, + &circuit_secondary, vec![::Scalar::ONE], vec![::Scalar::ZERO], ); assert!(res.is_ok()); - recursive_snark = Some(res.unwrap()); } - assert!(recursive_snark.is_some()); - let recursive_snark = recursive_snark.unwrap(); - // verify the recursive SNARK let res = recursive_snark.verify( &pp, num_steps, - vec![::Scalar::ONE], - vec![::Scalar::ZERO], + &vec![::Scalar::ONE][..], + &vec![::Scalar::ZERO][..], ); assert!(res.is_ok()); @@ -1138,37 +1150,36 @@ mod tests { let num_steps = 3; // produce a recursive SNARK - let mut recursive_snark: Option< - RecursiveSNARK< - G1, - G2, - TrivialTestCircuit<::Scalar>, - CubicCircuit<::Scalar>, - >, - > = None; + let mut recursive_snark = RecursiveSNARK::< + G1, + G2, + TrivialTestCircuit<::Scalar>, + CubicCircuit<::Scalar>, + >::new( + &pp, + &circuit_primary, + &circuit_secondary, + vec![::Scalar::ONE], + vec![::Scalar::ZERO], + ); for _i in 0..num_steps { - let res = RecursiveSNARK::prove_step( + let res = recursive_snark.prove_step( &pp, - recursive_snark, - circuit_primary.clone(), - circuit_secondary.clone(), + &circuit_primary, + &circuit_secondary, vec![::Scalar::ONE], vec![::Scalar::ZERO], ); assert!(res.is_ok()); - recursive_snark = Some(res.unwrap()); } - assert!(recursive_snark.is_some()); - let recursive_snark = recursive_snark.unwrap(); - // verify the recursive SNARK let res = recursive_snark.verify( &pp, num_steps, - vec![::Scalar::ONE], - vec![::Scalar::ZERO], + &vec![::Scalar::ONE][..], + &vec![::Scalar::ZERO][..], ); assert!(res.is_ok()); @@ -1237,14 +1248,9 @@ mod tests { let rng = &mut rand::rngs::OsRng; let mut seed = F::random(rng); for _i in 0..num_steps + 1 { - let mut power = seed; - power = power.square(); - power = power.square(); - power *= seed; + seed *= seed.clone().square().square(); - powers.push(Self { y: power }); - - seed = power; + powers.push(Self { y: seed }); } // reverse the powers to get roots @@ -1289,12 +1295,7 @@ mod tests { fn output(&self, z: &[F]) -> Vec { // sanity check let x = z[0]; - let y_pow_5 = { - let y = self.y; - let y_sq = y.square(); - let y_quad = y_sq.square(); - y_quad * self.y - }; + let y_pow_5 = self.y * self.y.clone().square().square(); assert_eq!(x, y_pow_5); // return non-deterministic advice @@ -1324,33 +1325,37 @@ mod tests { let z0_secondary = vec![::Scalar::ZERO]; // produce a recursive SNARK - let mut recursive_snark: Option< - RecursiveSNARK< - G1, - G2, - FifthRootCheckingCircuit<::Scalar>, - TrivialTestCircuit<::Scalar>, - >, - > = None; + let mut recursive_snark: RecursiveSNARK< + G1, + G2, + FifthRootCheckingCircuit<::Scalar>, + TrivialTestCircuit<::Scalar>, + > = RecursiveSNARK::< + G1, + G2, + FifthRootCheckingCircuit<::Scalar>, + TrivialTestCircuit<::Scalar>, + >::new( + &pp, + &roots[0], + &circuit_secondary, + z0_primary.clone(), + z0_secondary.clone(), + ); for circuit_primary in roots.iter().take(num_steps) { - let res = RecursiveSNARK::prove_step( + let res = recursive_snark.prove_step( &pp, - recursive_snark, - circuit_primary.clone(), - circuit_secondary.clone(), + circuit_primary, + &circuit_secondary.clone(), z0_primary.clone(), z0_secondary.clone(), ); assert!(res.is_ok()); - recursive_snark = Some(res.unwrap()); } - assert!(recursive_snark.is_some()); - let recursive_snark = recursive_snark.unwrap(); - // verify the recursive SNARK - let res = recursive_snark.verify(&pp, num_steps, z0_primary.clone(), z0_secondary.clone()); + let res = recursive_snark.verify(&pp, num_steps, &z0_primary, &z0_secondary); assert!(res.is_ok()); // produce the prover and verifier keys for compressed snark @@ -1379,34 +1384,50 @@ mod tests { G1: Group::Scalar>, G2: Group::Scalar>, { + let test_circuit1 = TrivialTestCircuit::<::Scalar>::default(); + let test_circuit2 = CubicCircuit::<::Scalar>::default(); + // produce public parameters let pp = PublicParams::< G1, G2, TrivialTestCircuit<::Scalar>, CubicCircuit<::Scalar>, - >::setup(TrivialTestCircuit::default(), CubicCircuit::default()); + >::setup(test_circuit1.clone(), test_circuit2.clone()); let num_steps = 1; // produce a recursive SNARK - let res = RecursiveSNARK::prove_step( + let mut recursive_snark = RecursiveSNARK::< + G1, + G2, + TrivialTestCircuit<::Scalar>, + CubicCircuit<::Scalar>, + >::new( &pp, - None, - TrivialTestCircuit::default(), - CubicCircuit::default(), + &test_circuit1, + &test_circuit2, vec![::Scalar::ONE], vec![::Scalar::ZERO], ); + + // produce a recursive SNARK + let res = recursive_snark.prove_step( + &pp, + &test_circuit1, + &test_circuit2, + vec![::Scalar::ONE], + vec![::Scalar::ZERO], + ); + assert!(res.is_ok()); - let recursive_snark = res.unwrap(); // verify the recursive SNARK let res = recursive_snark.verify( &pp, num_steps, - vec![::Scalar::ONE], - vec![::Scalar::ZERO], + &vec![::Scalar::ONE][..], + &vec![::Scalar::ZERO][..], ); assert!(res.is_ok()); diff --git a/src/provider/pedersen.rs b/src/provider/pedersen.rs index b5a45e1..bad1247 100644 --- a/src/provider/pedersen.rs +++ b/src/provider/pedersen.rs @@ -69,7 +69,7 @@ impl Default for Commitment { impl TranscriptReprTrait for Commitment { fn to_transcript_bytes(&self) -> Vec { let (x, y, is_infinity) = self.comm.to_coordinates(); - let is_infinity_byte = if is_infinity { 0u8 } else { 1u8 }; + let is_infinity_byte = (!is_infinity).into(); [ x.to_transcript_bytes(), y.to_transcript_bytes(),