NAC_Blockchain/nvm_v2/acc-protocol/src/acc_custody.rs

673 lines
18 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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<String>,
/// 托管类型
pub custody_type: CustodyType,
/// 托管状态
pub status: CustodyStatus,
/// 创建时间
pub created_at: u64,
/// 更新时间
pub updated_at: u64,
/// 托管金额(如果是代币)
pub amount: Option<u128>,
/// 托管条件
pub conditions: Vec<String>,
/// 操作历史
pub operations: Vec<CustodyOperationRecord>,
}
/// 托管操作记录
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CustodyOperationRecord {
/// 操作类型
pub operation: CustodyOperation,
/// 操作发起人
pub initiator: String,
/// 签名列表
pub signatures: Vec<String>,
/// 操作时间
pub timestamp: u64,
/// 操作数据
pub data: Option<String>,
}
/// 托管错误类型
#[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<String, CustodyRecord>,
/// 资产托管映射 (asset_id -> custody_id)
pub asset_custodies: HashMap<String, String>,
/// 所有者托管列表 (owner -> [custody_ids])
pub owner_custodies: HashMap<String, Vec<String>>,
/// 托管人托管列表 (custodian -> [custody_ids])
pub custodian_custodies: HashMap<String, Vec<String>>,
}
/// ACC-Custody接口
pub trait ACCCustody {
/// 创建托管
fn create_custody(&mut self, record: CustodyRecord) -> Result<(), CustodyError>;
/// 获取托管记录
fn get_custody(&self, custody_id: &str) -> Result<CustodyRecord, CustodyError>;
/// 获取资产的托管记录
fn get_asset_custody(&self, asset_id: &str) -> Result<CustodyRecord, CustodyError>;
/// 存入资产
fn deposit(
&mut self,
custody_id: &str,
initiator: &str,
amount: Option<u128>,
) -> Result<(), CustodyError>;
/// 取出资产
fn withdraw(
&mut self,
custody_id: &str,
initiator: &str,
signatures: Vec<String>,
amount: Option<u128>,
) -> Result<(), CustodyError>;
/// 转移托管
fn transfer_custody(
&mut self,
custody_id: &str,
new_owner: String,
signatures: Vec<String>,
) -> 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<String>,
) -> 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<CustodyRecord>;
/// 获取托管人的托管列表
fn get_custodian_custodies(&self, custodian: &str) -> Vec<CustodyRecord>;
}
/// 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<String>,
data: Option<String>,
) -> 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<CustodyRecord, CustodyError> {
self.state
.custodies
.get(custody_id)
.cloned()
.ok_or(CustodyError::RecordNotFound)
}
fn get_asset_custody(&self, asset_id: &str) -> Result<CustodyRecord, CustodyError> {
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<u128>,
) -> 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<String>,
amount: Option<u128>,
) -> 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<String>,
) -> 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<String>,
) -> 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<CustodyRecord> {
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<CustodyRecord> {
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
);
}
}