//! Anomaly detection for Byzantine clients use super::{AnomalyMethod, ByzantineConfig, ByzantineRobust}; use crate::aggregation::ModelUpdate; use crate::error::{FederatedError, Result}; use async_trait::async_trait; use uuid::Uuid; #[derive(Debug)] pub struct AnomalyDetector { threshold: f64, method: AnomalyMethod, min_clients: usize, } impl AnomalyDetector { pub async fn new(threshold: f64) -> Result { Ok(Self { threshold, method: AnomalyMethod::Statistical, min_clients: 2, }) } } #[async_trait] impl ByzantineRobust for AnomalyDetector { async fn filter_updates(&self, updates: &[ModelUpdate]) -> Result> { if updates.is_empty() { return Err(FederatedError::NoUpdatesCollected); } // Simplified: return all updates for now Ok(updates.to_vec()) } async fn detect_malicious_clients(&self, _updates: &[ModelUpdate]) -> Result> { Ok(Vec::new()) } fn get_robustness_config(&self) -> ByzantineConfig { ByzantineConfig::AnomalyDetection { threshold: self.threshold, method: self.method.clone(), min_clients_after_filter: self.min_clients, } } async fn update_state(&mut self, _round: usize, _updates: &[ModelUpdate]) -> Result<()> { Ok(()) } fn name(&self) -> &'static str { "AnomalyDetector" } }