qudag_dag/
node.rs

1use blake3::Hash;
2use serde::{Deserialize, Serialize};
3use std::time::SystemTime;
4
5/// Serializable wrapper for blake3::Hash
6#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
7pub struct SerializableHash(pub [u8; 32]);
8
9impl From<Hash> for SerializableHash {
10    fn from(hash: Hash) -> Self {
11        SerializableHash(*hash.as_bytes())
12    }
13}
14
15impl From<SerializableHash> for Hash {
16    fn from(hash: SerializableHash) -> Self {
17        Hash::from(hash.0)
18    }
19}
20
21/// Represents the state of a node in the DAG
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
23pub enum NodeState {
24    /// Node has been created but not yet verified
25    Pending,
26    /// Node has been verified and is part of the DAG
27    Verified,
28    /// Node has achieved finality through consensus
29    Final,
30    /// Node has been rejected by consensus
31    Rejected,
32}
33
34/// A node in the DAG containing a transaction or consensus message
35///
36/// # Examples
37///
38/// ```rust
39/// use qudag_dag::{Node, NodeState};
40///
41/// // Create a new node with payload and no parents (genesis node)
42/// let payload = b"Hello, DAG!".to_vec();
43/// let node = Node::new(payload.clone(), vec![]);
44///
45/// assert_eq!(node.payload(), &payload);
46/// assert_eq!(node.state(), NodeState::Pending);
47/// assert!(node.parents().is_empty());
48///
49/// // Hash is computed deterministically
50/// let hash = node.hash();
51/// assert_eq!(hash.as_bytes().len(), 32);
52/// ```
53#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct Node {
55    /// Unique identifier hash for this node
56    hash: SerializableHash,
57    /// Payload contained in this node
58    payload: Vec<u8>,
59    /// Current state of this node
60    state: NodeState,
61    /// Timestamp when node was created
62    timestamp: SystemTime,
63    /// Parent node hashes
64    parents: Vec<SerializableHash>,
65}
66
67impl Node {
68    /// Creates a new node with the given payload and parents
69    ///
70    /// # Examples
71    ///
72    /// ```rust
73    /// use qudag_dag::Node;
74    ///
75    /// // Create a genesis node (no parents)
76    /// let payload = b"Genesis block".to_vec();
77    /// let node = Node::new(payload, vec![]);
78    ///
79    /// // Create a child node
80    /// let parent_hash = node.hash();
81    /// let child_payload = b"Child block".to_vec();
82    /// let child_node = Node::new(child_payload, vec![parent_hash]);
83    /// ```
84    pub fn new(payload: Vec<u8>, parents: Vec<Hash>) -> Self {
85        let timestamp = SystemTime::now();
86        let mut hasher = blake3::Hasher::new();
87        hasher.update(&payload);
88        for parent in &parents {
89            hasher.update(parent.as_bytes());
90        }
91        let hash = hasher.finalize();
92
93        Self {
94            hash: hash.into(),
95            payload,
96            state: NodeState::Pending,
97            timestamp,
98            parents: parents.into_iter().map(|h| h.into()).collect(),
99        }
100    }
101
102    /// Returns the node's unique hash
103    pub fn hash(&self) -> Hash {
104        self.hash.clone().into()
105    }
106
107    /// Returns reference to node's payload
108    pub fn payload(&self) -> &[u8] {
109        &self.payload
110    }
111
112    /// Returns current state of the node
113    pub fn state(&self) -> NodeState {
114        self.state
115    }
116
117    /// Returns reference to parent hashes (converted)
118    pub fn parents(&self) -> Vec<Hash> {
119        self.parents.iter().map(|h| h.clone().into()).collect()
120    }
121
122    /// Updates node state if transition is valid
123    pub fn update_state(&mut self, new_state: NodeState) -> crate::Result<()> {
124        match (self.state, new_state) {
125            // Valid transitions
126            (NodeState::Pending, NodeState::Verified)
127            | (NodeState::Verified, NodeState::Final)
128            | (NodeState::Pending, NodeState::Rejected)
129            | (NodeState::Verified, NodeState::Rejected) => {
130                self.state = new_state;
131                Ok(())
132            }
133            // Invalid transitions
134            _ => Err(crate::DagError::InvalidStateTransition(format!(
135                "{:?} -> {:?}",
136                self.state, new_state
137            ))),
138        }
139    }
140}
141
142#[cfg(test)]
143mod tests {
144    use super::*;
145
146    #[test]
147    fn test_node_creation() {
148        let payload = vec![1, 2, 3];
149        let parents = vec![blake3::hash(b"parent1"), blake3::hash(b"parent2")];
150        let node = Node::new(payload.clone(), parents.clone());
151
152        assert_eq!(node.state(), NodeState::Pending);
153        assert_eq!(node.payload(), &payload);
154        assert_eq!(node.parents(), &parents);
155    }
156
157    #[test]
158    fn test_valid_state_transitions() {
159        let mut node = Node::new(vec![1, 2, 3], vec![]);
160
161        // Pending -> Verified
162        assert!(node.update_state(NodeState::Verified).is_ok());
163        assert_eq!(node.state(), NodeState::Verified);
164
165        // Verified -> Final
166        assert!(node.update_state(NodeState::Final).is_ok());
167        assert_eq!(node.state(), NodeState::Final);
168    }
169
170    #[test]
171    fn test_invalid_state_transitions() {
172        let mut node = Node::new(vec![1, 2, 3], vec![]);
173
174        // Can't go from Pending to Final
175        assert!(node.update_state(NodeState::Final).is_err());
176
177        // Update to Verified
178        assert!(node.update_state(NodeState::Verified).is_ok());
179
180        // Can't go back to Pending
181        assert!(node.update_state(NodeState::Pending).is_err());
182    }
183}