use commonware_codec::EncodeSize as _;
use commonware_cryptography::bls12381::dkg::golden::{
self, DealerLog, Info, PrivateKey, PublicKey, Setup, SignedDealerLog,
};
use commonware_math::algebra::Random;
use commonware_parallel::Sequential;
use commonware_utils::{ordered::Set, test_rng, N3f1, TryCollect};
use criterion::{criterion_group, BatchSize, Criterion};
use rand_core::CryptoRng;
use std::{collections::BTreeMap, hint::black_box, num::NonZeroU32, sync::LazyLock};
const BENCH_NAMESPACE: &[u8] = b"bench";
cfg_if::cfg_if! {
if #[cfg(full_bench)] {
const RECEIVERS: &[u32] = &[5, 10, 15, 20, 25];
const MAX_RECEIVERS: u32 = 25;
} else {
const RECEIVERS: &[u32] = &[5, 10, 25];
const MAX_RECEIVERS: u32 = 25;
}
}
static SETUP: LazyLock<Setup> =
LazyLock::new(|| Setup::new(NonZeroU32::new(MAX_RECEIVERS).unwrap()));
struct Bench {
info: Info,
me: PrivateKey,
}
impl Bench {
fn new(rng: &mut impl CryptoRng, n: u32) -> Self {
let me = PrivateKey::random(&mut *rng);
let dealers: Set<PublicKey> = std::iter::once(me.public()).try_collect().unwrap();
let players: Set<PublicKey> = (0..n)
.map(|_| PrivateKey::random(&mut *rng).public())
.try_collect()
.unwrap();
let info = Info::new::<N3f1>(BENCH_NAMESPACE, 0, None, dealers, players).unwrap();
Self { info, me }
}
fn deal(&self, rng: &mut impl CryptoRng) -> SignedDealerLog {
golden::deal(rng, &SETUP, &self.info, &self.me, None, &Sequential)
.expect("honest deal should succeed")
}
}
fn bench_deal(c: &mut Criterion) {
let mut rng = test_rng();
for &n in RECEIVERS {
let bench = Bench::new(&mut rng, n);
c.bench_function(&format!("{}::deal/n={}", module_path!(), n), |b| {
b.iter_batched(
|| (bench.info.clone(), bench.me.clone(), test_rng()),
|(info, me, mut rng)| {
black_box(
golden::deal(&mut rng, &SETUP, &info, &me, None, &Sequential).unwrap(),
);
},
BatchSize::SmallInput,
);
});
}
}
fn bench_verify(c: &mut Criterion) {
let mut rng = test_rng();
for &n in RECEIVERS {
let bench = Bench::new(&mut rng, n);
let signed = bench.deal(&mut rng);
c.bench_function(&format!("{}::verify/n={}", module_path!(), n), |b| {
b.iter_batched(
|| (bench.info.clone(), signed.clone(), test_rng()),
|(info, signed, mut rng)| {
let (pk, log) = signed.identify(&info).expect("honest log should identify");
let mut logs = BTreeMap::<PublicKey, DealerLog>::new();
logs.insert(pk, log);
black_box(golden::observe(&mut rng, &SETUP, &info, logs, &Sequential).unwrap());
},
BatchSize::SmallInput,
);
});
}
}
fn bench_dealing_size(_c: &mut Criterion) {
let mut rng = test_rng();
for &n in RECEIVERS {
let bench = Bench::new(&mut rng, n);
let signed = bench.deal(&mut rng);
println!(
"{}::dealing_size/n={}: {} B",
module_path!(),
n,
signed.encode_size(),
);
}
}
criterion_group! {
name = benches;
config = Criterion::default().sample_size(10);
targets =
bench_deal,
bench_verify,
bench_dealing_size,
}