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

532 lines
15 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-RWA: 真实世界资产协议Real World Asset Protocol
//
// NAC原生的RWA资产标准专为真实世界资产上链设计
// 100% NAC原生协议不是任何现有标准的实现
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
/// RWA资产类型
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum RWAAssetType {
/// 不动产(房地产、土地)
RealEstate,
/// 贵金属(黄金、白银、铂金)
PreciousMetal,
/// 艺术品(绘画、雕塑、古董)
Artwork,
/// 股权(公司股权、基金份额)
Equity,
/// 债券(政府债券、企业债券)
Bond,
/// 大宗商品(石油、天然气、农产品)
Commodity,
/// 知识产权(专利、商标、版权)
IntellectualProperty,
/// 收藏品(邮票、钱币、珠宝)
Collectible,
/// 其他
Other(String),
}
/// RWA资产状态
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum RWAAssetStatus {
/// 待审核
Pending,
/// 已激活
Active,
/// 已冻结
Frozen,
/// 已注销
Deactivated,
}
/// RWA资产信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RWAAssetInfo {
/// 资产ID
pub asset_id: String,
/// 资产类型
pub asset_type: RWAAssetType,
/// 资产名称
pub name: String,
/// 资产描述
pub description: String,
/// 资产DNANAC原生简化为String
pub asset_dna: String,
/// GNACS分类编码NAC原生
pub gnacs_code: String,
/// 所有者地址
pub owner: String,
/// 估值USD以分为单位
pub valuation_usd: u128,
/// 资产状态
pub status: RWAAssetStatus,
/// 物理位置
pub physical_location: Option<String>,
/// 法律文件哈希列表简化为String列表
pub legal_documents: Vec<String>,
/// 创建时间Unix时间戳
pub created_at: u64,
/// 更新时间Unix时间戳
pub updated_at: u64,
/// 最后审计时间
pub last_audited_at: Option<u64>,
}
/// RWA资产错误类型
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum RWAError {
/// 资产不存在
AssetNotFound,
/// 资产已存在
AssetAlreadyExists,
/// 无效的所有者
InvalidOwner,
/// 资产已冻结
AssetFrozen,
/// 未授权操作
Unauthorized,
/// 无效的资产DNA
InvalidAssetDNA,
/// 无效的GNACS编码
InvalidGNACSCode,
/// 估值过期
ValuationExpired,
/// 法律文件缺失
MissingLegalDocuments,
}
/// RWA资产状态
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RWAState {
/// 资产映射 (asset_id -> RWAAssetInfo)
pub assets: HashMap<String, RWAAssetInfo>,
/// 所有者资产列表 (owner -> [asset_ids])
pub owner_assets: HashMap<String, Vec<String>>,
/// 资产DNA索引 (dna_hash -> asset_id)
pub dna_index: HashMap<String, String>,
/// GNACS索引 (gnacs_code -> [asset_ids])
pub gnacs_index: HashMap<String, Vec<String>>,
}
/// ACC-RWA接口
pub trait ACCRwa {
/// 注册RWA资产
fn register_asset(&mut self, asset_info: RWAAssetInfo) -> Result<(), RWAError>;
/// 获取RWA资产信息
fn get_asset(&self, asset_id: &str) -> Result<RWAAssetInfo, RWAError>;
/// 更新资产估值
fn update_valuation(&mut self, asset_id: &str, new_valuation: u128) -> Result<(), RWAError>;
/// 转移资产所有权
fn transfer_ownership(&mut self, asset_id: &str, new_owner: String) -> Result<(), RWAError>;
/// 冻结资产
fn freeze_asset(&mut self, asset_id: &str) -> Result<(), RWAError>;
/// 解冻资产
fn unfreeze_asset(&mut self, asset_id: &str) -> Result<(), RWAError>;
/// 注销资产
fn deactivate_asset(&mut self, asset_id: &str) -> Result<(), RWAError>;
/// 添加法律文件
fn add_legal_document(&mut self, asset_id: &str, document_hash: String) -> Result<(), RWAError>;
/// 获取所有者的资产列表
fn get_owner_assets(&self, owner: &str) -> Vec<RWAAssetInfo>;
/// 按GNACS编码查询资产
fn get_assets_by_gnacs(&self, gnacs_code: &str) -> Vec<RWAAssetInfo>;
/// 按资产类型查询资产
fn get_assets_by_type(&self, asset_type: RWAAssetType) -> Vec<RWAAssetInfo>;
/// 更新审计时间
fn update_audit_time(&mut self, asset_id: &str) -> Result<(), RWAError>;
}
/// ACC-RWA标准实现
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RwaToken {
state: RWAState,
}
impl RwaToken {
/// 创建新的RWA资产管理器
pub fn new() -> Self {
Self {
state: RWAState {
assets: HashMap::new(),
owner_assets: HashMap::new(),
dna_index: HashMap::new(),
gnacs_index: HashMap::new(),
},
}
}
/// 获取状态的可变引用
pub fn state_mut(&mut self) -> &mut RWAState {
&mut self.state
}
/// 获取状态的不可变引用
pub fn state(&self) -> &RWAState {
&self.state
}
/// 生成资产DNA简化实现
fn generate_asset_dna(&self, asset_id: &str) -> String {
format!("DNA-{}", asset_id)
}
/// 验证资产DNA
fn validate_asset_dna(&self, dna: &str) -> bool {
dna.starts_with("DNA-") && dna.len() > 4
}
/// 验证GNACS编码
fn validate_gnacs_code(&self, code: &str) -> bool {
// 简化验证检查格式应为NAC-XXXX-XXXX格式
code.starts_with("NAC-") && code.len() >= 8
}
}
impl Default for RwaToken {
fn default() -> Self {
Self::new()
}
}
impl ACCRwa for RwaToken {
fn register_asset(&mut self, mut asset_info: RWAAssetInfo) -> Result<(), RWAError> {
// 检查资产是否已存在
if self.state.assets.contains_key(&asset_info.asset_id) {
return Err(RWAError::AssetAlreadyExists);
}
// 验证GNACS编码
if !self.validate_gnacs_code(&asset_info.gnacs_code) {
return Err(RWAError::InvalidGNACSCode);
}
// 生成资产DNA
if asset_info.asset_dna.is_empty() {
asset_info.asset_dna = self.generate_asset_dna(&asset_info.asset_id);
}
// 验证资产DNA
if !self.validate_asset_dna(&asset_info.asset_dna) {
return Err(RWAError::InvalidAssetDNA);
}
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs();
asset_info.created_at = now;
asset_info.updated_at = now;
asset_info.status = RWAAssetStatus::Active;
let asset_id = asset_info.asset_id.clone();
let owner = asset_info.owner.clone();
let dna = asset_info.asset_dna.clone();
let gnacs_code = asset_info.gnacs_code.clone();
// 保存资产信息
self.state.assets.insert(asset_id.clone(), asset_info);
// 更新所有者资产列表
self.state
.owner_assets
.entry(owner)
.or_insert_with(Vec::new)
.push(asset_id.clone());
// 更新DNA索引
self.state.dna_index.insert(dna, asset_id.clone());
// 更新GNACS索引
self.state
.gnacs_index
.entry(gnacs_code)
.or_insert_with(Vec::new)
.push(asset_id);
Ok(())
}
fn get_asset(&self, asset_id: &str) -> Result<RWAAssetInfo, RWAError> {
self.state
.assets
.get(asset_id)
.cloned()
.ok_or(RWAError::AssetNotFound)
}
fn update_valuation(&mut self, asset_id: &str, new_valuation: u128) -> Result<(), RWAError> {
let mut asset = self.get_asset(asset_id)?;
if asset.status == RWAAssetStatus::Frozen {
return Err(RWAError::AssetFrozen);
}
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs();
asset.valuation_usd = new_valuation;
asset.updated_at = now;
self.state.assets.insert(asset_id.to_string(), asset);
Ok(())
}
fn transfer_ownership(&mut self, asset_id: &str, new_owner: String) -> Result<(), RWAError> {
let mut asset = self.get_asset(asset_id)?;
if asset.status == RWAAssetStatus::Frozen {
return Err(RWAError::AssetFrozen);
}
let old_owner = asset.owner.clone();
asset.owner = new_owner.clone();
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs();
asset.updated_at = now;
// 更新所有者资产列表
if let Some(assets) = self.state.owner_assets.get_mut(&old_owner) {
assets.retain(|id| id != asset_id);
}
self.state
.owner_assets
.entry(new_owner)
.or_insert_with(Vec::new)
.push(asset_id.to_string());
self.state.assets.insert(asset_id.to_string(), asset);
Ok(())
}
fn freeze_asset(&mut self, asset_id: &str) -> Result<(), RWAError> {
let mut asset = self.get_asset(asset_id)?;
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs();
asset.status = RWAAssetStatus::Frozen;
asset.updated_at = now;
self.state.assets.insert(asset_id.to_string(), asset);
Ok(())
}
fn unfreeze_asset(&mut self, asset_id: &str) -> Result<(), RWAError> {
let mut asset = self.get_asset(asset_id)?;
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs();
asset.status = RWAAssetStatus::Active;
asset.updated_at = now;
self.state.assets.insert(asset_id.to_string(), asset);
Ok(())
}
fn deactivate_asset(&mut self, asset_id: &str) -> Result<(), RWAError> {
let mut asset = self.get_asset(asset_id)?;
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs();
asset.status = RWAAssetStatus::Deactivated;
asset.updated_at = now;
self.state.assets.insert(asset_id.to_string(), asset);
Ok(())
}
fn add_legal_document(&mut self, asset_id: &str, document_hash: String) -> Result<(), RWAError> {
let mut asset = self.get_asset(asset_id)?;
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs();
asset.legal_documents.push(document_hash);
asset.updated_at = now;
self.state.assets.insert(asset_id.to_string(), asset);
Ok(())
}
fn get_owner_assets(&self, owner: &str) -> Vec<RWAAssetInfo> {
self.state
.owner_assets
.get(owner)
.map(|asset_ids| {
asset_ids
.iter()
.filter_map(|id| self.state.assets.get(id).cloned())
.collect()
})
.unwrap_or_default()
}
fn get_assets_by_gnacs(&self, gnacs_code: &str) -> Vec<RWAAssetInfo> {
self.state
.gnacs_index
.get(gnacs_code)
.map(|asset_ids| {
asset_ids
.iter()
.filter_map(|id| self.state.assets.get(id).cloned())
.collect()
})
.unwrap_or_default()
}
fn get_assets_by_type(&self, asset_type: RWAAssetType) -> Vec<RWAAssetInfo> {
self.state
.assets
.values()
.filter(|asset| asset.asset_type == asset_type)
.cloned()
.collect()
}
fn update_audit_time(&mut self, asset_id: &str) -> Result<(), RWAError> {
let mut asset = self.get_asset(asset_id)?;
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs();
asset.last_audited_at = Some(now);
asset.updated_at = now;
self.state.assets.insert(asset_id.to_string(), asset);
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
fn create_test_asset() -> RWAAssetInfo {
RWAAssetInfo {
asset_id: "RWA-001".to_string(),
asset_type: RWAAssetType::RealEstate,
name: "Test Property".to_string(),
description: "A test real estate asset".to_string(),
asset_dna: String::new(),
gnacs_code: "NAC-RE-001".to_string(),
owner: "alice".to_string(),
valuation_usd: 1000000_00,
status: RWAAssetStatus::Pending,
physical_location: Some("123 Main St".to_string()),
legal_documents: vec!["doc1".to_string()],
created_at: 0,
updated_at: 0,
last_audited_at: None,
}
}
#[test]
fn test_register_asset() {
let mut rwa = RwaToken::new();
let asset = create_test_asset();
assert!(rwa.register_asset(asset).is_ok());
}
#[test]
fn test_update_valuation() {
let mut rwa = RwaToken::new();
let asset = create_test_asset();
rwa.register_asset(asset).unwrap();
assert!(rwa.update_valuation("RWA-001", 1200000_00).is_ok());
assert_eq!(rwa.get_asset("RWA-001").unwrap().valuation_usd, 1200000_00);
}
#[test]
fn test_transfer_ownership() {
let mut rwa = RwaToken::new();
let asset = create_test_asset();
rwa.register_asset(asset).unwrap();
assert!(rwa.transfer_ownership("RWA-001", "bob".to_string()).is_ok());
assert_eq!(rwa.get_asset("RWA-001").unwrap().owner, "bob");
}
#[test]
fn test_freeze_unfreeze_asset() {
let mut rwa = RwaToken::new();
let asset = create_test_asset();
rwa.register_asset(asset).unwrap();
assert!(rwa.freeze_asset("RWA-001").is_ok());
assert_eq!(rwa.get_asset("RWA-001").unwrap().status, RWAAssetStatus::Frozen);
assert!(rwa.unfreeze_asset("RWA-001").is_ok());
assert_eq!(rwa.get_asset("RWA-001").unwrap().status, RWAAssetStatus::Active);
}
#[test]
fn test_add_legal_document() {
let mut rwa = RwaToken::new();
let asset = create_test_asset();
rwa.register_asset(asset).unwrap();
assert!(rwa.add_legal_document("RWA-001", "doc2".to_string()).is_ok());
assert_eq!(rwa.get_asset("RWA-001").unwrap().legal_documents.len(), 2);
}
#[test]
fn test_get_owner_assets() {
let mut rwa = RwaToken::new();
let asset = create_test_asset();
rwa.register_asset(asset).unwrap();
let assets = rwa.get_owner_assets("alice");
assert_eq!(assets.len(), 1);
}
#[test]
fn test_get_assets_by_gnacs() {
let mut rwa = RwaToken::new();
let asset = create_test_asset();
rwa.register_asset(asset).unwrap();
let assets = rwa.get_assets_by_gnacs("NAC-RE-001");
assert_eq!(assets.len(), 1);
}
}