NAC_Blockchain/nac-acc-1594/src/lib.rs

590 lines
18 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.

//! NAC ACC-1594 Protocol Implementation
//! NAC ACC-1594协议实现 - 基于GNACS数字基因的核心收益与资产操作协议
//!
//! ACC-1594在继承ACC-1400的基础上增加了
//! 1. 资产生命周期操作(发行、赎回)
//! 2. 收益分配系统(分红、领取)
//! 3. GNACS收益扩展编码80位
//! 4. 宪法收据强制验证
//! 5. AI驱动的收益计算
pub mod error;
pub mod types;
pub use error::{Acc1594Error, Result};
pub use types::*;
use nac_acc_1400::Acc1400;
use nac_acc_1410::Acc1410;
use std::collections::HashMap;
/// ACC-1594核心收益与资产操作协议
#[derive(Debug)]
pub struct Acc1594 {
/// 基础ACC-1400实例
#[allow(dead_code)]
base: Acc1400,
/// ACC-1410实例用于访问底层方法
base1410: Acc1410,
/// 资产GNACS含收益扩展
asset_gnacs: FullDividendGNACS,
/// 是否可发行
is_issuable: bool,
/// 发行上限
issuance_limit: Option<u64>,
/// 发行记录
issuance_records: Vec<IssuanceRecord>,
/// 赎回记录
redemption_records: Vec<RedemptionRecord>,
/// 分红记录(按分区)
dividend_records: HashMap<String, Vec<DividendRecord>>,
/// 可领取分红(账户 -> 分区 -> 金额)
claimable_dividends: HashMap<String, HashMap<String, u64>>,
/// 账户持有开始时间(用于检查最低持有期)
holding_start_time: HashMap<String, u64>,
/// 授权角色(角色名 -> 地址列表)
authorized_roles: HashMap<String, Vec<String>>,
}
impl Acc1594 {
/// 创建新的ACC-1594实例
pub fn new(asset_gnacs: FullDividendGNACS) -> Self {
Self {
base: Acc1400::new(),
base1410: Acc1410::new(),
asset_gnacs,
is_issuable: true,
issuance_limit: None,
issuance_records: Vec::new(),
redemption_records: Vec::new(),
dividend_records: HashMap::new(),
claimable_dividends: HashMap::new(),
holding_start_time: HashMap::new(),
authorized_roles: HashMap::new(),
}
}
/// 设置发行上限
pub fn set_issuance_limit(&mut self, limit: u64) {
self.issuance_limit = Some(limit);
}
/// 设置是否可发行
pub fn set_issuable(&mut self, issuable: bool) {
self.is_issuable = issuable;
}
/// 授权角色
pub fn authorize_role(&mut self, role: &str, address: &str) {
self.authorized_roles
.entry(role.to_string())
.or_insert_with(Vec::new)
.push(address.to_string());
}
/// 检查角色权限
pub fn has_role(&self, role: &str, address: &str) -> bool {
self.authorized_roles
.get(role)
.map(|addresses| addresses.contains(&address.to_string()))
.unwrap_or(false)
}
// ==================== 资产生命周期操作 ====================
/// 发行新资产(增加总供应量)
pub fn issue(
&mut self,
operator: &str,
to: &str,
amount: u64,
data: Vec<u8>,
partition_id: &[u8; 32],
receipt_hash: [u8; 32],
) -> Result<()> {
// 检查权限
if !self.has_role("ISSUER", operator) {
return Err(Acc1594Error::Unauthorized {
operator: operator.to_string(),
required_role: "ISSUER".to_string(),
});
}
// 检查是否可发行
if !self.is_issuable {
return Err(Acc1594Error::NotIssuable("Asset is not issuable".to_string()));
}
// 检查发行上限
if let Some(limit) = self.issuance_limit {
let current_supply = self.total_supply(partition_id)?;
if current_supply + amount > limit {
return Err(Acc1594Error::ExceedsIssuanceLimit {
current: current_supply + amount,
limit,
});
}
}
// 发行到分区
self.base1410.issue_to_partition(partition_id, to, amount)?;
// 记录持有开始时间
if !self.holding_start_time.contains_key(to) {
self.holding_start_time.insert(to.to_string(), Self::current_timestamp());
}
// 记录发行
self.issuance_records.push(IssuanceRecord {
operator: operator.to_string(),
to: to.to_string(),
amount,
data,
timestamp: Self::current_timestamp(),
receipt_hash,
});
Ok(())
}
/// 赎回资产(销毁)
pub fn redeem(
&mut self,
account: &str,
amount: u64,
data: Vec<u8>,
partition_id: &[u8; 32],
receipt_hash: [u8; 32],
) -> Result<()> {
// 检查赎回策略
let policy = RedemptionPolicy::from(self.asset_gnacs.dividend_extension.redemption_policy);
if policy == RedemptionPolicy::NonRedeemable {
return Err(Acc1594Error::RedemptionNotAllowed(
"Asset is non-redeemable".to_string(),
));
}
// 检查最低持有期
self.check_min_holding_period(account)?;
// 从分区销毁
self.base1410.burn_from_partition(partition_id, account, amount)?;
// 记录赎回
self.redemption_records.push(RedemptionRecord {
operator: account.to_string(),
from: account.to_string(),
amount,
data,
timestamp: Self::current_timestamp(),
receipt_hash,
});
Ok(())
}
/// 操作员代表持有者赎回
pub fn operator_redeem(
&mut self,
operator: &str,
token_holder: &str,
amount: u64,
data: Vec<u8>,
partition_id: &[u8; 32],
receipt_hash: [u8; 32],
) -> Result<()> {
// 检查操作员权限
if !self.base1410.is_operator_for(token_holder, operator) {
return Err(Acc1594Error::Unauthorized {
operator: operator.to_string(),
required_role: "OPERATOR".to_string(),
});
}
// 检查赎回策略
let policy = RedemptionPolicy::from(self.asset_gnacs.dividend_extension.redemption_policy);
if policy == RedemptionPolicy::NonRedeemable {
return Err(Acc1594Error::RedemptionNotAllowed(
"Asset is non-redeemable".to_string(),
));
}
// 检查最低持有期
self.check_min_holding_period(token_holder)?;
// 从分区销毁
self.base1410.burn_from_partition(partition_id, token_holder, amount)?;
// 记录赎回
self.redemption_records.push(RedemptionRecord {
operator: operator.to_string(),
from: token_holder.to_string(),
amount,
data,
timestamp: Self::current_timestamp(),
receipt_hash,
});
Ok(())
}
/// 检查资产是否可发行
pub fn is_issuable(&self) -> bool {
self.is_issuable
}
// ==================== 收益分配 ====================
/// 分配收益(由宪法执行引擎自动触发,或授权角色手动触发)
pub fn distribute_dividend(
&mut self,
operator: &str,
partition_id: &[u8; 32],
total_amount: u64,
period: u64,
receipt_hash: [u8; 32],
) -> Result<()> {
// 检查权限
if !self.has_role("DISTRIBUTOR", operator) {
return Err(Acc1594Error::Unauthorized {
operator: operator.to_string(),
required_role: "DISTRIBUTOR".to_string(),
});
}
// 获取分区总供应量
let total_supply = self.total_supply(partition_id)?;
if total_supply == 0 {
return Ok(());
}
// 获取所有持有者并分配
let partition_id_hex = hex::encode(partition_id);
let holders = self.get_all_holders(partition_id)?;
for account in holders {
let balance = self.base1410.balance_of_by_partition(partition_id, &account)?;
// 修复:先乘后除避免整数除法精度损失
let dividend = (balance * total_amount) / total_supply;
self.claimable_dividends
.entry(account.clone())
.or_insert_with(HashMap::new)
.entry(partition_id_hex.clone())
.and_modify(|e| *e += dividend)
.or_insert(dividend);
}
// 记录分红
let per_share_amount = if total_supply > 0 { total_amount / total_supply } else { 0 };
let record = DividendRecord {
period,
total_amount,
per_share_amount,
timestamp: Self::current_timestamp(),
receipt_hash,
};
self.dividend_records
.entry(partition_id_hex)
.or_insert_with(Vec::new)
.push(record);
Ok(())
}
/// 查询账户可领取的收益(分区级)
pub fn claimable_dividend(&self, account: &str, partition_id: &[u8; 32]) -> u64 {
let partition_id_hex = hex::encode(partition_id);
self.claimable_dividends
.get(account)
.and_then(|partitions| partitions.get(&partition_id_hex))
.copied()
.unwrap_or(0)
}
/// 领取收益自动转入账户XTZH余额
pub fn claim_dividend(
&mut self,
account: &str,
partition_id: &[u8; 32],
_receipt_hash: [u8; 32],
) -> Result<u64> {
let partition_id_hex = hex::encode(partition_id);
let amount = self.claimable_dividend(account, partition_id);
if amount == 0 {
return Err(Acc1594Error::NoClaimableDividend {
account: account.to_string(),
partition: partition_id_hex,
});
}
// 清除可领取分红
if let Some(partitions) = self.claimable_dividends.get_mut(account) {
partitions.remove(&partition_id_hex);
}
Ok(amount)
}
/// 批量领取收益(多个分区)
pub fn claim_multiple_dividends(
&mut self,
account: &str,
partition_ids: &[[u8; 32]],
receipt_hash: [u8; 32],
) -> Result<u64> {
let mut total = 0;
for partition_id in partition_ids {
if let Ok(amount) = self.claim_dividend(account, partition_id, receipt_hash) {
total += amount;
}
}
Ok(total)
}
/// 获取历史分红记录
pub fn get_dividend_history(
&self,
partition_id: &[u8; 32],
from: u64,
to: u64,
) -> Vec<DividendRecord> {
let partition_id_hex = hex::encode(partition_id);
self.dividend_records
.get(&partition_id_hex)
.map(|records| {
records
.iter()
.filter(|r| r.period >= from && r.period <= to)
.cloned()
.collect()
})
.unwrap_or_default()
}
// ==================== 资产状态查询 ====================
/// 获取资产GNACS含收益扩展
pub fn asset_gnacs(&self) -> &FullDividendGNACS {
&self.asset_gnacs
}
/// 获取资产总供应量
pub fn total_supply(&self, partition_id: &[u8; 32]) -> Result<u64> {
// 简化实现:返回分区信息中的总供应量
let info = self.base1410.get_partition_info(partition_id)?;
Ok(info.total_supply)
}
/// 获取账户余额(指定分区)
pub fn balance_of(&self, account: &str, partition_id: &[u8; 32]) -> Result<u64> {
Ok(self.base1410.balance_of_by_partition(partition_id, account)?)
}
/// 获取资产净值由AI估值引擎提供
pub fn net_asset_value(&self) -> (u64, u64) {
// 简化实现:返回模拟的净值和时间戳
(1000000, Self::current_timestamp())
}
// ==================== 辅助方法 ====================
/// 检查最低持有期
fn check_min_holding_period(&self, account: &str) -> Result<()> {
let min_period = self.asset_gnacs.dividend_extension.min_holding_period;
if min_period == 0 {
return Ok(());
}
if let Some(&start_time) = self.holding_start_time.get(account) {
let current_time = Self::current_timestamp();
let held_seconds = current_time - start_time;
let held_months = (held_seconds / (30 * 24 * 3600)) as u8;
if held_months < min_period {
return Err(Acc1594Error::MinHoldingPeriodNotMet {
required_months: min_period,
held_months,
});
}
}
Ok(())
}
/// 获取分区的所有持有者
fn get_all_holders(&self, partition_id: &[u8; 32]) -> Result<Vec<String>> {
// 从持有开始时间记录中获取所有账户,筛选出在该分区有余额的账户
let mut holders = Vec::new();
for account in self.holding_start_time.keys() {
if let Ok(balance) = self.base1410.balance_of_by_partition(partition_id, account) {
if balance > 0 {
holders.push(account.clone());
}
}
}
Ok(holders)
}
/// 获取当前时间戳
fn current_timestamp() -> u64 {
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs()
}
}
#[cfg(test)]
mod tests {
use super::*;
use nac_acc_1410::{ExtendedGNACS, GNACSExtension, PartitionType};
fn create_test_acc1594() -> (Acc1594, [u8; 32]) {
let dividend_gnacs = FullDividendGNACS {
base_gnacs: vec![0x94, 0x01, 0x00, 0x04, 0x02, 0x01],
dividend_extension: DividendGNACSExtension {
dividend_policy: 1, // 固定比例
dividend_period: 4, // 年度
dividend_rate: 5, // 5%
redemption_policy: 1, // 按面值赎回
min_holding_period: 0, // 无最低持有期
},
};
let mut acc1594 = Acc1594::new(dividend_gnacs);
// 授权角色
acc1594.authorize_role("ISSUER", "issuer1");
acc1594.authorize_role("DISTRIBUTOR", "distributor1");
// 创建分区
let extended_gnacs = ExtendedGNACS {
base_gnacs: vec![0x94, 0x01, 0x00, 0x04, 0x02, 0x01],
extension: GNACSExtension {
partition_type: 0x01,
vesting_years: 0,
voting_multiplier: 1,
dividend_priority: 1,
},
};
let partition_id = acc1594
.base1410
.create_partition(
"Test Partition".to_string(),
extended_gnacs,
PartitionType::CommonStock,
)
.unwrap();
(acc1594, partition_id)
}
#[test]
fn test_issue() {
let (mut acc1594, partition_id) = create_test_acc1594();
let result = acc1594.issue(
"issuer1",
"investor1",
1000,
vec![],
&partition_id,
[0u8; 32],
);
assert!(result.is_ok());
assert_eq!(acc1594.balance_of("investor1", &partition_id).unwrap(), 1000);
}
#[test]
fn test_redeem() {
let (mut acc1594, partition_id) = create_test_acc1594();
acc1594
.issue("issuer1", "investor1", 1000, vec![], &partition_id, [0u8; 32])
.unwrap();
let result = acc1594.redeem("investor1", 300, vec![], &partition_id, [0u8; 32]);
assert!(result.is_ok());
assert_eq!(acc1594.balance_of("investor1", &partition_id).unwrap(), 700);
}
#[test]
fn test_distribute_dividend() {
let (mut acc1594, partition_id) = create_test_acc1594();
// 发行给两个投资者
acc1594
.issue("issuer1", "investor1", 600, vec![], &partition_id, [0u8; 32])
.unwrap();
acc1594
.issue("issuer1", "investor2", 400, vec![], &partition_id, [0u8; 32])
.unwrap();
// 分配分红
let result = acc1594.distribute_dividend(
"distributor1",
&partition_id,
1000,
202601,
[0u8; 32],
);
assert!(result.is_ok());
// 检查可领取分红
assert_eq!(acc1594.claimable_dividend("investor1", &partition_id), 600);
assert_eq!(acc1594.claimable_dividend("investor2", &partition_id), 400);
}
#[test]
fn test_claim_dividend() {
let (mut acc1594, partition_id) = create_test_acc1594();
acc1594
.issue("issuer1", "investor1", 1000, vec![], &partition_id, [0u8; 32])
.unwrap();
acc1594
.distribute_dividend("distributor1", &partition_id, 500, 202601, [0u8; 32])
.unwrap();
let claimed = acc1594
.claim_dividend("investor1", &partition_id, [0u8; 32])
.unwrap();
assert_eq!(claimed, 500);
assert_eq!(acc1594.claimable_dividend("investor1", &partition_id), 0);
}
#[test]
fn test_issuance_limit() {
let (mut acc1594, partition_id) = create_test_acc1594();
acc1594.set_issuance_limit(1000);
// 第一次发行应该成功
assert!(acc1594
.issue("issuer1", "investor1", 500, vec![], &partition_id, [0u8; 32])
.is_ok());
// 第二次发行超过限额应该失败
let result = acc1594.issue("issuer1", "investor2", 600, vec![], &partition_id, [0u8; 32]);
assert!(result.is_err());
}
}