178 lines
8.0 KiB
Rust
178 lines
8.0 KiB
Rust
//! 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(×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<RWAProtocolEvent> { std::mem::take(&mut self.pending_events) }
|
||
}
|