//! NAC CBPP L1层 - Charter合约实现 //! //! 实现CBP(Constitutional Block Producer)注册与管理合约 //! 基于CBPP技术白皮书第5章"开放生产网络(OPN)" use nac_udm::primitives::{Address, Hash}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use thiserror::Error; // 导出子模块 pub mod exit; pub mod redemption; pub mod reputation; pub mod penalty; // 重新导出常用类型 pub use exit::{ExitManager, ExitRequest, ExitRecord, ExitStatus, ExitReason}; pub use redemption::{RedemptionManager, RedemptionRequest, RedemptionRecord, RedemptionType, RedemptionStatus}; pub use reputation::{ReputationManager, ReputationEvent, ReputationChange, ReputationConfig}; pub use penalty::{PenaltyManager, ViolationType, PenaltyType, PenaltyRecord, AppealRequest}; #[derive(Debug, Error)] pub enum CbppL1Error { #[error("CBP already registered: {0:?}")] AlreadyRegistered(Address), #[error("CBP not found: {0:?}")] NotFound(Address), #[error("Insufficient stake: required {required}, got {actual}")] InsufficientStake { required: u64, actual: u64 }, #[error("Invalid KYC level: {0}")] InvalidKycLevel(u8), #[error("Hardware benchmark failed")] HardwareBenchmarkFailed, #[error("Constitution test failed: score {0}/100")] ConstitutionTestFailed(u8), // 退出相关错误 #[error("Exit request already exists")] ExitRequestExists, #[error("Exit request not found")] ExitRequestNotFound, #[error("Review period not met")] ReviewPeriodNotMet, #[error("Confirmation period not met")] ConfirmationPeriodNotMet, // 赎回相关错误 #[error("Redemption request already exists")] RedemptionRequestExists, #[error("Redemption request not found")] RedemptionRequestNotFound, #[error("Lock period not met")] LockPeriodNotMet, #[error("Invalid redemption amount")] InvalidRedemptionAmount, #[error("Insufficient remaining stake")] InsufficientRemainingStake, #[error("Insufficient stake for penalty")] InsufficientStakeForPenalty, // 处罚相关错误 #[error("Unknown violation type")] UnknownViolationType, #[error("Penalty record not found")] PenaltyRecordNotFound, #[error("Already appealed")] AlreadyAppealed, #[error("Appeal period expired")] AppealPeriodExpired, #[error("Appeal not found")] AppealNotFound, #[error("Invalid address")] InvalidAddress, // 通用错误 #[error("Invalid status: {0}")] InvalidStatus(String), } /// CBP节点状态 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] pub enum CbpStatus { Candidate, Active, Suspended, Exited, } /// CBP节点信息 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct CbpNode { pub address: Address, pub did: String, pub stake_amount: u64, pub kyc_level: u8, pub hardware_score: u32, pub constitution_score: u8, pub status: CbpStatus, pub registered_at: u64, pub last_active_at: u64, pub blocks_produced: u64, pub reputation: f64, } /// CBP注册要求 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct CbpRequirements { pub min_stake: u64, pub min_kyc_level: u8, pub min_hardware_score: u32, pub min_constitution_score: u8, } impl Default for CbpRequirements { fn default() -> Self { Self { min_stake: 100_000_000_000, min_kyc_level: 2, min_hardware_score: 7000, min_constitution_score: 70, } } } /// CBP注册与管理合约 pub struct CbpRegistry { nodes: HashMap
, requirements: CbpRequirements, active_cbps: Vec, exit_manager: ExitManager, redemption_manager: RedemptionManager, reputation_manager: ReputationManager, penalty_manager: PenaltyManager, } impl CbpRegistry { pub fn new() -> Self { Self { nodes: HashMap::new(), requirements: CbpRequirements::default(), active_cbps: Vec::new(), exit_manager: ExitManager::new(), redemption_manager: RedemptionManager::new(), reputation_manager: ReputationManager::new(), penalty_manager: PenaltyManager::new(), } } pub fn register_cbp( &mut self, address: Address, did: String, stake_amount: u64, kyc_level: u8, hardware_score: u32, constitution_score: u8, timestamp: u64, ) -> Result<(), CbppL1Error> { if self.nodes.contains_key(&address) { return Err(CbppL1Error::AlreadyRegistered(address)); } if stake_amount < self.requirements.min_stake { return Err(CbppL1Error::InsufficientStake { required: self.requirements.min_stake, actual: stake_amount, }); } if kyc_level < self.requirements.min_kyc_level { return Err(CbppL1Error::InvalidKycLevel(kyc_level)); } if hardware_score < self.requirements.min_hardware_score { return Err(CbppL1Error::HardwareBenchmarkFailed); } if constitution_score < self.requirements.min_constitution_score { return Err(CbppL1Error::ConstitutionTestFailed(constitution_score)); } let node = CbpNode { address, did, stake_amount, kyc_level, hardware_score, constitution_score, status: CbpStatus::Candidate, registered_at: timestamp, last_active_at: timestamp, blocks_produced: 0, reputation: 0.5, }; self.nodes.insert(address, node); Ok(()) } pub fn activate_cbp(&mut self, address: &Address) -> Result<(), CbppL1Error> { let node = self.nodes.get_mut(address) .ok_or(CbppL1Error::NotFound(*address))?; if node.status == CbpStatus::Candidate { node.status = CbpStatus::Active; self.active_cbps.push(*address); } Ok(()) } pub fn suspend_cbp(&mut self, address: &Address) -> Result<(), CbppL1Error> { let node = self.nodes.get_mut(address) .ok_or(CbppL1Error::NotFound(*address))?; if node.status == CbpStatus::Active { node.status = CbpStatus::Suspended; self.active_cbps.retain(|addr| addr != address); } Ok(()) } pub fn get_cbp(&self, address: &Address) -> Option<&CbpNode> { self.nodes.get(address) } pub fn get_cbp_mut(&mut self, address: &Address) -> Option<&mut CbpNode> { self.nodes.get_mut(address) } pub fn get_active_cbps(&self) -> &[Address] { &self.active_cbps } pub fn get_all_nodes(&self) -> Vec<&CbpNode> { self.nodes.values().collect() } // 退出管理 pub fn exit_manager(&self) -> &ExitManager { &self.exit_manager } pub fn exit_manager_mut(&mut self) -> &mut ExitManager { &mut self.exit_manager } // 赎回管理 pub fn redemption_manager(&self) -> &RedemptionManager { &self.redemption_manager } pub fn redemption_manager_mut(&mut self) -> &mut RedemptionManager { &mut self.redemption_manager } // 声誉管理 pub fn reputation_manager(&self) -> &ReputationManager { &self.reputation_manager } pub fn reputation_manager_mut(&mut self) -> &mut ReputationManager { &mut self.reputation_manager } // 处罚管理 pub fn penalty_manager(&self) -> &PenaltyManager { &self.penalty_manager } pub fn penalty_manager_mut(&mut self) -> &mut PenaltyManager { &mut self.penalty_manager } } impl Default for CbpRegistry { fn default() -> Self { Self::new() } } #[cfg(test)] mod tests { use super::*; #[test] fn test_register_cbp() { let mut registry = CbpRegistry::new(); let address = Address::new([1u8; 32]); let result = registry.register_cbp( address, "did:nac:test".to_string(), 100_000_000_000, 2, 8000, 80, 1000, ); assert!(result.is_ok()); assert!(registry.get_cbp(&address).is_some()); } #[test] fn test_activate_cbp() { let mut registry = CbpRegistry::new(); let address = Address::new([1u8; 32]); registry.register_cbp( address, "did:nac:test".to_string(), 100_000_000_000, 2, 8000, 80, 1000, ).unwrap(); let result = registry.activate_cbp(&address); assert!(result.is_ok()); let node = registry.get_cbp(&address).unwrap(); assert_eq!(node.status, CbpStatus::Active); } #[test] fn test_suspend_cbp() { let mut registry = CbpRegistry::new(); let address = Address::new([1u8; 32]); registry.register_cbp( address, "did:nac:test".to_string(), 100_000_000_000, 2, 8000, 80, 1000, ).unwrap(); registry.activate_cbp(&address).unwrap(); let result = registry.suspend_cbp(&address); assert!(result.is_ok()); let node = registry.get_cbp(&address).unwrap(); assert_eq!(node.status, CbpStatus::Suspended); } #[test] fn test_integrated_managers() { let registry = CbpRegistry::new(); // 测试所有管理器都已初始化 assert!(registry.exit_manager().get_pending_requests().is_empty()); assert!(registry.redemption_manager().get_pending_requests().is_empty()); assert!(registry.penalty_manager().get_penalty_records(None).is_empty()); } }