//! acc_rwa - NAC 原生协议实现 //! 从 acc_remaining_protocols.rs 提取 use crate::primitives::{Address, Hash, Timestamp}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum ACCRWAError { AssetNotFound(Hash), AssetAlreadyRegistered(Hash), InvalidConstitutionalReceipt, Unauthorized(Address), ComplianceCheckFailed(String), ValuationExpired(Hash), AssetFrozen(Hash), } impl std::fmt::Display for ACCRWAError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::AssetNotFound(h) => write!(f, "RWA 资产不存在: {}", h.to_hex()), Self::AssetAlreadyRegistered(h) => write!(f, "RWA 资产已注册: {}", h.to_hex()), Self::InvalidConstitutionalReceipt => write!(f, "宪法收据无效"), Self::Unauthorized(a) => write!(f, "未授权: {}", a.to_hex()), Self::ComplianceCheckFailed(msg) => write!(f, "合规检查失败: {}", msg), Self::ValuationExpired(h) => write!(f, "估值已过期: {}", h.to_hex()), Self::AssetFrozen(h) => write!(f, "资产已冻结: {}", h.to_hex()), } } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] pub enum RWAAssetType { RealEstate, CorporateBond, GovernmentBond, Commodity, PrivateEquity, Infrastructure, IntellectualProperty, NaturalResource, Other, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] pub enum RWAAssetStatus { Pending, Active, Frozen, Redeemed, Delisted } /// RWA 资产记录 /// UID: nac.acc.RWAAssetRecord.v1 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct RWAAssetRecord { pub asset_id: Hash, pub gnacs_code: String, pub asset_type: RWAAssetType, pub owner: Address, pub issuer: Address, pub total_supply: u128, pub current_valuation_xtzh: u128, pub jurisdiction: String, pub status: RWAAssetStatus, /// 法律文件哈希(SHA3-384) pub legal_document_hash: Hash, /// AI 合规评分(0-100) pub ai_compliance_score: u8, pub constitutional_receipt: Hash, pub registered_at: Timestamp, pub updated_at: Timestamp, } #[derive(Debug, Clone, Serialize, Deserialize)] pub enum RWAProtocolEvent { AssetRegistered { asset_id: Hash, gnacs_code: String, owner: Address, valuation: u128, timestamp: Timestamp }, AssetTransferred { asset_id: Hash, from: Address, to: Address, amount: u128, timestamp: Timestamp }, AssetFrozen { asset_id: Hash, reason: String, timestamp: Timestamp, constitutional_receipt: Hash }, AssetUnfrozen { asset_id: Hash, timestamp: Timestamp, constitutional_receipt: Hash }, ValuationUpdated { asset_id: Hash, old_value: u128, new_value: u128, timestamp: Timestamp }, } /// ACC-RWA 真实世界资产协议 /// UID: nac.acc.ACCRWAProtocol.v1 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ACCRWAProtocol { pub protocol_uid: String, pub lens_protocol_vector: String, pub assets: HashMap, /// 持仓(asset_id -> (address -> amount)) pub holdings: HashMap>, pub pending_events: Vec, pub created_at: Timestamp, pub updated_at: Timestamp, } impl ACCRWAProtocol { pub fn new() -> Self { Self { protocol_uid: "nac.acc.ACCRWAProtocol.v1".to_string(), lens_protocol_vector: "ACC-RWA".to_string(), assets: HashMap::new(), holdings: HashMap::new(), pending_events: Vec::new(), created_at: Timestamp::now(), updated_at: Timestamp::now(), } } pub fn register_asset( &mut self, gnacs_code: String, asset_type: RWAAssetType, owner: Address, issuer: Address, total_supply: u128, initial_valuation_xtzh: u128, jurisdiction: String, legal_document_hash: Hash, ai_compliance_score: u8, constitutional_receipt: Hash, timestamp: Timestamp, ) -> Result { if constitutional_receipt.is_zero() { return Err(ACCRWAError::InvalidConstitutionalReceipt); } if ai_compliance_score < 60 { return Err(ACCRWAError::ComplianceCheckFailed(format!("AI 合规评分不足: {}/100", ai_compliance_score))); } let mut data = Vec::new(); data.extend_from_slice(gnacs_code.as_bytes()); data.extend_from_slice(owner.as_bytes()); data.extend_from_slice(×tamp.as_secs().to_be_bytes()); let asset_id = Hash::sha3_384(&data); if self.assets.contains_key(&asset_id) { return Err(ACCRWAError::AssetAlreadyRegistered(asset_id)); } let record = RWAAssetRecord { asset_id, gnacs_code: gnacs_code.clone(), asset_type, owner: owner.clone(), issuer, total_supply, current_valuation_xtzh: initial_valuation_xtzh, jurisdiction, status: RWAAssetStatus::Active, legal_document_hash, ai_compliance_score, constitutional_receipt, registered_at: timestamp.clone(), updated_at: timestamp.clone(), }; let mut asset_holdings = HashMap::new(); asset_holdings.insert(owner.clone(), total_supply); self.holdings.insert(asset_id, asset_holdings); self.assets.insert(asset_id, record); self.pending_events.push(RWAProtocolEvent::AssetRegistered { asset_id, gnacs_code, owner, valuation: initial_valuation_xtzh, timestamp, }); self.updated_at = Timestamp::now(); Ok(asset_id) } pub fn transfer_asset( &mut self, asset_id: Hash, from: Address, to: Address, amount: u128, timestamp: Timestamp, ) -> Result<(), ACCRWAError> { let asset = self.assets.get(&asset_id).ok_or(ACCRWAError::AssetNotFound(asset_id))?; if asset.status == RWAAssetStatus::Frozen { return Err(ACCRWAError::AssetFrozen(asset_id)); } let holdings = self.holdings.get_mut(&asset_id).ok_or(ACCRWAError::AssetNotFound(asset_id))?; let from_balance = holdings.get(&from).copied().unwrap_or(0); if from_balance < amount { return Err(ACCRWAError::Unauthorized(from.clone())); } *holdings.get_mut(&from).unwrap() -= amount; *holdings.entry(to.clone()).or_insert(0) += amount; self.pending_events.push(RWAProtocolEvent::AssetTransferred { asset_id, from, to, amount, timestamp }); Ok(()) } pub fn freeze_asset( &mut self, asset_id: Hash, reason: String, constitutional_receipt: Hash, timestamp: Timestamp, ) -> Result<(), ACCRWAError> { if constitutional_receipt.is_zero() { return Err(ACCRWAError::InvalidConstitutionalReceipt); } let asset = self.assets.get_mut(&asset_id).ok_or(ACCRWAError::AssetNotFound(asset_id))?; asset.status = RWAAssetStatus::Frozen; asset.updated_at = timestamp.clone(); self.pending_events.push(RWAProtocolEvent::AssetFrozen { asset_id, reason, timestamp, constitutional_receipt }); Ok(()) } pub fn update_valuation( &mut self, asset_id: Hash, new_valuation: u128, constitutional_receipt: Hash, timestamp: Timestamp, ) -> Result<(), ACCRWAError> { if constitutional_receipt.is_zero() { return Err(ACCRWAError::InvalidConstitutionalReceipt); } let asset = self.assets.get_mut(&asset_id).ok_or(ACCRWAError::AssetNotFound(asset_id))?; let old_value = asset.current_valuation_xtzh; asset.current_valuation_xtzh = new_valuation; asset.updated_at = timestamp.clone(); self.pending_events.push(RWAProtocolEvent::ValuationUpdated { asset_id, old_value, new_value: new_valuation, timestamp }); Ok(()) } pub fn get_asset(&self, id: &Hash) -> Option<&RWAAssetRecord> { self.assets.get(id) } pub fn balance_of(&self, asset_id: &Hash, holder: &Address) -> u128 { self.holdings.get(asset_id).and_then(|h| h.get(holder)).copied().unwrap_or(0) } pub fn drain_pending_events(&mut self) -> Vec { std::mem::take(&mut self.pending_events) } }