NAC_Blockchain/nvm_v2/nvm-l0/src/dag.rs

485 lines
15 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.

// 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<Hash>,
pub data: Vec<u8>,
pub timestamp: u64,
pub weight: u64,
pub cumulative_weight: u64,
}
/// DAG图结构
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DagGraph {
nodes: HashMap<Hash, DagNode>,
tips: HashSet<Hash>,
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<Hash> {
self.tips.iter().copied().collect()
}
/// 选择父节点(用于新交易)
/// 使用加权随机算法选择2个父节点
pub fn select_parents(&self) -> Vec<Hash> {
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<u64, DagError> {
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<Hash> {
let mut sorted = Vec::new();
let mut visited = HashSet::new();
let mut in_degree: HashMap<Hash, usize> = 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<Hash> = in_degree.iter()
.filter(|(_, &degree)| 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<Hash> {
self.nodes.iter()
.filter(|(_, node)| node.cumulative_weight >= threshold)
.map(|(hash, _)| *hash)
.collect()
}
/// 并发验证多个节点
pub fn concurrent_validate(&self, nodes: &[DagNode]) -> Vec<Result<(), DagError>> {
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<Hash> {
let mut ancestors = HashSet::new();
let mut queue = VecDeque::new();
queue.push_back(*hash);
while let Some(current) = queue.pop_front() {
if ancestors.contains(&current) {
continue;
}
ancestors.insert(current);
if let Some(node) = self.nodes.get(&current) {
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<Hash>, 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
}
}