#![allow( dead_code, unused_imports, clippy::missing_panics_doc, clippy::indexing_slicing )] #[path = "bench_utils/ckd.rs"] mod ckd; #[path = "bench_utils/dkg.rs"] mod dkg; #[path = "bench_utils/frost_eddsa.rs"] mod frost_eddsa; #[path = "bench_utils/ot_based_ecdsa.rs"] mod ot_based_ecdsa; #[path = "bench_utils/robust_ecdsa.rs"] mod robust_ecdsa; pub use ckd::*; pub use dkg::*; pub use frost_eddsa::*; pub use ot_based_ecdsa::*; pub use robust_ecdsa::*; use average::{Estimate, Quantile, Variance}; use k256::AffinePoint; use std::{collections::HashMap, env, sync::LazyLock}; use rand_core::SeedableRng; use threshold_signatures::{ ReconstructionThreshold, ecdsa::{self, Scalar}, participants::Participant, protocol::Protocol, test_utils::{MockCryptoRng, Simulator}, }; /// Rebuilds the RNG a participant's protocol was seeded with during snapshot /// capture, so the simulated replay reproduces the exact recorded run. pub fn participant_rng( seeds: &HashMap, participant: Participant, ) -> MockCryptoRng { let seed = *seeds .get(&participant) .expect("participant must have a recorded seed"); MockCryptoRng::seed_from_u64(seed) } // fix malicious number of participants pub static MAX_MALICIOUS: LazyLock = std::sync::LazyLock::new(|| { env::var("MAX_MALICIOUS") .ok() .and_then(|v| v.parse().ok()) .unwrap_or(6) }); // fix number of samples pub static SAMPLE_SIZE: LazyLock = std::sync::LazyLock::new(|| { env::var("SAMPLE_SIZE") .ok() .and_then(|v| v.parse().ok()) .unwrap_or(15) }); pub static RECONSTRUCTION_LOWER_BOUND: LazyLock = LazyLock::new(|| ReconstructionThreshold::from(*MAX_MALICIOUS + 1)); /// This helps defining a generic type for the benchmarks prepared outputs pub struct PreparedOutputs { pub participant: Participant, pub protocol: Box>, pub simulator: Simulator, } pub struct PreparedPresig { pub protocols: Vec<(Participant, Box>)>, pub key_packages: Vec<(Participant, KeygenOutput)>, pub participants: Vec, /// Per-participant RNG seed used to build each presign protocol; empty when /// the protocol is built from deterministic inputs. pub seeds: HashMap, } pub struct PreparedSig { pub protocols: Vec<( Participant, Box>, )>, pub index: usize, pub presig: RerandomizedPresignOutput, pub derived_pk: AffinePoint, pub msg_hash: Scalar, } #[allow(clippy::cast_precision_loss)] /// Analyzes the size of the received data by a participant across the entire protocol pub fn analyze_received_sizes( sizes: &[usize], is_print: bool, ) -> (usize, usize, f64, f64, f64, f64) { if sizes.len() <= 1 { return (0, 0, 0.0, 0.0, 0.0, 0.0); } let min = *sizes.iter().min().expect("Minimum should exist"); let max = *sizes.iter().max().expect("Maximum should exist"); let avg = sizes.iter().sum::() as f64 / sizes.len() as f64; let data = sizes.iter().map(|&x| x as f64).collect::>(); // Median (0.5 quantile) let mut quantile = Quantile::new(0.5); // Variance + Std Dev let mut variance_est = Variance::new(); for &x in &data { variance_est.add(x); quantile.add(x); } let median = quantile.quantile(); let variance = variance_est.sample_variance(); let std_dev = variance.sqrt(); if is_print { println!("Analysis for received messages:"); println!( "\ min:{min}B\t\ max:{max}B\t\ average:{avg}B\t\ median:{median}B\t\ variance:{variance}B\t\ standard deviation:{std_dev}B " ); } (min, max, avg, median, variance, std_dev) }