// ACC-Custody: 资产托管协议(Custody Protocol) // // NAC原生的资产托管标准,用于多签托管和安全保管 // 100% NAC原生协议,不是任何现有标准的实现 use serde::{Deserialize, Serialize}; use std::collections::HashMap; /// 托管状态 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum CustodyStatus { /// 活跃 Active, /// 已暂停 Suspended, /// 已终止 Terminated, /// 待审核 Pending, } /// 托管类型 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum CustodyType { /// 单一托管人 Single, /// 多签托管(M-of-N) MultiSig { required: u8, total: u8 }, /// 时间锁托管 TimeLock { unlock_at: u64 }, /// 条件托管 Conditional, } /// 托管操作类型 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum CustodyOperation { /// 存入 Deposit, /// 取出 Withdraw, /// 转移 Transfer, /// 暂停 Suspend, /// 恢复 Resume, /// 终止 Terminate, } /// 托管记录 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct CustodyRecord { /// 托管ID pub custody_id: String, /// 资产ID pub asset_id: String, /// 所有者地址 pub owner: String, /// 托管人列表 pub custodians: Vec, /// 托管类型 pub custody_type: CustodyType, /// 托管状态 pub status: CustodyStatus, /// 创建时间 pub created_at: u64, /// 更新时间 pub updated_at: u64, /// 托管金额(如果是代币) pub amount: Option, /// 托管条件 pub conditions: Vec, /// 操作历史 pub operations: Vec, } /// 托管操作记录 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct CustodyOperationRecord { /// 操作类型 pub operation: CustodyOperation, /// 操作发起人 pub initiator: String, /// 签名列表 pub signatures: Vec, /// 操作时间 pub timestamp: u64, /// 操作数据 pub data: Option, } /// 托管错误类型 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum CustodyError { /// 托管记录不存在 RecordNotFound, /// 托管记录已存在 RecordAlreadyExists, /// 资产不存在 AssetNotFound, /// 未授权操作 Unauthorized, /// 签名不足 InsufficientSignatures, /// 托管已暂停 CustodySuspended, /// 托管已终止 CustodyTerminated, /// 时间锁未解锁 TimeLockNotUnlocked, /// 条件未满足 ConditionsNotMet, /// 无效的托管人 InvalidCustodian, } /// 托管状态 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct CustodyState { /// 托管记录映射 (custody_id -> CustodyRecord) pub custodies: HashMap, /// 资产托管映射 (asset_id -> custody_id) pub asset_custodies: HashMap, /// 所有者托管列表 (owner -> [custody_ids]) pub owner_custodies: HashMap>, /// 托管人托管列表 (custodian -> [custody_ids]) pub custodian_custodies: HashMap>, } /// ACC-Custody接口 pub trait ACCCustody { /// 创建托管 fn create_custody(&mut self, record: CustodyRecord) -> Result<(), CustodyError>; /// 获取托管记录 fn get_custody(&self, custody_id: &str) -> Result; /// 获取资产的托管记录 fn get_asset_custody(&self, asset_id: &str) -> Result; /// 存入资产 fn deposit( &mut self, custody_id: &str, initiator: &str, amount: Option, ) -> Result<(), CustodyError>; /// 取出资产 fn withdraw( &mut self, custody_id: &str, initiator: &str, signatures: Vec, amount: Option, ) -> Result<(), CustodyError>; /// 转移托管 fn transfer_custody( &mut self, custody_id: &str, new_owner: String, signatures: Vec, ) -> Result<(), CustodyError>; /// 暂停托管 fn suspend_custody( &mut self, custody_id: &str, initiator: &str, ) -> Result<(), CustodyError>; /// 恢复托管 fn resume_custody(&mut self, custody_id: &str, initiator: &str) -> Result<(), CustodyError>; /// 终止托管 fn terminate_custody( &mut self, custody_id: &str, signatures: Vec, ) -> Result<(), CustodyError>; /// 添加托管人 fn add_custodian(&mut self, custody_id: &str, custodian: String) -> Result<(), CustodyError>; /// 移除托管人 fn remove_custodian(&mut self, custody_id: &str, custodian: &str) -> Result<(), CustodyError>; /// 验证签名 fn verify_signatures(&self, custody_id: &str, signatures: &[String]) -> bool; /// 获取所有者的托管列表 fn get_owner_custodies(&self, owner: &str) -> Vec; /// 获取托管人的托管列表 fn get_custodian_custodies(&self, custodian: &str) -> Vec; } /// ACC-Custody标准实现 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct CustodyToken { state: CustodyState, } impl CustodyToken { /// 创建新的托管管理器 pub fn new() -> Self { Self { state: CustodyState { custodies: HashMap::new(), asset_custodies: HashMap::new(), owner_custodies: HashMap::new(), custodian_custodies: HashMap::new(), }, } } /// 获取状态的可变引用 pub fn state_mut(&mut self) -> &mut CustodyState { &mut self.state } /// 获取状态的不可变引用 pub fn state(&self) -> &CustodyState { &self.state } /// 检查托管状态 fn check_custody_status(&self, record: &CustodyRecord) -> Result<(), CustodyError> { match record.status { CustodyStatus::Suspended => Err(CustodyError::CustodySuspended), CustodyStatus::Terminated => Err(CustodyError::CustodyTerminated), _ => Ok(()), } } /// 记录操作 fn record_operation( &mut self, custody_id: &str, operation: CustodyOperation, initiator: &str, signatures: Vec, data: Option, ) -> Result<(), CustodyError> { let mut record = self.get_custody(custody_id)?; let now = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_secs(); let op_record = CustodyOperationRecord { operation, initiator: initiator.to_string(), signatures, timestamp: now, data, }; record.operations.push(op_record); record.updated_at = now; self.state .custodies .insert(custody_id.to_string(), record); Ok(()) } } impl Default for CustodyToken { fn default() -> Self { Self::new() } } impl ACCCustody for CustodyToken { fn create_custody(&mut self, mut record: CustodyRecord) -> Result<(), CustodyError> { // 检查托管记录是否已存在 if self.state.custodies.contains_key(&record.custody_id) { return Err(CustodyError::RecordAlreadyExists); } // 检查资产是否已被托管 if self.state.asset_custodies.contains_key(&record.asset_id) { return Err(CustodyError::RecordAlreadyExists); } let now = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_secs(); record.created_at = now; record.updated_at = now; record.status = CustodyStatus::Active; let custody_id = record.custody_id.clone(); let asset_id = record.asset_id.clone(); let owner = record.owner.clone(); let custodians = record.custodians.clone(); // 保存托管记录 self.state.custodies.insert(custody_id.clone(), record); // 更新资产托管映射 self.state .asset_custodies .insert(asset_id, custody_id.clone()); // 更新所有者托管列表 self.state .owner_custodies .entry(owner) .or_insert_with(Vec::new) .push(custody_id.clone()); // 更新托管人托管列表 for custodian in custodians { self.state .custodian_custodies .entry(custodian) .or_insert_with(Vec::new) .push(custody_id.clone()); } Ok(()) } fn get_custody(&self, custody_id: &str) -> Result { self.state .custodies .get(custody_id) .cloned() .ok_or(CustodyError::RecordNotFound) } fn get_asset_custody(&self, asset_id: &str) -> Result { let custody_id = self .state .asset_custodies .get(asset_id) .ok_or(CustodyError::AssetNotFound)?; self.get_custody(custody_id) } fn deposit( &mut self, custody_id: &str, initiator: &str, amount: Option, ) -> Result<(), CustodyError> { let record = self.get_custody(custody_id)?; self.check_custody_status(&record)?; self.record_operation( custody_id, CustodyOperation::Deposit, initiator, vec![], amount.map(|a| a.to_string()), ) } fn withdraw( &mut self, custody_id: &str, initiator: &str, signatures: Vec, amount: Option, ) -> Result<(), CustodyError> { let record = self.get_custody(custody_id)?; self.check_custody_status(&record)?; // 验证签名 if !self.verify_signatures(custody_id, &signatures) { return Err(CustodyError::InsufficientSignatures); } self.record_operation( custody_id, CustodyOperation::Withdraw, initiator, signatures, amount.map(|a| a.to_string()), ) } fn transfer_custody( &mut self, custody_id: &str, new_owner: String, signatures: Vec, ) -> Result<(), CustodyError> { let mut record = self.get_custody(custody_id)?; self.check_custody_status(&record)?; // 验证签名 if !self.verify_signatures(custody_id, &signatures) { return Err(CustodyError::InsufficientSignatures); } // 更新所有者 let old_owner = record.owner.clone(); record.owner = new_owner.clone(); // 更新所有者托管列表 if let Some(custodies) = self.state.owner_custodies.get_mut(&old_owner) { custodies.retain(|id| id != custody_id); } self.state .owner_custodies .entry(new_owner) .or_insert_with(Vec::new) .push(custody_id.to_string()); self.state .custodies .insert(custody_id.to_string(), record); self.record_operation( custody_id, CustodyOperation::Transfer, &old_owner, signatures, None, ) } fn suspend_custody( &mut self, custody_id: &str, initiator: &str, ) -> Result<(), CustodyError> { let mut record = self.get_custody(custody_id)?; record.status = CustodyStatus::Suspended; self.state .custodies .insert(custody_id.to_string(), record); self.record_operation( custody_id, CustodyOperation::Suspend, initiator, vec![], None, ) } fn resume_custody(&mut self, custody_id: &str, initiator: &str) -> Result<(), CustodyError> { let mut record = self.get_custody(custody_id)?; record.status = CustodyStatus::Active; self.state .custodies .insert(custody_id.to_string(), record); self.record_operation( custody_id, CustodyOperation::Resume, initiator, vec![], None, ) } fn terminate_custody( &mut self, custody_id: &str, signatures: Vec, ) -> Result<(), CustodyError> { let mut record = self.get_custody(custody_id)?; // 验证签名 if !self.verify_signatures(custody_id, &signatures) { return Err(CustodyError::InsufficientSignatures); } record.status = CustodyStatus::Terminated; self.state .custodies .insert(custody_id.to_string(), record); self.record_operation( custody_id, CustodyOperation::Terminate, "", signatures, None, ) } fn add_custodian(&mut self, custody_id: &str, custodian: String) -> Result<(), CustodyError> { let mut record = self.get_custody(custody_id)?; if !record.custodians.contains(&custodian) { record.custodians.push(custodian.clone()); self.state .custodies .insert(custody_id.to_string(), record); // 更新托管人托管列表 self.state .custodian_custodies .entry(custodian) .or_insert_with(Vec::new) .push(custody_id.to_string()); } Ok(()) } fn remove_custodian(&mut self, custody_id: &str, custodian: &str) -> Result<(), CustodyError> { let mut record = self.get_custody(custody_id)?; record.custodians.retain(|c| c != custodian); self.state .custodies .insert(custody_id.to_string(), record); // 更新托管人托管列表 if let Some(custodies) = self.state.custodian_custodies.get_mut(custodian) { custodies.retain(|id| id != custody_id); } Ok(()) } fn verify_signatures(&self, custody_id: &str, signatures: &[String]) -> bool { if let Ok(record) = self.get_custody(custody_id) { match &record.custody_type { CustodyType::Single => signatures.len() >= 1, CustodyType::MultiSig { required, .. } => { signatures.len() >= *required as usize } CustodyType::TimeLock { unlock_at } => { let now = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_secs(); now >= *unlock_at } CustodyType::Conditional => true, // 简化实现 } } else { false } } fn get_owner_custodies(&self, owner: &str) -> Vec { self.state .owner_custodies .get(owner) .map(|custody_ids| { custody_ids .iter() .filter_map(|id| self.state.custodies.get(id).cloned()) .collect() }) .unwrap_or_default() } fn get_custodian_custodies(&self, custodian: &str) -> Vec { self.state .custodian_custodies .get(custodian) .map(|custody_ids| { custody_ids .iter() .filter_map(|id| self.state.custodies.get(id).cloned()) .collect() }) .unwrap_or_default() } } #[cfg(test)] mod tests { use super::*; fn create_test_record() -> CustodyRecord { CustodyRecord { custody_id: "CUSTODY-001".to_string(), asset_id: "RWA-001".to_string(), owner: "alice".to_string(), custodians: vec!["custodian1".to_string(), "custodian2".to_string()], custody_type: CustodyType::MultiSig { required: 2, total: 2, }, status: CustodyStatus::Active, created_at: 0, updated_at: 0, amount: Some(1000000), conditions: Vec::new(), operations: Vec::new(), } } #[test] fn test_create_custody() { let mut custody = CustodyToken::new(); let record = create_test_record(); assert!(custody.create_custody(record).is_ok()); } #[test] fn test_deposit() { let mut custody = CustodyToken::new(); let record = create_test_record(); custody.create_custody(record).unwrap(); assert!(custody .deposit("CUSTODY-001", "alice", Some(500000)) .is_ok()); } #[test] fn test_withdraw() { let mut custody = CustodyToken::new(); let record = create_test_record(); custody.create_custody(record).unwrap(); let signatures = vec!["sig1".to_string(), "sig2".to_string()]; assert!(custody .withdraw("CUSTODY-001", "alice", signatures, Some(500000)) .is_ok()); } #[test] fn test_suspend_and_resume() { let mut custody = CustodyToken::new(); let record = create_test_record(); custody.create_custody(record).unwrap(); assert!(custody.suspend_custody("CUSTODY-001", "alice").is_ok()); assert_eq!( custody.get_custody("CUSTODY-001").unwrap().status, CustodyStatus::Suspended ); assert!(custody.resume_custody("CUSTODY-001", "alice").is_ok()); assert_eq!( custody.get_custody("CUSTODY-001").unwrap().status, CustodyStatus::Active ); } #[test] fn test_add_remove_custodian() { let mut custody = CustodyToken::new(); let record = create_test_record(); custody.create_custody(record).unwrap(); assert!(custody .add_custodian("CUSTODY-001", "custodian3".to_string()) .is_ok()); assert_eq!( custody.get_custody("CUSTODY-001").unwrap().custodians.len(), 3 ); assert!(custody .remove_custodian("CUSTODY-001", "custodian3") .is_ok()); assert_eq!( custody.get_custody("CUSTODY-001").unwrap().custodians.len(), 2 ); } }