diff --git a/Cargo.toml b/Cargo.toml index 099343a..b97cbf9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,8 +32,8 @@ git = "https://github.com/gtank/blake2-rfc" rev = "7a5b5fc99ae483a0043db7547fb79a6fa44b88a9" [features] -#default = ["multicore"] -default = ["multicore", "gm17", "sonic"] +default = ["multicore"] +#default = ["multicore", "gm17", "sonic"] #default = ["singlecore"] multicore = ["futures-cpupool", "num_cpus", "crossbeam"] sonic = ["tiny-keccak"] diff --git a/src/multiexp.rs b/src/multiexp.rs index 9fbec53..e4682f2 100644 --- a/src/multiexp.rs +++ b/src/multiexp.rs @@ -185,6 +185,7 @@ pub fn multiexp( /// Perform multi-exponentiation. The caller is responsible for ensuring that /// the number of bases is the same as the number of exponents. +#[allow(dead_code)] pub fn dense_multiexp( pool: &Worker, bases: & [G], @@ -220,7 +221,6 @@ fn dense_multiexp_inner( let this_region = Mutex::new(::Projective::zero()); let arc = Arc::new(this_region); pool.scope(bases.len(), |scope, chunk| { - let mut this_acc = ::Projective::zero(); for (base, exp) in bases.chunks(chunk).zip(exponents.chunks(chunk)) { let this_region_rwlock = arc.clone(); // let handle = @@ -265,7 +265,7 @@ fn dense_multiexp_inner( let mut guard = match this_region_rwlock.lock() { Ok(guard) => guard, - Err(poisoned) => { + Err(_) => { panic!("poisoned!"); // poisoned.into_inner() } @@ -387,7 +387,7 @@ fn test_dense_multiexp() { const SAMPLES: usize = 1 << 16; let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); - let mut v = (0..SAMPLES).map(|_| ::Fr::rand(rng).into_repr()).collect::>(); + let v = (0..SAMPLES).map(|_| ::Fr::rand(rng).into_repr()).collect::>(); let g = (0..SAMPLES).map(|_| ::G1::rand(rng).into_affine()).collect::>(); println!("Done generating test points and scalars"); @@ -397,7 +397,7 @@ fn test_dense_multiexp() { let start = std::time::Instant::now(); let dense = dense_multiexp( - &pool, &g, &mut v.clone()).unwrap(); + &pool, &g, &v.clone()).unwrap(); let duration_ns = start.elapsed().as_nanos() as f64; println!("{} ns for dense for {} samples", duration_ns, SAMPLES); diff --git a/src/sonic/mod.rs b/src/sonic/mod.rs index 2241a62..4c99ffa 100644 --- a/src/sonic/mod.rs +++ b/src/sonic/mod.rs @@ -11,5 +11,7 @@ pub mod unhelped; mod transcript; +#[cfg(test)] +mod tests; diff --git a/src/sonic/tests/sonics.rs b/src/sonic/tests/sonics.rs new file mode 100644 index 0000000..91d6ddd --- /dev/null +++ b/src/sonic/tests/sonics.rs @@ -0,0 +1,436 @@ +extern crate bellman; +extern crate pairing; +extern crate rand; + +// For randomness (during paramgen and proof generation) +use rand::{thread_rng, Rng}; + +// For benchmarking +use std::time::{Duration, Instant}; + +// Bring in some tools for using pairing-friendly curves +use pairing::{ + Engine +}; + +use pairing::ff::{ + Field, +}; + +// We're going to use the BLS12-381 pairing-friendly elliptic curve. +use pairing::bls12_381::{ + Bls12 +}; + +use pairing::bn256::{ + Bn256 +}; + +// We'll use these interfaces to construct our circuit. +use bellman::{ + Circuit, + ConstraintSystem, + SynthesisError +}; + +// We're going to use the Groth16 proving system. +use bellman::groth16::{ + Proof, + generate_random_parameters, + prepare_verifying_key, + create_random_proof, + verify_proof, +}; + +const MIMC_ROUNDS: usize = 322; + +/// This is our demo circuit for proving knowledge of the +/// preimage of a MiMC hash invocation. +#[derive(Clone)] +struct MiMCDemoNoInputs<'a, E: Engine> { + xl: Option, + xr: Option, + image: Option, + constants: &'a [E::Fr] +} + +/// Our demo circuit implements this `Circuit` trait which +/// is used during paramgen and proving in order to +/// synthesize the constraint system. +impl<'a, E: Engine> Circuit for MiMCDemoNoInputs<'a, E> { + fn synthesize>( + self, + cs: &mut CS + ) -> Result<(), SynthesisError> + { + assert_eq!(self.constants.len(), MIMC_ROUNDS); + + // Allocate the first component of the preimage. + let mut xl_value = self.xl; + let mut xl = cs.alloc(|| "preimage xl", || { + xl_value.ok_or(SynthesisError::AssignmentMissing) + })?; + + // Allocate the second component of the preimage. + let mut xr_value = self.xr; + let mut xr = cs.alloc(|| "preimage xr", || { + xr_value.ok_or(SynthesisError::AssignmentMissing) + })?; + + for i in 0..MIMC_ROUNDS { + // xL, xR := xR + (xL + Ci)^3, xL + let cs = &mut cs.namespace(|| format!("round {}", i)); + + // tmp = (xL + Ci)^2 + let tmp_value = xl_value.map(|mut e| { + e.add_assign(&self.constants[i]); + e.square(); + e + }); + let tmp = cs.alloc(|| "tmp", || { + tmp_value.ok_or(SynthesisError::AssignmentMissing) + })?; + + cs.enforce( + || "tmp = (xL + Ci)^2", + |lc| lc + xl + (self.constants[i], CS::one()), + |lc| lc + xl + (self.constants[i], CS::one()), + |lc| lc + tmp + ); + + // new_xL = xR + (xL + Ci)^3 + // new_xL = xR + tmp * (xL + Ci) + // new_xL - xR = tmp * (xL + Ci) + let new_xl_value = xl_value.map(|mut e| { + e.add_assign(&self.constants[i]); + e.mul_assign(&tmp_value.unwrap()); + e.add_assign(&xr_value.unwrap()); + e + }); + + let new_xl = if i == (MIMC_ROUNDS-1) { + // This is the last round, xL is our image and so + // we use the image + let image_value = self.image; + cs.alloc(|| "image", || { + image_value.ok_or(SynthesisError::AssignmentMissing) + })? + } else { + cs.alloc(|| "new_xl", || { + new_xl_value.ok_or(SynthesisError::AssignmentMissing) + })? + }; + + cs.enforce( + || "new_xL = xR + (xL + Ci)^3", + |lc| lc + tmp, + |lc| lc + xl + (self.constants[i], CS::one()), + |lc| lc + new_xl - xr + ); + + // xR = xL + xr = xl; + xr_value = xl_value; + + // xL = new_xL + xl = new_xl; + xl_value = new_xl_value; + } + + Ok(()) + } +} + +#[test] +fn test_sonic_mimc() { + use pairing::ff::{Field, PrimeField}; + use pairing::{Engine, CurveAffine, CurveProjective}; + use pairing::bls12_381::{Bls12, Fr}; + use std::time::{Instant}; + use bellman::sonic::srs::SRS; + + let srs_x = Fr::from_str("23923").unwrap(); + let srs_alpha = Fr::from_str("23728792").unwrap(); + println!("making srs"); + let start = Instant::now(); + let srs = SRS::::dummy(830564, srs_x, srs_alpha); + println!("done in {:?}", start.elapsed()); + + { + // This may not be cryptographically safe, use + // `OsRng` (for example) in production software. + let rng = &mut thread_rng(); + + // Generate the MiMC round constants + let constants = (0..MIMC_ROUNDS).map(|_| rng.gen()).collect::>(); + let samples: usize = 100; + + let xl = rng.gen(); + let xr = rng.gen(); + let image = mimc::(xl, xr, &constants); + + // Create an instance of our circuit (with the + // witness) + let circuit = MiMCDemoNoInputs { + xl: Some(xl), + xr: Some(xr), + image: Some(image), + constants: &constants + }; + + use bellman::sonic::cs::Basic; + use bellman::sonic::sonic::AdaptorCircuit; + use bellman::sonic::helped::prover::{create_advice_on_srs, create_proof_on_srs}; + use bellman::sonic::helped::{MultiVerifier, get_circuit_parameters}; + use bellman::sonic::helped::helper::{create_aggregate_on_srs}; + + println!("creating proof"); + let start = Instant::now(); + let proof = create_proof_on_srs::(&AdaptorCircuit(circuit.clone()), &srs).unwrap(); + println!("done in {:?}", start.elapsed()); + + println!("creating advice"); + let start = Instant::now(); + let advice = create_advice_on_srs::(&AdaptorCircuit(circuit.clone()), &proof, &srs).unwrap(); + println!("done in {:?}", start.elapsed()); + + println!("creating aggregate for {} proofs", samples); + let start = Instant::now(); + let proofs: Vec<_> = (0..samples).map(|_| (proof.clone(), advice.clone())).collect(); + let aggregate = create_aggregate_on_srs::(&AdaptorCircuit(circuit.clone()), &proofs, &srs); + println!("done in {:?}", start.elapsed()); + + { + let rng = thread_rng(); + let mut verifier = MultiVerifier::::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap(); + println!("verifying 1 proof without advice"); + let start = Instant::now(); + { + for _ in 0..1 { + verifier.add_proof(&proof, &[], |_, _| None); + } + assert_eq!(verifier.check_all(), true); // TODO + } + println!("done in {:?}", start.elapsed()); + } + + { + let rng = thread_rng(); + let mut verifier = MultiVerifier::::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap(); + println!("verifying {} proofs without advice", samples); + let start = Instant::now(); + { + for _ in 0..samples { + verifier.add_proof(&proof, &[], |_, _| None); + } + assert_eq!(verifier.check_all(), true); // TODO + } + println!("done in {:?}", start.elapsed()); + } + + { + let rng = thread_rng(); + let mut verifier = MultiVerifier::::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap(); + println!("verifying 100 proofs with advice"); + let start = Instant::now(); + { + for (ref proof, ref advice) in &proofs { + verifier.add_proof_with_advice(proof, &[], advice); + } + verifier.add_aggregate(&proofs, &aggregate); + assert_eq!(verifier.check_all(), true); // TODO + } + println!("done in {:?}", start.elapsed()); + } + } +} + +#[test] +fn test_inputs_into_sonic_mimc() { + use pairing::ff::{Field, PrimeField}; + use pairing::{Engine, CurveAffine, CurveProjective}; + use pairing::bn256::{Bn256, Fr}; + // use pairing::bls12_381::{Bls12, Fr}; + use std::time::{Instant}; + use bellman::sonic::srs::SRS; + + let srs_x = Fr::from_str("23923").unwrap(); + let srs_alpha = Fr::from_str("23728792").unwrap(); + println!("making srs"); + let start = Instant::now(); + let srs = SRS::::dummy(830564, srs_x, srs_alpha); + println!("done in {:?}", start.elapsed()); + + { + // This may not be cryptographically safe, use + // `OsRng` (for example) in production software. + let rng = &mut thread_rng(); + + // Generate the MiMC round constants + let constants = (0..MIMC_ROUNDS).map(|_| rng.gen()).collect::>(); + let samples: usize = 100; + + let xl = rng.gen(); + let xr = rng.gen(); + let image = mimc::(xl, xr, &constants); + + // Create an instance of our circuit (with the + // witness) + let circuit = MiMCDemo { + xl: Some(xl), + xr: Some(xr), + constants: &constants + }; + + use bellman::sonic::cs::Basic; + use bellman::sonic::sonic::AdaptorCircuit; + use bellman::sonic::helped::prover::{create_advice_on_srs, create_proof_on_srs}; + use bellman::sonic::helped::{MultiVerifier, get_circuit_parameters}; + use bellman::sonic::helped::helper::{create_aggregate_on_srs}; + + let info = get_circuit_parameters::(circuit.clone()).expect("Must get circuit info"); + println!("{:?}", info); + + println!("creating proof"); + let start = Instant::now(); + let proof = create_proof_on_srs::(&AdaptorCircuit(circuit.clone()), &srs).unwrap(); + println!("done in {:?}", start.elapsed()); + + println!("creating advice"); + let start = Instant::now(); + let advice = create_advice_on_srs::(&AdaptorCircuit(circuit.clone()), &proof, &srs).unwrap(); + println!("done in {:?}", start.elapsed()); + + println!("creating aggregate for {} proofs", samples); + let start = Instant::now(); + let proofs: Vec<_> = (0..samples).map(|_| (proof.clone(), advice.clone())).collect(); + let aggregate = create_aggregate_on_srs::(&AdaptorCircuit(circuit.clone()), &proofs, &srs); + println!("done in {:?}", start.elapsed()); + + { + let rng = thread_rng(); + let mut verifier = MultiVerifier::::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap(); + println!("verifying 1 proof without advice"); + let start = Instant::now(); + { + for _ in 0..1 { + verifier.add_proof(&proof, &[image], |_, _| None); + } + assert_eq!(verifier.check_all(), true); // TODO + } + println!("done in {:?}", start.elapsed()); + } + + { + let rng = thread_rng(); + let mut verifier = MultiVerifier::::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap(); + println!("verifying {} proofs without advice", samples); + let start = Instant::now(); + { + for _ in 0..samples { + verifier.add_proof(&proof, &[image], |_, _| None); + } + assert_eq!(verifier.check_all(), true); // TODO + } + println!("done in {:?}", start.elapsed()); + } + + { + let rng = thread_rng(); + let mut verifier = MultiVerifier::::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap(); + println!("verifying 100 proofs with advice and aggregate"); + let start = Instant::now(); + { + for (ref proof, ref advice) in &proofs { + verifier.add_proof_with_advice(proof, &[image], advice); + } + verifier.add_aggregate(&proofs, &aggregate); + assert_eq!(verifier.check_all(), true); // TODO + } + println!("done in {:?}", start.elapsed()); + } + } +} + +#[test] +fn test_high_level_sonic_api() { + use pairing::bn256::{Bn256}; + use std::time::{Instant}; + use bellman::sonic::helped::{ + generate_random_parameters, + verify_aggregate, + verify_proofs, + create_proof, + create_advice, + create_aggregate, + get_circuit_parameters + }; + + { + // This may not be cryptographically safe, use + // `OsRng` (for example) in production software. + let mut rng = &mut thread_rng(); + + // Generate the MiMC round constants + let constants = (0..MIMC_ROUNDS).map(|_| rng.gen()).collect::>(); + let samples: usize = 100; + + let xl = rng.gen(); + let xr = rng.gen(); + let image = mimc::(xl, xr, &constants); + + // Create an instance of our circuit (with the + // witness) + let circuit = MiMCDemo { + xl: Some(xl), + xr: Some(xr), + constants: &constants + }; + + let info = get_circuit_parameters::(circuit.clone()).expect("Must get circuit info"); + println!("{:?}", info); + + let params = generate_random_parameters(circuit.clone(), &mut rng).unwrap(); + + println!("creating proof"); + let start = Instant::now(); + let proof = create_proof(circuit.clone(), ¶ms).unwrap(); + println!("done in {:?}", start.elapsed()); + + println!("creating advice"); + let start = Instant::now(); + let advice = create_advice(circuit.clone(), &proof, ¶ms).unwrap(); + println!("done in {:?}", start.elapsed()); + + println!("creating aggregate for {} proofs", samples); + let start = Instant::now(); + let proofs: Vec<_> = (0..samples).map(|_| (proof.clone(), advice.clone())).collect(); + + let aggregate = create_aggregate::(circuit.clone(), &proofs, ¶ms); + println!("done in {:?}", start.elapsed()); + + { + println!("verifying 1 proof without advice"); + let rng = thread_rng(); + let start = Instant::now(); + assert_eq!(verify_proofs(&vec![proof.clone()], &vec![vec![image.clone()]], circuit.clone(), rng, ¶ms).unwrap(), true); + println!("done in {:?}", start.elapsed()); + } + + { + println!("verifying {} proofs without advice", samples); + let rng = thread_rng(); + let start = Instant::now(); + assert_eq!(verify_proofs(&vec![proof.clone(); 100], &vec![vec![image.clone()]; 100], circuit.clone(), rng, ¶ms).unwrap(), true); + println!("done in {:?}", start.elapsed()); + } + + { + println!("verifying 100 proofs with advice and aggregate"); + let rng = thread_rng(); + let start = Instant::now(); + assert_eq!(verify_aggregate(&vec![(proof.clone(), advice.clone()); 100], &aggregate, &vec![vec![image.clone()]; 100], circuit.clone(), rng, ¶ms).unwrap(), true); + println!("done in {:?}", start.elapsed()); + } + } +} \ No newline at end of file diff --git a/tests/mimc.rs b/tests/mimc.rs index 9446145..89da2eb 100644 --- a/tests/mimc.rs +++ b/tests/mimc.rs @@ -116,12 +116,12 @@ impl<'a, E: Engine> Circuit for MiMCDemo<'a, E> { let cs = &mut cs.namespace(|| format!("round {}", i)); // tmp = (xL + Ci)^2 - let mut tmp_value = xl_value.map(|mut e| { + let tmp_value = xl_value.map(|mut e| { e.add_assign(&self.constants[i]); e.square(); e }); - let mut tmp = cs.alloc(|| "tmp", || { + let tmp = cs.alloc(|| "tmp", || { tmp_value.ok_or(SynthesisError::AssignmentMissing) })?; @@ -135,14 +135,14 @@ impl<'a, E: Engine> Circuit for MiMCDemo<'a, E> { // new_xL = xR + (xL + Ci)^3 // new_xL = xR + tmp * (xL + Ci) // new_xL - xR = tmp * (xL + Ci) - let mut new_xl_value = xl_value.map(|mut e| { + let new_xl_value = xl_value.map(|mut e| { e.add_assign(&self.constants[i]); e.mul_assign(&tmp_value.unwrap()); e.add_assign(&xr_value.unwrap()); e }); - let mut new_xl = if i == (MIMC_ROUNDS-1) { + let new_xl = if i == (MIMC_ROUNDS-1) { // This is the last round, xL is our image and so // we allocate a public input. cs.alloc_input(|| "image", || { @@ -341,394 +341,3 @@ fn test_mimc_bn256() { println!("Average proving time: {:?} seconds", proving_avg); println!("Average verifying time: {:?} seconds", verifying_avg); } - -/// This is our demo circuit for proving knowledge of the -/// preimage of a MiMC hash invocation. -#[derive(Clone)] -struct MiMCDemoNoInputs<'a, E: Engine> { - xl: Option, - xr: Option, - image: Option, - constants: &'a [E::Fr] -} - -/// Our demo circuit implements this `Circuit` trait which -/// is used during paramgen and proving in order to -/// synthesize the constraint system. -impl<'a, E: Engine> Circuit for MiMCDemoNoInputs<'a, E> { - fn synthesize>( - self, - cs: &mut CS - ) -> Result<(), SynthesisError> - { - assert_eq!(self.constants.len(), MIMC_ROUNDS); - - // Allocate the first component of the preimage. - let mut xl_value = self.xl; - let mut xl = cs.alloc(|| "preimage xl", || { - xl_value.ok_or(SynthesisError::AssignmentMissing) - })?; - - // Allocate the second component of the preimage. - let mut xr_value = self.xr; - let mut xr = cs.alloc(|| "preimage xr", || { - xr_value.ok_or(SynthesisError::AssignmentMissing) - })?; - - for i in 0..MIMC_ROUNDS { - // xL, xR := xR + (xL + Ci)^3, xL - let cs = &mut cs.namespace(|| format!("round {}", i)); - - // tmp = (xL + Ci)^2 - let mut tmp_value = xl_value.map(|mut e| { - e.add_assign(&self.constants[i]); - e.square(); - e - }); - let mut tmp = cs.alloc(|| "tmp", || { - tmp_value.ok_or(SynthesisError::AssignmentMissing) - })?; - - cs.enforce( - || "tmp = (xL + Ci)^2", - |lc| lc + xl + (self.constants[i], CS::one()), - |lc| lc + xl + (self.constants[i], CS::one()), - |lc| lc + tmp - ); - - // new_xL = xR + (xL + Ci)^3 - // new_xL = xR + tmp * (xL + Ci) - // new_xL - xR = tmp * (xL + Ci) - let mut new_xl_value = xl_value.map(|mut e| { - e.add_assign(&self.constants[i]); - e.mul_assign(&tmp_value.unwrap()); - e.add_assign(&xr_value.unwrap()); - e - }); - - let mut new_xl = if i == (MIMC_ROUNDS-1) { - // This is the last round, xL is our image and so - // we use the image - let image_value = self.image; - cs.alloc(|| "image", || { - image_value.ok_or(SynthesisError::AssignmentMissing) - })? - } else { - cs.alloc(|| "new_xl", || { - new_xl_value.ok_or(SynthesisError::AssignmentMissing) - })? - }; - - cs.enforce( - || "new_xL = xR + (xL + Ci)^3", - |lc| lc + tmp, - |lc| lc + xl + (self.constants[i], CS::one()), - |lc| lc + new_xl - xr - ); - - // xR = xL - xr = xl; - xr_value = xl_value; - - // xL = new_xL - xl = new_xl; - xl_value = new_xl_value; - } - - Ok(()) - } -} - -#[test] -fn test_sonic_mimc() { - use pairing::ff::{Field, PrimeField}; - use pairing::{Engine, CurveAffine, CurveProjective}; - use pairing::bls12_381::{Bls12, Fr}; - use std::time::{Instant}; - use bellman::sonic::srs::SRS; - - let srs_x = Fr::from_str("23923").unwrap(); - let srs_alpha = Fr::from_str("23728792").unwrap(); - println!("making srs"); - let start = Instant::now(); - let srs = SRS::::dummy(830564, srs_x, srs_alpha); - println!("done in {:?}", start.elapsed()); - - { - // This may not be cryptographically safe, use - // `OsRng` (for example) in production software. - let rng = &mut thread_rng(); - - // Generate the MiMC round constants - let constants = (0..MIMC_ROUNDS).map(|_| rng.gen()).collect::>(); - let samples: usize = 100; - - let xl = rng.gen(); - let xr = rng.gen(); - let image = mimc::(xl, xr, &constants); - - // Create an instance of our circuit (with the - // witness) - let circuit = MiMCDemoNoInputs { - xl: Some(xl), - xr: Some(xr), - image: Some(image), - constants: &constants - }; - - use bellman::sonic::cs::Basic; - use bellman::sonic::sonic::AdaptorCircuit; - use bellman::sonic::helped::prover::{create_advice_on_srs, create_proof_on_srs}; - use bellman::sonic::helped::{MultiVerifier, get_circuit_parameters}; - use bellman::sonic::helped::helper::{create_aggregate_on_srs}; - - println!("creating proof"); - let start = Instant::now(); - let proof = create_proof_on_srs::(&AdaptorCircuit(circuit.clone()), &srs).unwrap(); - println!("done in {:?}", start.elapsed()); - - println!("creating advice"); - let start = Instant::now(); - let advice = create_advice_on_srs::(&AdaptorCircuit(circuit.clone()), &proof, &srs).unwrap(); - println!("done in {:?}", start.elapsed()); - - println!("creating aggregate for {} proofs", samples); - let start = Instant::now(); - let proofs: Vec<_> = (0..samples).map(|_| (proof.clone(), advice.clone())).collect(); - let aggregate = create_aggregate_on_srs::(&AdaptorCircuit(circuit.clone()), &proofs, &srs); - println!("done in {:?}", start.elapsed()); - - { - let rng = thread_rng(); - let mut verifier = MultiVerifier::::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap(); - println!("verifying 1 proof without advice"); - let start = Instant::now(); - { - for _ in 0..1 { - verifier.add_proof(&proof, &[], |_, _| None); - } - assert_eq!(verifier.check_all(), true); // TODO - } - println!("done in {:?}", start.elapsed()); - } - - { - let rng = thread_rng(); - let mut verifier = MultiVerifier::::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap(); - println!("verifying {} proofs without advice", samples); - let start = Instant::now(); - { - for _ in 0..samples { - verifier.add_proof(&proof, &[], |_, _| None); - } - assert_eq!(verifier.check_all(), true); // TODO - } - println!("done in {:?}", start.elapsed()); - } - - { - let rng = thread_rng(); - let mut verifier = MultiVerifier::::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap(); - println!("verifying 100 proofs with advice"); - let start = Instant::now(); - { - for (ref proof, ref advice) in &proofs { - verifier.add_proof_with_advice(proof, &[], advice); - } - verifier.add_aggregate(&proofs, &aggregate); - assert_eq!(verifier.check_all(), true); // TODO - } - println!("done in {:?}", start.elapsed()); - } - } -} - -#[test] -fn test_inputs_into_sonic_mimc() { - use pairing::ff::{Field, PrimeField}; - use pairing::{Engine, CurveAffine, CurveProjective}; - use pairing::bn256::{Bn256, Fr}; - // use pairing::bls12_381::{Bls12, Fr}; - use std::time::{Instant}; - use bellman::sonic::srs::SRS; - - let srs_x = Fr::from_str("23923").unwrap(); - let srs_alpha = Fr::from_str("23728792").unwrap(); - println!("making srs"); - let start = Instant::now(); - let srs = SRS::::dummy(830564, srs_x, srs_alpha); - println!("done in {:?}", start.elapsed()); - - { - // This may not be cryptographically safe, use - // `OsRng` (for example) in production software. - let rng = &mut thread_rng(); - - // Generate the MiMC round constants - let constants = (0..MIMC_ROUNDS).map(|_| rng.gen()).collect::>(); - let samples: usize = 100; - - let xl = rng.gen(); - let xr = rng.gen(); - let image = mimc::(xl, xr, &constants); - - // Create an instance of our circuit (with the - // witness) - let circuit = MiMCDemo { - xl: Some(xl), - xr: Some(xr), - constants: &constants - }; - - use bellman::sonic::cs::Basic; - use bellman::sonic::sonic::AdaptorCircuit; - use bellman::sonic::helped::prover::{create_advice_on_srs, create_proof_on_srs}; - use bellman::sonic::helped::{MultiVerifier, get_circuit_parameters}; - use bellman::sonic::helped::helper::{create_aggregate_on_srs}; - - let info = get_circuit_parameters::(circuit.clone()).expect("Must get circuit info"); - println!("{:?}", info); - - println!("creating proof"); - let start = Instant::now(); - let proof = create_proof_on_srs::(&AdaptorCircuit(circuit.clone()), &srs).unwrap(); - println!("done in {:?}", start.elapsed()); - - println!("creating advice"); - let start = Instant::now(); - let advice = create_advice_on_srs::(&AdaptorCircuit(circuit.clone()), &proof, &srs).unwrap(); - println!("done in {:?}", start.elapsed()); - - println!("creating aggregate for {} proofs", samples); - let start = Instant::now(); - let proofs: Vec<_> = (0..samples).map(|_| (proof.clone(), advice.clone())).collect(); - let aggregate = create_aggregate_on_srs::(&AdaptorCircuit(circuit.clone()), &proofs, &srs); - println!("done in {:?}", start.elapsed()); - - { - let rng = thread_rng(); - let mut verifier = MultiVerifier::::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap(); - println!("verifying 1 proof without advice"); - let start = Instant::now(); - { - for _ in 0..1 { - verifier.add_proof(&proof, &[image], |_, _| None); - } - assert_eq!(verifier.check_all(), true); // TODO - } - println!("done in {:?}", start.elapsed()); - } - - { - let rng = thread_rng(); - let mut verifier = MultiVerifier::::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap(); - println!("verifying {} proofs without advice", samples); - let start = Instant::now(); - { - for _ in 0..samples { - verifier.add_proof(&proof, &[image], |_, _| None); - } - assert_eq!(verifier.check_all(), true); // TODO - } - println!("done in {:?}", start.elapsed()); - } - - { - let rng = thread_rng(); - let mut verifier = MultiVerifier::::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap(); - println!("verifying 100 proofs with advice and aggregate"); - let start = Instant::now(); - { - for (ref proof, ref advice) in &proofs { - verifier.add_proof_with_advice(proof, &[image], advice); - } - verifier.add_aggregate(&proofs, &aggregate); - assert_eq!(verifier.check_all(), true); // TODO - } - println!("done in {:?}", start.elapsed()); - } - } -} - -#[test] -fn test_high_level_sonic_api() { - use pairing::bn256::{Bn256}; - use std::time::{Instant}; - use bellman::sonic::helped::{ - generate_random_parameters, - verify_aggregate, - verify_proofs, - create_proof, - create_advice, - create_aggregate, - get_circuit_parameters - }; - - { - // This may not be cryptographically safe, use - // `OsRng` (for example) in production software. - let mut rng = &mut thread_rng(); - - // Generate the MiMC round constants - let constants = (0..MIMC_ROUNDS).map(|_| rng.gen()).collect::>(); - let samples: usize = 100; - - let xl = rng.gen(); - let xr = rng.gen(); - let image = mimc::(xl, xr, &constants); - - // Create an instance of our circuit (with the - // witness) - let circuit = MiMCDemo { - xl: Some(xl), - xr: Some(xr), - constants: &constants - }; - - let info = get_circuit_parameters::(circuit.clone()).expect("Must get circuit info"); - println!("{:?}", info); - - let params = generate_random_parameters(circuit.clone(), &mut rng).unwrap(); - - println!("creating proof"); - let start = Instant::now(); - let proof = create_proof(circuit.clone(), ¶ms).unwrap(); - println!("done in {:?}", start.elapsed()); - - println!("creating advice"); - let start = Instant::now(); - let advice = create_advice(circuit.clone(), &proof, ¶ms).unwrap(); - println!("done in {:?}", start.elapsed()); - - println!("creating aggregate for {} proofs", samples); - let start = Instant::now(); - let proofs: Vec<_> = (0..samples).map(|_| (proof.clone(), advice.clone())).collect(); - - let aggregate = create_aggregate::(circuit.clone(), &proofs, ¶ms); - println!("done in {:?}", start.elapsed()); - - { - println!("verifying 1 proof without advice"); - let rng = thread_rng(); - let start = Instant::now(); - assert_eq!(verify_proofs(&vec![proof.clone()], &vec![vec![image.clone()]], circuit.clone(), rng, ¶ms).unwrap(), true); - println!("done in {:?}", start.elapsed()); - } - - { - println!("verifying {} proofs without advice", samples); - let rng = thread_rng(); - let start = Instant::now(); - assert_eq!(verify_proofs(&vec![proof.clone(); 100], &vec![vec![image.clone()]; 100], circuit.clone(), rng, ¶ms).unwrap(), true); - println!("done in {:?}", start.elapsed()); - } - - { - println!("verifying 100 proofs with advice and aggregate"); - let rng = thread_rng(); - let start = Instant::now(); - assert_eq!(verify_aggregate(&vec![(proof.clone(), advice.clone()); 100], &aggregate, &vec![vec![image.clone()]; 100], circuit.clone(), rng, ¶ms).unwrap(), true); - println!("done in {:?}", start.elapsed()); - } - } -} \ No newline at end of file