NAC_Blockchain/nac-acc-1410/src/transfer.rs

435 lines
13 KiB
Rust

//! 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<String, HashSet<String>>,
/// 分区级操作员授权(账户 -> 分区ID -> 操作员集合)
partition_operators: HashMap<String, HashMap<String, HashSet<String>>>,
}
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<String, u64>,
}
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<u64> {
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<TransferResult> {
// 预检查
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<TransferResult> {
// 检查操作员权限
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());
}
}