369 lines
9.2 KiB
Rust
369 lines
9.2 KiB
Rust
//! NAC UCA - 统一跨链审计器
|
||
//! Unified Cross-chain Auditor
|
||
//!
|
||
//! 基于CSNP V2.0技术白皮书第5章"UCA"
|
||
|
||
use nac_udm::primitives::{Address, Hash};
|
||
use serde::{Deserialize, Serialize};
|
||
use std::collections::HashMap;
|
||
use thiserror::Error;
|
||
|
||
#[derive(Debug, Error)]
|
||
pub enum UcaError {
|
||
#[error("Audit record not found: {0:?}")]
|
||
RecordNotFound(Hash),
|
||
|
||
#[error("Invalid proof")]
|
||
InvalidProof,
|
||
|
||
#[error("Violation detected: {0}")]
|
||
ViolationDetected(String),
|
||
}
|
||
|
||
/// 跨链行为类型
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||
pub enum CrossChainAction {
|
||
/// 资产转移
|
||
AssetTransfer,
|
||
/// 消息传递
|
||
MessagePassing,
|
||
/// 合约调用
|
||
ContractCall,
|
||
/// 状态同步
|
||
StateSync,
|
||
}
|
||
|
||
/// 跨链审计记录
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct AuditRecord {
|
||
/// 记录ID
|
||
pub record_id: Hash,
|
||
/// 源链ID
|
||
pub source_chain_id: u64,
|
||
/// 目标链ID
|
||
pub target_chain_id: u64,
|
||
/// 行为类型
|
||
pub action: CrossChainAction,
|
||
/// 发起者地址
|
||
pub initiator: Address,
|
||
/// 交易哈希
|
||
pub tx_hash: Hash,
|
||
/// 时间戳
|
||
pub timestamp: u64,
|
||
/// 行为数据
|
||
pub data: Vec<u8>,
|
||
/// 验证证明
|
||
pub proof: Vec<u8>,
|
||
/// 状态(pending/confirmed/violated)
|
||
pub status: AuditStatus,
|
||
}
|
||
|
||
/// 审计状态
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||
pub enum AuditStatus {
|
||
/// 待确认
|
||
Pending,
|
||
/// 已确认
|
||
Confirmed,
|
||
/// 违规
|
||
Violated,
|
||
}
|
||
|
||
/// 违规记录
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct ViolationRecord {
|
||
/// 违规ID
|
||
pub violation_id: Hash,
|
||
/// 相关审计记录ID
|
||
pub audit_record_id: Hash,
|
||
/// 违规类型
|
||
pub violation_type: ViolationType,
|
||
/// 违规描述
|
||
pub description: String,
|
||
/// 惩罚措施
|
||
pub penalty: Penalty,
|
||
/// 记录时间
|
||
pub timestamp: u64,
|
||
}
|
||
|
||
/// 违规类型
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||
pub enum ViolationType {
|
||
/// 双花攻击
|
||
DoubleSpending,
|
||
/// 未授权转移
|
||
UnauthorizedTransfer,
|
||
/// 数据不一致
|
||
DataInconsistency,
|
||
/// 超时未确认
|
||
TimeoutUnconfirmed,
|
||
}
|
||
|
||
/// 惩罚措施
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct Penalty {
|
||
/// 惩罚类型
|
||
pub penalty_type: PenaltyType,
|
||
/// 惩罚金额(如适用)
|
||
pub amount: u64,
|
||
/// 惩罚持续时间(秒)
|
||
pub duration_secs: u64,
|
||
}
|
||
|
||
/// 惩罚类型
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||
pub enum PenaltyType {
|
||
/// 警告
|
||
Warning,
|
||
/// 罚款
|
||
Fine,
|
||
/// 暂停服务
|
||
Suspension,
|
||
/// 永久封禁
|
||
Ban,
|
||
}
|
||
|
||
/// UCA审计器
|
||
pub struct UnifiedCrossChainAuditor {
|
||
/// 审计器ID
|
||
auditor_id: String,
|
||
/// 审计记录
|
||
records: HashMap<Hash, AuditRecord>,
|
||
/// 违规记录
|
||
violations: HashMap<Hash, ViolationRecord>,
|
||
/// 已审计交易数
|
||
audited_count: u64,
|
||
/// 检测到的违规数
|
||
violation_count: u64,
|
||
}
|
||
|
||
impl UnifiedCrossChainAuditor {
|
||
/// 创建新的UCA审计器
|
||
pub fn new(auditor_id: String) -> Self {
|
||
Self {
|
||
auditor_id,
|
||
records: HashMap::new(),
|
||
violations: HashMap::new(),
|
||
audited_count: 0,
|
||
violation_count: 0,
|
||
}
|
||
}
|
||
|
||
/// 记录跨链行为
|
||
pub fn record_action(
|
||
&mut self,
|
||
source_chain_id: u64,
|
||
target_chain_id: u64,
|
||
action: CrossChainAction,
|
||
initiator: Address,
|
||
tx_hash: Hash,
|
||
data: Vec<u8>,
|
||
proof: Vec<u8>,
|
||
timestamp: u64,
|
||
) -> Hash {
|
||
// 生成记录ID
|
||
let record_id = self.generate_record_id(&tx_hash, timestamp);
|
||
|
||
let record = AuditRecord {
|
||
record_id,
|
||
source_chain_id,
|
||
target_chain_id,
|
||
action,
|
||
initiator,
|
||
tx_hash,
|
||
timestamp,
|
||
data,
|
||
proof,
|
||
status: AuditStatus::Pending,
|
||
};
|
||
|
||
self.records.insert(record_id, record);
|
||
self.audited_count += 1;
|
||
|
||
record_id
|
||
}
|
||
|
||
/// 验证跨链行为
|
||
pub fn verify_action(&mut self, record_id: &Hash) -> Result<bool, UcaError> {
|
||
// 先获取必要的数据
|
||
let (is_valid, timestamp) = {
|
||
let record = self.records
|
||
.get(record_id)
|
||
.ok_or(UcaError::RecordNotFound(*record_id))?;
|
||
(!record.proof.is_empty(), record.timestamp)
|
||
};
|
||
|
||
// 更新状态
|
||
if is_valid {
|
||
if let Some(record) = self.records.get_mut(record_id) {
|
||
record.status = AuditStatus::Confirmed;
|
||
}
|
||
Ok(true)
|
||
} else {
|
||
if let Some(record) = self.records.get_mut(record_id) {
|
||
record.status = AuditStatus::Violated;
|
||
}
|
||
|
||
// 记录违规
|
||
self.record_violation(
|
||
*record_id,
|
||
ViolationType::DataInconsistency,
|
||
"Invalid proof".to_string(),
|
||
Penalty {
|
||
penalty_type: PenaltyType::Warning,
|
||
amount: 0,
|
||
duration_secs: 0,
|
||
},
|
||
timestamp,
|
||
);
|
||
|
||
Ok(false)
|
||
}
|
||
}
|
||
|
||
/// 记录违规
|
||
pub fn record_violation(
|
||
&mut self,
|
||
audit_record_id: Hash,
|
||
violation_type: ViolationType,
|
||
description: String,
|
||
penalty: Penalty,
|
||
timestamp: u64,
|
||
) -> Hash {
|
||
let violation_id = self.generate_violation_id(&audit_record_id, timestamp);
|
||
|
||
let violation = ViolationRecord {
|
||
violation_id,
|
||
audit_record_id,
|
||
violation_type,
|
||
description,
|
||
penalty,
|
||
timestamp,
|
||
};
|
||
|
||
self.violations.insert(violation_id, violation);
|
||
self.violation_count += 1;
|
||
|
||
violation_id
|
||
}
|
||
|
||
/// 查询审计记录
|
||
pub fn get_record(&self, record_id: &Hash) -> Option<&AuditRecord> {
|
||
self.records.get(record_id)
|
||
}
|
||
|
||
/// 查询违规记录
|
||
pub fn get_violation(&self, violation_id: &Hash) -> Option<&ViolationRecord> {
|
||
self.violations.get(violation_id)
|
||
}
|
||
|
||
/// 获取统计信息
|
||
pub fn get_stats(&self) -> UcaStats {
|
||
UcaStats {
|
||
auditor_id: self.auditor_id.clone(),
|
||
total_audited: self.audited_count,
|
||
total_violations: self.violation_count,
|
||
pending_records: self.records.values()
|
||
.filter(|r| r.status == AuditStatus::Pending)
|
||
.count(),
|
||
}
|
||
}
|
||
|
||
/// 生成记录ID
|
||
fn generate_record_id(&self, tx_hash: &Hash, timestamp: u64) -> Hash {
|
||
// 简化实现:使用tx_hash作为record_id
|
||
*tx_hash
|
||
}
|
||
|
||
/// 生成违规ID
|
||
fn generate_violation_id(&self, audit_record_id: &Hash, timestamp: u64) -> Hash {
|
||
// 简化实现:使用audit_record_id作为violation_id
|
||
*audit_record_id
|
||
}
|
||
|
||
/// 获取审计器ID
|
||
pub fn auditor_id(&self) -> &str {
|
||
&self.auditor_id
|
||
}
|
||
}
|
||
|
||
/// UCA统计信息
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct UcaStats {
|
||
pub auditor_id: String,
|
||
pub total_audited: u64,
|
||
pub total_violations: u64,
|
||
pub pending_records: usize,
|
||
}
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
fn create_test_hash(id: u8) -> Hash {
|
||
let mut bytes = [0u8; 48];
|
||
bytes[47] = id;
|
||
Hash::from_bytes(bytes)
|
||
}
|
||
|
||
fn create_test_address(id: u8) -> Address {
|
||
let mut bytes = [0u8; 32];
|
||
bytes[31] = id;
|
||
Address::from_bytes(bytes)
|
||
}
|
||
|
||
#[test]
|
||
fn test_record_and_verify() {
|
||
let mut auditor = UnifiedCrossChainAuditor::new("uca1".to_string());
|
||
|
||
let tx_hash = create_test_hash(1);
|
||
let initiator = create_test_address(1);
|
||
|
||
// 记录跨链行为
|
||
let record_id = auditor.record_action(
|
||
1,
|
||
2,
|
||
CrossChainAction::AssetTransfer,
|
||
initiator,
|
||
tx_hash,
|
||
vec![1, 2, 3],
|
||
vec![4, 5, 6], // 有效proof
|
||
1000,
|
||
);
|
||
|
||
// 验证
|
||
let is_valid = auditor.verify_action(&record_id).expect("mainnet: handle error");
|
||
assert!(is_valid);
|
||
|
||
let record = auditor.get_record(&record_id).expect("mainnet: handle error");
|
||
assert_eq!(record.status, AuditStatus::Confirmed);
|
||
}
|
||
|
||
#[test]
|
||
fn test_violation_detection() {
|
||
let mut auditor = UnifiedCrossChainAuditor::new("uca1".to_string());
|
||
|
||
let tx_hash = create_test_hash(1);
|
||
let initiator = create_test_address(1);
|
||
|
||
// 记录无效的跨链行为
|
||
let record_id = auditor.record_action(
|
||
1,
|
||
2,
|
||
CrossChainAction::AssetTransfer,
|
||
initiator,
|
||
tx_hash,
|
||
vec![1, 2, 3],
|
||
vec![], // 无效proof
|
||
1000,
|
||
);
|
||
|
||
// 验证
|
||
let is_valid = auditor.verify_action(&record_id).expect("mainnet: handle error");
|
||
assert!(!is_valid);
|
||
|
||
let stats = auditor.get_stats();
|
||
assert_eq!(stats.total_violations, 1);
|
||
}
|
||
}
|