├── .gitignore ├── Cargo.toml ├── Readme.md └── src └── lib.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | 3 | name = "merkle" 4 | version = "0.0.1" 5 | authors = ["Daniel Fagnan "] 6 | 7 | [dependencies.rust-crypto] 8 | git = "https://github.com/DaGenix/rust-crypto" 9 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Merkle 2 | 3 | A [merkle tree](http://en.wikipedia.org/wiki/Merkle_tree) implementation in Rust. This library is still fairly early. 4 | 5 | 6 | ## Getting Started 7 | 8 | Get it using Cargo! 9 | 10 | ```toml 11 | # Cargo.toml 12 | [dependencies.merkle] 13 | git = "https://github.com/thehydroimpulse/merkle.git" 14 | ``` 15 | 16 | Now let's link the crate: 17 | 18 | ```rust 19 | // src/lib.rs 20 | extern crate merkle; 21 | 22 | use merkle::{MerkleTree, Node}; 23 | ``` 24 | 25 | ## Introduction 26 | 27 | A merkle tree is a unique type a tree that's used in [Bitcoin](https://en.bitcoin.it/wiki/Protocol_specification#Merkle_Trees), [Cassandra](http://distributeddatastore.blogspot.ca/2013/07/cassandra-using-merkle-trees-to-detect.html), Apache Wave, ZFS, and [Adobe Brackets](http://brackets.io/) just to name a few. 28 | 29 | Merkle trees are extremely useful to validate for corruptness, differences, etc... Bitcoin uses it to validate transactions, Cassandra uses it to determine if replicas are corrupt, and Brackets uses it in their virtual DOM system to try and find the minimal possible updates the DOM needs to achieve a final result. Comparing two versions of a virtual DOM tree (and their merkle trees) can easily lead to a list of the most atomic changes and how to go about it most efficiently. 30 | 31 | ## Creating a Node 32 | 33 | Creating a node is extremely easy. In the current variation, any node can contain data, not just the leaf nodes. In this case, we start with the root node and start pushing children onto it. 34 | 35 | ```rust 36 | let mut root = Node::new("foobar"); 37 | root.push_child(Node::new("another_child")); 38 | ``` 39 | 40 | ## Creating a Merkle Tree 41 | 42 | Now we can create a merkle tree given a root node: 43 | 44 | ```rust 45 | let mut merkle = MerkleTree::new(root); 46 | ``` 47 | 48 | ## Hashing The Tree 49 | 50 | The final step is to hash the tree to get a merkle root or root hash. 51 | 52 | ```rust 53 | merkle.hash(); 54 | merkle.root() // &str - containing the root hash 55 | ``` 56 | 57 | # License 58 | 59 | The MIT License (MIT) 60 | 61 | Copyright (c) 2014 Daniel Fagnan 62 | 63 | Permission is hereby granted, free of charge, to any person obtaining a copy 64 | of this software and associated documentation files (the "Software"), to deal 65 | in the Software without restriction, including without limitation the rights 66 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 67 | copies of the Software, and to permit persons to whom the Software is 68 | furnished to do so, subject to the following conditions: 69 | 70 | The above copyright notice and this permission notice shall be included in 71 | all copies or substantial portions of the Software. 72 | 73 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 74 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 75 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 76 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 77 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 78 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 79 | THE SOFTWARE. 80 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate "rust-crypto" as crypto; 2 | 3 | use crypto::sha2::Sha256; 4 | use crypto::digest::Digest; 5 | use std::slice::raw; 6 | use std::mem; 7 | use std::fmt; 8 | 9 | trait Hash { 10 | fn hash<'a>(&'a self) -> &'a [u8]; 11 | } 12 | 13 | impl Hash for String { 14 | fn hash<'a>(&'a self) -> &'a [u8] { 15 | self.as_slice().as_bytes() 16 | } 17 | } 18 | 19 | impl<'a> Hash for &'a str { 20 | fn hash<'a>(&'a self) -> &'a [u8] { 21 | self.as_bytes() 22 | } 23 | } 24 | 25 | fn hash(input: T) -> String { 26 | let mut hash = Sha256::new(); 27 | hash.input(input.hash()); 28 | hash.result_str() 29 | } 30 | 31 | #[deriving(Show)] 32 | pub struct MerkleTree { 33 | hash: String, 34 | root: Node 35 | } 36 | 37 | impl MerkleTree 38 | where T: Hash, T: fmt::Show { 39 | pub fn new(root: Node) -> MerkleTree { 40 | MerkleTree { 41 | hash: String::new(), 42 | root: root 43 | } 44 | } 45 | 46 | pub fn hash(&mut self) { 47 | self.root.hash(); 48 | if self.root.children.len() == 0 { 49 | self.hash = self.root.value_hash.clone(); 50 | } else { 51 | self.hash = self.root.combined_hash.clone(); 52 | } 53 | } 54 | 55 | pub fn root<'a>(&'a self) -> &'a str { 56 | self.hash.as_slice() 57 | } 58 | } 59 | 60 | #[deriving(Show)] 61 | pub struct Node { 62 | value_hash: String, 63 | combined_hash: String, 64 | children: Vec> 65 | } 66 | 67 | impl Node 68 | where T: Hash, T: fmt::Show { 69 | pub fn new(value: T) -> Node { 70 | Node { 71 | value_hash: hash(value), 72 | combined_hash: String::new(), 73 | children: Vec::new() 74 | } 75 | } 76 | 77 | pub fn hash(&mut self) { 78 | let mut combined = String::new(); 79 | for child in self.children.iter_mut() { 80 | child.hash(); 81 | 82 | if child.children.len() == 0 { 83 | combined = combined + child.value_hash; 84 | } else { 85 | combined = combined + child.combined_hash; 86 | } 87 | } 88 | 89 | if self.children.len() > 0 { 90 | self.combined_hash = hash(self.value_hash + combined); 91 | } 92 | } 93 | 94 | pub fn push_child(&mut self, child: Node) { 95 | self.children.push(child); 96 | } 97 | } 98 | 99 | #[cfg(test)] 100 | mod test { 101 | use super::{MerkleTree, Node}; 102 | 103 | #[test] 104 | fn new_root_node() { 105 | let root = Node::new(""); 106 | let mut merkle = MerkleTree::new(root); 107 | merkle.hash(); 108 | assert_eq!(merkle.root(), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855") 109 | } 110 | 111 | #[test] 112 | fn one_child() { 113 | let mut root = Node::new(""); 114 | root.push_child(Node::new("")); 115 | let mut merkle = MerkleTree::new(root); 116 | merkle.hash(); 117 | assert_eq!(merkle.root(), "3b7546ed79e3e5a7907381b093c5a182cbf364c5dd0443dfa956c8cca271cc33"); 118 | assert_eq!(merkle.root.children[0].value_hash.as_slice(), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); 119 | } 120 | } 121 | --------------------------------------------------------------------------------