pub(crate) const WINDOW_BITS: u64 = 64;
pub(crate) struct AntiReplayWindow {
highest: u64,
bitmap: u64,
seeded: bool,
}
impl AntiReplayWindow {
pub(crate) fn new() -> Self {
Self {
highest: 0,
bitmap: 0,
seeded: false,
}
}
pub(crate) fn check(&self, seq: u64) -> bool {
if !self.seeded {
return true;
}
if seq > self.highest {
return true;
}
let delta = self.highest - seq;
if delta >= WINDOW_BITS {
return false;
}
let bit = 1u64 << delta;
self.bitmap & bit == 0
}
pub(crate) fn mark(&mut self, seq: u64) {
if !self.seeded {
self.highest = seq;
self.bitmap = 1; self.seeded = true;
return;
}
if seq > self.highest {
let delta = seq - self.highest;
self.bitmap = if delta >= WINDOW_BITS {
1
} else {
(self.bitmap << delta) | 1
};
self.highest = seq;
} else {
let delta = self.highest - seq;
if delta >= WINDOW_BITS {
return;
}
let bit = 1u64 << delta;
self.bitmap |= bit;
}
}
#[cfg(test)]
pub(crate) fn accept(&mut self, seq: u64) -> bool {
if !self.check(seq) {
return false;
}
self.mark(seq);
true
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn first_record_accepted_regardless_of_value() {
let mut w = AntiReplayWindow::new();
assert!(w.accept(0));
let mut w = AntiReplayWindow::new();
assert!(w.accept(1_000_000));
let mut w = AntiReplayWindow::new();
assert!(w.accept((1u64 << 48) - 1));
}
#[test]
fn slides_in_within_window() {
let mut w = AntiReplayWindow::new();
assert!(w.accept(5));
assert!(w.accept(4));
assert!(w.accept(3));
assert!(w.accept(0));
}
#[test]
fn rejects_duplicate() {
let mut w = AntiReplayWindow::new();
assert!(w.accept(5));
assert!(!w.accept(5));
assert!(w.accept(7));
assert!(!w.accept(7));
assert!(w.accept(6));
assert!(!w.accept(6));
}
#[test]
fn rejects_too_old() {
let mut w = AntiReplayWindow::new();
assert!(w.accept(100));
assert!(w.accept(37));
assert!(!w.accept(36));
assert!(!w.accept(20));
}
#[test]
fn accepts_large_forward_jump() {
let mut w = AntiReplayWindow::new();
assert!(w.accept(5));
assert!(w.accept(200));
assert!(w.accept(199));
assert!(!w.accept(5));
}
#[test]
fn window_floor_inclusive() {
let mut w = AntiReplayWindow::new();
assert!(w.accept(63));
assert!(w.accept(0));
assert!(!w.accept(0));
assert!(w.accept(64));
assert!(!w.accept(0));
}
#[test]
fn check_is_read_only() {
let mut w = AntiReplayWindow::new();
assert!(w.accept(10));
assert!(w.check(20));
assert!(w.check(20));
assert!(w.check(20));
w.mark(20);
assert!(w.check(19));
w.mark(19);
assert!(!w.check(19));
}
#[test]
fn mark_after_check_pattern() {
let mut w = AntiReplayWindow::new();
for seq in [5u64, 10, 7, 6, 11] {
assert!(w.check(seq), "seq {seq} should be acceptable on check");
w.mark(seq);
}
for seq in [5u64, 10, 7, 6, 11] {
assert!(!w.check(seq), "seq {seq} should now be a duplicate");
}
}
#[test]
fn forged_seq_does_not_burn_slots() {
let mut w = AntiReplayWindow::new();
assert!(w.accept(5));
assert!(w.check(6));
assert!(w.check(7));
assert!(w.check(6)); assert!(w.check(6));
w.mark(6);
assert!(!w.check(6)); assert!(w.check(7));
w.mark(7);
assert!(!w.check(7));
}
#[test]
fn boundary_jump_clears_window() {
let mut w = AntiReplayWindow::new();
assert!(w.accept(0));
assert!(w.accept(WINDOW_BITS));
assert!(!w.accept(0));
assert!(w.accept(1));
}
}