diff --git a/examples/minroot.rs b/examples/minroot.rs index 80a3787..d173608 100644 --- a/examples/minroot.rs +++ b/examples/minroot.rs @@ -87,14 +87,16 @@ where z: AllocatedNum, ) -> Result, SynthesisError> { let mut z_out: Result, SynthesisError> = Err(SynthesisError::AssignmentMissing); + + // allocate variables to hold x_0 and y_0 + let x_0 = AllocatedNum::alloc(cs.namespace(|| "x_0"), || Ok(self.seq[0].x_i))?; + let y_0 = AllocatedNum::alloc(cs.namespace(|| "y_0"), || Ok(self.seq[0].y_i))?; + + // variables to hold running x_i and y_i + let mut x_i = x_0; + let mut y_i = y_0; for i in 0..self.seq.len() { - // Allocate four variables for holding non-deterministic advice: x_i, y_i, x_i_plus_1, y_i_plus_1 - let x_i = AllocatedNum::alloc(cs.namespace(|| format!("x_i_iter_{}", i)), || { - Ok(self.seq[i].x_i) - })?; - let y_i = AllocatedNum::alloc(cs.namespace(|| format!("y_i_iter_{}", i)), || { - Ok(self.seq[i].y_i) - })?; + // non deterministic advice let x_i_plus_1 = AllocatedNum::alloc(cs.namespace(|| format!("x_i_plus_1_iter_{}", i)), || { Ok(self.seq[i].x_i_plus_1) @@ -135,10 +137,14 @@ where if i == self.seq.len() - 1 { z_out = poseidon_hash( cs.namespace(|| "output hash"), - vec![x_i_plus_1, x_i.clone()], + vec![x_i_plus_1.clone(), x_i.clone()], &self.pc, ); } + + // update x_i and y_i for the next iteration + y_i = x_i; + x_i = x_i_plus_1; } z_out @@ -164,143 +170,146 @@ where } fn main() { + println!("Nova-based VDF with MinRoot delay function"); + println!("========================================================="); + let num_steps = 10; - let num_iters_per_step = 10; // number of iterations of MinRoot per Nova's recursive step - - let pc = PoseidonConstants::<::Scalar, U2>::new_with_strength(Strength::Standard); - let circuit_primary = MinRootCircuit { - seq: vec![ - MinRootIteration { - x_i: ::Scalar::zero(), - y_i: ::Scalar::zero(), - x_i_plus_1: ::Scalar::zero(), - y_i_plus_1: ::Scalar::zero(), - }; + for num_iters_per_step in [1024, 2048, 4096, 8192, 16384, 32768, 65535] { + // number of iterations of MinRoot per Nova's recursive step + let pc = PoseidonConstants::<::Scalar, U2>::new_with_strength(Strength::Standard); + let circuit_primary = MinRootCircuit { + seq: vec![ + MinRootIteration { + x_i: ::Scalar::zero(), + y_i: ::Scalar::zero(), + x_i_plus_1: ::Scalar::zero(), + y_i_plus_1: ::Scalar::zero(), + }; + num_iters_per_step + ], + pc: pc.clone(), + }; + + let circuit_secondary = TrivialTestCircuit::default(); + + println!( + "Proving {} iterations of MinRoot per step", num_iters_per_step - ], - pc: pc.clone(), - }; + ); - let circuit_secondary = TrivialTestCircuit::default(); + // produce public parameters + println!("Producing public parameters..."); + let pp = PublicParams::< + G1, + G2, + MinRootCircuit<::Scalar>, + TrivialTestCircuit<::Scalar>, + >::setup(circuit_primary, circuit_secondary.clone()); + println!( + "Number of constraints per step (primary circuit): {}", + pp.num_constraints().0 + ); + println!( + "Number of constraints per step (secondary circuit): {}", + pp.num_constraints().1 + ); - println!("Nova-based VDF with MinRoot delay function"); - println!("=========================================="); - println!( - "Proving {} iterations of MinRoot per step", - num_iters_per_step - ); - - // produce public parameters - println!("Producing public parameters..."); - let pp = PublicParams::< - G1, - G2, - MinRootCircuit<::Scalar>, - TrivialTestCircuit<::Scalar>, - >::setup(circuit_primary, circuit_secondary.clone()); - println!( - "Number of constraints per step (primary circuit): {}", - pp.num_constraints().0 - ); - println!( - "Number of constraints per step (secondary circuit): {}", - pp.num_constraints().1 - ); - - println!( - "Number of variables per step (primary circuit): {}", - pp.num_variables().0 - ); - println!( - "Number of variables per step (secondary circuit): {}", - pp.num_variables().1 - ); - - // produce non-deterministic advice - let (z0_primary, minroot_iterations) = MinRootIteration::new( - num_iters_per_step * num_steps, - &::Scalar::zero(), - &::Scalar::one(), - &pc, - ); - let minroot_circuits = (0..num_steps) - .map(|i| MinRootCircuit { - seq: (0..num_iters_per_step) - .map(|j| MinRootIteration { - x_i: minroot_iterations[i * num_iters_per_step + j].x_i, - y_i: minroot_iterations[i * num_iters_per_step + j].y_i, - x_i_plus_1: minroot_iterations[i * num_iters_per_step + j].x_i_plus_1, - y_i_plus_1: minroot_iterations[i * num_iters_per_step + j].y_i_plus_1, - }) - .collect::>(), - pc: pc.clone(), - }) - .collect::>(); + println!( + "Number of variables per step (primary circuit): {}", + pp.num_variables().0 + ); + println!( + "Number of variables per step (secondary circuit): {}", + pp.num_variables().1 + ); - let z0_secondary = ::Scalar::zero(); + // produce non-deterministic advice + let (z0_primary, minroot_iterations) = MinRootIteration::new( + num_iters_per_step * num_steps, + &::Scalar::zero(), + &::Scalar::one(), + &pc, + ); + let minroot_circuits = (0..num_steps) + .map(|i| MinRootCircuit { + seq: (0..num_iters_per_step) + .map(|j| MinRootIteration { + x_i: minroot_iterations[i * num_iters_per_step + j].x_i, + y_i: minroot_iterations[i * num_iters_per_step + j].y_i, + x_i_plus_1: minroot_iterations[i * num_iters_per_step + j].x_i_plus_1, + y_i_plus_1: minroot_iterations[i * num_iters_per_step + j].y_i_plus_1, + }) + .collect::>(), + pc: pc.clone(), + }) + .collect::>(); + + let z0_secondary = ::Scalar::zero(); + + type C1 = MinRootCircuit<::Scalar>; + type C2 = TrivialTestCircuit<::Scalar>; + // produce a recursive SNARK + println!("Generating a RecursiveSNARK..."); + let mut recursive_snark: Option> = None; - type C1 = MinRootCircuit<::Scalar>; - type C2 = TrivialTestCircuit<::Scalar>; - // produce a recursive SNARK - println!("Generating a RecursiveSNARK..."); - let mut recursive_snark: Option> = None; + for (i, circuit_primary) in minroot_circuits.iter().take(num_steps).enumerate() { + let start = Instant::now(); + let res = RecursiveSNARK::prove_step( + &pp, + recursive_snark, + circuit_primary.clone(), + circuit_secondary.clone(), + z0_primary, + z0_secondary, + ); + assert!(res.is_ok()); + println!( + "RecursiveSNARK::prove_step {}: {:?}, took {:?} ", + i, + res.is_ok(), + start.elapsed() + ); + recursive_snark = Some(res.unwrap()); + } - for (i, circuit_primary) in minroot_circuits.iter().take(num_steps).enumerate() { + 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 = RecursiveSNARK::prove_step( - &pp, - recursive_snark, - circuit_primary.clone(), - circuit_secondary.clone(), - z0_primary, - z0_secondary, + let res = recursive_snark.verify(&pp, num_steps, z0_primary, z0_secondary); + println!( + "RecursiveSNARK::verify: {:?}, took {:?}", + res.is_ok(), + start.elapsed() ); assert!(res.is_ok()); + + // produce a compressed SNARK + println!("Generating a CompressedSNARK using Spartan with IPA-PC..."); + let start = Instant::now(); + type S1 = nova_snark::spartan_with_ipa_pc::RelaxedR1CSSNARK; + type S2 = nova_snark::spartan_with_ipa_pc::RelaxedR1CSSNARK; + let res = CompressedSNARK::<_, _, _, _, S1, S2>::prove(&pp, &recursive_snark); println!( - "RecursiveSNARK::prove_step {}: {:?}, took {:?} ", - i, + "CompressedSNARK::prove: {:?}, took {:?}", res.is_ok(), start.elapsed() ); - recursive_snark = Some(res.unwrap()); - } + assert!(res.is_ok()); + let compressed_snark = 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, z0_secondary); - println!( - "RecursiveSNARK::verify: {:?}, took {:?}", - res.is_ok(), - start.elapsed() - ); - assert!(res.is_ok()); - - // produce a compressed SNARK - println!("Generating a CompressedSNARK using Spartan with IPA-PC..."); - let start = Instant::now(); - type S1 = nova_snark::spartan_with_ipa_pc::RelaxedR1CSSNARK; - type S2 = nova_snark::spartan_with_ipa_pc::RelaxedR1CSSNARK; - let res = CompressedSNARK::<_, _, _, _, S1, S2>::prove(&pp, &recursive_snark); - println!( - "CompressedSNARK::prove: {:?}, took {:?}", - res.is_ok(), - start.elapsed() - ); - assert!(res.is_ok()); - let compressed_snark = res.unwrap(); - - // verify the compressed SNARK - println!("Verifying a CompressedSNARK..."); - let start = Instant::now(); - let res = compressed_snark.verify(&pp, num_steps, z0_primary, z0_secondary); - println!( - "CompressedSNARK::verify: {:?}, took {:?}", - res.is_ok(), - start.elapsed() - ); - assert!(res.is_ok()); + // verify the compressed SNARK + println!("Verifying a CompressedSNARK..."); + let start = Instant::now(); + let res = compressed_snark.verify(&pp, num_steps, z0_primary, z0_secondary); + println!( + "CompressedSNARK::verify: {:?}, took {:?}", + res.is_ok(), + start.elapsed() + ); + assert!(res.is_ok()); + println!("========================================================="); + } }