//! CBP声誉更新机制 //! //! 实现CBP节点的声誉计算、衰减、恢复和查询功能 use crate::{CbpNode, CbppL1Error}; use nac_udm::primitives::Address; use serde::{Deserialize, Serialize}; use std::collections::HashMap; /// 声誉事件类型 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum ReputationEvent { /// 成功出块 BlockProduced, /// 错过出块 BlockMissed, /// 双签 DoubleSign, /// 违规行为 Violation, /// 长时间在线 LongUptime, /// 宪法测试通过 ConstitutionTestPassed, /// 社区贡献 CommunityContribution, } /// 声誉变化记录 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ReputationChange { /// CBP地址 pub address: Address, /// 事件类型 pub event: ReputationEvent, /// 变化前声誉 pub old_reputation: f64, /// 变化后声誉 pub new_reputation: f64, /// 变化量 pub delta: f64, /// 时间戳 pub timestamp: u64, /// 备注 pub note: Option, } /// 声誉配置 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ReputationConfig { /// 初始声誉 pub initial_reputation: f64, /// 最小声誉 pub min_reputation: f64, /// 最大声誉 pub max_reputation: f64, /// 衰减率(每天) pub decay_rate: f64, /// 衰减间隔(秒) pub decay_interval: u64, /// 恢复率(每次成功出块) pub recovery_rate: f64, /// 事件影响权重 pub event_weights: HashMap, } impl Default for ReputationConfig { fn default() -> Self { let mut event_weights = HashMap::new(); event_weights.insert(ReputationEvent::BlockProduced, 0.001); event_weights.insert(ReputationEvent::BlockMissed, -0.01); event_weights.insert(ReputationEvent::DoubleSign, -0.5); event_weights.insert(ReputationEvent::Violation, -0.3); event_weights.insert(ReputationEvent::LongUptime, 0.05); event_weights.insert(ReputationEvent::ConstitutionTestPassed, 0.02); event_weights.insert(ReputationEvent::CommunityContribution, 0.03); Self { initial_reputation: 0.5, min_reputation: 0.0, max_reputation: 1.0, decay_rate: 0.001, // 每天衰减0.1% decay_interval: 24 * 3600, // 1天 recovery_rate: 0.002, // 每次成功出块恢复0.2% event_weights, } } } /// 声誉管理器 pub struct ReputationManager { /// 声誉配置 config: ReputationConfig, /// 声誉变化记录 changes: Vec, /// 上次衰减时间 last_decay: HashMap, } impl ReputationManager { pub fn new() -> Self { Self { config: ReputationConfig::default(), changes: Vec::new(), last_decay: HashMap::new(), } } pub fn with_config(config: ReputationConfig) -> Self { Self { config, changes: Vec::new(), last_decay: HashMap::new(), } } /// 记录声誉事件 pub fn record_event( &mut self, node: &mut CbpNode, event: ReputationEvent, timestamp: u64, note: Option, ) -> Result { let old_reputation = node.reputation; // 获取事件权重 let weight = self.config.event_weights.get(&event) .copied() .unwrap_or(0.0); // 计算新声誉 let mut new_reputation = old_reputation + weight; new_reputation = new_reputation.max(self.config.min_reputation); new_reputation = new_reputation.min(self.config.max_reputation); // 更新节点声誉 node.reputation = new_reputation; // 记录变化 let change = ReputationChange { address: node.address, event, old_reputation, new_reputation, delta: new_reputation - old_reputation, timestamp, note, }; self.changes.push(change); Ok(new_reputation) } /// 应用声誉衰减 pub fn apply_decay( &mut self, node: &mut CbpNode, timestamp: u64, ) -> Result { // 获取上次衰减时间 let last_decay = self.last_decay.get(&node.address).copied().unwrap_or(node.registered_at); // 检查是否需要衰减 if timestamp < last_decay + self.config.decay_interval { return Ok(node.reputation); } // 计算衰减次数 let decay_count = (timestamp - last_decay) / self.config.decay_interval; let old_reputation = node.reputation; let mut new_reputation = old_reputation; // 应用衰减 for _ in 0..decay_count { new_reputation *= 1.0 - self.config.decay_rate; new_reputation = new_reputation.max(self.config.min_reputation); } // 更新节点声誉 node.reputation = new_reputation; // 更新上次衰减时间 self.last_decay.insert(node.address, timestamp); // 记录变化 if (new_reputation - old_reputation).abs() > 0.0001 { let change = ReputationChange { address: node.address, event: ReputationEvent::BlockMissed, // 使用BlockMissed表示衰减 old_reputation, new_reputation, delta: new_reputation - old_reputation, timestamp, note: Some(format!("Decay applied ({} intervals)", decay_count)), }; self.changes.push(change); } Ok(new_reputation) } /// 恢复声誉 pub fn recover_reputation( &mut self, node: &mut CbpNode, amount: f64, timestamp: u64, reason: String, ) -> Result { let old_reputation = node.reputation; let mut new_reputation = old_reputation + amount; new_reputation = new_reputation.min(self.config.max_reputation); // 更新节点声誉 node.reputation = new_reputation; // 记录变化 let change = ReputationChange { address: node.address, event: ReputationEvent::CommunityContribution, old_reputation, new_reputation, delta: new_reputation - old_reputation, timestamp, note: Some(reason), }; self.changes.push(change); Ok(new_reputation) } /// 批量更新声誉(用于出块奖励) pub fn batch_update_for_blocks( &mut self, nodes: &mut [CbpNode], timestamp: u64, ) -> Result { let mut updated = 0; for node in nodes.iter_mut() { if node.blocks_produced > 0 { self.record_event( node, ReputationEvent::BlockProduced, timestamp, Some(format!("Block production reward")), )?; updated += 1; } } Ok(updated) } /// 查询声誉历史 pub fn get_reputation_history( &self, address: &Address, limit: Option, ) -> Vec<&ReputationChange> { let mut history: Vec<&ReputationChange> = self.changes.iter() .filter(|c| &c.address == address) .collect(); // 按时间倒序 history.sort_by(|a, b| b.timestamp.cmp(&a.timestamp)); if let Some(limit) = limit { history.truncate(limit); } history } /// 查询声誉统计 pub fn get_reputation_statistics(&self, address: &Address) -> ReputationStatistics { let history: Vec<&ReputationChange> = self.changes.iter() .filter(|c| &c.address == address) .collect(); if history.is_empty() { return ReputationStatistics { total_changes: 0, positive_changes: 0, negative_changes: 0, total_gain: 0.0, total_loss: 0.0, current_reputation: self.config.initial_reputation, }; } let total_changes = history.len(); let positive_changes = history.iter().filter(|c| c.delta > 0.0).count(); let negative_changes = history.iter().filter(|c| c.delta < 0.0).count(); let total_gain: f64 = history.iter() .filter(|c| c.delta > 0.0) .map(|c| c.delta) .sum(); let total_loss: f64 = history.iter() .filter(|c| c.delta < 0.0) .map(|c| c.delta.abs()) .sum(); let current_reputation = history.first().map(|c| c.new_reputation).unwrap_or(self.config.initial_reputation); ReputationStatistics { total_changes, positive_changes, negative_changes, total_gain, total_loss, current_reputation, } } /// 获取声誉排名 pub fn get_reputation_ranking(&self, nodes: &[CbpNode]) -> Vec<(Address, f64)> { let mut ranking: Vec<(Address, f64)> = nodes.iter() .map(|n| (n.address, n.reputation)) .collect(); // 按声誉降序排序 ranking.sort_by(|a, b| b.1.partial_cmp(&a.1).expect("FIX-006: unexpected None/Err")); ranking } /// 更新配置 pub fn update_config(&mut self, config: ReputationConfig) { self.config = config; } /// 获取配置 pub fn get_config(&self) -> &ReputationConfig { &self.config } } impl Default for ReputationManager { fn default() -> Self { Self::new() } } /// 声誉统计 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ReputationStatistics { /// 总变化次数 pub total_changes: usize, /// 正向变化次数 pub positive_changes: usize, /// 负向变化次数 pub negative_changes: usize, /// 总增长 pub total_gain: f64, /// 总损失 pub total_loss: f64, /// 当前声誉 pub current_reputation: f64, } #[cfg(test)] mod tests { use super::*; use crate::CbpStatus; fn create_test_node() -> CbpNode { CbpNode { address: Address::new([1u8; 32]), did: "did:nac:test".to_string(), stake_amount: 100_000_000_000, kyc_level: 2, hardware_score: 8000, constitution_score: 80, status: CbpStatus::Active, registered_at: 1000, last_active_at: 2000, blocks_produced: 100, reputation: 0.5, } } #[test] fn test_record_event_positive() { let mut manager = ReputationManager::new(); let mut node = create_test_node(); let result = manager.record_event( &mut node, ReputationEvent::BlockProduced, 3000, None, ); assert!(result.is_ok()); assert!(node.reputation > 0.5); } #[test] fn test_record_event_negative() { let mut manager = ReputationManager::new(); let mut node = create_test_node(); let result = manager.record_event( &mut node, ReputationEvent::BlockMissed, 3000, None, ); assert!(result.is_ok()); assert!(node.reputation < 0.5); } #[test] fn test_reputation_bounds() { let mut manager = ReputationManager::new(); let mut node = create_test_node(); node.reputation = 0.99; // 测试最大值 manager.record_event(&mut node, ReputationEvent::LongUptime, 3000, None).expect("FIX-006: unexpected None/Err"); assert!(node.reputation <= 1.0); // 测试最小值 node.reputation = 0.01; manager.record_event(&mut node, ReputationEvent::DoubleSign, 3000, None).expect("FIX-006: unexpected None/Err"); assert!(node.reputation >= 0.0); } #[test] fn test_apply_decay() { let mut manager = ReputationManager::new(); let mut node = create_test_node(); node.reputation = 0.8; // 1天后衰减 let timestamp = node.registered_at + 24 * 3600; let result = manager.apply_decay(&mut node, timestamp); assert!(result.is_ok()); assert!(node.reputation < 0.8); } #[test] fn test_no_decay_before_interval() { let mut manager = ReputationManager::new(); let mut node = create_test_node(); node.reputation = 0.8; // 不足1天,不应该衰减 let timestamp = node.registered_at + 3600; let result = manager.apply_decay(&mut node, timestamp); assert!(result.is_ok()); assert_eq!(node.reputation, 0.8); } #[test] fn test_recover_reputation() { let mut manager = ReputationManager::new(); let mut node = create_test_node(); node.reputation = 0.5; let result = manager.recover_reputation( &mut node, 0.1, 3000, "Community contribution".to_string(), ); assert!(result.is_ok()); assert_eq!(node.reputation, 0.6); } #[test] fn test_batch_update_for_blocks() { let mut manager = ReputationManager::new(); let mut nodes = vec![ create_test_node(), create_test_node(), ]; nodes[0].blocks_produced = 10; nodes[1].blocks_produced = 5; let result = manager.batch_update_for_blocks(&mut nodes, 3000); assert!(result.is_ok()); assert_eq!(result.expect("mainnet: handle error"), 2); } #[test] fn test_get_reputation_history() { let mut manager = ReputationManager::new(); let mut node = create_test_node(); manager.record_event(&mut node, ReputationEvent::BlockProduced, 1000, None).expect("FIX-006: unexpected None/Err"); manager.record_event(&mut node, ReputationEvent::BlockProduced, 2000, None).expect("FIX-006: unexpected None/Err"); manager.record_event(&mut node, ReputationEvent::BlockMissed, 3000, None).expect("FIX-006: unexpected None/Err"); let history = manager.get_reputation_history(&node.address, None); assert_eq!(history.len(), 3); // 限制数量 let limited = manager.get_reputation_history(&node.address, Some(2)); assert_eq!(limited.len(), 2); } #[test] fn test_get_reputation_statistics() { let mut manager = ReputationManager::new(); let mut node = create_test_node(); manager.record_event(&mut node, ReputationEvent::BlockProduced, 1000, None).expect("FIX-006: unexpected None/Err"); manager.record_event(&mut node, ReputationEvent::BlockProduced, 2000, None).expect("FIX-006: unexpected None/Err"); manager.record_event(&mut node, ReputationEvent::BlockMissed, 3000, None).expect("FIX-006: unexpected None/Err"); let stats = manager.get_reputation_statistics(&node.address); assert_eq!(stats.total_changes, 3); assert_eq!(stats.positive_changes, 2); assert_eq!(stats.negative_changes, 1); } #[test] fn test_get_reputation_ranking() { let manager = ReputationManager::new(); let mut nodes = vec![ create_test_node(), create_test_node(), create_test_node(), ]; nodes[0].reputation = 0.8; nodes[1].reputation = 0.6; nodes[2].reputation = 0.9; let ranking = manager.get_reputation_ranking(&nodes); assert_eq!(ranking.len(), 3); assert_eq!(ranking[0].1, 0.9); assert_eq!(ranking[1].1, 0.8); assert_eq!(ranking[2].1, 0.6); } #[test] fn test_update_config() { let mut manager = ReputationManager::new(); let mut new_config = ReputationConfig::default(); new_config.decay_rate = 0.002; new_config.recovery_rate = 0.003; manager.update_config(new_config); let config = manager.get_config(); assert_eq!(config.decay_rate, 0.002); assert_eq!(config.recovery_rate, 0.003); } }