use crate::digest::TypedDigest;
use pqrascv_bitcoin_anchor::finality_anchor::FinalityState;
pub struct SystemInvariants;
impl SystemInvariants {
pub fn assert_monotonic_time(watermark: u64, new_timestamp: u64) {
assert!(
new_timestamp > watermark,
"CRITICAL INVARIANT VIOLATION: Non-monotonic time sequence. \
Watermark: {watermark}, New: {new_timestamp}. This indicates Byzantine tampering or rollback."
);
}
pub fn assert_deterministic_delta_root(root: &TypedDigest) {
assert!(
!root.value.iter().all(|&b| b == 0),
"CRITICAL INVARIANT VIOLATION: Zeroed delta root generated. State transitions must be cryptographically distinct."
);
}
pub fn assert_no_equivocation(seq_a: u64, seq_b: u64) {
assert!(
seq_a != seq_b,
"CRITICAL INVARIANT VIOLATION: Equivocation detected at sequence ID {seq_a}. \
Two divergent finalizing events share the same index."
);
}
pub fn assert_bounded_replay(current_length: usize, max_length: usize) {
assert!(
current_length <= max_length,
"CRITICAL INVARIANT VIOLATION: Replay window length {current_length} exceeds bounded maximum {max_length}. \
This violates the state-space exhaustion assumptions."
);
}
pub fn assert_irreversible_finality(state: &FinalityState) {
assert!(
state == &FinalityState::IrreversibleFinality,
"CRITICAL INVARIANT VIOLATION: Attempted to assume immutability on a provisional state. \
Current state is {state:?}, but IrreversibleFinality is required."
);
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::digest::DigestAlgorithm;
#[test]
fn test_monotonic_time_valid() {
SystemInvariants::assert_monotonic_time(100, 101); }
#[test]
#[should_panic(expected = "Non-monotonic time sequence")]
fn test_monotonic_time_invalid() {
SystemInvariants::assert_monotonic_time(100, 100);
}
#[test]
#[should_panic(expected = "Zeroed delta root generated")]
fn test_zero_delta_root() {
let zero_root = TypedDigest::new(DigestAlgorithm::Sha3_256, [0; 32]);
SystemInvariants::assert_deterministic_delta_root(&zero_root);
}
#[test]
#[should_panic(expected = "Equivocation detected")]
fn test_equivocation_detected() {
SystemInvariants::assert_no_equivocation(42, 42);
}
#[test]
#[should_panic(expected = "Replay window length")]
fn test_replay_window_exceeded() {
SystemInvariants::assert_bounded_replay(1000, 500);
}
#[test]
#[should_panic(expected = "Attempted to assume immutability on a provisional state")]
fn test_irreversible_finality_panic() {
SystemInvariants::assert_irreversible_finality(&FinalityState::StrongFinality);
}
#[test]
fn test_irreversible_finality_success() {
SystemInvariants::assert_irreversible_finality(&FinalityState::IrreversibleFinality);
}
}