use bsv_rs::primitives::bsv::shamir::split_private_key;
use bsv_rs::primitives::ec::PrivateKey;
use bsv_rs::primitives::symmetric::SymmetricKey;
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
use memory_stats::memory_stats;
fn current_rss() -> usize {
memory_stats().map(|s| s.physical_mem).unwrap_or(0)
}
fn print_memory_delta(name: &str, start_rss: usize) {
let end_rss = current_rss();
let delta = end_rss.saturating_sub(start_rss);
if delta > 0 {
println!(" [Memory] {}: RSS delta = {} KB", name, delta / 1024);
}
}
fn bench_encryption_memory(c: &mut Criterion) {
let mut group = c.benchmark_group("Memory/Encryption");
let key = SymmetricKey::random();
let sizes: &[usize] = &[64, 1024, 16384];
for &size in sizes {
let plaintext = vec![0u8; size];
group.throughput(Throughput::Bytes(size as u64));
let start_rss = current_rss();
group.bench_with_input(
BenchmarkId::new("aes_gcm_encrypt", format!("{} bytes", size)),
&plaintext,
|b, pt| b.iter(|| black_box(&key).encrypt(black_box(pt))),
);
print_memory_delta(&format!("encrypt {} bytes", size), start_rss);
let ciphertext = key.encrypt(&plaintext).unwrap();
let start_rss = current_rss();
group.bench_with_input(
BenchmarkId::new("aes_gcm_decrypt", format!("{} bytes", size)),
&ciphertext,
|b, ct| b.iter(|| black_box(&key).decrypt(black_box(ct))),
);
print_memory_delta(&format!("decrypt {} bytes", size), start_rss);
}
group.finish();
}
fn bench_key_derivation_memory(c: &mut Criterion) {
let mut group = c.benchmark_group("Memory/KeyDerivation");
let alice = PrivateKey::random();
let bob = PrivateKey::random();
let bob_pub = bob.public_key();
let start_rss = current_rss();
group.bench_function("brc42_derive_child", |b| {
let mut counter = 0u64;
b.iter(|| {
counter += 1;
let invoice_id = format!("invoice-{}", counter);
black_box(&alice).derive_child(black_box(&bob_pub), black_box(&invoice_id))
})
});
print_memory_delta("brc42_derive_child", start_rss);
let start_rss = current_rss();
group.bench_function("ecdh_shared_secret", |b| {
b.iter(|| black_box(&alice).derive_shared_secret(black_box(&bob_pub)))
});
print_memory_delta("ecdh_shared_secret", start_rss);
group.finish();
}
fn bench_shamir_memory(c: &mut Criterion) {
let mut group = c.benchmark_group("Memory/Shamir");
let key = PrivateKey::random();
let start_rss = current_rss();
group.bench_function("split_3_of_5", |b| {
b.iter(|| split_private_key(black_box(&key), 3, 5))
});
print_memory_delta("split_3_of_5", start_rss);
let start_rss = current_rss();
group.bench_function("split_5_of_10", |b| {
b.iter(|| split_private_key(black_box(&key), 5, 10))
});
print_memory_delta("split_5_of_10", start_rss);
let shares = split_private_key(&key, 3, 5).unwrap();
let start_rss = current_rss();
group.bench_function("recover_3_of_5", |b| {
b.iter(|| {
let subset = bsv_rs::primitives::bsv::shamir::KeyShares::new(
shares.points[0..3].to_vec(),
3,
shares.integrity.clone(),
);
black_box(subset.recover_private_key())
})
});
print_memory_delta("recover_3_of_5", start_rss);
group.finish();
}
fn bench_signing_memory(c: &mut Criterion) {
let mut group = c.benchmark_group("Memory/Signing");
let key = PrivateKey::random();
let pubkey = key.public_key();
let msg_hash = bsv_rs::primitives::hash::sha256(b"benchmark message for signing");
let start_rss = current_rss();
group.bench_function("ecdsa_sign", |b| {
b.iter(|| black_box(&key).sign(black_box(&msg_hash)))
});
print_memory_delta("ecdsa_sign", start_rss);
let sig = key.sign(&msg_hash).unwrap();
let start_rss = current_rss();
group.bench_function("ecdsa_verify", |b| {
b.iter(|| black_box(&pubkey).verify(black_box(&msg_hash), black_box(&sig)))
});
print_memory_delta("ecdsa_verify", start_rss);
group.finish();
}
criterion_group!(
benches,
bench_encryption_memory,
bench_key_derivation_memory,
bench_shamir_memory,
bench_signing_memory,
);
criterion_main!(benches);