use std::time::Instant;
use foculus::settlement::Contribution;
use foculus::ticket_proof::{TicketProver, verify_fold_seal};
use foculus::tickets::{easy_target, grind_settlement};
use tru::{Context, FocusingParams, Fx, Link};
fn h(b: u8) -> [u8; 32] {
let mut x = [0u8; 32];
x[0] = b;
x
}
fn setup() -> (Vec<Link>, Vec<Contribution>, [u8; 32], [u8; 32]) {
let base = vec![
Link::stake(h(1), h(2), 100),
Link::stake(h(2), h(3), 100),
Link::stake(h(3), h(1), 100),
];
let contribs = vec![Contribution {
neuron: h(10),
links: vec![Link::stake(h(2), h(1), 8000)],
surprise: Fx::ONE,
}];
(base, contribs, h(0xBE), h(0xC1))
}
fn measure(n: usize) -> (std::time::Duration, std::time::Duration, std::time::Duration) {
let (base, contribs, beacon, cluster) = setup();
let tickets = grind_settlement(
&base,
&contribs,
&Context::none(),
&FocusingParams::default(),
&beacon,
&cluster,
&h(0x91),
0,
n as u64,
n,
easy_target(),
);
assert_eq!(tickets.len(), n, "grind must produce every requested ticket under an always-win target");
let mut prover = TicketProver::new();
let fold_start = Instant::now();
for t in &tickets {
prover.fold_settlement(&beacon, &cluster, t).expect("fold_settlement");
}
let fold_only = fold_start.elapsed();
let decide_start = Instant::now();
let seal = prover.seal(&beacon, &cluster, tickets.len() as u64).expect("seal");
let decide_only = decide_start.elapsed();
let verify_start = Instant::now();
assert!(verify_fold_seal(&seal));
let verify_only = verify_start.elapsed();
(fold_only, decide_only, verify_only)
}
#[test]
fn decide_and_verify_are_flat_in_ticket_count() {
let sizes = [1usize, 8, 64, 512];
let mut verify_times = Vec::with_capacity(sizes.len());
for &n in &sizes {
let (fold_only, decide_only, verify_only) = measure(n);
eprintln!(
"n={n:>4} fold_only={fold_only:>10?} decide_only={decide_only:>10?} verify_only={verify_only:>10?}"
);
verify_times.push(verify_only);
}
let smallest = verify_times.first().copied().unwrap();
let largest = verify_times.last().copied().unwrap();
assert!(
largest <= smallest * 20 + std::time::Duration::from_millis(5),
"verify time grew with ticket count: {smallest:?} at n={} vs {largest:?} at n={}; \
decide/verify must be O(1) per specs/fold-mining.md",
sizes[0],
sizes[sizes.len() - 1]
);
}