//! 资产锁定/解锁模块 use crate::error::{BridgeError, BridgeResult}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; /// 锁定记录 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct LockRecord { /// 锁定ID pub lock_id: String, /// 以太坊交易哈希 pub eth_tx_hash: String, /// 锁定金额 pub amount: u128, /// Token地址(None表示ETH) pub token_address: Option, /// NAC目标地址 pub nac_target_address: [u8; 32], /// 锁定时间戳 pub locked_at: u64, /// 状态 pub status: LockStatus, /// 签名列表(多签) pub signatures: Vec, } /// 锁定状态 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub enum LockStatus { /// 待确认 Pending, /// 已确认 Confirmed, /// 已解锁 Unlocked, /// 已取消 Cancelled, } /// 签名 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Signature { /// 签名者地址 pub signer: String, /// 签名数据 pub signature: Vec, /// 签名时间 pub signed_at: u64, } /// 解锁请求 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct UnlockRequest { /// 解锁ID pub unlock_id: String, /// NAC交易哈希 pub nac_tx_hash: String, /// 解锁金额 pub amount: u128, /// Token地址(None表示ETH) pub token_address: Option, /// 以太坊目标地址 pub eth_target_address: String, /// 请求时间戳 pub requested_at: u64, /// 状态 pub status: UnlockStatus, /// 签名列表(多签) pub signatures: Vec, } /// 解锁状态 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub enum UnlockStatus { /// 待审批 PendingApproval, /// 已批准 Approved, /// 已执行 Executed, /// 已拒绝 Rejected, } /// 锁定/解锁管理器 pub struct LockUnlockManager { /// 锁定记录 locks: HashMap, /// 解锁请求 unlocks: HashMap, /// 多签阈值 multisig_threshold: usize, /// 授权签名者列表 authorized_signers: Vec, } impl LockUnlockManager { /// 创建新的管理器 pub fn new(multisig_threshold: usize, authorized_signers: Vec) -> Self { Self { locks: HashMap::new(), unlocks: HashMap::new(), multisig_threshold, authorized_signers, } } /// 记录锁定 pub fn record_lock(&mut self, lock: LockRecord) -> BridgeResult<()> { if self.locks.contains_key(&lock.lock_id) { return Err(BridgeError::ValidationError( "Lock ID already exists".to_string() )); } self.locks.insert(lock.lock_id.clone(), lock); Ok(()) } /// 获取锁定记录 pub fn get_lock(&self, lock_id: &str) -> Option<&LockRecord> { self.locks.get(lock_id) } /// 添加锁定签名 pub fn add_lock_signature( &mut self, lock_id: &str, signature: Signature, ) -> BridgeResult<()> { // 验证签名者 if !self.authorized_signers.contains(&signature.signer) { return Err(BridgeError::SecurityError( "Unauthorized signer".to_string() )); } let lock = self.locks.get_mut(lock_id) .ok_or_else(|| BridgeError::ValidationError("Lock not found".to_string()))?; // 检查是否已签名 if lock.signatures.iter().any(|s| s.signer == signature.signer) { return Err(BridgeError::ValidationError( "Signer already signed".to_string() )); } lock.signatures.push(signature); // 检查是否达到阈值 if lock.signatures.len() >= self.multisig_threshold { lock.status = LockStatus::Confirmed; } Ok(()) } /// 记录解锁请求 pub fn record_unlock(&mut self, unlock: UnlockRequest) -> BridgeResult<()> { if self.unlocks.contains_key(&unlock.unlock_id) { return Err(BridgeError::ValidationError( "Unlock ID already exists".to_string() )); } self.unlocks.insert(unlock.unlock_id.clone(), unlock); Ok(()) } /// 获取解锁请求 pub fn get_unlock(&self, unlock_id: &str) -> Option<&UnlockRequest> { self.unlocks.get(unlock_id) } /// 添加解锁签名 pub fn add_unlock_signature( &mut self, unlock_id: &str, signature: Signature, ) -> BridgeResult<()> { // 验证签名者 if !self.authorized_signers.contains(&signature.signer) { return Err(BridgeError::SecurityError( "Unauthorized signer".to_string() )); } let unlock = self.unlocks.get_mut(unlock_id) .ok_or_else(|| BridgeError::ValidationError("Unlock not found".to_string()))?; // 检查是否已签名 if unlock.signatures.iter().any(|s| s.signer == signature.signer) { return Err(BridgeError::ValidationError( "Signer already signed".to_string() )); } unlock.signatures.push(signature); // 检查是否达到阈值 if unlock.signatures.len() >= self.multisig_threshold { unlock.status = UnlockStatus::Approved; } Ok(()) } /// 执行解锁 pub fn execute_unlock(&mut self, unlock_id: &str) -> BridgeResult<()> { let unlock = self.unlocks.get_mut(unlock_id) .ok_or_else(|| BridgeError::ValidationError("Unlock not found".to_string()))?; if unlock.status != UnlockStatus::Approved { return Err(BridgeError::ValidationError( "Unlock not approved".to_string() )); } unlock.status = UnlockStatus::Executed; Ok(()) } /// 获取所有待确认的锁定 pub fn get_pending_locks(&self) -> Vec<&LockRecord> { self.locks.values() .filter(|lock| lock.status == LockStatus::Pending) .collect() } /// 获取所有待审批的解锁 pub fn get_pending_unlocks(&self) -> Vec<&UnlockRequest> { self.unlocks.values() .filter(|unlock| unlock.status == UnlockStatus::PendingApproval) .collect() } } #[cfg(test)] mod tests { use super::*; #[test] fn test_lock_unlock_manager() { let signers = vec!["signer1".to_string(), "signer2".to_string()]; let mut manager = LockUnlockManager::new(2, signers); // 测试锁定 let lock = LockRecord { lock_id: "lock1".to_string(), eth_tx_hash: "0x123".to_string(), amount: 1000, token_address: None, nac_target_address: [0u8; 32], locked_at: 1234567890, status: LockStatus::Pending, signatures: vec![], }; assert!(manager.record_lock(lock).is_ok()); assert!(manager.get_lock("lock1").is_some()); // 测试签名 let sig1 = Signature { signer: "signer1".to_string(), signature: vec![1, 2, 3], signed_at: 1234567891, }; assert!(manager.add_lock_signature("lock1", sig1).is_ok()); assert_eq!(manager.get_lock("lock1").unwrap().signatures.len(), 1); let sig2 = Signature { signer: "signer2".to_string(), signature: vec![4, 5, 6], signed_at: 1234567892, }; assert!(manager.add_lock_signature("lock1", sig2).is_ok()); assert_eq!(manager.get_lock("lock1").unwrap().status, LockStatus::Confirmed); } #[test] fn test_unauthorized_signer() { let signers = vec!["signer1".to_string()]; let mut manager = LockUnlockManager::new(1, signers); let lock = LockRecord { lock_id: "lock1".to_string(), eth_tx_hash: "0x123".to_string(), amount: 1000, token_address: None, nac_target_address: [0u8; 32], locked_at: 1234567890, status: LockStatus::Pending, signatures: vec![], }; manager.record_lock(lock).unwrap(); let sig = Signature { signer: "unauthorized".to_string(), signature: vec![1, 2, 3], signed_at: 1234567891, }; assert!(manager.add_lock_signature("lock1", sig).is_err()); } }