NAC_Blockchain/nac-cbpp/src/receipt.rs

225 lines
7.4 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.

//! 宪法收据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-38448 字节)
pub tx_hash: String,
/// 宪法哈希(当前生效的宪法版本哈希)
pub constitution_hash: String,
/// 执行结果哈希CEE 执行后的状态哈希)
pub execution_result_hash: String,
/// CEE 签名(宪法执行引擎的签名)
pub cee_signature: String,
/// 签发时间
pub issued_at: DateTime<Utc>,
/// 有效期截止时间(时间窗口)
pub expires_at: DateTime<Utc>,
/// 收据权重(用于分叉选择的收据权重累计)
pub weight: u64,
/// 合规等级1-5影响权重
pub compliance_level: u8,
/// 资产类型GNACS 编码)
pub asset_gnacs_code: Option<String>,
}
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<String>,
) -> 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<Utc>) -> 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<ConstitutionalReceipt>,
/// 总权重(用于分叉选择)
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);
}
}