#![allow(missing_docs)]
#[macro_use]
extern crate criterion;
extern crate alloc;
use alloc::sync::Arc;
use criterion::{BatchSize, Criterion};
use curve25519_dalek::{RistrettoPoint, Scalar};
use itertools::izip;
use rand_chacha::ChaCha12Rng;
use rand_core::{CryptoRngCore, SeedableRng};
use triptych::{
parallel::{
parameters::TriptychParameters,
proof::TriptychProof,
statement::{TriptychInputSet, TriptychStatement},
witness::TriptychWitness,
},
Transcript,
};
const N_VALUES: [u32; 1] = [2];
const M_VALUES: [u32; 4] = [2, 4, 8, 10];
const BATCH_SIZES: [usize; 1] = [2];
#[allow(non_snake_case)]
#[allow(clippy::arithmetic_side_effects)]
fn generate_data<R: CryptoRngCore>(
params: &Arc<TriptychParameters>,
b: usize,
rng: &mut R,
) -> (Vec<TriptychWitness>, Vec<TriptychStatement>, Vec<Transcript>) {
assert!(b <= params.get_N() as usize);
let mut witnesses = Vec::with_capacity(b);
witnesses.push(TriptychWitness::random(params, rng));
for _ in 1..b {
let r = Scalar::random(rng);
let r1 = Scalar::random(rng);
let l = (witnesses.last().unwrap().get_l() + 1) % params.get_N();
witnesses.push(TriptychWitness::new(params, l, &r, &r1).unwrap());
}
let mut M = (0..params.get_N())
.map(|_| RistrettoPoint::random(rng))
.collect::<Vec<RistrettoPoint>>();
let mut M1 = (0..params.get_N())
.map(|_| RistrettoPoint::random(rng))
.collect::<Vec<RistrettoPoint>>();
let mut offsets = Vec::with_capacity(b);
for witness in &witnesses {
M[witness.get_l() as usize] = witness.compute_verification_key();
let r_offset = Scalar::random(rng);
offsets.push(r_offset * params.get_G1());
M1[witness.get_l() as usize] = witness.compute_auxiliary_verification_key() + offsets.last().unwrap();
}
let input_set = Arc::new(TriptychInputSet::new(&M, &M1).unwrap());
let mut statements = Vec::with_capacity(b);
for (witness, offset) in witnesses.iter().zip(offsets.iter()) {
let J = witness.compute_linking_tag();
statements.push(TriptychStatement::new(params, &input_set, offset, &J).unwrap());
}
let transcripts = (0..b)
.map(|i| {
let mut transcript = Transcript::new(b"Test transcript");
transcript.append_u64(b"index", i as u64);
transcript
})
.collect::<Vec<Transcript>>();
(witnesses, statements, transcripts)
}
#[allow(non_snake_case)]
#[allow(non_upper_case_globals)]
fn generate_proof(c: &mut Criterion) {
let mut group = c.benchmark_group("generate_proof");
let mut rng = ChaCha12Rng::seed_from_u64(8675309);
for n in N_VALUES {
for m in M_VALUES {
let params = Arc::new(TriptychParameters::new(n, m).unwrap());
let label = format!("Generate proof: n = {}, m = {} (N = {})", n, m, params.get_N());
group.bench_function(&label, |b| {
let (witnesses, statements, transcripts) = generate_data(¶ms, 1, &mut rng);
b.iter_batched_ref(
|| transcripts[0].clone(),
|t| {
TriptychProof::prove_with_rng(&witnesses[0], &statements[0], &mut rng, t).unwrap();
},
BatchSize::SmallInput,
)
});
}
}
group.finish();
}
#[allow(non_snake_case)]
#[allow(non_upper_case_globals)]
fn generate_proof_vartime(c: &mut Criterion) {
let mut group = c.benchmark_group("generate_proof_vartime");
let mut rng = ChaCha12Rng::seed_from_u64(8675309);
for n in N_VALUES {
for m in M_VALUES {
let params = Arc::new(TriptychParameters::new(n, m).unwrap());
let label = format!(
"Generate proof (variable time): n = {}, m = {} (N = {})",
n,
m,
params.get_N()
);
group.bench_function(&label, |b| {
let (witnesses, statements, transcripts) = generate_data(¶ms, 1, &mut rng);
b.iter_batched_ref(
|| transcripts[0].clone(),
|t| {
TriptychProof::prove_with_rng_vartime(&witnesses[0], &statements[0], &mut rng, t).unwrap();
},
BatchSize::SmallInput,
)
});
}
}
group.finish();
}
#[allow(non_snake_case)]
#[allow(non_upper_case_globals)]
fn verify_proof(c: &mut Criterion) {
let mut group = c.benchmark_group("verify_proof");
let mut rng = ChaCha12Rng::seed_from_u64(8675309);
for n in N_VALUES {
for m in M_VALUES {
let params = Arc::new(TriptychParameters::new(n, m).unwrap());
let label = format!("Verify proof: n = {}, m = {} (N = {})", n, m, params.get_N());
group.bench_function(&label, |b| {
let (witnesses, statements, transcripts) = generate_data(¶ms, 1, &mut rng);
let proof =
TriptychProof::prove_with_rng(&witnesses[0], &statements[0], &mut rng, &mut transcripts[0].clone())
.unwrap();
b.iter_batched_ref(
|| transcripts[0].clone(),
|t| {
assert!(proof.verify(&statements[0], t).is_ok());
},
BatchSize::SmallInput,
)
});
}
}
group.finish();
}
#[allow(non_snake_case)]
#[allow(non_upper_case_globals)]
fn verify_batch_proof(c: &mut Criterion) {
let mut group = c.benchmark_group("verify_batch_proof");
let mut rng = ChaCha12Rng::seed_from_u64(8675309);
for n in N_VALUES {
for m in M_VALUES {
let params = Arc::new(TriptychParameters::new(n, m).unwrap());
for batch in BATCH_SIZES {
let label = format!(
"Verify batch proof: n = {}, m = {} (N = {}), {}-batch",
n,
m,
params.get_N(),
batch
);
group.bench_function(&label, |b| {
let (witnesses, statements, transcripts) = generate_data(¶ms, batch, &mut rng);
let proofs = izip!(witnesses.iter(), statements.iter(), transcripts.clone().iter_mut())
.map(|(w, s, t)| TriptychProof::prove_with_rng_vartime(w, s, &mut rng, t).unwrap())
.collect::<Vec<TriptychProof>>();
b.iter_batched_ref(
|| transcripts.clone(),
|t| {
assert!(TriptychProof::verify_batch(&statements, &proofs, t).is_ok());
},
BatchSize::SmallInput,
)
});
}
}
}
group.finish();
}
criterion_group! {
name = generate;
config = Criterion::default();
targets = generate_proof, generate_proof_vartime
}
criterion_group! {
name = verify;
config = Criterion::default();
targets = verify_proof, verify_batch_proof
}
criterion_main!(generate, verify);