NAC_Blockchain/nac-udm/src/l1_protocol/acc/acc_rwa.rs

178 lines
8.0 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 - 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<Hash, RWAAssetRecord>,
/// 持仓asset_id -> (address -> amount)
pub holdings: HashMap<Hash, HashMap<Address, u128>>,
pub pending_events: Vec<RWAProtocolEvent>,
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<Hash, ACCRWAError> {
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(&timestamp.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<RWAProtocolEvent> { std::mem::take(&mut self.pending_events) }
}