668 lines
19 KiB
Rust
668 lines
19 KiB
Rust
//! NAC ACC-1400 Protocol Implementation
|
||
//! NAC ACC-1400协议实现 - 证券型资产协议
|
||
//!
|
||
//! ACC-1400继承ACC-1410,专门用于证券型资产(Security Token),
|
||
//! 增加了证券特有的功能,如股息分配、投票权管理、转让限制等。
|
||
|
||
pub use nac_acc_1410::*;
|
||
|
||
// 导出子模块
|
||
pub mod dividend;
|
||
pub mod voting;
|
||
pub mod transfer_restrictions;
|
||
pub mod compliance;
|
||
|
||
use dividend::DividendEngine;
|
||
use voting::VotingSystem;
|
||
use transfer_restrictions::TransferRestrictionSystem;
|
||
use compliance::ComplianceSystem;
|
||
|
||
/// ACC-1400证券型资产协议
|
||
#[derive(Debug)]
|
||
pub struct Acc1400 {
|
||
/// 基础ACC-1410协议
|
||
base: Acc1410,
|
||
/// 股息分配引擎
|
||
dividend_engine: DividendEngine,
|
||
/// 投票系统
|
||
voting_system: VotingSystem,
|
||
/// 转让限制系统
|
||
transfer_restrictions: TransferRestrictionSystem,
|
||
/// 合规验证系统
|
||
compliance_system: ComplianceSystem,
|
||
}
|
||
|
||
impl Acc1400 {
|
||
/// 创建新的ACC-1400实例
|
||
pub fn new() -> Self {
|
||
Self {
|
||
base: Acc1410::new(),
|
||
dividend_engine: DividendEngine::new(),
|
||
voting_system: VotingSystem::new(),
|
||
transfer_restrictions: TransferRestrictionSystem::new(),
|
||
compliance_system: ComplianceSystem::new(),
|
||
}
|
||
}
|
||
|
||
// ==================== 基础证券操作 ====================
|
||
|
||
/// 创建证券型资产分区
|
||
pub fn create_security_partition(
|
||
&mut self,
|
||
name: String,
|
||
extended_gnacs: ExtendedGNACS,
|
||
partition_type: PartitionType,
|
||
) -> Result<[u8; 32]> {
|
||
self.base
|
||
.create_partition(name, extended_gnacs, partition_type)
|
||
}
|
||
|
||
/// 发行证券代币
|
||
pub fn issue_security(
|
||
&mut self,
|
||
partition_id: &[u8; 32],
|
||
to: &str,
|
||
amount: u64,
|
||
) -> Result<()> {
|
||
// 记录持有开始时间
|
||
self.transfer_restrictions.record_holding_start(to.to_string(), *partition_id);
|
||
|
||
self.base.issue_to_partition(partition_id, to, amount)
|
||
}
|
||
|
||
/// 转让证券(带合规检查)
|
||
pub fn transfer_security(
|
||
&mut self,
|
||
from: &str,
|
||
to: &str,
|
||
amount: u64,
|
||
partition_id: &[u8; 32],
|
||
) -> Result<nac_acc_1410::TransferResult> {
|
||
// 获取余额
|
||
let balance = self.base.balance_of_by_partition(partition_id, from)?;
|
||
|
||
// 执行转让限制检查
|
||
let restriction_result = self.transfer_restrictions.check_transfer(
|
||
from,
|
||
to,
|
||
amount,
|
||
partition_id,
|
||
balance,
|
||
);
|
||
|
||
if !restriction_result.allowed {
|
||
return Err(format!(
|
||
"Transfer restricted: {}",
|
||
restriction_result.reasons.join(", ")
|
||
).into());
|
||
}
|
||
|
||
// 执行转账
|
||
let result = self.base.transfer_by_partition(from, to, amount, partition_id)?;
|
||
|
||
// 记录转让
|
||
self.transfer_restrictions.record_transfer(
|
||
from.to_string(),
|
||
to.to_string(),
|
||
amount,
|
||
*partition_id,
|
||
);
|
||
|
||
Ok(result)
|
||
}
|
||
|
||
/// 获取证券余额
|
||
pub fn balance_of_security(
|
||
&self,
|
||
partition_id: &[u8; 32],
|
||
account: &str,
|
||
) -> Result<u64> {
|
||
self.base.balance_of_by_partition(partition_id, account)
|
||
}
|
||
|
||
/// 获取账户持有的所有证券分区
|
||
pub fn securities_of(&self, account: &str) -> Vec<[u8; 32]> {
|
||
self.base.partitions_of(account)
|
||
}
|
||
|
||
// ==================== 股息分配功能 ====================
|
||
|
||
/// 声明股息分配
|
||
pub fn declare_dividend(
|
||
&mut self,
|
||
security_id: [u8; 32],
|
||
amount_per_share: u64,
|
||
tax_rate: u8,
|
||
) -> Result<String> {
|
||
// 获取所有持有人
|
||
let holders = self.get_all_holders(&security_id)?;
|
||
|
||
self.dividend_engine
|
||
.declare_dividend(security_id, amount_per_share, tax_rate, &holders)
|
||
.map_err(|e| e.into())
|
||
}
|
||
|
||
/// 执行股息分配
|
||
pub fn distribute_dividend(&mut self, dividend_id: &str) -> Result<()> {
|
||
self.dividend_engine
|
||
.distribute_dividend(dividend_id)
|
||
.map_err(|e| e.into())
|
||
}
|
||
|
||
/// 领取股息
|
||
pub fn claim_dividend(&mut self, account: &str, dividend_id: &str) -> Result<u64> {
|
||
self.dividend_engine
|
||
.claim_dividend(account, dividend_id)
|
||
.map_err(|e| e.into())
|
||
}
|
||
|
||
/// 获取账户的未领取股息
|
||
pub fn get_unclaimed_dividends(&self, account: &str) -> Vec<dividend::PersonalDividend> {
|
||
self.dividend_engine.get_unclaimed_dividends(account)
|
||
}
|
||
|
||
/// 获取账户的总未领取股息金额
|
||
pub fn get_total_unclaimed_amount(&self, account: &str) -> u64 {
|
||
self.dividend_engine.get_total_unclaimed_amount(account)
|
||
}
|
||
|
||
// ==================== 投票功能 ====================
|
||
|
||
/// 创建投票提案
|
||
pub fn create_proposal(
|
||
&mut self,
|
||
title: String,
|
||
description: String,
|
||
proposal_type: voting::ProposalType,
|
||
creator: String,
|
||
security_id: [u8; 32],
|
||
voting_start: u64,
|
||
voting_end: u64,
|
||
quorum_percentage: u8,
|
||
approval_percentage: u8,
|
||
) -> Result<String> {
|
||
self.voting_system
|
||
.create_proposal(
|
||
title,
|
||
description,
|
||
proposal_type,
|
||
creator,
|
||
security_id,
|
||
voting_start,
|
||
voting_end,
|
||
quorum_percentage,
|
||
approval_percentage,
|
||
)
|
||
.map_err(|e| e.into())
|
||
}
|
||
|
||
/// 激活提案
|
||
pub fn activate_proposal(&mut self, proposal_id: &str) -> Result<()> {
|
||
self.voting_system
|
||
.activate_proposal(proposal_id)
|
||
.map_err(|e| e.into())
|
||
}
|
||
|
||
/// 设置投票权
|
||
pub fn set_voting_rights(
|
||
&mut self,
|
||
account: String,
|
||
shares: u64,
|
||
voting_multiplier: u32,
|
||
) {
|
||
self.voting_system.set_voting_rights(account, shares, voting_multiplier);
|
||
}
|
||
|
||
/// 投票
|
||
pub fn cast_vote(
|
||
&mut self,
|
||
proposal_id: &str,
|
||
voter: &str,
|
||
option: voting::VoteOption,
|
||
) -> Result<()> {
|
||
self.voting_system
|
||
.cast_vote(proposal_id, voter, option, None)
|
||
.map_err(|e| e.into())
|
||
}
|
||
|
||
/// 代理投票
|
||
pub fn cast_proxy_vote(
|
||
&mut self,
|
||
proposal_id: &str,
|
||
proxy: &str,
|
||
principal: &str,
|
||
option: voting::VoteOption,
|
||
) -> Result<()> {
|
||
self.voting_system
|
||
.cast_vote(proposal_id, proxy, option, Some(principal))
|
||
.map_err(|e| e.into())
|
||
}
|
||
|
||
/// 授权代理投票
|
||
pub fn authorize_proxy(
|
||
&mut self,
|
||
principal: String,
|
||
proxy: String,
|
||
proposal_id: Option<String>,
|
||
valid_from: u64,
|
||
valid_until: u64,
|
||
) -> Result<()> {
|
||
self.voting_system
|
||
.authorize_proxy(principal, proxy, proposal_id, valid_from, valid_until)
|
||
.map_err(|e| e.into())
|
||
}
|
||
|
||
/// 计算投票结果
|
||
pub fn calculate_voting_result(&self, proposal_id: &str) -> Result<voting::VotingResult> {
|
||
self.voting_system
|
||
.calculate_result(proposal_id)
|
||
.map_err(|e| e.into())
|
||
}
|
||
|
||
/// 结束投票
|
||
pub fn finalize_proposal(&mut self, proposal_id: &str) -> Result<voting::VotingResult> {
|
||
self.voting_system
|
||
.finalize_proposal(proposal_id)
|
||
.map_err(|e| e.into())
|
||
}
|
||
|
||
// ==================== 转让限制功能 ====================
|
||
|
||
/// 设置KYC信息
|
||
pub fn set_kyc_info(
|
||
&mut self,
|
||
account: String,
|
||
status: transfer_restrictions::KycStatus,
|
||
level: transfer_restrictions::KycLevel,
|
||
verifier: Option<String>,
|
||
expires_at: Option<u64>,
|
||
) {
|
||
self.transfer_restrictions.set_kyc_info(account, status, level, verifier, expires_at);
|
||
}
|
||
|
||
/// 添加到白名单
|
||
pub fn add_to_whitelist(
|
||
&mut self,
|
||
account: String,
|
||
added_by: String,
|
||
expires_at: Option<u64>,
|
||
notes: Option<String>,
|
||
) -> Result<()> {
|
||
self.transfer_restrictions
|
||
.add_to_whitelist(account, added_by, expires_at, notes)
|
||
.map_err(|e| e.into())
|
||
}
|
||
|
||
/// 从白名单移除
|
||
pub fn remove_from_whitelist(&mut self, account: &str) -> Result<()> {
|
||
self.transfer_restrictions
|
||
.remove_from_whitelist(account)
|
||
.map_err(|e| e.into())
|
||
}
|
||
|
||
/// 添加锁定期
|
||
pub fn add_lockup_period(
|
||
&mut self,
|
||
account: String,
|
||
security_id: [u8; 32],
|
||
locked_amount: u64,
|
||
unlock_time: u64,
|
||
reason: String,
|
||
early_unlock_allowed: bool,
|
||
) -> Result<()> {
|
||
self.transfer_restrictions
|
||
.add_lockup_period(
|
||
account,
|
||
security_id,
|
||
locked_amount,
|
||
unlock_time,
|
||
reason,
|
||
early_unlock_allowed,
|
||
)
|
||
.map_err(|e| e.into())
|
||
}
|
||
|
||
/// 获取锁定数量
|
||
pub fn get_locked_amount(&self, account: &str, security_id: &[u8; 32]) -> u64 {
|
||
self.transfer_restrictions.get_locked_amount(account, security_id)
|
||
}
|
||
|
||
/// 添加转让限制规则
|
||
pub fn add_transfer_restriction(
|
||
&mut self,
|
||
name: String,
|
||
restriction_type: transfer_restrictions::RestrictionType,
|
||
) -> String {
|
||
self.transfer_restrictions.add_restriction(name, restriction_type)
|
||
}
|
||
|
||
// ==================== 合规验证功能 ====================
|
||
|
||
/// 设置投资者资格
|
||
pub fn set_investor_qualification(
|
||
&mut self,
|
||
account: String,
|
||
investor_type: compliance::InvestorType,
|
||
annual_income: Option<u64>,
|
||
net_worth: Option<u64>,
|
||
is_professional: bool,
|
||
certifier: String,
|
||
expires_at: Option<u64>,
|
||
) -> Result<()> {
|
||
self.compliance_system
|
||
.set_investor_qualification(
|
||
account,
|
||
investor_type,
|
||
annual_income,
|
||
net_worth,
|
||
is_professional,
|
||
certifier,
|
||
expires_at,
|
||
)
|
||
.map_err(|e| e.into())
|
||
}
|
||
|
||
/// 添加持有限额
|
||
pub fn add_holding_limit(
|
||
&mut self,
|
||
name: String,
|
||
limit_type: compliance::LimitType,
|
||
limit_value: u64,
|
||
applies_to: Vec<compliance::InvestorType>,
|
||
) -> String {
|
||
self.compliance_system.add_holding_limit(name, limit_type, limit_value, applies_to)
|
||
}
|
||
|
||
/// 添加地域限制
|
||
pub fn add_geographic_restriction(
|
||
&mut self,
|
||
restriction_type: compliance::GeoRestrictionType,
|
||
regions: Vec<String>,
|
||
) -> String {
|
||
self.compliance_system.add_geographic_restriction(restriction_type, regions)
|
||
}
|
||
|
||
/// 设置投资者地域信息
|
||
pub fn set_investor_location(
|
||
&mut self,
|
||
account: String,
|
||
country_code: String,
|
||
state_code: Option<String>,
|
||
) {
|
||
self.compliance_system.set_investor_location(account, country_code, state_code);
|
||
}
|
||
|
||
/// 执行完整的合规检查
|
||
pub fn perform_compliance_check(
|
||
&self,
|
||
account: &str,
|
||
security_id: &[u8; 32],
|
||
amount: u64,
|
||
total_supply: u64,
|
||
required_investor_type: Option<compliance::InvestorType>,
|
||
) -> compliance::ComplianceCheckResult {
|
||
self.compliance_system.perform_compliance_check(
|
||
account,
|
||
security_id,
|
||
amount,
|
||
total_supply,
|
||
required_investor_type,
|
||
)
|
||
}
|
||
|
||
/// 生成持有人报告
|
||
pub fn generate_holder_report(
|
||
&mut self,
|
||
security_id: &[u8; 32],
|
||
generated_by: String,
|
||
) -> Result<String> {
|
||
self.compliance_system
|
||
.generate_holder_report(security_id, generated_by)
|
||
.map_err(|e| e.into())
|
||
}
|
||
|
||
/// 生成投资者分类报告
|
||
pub fn generate_investor_classification_report(
|
||
&mut self,
|
||
generated_by: String,
|
||
) -> String {
|
||
self.compliance_system.generate_investor_classification_report(generated_by)
|
||
}
|
||
|
||
/// 生成地域分布报告
|
||
pub fn generate_geographic_distribution_report(
|
||
&mut self,
|
||
generated_by: String,
|
||
) -> String {
|
||
self.compliance_system.generate_geographic_distribution_report(generated_by)
|
||
}
|
||
|
||
// ==================== 辅助功能 ====================
|
||
|
||
/// 获取所有持有人(用于股息分配)
|
||
fn get_all_holders(&self, _security_id: &[u8; 32]) -> Result<std::collections::HashMap<String, u64>> {
|
||
// 简化实现:从base获取所有账户余额
|
||
// 实际实现需要遍历所有账户
|
||
let holders = std::collections::HashMap::new();
|
||
|
||
// 这里应该从base中获取所有持有该证券的账户
|
||
// 由于ACC-1410没有提供这个接口,这里返回空map
|
||
// 实际使用时需要在外部维护持有人列表
|
||
|
||
Ok(holders)
|
||
}
|
||
|
||
/// 授权证券操作员
|
||
pub fn authorize_security_operator(&mut self, account: &str, operator: &str) {
|
||
self.base.authorize_operator(account, operator);
|
||
}
|
||
|
||
/// 撤销证券操作员
|
||
pub fn revoke_security_operator(&mut self, account: &str, operator: &str) {
|
||
self.base.revoke_operator(account, operator);
|
||
}
|
||
|
||
/// 锁定证券账户
|
||
pub fn lock_security_account(&mut self, account: &str, unlock_time: u64) {
|
||
self.base.lock_account(account, unlock_time);
|
||
}
|
||
|
||
/// 解锁证券账户
|
||
pub fn unlock_security_account(&mut self, account: &str) {
|
||
self.base.unlock_account(account);
|
||
}
|
||
|
||
/// 暂停证券转账
|
||
pub fn halt_security_transfers(&mut self) {
|
||
self.base.halt_transfers();
|
||
}
|
||
|
||
/// 恢复证券转账
|
||
pub fn resume_security_transfers(&mut self) {
|
||
self.base.resume_transfers();
|
||
}
|
||
|
||
/// 获取股息引擎引用
|
||
pub fn dividend_engine(&self) -> &DividendEngine {
|
||
&self.dividend_engine
|
||
}
|
||
|
||
/// 获取投票系统引用
|
||
pub fn voting_system(&self) -> &VotingSystem {
|
||
&self.voting_system
|
||
}
|
||
|
||
/// 获取转让限制系统引用
|
||
pub fn transfer_restrictions(&self) -> &TransferRestrictionSystem {
|
||
&self.transfer_restrictions
|
||
}
|
||
|
||
/// 获取合规验证系统引用
|
||
pub fn compliance_system(&self) -> &ComplianceSystem {
|
||
&self.compliance_system
|
||
}
|
||
}
|
||
|
||
impl Default for Acc1400 {
|
||
fn default() -> Self {
|
||
Self::new()
|
||
}
|
||
}
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
use nac_acc_1410::GNACSExtension;
|
||
|
||
#[test]
|
||
fn test_acc1400_security_issuance() {
|
||
let mut acc1400 = Acc1400::new();
|
||
|
||
// 创建普通股证券
|
||
let common_stock_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 security_id = acc1400
|
||
.create_security_partition(
|
||
"ACME Corp Common Stock".to_string(),
|
||
common_stock_gnacs,
|
||
PartitionType::CommonStock,
|
||
)
|
||
.unwrap();
|
||
|
||
// 发行证券
|
||
acc1400
|
||
.issue_security(&security_id, "investor1", 10000)
|
||
.unwrap();
|
||
|
||
// 检查余额
|
||
assert_eq!(
|
||
acc1400
|
||
.balance_of_security(&security_id, "investor1")
|
||
.unwrap(),
|
||
10000
|
||
);
|
||
}
|
||
|
||
#[test]
|
||
fn test_acc1400_with_compliance() {
|
||
let mut acc1400 = Acc1400::new();
|
||
|
||
let 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 security_id = acc1400
|
||
.create_security_partition(
|
||
"Test Security".to_string(),
|
||
gnacs,
|
||
PartitionType::CommonStock,
|
||
)
|
||
.unwrap();
|
||
|
||
// 设置白名单限制
|
||
acc1400.add_transfer_restriction(
|
||
"Whitelist Required".to_string(),
|
||
transfer_restrictions::RestrictionType::RequireWhitelist,
|
||
);
|
||
|
||
// 发行证券
|
||
acc1400
|
||
.issue_security(&security_id, "investor1", 5000)
|
||
.unwrap();
|
||
|
||
// 添加到白名单
|
||
acc1400
|
||
.add_to_whitelist(
|
||
"investor1".to_string(),
|
||
"admin".to_string(),
|
||
None,
|
||
None,
|
||
)
|
||
.unwrap();
|
||
|
||
acc1400
|
||
.add_to_whitelist(
|
||
"investor2".to_string(),
|
||
"admin".to_string(),
|
||
None,
|
||
None,
|
||
)
|
||
.unwrap();
|
||
|
||
// 现在转让应该成功
|
||
let result = acc1400.transfer_security("investor1", "investor2", 2000, &security_id);
|
||
assert!(result.is_ok());
|
||
}
|
||
|
||
#[test]
|
||
fn test_acc1400_voting() {
|
||
let mut acc1400 = Acc1400::new();
|
||
|
||
let 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 security_id = acc1400
|
||
.create_security_partition(
|
||
"Test Security".to_string(),
|
||
gnacs,
|
||
PartitionType::CommonStock,
|
||
)
|
||
.unwrap();
|
||
|
||
// 设置投票权
|
||
acc1400.set_voting_rights("investor1".to_string(), 1000, 1);
|
||
acc1400.set_voting_rights("investor2".to_string(), 500, 1);
|
||
|
||
// 创建提案
|
||
let current_time = std::time::SystemTime::now()
|
||
.duration_since(std::time::UNIX_EPOCH)
|
||
.unwrap()
|
||
.as_secs();
|
||
|
||
let proposal_id = acc1400
|
||
.create_proposal(
|
||
"Test Proposal".to_string(),
|
||
"Test".to_string(),
|
||
voting::ProposalType::Other,
|
||
"creator1".to_string(),
|
||
security_id,
|
||
current_time,
|
||
current_time + 1000,
|
||
50,
|
||
66,
|
||
)
|
||
.unwrap();
|
||
|
||
// 激活并投票
|
||
acc1400.activate_proposal(&proposal_id).unwrap();
|
||
acc1400
|
||
.cast_vote(&proposal_id, "investor1", voting::VoteOption::For)
|
||
.unwrap();
|
||
|
||
// 检查结果
|
||
let result = acc1400.calculate_voting_result(&proposal_id).unwrap();
|
||
assert_eq!(result.votes_for, 1000);
|
||
}
|
||
}
|