pub const SPOOF_DETECT_K: f64 = 5.0;
pub const SPOOF_MONITOR_S: f64 = 600.0;
pub fn monitor_sigma_s(q_wf: f64, q_rw: f64, r: f64, tau: f64, samples: f64) -> f64 {
let m = samples.max(1.0);
let var = r / m + q_wf * tau + q_rw * tau.powi(3) / 3.0;
var.max(0.0).sqrt()
}
pub fn min_detectable_offset_ns(
q_wf: f64,
q_rw: f64,
r: f64,
tau: f64,
samples: f64,
k: f64,
) -> f64 {
k * monitor_sigma_s(q_wf, q_rw, r, tau, samples) * 1e9
}
pub fn spoof_detection_score(
q_wf: f64,
q_rw: f64,
r: f64,
threshold_ns: f64,
tau: f64,
dt: f64,
k: f64,
) -> f64 {
if threshold_ns <= 0.0 {
return 0.0;
}
let samples = if dt > 0.0 { (tau / dt).round() } else { 1.0 };
let floor = min_detectable_offset_ns(q_wf, q_rw, r, tau, samples, k);
(1.0 - floor / threshold_ns).clamp(0.0, 1.0)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn monitor_variance_is_hand_derived() {
let sigma = monitor_sigma_s(1e-24, 0.0, 1e-20, 600.0, 600.0);
assert!(
(sigma * sigma - 6.166_666_666_7e-22).abs() < 1e-31,
"sigma={sigma}"
);
}
#[test]
fn random_walk_term_adds_to_the_variance() {
let sigma = monitor_sigma_s(1e-24, 1e-30, 1e-20, 600.0, 600.0);
assert!(
(sigma * sigma - 6.886_666_666_7e-22).abs() < 1e-31,
"sigma={sigma}"
);
}
#[test]
fn min_detectable_offset_is_k_sigma_in_ns() {
let off = min_detectable_offset_ns(1e-24, 0.0, 1e-20, 600.0, 600.0, 5.0);
assert!((off - 0.124_163_87).abs() < 1e-6, "off={off}");
}
#[test]
fn score_is_hand_derived() {
let s = spoof_detection_score(1e-24, 0.0, 1e-20, 20.0, 600.0, 1.0, 5.0);
assert!((s - 0.993_791_81).abs() < 1e-6, "score={s}");
}
#[test]
fn better_clock_scores_higher() {
let quantum = spoof_detection_score(1e-26, 1e-34, 1e-20, 20.0, 600.0, 1.0, 5.0);
let classical = spoof_detection_score(1e-24, 1e-32, 1e-20, 20.0, 600.0, 1.0, 5.0);
assert!(quantum > classical, "q={quantum} c={classical}");
assert!(quantum <= 1.0 && classical >= 0.0);
}
#[test]
fn floor_above_threshold_clamps_to_zero() {
let s = spoof_detection_score(1e-24, 0.0, 1e-20, 0.05, 600.0, 1.0, 5.0);
assert_eq!(s, 0.0);
}
#[test]
fn nonpositive_threshold_is_zero() {
assert_eq!(
spoof_detection_score(1e-24, 0.0, 1e-20, 0.0, 600.0, 1.0, 5.0),
0.0
);
}
}