//! Transfer Manager //! 转账管理器 - 处理分区间转账和操作员授权 use crate::error::{Acc1410Error, Result}; use crate::partition::PartitionManager; use crate::types::{TransferResult, TransferStatus}; use std::collections::{HashMap, HashSet}; /// 操作员授权管理器 #[derive(Debug)] pub struct OperatorManager { /// 全局操作员授权(账户 -> 操作员集合) global_operators: HashMap>, /// 分区级操作员授权(账户 -> 分区ID -> 操作员集合) partition_operators: HashMap>>, } impl OperatorManager { pub fn new() -> Self { Self { global_operators: HashMap::new(), partition_operators: HashMap::new(), } } /// 授权全局操作员 pub fn authorize_operator(&mut self, account: &str, operator: &str) { self.global_operators .entry(account.to_string()) .or_insert_with(HashSet::new) .insert(operator.to_string()); } /// 撤销全局操作员 pub fn revoke_operator(&mut self, account: &str, operator: &str) { if let Some(operators) = self.global_operators.get_mut(account) { operators.remove(operator); } } /// 授权分区级操作员 pub fn authorize_operator_by_partition( &mut self, account: &str, partition_id: &[u8; 32], operator: &str, ) { let partition_id_hex = hex::encode(partition_id); self.partition_operators .entry(account.to_string()) .or_insert_with(HashMap::new) .entry(partition_id_hex) .or_insert_with(HashSet::new) .insert(operator.to_string()); } /// 撤销分区级操作员 pub fn revoke_operator_by_partition( &mut self, account: &str, partition_id: &[u8; 32], operator: &str, ) { let partition_id_hex = hex::encode(partition_id); if let Some(partitions) = self.partition_operators.get_mut(account) { if let Some(operators) = partitions.get_mut(&partition_id_hex) { operators.remove(operator); } } } /// 检查是否为全局操作员 pub fn is_operator_for(&self, account: &str, operator: &str) -> bool { self.global_operators .get(account) .map(|ops| ops.contains(operator)) .unwrap_or(false) } /// 检查是否为分区级操作员 pub fn is_operator_for_partition( &self, account: &str, partition_id: &[u8; 32], operator: &str, ) -> bool { let partition_id_hex = hex::encode(partition_id); self.partition_operators .get(account) .and_then(|partitions| partitions.get(&partition_id_hex)) .map(|ops| ops.contains(operator)) .unwrap_or(false) } } impl Default for OperatorManager { fn default() -> Self { Self::new() } } /// 转账管理器 #[derive(Debug)] pub struct TransferManager { /// 分区管理器 partition_manager: PartitionManager, /// 操作员管理器 operator_manager: OperatorManager, /// 转账是否暂停 transfers_halted: bool, /// 账户锁定期(账户 -> 解锁时间戳) account_locks: HashMap, } impl TransferManager { pub fn new(partition_manager: PartitionManager) -> Self { Self { partition_manager, operator_manager: OperatorManager::new(), transfers_halted: false, account_locks: HashMap::new(), } } /// 获取分区管理器的引用 pub fn partition_manager(&self) -> &PartitionManager { &self.partition_manager } /// 获取分区管理器的可变引用 pub fn partition_manager_mut(&mut self) -> &mut PartitionManager { &mut self.partition_manager } /// 获取操作员管理器的引用 pub fn operator_manager(&self) -> &OperatorManager { &self.operator_manager } /// 获取操作员管理器的可变引用 pub fn operator_manager_mut(&mut self) -> &mut OperatorManager { &mut self.operator_manager } /// 暂停所有转账 pub fn halt_transfers(&mut self) { self.transfers_halted = true; } /// 恢复转账 pub fn resume_transfers(&mut self) { self.transfers_halted = false; } /// 锁定账户 pub fn lock_account(&mut self, account: &str, unlock_time: u64) { self.account_locks.insert(account.to_string(), unlock_time); } /// 解锁账户 pub fn unlock_account(&mut self, account: &str) { self.account_locks.remove(account); } /// 检查账户是否被锁定 fn is_account_locked(&self, account: &str) -> Option { self.account_locks.get(account).copied().and_then(|unlock_time| { let now = Self::current_timestamp(); if now < unlock_time { Some(unlock_time) } else { None } }) } /// 分区间转账 pub fn transfer_by_partition( &mut self, from: &str, to: &str, amount: u64, partition_id: &[u8; 32], ) -> Result { // 预检查 self.pre_transfer_check(from, to, partition_id)?; // 执行转账 self.partition_manager.sub_balance(partition_id, from, amount)?; self.partition_manager.add_balance(partition_id, to, amount)?; Ok(TransferResult { status: TransferStatus::Success, reason: None, destination_partition: Some(*partition_id), }) } /// 操作员代理转账 pub fn operator_transfer_by_partition( &mut self, operator: &str, from: &str, to: &str, amount: u64, partition_id: &[u8; 32], ) -> Result { // 检查操作员权限 if !self.operator_manager.is_operator_for(from, operator) && !self.operator_manager.is_operator_for_partition(from, partition_id, operator) { return Err(Acc1410Error::UnauthorizedOperator { operator: operator.to_string(), account: from.to_string(), }); } // 预检查 self.pre_transfer_check(from, to, partition_id)?; // 执行转账 self.partition_manager.sub_balance(partition_id, from, amount)?; self.partition_manager.add_balance(partition_id, to, amount)?; Ok(TransferResult { status: TransferStatus::Success, reason: None, destination_partition: Some(*partition_id), }) } /// 转账前检查 fn pre_transfer_check( &self, from: &str, to: &str, partition_id: &[u8; 32], ) -> Result<()> { // 检查转账是否暂停 if self.transfers_halted { return Err(Acc1410Error::TransfersHalted); } // 检查发送方是否被锁定 if let Some(unlock_time) = self.is_account_locked(from) { return Err(Acc1410Error::FundsLocked { account: from.to_string(), unlock_time, }); } // 检查接收方是否有效(简单验证非空) if to.is_empty() { return Err(Acc1410Error::InvalidReceiver(to.to_string())); } // 检查发送方是否有效 if from.is_empty() { return Err(Acc1410Error::InvalidSender(from.to_string())); } // 检查分区是否存在且激活 let info = self.partition_manager.get_partition_info(partition_id)?; if !info.is_active { return Err(Acc1410Error::PartitionClosed(hex::encode(partition_id))); } Ok(()) } /// 获取当前时间戳 fn current_timestamp() -> u64 { std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_secs() } } #[cfg(test)] mod tests { use super::*; use crate::types::{ExtendedGNACS, GNACSExtension, PartitionType}; fn create_test_partition(manager: &mut PartitionManager) -> [u8; 32] { let extended_gnacs = ExtendedGNACS { base_gnacs: vec![0; 6], extension: GNACSExtension { partition_type: 0x01, vesting_years: 0, voting_multiplier: 1, dividend_priority: 1, }, }; manager .create_partition( "Test Partition".to_string(), extended_gnacs, PartitionType::CommonStock, ) .unwrap() } #[test] fn test_operator_authorization() { let mut op_manager = OperatorManager::new(); // 授权全局操作员 op_manager.authorize_operator("user1", "operator1"); assert!(op_manager.is_operator_for("user1", "operator1")); // 撤销全局操作员 op_manager.revoke_operator("user1", "operator1"); assert!(!op_manager.is_operator_for("user1", "operator1")); } #[test] fn test_partition_operator_authorization() { let mut op_manager = OperatorManager::new(); let partition_id = [1u8; 32]; // 授权分区级操作员 op_manager.authorize_operator_by_partition("user1", &partition_id, "operator1"); assert!(op_manager.is_operator_for_partition("user1", &partition_id, "operator1")); // 撤销分区级操作员 op_manager.revoke_operator_by_partition("user1", &partition_id, "operator1"); assert!(!op_manager.is_operator_for_partition("user1", &partition_id, "operator1")); } #[test] fn test_transfer_by_partition() { let mut partition_manager = PartitionManager::new(); let partition_id = create_test_partition(&mut partition_manager); // 初始化余额 partition_manager.add_balance(&partition_id, "user1", 1000).unwrap(); let mut transfer_manager = TransferManager::new(partition_manager); // 执行转账 let result = transfer_manager .transfer_by_partition("user1", "user2", 300, &partition_id) .unwrap(); assert_eq!(result.status, TransferStatus::Success); assert_eq!( transfer_manager .partition_manager() .balance_of_by_partition(&partition_id, "user1") .unwrap(), 700 ); assert_eq!( transfer_manager .partition_manager() .balance_of_by_partition(&partition_id, "user2") .unwrap(), 300 ); } #[test] fn test_operator_transfer() { let mut partition_manager = PartitionManager::new(); let partition_id = create_test_partition(&mut partition_manager); partition_manager.add_balance(&partition_id, "user1", 1000).unwrap(); let mut transfer_manager = TransferManager::new(partition_manager); // 授权操作员 transfer_manager .operator_manager_mut() .authorize_operator("user1", "operator1"); // 操作员代理转账 let result = transfer_manager .operator_transfer_by_partition("operator1", "user1", "user2", 200, &partition_id) .unwrap(); assert_eq!(result.status, TransferStatus::Success); assert_eq!( transfer_manager .partition_manager() .balance_of_by_partition(&partition_id, "user1") .unwrap(), 800 ); } #[test] fn test_transfers_halted() { let mut partition_manager = PartitionManager::new(); let partition_id = create_test_partition(&mut partition_manager); partition_manager.add_balance(&partition_id, "user1", 1000).unwrap(); let mut transfer_manager = TransferManager::new(partition_manager); // 暂停转账 transfer_manager.halt_transfers(); // 尝试转账应失败 let result = transfer_manager.transfer_by_partition("user1", "user2", 100, &partition_id); assert!(result.is_err()); } #[test] fn test_account_lock() { let mut partition_manager = PartitionManager::new(); let partition_id = create_test_partition(&mut partition_manager); partition_manager.add_balance(&partition_id, "user1", 1000).unwrap(); let mut transfer_manager = TransferManager::new(partition_manager); // 锁定账户 let future_time = TransferManager::current_timestamp() + 3600; // 1小时后 transfer_manager.lock_account("user1", future_time); // 尝试转账应失败 let result = transfer_manager.transfer_by_partition("user1", "user2", 100, &partition_id); assert!(result.is_err()); // 解锁账户 transfer_manager.unlock_account("user1"); // 现在应该可以转账 let result = transfer_manager.transfer_by_partition("user1", "user2", 100, &partition_id); assert!(result.is_ok()); } }