NAC_Blockchain/nac-cbpp-l1/src/lib.rs

380 lines
9.8 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 CBPP L1层 - Charter合约实现
//!
//! 实现CBPConstitutional Block Producer注册与管理合约
//! 基于CBPP技术白皮书第5章"开放生产网络(OPN)"
use nac_udm::primitives::{Address, Hash};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use thiserror::Error;
// 导出子模块
pub mod exit;
pub mod redemption;
pub mod reputation;
pub mod penalty;
// 重新导出常用类型
pub use exit::{ExitManager, ExitRequest, ExitRecord, ExitStatus, ExitReason};
pub use redemption::{RedemptionManager, RedemptionRequest, RedemptionRecord, RedemptionType, RedemptionStatus};
pub use reputation::{ReputationManager, ReputationEvent, ReputationChange, ReputationConfig};
pub use penalty::{PenaltyManager, ViolationType, PenaltyType, PenaltyRecord, AppealRequest};
#[derive(Debug, Error)]
pub enum CbppL1Error {
#[error("CBP already registered: {0:?}")]
AlreadyRegistered(Address),
#[error("CBP not found: {0:?}")]
NotFound(Address),
#[error("Insufficient stake: required {required}, got {actual}")]
InsufficientStake { required: u64, actual: u64 },
#[error("Invalid KYC level: {0}")]
InvalidKycLevel(u8),
#[error("Hardware benchmark failed")]
HardwareBenchmarkFailed,
#[error("Constitution test failed: score {0}/100")]
ConstitutionTestFailed(u8),
// 退出相关错误
#[error("Exit request already exists")]
ExitRequestExists,
#[error("Exit request not found")]
ExitRequestNotFound,
#[error("Review period not met")]
ReviewPeriodNotMet,
#[error("Confirmation period not met")]
ConfirmationPeriodNotMet,
// 赎回相关错误
#[error("Redemption request already exists")]
RedemptionRequestExists,
#[error("Redemption request not found")]
RedemptionRequestNotFound,
#[error("Lock period not met")]
LockPeriodNotMet,
#[error("Invalid redemption amount")]
InvalidRedemptionAmount,
#[error("Insufficient remaining stake")]
InsufficientRemainingStake,
#[error("Insufficient stake for penalty")]
InsufficientStakeForPenalty,
// 处罚相关错误
#[error("Unknown violation type")]
UnknownViolationType,
#[error("Penalty record not found")]
PenaltyRecordNotFound,
#[error("Already appealed")]
AlreadyAppealed,
#[error("Appeal period expired")]
AppealPeriodExpired,
#[error("Appeal not found")]
AppealNotFound,
#[error("Invalid address")]
InvalidAddress,
// 通用错误
#[error("Invalid status: {0}")]
InvalidStatus(String),
}
/// CBP节点状态
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum CbpStatus {
Candidate,
Active,
Suspended,
Exited,
}
/// CBP节点信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CbpNode {
pub address: Address,
pub did: String,
pub stake_amount: u64,
pub kyc_level: u8,
pub hardware_score: u32,
pub constitution_score: u8,
pub status: CbpStatus,
pub registered_at: u64,
pub last_active_at: u64,
pub blocks_produced: u64,
pub reputation: f64,
}
/// CBP注册要求
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CbpRequirements {
pub min_stake: u64,
pub min_kyc_level: u8,
pub min_hardware_score: u32,
pub min_constitution_score: u8,
}
impl Default for CbpRequirements {
fn default() -> Self {
Self {
min_stake: 100_000_000_000,
min_kyc_level: 2,
min_hardware_score: 7000,
min_constitution_score: 70,
}
}
}
/// CBP注册与管理合约
pub struct CbpRegistry {
nodes: HashMap<Address, CbpNode>,
requirements: CbpRequirements,
active_cbps: Vec<Address>,
exit_manager: ExitManager,
redemption_manager: RedemptionManager,
reputation_manager: ReputationManager,
penalty_manager: PenaltyManager,
}
impl CbpRegistry {
pub fn new() -> Self {
Self {
nodes: HashMap::new(),
requirements: CbpRequirements::default(),
active_cbps: Vec::new(),
exit_manager: ExitManager::new(),
redemption_manager: RedemptionManager::new(),
reputation_manager: ReputationManager::new(),
penalty_manager: PenaltyManager::new(),
}
}
pub fn register_cbp(
&mut self,
address: Address,
did: String,
stake_amount: u64,
kyc_level: u8,
hardware_score: u32,
constitution_score: u8,
timestamp: u64,
) -> Result<(), CbppL1Error> {
if self.nodes.contains_key(&address) {
return Err(CbppL1Error::AlreadyRegistered(address));
}
if stake_amount < self.requirements.min_stake {
return Err(CbppL1Error::InsufficientStake {
required: self.requirements.min_stake,
actual: stake_amount,
});
}
if kyc_level < self.requirements.min_kyc_level {
return Err(CbppL1Error::InvalidKycLevel(kyc_level));
}
if hardware_score < self.requirements.min_hardware_score {
return Err(CbppL1Error::HardwareBenchmarkFailed);
}
if constitution_score < self.requirements.min_constitution_score {
return Err(CbppL1Error::ConstitutionTestFailed(constitution_score));
}
let node = CbpNode {
address,
did,
stake_amount,
kyc_level,
hardware_score,
constitution_score,
status: CbpStatus::Candidate,
registered_at: timestamp,
last_active_at: timestamp,
blocks_produced: 0,
reputation: 0.5,
};
self.nodes.insert(address, node);
Ok(())
}
pub fn activate_cbp(&mut self, address: &Address) -> Result<(), CbppL1Error> {
let node = self.nodes.get_mut(address)
.ok_or(CbppL1Error::NotFound(*address))?;
if node.status == CbpStatus::Candidate {
node.status = CbpStatus::Active;
self.active_cbps.push(*address);
}
Ok(())
}
pub fn suspend_cbp(&mut self, address: &Address) -> Result<(), CbppL1Error> {
let node = self.nodes.get_mut(address)
.ok_or(CbppL1Error::NotFound(*address))?;
if node.status == CbpStatus::Active {
node.status = CbpStatus::Suspended;
self.active_cbps.retain(|addr| addr != address);
}
Ok(())
}
pub fn get_cbp(&self, address: &Address) -> Option<&CbpNode> {
self.nodes.get(address)
}
pub fn get_cbp_mut(&mut self, address: &Address) -> Option<&mut CbpNode> {
self.nodes.get_mut(address)
}
pub fn get_active_cbps(&self) -> &[Address] {
&self.active_cbps
}
pub fn get_all_nodes(&self) -> Vec<&CbpNode> {
self.nodes.values().collect()
}
// 退出管理
pub fn exit_manager(&self) -> &ExitManager {
&self.exit_manager
}
pub fn exit_manager_mut(&mut self) -> &mut ExitManager {
&mut self.exit_manager
}
// 赎回管理
pub fn redemption_manager(&self) -> &RedemptionManager {
&self.redemption_manager
}
pub fn redemption_manager_mut(&mut self) -> &mut RedemptionManager {
&mut self.redemption_manager
}
// 声誉管理
pub fn reputation_manager(&self) -> &ReputationManager {
&self.reputation_manager
}
pub fn reputation_manager_mut(&mut self) -> &mut ReputationManager {
&mut self.reputation_manager
}
// 处罚管理
pub fn penalty_manager(&self) -> &PenaltyManager {
&self.penalty_manager
}
pub fn penalty_manager_mut(&mut self) -> &mut PenaltyManager {
&mut self.penalty_manager
}
}
impl Default for CbpRegistry {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_register_cbp() {
let mut registry = CbpRegistry::new();
let address = Address::new([1u8; 32]);
let result = registry.register_cbp(
address,
"did:nac:test".to_string(),
100_000_000_000,
2,
8000,
80,
1000,
);
assert!(result.is_ok());
assert!(registry.get_cbp(&address).is_some());
}
#[test]
fn test_activate_cbp() {
let mut registry = CbpRegistry::new();
let address = Address::new([1u8; 32]);
registry.register_cbp(
address,
"did:nac:test".to_string(),
100_000_000_000,
2,
8000,
80,
1000,
).unwrap();
let result = registry.activate_cbp(&address);
assert!(result.is_ok());
let node = registry.get_cbp(&address).unwrap();
assert_eq!(node.status, CbpStatus::Active);
}
#[test]
fn test_suspend_cbp() {
let mut registry = CbpRegistry::new();
let address = Address::new([1u8; 32]);
registry.register_cbp(
address,
"did:nac:test".to_string(),
100_000_000_000,
2,
8000,
80,
1000,
).unwrap();
registry.activate_cbp(&address).unwrap();
let result = registry.suspend_cbp(&address);
assert!(result.is_ok());
let node = registry.get_cbp(&address).unwrap();
assert_eq!(node.status, CbpStatus::Suspended);
}
#[test]
fn test_integrated_managers() {
let registry = CbpRegistry::new();
// 测试所有管理器都已初始化
assert!(registry.exit_manager().get_pending_requests().is_empty());
assert!(registry.redemption_manager().get_pending_requests().is_empty());
assert!(registry.penalty_manager().get_penalty_records(None).is_empty());
}
}