333 lines
8.4 KiB
Rust
333 lines
8.4 KiB
Rust
// 收据系统模块
|
||
|
||
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);
|
||
}
|
||
}
|