356 lines
11 KiB
Rust
356 lines
11 KiB
Rust
//! 升级治理模块(CBPP 宪法授权审批机制)
|
||
//!
|
||
//! 在 NAC 公链中,协议升级不通过节点投票决定,而是通过宪法授权审批。
|
||
//! 升级提案必须通过 CEE(宪法执行引擎)的合规验证,并由具有有效 DID+KYC 的
|
||
//! CBP(宪政区块生产者)进行宪法收据(CR)签署确认。
|
||
//!
|
||
//! 与以太坊治理的根本区别:
|
||
//! - 以太坊:节点投票(Yes/No/Abstain),多数决
|
||
//! - CBPP:宪法规则验证,CR 权重累计,合规优先
|
||
|
||
use serde::{Deserialize, Serialize};
|
||
|
||
/// 宪法授权类型(替代以太坊风格的 Yes/No/Abstain 投票)
|
||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||
pub enum ConstitutionalApproval {
|
||
/// 宪法授权通过(CBP 签署 CR,确认升级符合宪法规则)
|
||
Authorized,
|
||
/// 宪法拒绝(升级违反宪法规则,CEE 验证不通过)
|
||
Rejected(String),
|
||
/// 待审核(等待 CEE 完成合规验证)
|
||
PendingReview,
|
||
}
|
||
|
||
/// 宪法审批记录(替代以太坊风格的 VoteRecord)
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct ApprovalRecord {
|
||
/// 审批 CBP 的 DID 地址(32 字节 NAC 地址,非以太坊 20 字节地址)
|
||
pub cbp_did: String,
|
||
/// 审批类型
|
||
pub approval: ConstitutionalApproval,
|
||
/// CR 权重(宪法收据权重,非以太坊的 voting_power/stake)
|
||
pub receipt_weight: u64,
|
||
/// 审批时间(UTC)
|
||
pub approved_at: chrono::DateTime<chrono::Utc>,
|
||
/// 宪法收据哈希(SHA3-384,48 字节,非以太坊 Keccak-256)
|
||
pub receipt_hash: String,
|
||
}
|
||
|
||
impl ApprovalRecord {
|
||
/// 创建新的宪法审批记录
|
||
pub fn new(cbp_did: String, approval: ConstitutionalApproval, receipt_weight: u64) -> Self {
|
||
Self {
|
||
cbp_did,
|
||
approval,
|
||
receipt_weight,
|
||
approved_at: chrono::Utc::now(),
|
||
receipt_hash: String::new(),
|
||
}
|
||
}
|
||
|
||
/// 创建带 CR 哈希的审批记录
|
||
pub fn with_receipt(
|
||
cbp_did: String,
|
||
approval: ConstitutionalApproval,
|
||
receipt_weight: u64,
|
||
receipt_hash: String,
|
||
) -> Self {
|
||
Self {
|
||
cbp_did,
|
||
approval,
|
||
receipt_weight,
|
||
approved_at: chrono::Utc::now(),
|
||
receipt_hash,
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 宪法审批结果(替代以太坊风格的 VoteResult)
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct ApprovalResult {
|
||
/// 已授权的 CR 权重总量
|
||
pub authorized_weight: u64,
|
||
/// 已拒绝的 CR 权重总量
|
||
pub rejected_weight: u64,
|
||
/// 待审核的 CR 权重总量
|
||
pub pending_weight: u64,
|
||
/// 总 CR 权重
|
||
pub total_weight: u64,
|
||
/// 审批记录列表
|
||
pub records: Vec<ApprovalRecord>,
|
||
}
|
||
|
||
impl ApprovalResult {
|
||
/// 创建新的审批结果
|
||
pub fn new() -> Self {
|
||
Self {
|
||
authorized_weight: 0,
|
||
rejected_weight: 0,
|
||
pending_weight: 0,
|
||
total_weight: 0,
|
||
records: Vec::new(),
|
||
}
|
||
}
|
||
|
||
/// 添加审批记录
|
||
pub fn add_approval(&mut self, record: ApprovalRecord) {
|
||
match &record.approval {
|
||
ConstitutionalApproval::Authorized => {
|
||
self.authorized_weight += record.receipt_weight;
|
||
}
|
||
ConstitutionalApproval::Rejected(_) => {
|
||
self.rejected_weight += record.receipt_weight;
|
||
}
|
||
ConstitutionalApproval::PendingReview => {
|
||
self.pending_weight += record.receipt_weight;
|
||
}
|
||
}
|
||
self.total_weight += record.receipt_weight;
|
||
self.records.push(record);
|
||
}
|
||
|
||
/// 判断升级是否通过宪法授权(基于 CR 权重比例,非投票数量)
|
||
pub fn is_constitutionally_approved(&self, threshold_percent: u64) -> bool {
|
||
if self.total_weight == 0 {
|
||
return false;
|
||
}
|
||
let authorized_percent = self.authorized_weight * 100 / self.total_weight;
|
||
authorized_percent >= threshold_percent
|
||
}
|
||
|
||
/// 判断升级是否被宪法拒绝
|
||
pub fn is_constitutionally_rejected(&self, threshold_percent: u64) -> bool {
|
||
if self.total_weight == 0 {
|
||
return false;
|
||
}
|
||
let rejected_percent = self.rejected_weight * 100 / self.total_weight;
|
||
rejected_percent >= threshold_percent
|
||
}
|
||
|
||
/// 获取授权百分比
|
||
pub fn authorized_percentage(&self) -> f64 {
|
||
if self.total_weight == 0 {
|
||
return 0.0;
|
||
}
|
||
(self.authorized_weight as f64 / self.total_weight as f64) * 100.0
|
||
}
|
||
|
||
/// 获取拒绝百分比
|
||
pub fn rejected_percentage(&self) -> f64 {
|
||
if self.total_weight == 0 {
|
||
return 0.0;
|
||
}
|
||
(self.rejected_weight as f64 / self.total_weight as f64) * 100.0
|
||
}
|
||
|
||
/// 获取待审核百分比
|
||
pub fn pending_percentage(&self) -> f64 {
|
||
if self.total_weight == 0 {
|
||
return 0.0;
|
||
}
|
||
(self.pending_weight as f64 / self.total_weight as f64) * 100.0
|
||
}
|
||
}
|
||
|
||
impl Default for ApprovalResult {
|
||
fn default() -> Self {
|
||
Self::new()
|
||
}
|
||
}
|
||
|
||
/// 宪法治理配置(替代以太坊风格的 GovernanceConfig)
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct ConstitutionalGovernanceConfig {
|
||
/// 授权通过阈值(CR 权重百分比,默认 66%)
|
||
pub approval_threshold: u64,
|
||
/// 最小参与 CBP 数量(开放生产网络 OPN 要求)
|
||
pub min_cbp_count: usize,
|
||
/// 最小总 CR 权重
|
||
pub min_total_weight: u64,
|
||
/// 审批超时(秒)
|
||
pub review_timeout_secs: u64,
|
||
}
|
||
|
||
impl ConstitutionalGovernanceConfig {
|
||
/// 标准配置(66% CR 权重阈值)
|
||
pub fn default_config() -> Self {
|
||
Self {
|
||
approval_threshold: 66,
|
||
min_cbp_count: 3,
|
||
min_total_weight: 1000,
|
||
review_timeout_secs: 86400, // 24 小时
|
||
}
|
||
}
|
||
|
||
/// 严格配置(80% CR 权重阈值,用于重大协议升级)
|
||
pub fn strict_config() -> Self {
|
||
Self {
|
||
approval_threshold: 80,
|
||
min_cbp_count: 5,
|
||
min_total_weight: 5000,
|
||
review_timeout_secs: 604800, // 7 天
|
||
}
|
||
}
|
||
|
||
/// 宽松配置(50% CR 权重阈值,用于紧急修复)
|
||
pub fn relaxed_config() -> Self {
|
||
Self {
|
||
approval_threshold: 50,
|
||
min_cbp_count: 1,
|
||
min_total_weight: 100,
|
||
review_timeout_secs: 3600, // 1 小时
|
||
}
|
||
}
|
||
|
||
/// 验证审批结果是否满足宪法治理要求
|
||
pub fn validate_result(&self, result: &ApprovalResult) -> bool {
|
||
// 检查最小 CBP 参与数量
|
||
let cbp_count = result.records.iter()
|
||
.filter(|r| matches!(r.approval, ConstitutionalApproval::Authorized))
|
||
.count();
|
||
if cbp_count < self.min_cbp_count {
|
||
return false;
|
||
}
|
||
// 检查最小总 CR 权重
|
||
if result.total_weight < self.min_total_weight {
|
||
return false;
|
||
}
|
||
// 检查授权阈值
|
||
result.is_constitutionally_approved(self.approval_threshold)
|
||
}
|
||
}
|
||
|
||
// ============================================================
|
||
// 向后兼容别名(保留旧 API 以避免破坏现有调用代码)
|
||
// 注意:这些别名仅用于过渡期,新代码应使用 Constitutional* 类型
|
||
// ============================================================
|
||
|
||
/// @deprecated 使用 ConstitutionalApproval 替代
|
||
pub type Vote = ConstitutionalApproval;
|
||
|
||
/// @deprecated 使用 ApprovalRecord 替代
|
||
pub type VoteRecord = ApprovalRecord;
|
||
|
||
/// @deprecated 使用 ApprovalResult 替代
|
||
pub type VoteResult = ApprovalResult;
|
||
|
||
/// @deprecated 使用 ConstitutionalGovernanceConfig 替代
|
||
pub type GovernanceConfig = ConstitutionalGovernanceConfig;
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
#[test]
|
||
fn test_approval_record_creation() {
|
||
let record = ApprovalRecord::new(
|
||
"did:nac:cbp1".to_string(),
|
||
ConstitutionalApproval::Authorized,
|
||
1000,
|
||
);
|
||
assert_eq!(record.cbp_did, "did:nac:cbp1");
|
||
assert_eq!(record.approval, ConstitutionalApproval::Authorized);
|
||
assert_eq!(record.receipt_weight, 1000);
|
||
}
|
||
|
||
#[test]
|
||
fn test_approval_result_add_approval() {
|
||
let mut result = ApprovalResult::new();
|
||
result.add_approval(ApprovalRecord::new(
|
||
"did:nac:cbp1".to_string(),
|
||
ConstitutionalApproval::Authorized,
|
||
1000,
|
||
));
|
||
result.add_approval(ApprovalRecord::new(
|
||
"did:nac:cbp2".to_string(),
|
||
ConstitutionalApproval::Authorized,
|
||
1000,
|
||
));
|
||
result.add_approval(ApprovalRecord::new(
|
||
"did:nac:cbp3".to_string(),
|
||
ConstitutionalApproval::Rejected("违反宪法第3条".to_string()),
|
||
500,
|
||
));
|
||
assert_eq!(result.authorized_weight, 2000);
|
||
assert_eq!(result.rejected_weight, 500);
|
||
assert_eq!(result.total_weight, 2500);
|
||
}
|
||
|
||
#[test]
|
||
fn test_constitutional_approval_threshold() {
|
||
let mut result = ApprovalResult::new();
|
||
result.add_approval(ApprovalRecord::new(
|
||
"did:nac:cbp1".to_string(),
|
||
ConstitutionalApproval::Authorized,
|
||
700,
|
||
));
|
||
result.add_approval(ApprovalRecord::new(
|
||
"did:nac:cbp2".to_string(),
|
||
ConstitutionalApproval::Rejected("".to_string()),
|
||
300,
|
||
));
|
||
// 70% 授权权重 >= 66% 阈值
|
||
assert!(result.is_constitutionally_approved(66));
|
||
// 70% 授权权重 < 80% 阈值
|
||
assert!(!result.is_constitutionally_approved(80));
|
||
}
|
||
|
||
#[test]
|
||
fn test_governance_config_default() {
|
||
let config = ConstitutionalGovernanceConfig::default_config();
|
||
assert_eq!(config.approval_threshold, 66);
|
||
assert_eq!(config.min_cbp_count, 3);
|
||
}
|
||
|
||
#[test]
|
||
fn test_governance_config_strict() {
|
||
let config = ConstitutionalGovernanceConfig::strict_config();
|
||
assert_eq!(config.approval_threshold, 80);
|
||
assert_eq!(config.min_cbp_count, 5);
|
||
}
|
||
|
||
#[test]
|
||
fn test_governance_config_relaxed() {
|
||
let config = ConstitutionalGovernanceConfig::relaxed_config();
|
||
assert_eq!(config.approval_threshold, 50);
|
||
assert_eq!(config.min_cbp_count, 1);
|
||
}
|
||
|
||
#[test]
|
||
fn test_governance_config_validate_result() {
|
||
let config = ConstitutionalGovernanceConfig::default_config();
|
||
let mut result = ApprovalResult::new();
|
||
|
||
// 不满足最小 CBP 数量(需要 3 个)
|
||
result.add_approval(ApprovalRecord::new(
|
||
"did:nac:cbp1".to_string(),
|
||
ConstitutionalApproval::Authorized,
|
||
500,
|
||
));
|
||
assert!(!config.validate_result(&result));
|
||
|
||
// 满足 CBP 数量但不满足最小权重
|
||
result.add_approval(ApprovalRecord::new(
|
||
"did:nac:cbp2".to_string(),
|
||
ConstitutionalApproval::Authorized,
|
||
300,
|
||
));
|
||
result.add_approval(ApprovalRecord::new(
|
||
"did:nac:cbp3".to_string(),
|
||
ConstitutionalApproval::Authorized,
|
||
100,
|
||
));
|
||
// total_weight = 900 < min_total_weight = 1000
|
||
assert!(!config.validate_result(&result));
|
||
|
||
// 满足所有条件
|
||
result.add_approval(ApprovalRecord::new(
|
||
"did:nac:cbp4".to_string(),
|
||
ConstitutionalApproval::Authorized,
|
||
200,
|
||
));
|
||
// total_weight = 1100 >= 1000, authorized = 1100/1100 = 100% >= 66%
|
||
assert!(config.validate_result(&result));
|
||
}
|
||
}
|