introduce high-level verifier api
This commit is contained in:
parent
2327a4527b
commit
f98b6eaaf4
@ -28,7 +28,7 @@ use super::{
|
||||
use super::multicore::Worker;
|
||||
pub use super::group::*;
|
||||
|
||||
#[feature(not(singlecore))]
|
||||
#[cfg(not(feature = "singlecore"))]
|
||||
use super::parallel_fft::*;
|
||||
|
||||
pub struct EvaluationDomain<E: Engine, G: Group<E>> {
|
||||
|
102
src/sonic/helped/adapted_verifier.rs
Normal file
102
src/sonic/helped/adapted_verifier.rs
Normal file
@ -0,0 +1,102 @@
|
||||
use ff::{Field};
|
||||
use pairing::{Engine, CurveProjective};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use rand::{Rand, Rng};
|
||||
|
||||
use super::{Proof, SxyAdvice};
|
||||
use super::batch::Batch;
|
||||
use super::poly::{SxEval, SyEval};
|
||||
use super::parameters::{Parameters};
|
||||
use super::helper::{Aggregate};
|
||||
|
||||
use crate::SynthesisError;
|
||||
|
||||
use crate::sonic::transcript::{Transcript, TranscriptProtocol};
|
||||
use crate::sonic::util::*;
|
||||
use crate::sonic::cs::{Backend, SynthesisDriver};
|
||||
use crate::{Circuit};
|
||||
use crate::sonic::sonic::AdaptorCircuit;
|
||||
use crate::sonic::srs::SRS;
|
||||
use crate::sonic::cs::Nonassigning;
|
||||
use super::verifier::verify_aggregate_on_srs as verify_aggregate_on_srs_sonic_circuit;
|
||||
use super::verifier::verify_proofs_on_srs as verify_proofs_on_srs_sonic_circuit;
|
||||
|
||||
pub fn verify_proofs<E: Engine, C: Circuit<E> + Clone, R: Rng>(
|
||||
proofs: &[Proof<E>],
|
||||
inputs: &[Vec<E::Fr>],
|
||||
circuit: C,
|
||||
rng: R,
|
||||
params: &Parameters<E>,
|
||||
) -> Result<bool, SynthesisError>
|
||||
{
|
||||
let adapted_circuit = AdaptorCircuit(circuit);
|
||||
|
||||
verify_proofs_on_srs_sonic_circuit::<_, _, Nonassigning, _>(proofs, inputs, adapted_circuit, rng, ¶ms.srs)
|
||||
}
|
||||
|
||||
/// Check multiple proofs with aggregation. Verifier's work is
|
||||
/// not succint due to `S(X, Y)` evaluation
|
||||
pub fn verify_aggregate<E: Engine, C: Circuit<E> + Clone, R: Rng>(
|
||||
proofs: &[(Proof<E>, SxyAdvice<E>)],
|
||||
aggregate: &Aggregate<E>,
|
||||
inputs: &[Vec<E::Fr>],
|
||||
circuit: C,
|
||||
rng: R,
|
||||
params: &Parameters<E>,
|
||||
) -> Result<bool, SynthesisError> {
|
||||
let adapted_circuit = AdaptorCircuit(circuit);
|
||||
|
||||
verify_aggregate_on_srs_sonic_circuit::<_, _, Nonassigning, _>(proofs, aggregate, inputs, adapted_circuit, rng, ¶ms.srs)
|
||||
}
|
||||
|
||||
|
||||
// #[test]
|
||||
// fn my_fun_circuit_test() {
|
||||
// use ff::PrimeField;
|
||||
// use pairing::bls12_381::{Bls12, Fr};
|
||||
// use super::*;
|
||||
// use crate::sonic::cs::{Basic, ConstraintSystem, LinearCombination};
|
||||
|
||||
// struct MyCircuit;
|
||||
|
||||
// impl<E: Engine> Circuit<E> for MyCircuit {
|
||||
// fn synthesize<CS: ConstraintSystem<E>>(&self, cs: &mut CS) -> Result<(), SynthesisError> {
|
||||
// let (a, b, _) = cs.multiply(|| {
|
||||
// Ok((
|
||||
// E::Fr::from_str("10").unwrap(),
|
||||
// E::Fr::from_str("20").unwrap(),
|
||||
// E::Fr::from_str("200").unwrap(),
|
||||
// ))
|
||||
// })?;
|
||||
|
||||
// cs.enforce_zero(LinearCombination::from(a) + a - b);
|
||||
|
||||
// //let multiplier = cs.alloc_input(|| Ok(E::Fr::from_str("20").unwrap()))?;
|
||||
|
||||
// //cs.enforce_zero(LinearCombination::from(b) - multiplier);
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
// }
|
||||
|
||||
// let srs = SRS::<Bls12>::new(
|
||||
// 20,
|
||||
// Fr::from_str("22222").unwrap(),
|
||||
// Fr::from_str("33333333").unwrap(),
|
||||
// );
|
||||
// let proof = create_proof_on_srs::<Bls12, _, Basic>(&MyCircuit, &srs).unwrap();
|
||||
|
||||
// use std::time::{Instant};
|
||||
// let start = Instant::now();
|
||||
// let mut batch = MultiVerifier::<Bls12, _, Basic>::new(MyCircuit, &srs).unwrap();
|
||||
|
||||
// for _ in 0..1 {
|
||||
// batch.add_proof(&proof, &[/*Fr::from_str("20").unwrap()*/], |_, _| None);
|
||||
// }
|
||||
|
||||
// assert!(batch.check_all());
|
||||
|
||||
// let elapsed = start.elapsed();
|
||||
// println!("time to verify: {:?}", elapsed);
|
||||
// }
|
@ -482,7 +482,7 @@ pub fn generate_srs<E: Engine>(
|
||||
let mut x_powers_negative = vec![Scalar::<E>(E::Fr::zero()); d];
|
||||
{
|
||||
// Compute powers of tau
|
||||
if verbose {eprintln!("computing powers of tau...")};
|
||||
if verbose {eprintln!("computing powers of x...")};
|
||||
|
||||
let start = std::time::Instant::now();
|
||||
|
||||
|
@ -12,6 +12,7 @@ mod helper;
|
||||
mod parameters;
|
||||
mod generator;
|
||||
mod adapted_prover;
|
||||
mod adapted_verifier;
|
||||
|
||||
pub mod prover;
|
||||
|
||||
@ -36,3 +37,8 @@ pub use self::adapted_prover::{
|
||||
create_proof,
|
||||
create_proof_on_srs,
|
||||
};
|
||||
|
||||
pub use self::adapted_verifier::{
|
||||
verify_proofs,
|
||||
verify_aggregate
|
||||
};
|
@ -382,6 +382,7 @@ fn my_fun_circuit_test() {
|
||||
use pairing::bls12_381::{Bls12, Fr};
|
||||
use super::*;
|
||||
use crate::sonic::cs::{Basic, ConstraintSystem, LinearCombination};
|
||||
use rand::{thread_rng};
|
||||
|
||||
struct MyCircuit;
|
||||
|
||||
@ -414,7 +415,8 @@ fn my_fun_circuit_test() {
|
||||
|
||||
use std::time::{Instant};
|
||||
let start = Instant::now();
|
||||
let mut batch = MultiVerifier::<Bls12, _, Basic>::new(MyCircuit, &srs).unwrap();
|
||||
let rng = thread_rng();
|
||||
let mut batch = MultiVerifier::<Bls12, _, Basic, _>::new(MyCircuit, &srs, rng).unwrap();
|
||||
|
||||
for _ in 0..1 {
|
||||
batch.add_proof(&proof, &[/*Fr::from_str("20").unwrap()*/], |_, _| None);
|
||||
|
@ -1,11 +1,13 @@
|
||||
use ff::{Field};
|
||||
use pairing::{Engine, CurveProjective};
|
||||
use std::marker::PhantomData;
|
||||
use rand::{Rand, Rng};
|
||||
|
||||
use super::{Proof, SxyAdvice};
|
||||
use super::batch::Batch;
|
||||
use super::poly::{SxEval, SyEval};
|
||||
use super::helper::Aggregate;
|
||||
use super::parameters::{Parameters};
|
||||
|
||||
use crate::SynthesisError;
|
||||
|
||||
@ -15,17 +17,19 @@ use crate::sonic::cs::{Backend, SynthesisDriver};
|
||||
use crate::sonic::cs::{Circuit, Variable, Coeff};
|
||||
use crate::sonic::srs::SRS;
|
||||
|
||||
pub struct MultiVerifier<E: Engine, C: Circuit<E>, S: SynthesisDriver> {
|
||||
pub struct MultiVerifier<E: Engine, C: Circuit<E>, S: SynthesisDriver, R: Rng> {
|
||||
circuit: C,
|
||||
batch: Batch<E>,
|
||||
k_map: Vec<usize>,
|
||||
n: usize,
|
||||
q: usize,
|
||||
randomness_source: R,
|
||||
_marker: PhantomData<(E, S)>
|
||||
}
|
||||
|
||||
impl<E: Engine, C: Circuit<E>, S: SynthesisDriver> MultiVerifier<E, C, S> {
|
||||
pub fn new(circuit: C, srs: &SRS<E>) -> Result<Self, SynthesisError> {
|
||||
impl<E: Engine, C: Circuit<E>, S: SynthesisDriver, R: Rng> MultiVerifier<E, C, S, R> {
|
||||
// This constructor consumes randomness source cause it's later used internally
|
||||
pub fn new(circuit: C, srs: &SRS<E>, rng: R) -> Result<Self, SynthesisError> {
|
||||
struct Preprocess<E: Engine> {
|
||||
k_map: Vec<usize>,
|
||||
n: usize,
|
||||
@ -57,6 +61,7 @@ impl<E: Engine, C: Circuit<E>, S: SynthesisDriver> MultiVerifier<E, C, S> {
|
||||
k_map: preprocess.k_map,
|
||||
n: preprocess.n,
|
||||
q: preprocess.q,
|
||||
randomness_source: rng,
|
||||
_marker: PhantomData
|
||||
})
|
||||
}
|
||||
@ -93,10 +98,7 @@ impl<E: Engine, C: Circuit<E>, S: SynthesisDriver> MultiVerifier<E, C, S> {
|
||||
};
|
||||
|
||||
{
|
||||
// TODO: like everything else doing this, this isn't really random
|
||||
let random: E::Fr;
|
||||
let mut transcript = transcript.clone();
|
||||
random = transcript.get_challenge_scalar();
|
||||
let random: E::Fr = self.randomness_source.gen();
|
||||
|
||||
self.batch.add_opening(aggregate.opening, random, w);
|
||||
self.batch.add_commitment(aggregate.c, random);
|
||||
@ -104,20 +106,14 @@ impl<E: Engine, C: Circuit<E>, S: SynthesisDriver> MultiVerifier<E, C, S> {
|
||||
}
|
||||
|
||||
for ((opening, value), &y) in aggregate.c_openings.iter().zip(y_values.iter()) {
|
||||
let random: E::Fr;
|
||||
let mut transcript = transcript.clone();
|
||||
random = transcript.get_challenge_scalar();
|
||||
let random: E::Fr = self.randomness_source.gen();
|
||||
|
||||
self.batch.add_opening(*opening, random, y);
|
||||
self.batch.add_commitment(aggregate.c, random);
|
||||
self.batch.add_opening_value(*value, random);
|
||||
}
|
||||
|
||||
let random: E::Fr;
|
||||
{
|
||||
let mut transcript = transcript.clone();
|
||||
random = transcript.get_challenge_scalar();
|
||||
}
|
||||
let random: E::Fr = self.randomness_source.gen();
|
||||
|
||||
let mut expected_value = E::Fr::zero();
|
||||
for ((_, advice), c_opening) in proofs.iter().zip(aggregate.c_openings.iter()) {
|
||||
@ -139,6 +135,7 @@ impl<E: Engine, C: Circuit<E>, S: SynthesisDriver> MultiVerifier<E, C, S> {
|
||||
self.batch.add_opening(aggregate.s_opening, random, z);
|
||||
}
|
||||
|
||||
/// Caller must ensure to add aggregate after adding a proof
|
||||
pub fn add_proof_with_advice(
|
||||
&mut self,
|
||||
proof: &Proof<E>,
|
||||
@ -160,7 +157,7 @@ impl<E: Engine, C: Circuit<E>, S: SynthesisDriver> MultiVerifier<E, C, S> {
|
||||
transcript.commit_point(&advice.opening);
|
||||
transcript.commit_point(&advice.s);
|
||||
transcript.commit_scalar(&advice.szy);
|
||||
let random: E::Fr = transcript.get_challenge_scalar();
|
||||
let random: E::Fr = self.randomness_source.gen();
|
||||
|
||||
self.batch.add_opening(advice.opening, random, z);
|
||||
self.batch.add_commitment(advice.s, random);
|
||||
@ -196,7 +193,7 @@ impl<E: Engine, C: Circuit<E>, S: SynthesisDriver> MultiVerifier<E, C, S> {
|
||||
// First, the easy one. Let's open up proof.r at zy, using proof.zy_opening
|
||||
// as the evidence and proof.rzy as the opening.
|
||||
{
|
||||
let random = transcript.get_challenge_scalar();
|
||||
let random: E::Fr = self.randomness_source.gen();
|
||||
let mut zy = z;
|
||||
zy.mul_assign(&y);
|
||||
self.batch.add_opening(proof.zy_opening, random, zy);
|
||||
@ -235,7 +232,7 @@ impl<E: Engine, C: Circuit<E>, S: SynthesisDriver> MultiVerifier<E, C, S> {
|
||||
// We open these both at the same time by keeping their commitments
|
||||
// linearly independent (using r1).
|
||||
{
|
||||
let mut random = transcript.get_challenge_scalar();
|
||||
let mut random: E::Fr = self.randomness_source.gen();
|
||||
|
||||
self.batch.add_opening(proof.z_opening, random, z);
|
||||
self.batch.add_opening_value(tzy, random);
|
||||
@ -264,3 +261,73 @@ impl<E: Engine, C: Circuit<E>, S: SynthesisDriver> MultiVerifier<E, C, S> {
|
||||
self.batch.check_all()
|
||||
}
|
||||
}
|
||||
|
||||
/// Check multiple proofs without aggregation. Verifier's work is
|
||||
/// not succint due to `S(X, Y)` evaluation
|
||||
pub fn verify_proofs<E: Engine, C: Circuit<E>, S: SynthesisDriver, R: Rng>(
|
||||
proofs: &[Proof<E>],
|
||||
inputs: &[Vec<E::Fr>],
|
||||
circuit: C,
|
||||
rng: R,
|
||||
params: &Parameters<E>,
|
||||
) -> Result<bool, SynthesisError> {
|
||||
verify_proofs_on_srs::<E, C, S, R>(proofs, inputs, circuit, rng, ¶ms.srs)
|
||||
}
|
||||
|
||||
/// Check multiple proofs without aggregation. Verifier's work is
|
||||
/// not succint due to `S(X, Y)` evaluation
|
||||
pub fn verify_proofs_on_srs<E: Engine, C: Circuit<E>, S: SynthesisDriver, R: Rng>(
|
||||
proofs: &[Proof<E>],
|
||||
inputs: &[Vec<E::Fr>],
|
||||
circuit: C,
|
||||
rng: R,
|
||||
srs: &SRS<E>,
|
||||
) -> Result<bool, SynthesisError> {
|
||||
let mut verifier = MultiVerifier::<E, C, S, R>::new(circuit, srs, rng)?;
|
||||
let expected_inputs_size = verifier.get_k_map().len() - 1;
|
||||
for (proof, inputs) in proofs.iter().zip(inputs.iter()) {
|
||||
if inputs.len() != expected_inputs_size {
|
||||
return Err(SynthesisError::Unsatisfiable);
|
||||
}
|
||||
verifier.add_proof(proof, &inputs, |_, _| None);
|
||||
}
|
||||
|
||||
Ok(verifier.check_all())
|
||||
}
|
||||
|
||||
/// Check multiple proofs with aggregation. Verifier's work is
|
||||
/// not succint due to `S(X, Y)` evaluation
|
||||
pub fn verify_aggregate<E: Engine, C: Circuit<E>, S: SynthesisDriver,R: Rng>(
|
||||
proofs: &[(Proof<E>, SxyAdvice<E>)],
|
||||
aggregate: &Aggregate<E>,
|
||||
inputs: &[Vec<E::Fr>],
|
||||
circuit: C,
|
||||
rng: R,
|
||||
params: &Parameters<E>,
|
||||
) -> Result<bool, SynthesisError> {
|
||||
verify_aggregate_on_srs::<E, C, S, R>(proofs, aggregate, inputs, circuit, rng, ¶ms.srs)
|
||||
}
|
||||
|
||||
/// Check multiple proofs with aggregation. Verifier's work is
|
||||
/// not succint due to `S(X, Y)` evaluation
|
||||
pub fn verify_aggregate_on_srs<E: Engine, C: Circuit<E>, S: SynthesisDriver, R: Rng>(
|
||||
proofs: &[(Proof<E>, SxyAdvice<E>)],
|
||||
aggregate: &Aggregate<E>,
|
||||
inputs: &[Vec<E::Fr>],
|
||||
circuit: C,
|
||||
rng: R,
|
||||
srs: &SRS<E>,
|
||||
) -> Result<bool, SynthesisError> {
|
||||
let mut verifier = MultiVerifier::<E, C, S, R>::new(circuit, srs, rng)?;
|
||||
let expected_inputs_size = verifier.get_k_map().len() - 1;
|
||||
for ((proof, advice), inputs) in proofs.iter().zip(inputs.iter()) {
|
||||
if inputs.len() != expected_inputs_size {
|
||||
return Err(SynthesisError::Unsatisfiable);
|
||||
}
|
||||
verifier.add_proof_with_advice(proof, &inputs, &advice);
|
||||
}
|
||||
verifier.add_aggregate(proofs, aggregate);
|
||||
|
||||
Ok(verifier.check_all())
|
||||
}
|
||||
|
||||
|
@ -499,7 +499,8 @@ fn test_sonic_mimc() {
|
||||
println!("done in {:?}", start.elapsed());
|
||||
|
||||
{
|
||||
let mut verifier = MultiVerifier::<Bls12, _, Basic>::new(AdaptorCircuit(circuit.clone()), &srs).unwrap();
|
||||
let rng = thread_rng();
|
||||
let mut verifier = MultiVerifier::<Bls12, _, Basic, _>::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap();
|
||||
println!("verifying 1 proof without advice");
|
||||
let start = Instant::now();
|
||||
{
|
||||
@ -512,7 +513,8 @@ fn test_sonic_mimc() {
|
||||
}
|
||||
|
||||
{
|
||||
let mut verifier = MultiVerifier::<Bls12, _, Basic>::new(AdaptorCircuit(circuit.clone()), &srs).unwrap();
|
||||
let rng = thread_rng();
|
||||
let mut verifier = MultiVerifier::<Bls12, _, Basic, _>::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap();
|
||||
println!("verifying {} proofs without advice", samples);
|
||||
let start = Instant::now();
|
||||
{
|
||||
@ -525,7 +527,8 @@ fn test_sonic_mimc() {
|
||||
}
|
||||
|
||||
{
|
||||
let mut verifier = MultiVerifier::<Bls12, _, Basic>::new(AdaptorCircuit(circuit.clone()), &srs).unwrap();
|
||||
let rng = thread_rng();
|
||||
let mut verifier = MultiVerifier::<Bls12, _, Basic, _>::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap();
|
||||
println!("verifying 100 proofs with advice");
|
||||
let start = Instant::now();
|
||||
{
|
||||
@ -602,7 +605,8 @@ fn test_inputs_into_sonic_mimc() {
|
||||
println!("done in {:?}", start.elapsed());
|
||||
|
||||
{
|
||||
let mut verifier = MultiVerifier::<Bn256, _, Basic>::new(AdaptorCircuit(circuit.clone()), &srs).unwrap();
|
||||
let rng = thread_rng();
|
||||
let mut verifier = MultiVerifier::<Bn256, _, Basic, _>::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap();
|
||||
println!("verifying 1 proof without advice");
|
||||
let start = Instant::now();
|
||||
{
|
||||
@ -615,7 +619,8 @@ fn test_inputs_into_sonic_mimc() {
|
||||
}
|
||||
|
||||
{
|
||||
let mut verifier = MultiVerifier::<Bn256, _, Basic>::new(AdaptorCircuit(circuit.clone()), &srs).unwrap();
|
||||
let rng = thread_rng();
|
||||
let mut verifier = MultiVerifier::<Bn256, _, Basic, _>::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap();
|
||||
println!("verifying {} proofs without advice", samples);
|
||||
let start = Instant::now();
|
||||
{
|
||||
@ -628,7 +633,8 @@ fn test_inputs_into_sonic_mimc() {
|
||||
}
|
||||
|
||||
{
|
||||
let mut verifier = MultiVerifier::<Bn256, _, Basic>::new(AdaptorCircuit(circuit.clone()), &srs).unwrap();
|
||||
let rng = thread_rng();
|
||||
let mut verifier = MultiVerifier::<Bn256, _, Basic, _>::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap();
|
||||
println!("verifying 100 proofs with advice and aggregate");
|
||||
let start = Instant::now();
|
||||
{
|
||||
@ -642,3 +648,84 @@ fn test_inputs_into_sonic_mimc() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_high_level_sonic_api() {
|
||||
use ff::{Field, PrimeField};
|
||||
use pairing::{Engine, CurveAffine, CurveProjective};
|
||||
use pairing::bn256::{Bn256, Fr};
|
||||
use std::time::{Instant};
|
||||
use bellman::sonic::helped::{generate_random_parameters,
|
||||
verify_aggregate,
|
||||
verify_proofs,
|
||||
create_proof,
|
||||
create_advice,
|
||||
create_aggregate
|
||||
};
|
||||
use bellman::sonic::cs::Basic;
|
||||
use bellman::sonic::sonic::AdaptorCircuit;
|
||||
|
||||
{
|
||||
// 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::<Vec<_>>();
|
||||
let samples: usize = 100;
|
||||
|
||||
let xl = rng.gen();
|
||||
let xr = rng.gen();
|
||||
let image = mimc::<Bn256>(xl, xr, &constants);
|
||||
|
||||
// Create an instance of our circuit (with the
|
||||
// witness)
|
||||
let circuit = MiMCDemo {
|
||||
xl: Some(xl),
|
||||
xr: Some(xr),
|
||||
constants: &constants
|
||||
};
|
||||
|
||||
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::<Bn256, _, Basic>(&AdaptorCircuit(circuit.clone()), &proofs, ¶ms.srs);
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user