use clock_hash::{clockhash256, tags, verify_avalanche, verify_collision_resistance, verify_domain_separation};
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
use std::hint::black_box;
fn bench_constant_time_verification(c: &mut Criterion) {
let mut group = c.benchmark_group("constant_time_verification");
let iterations = [100, 1000, 10000];
for &iter in &iterations {
group.bench_with_input(
BenchmarkId::from_parameter(format!("{}_iterations", iter)),
&iter,
|b, &iter| {
b.iter(|| {
let mut result = 0u64;
for i in 0..iter {
let data = vec![(i % 256) as u8; 1024];
let hash = clockhash256(black_box(&data));
result ^= u64::from_le_bytes(hash[0..8].try_into().unwrap());
}
black_box(result);
});
},
);
}
group.finish();
}
fn bench_avalanche_verification(c: &mut Criterion) {
let mut group = c.benchmark_group("avalanche_verification");
let sizes = [64, 256, 1024, 4096];
for &size in &sizes {
let input1 = vec![0x00u8; size];
let input2 = {
let mut v = vec![0x00u8; size];
if !v.is_empty() {
v[0] = 0x01; }
v
};
group.bench_with_input(
BenchmarkId::from_parameter(format!("{}_bytes", size)),
&(input1, input2),
|b, (input1, input2)| {
b.iter(|| {
let avalanche = verify_avalanche(black_box(input1), black_box(input2));
black_box(avalanche);
});
},
);
}
group.finish();
}
fn bench_collision_resistance(c: &mut Criterion) {
let mut group = c.benchmark_group("collision_resistance");
let test_case_counts = [10, 50, 100, 500];
for &count in &test_case_counts {
let test_cases: Vec<Vec<u8>> = (0..count)
.map(|i| {
match i % 4 {
0 => vec![0x00u8; 32], 1 => vec![0xFFu8; 32], 2 => (0..32).map(|j| (i * j) as u8).collect(), _ => vec![i as u8; 32], }
})
.collect();
let test_refs: Vec<&[u8]> = test_cases.iter().map(|v| v.as_slice()).collect();
group.bench_with_input(
BenchmarkId::from_parameter(format!("{}_cases", count)),
&test_refs,
|b, test_refs| {
b.iter(|| {
let is_collision_resistant = verify_collision_resistance(black_box(test_refs));
black_box(is_collision_resistant);
});
},
);
}
group.finish();
}
fn bench_domain_separation_verification(c: &mut Criterion) {
let mut group = c.benchmark_group("domain_separation_verification");
let data_sizes = [64, 256, 1024];
for &size in &data_sizes {
let data = vec![0x42u8; size];
let domains = vec![
tags::CLK_BLOCK,
tags::CLK_TX,
tags::CLK_MERKLE,
tags::CLK_NONCE,
tags::CLK_RNG,
];
group.bench_with_input(
BenchmarkId::from_parameter(format!("{}_bytes", size)),
&(data, domains),
|b, (data, domains)| {
b.iter(|| {
let is_domain_separated = verify_domain_separation(
black_box(data),
black_box(&domains.iter().map(|d| *d).collect::<Vec<_>>()),
);
black_box(is_domain_separated);
});
},
);
}
group.finish();
}
fn bench_security_property_suite(c: &mut Criterion) {
let mut group = c.benchmark_group("security_property_suite");
group.bench_function("full_security_verification", |b| {
b.iter(|| {
let input1 = vec![0x00u8; 1024];
let input2 = {
let mut v = vec![0x00u8; 1024];
v[0] = 0x01;
v
};
let avalanche = verify_avalanche(&input1, &input2);
black_box(avalanche);
let test_cases = vec![
&[0x00u8; 32][..],
&[0xFFu8; 32][..],
&[0xAAu8; 32][..],
];
let collision_resistant = verify_collision_resistance(&test_cases);
black_box(collision_resistant);
let data = vec![0x42u8; 256];
let domains = vec![tags::CLK_BLOCK, tags::CLK_TX, tags::CLK_MERKLE];
let domain_separated = verify_domain_separation(&data, &domains);
black_box(domain_separated);
});
});
group.finish();
}
fn bench_adversarial_inputs(c: &mut Criterion) {
let mut group = c.benchmark_group("adversarial_inputs");
let inputs = vec![
("all_zeros", vec![0x00u8; 4096]),
("all_ones", vec![0xFFu8; 4096]),
("alternating", (0..4096).map(|i| if i % 2 == 0 { 0x00 } else { 0xFF }).collect()),
("increasing", (0..4096).map(|i| (i % 256) as u8).collect()),
("decreasing", (0..4096).map(|i| (255 - (i % 256)) as u8).collect()),
("sparse_ones", (0..4096).map(|i| if i % 128 == 0 { 0xFF } else { 0x00 }).collect()),
];
for (name, data) in inputs {
group.bench_with_input(
BenchmarkId::from_parameter(name),
&data,
|b, data| {
b.iter(|| {
let hash = clockhash256(black_box(data));
black_box(hash);
});
},
);
}
group.finish();
}
fn bench_timing_resistance(c: &mut Criterion) {
let mut group = c.benchmark_group("timing_resistance");
let sizes = [0, 1, 32, 64, 128, 256, 512, 1024, 2048, 4096];
for &size in &sizes {
let data = vec![0x42u8; size];
group.bench_with_input(
BenchmarkId::from_parameter(format!("{}_bytes", size)),
&data,
|b, data| {
b.iter(|| {
let hash = clockhash256(black_box(data));
black_box(hash);
});
},
);
}
group.finish();
}
criterion_group!(
benches,
bench_constant_time_verification,
bench_avalanche_verification,
bench_collision_resistance,
bench_domain_separation_verification,
bench_security_property_suite,
bench_adversarial_inputs,
bench_timing_resistance,
);
criterion_main!(benches);