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

113 lines
5.5 KiB
Rust

//! acc_reserve - 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 ACCReserveError {
ReserveNotFound(String),
InsufficientReserve { asset: String, available: u128, requested: u128 },
InvalidConstitutionalReceipt,
Unauthorized(Address),
ReserveRatioViolation { required: u8, actual: u8 },
}
impl std::fmt::Display for ACCReserveError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::ReserveNotFound(s) => write!(f, "储备资产不存在: {}", s),
Self::InsufficientReserve { asset, available, requested } => write!(f, "储备不足 {}: 可用 {},请求 {}", asset, available, requested),
Self::InvalidConstitutionalReceipt => write!(f, "宪法收据无效"),
Self::Unauthorized(a) => write!(f, "未授权: {}", a.to_hex()),
Self::ReserveRatioViolation { required, actual } => write!(f, "储备率违规: 要求 {}%,实际 {}%", required, actual),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReserveEntry {
pub asset_symbol: String,
pub amount: u128,
pub custodian: Address,
pub last_audited: Timestamp,
pub audit_hash: Hash,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ReserveProtocolEvent {
ReserveDeposited { asset: String, amount: u128, custodian: Address, timestamp: Timestamp },
ReserveWithdrawn { asset: String, amount: u128, recipient: Address, constitutional_receipt: Hash, timestamp: Timestamp },
ReserveAudited { asset: String, audit_hash: Hash, timestamp: Timestamp },
}
/// ACC-Reserve 储备协议
/// UID: nac.acc.ACCReserveProtocol.v1
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ACCReserveProtocol {
pub protocol_uid: String,
pub lens_protocol_vector: String,
pub reserves: HashMap<String, ReserveEntry>,
/// 最低储备率(百分比)
pub min_reserve_ratio: u8,
pub pending_events: Vec<ReserveProtocolEvent>,
pub created_at: Timestamp,
pub updated_at: Timestamp,
}
impl ACCReserveProtocol {
pub fn new(min_reserve_ratio: u8) -> Self {
Self {
protocol_uid: "nac.acc.ACCReserveProtocol.v1".to_string(),
lens_protocol_vector: "ACC-Reserve".to_string(),
reserves: HashMap::new(),
min_reserve_ratio,
pending_events: Vec::new(),
created_at: Timestamp::now(),
updated_at: Timestamp::now(),
}
}
pub fn deposit(
&mut self, asset_symbol: String, amount: u128, custodian: Address,
constitutional_receipt: Hash, timestamp: Timestamp,
) -> Result<(), ACCReserveError> {
if constitutional_receipt.is_zero() { return Err(ACCReserveError::InvalidConstitutionalReceipt); }
let entry = self.reserves.entry(asset_symbol.clone()).or_insert(ReserveEntry {
asset_symbol: asset_symbol.clone(), amount: 0,
custodian: custodian.clone(), last_audited: timestamp.clone(),
audit_hash: Hash::zero(),
});
entry.amount = entry.amount.saturating_add(amount);
entry.custodian = custodian.clone();
self.pending_events.push(ReserveProtocolEvent::ReserveDeposited { asset: asset_symbol, amount, custodian, timestamp });
self.updated_at = Timestamp::now();
Ok(())
}
pub fn withdraw(
&mut self, asset_symbol: String, amount: u128, recipient: Address,
constitutional_receipt: Hash, timestamp: Timestamp,
) -> Result<(), ACCReserveError> {
if constitutional_receipt.is_zero() { return Err(ACCReserveError::InvalidConstitutionalReceipt); }
let entry = self.reserves.get_mut(&asset_symbol)
.ok_or_else(|| ACCReserveError::ReserveNotFound(asset_symbol.clone()))?;
if entry.amount < amount {
return Err(ACCReserveError::InsufficientReserve { asset: asset_symbol.clone(), available: entry.amount, requested: amount });
}
entry.amount -= amount;
self.pending_events.push(ReserveProtocolEvent::ReserveWithdrawn { asset: asset_symbol, amount, recipient, constitutional_receipt, timestamp });
self.updated_at = Timestamp::now();
Ok(())
}
pub fn audit(
&mut self, asset_symbol: String, audit_hash: Hash, timestamp: Timestamp,
) -> Result<(), ACCReserveError> {
let entry = self.reserves.get_mut(&asset_symbol)
.ok_or_else(|| ACCReserveError::ReserveNotFound(asset_symbol.clone()))?;
entry.last_audited = timestamp.clone();
entry.audit_hash = audit_hash;
self.pending_events.push(ReserveProtocolEvent::ReserveAudited { asset: asset_symbol, audit_hash, timestamp });
Ok(())
}
pub fn get_reserve(&self, asset: &str) -> Option<&ReserveEntry> { self.reserves.get(asset) }
pub fn total_reserve_count(&self) -> usize { self.reserves.len() }
pub fn drain_pending_events(&mut self) -> Vec<ReserveProtocolEvent> { std::mem::take(&mut self.pending_events) }
}