657 lines
20 KiB
Rust
657 lines
20 KiB
Rust
/// NAC ACC-1644 协议实现
|
||
/// 宪法授权控制器操作协议
|
||
|
||
mod error;
|
||
mod types;
|
||
|
||
pub use error::{Acc1644Error, Result};
|
||
pub use types::*;
|
||
|
||
use std::collections::HashMap;
|
||
|
||
/// ACC-1644 宪法授权控制器操作协议
|
||
#[derive(Debug)]
|
||
pub struct Acc1644 {
|
||
/// 当前控制器地址
|
||
controller: Option<String>,
|
||
|
||
/// 控制器角色
|
||
controller_role: Option<ControllerRole>,
|
||
|
||
/// 接管到期时间(Unix时间戳)
|
||
takeover_expiry: Option<u64>,
|
||
|
||
/// 冻结状态(partition_id_hex -> 冻结原因)
|
||
frozen_partitions: HashMap<String, String>,
|
||
|
||
/// 全局冻结状态
|
||
globally_frozen: bool,
|
||
|
||
/// 控制操作历史
|
||
control_actions: Vec<ControlAction>,
|
||
|
||
/// GNACS控制状态
|
||
gnacs_control: GnacsControlExtension,
|
||
|
||
/// 角色权限(简化实现)
|
||
roles: HashMap<String, Vec<String>>,
|
||
|
||
/// 账户余额(简化实现,用于测试)
|
||
balances: HashMap<String, HashMap<String, u128>>, // partition_id -> (account -> balance)
|
||
}
|
||
|
||
impl Acc1644 {
|
||
/// 创建新的ACC-1644实例
|
||
pub fn new() -> Self {
|
||
Self {
|
||
controller: None,
|
||
controller_role: None,
|
||
takeover_expiry: None,
|
||
frozen_partitions: HashMap::new(),
|
||
globally_frozen: false,
|
||
control_actions: Vec::new(),
|
||
gnacs_control: GnacsControlExtension::new(ControlLevel::Normal, 0),
|
||
roles: HashMap::new(),
|
||
balances: HashMap::new(),
|
||
}
|
||
}
|
||
|
||
/// 查询当前控制器
|
||
pub fn controller(&self) -> Option<String> {
|
||
self.controller.clone()
|
||
}
|
||
|
||
/// 查询控制器层级
|
||
pub fn controller_level(&self) -> Option<u8> {
|
||
self.controller_role.as_ref().map(|r| r.to_u8())
|
||
}
|
||
|
||
/// 冻结资产(分区级或全局)
|
||
pub fn freeze(
|
||
&mut self,
|
||
operator: &str,
|
||
partition_id: &[u8; 32],
|
||
reason: &[u8],
|
||
_evidence: &[u8],
|
||
receipt_hash: [u8; 32],
|
||
) -> Result<()> {
|
||
// 检查权限
|
||
if !self.has_role("REGULATOR", operator) {
|
||
return Err(Acc1644Error::Unauthorized {
|
||
operator: operator.to_string(),
|
||
required_role: "REGULATOR".to_string(),
|
||
});
|
||
}
|
||
|
||
// 验证宪法收据
|
||
if receipt_hash == [0u8; 32] {
|
||
return Err(Acc1644Error::InvalidConstitutionalReceipt {
|
||
receipt_hash: hex::encode(receipt_hash),
|
||
});
|
||
}
|
||
|
||
let partition_id_hex = hex::encode(partition_id);
|
||
let is_global = *partition_id == [0u8; 32];
|
||
|
||
if is_global {
|
||
self.globally_frozen = true;
|
||
self.gnacs_control.control_level = ControlLevel::FullyFrozen;
|
||
} else {
|
||
self.frozen_partitions.insert(
|
||
partition_id_hex.clone(),
|
||
String::from_utf8_lossy(reason).to_string(),
|
||
);
|
||
|
||
// 如果有分区冻结,更新为部分冻结
|
||
if self.gnacs_control.control_level == ControlLevel::Normal {
|
||
self.gnacs_control.control_level = ControlLevel::PartiallyFrozen;
|
||
}
|
||
}
|
||
|
||
// 记录操作
|
||
self.control_actions.push(ControlAction {
|
||
action_type: ControlActionType::Freeze,
|
||
partition_id: *partition_id,
|
||
from: String::new(),
|
||
to: String::new(),
|
||
amount: 0,
|
||
legal_basis: [0u8; 32], // 简化实现
|
||
timestamp: Self::current_timestamp(),
|
||
receipt_hash,
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// 解冻资产
|
||
pub fn unfreeze(
|
||
&mut self,
|
||
operator: &str,
|
||
partition_id: &[u8; 32],
|
||
_reason: &[u8],
|
||
_evidence: &[u8],
|
||
receipt_hash: [u8; 32],
|
||
) -> Result<()> {
|
||
// 检查权限
|
||
if !self.has_role("REGULATOR", operator) {
|
||
return Err(Acc1644Error::Unauthorized {
|
||
operator: operator.to_string(),
|
||
required_role: "REGULATOR".to_string(),
|
||
});
|
||
}
|
||
|
||
// 验证宪法收据
|
||
if receipt_hash == [0u8; 32] {
|
||
return Err(Acc1644Error::InvalidConstitutionalReceipt {
|
||
receipt_hash: hex::encode(receipt_hash),
|
||
});
|
||
}
|
||
|
||
let partition_id_hex = hex::encode(partition_id);
|
||
let is_global = *partition_id == [0u8; 32];
|
||
|
||
if is_global {
|
||
if !self.globally_frozen {
|
||
return Err(Acc1644Error::AssetNotFrozen {
|
||
partition_id: "global".to_string(),
|
||
});
|
||
}
|
||
self.globally_frozen = false;
|
||
|
||
// 如果没有分区冻结,恢复正常
|
||
if self.frozen_partitions.is_empty() {
|
||
self.gnacs_control.control_level = ControlLevel::Normal;
|
||
} else {
|
||
self.gnacs_control.control_level = ControlLevel::PartiallyFrozen;
|
||
}
|
||
} else {
|
||
if !self.frozen_partitions.contains_key(&partition_id_hex) {
|
||
return Err(Acc1644Error::AssetNotFrozen {
|
||
partition_id: partition_id_hex,
|
||
});
|
||
}
|
||
self.frozen_partitions.remove(&partition_id_hex);
|
||
|
||
// 如果没有冻结且全局未冻结,恢复正常
|
||
if self.frozen_partitions.is_empty() && !self.globally_frozen {
|
||
self.gnacs_control.control_level = ControlLevel::Normal;
|
||
}
|
||
}
|
||
|
||
// 记录操作
|
||
self.control_actions.push(ControlAction {
|
||
action_type: ControlActionType::Unfreeze,
|
||
partition_id: *partition_id,
|
||
from: String::new(),
|
||
to: String::new(),
|
||
amount: 0,
|
||
legal_basis: [0u8; 32],
|
||
timestamp: Self::current_timestamp(),
|
||
receipt_hash,
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// 强制转账(需超级监管权限)
|
||
pub fn force_transfer(
|
||
&mut self,
|
||
operator: &str,
|
||
partition_id: &[u8; 32],
|
||
from: &str,
|
||
to: &str,
|
||
amount: u128,
|
||
legal_basis: [u8; 32],
|
||
_evidence: &[u8],
|
||
receipt_hash: [u8; 32],
|
||
) -> Result<()> {
|
||
// 检查权限
|
||
if !self.has_role("SUPER_REGULATOR", operator) {
|
||
return Err(Acc1644Error::Unauthorized {
|
||
operator: operator.to_string(),
|
||
required_role: "SUPER_REGULATOR".to_string(),
|
||
});
|
||
}
|
||
|
||
// 验证法律依据
|
||
if legal_basis == [0u8; 32] {
|
||
return Err(Acc1644Error::InvalidLegalBasis {
|
||
legal_basis: hex::encode(legal_basis),
|
||
});
|
||
}
|
||
|
||
// 验证宪法收据
|
||
if receipt_hash == [0u8; 32] {
|
||
return Err(Acc1644Error::InvalidConstitutionalReceipt {
|
||
receipt_hash: hex::encode(receipt_hash),
|
||
});
|
||
}
|
||
|
||
let partition_id_hex = hex::encode(partition_id);
|
||
|
||
// 检查余额(简化实现)
|
||
let from_balance = self.get_balance(&partition_id_hex, from);
|
||
if from_balance < amount {
|
||
return Err(Acc1644Error::InsufficientBalance {
|
||
account: from.to_string(),
|
||
available: from_balance,
|
||
required: amount,
|
||
});
|
||
}
|
||
|
||
// 执行转账
|
||
self.set_balance(&partition_id_hex, from, from_balance - amount);
|
||
let to_balance = self.get_balance(&partition_id_hex, to);
|
||
self.set_balance(&partition_id_hex, to, to_balance + amount);
|
||
|
||
// 记录操作
|
||
self.control_actions.push(ControlAction {
|
||
action_type: ControlActionType::ForceTransfer,
|
||
partition_id: *partition_id,
|
||
from: from.to_string(),
|
||
to: to.to_string(),
|
||
amount,
|
||
legal_basis,
|
||
timestamp: Self::current_timestamp(),
|
||
receipt_hash,
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// 强制赎回(需超级监管权限)
|
||
pub fn force_redeem(
|
||
&mut self,
|
||
operator: &str,
|
||
partition_id: &[u8; 32],
|
||
from: &str,
|
||
amount: u128,
|
||
legal_basis: [u8; 32],
|
||
_evidence: &[u8],
|
||
receipt_hash: [u8; 32],
|
||
) -> Result<()> {
|
||
// 检查权限
|
||
if !self.has_role("SUPER_REGULATOR", operator) {
|
||
return Err(Acc1644Error::Unauthorized {
|
||
operator: operator.to_string(),
|
||
required_role: "SUPER_REGULATOR".to_string(),
|
||
});
|
||
}
|
||
|
||
// 验证法律依据
|
||
if legal_basis == [0u8; 32] {
|
||
return Err(Acc1644Error::InvalidLegalBasis {
|
||
legal_basis: hex::encode(legal_basis),
|
||
});
|
||
}
|
||
|
||
// 验证宪法收据
|
||
if receipt_hash == [0u8; 32] {
|
||
return Err(Acc1644Error::InvalidConstitutionalReceipt {
|
||
receipt_hash: hex::encode(receipt_hash),
|
||
});
|
||
}
|
||
|
||
let partition_id_hex = hex::encode(partition_id);
|
||
|
||
// 检查余额
|
||
let from_balance = self.get_balance(&partition_id_hex, from);
|
||
if from_balance < amount {
|
||
return Err(Acc1644Error::InsufficientBalance {
|
||
account: from.to_string(),
|
||
available: from_balance,
|
||
required: amount,
|
||
});
|
||
}
|
||
|
||
// 执行赎回(销毁代币)
|
||
self.set_balance(&partition_id_hex, from, from_balance - amount);
|
||
|
||
// 记录操作
|
||
self.control_actions.push(ControlAction {
|
||
action_type: ControlActionType::ForceRedeem,
|
||
partition_id: *partition_id,
|
||
from: from.to_string(),
|
||
to: String::new(),
|
||
amount,
|
||
legal_basis,
|
||
timestamp: Self::current_timestamp(),
|
||
receipt_hash,
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// 接管资产(紧急控制器权限)
|
||
pub fn take_control(
|
||
&mut self,
|
||
operator: &str,
|
||
new_controller: &str,
|
||
duration: u64,
|
||
_reason: &[u8],
|
||
receipt_hash: [u8; 32],
|
||
) -> Result<()> {
|
||
// 检查权限
|
||
if !self.has_role("EMERGENCY_CONTROLLER", operator) {
|
||
return Err(Acc1644Error::Unauthorized {
|
||
operator: operator.to_string(),
|
||
required_role: "EMERGENCY_CONTROLLER".to_string(),
|
||
});
|
||
}
|
||
|
||
// 验证宪法收据
|
||
if receipt_hash == [0u8; 32] {
|
||
return Err(Acc1644Error::InvalidConstitutionalReceipt {
|
||
receipt_hash: hex::encode(receipt_hash),
|
||
});
|
||
}
|
||
|
||
// 设置新控制器
|
||
self.controller = Some(new_controller.to_string());
|
||
self.controller_role = Some(ControllerRole::EmergencyController);
|
||
self.takeover_expiry = Some(Self::current_timestamp() + duration);
|
||
|
||
// 更新GNACS状态
|
||
self.gnacs_control.control_level = ControlLevel::Takeover;
|
||
self.gnacs_control.controller_id = 3; // EmergencyController
|
||
|
||
// 记录操作
|
||
self.control_actions.push(ControlAction {
|
||
action_type: ControlActionType::TakeControl,
|
||
partition_id: [0u8; 32],
|
||
from: String::new(),
|
||
to: new_controller.to_string(),
|
||
amount: 0,
|
||
legal_basis: [0u8; 32],
|
||
timestamp: Self::current_timestamp(),
|
||
receipt_hash,
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// 放弃控制权(主动或到期)
|
||
pub fn relinquish_control(&mut self) -> Result<()> {
|
||
if self.controller.is_none() {
|
||
return Err(Acc1644Error::NoController);
|
||
}
|
||
|
||
// 检查是否到期
|
||
if let Some(expiry) = self.takeover_expiry {
|
||
let now = Self::current_timestamp();
|
||
if now < expiry {
|
||
return Err(Acc1644Error::TakeoverNotExpired {
|
||
remaining_seconds: expiry - now,
|
||
});
|
||
}
|
||
}
|
||
|
||
let old_controller = self.controller.take().unwrap();
|
||
self.controller_role = None;
|
||
self.takeover_expiry = None;
|
||
|
||
// 恢复GNACS状态
|
||
if self.globally_frozen {
|
||
self.gnacs_control.control_level = ControlLevel::FullyFrozen;
|
||
} else if !self.frozen_partitions.is_empty() {
|
||
self.gnacs_control.control_level = ControlLevel::PartiallyFrozen;
|
||
} else {
|
||
self.gnacs_control.control_level = ControlLevel::Normal;
|
||
}
|
||
self.gnacs_control.controller_id = 0;
|
||
|
||
// 记录操作
|
||
self.control_actions.push(ControlAction {
|
||
action_type: ControlActionType::RelinquishControl,
|
||
partition_id: [0u8; 32],
|
||
from: old_controller,
|
||
to: String::new(),
|
||
amount: 0,
|
||
legal_basis: [0u8; 32],
|
||
timestamp: Self::current_timestamp(),
|
||
receipt_hash: [0u8; 32],
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// 获取操作历史
|
||
pub fn get_control_actions(&self, from: usize, to: usize) -> Vec<ControlAction> {
|
||
self.control_actions
|
||
.iter()
|
||
.skip(from)
|
||
.take(to - from)
|
||
.cloned()
|
||
.collect()
|
||
}
|
||
|
||
/// 检查分区是否冻结
|
||
pub fn is_partition_frozen(&self, partition_id: &[u8; 32]) -> bool {
|
||
if self.globally_frozen {
|
||
return true;
|
||
}
|
||
|
||
let partition_id_hex = hex::encode(partition_id);
|
||
self.frozen_partitions.contains_key(&partition_id_hex)
|
||
}
|
||
|
||
/// 获取GNACS控制状态
|
||
pub fn gnacs_control(&self) -> GnacsControlExtension {
|
||
self.gnacs_control
|
||
}
|
||
|
||
// 辅助方法
|
||
|
||
fn has_role(&self, role: &str, account: &str) -> bool {
|
||
if let Some(accounts) = self.roles.get(role) {
|
||
accounts.contains(&account.to_string())
|
||
} else {
|
||
false
|
||
}
|
||
}
|
||
|
||
pub fn grant_role(&mut self, role: &str, account: &str) {
|
||
self.roles
|
||
.entry(role.to_string())
|
||
.or_insert_with(Vec::new)
|
||
.push(account.to_string());
|
||
}
|
||
|
||
fn get_balance(&self, partition_id: &str, account: &str) -> u128 {
|
||
self.balances
|
||
.get(partition_id)
|
||
.and_then(|accounts| accounts.get(account))
|
||
.copied()
|
||
.unwrap_or(0)
|
||
}
|
||
|
||
fn set_balance(&mut self, partition_id: &str, account: &str, balance: u128) {
|
||
self.balances
|
||
.entry(partition_id.to_string())
|
||
.or_insert_with(HashMap::new)
|
||
.insert(account.to_string(), balance);
|
||
}
|
||
|
||
pub fn mint(&mut self, partition_id: &[u8; 32], account: &str, amount: u128) {
|
||
let partition_id_hex = hex::encode(partition_id);
|
||
let current = self.get_balance(&partition_id_hex, account);
|
||
self.set_balance(&partition_id_hex, account, current + amount);
|
||
}
|
||
|
||
fn current_timestamp() -> u64 {
|
||
std::time::SystemTime::now()
|
||
.duration_since(std::time::UNIX_EPOCH)
|
||
.unwrap()
|
||
.as_secs()
|
||
}
|
||
}
|
||
|
||
impl Default for Acc1644 {
|
||
fn default() -> Self {
|
||
Self::new()
|
||
}
|
||
}
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
fn create_test_acc1644() -> Acc1644 {
|
||
let mut acc1644 = Acc1644::new();
|
||
acc1644.grant_role("REGULATOR", "regulator1");
|
||
acc1644.grant_role("SUPER_REGULATOR", "super_reg1");
|
||
acc1644.grant_role("EMERGENCY_CONTROLLER", "emergency1");
|
||
acc1644
|
||
}
|
||
|
||
#[test]
|
||
fn test_freeze_and_unfreeze() {
|
||
let mut acc1644 = create_test_acc1644();
|
||
|
||
let partition_id = [1u8; 32];
|
||
let reason = b"Court order";
|
||
let evidence = b"Evidence hash";
|
||
let receipt = [1u8; 32];
|
||
|
||
// 冻结分区
|
||
acc1644
|
||
.freeze("regulator1", &partition_id, reason, evidence, receipt)
|
||
.unwrap();
|
||
|
||
assert!(acc1644.is_partition_frozen(&partition_id));
|
||
assert_eq!(
|
||
acc1644.gnacs_control().control_level,
|
||
ControlLevel::PartiallyFrozen
|
||
);
|
||
|
||
// 解冻分区
|
||
acc1644
|
||
.unfreeze("regulator1", &partition_id, reason, evidence, receipt)
|
||
.unwrap();
|
||
|
||
assert!(!acc1644.is_partition_frozen(&partition_id));
|
||
assert_eq!(
|
||
acc1644.gnacs_control().control_level,
|
||
ControlLevel::Normal
|
||
);
|
||
}
|
||
|
||
#[test]
|
||
fn test_global_freeze() {
|
||
let mut acc1644 = create_test_acc1644();
|
||
|
||
let global_partition = [0u8; 32];
|
||
let receipt = [1u8; 32];
|
||
|
||
acc1644
|
||
.freeze("regulator1", &global_partition, b"Emergency", b"", receipt)
|
||
.unwrap();
|
||
|
||
assert!(acc1644.is_partition_frozen(&global_partition));
|
||
assert!(acc1644.is_partition_frozen(&[1u8; 32])); // 任何分区都被冻结
|
||
assert_eq!(
|
||
acc1644.gnacs_control().control_level,
|
||
ControlLevel::FullyFrozen
|
||
);
|
||
}
|
||
|
||
#[test]
|
||
fn test_force_transfer() {
|
||
let mut acc1644 = create_test_acc1644();
|
||
|
||
let partition_id = [1u8; 32];
|
||
acc1644.mint(&partition_id, "alice", 1000);
|
||
|
||
let legal_basis = [1u8; 32];
|
||
let receipt = [1u8; 32];
|
||
|
||
acc1644
|
||
.force_transfer(
|
||
"super_reg1",
|
||
&partition_id,
|
||
"alice",
|
||
"bob",
|
||
500,
|
||
legal_basis,
|
||
b"",
|
||
receipt,
|
||
)
|
||
.unwrap();
|
||
|
||
assert_eq!(
|
||
acc1644.get_balance(&hex::encode(partition_id), "alice"),
|
||
500
|
||
);
|
||
assert_eq!(
|
||
acc1644.get_balance(&hex::encode(partition_id), "bob"),
|
||
500
|
||
);
|
||
}
|
||
|
||
#[test]
|
||
fn test_force_redeem() {
|
||
let mut acc1644 = create_test_acc1644();
|
||
|
||
let partition_id = [1u8; 32];
|
||
acc1644.mint(&partition_id, "alice", 1000);
|
||
|
||
let legal_basis = [1u8; 32];
|
||
let receipt = [1u8; 32];
|
||
|
||
acc1644
|
||
.force_redeem(
|
||
"super_reg1",
|
||
&partition_id,
|
||
"alice",
|
||
300,
|
||
legal_basis,
|
||
b"",
|
||
receipt,
|
||
)
|
||
.unwrap();
|
||
|
||
assert_eq!(
|
||
acc1644.get_balance(&hex::encode(partition_id), "alice"),
|
||
700
|
||
);
|
||
}
|
||
|
||
#[test]
|
||
fn test_take_control() {
|
||
let mut acc1644 = create_test_acc1644();
|
||
|
||
let receipt = [1u8; 32];
|
||
|
||
acc1644
|
||
.take_control("emergency1", "emergency_controller", 3600, b"Emergency", receipt)
|
||
.unwrap();
|
||
|
||
assert_eq!(acc1644.controller(), Some("emergency_controller".to_string()));
|
||
assert_eq!(
|
||
acc1644.gnacs_control().control_level,
|
||
ControlLevel::Takeover
|
||
);
|
||
}
|
||
|
||
#[test]
|
||
fn test_control_actions_history() {
|
||
let mut acc1644 = create_test_acc1644();
|
||
|
||
let partition_id = [1u8; 32];
|
||
let receipt = [1u8; 32];
|
||
|
||
acc1644
|
||
.freeze("regulator1", &partition_id, b"Test", b"", receipt)
|
||
.unwrap();
|
||
|
||
acc1644
|
||
.unfreeze("regulator1", &partition_id, b"Test", b"", receipt)
|
||
.unwrap();
|
||
|
||
let actions = acc1644.get_control_actions(0, 10);
|
||
assert_eq!(actions.len(), 2);
|
||
assert_eq!(actions[0].action_type, ControlActionType::Freeze);
|
||
assert_eq!(actions[1].action_type, ControlActionType::Unfreeze);
|
||
}
|
||
}
|