use super::utils::optimistic_assemble::{BenchSubject, Case, bench_case}; use commonware_cryptography::{ Signer as _, bls12381::primitives::{ group::Private, ops::{compute_public, sign_proof_of_possession, verify_proof_of_possession}, variant::{MinPk, MinSig, Variant}, }, certificate::{Attestation, Scheme as _}, ed25519, impl_certificate_bls12381_multisig, sha256::Digest as Sha256Digest, }; use commonware_math::algebra::Random; use commonware_utils::{Faults, N3f1, TestRng, TryCollect, ordered::BiMap}; use criterion::{Criterion, criterion_group}; const NAMESPACE: &[u8] = b"_COMMONWARE_CRYPTOGRAPHY_BLS12381_MULTISIG_OPTIMISTIC_ASSEMBLE"; const POP_NAMESPACE: &[u8] = b"_COMMONWARE_CRYPTOGRAPHY_BLS12381_MULTISIG_OPTIMISTIC_ASSEMBLE_POP"; impl_certificate_bls12381_multisig!(BenchSubject, Vec, N3f1); type Multisig = Scheme; fn setup(n: u32) -> (Multisig, Vec>>) { let identity_keys: Vec<_> = (0..n) .map(|i| ed25519::PrivateKey::from_seed(u64::from(i))) .collect(); let mut rng = TestRng::new(u64::from(n)); let signing_keys: Vec<_> = (0..n).map(|_| Private::random(&mut rng)).collect(); let signing_publics: Vec<_> = signing_keys.iter().map(compute_public::).collect(); for (private, public) in signing_keys.iter().zip(&signing_publics) { let proof = sign_proof_of_possession::(private, POP_NAMESPACE); verify_proof_of_possession::(public, POP_NAMESPACE, &proof) .expect("proof of possession must verify"); } let participants: BiMap<_, _> = identity_keys .iter() .map(|key| key.public_key()) .zip(signing_publics) .try_collect() .unwrap(); let quorum = N3f1::quorum(n) as usize; let attestations = signing_keys .into_iter() .take(quorum + 1) .map(|private| { Scheme::signer(NAMESPACE, participants.clone(), private) .expect("signer must be a participant") .sign::(BenchSubject) .unwrap() }) .collect(); (Scheme::verifier(NAMESPACE, participants), attestations) } fn bench_variant(c: &mut Criterion, variant: &str) { for (n, quorum) in [(100, 67), (298, 199)] { assert_eq!(N3f1::quorum(n), quorum); let (scheme, attestations) = setup::(n); for case in [Case::Valid, Case::Bad, Case::Spare, Case::Split] { bench_case::<_, Sha256Digest>( c, &format!( "{}/variant={} n={} case={}", module_path!(), variant, n, case.name(), ), &scheme, BenchSubject, &attestations, quorum as usize, case, ); } } } fn bench_multisig_optimistic_assemble(c: &mut Criterion) { bench_variant::(c, "MinPk"); bench_variant::(c, "MinSig"); } criterion_group! { name = benches; config = Criterion::default().sample_size(10); targets = bench_multisig_optimistic_assemble, }