irkle/
lib.rs

1//! A [blake3](https://en.wikipedia.org/wiki/BLAKE_(hash_function)#BLAKE3)-based
2//! merkle (hash) tree implementation for superfast trees ⚡
3//!
4//! # Example
5//!
6//! ```rust
7//! use irkle::Tree;
8//!
9//! fn main() {
10//!     println!("{:#?}", Tree::new(vec!["hello", "there"]));
11//! }
12//! ```
13//!
14//! # Installation
15//!
16//! Simply add the following to your `Cargo.toml` file:
17//!
18//! ```toml
19//! [depedencies]
20//! irkle = "0.1"
21//! ```
22
23use blake3::{self, Hash};
24use std::rc::Rc;
25
26/// Trait for running methods on any abstract kind of node, such as hash verification
27/// or just getting the hash
28pub trait NodeMethod<T: AsRef<[u8]>> {
29    /// Gets the [blake3]-based [Hash] for trait implementation, just call on any
30    /// [Node], [Data] or [NodeType] like so: `item.get_hash()`. Typically all
31    /// this method will do is get the `self.hash` but this can be used to adapt
32    /// a broader [NodeType]
33    fn get_hash(&self) -> Hash;
34
35    /// Verifies the node down through recursion, providing a high-level
36    /// checking/verification method
37    ///
38    /// If this fails, it will return the expected hash and the found hash where
39    /// this hash failed at; this is formatted as `(expected_hash, found_node)`
40    fn verify(&self) -> Result<(), (Hash, Hash)>;
41}
42
43/// A merkle tree
44///
45/// # Example
46///
47/// ```rs
48/// use irkle::Tree;
49///
50/// fn main() {
51///     println!("{:#?}", Tree::new(vec!["hello", "there"]));
52/// }
53/// ```
54#[derive(Debug, Clone, PartialEq)]
55pub struct Tree<T: AsRef<[u8]>> {
56    /// Type of node contained inside the tree or represents an empty tree
57    pub inner: NodeType<T>,
58}
59
60impl<T: AsRef<[u8]>> Tree<T> {
61    /// Creates a new [Tree] based off of data supplied in `data`
62    pub fn new<D: IntoIterator<Item = T>>(datapoints: D) -> Self {
63        let mut data_nodes: Vec<Data<T>> = datapoints.into_iter().map(|d| Data::new(d)).collect();
64
65        match data_nodes.len() {
66            0 => panic!("Tree was given no datapoints and a merkle tree cannot be empty!"),
67            1 => Self {
68                inner: NodeType::Data(data_nodes.remove(0)),
69            },
70            _ => {
71                /// Makes all levels of new nodes recursively from given
72                /// originating [NodeType]s
73                fn generate_nodes<T: AsRef<[u8]>, N: Into<NodeType<T>>>(
74                    node_types: Vec<N>,
75                ) -> NodeType<T> {
76                    let mut output: Vec<NodeType<T>> = vec![];
77                    let mut left_buf: Option<NodeType<T>> = None;
78
79                    for node_type in node_types {
80                        match left_buf {
81                            Some(_) => output
82                                .push(Node::new(left_buf.take().unwrap(), node_type.into()).into()),
83                            None => left_buf = Some(node_type.into()),
84                        }
85                    }
86
87                    output.extend(left_buf);
88
89                    if output.len() == 1 {
90                        output.remove(0)
91                    } else {
92                        generate_nodes(output)
93                    }
94                }
95
96                Self {
97                    inner: generate_nodes(data_nodes),
98                }
99            }
100        }
101    }
102}
103
104impl<T: AsRef<[u8]>> NodeMethod<T> for Tree<T> {
105    fn get_hash(&self) -> Hash {
106        match &self.inner {
107            NodeType::Node(node) => node.hash,
108            NodeType::Data(node) => node.hash,
109        }
110    }
111
112    fn verify(&self) -> Result<(), (Hash, Hash)> {
113        self.inner.verify()
114    }
115}
116
117/// A middle-layer node, containing two nodes underneith that is of some [NodeType]
118/// variation
119#[derive(Debug, Clone, PartialEq)]
120pub struct Node<T: AsRef<[u8]>> {
121    pub hash: Hash,
122    pub left: Rc<NodeType<T>>,
123    pub right: Rc<NodeType<T>>,
124}
125
126impl<T: AsRef<[u8]>> Node<T> {
127    /// Creates a new [Node] from nodes below
128    pub fn new<N: Into<NodeType<T>>>(left: N, right: N) -> Self {
129        let left_into = left.into();
130        let right_into = right.into();
131
132        Self {
133            hash: hash_lr(&left_into, &right_into),
134            left: Rc::new(left_into),
135            right: Rc::new(right_into),
136        }
137    }
138}
139
140impl<T: AsRef<[u8]>> NodeMethod<T> for Node<T> {
141    fn get_hash(&self) -> Hash {
142        self.hash
143    }
144
145    fn verify(&self) -> Result<(), (Hash, Hash)> {
146        self.left.verify()?;
147        self.right.verify()?;
148
149        let found_hash = hash_lr(&self.left, &self.right);
150
151        if self.hash == found_hash {
152            Ok(())
153        } else {
154            Err((found_hash, self.hash))
155        }
156    }
157}
158
159/// The final datablock, containing the data needed
160#[derive(Debug, Clone, PartialEq)]
161pub struct Data<T: AsRef<[u8]>> {
162    pub hash: Hash,
163    pub data: T,
164}
165
166impl<T: AsRef<[u8]>> Data<T> {
167    /// Creates a new [Data] from given `data`
168    pub fn new<D: Into<T>>(data: D) -> Self {
169        let data_into = data.into();
170
171        Self {
172            hash: blake3::hash(data_into.as_ref()),
173            data: data_into.into(),
174        }
175    }
176}
177
178impl<T: AsRef<[u8]>> NodeMethod<T> for Data<T> {
179    fn get_hash(&self) -> Hash {
180        self.hash
181    }
182
183    fn verify(&self) -> Result<(), (Hash, Hash)> {
184        let found_hash = blake3::hash(self.data.as_ref());
185
186        if self.hash == found_hash {
187            Ok(())
188        } else {
189            Err((found_hash, self.hash))
190        }
191    }
192}
193
194/// Types of node that may be children
195#[derive(Debug, Clone, PartialEq)]
196pub enum NodeType<T: AsRef<[u8]>> {
197    Node(Node<T>),
198    Data(Data<T>),
199}
200
201impl<T: AsRef<[u8]>> NodeMethod<T> for NodeType<T> {
202    fn get_hash(&self) -> Hash {
203        match self {
204            NodeType::Node(inner) => inner.hash,
205            NodeType::Data(inner) => inner.hash,
206        }
207    }
208
209    fn verify(&self) -> Result<(), (Hash, Hash)> {
210        match self {
211            NodeType::Node(inner) => inner.verify(),
212            NodeType::Data(inner) => inner.verify(),
213        }
214    }
215}
216
217impl<T: AsRef<[u8]>> From<T> for NodeType<T> {
218    /// Similar to the `impl<T: AsRef<[u8]>> From<Data<T>> for NodeType<T>` impl
219    /// for [NodeType] but assumes raw input can also be a [Data]
220    fn from(data: T) -> Self {
221        NodeType::Data(Data::new(data))
222    }
223}
224
225impl<T: AsRef<[u8]>> From<Data<T>> for NodeType<T> {
226    fn from(data: Data<T>) -> Self {
227        NodeType::Data(data)
228    }
229}
230
231impl<T: AsRef<[u8]>> From<Node<T>> for NodeType<T> {
232    fn from(node: Node<T>) -> Self {
233        NodeType::Node(node)
234    }
235}
236
237/// Hashes left and right sides of a [NodeType], used for middle [Node]s
238fn hash_lr<T: AsRef<[u8]>>(left: &NodeType<T>, right: &NodeType<T>) -> Hash {
239    let mut hasher = blake3::Hasher::new();
240
241    hasher.update(left.get_hash().as_bytes());
242    hasher.update(right.get_hash().as_bytes());
243
244    hasher.finalize()
245}
246
247#[cfg(test)]
248mod tests {
249    use super::*;
250
251    const TEST_DATA: &str = "hello";
252
253    #[test]
254    fn hash_lr_check() {
255        let data: Data<&str> = Data::new(TEST_DATA);
256        let expected = blake3::hash(
257            &[
258                &data.get_hash().as_bytes()[..],
259                &data.get_hash().as_bytes()[..],
260            ]
261            .concat(),
262        );
263
264        assert_eq!(
265            hash_lr(&NodeType::from(data.clone()), &NodeType::from(data)),
266            expected
267        )
268    }
269
270    #[test]
271    fn tree_new_two() {
272        assert_eq!(
273            Tree::new(vec!["left one", "right one"]),
274            Tree {
275                inner: NodeType::Node(Node::new(Data::new("left one"), Data::new("right one")))
276            }
277        )
278    }
279
280    #[test]
281    fn tree_new_odd() {
282        let left = NodeType::Node(Node::new(Data::new("this"), Data::new("is")));
283        let right = NodeType::Data(Data::new("odd"));
284
285        assert_eq!(
286            Tree::new(vec!["this", "is", "odd"]),
287            Tree {
288                inner: NodeType::Node(Node::new(left, right))
289            }
290        )
291    }
292
293    #[test]
294    fn tree_new_four() {
295        let bottom_left: Node<&str> = Node::new("hello", "there");
296        let bottom_right: Node<&str> = Node::new("cool", "person");
297
298        let hash = blake3::hash(
299            &[
300                &bottom_left.hash.as_bytes()[..],
301                &bottom_right.hash.as_bytes()[..],
302            ]
303            .concat(),
304        );
305
306        let node = NodeType::Node(Node {
307            hash,
308            left: Rc::new(NodeType::Node(bottom_left)),
309            right: Rc::new(NodeType::Node(bottom_right)),
310        });
311
312        assert_eq!(
313            Tree::new(vec!["hello", "there", "cool", "person"]),
314            Tree { inner: node }
315        )
316    }
317
318    #[test]
319    fn node_to_node_type() {
320        let inner: Node<&str> = Node::new("", "").into();
321        assert_eq!(NodeType::from(inner.clone()), NodeType::Node(inner))
322    }
323
324    #[test]
325    fn data_to_node_type() {
326        let inner: Data<&str> = Data::new("");
327        assert_eq!(NodeType::from(inner.clone()), NodeType::Data(inner))
328    }
329
330    #[test]
331    fn node_get_hash() {
332        let node: Node<&str> = Node::new(TEST_DATA, TEST_DATA);
333
334        assert_eq!(
335            node.get_hash(),
336            blake3::hash(
337                &[
338                    &blake3::hash(TEST_DATA.as_bytes()).as_bytes()[..],
339                    &blake3::hash(TEST_DATA.as_bytes()).as_bytes()[..]
340                ]
341                .concat()
342            )
343        );
344    }
345
346    #[test]
347    fn data_get_hash() {
348        let data: Data<&str> = Data::new(TEST_DATA);
349        assert_eq!(data.get_hash(), blake3::hash(TEST_DATA.as_bytes()));
350    }
351
352    #[test]
353    #[should_panic]
354    fn empty_tree() {
355        let strings: Vec<String> = vec![];
356        Tree::new(strings);
357    }
358
359    #[test]
360    fn data_verification() {
361        let mut test_struct: Data<&str> = Data::new(TEST_DATA);
362        assert!(test_struct.verify().is_ok());
363
364        test_struct.hash = blake3::hash(b"fknrejnfjrenf");
365        assert!(test_struct.verify().is_err());
366    }
367
368    // TODO: more verification tests
369}