NAC_Blockchain/nac-cee/src/receipt/mod.rs

333 lines
8.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.

// 收据系统模块
use crate::ValidationResult;
use nac_udm::primitives::{Address, Hash};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
/// 执行类型
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum ExecutionType {
/// 交易执行
Transaction,
/// 区块执行
Block,
/// 状态变更
State,
/// 升级提案
Upgrade,
}
/// 宪法执行收据
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConstitutionalReceipt {
/// 收据ID
pub receipt_id: Hash,
/// 执行类型
pub execution_type: ExecutionType,
/// 目标哈希(交易哈希、区块哈希等)
pub target_hash: Hash,
/// 相关的宪法条款ID列表
pub clause_ids: Vec<u64>,
/// 验证结果
pub validation_result: ValidationResult,
/// 时间戳
pub timestamp: u64,
/// 执行者地址
pub executor: Address,
}
/// 收据生成器
pub struct ReceiptGenerator {
/// 收据计数器
counter: u64,
}
impl ReceiptGenerator {
/// 创建新的收据生成器
pub fn new() -> Self {
Self { counter: 0 }
}
/// 生成收据
pub fn generate(
&mut self,
execution_type: ExecutionType,
target_hash: Hash,
clause_ids: Vec<u64>,
validation_result: ValidationResult,
executor: Address,
) -> ConstitutionalReceipt {
self.counter += 1;
// 生成收据ID简化版实际应该使用哈希
let receipt_id = Hash::new({
let mut bytes = [0u8; 48];
bytes[0..8].copy_from_slice(&self.counter.to_be_bytes());
bytes
});
ConstitutionalReceipt {
receipt_id,
execution_type,
target_hash,
clause_ids,
validation_result,
timestamp: std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs(),
executor,
}
}
}
impl Default for ReceiptGenerator {
fn default() -> Self {
Self::new()
}
}
/// 收据存储
pub struct ReceiptStorage {
/// 收据存储
receipts: HashMap<Hash, ConstitutionalReceipt>,
/// 按目标哈希索引
by_target: HashMap<Hash, Vec<Hash>>,
/// 按执行者索引
by_executor: HashMap<Address, Vec<Hash>>,
}
impl ReceiptStorage {
/// 创建新的收据存储
pub fn new() -> Self {
Self {
receipts: HashMap::new(),
by_target: HashMap::new(),
by_executor: HashMap::new(),
}
}
/// 存储收据
pub fn store(&mut self, receipt: ConstitutionalReceipt) {
let receipt_id = receipt.receipt_id;
let target_hash = receipt.target_hash;
let executor = receipt.executor;
// 存储收据
self.receipts.insert(receipt_id, receipt);
// 更新索引
self.by_target
.entry(target_hash)
.or_insert_with(Vec::new)
.push(receipt_id);
self.by_executor
.entry(executor)
.or_insert_with(Vec::new)
.push(receipt_id);
}
/// 获取收据
pub fn get(&self, receipt_id: &Hash) -> Option<&ConstitutionalReceipt> {
self.receipts.get(receipt_id)
}
/// 按目标哈希查询收据
pub fn query_by_target(&self, target_hash: &Hash) -> Vec<&ConstitutionalReceipt> {
self.by_target
.get(target_hash)
.map(|ids| {
ids.iter()
.filter_map(|id| self.receipts.get(id))
.collect()
})
.unwrap_or_default()
}
/// 按执行者查询收据
pub fn query_by_executor(&self, executor: &Address) -> Vec<&ConstitutionalReceipt> {
self.by_executor
.get(executor)
.map(|ids| {
ids.iter()
.filter_map(|id| self.receipts.get(id))
.collect()
})
.unwrap_or_default()
}
/// 获取收据数量
pub fn count(&self) -> usize {
self.receipts.len()
}
/// 清空存储
pub fn clear(&mut self) {
self.receipts.clear();
self.by_target.clear();
self.by_executor.clear();
}
}
impl Default for ReceiptStorage {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_generator_creation() {
let generator = ReceiptGenerator::new();
assert_eq!(generator.counter, 0);
}
#[test]
fn test_generate_receipt() {
let mut generator = ReceiptGenerator::new();
let receipt = generator.generate(
ExecutionType::Transaction,
Hash::zero(),
vec![1, 2, 3],
ValidationResult {
passed: true,
violated_clauses: vec![],
warnings: vec![],
details: "Test".to_string(),
},
Address::zero(),
);
assert_eq!(receipt.execution_type, ExecutionType::Transaction);
assert_eq!(receipt.clause_ids, vec![1, 2, 3]);
assert!(receipt.validation_result.passed);
}
#[test]
fn test_storage_creation() {
let storage = ReceiptStorage::new();
assert_eq!(storage.count(), 0);
}
#[test]
fn test_store_and_get() {
let mut storage = ReceiptStorage::new();
let mut generator = ReceiptGenerator::new();
let receipt = generator.generate(
ExecutionType::Transaction,
Hash::zero(),
vec![1],
ValidationResult {
passed: true,
violated_clauses: vec![],
warnings: vec![],
details: "Test".to_string(),
},
Address::zero(),
);
let receipt_id = receipt.receipt_id;
storage.store(receipt);
assert_eq!(storage.count(), 1);
assert!(storage.get(&receipt_id).is_some());
}
#[test]
fn test_query_by_target() {
let mut storage = ReceiptStorage::new();
let mut generator = ReceiptGenerator::new();
let target_hash = Hash::new([1u8; 48]);
let receipt1 = generator.generate(
ExecutionType::Transaction,
target_hash,
vec![1],
ValidationResult {
passed: true,
violated_clauses: vec![],
warnings: vec![],
details: "Test".to_string(),
},
Address::zero(),
);
let receipt2 = generator.generate(
ExecutionType::Transaction,
target_hash,
vec![2],
ValidationResult {
passed: true,
violated_clauses: vec![],
warnings: vec![],
details: "Test".to_string(),
},
Address::zero(),
);
storage.store(receipt1);
storage.store(receipt2);
let results = storage.query_by_target(&target_hash);
assert_eq!(results.len(), 2);
}
#[test]
fn test_query_by_executor() {
let mut storage = ReceiptStorage::new();
let mut generator = ReceiptGenerator::new();
let executor = Address::new([1u8; 32]);
let receipt = generator.generate(
ExecutionType::Transaction,
Hash::zero(),
vec![1],
ValidationResult {
passed: true,
violated_clauses: vec![],
warnings: vec![],
details: "Test".to_string(),
},
executor,
);
storage.store(receipt);
let results = storage.query_by_executor(&executor);
assert_eq!(results.len(), 1);
}
#[test]
fn test_clear() {
let mut storage = ReceiptStorage::new();
let mut generator = ReceiptGenerator::new();
let receipt = generator.generate(
ExecutionType::Transaction,
Hash::zero(),
vec![1],
ValidationResult {
passed: true,
violated_clauses: vec![],
warnings: vec![],
details: "Test".to_string(),
},
Address::zero(),
);
storage.store(receipt);
assert_eq!(storage.count(), 1);
storage.clear();
assert_eq!(storage.count(), 0);
}
}