//! 宪法收据(Constitutional Receipt, CR) //! //! CBPP 共识的核心凭证。每笔交易在上链前必须由宪法执行引擎(CEE) //! 签发 CR,节点只需验证 CR 的有效性(签名、宪法哈希、时间窗口), //! 无需投票或协商——这是 CBPP 与 PoW/PoS/BFT 的根本区别。 //! //! # CBPP 共识原则 //! - 参与即共识:节点遵守规则的行为本身就是共识,无需额外投票 //! - 规则服从 vs 协商共识:CBPP 是规则验证而非节点协商 //! - 宪法收据(CR):交易合法性的唯一证明,由 CEE 签发 use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use sha3::{Digest, Sha3_384}; /// 宪法收据(Constitutional Receipt) /// /// 每笔交易的合法性证明,包含交易哈希、宪法哈希、执行结果哈希、CEE 签名。 /// 节点通过验证 CR 来确认交易合法,无需投票。 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ConstitutionalReceipt { /// 收据 ID(唯一标识) pub receipt_id: String, /// 交易哈希(SHA3-384,48 字节) pub tx_hash: String, /// 宪法哈希(当前生效的宪法版本哈希) pub constitution_hash: String, /// 执行结果哈希(CEE 执行后的状态哈希) pub execution_result_hash: String, /// CEE 签名(宪法执行引擎的签名) pub cee_signature: String, /// 签发时间 pub issued_at: DateTime, /// 有效期截止时间(时间窗口) pub expires_at: DateTime, /// 收据权重(用于分叉选择的收据权重累计) pub weight: u64, /// 合规等级(1-5,影响权重) pub compliance_level: u8, /// 资产类型(GNACS 编码) pub asset_gnacs_code: Option, } impl ConstitutionalReceipt { /// 创建新的宪法收据 pub fn new( tx_hash: String, constitution_hash: String, execution_result_hash: String, cee_signature: String, compliance_level: u8, asset_gnacs_code: Option, ) -> Self { let issued_at = Utc::now(); // 收据有效期:10 分钟时间窗口 let expires_at = issued_at + chrono::Duration::minutes(10); let weight = Self::calculate_weight(compliance_level); let receipt_id = Self::generate_id(&tx_hash, &constitution_hash, &issued_at); ConstitutionalReceipt { receipt_id, tx_hash, constitution_hash, execution_result_hash, cee_signature, issued_at, expires_at, weight, compliance_level, asset_gnacs_code, } } /// 计算收据权重 /// /// 权重基于合规等级,用于分叉选择时的收据权重累计。 /// 高合规等级的交易权重更高,鼓励合规行为。 pub fn calculate_weight(compliance_level: u8) -> u64 { match compliance_level { 1 => 100, // 基础合规 2 => 200, // 标准合规 3 => 400, // 增强合规 4 => 700, // 高级合规 5 => 1000, // 最高合规(机构级) _ => 50, // 未知等级,最低权重 } } /// 生成收据 ID fn generate_id(tx_hash: &str, constitution_hash: &str, issued_at: &DateTime) -> String { let data = format!("{}{}{}CR", tx_hash, constitution_hash, issued_at.timestamp_nanos_opt().unwrap_or(0)); let hash = Sha3_384::digest(data.as_bytes()); format!("CR-{}", hex::encode(&hash[..16])) } /// 验证 CR 是否在有效时间窗口内 pub fn is_valid_time_window(&self) -> bool { let now = Utc::now(); now >= self.issued_at && now <= self.expires_at } /// 验证 CR 签名(简化版,实际应使用 BLS 签名验证) pub fn verify_signature(&self) -> bool { // 实际实现中需要使用 CEE 公钥验证 BLS 签名 // 此处为结构占位,真实验证由 CeeSignatureVerifier 完成 !self.cee_signature.is_empty() } /// 验证宪法哈希是否匹配当前生效宪法 pub fn verify_constitution_hash(&self, current_constitution_hash: &str) -> bool { self.constitution_hash == current_constitution_hash } /// 完整验证 CR(签名 + 时间窗口 + 宪法哈希) pub fn verify(&self, current_constitution_hash: &str) -> CrVerificationResult { if !self.verify_signature() { return CrVerificationResult::InvalidSignature; } if !self.is_valid_time_window() { return CrVerificationResult::Expired; } if !self.verify_constitution_hash(current_constitution_hash) { return CrVerificationResult::ConstitutionMismatch; } CrVerificationResult::Valid } } /// CR 验证结果 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum CrVerificationResult { /// 验证通过 Valid, /// 签名无效(CEE 签名不匹配) InvalidSignature, /// 已过期(超出时间窗口) Expired, /// 宪法哈希不匹配(宪法已更新) ConstitutionMismatch, } /// CR 集合(一个区块内的所有宪法收据) #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct ReceiptSet { /// 收据列表 receipts: Vec, /// 总权重(用于分叉选择) total_weight: u64, } impl ReceiptSet { pub fn new() -> Self { Self::default() } /// 添加已验证的 CR pub fn add_receipt(&mut self, receipt: ConstitutionalReceipt) { self.total_weight += receipt.weight; self.receipts.push(receipt); } /// 获取总权重(分叉选择时使用) pub fn total_weight(&self) -> u64 { self.total_weight } /// 获取收据数量 pub fn len(&self) -> usize { self.receipts.len() } /// 是否为空 pub fn is_empty(&self) -> bool { self.receipts.is_empty() } /// 获取所有收据 pub fn receipts(&self) -> &[ConstitutionalReceipt] { &self.receipts } } #[cfg(test)] mod tests { use super::*; #[test] fn test_cr_creation() { let cr = ConstitutionalReceipt::new( "tx_hash_001".to_string(), "constitution_hash_v1".to_string(), "exec_result_hash".to_string(), "cee_signature_001".to_string(), 3, Some("RE01".to_string()), ); assert!(cr.receipt_id.starts_with("CR-")); assert_eq!(cr.weight, 400); // 合规等级 3 → 权重 400 } #[test] fn test_cr_weight_calculation() { assert_eq!(ConstitutionalReceipt::calculate_weight(1), 100); assert_eq!(ConstitutionalReceipt::calculate_weight(3), 400); assert_eq!(ConstitutionalReceipt::calculate_weight(5), 1000); } #[test] fn test_receipt_set_weight() { let mut set = ReceiptSet::new(); let cr1 = ConstitutionalReceipt::new( "tx1".to_string(), "ch1".to_string(), "er1".to_string(), "sig1".to_string(), 3, None, ); let cr2 = ConstitutionalReceipt::new( "tx2".to_string(), "ch1".to_string(), "er2".to_string(), "sig2".to_string(), 5, None, ); set.add_receipt(cr1); set.add_receipt(cr2); assert_eq!(set.total_weight(), 1400); // 400 + 1000 assert_eq!(set.len(), 2); } }