// NVM-L0 DAG数据结构(预留用于未来兼容) // // ⚠️ 重要说明: // 1. NAC使用CBPP共识机制,不是DAG共识 // 2. 此文件中的DAG是作为数据结构使用,不是共识机制 // 3. 当前版本暂不使用,预留用于未来与其他DAG链的兼容 // 4. 如需使用,必须明确区分"DAG数据结构"和"DAG共识机制" use crate::types::Hash; use serde::{Deserialize, Serialize}; use std::collections::{HashMap, HashSet, VecDeque}; use std::time::{SystemTime, UNIX_EPOCH}; /// DAG节点 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct DagNode { pub hash: Hash, pub parents: Vec, pub data: Vec, pub timestamp: u64, pub weight: u64, pub cumulative_weight: u64, } /// DAG图结构 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct DagGraph { nodes: HashMap, tips: HashSet, genesis_hash: Hash, } impl DagGraph { /// 创建新的DAG图 pub fn new(genesis_hash: Hash) -> Self { let mut tips = HashSet::new(); tips.insert(genesis_hash); Self { nodes: HashMap::new(), tips, genesis_hash, } } /// 添加节点到DAG pub fn add_node(&mut self, mut node: DagNode) -> Result<(), DagError> { // 验证父节点存在 for parent in &node.parents { if !self.nodes.contains_key(parent) && *parent != self.genesis_hash { return Err(DagError::ParentNotFound(*parent)); } } // 计算累积权重 node.cumulative_weight = self.calculate_cumulative_weight(&node)?; // 更新tips for parent in &node.parents { self.tips.remove(parent); } self.tips.insert(node.hash); // 添加节点 self.nodes.insert(node.hash, node); Ok(()) } /// 获取节点 pub fn get_node(&self, hash: &Hash) -> Option<&DagNode> { self.nodes.get(hash) } /// 获取所有tips pub fn get_tips(&self) -> Vec { self.tips.iter().copied().collect() } /// 选择父节点(用于新交易) /// 使用加权随机算法选择2个父节点 pub fn select_parents(&self) -> Vec { let tips: Vec<_> = self.tips.iter().copied().collect(); if tips.is_empty() { return vec![self.genesis_hash]; } if tips.len() == 1 { return tips; } // 选择权重最高的2个tips let mut sorted_tips: Vec<_> = tips.iter() .filter_map(|tip| { self.nodes.get(tip).map(|node| (*tip, node.cumulative_weight)) }) .collect(); sorted_tips.sort_by(|a, b| b.1.cmp(&a.1)); sorted_tips.iter() .take(2) .map(|(hash, _)| *hash) .collect() } /// 计算累积权重 fn calculate_cumulative_weight(&self, node: &DagNode) -> Result { let mut max_parent_weight = 0u64; for parent in &node.parents { if let Some(parent_node) = self.nodes.get(parent) { max_parent_weight = max_parent_weight.max(parent_node.cumulative_weight); } else if *parent == self.genesis_hash { max_parent_weight = 0; } else { return Err(DagError::ParentNotFound(*parent)); } } Ok(max_parent_weight + node.weight) } /// 拓扑排序(用于交易排序) pub fn topological_sort(&self) -> Vec { let mut sorted = Vec::new(); let mut visited = HashSet::new(); let mut in_degree: HashMap = HashMap::new(); // 计算入度 for (hash, node) in &self.nodes { in_degree.entry(*hash).or_insert(0); for parent in &node.parents { if self.nodes.contains_key(parent) { *in_degree.entry(*parent).or_insert(0) += 1; } } } // 找到所有入度为0的节点 let mut queue: VecDeque = in_degree.iter() .filter(|(_, °ree)| degree == 0) .map(|(hash, _)| *hash) .collect(); // BFS遍历 while let Some(hash) = queue.pop_front() { if visited.contains(&hash) { continue; } visited.insert(hash); sorted.push(hash); if let Some(node) = self.nodes.get(&hash) { for parent in &node.parents { if let Some(degree) = in_degree.get_mut(parent) { *degree -= 1; if *degree == 0 { queue.push_back(*parent); } } } } } sorted } /// 验证DAG一致性 pub fn validate(&self) -> Result<(), DagError> { for (hash, node) in &self.nodes { // 验证哈希 if *hash != node.hash { return Err(DagError::HashMismatch(*hash, node.hash)); } // 验证父节点存在 for parent in &node.parents { if !self.nodes.contains_key(parent) && *parent != self.genesis_hash { return Err(DagError::ParentNotFound(*parent)); } } // 验证时间戳单调性 for parent in &node.parents { if let Some(parent_node) = self.nodes.get(parent) { if node.timestamp < parent_node.timestamp { return Err(DagError::TimestampNotMonotonic(*hash)); } } } } Ok(()) } /// 检查最终性(基于累积权重) /// 如果一个节点的累积权重超过阈值,则认为已达到最终性 pub fn check_finality(&self, hash: &Hash, threshold: u64) -> bool { if let Some(node) = self.nodes.get(hash) { node.cumulative_weight >= threshold } else { false } } /// 获取确认的交易(已达到最终性的交易) pub fn get_confirmed_transactions(&self, threshold: u64) -> Vec { self.nodes.iter() .filter(|(_, node)| node.cumulative_weight >= threshold) .map(|(hash, _)| *hash) .collect() } /// 并发验证多个节点 pub fn concurrent_validate(&self, nodes: &[DagNode]) -> Vec> { nodes.iter() .map(|node| self.validate_node(node)) .collect() } /// 验证单个节点 fn validate_node(&self, node: &DagNode) -> Result<(), DagError> { // 验证父节点存在 for parent in &node.parents { if !self.nodes.contains_key(parent) && *parent != self.genesis_hash { return Err(DagError::ParentNotFound(*parent)); } } // 验证时间戳 let current_time = SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap() .as_secs(); if node.timestamp > current_time + 60 { return Err(DagError::FutureTimestamp(node.hash)); } // 验证父节点时间戳单调性 for parent in &node.parents { if let Some(parent_node) = self.nodes.get(parent) { if node.timestamp < parent_node.timestamp { return Err(DagError::TimestampNotMonotonic(node.hash)); } } } Ok(()) } /// 获取节点数量 pub fn node_count(&self) -> usize { self.nodes.len() } /// 获取tips数量 pub fn tips_count(&self) -> usize { self.tips.len() } /// 获取节点的所有祖先 pub fn get_ancestors(&self, hash: &Hash) -> HashSet { let mut ancestors = HashSet::new(); let mut queue = VecDeque::new(); queue.push_back(*hash); while let Some(current) = queue.pop_front() { if ancestors.contains(¤t) { continue; } ancestors.insert(current); if let Some(node) = self.nodes.get(¤t) { for parent in &node.parents { queue.push_back(*parent); } } } ancestors } /// 检查两个节点是否有冲突(双花检测) pub fn has_conflict(&self, hash1: &Hash, hash2: &Hash) -> bool { let ancestors1 = self.get_ancestors(hash1); let ancestors2 = self.get_ancestors(hash2); // 如果两个节点的祖先集合不相交,则可能存在冲突 ancestors1.is_disjoint(&ancestors2) } } impl Default for DagGraph { fn default() -> Self { Self::new(Hash::sha3_384(b"genesis")) } } /// DAG错误类型 #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum DagError { ParentNotFound(Hash), HashMismatch(Hash, Hash), TimestampNotMonotonic(Hash), FutureTimestamp(Hash), } impl std::fmt::Display for DagError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { DagError::ParentNotFound(hash) => write!(f, "Parent not found: {:?}", hash), DagError::HashMismatch(expected, actual) => { write!(f, "Hash mismatch: expected {:?}, got {:?}", expected, actual) } DagError::TimestampNotMonotonic(hash) => { write!(f, "Timestamp not monotonic for node: {:?}", hash) } DagError::FutureTimestamp(hash) => { write!(f, "Future timestamp for node: {:?}", hash) } } } } impl std::error::Error for DagError {} #[cfg(test)] mod tests { use super::*; fn create_test_node(data: &[u8], parents: Vec, weight: u64) -> DagNode { DagNode { hash: Hash::sha3_384(data), parents, data: data.to_vec(), timestamp: SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap() .as_secs(), weight, cumulative_weight: 0, } } #[test] fn test_dag_creation() { let genesis_hash = Hash::sha3_384(b"genesis"); let dag = DagGraph::new(genesis_hash); assert_eq!(dag.node_count(), 0); assert_eq!(dag.tips_count(), 1); } #[test] fn test_add_node() { let genesis_hash = Hash::sha3_384(b"genesis"); let mut dag = DagGraph::new(genesis_hash); let node1 = create_test_node(b"test1", vec![genesis_hash], 1); assert!(dag.add_node(node1.clone()).is_ok()); assert_eq!(dag.node_count(), 1); assert!(dag.get_node(&node1.hash).is_some()); } #[test] fn test_select_parents() { let genesis_hash = Hash::sha3_384(b"genesis"); let mut dag = DagGraph::new(genesis_hash); let node1 = create_test_node(b"test1", vec![genesis_hash], 1); dag.add_node(node1.clone()).unwrap(); let parents = dag.select_parents(); assert!(!parents.is_empty()); assert!(parents.contains(&node1.hash)); } #[test] fn test_topological_sort() { let genesis_hash = Hash::sha3_384(b"genesis"); let mut dag = DagGraph::new(genesis_hash); let node1 = create_test_node(b"test1", vec![genesis_hash], 1); let node1_hash = node1.hash; dag.add_node(node1).unwrap(); let node2 = create_test_node(b"test2", vec![node1_hash], 1); dag.add_node(node2).unwrap(); let sorted = dag.topological_sort(); assert_eq!(sorted.len(), 2); } #[test] fn test_validate() { let genesis_hash = Hash::sha3_384(b"genesis"); let mut dag = DagGraph::new(genesis_hash); let node1 = create_test_node(b"test1", vec![genesis_hash], 1); dag.add_node(node1).unwrap(); assert!(dag.validate().is_ok()); } #[test] fn test_finality() { let genesis_hash = Hash::sha3_384(b"genesis"); let mut dag = DagGraph::new(genesis_hash); let node1 = create_test_node(b"test1", vec![genesis_hash], 100); let node1_hash = node1.hash; dag.add_node(node1).unwrap(); assert!(dag.check_finality(&node1_hash, 50)); assert!(!dag.check_finality(&node1_hash, 200)); } #[test] fn test_concurrent_validate() { let genesis_hash = Hash::sha3_384(b"genesis"); let dag = DagGraph::new(genesis_hash); let nodes = vec![ create_test_node(b"test1", vec![genesis_hash], 1), create_test_node(b"test2", vec![genesis_hash], 1), ]; let results = dag.concurrent_validate(&nodes); assert_eq!(results.len(), 2); assert!(results.iter().all(|r| r.is_ok())); } #[test] fn test_get_ancestors() { let genesis_hash = Hash::sha3_384(b"genesis"); let mut dag = DagGraph::new(genesis_hash); let node1 = create_test_node(b"test1", vec![genesis_hash], 1); let node1_hash = node1.hash; dag.add_node(node1).unwrap(); let node2 = create_test_node(b"test2", vec![node1_hash], 1); let node2_hash = node2.hash; dag.add_node(node2).unwrap(); let ancestors = dag.get_ancestors(&node2_hash); assert!(ancestors.contains(&node2_hash)); assert!(ancestors.contains(&node1_hash)); } #[test] fn test_has_conflict() { let genesis_hash = Hash::sha3_384(b"genesis"); let mut dag = DagGraph::new(genesis_hash); let node1 = create_test_node(b"test1", vec![genesis_hash], 1); let node1_hash = node1.hash; dag.add_node(node1).unwrap(); let node2 = create_test_node(b"test2", vec![genesis_hash], 1); let node2_hash = node2.hash; dag.add_node(node2).unwrap(); // 两个节点都引用genesis,应该没有冲突 assert!(!dag.has_conflict(&node1_hash, &node2_hash)); } #[test] fn test_cumulative_weight() { let genesis_hash = Hash::sha3_384(b"genesis"); let mut dag = DagGraph::new(genesis_hash); let node1 = create_test_node(b"test1", vec![genesis_hash], 10); let node1_hash = node1.hash; dag.add_node(node1).unwrap(); let node2 = create_test_node(b"test2", vec![node1_hash], 5); let node2_hash = node2.hash; dag.add_node(node2).unwrap(); let node2_data = dag.get_node(&node2_hash).unwrap(); assert_eq!(node2_data.cumulative_weight, 15); // 10 + 5 } }