use blake3::Hash;
use serde::{Deserialize, Serialize};
use std::time::SystemTime;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct SerializableHash(pub [u8; 32]);
impl From<Hash> for SerializableHash {
fn from(hash: Hash) -> Self {
SerializableHash(*hash.as_bytes())
}
}
impl From<SerializableHash> for Hash {
fn from(hash: SerializableHash) -> Self {
Hash::from(hash.0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum NodeState {
Pending,
Verified,
Final,
Rejected,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Node {
hash: SerializableHash,
payload: Vec<u8>,
state: NodeState,
timestamp: SystemTime,
parents: Vec<SerializableHash>,
}
impl Node {
pub fn new(payload: Vec<u8>, parents: Vec<Hash>) -> Self {
let timestamp = SystemTime::now();
let mut hasher = blake3::Hasher::new();
hasher.update(&payload);
for parent in &parents {
hasher.update(parent.as_bytes());
}
let hash = hasher.finalize();
Self {
hash: hash.into(),
payload,
state: NodeState::Pending,
timestamp,
parents: parents.into_iter().map(|h| h.into()).collect(),
}
}
pub fn hash(&self) -> Hash {
self.hash.clone().into()
}
pub fn payload(&self) -> &[u8] {
&self.payload
}
pub fn state(&self) -> NodeState {
self.state
}
pub fn parents(&self) -> Vec<Hash> {
self.parents.iter().map(|h| h.clone().into()).collect()
}
pub fn update_state(&mut self, new_state: NodeState) -> crate::Result<()> {
match (self.state, new_state) {
(NodeState::Pending, NodeState::Verified)
| (NodeState::Verified, NodeState::Final)
| (NodeState::Pending, NodeState::Rejected)
| (NodeState::Verified, NodeState::Rejected) => {
self.state = new_state;
Ok(())
}
_ => Err(crate::DagError::InvalidStateTransition(format!(
"{:?} -> {:?}",
self.state, new_state
))),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_node_creation() {
let payload = vec![1, 2, 3];
let parents = vec![blake3::hash(b"parent1"), blake3::hash(b"parent2")];
let node = Node::new(payload.clone(), parents.clone());
assert_eq!(node.state(), NodeState::Pending);
assert_eq!(node.payload(), &payload);
assert_eq!(node.parents(), &parents);
}
#[test]
fn test_valid_state_transitions() {
let mut node = Node::new(vec![1, 2, 3], vec![]);
assert!(node.update_state(NodeState::Verified).is_ok());
assert_eq!(node.state(), NodeState::Verified);
assert!(node.update_state(NodeState::Final).is_ok());
assert_eq!(node.state(), NodeState::Final);
}
#[test]
fn test_invalid_state_transitions() {
let mut node = Node::new(vec![1, 2, 3], vec![]);
assert!(node.update_state(NodeState::Final).is_err());
assert!(node.update_state(NodeState::Verified).is_ok());
assert!(node.update_state(NodeState::Pending).is_err());
}
}