diff --git a/benches/lib.rs b/benches/lib.rs index 172a185..61ef5c9 100644 --- a/benches/lib.rs +++ b/benches/lib.rs @@ -22,41 +22,38 @@ static digest: &'static Algorithm = &SHA512; fn bench_small_str_tree(b: &mut Bencher) { let values = vec!["one", "two", "three", "four"]; - b.iter(|| { - MerkleTree::from_vec(digest, values.clone()) - }); + b.iter(|| MerkleTree::from_vec(digest, values.clone())); } #[bench] fn bench_small_str_proof_gen(b: &mut Bencher) { let values = vec!["one", "two", "three", "four"]; - let tree = MerkleTree::from_vec(digest, values.clone()); + let tree = MerkleTree::from_vec(digest, values.clone()); - b.iter(|| { - for value in &values { - let proof = tree.gen_proof(value); - test::black_box(proof); - } + b.iter(|| for value in &values { + let proof = tree.gen_proof(value); + test::black_box(proof); }); } #[bench] fn bench_small_str_proof_check(b: &mut Bencher) { let values = vec!["one", "two", "three", "four"]; - let tree = MerkleTree::from_vec(digest, values.clone()); - let proofs = values.iter().map(|v| tree.gen_proof(v).unwrap()).collect::>(); + let tree = MerkleTree::from_vec(digest, values.clone()); + let proofs = values + .iter() + .map(|v| tree.gen_proof(v).unwrap()) + .collect::>(); - b.iter(|| { - for proof in &proofs { - test::black_box(proof.validate(tree.root_hash())); - } + b.iter(|| for proof in &proofs { + test::black_box(proof.validate(tree.root_hash())); }); } #[bench] fn bench_big_rnd_tree(b: &mut Bencher) { let mut values = vec![vec![0u8; 256]; 160]; - let mut rng = rand::IsaacRng::new_unseeded(); + let mut rng = rand::IsaacRng::new_unseeded(); for mut v in &mut values { rng.fill_bytes(&mut v); @@ -71,7 +68,7 @@ fn bench_big_rnd_tree(b: &mut Bencher) { #[bench] fn bench_big_rnd_proof_gen(b: &mut Bencher) { let mut values = vec![vec![0u8; 256]; 160]; - let mut rng = rand::IsaacRng::new_unseeded(); + let mut rng = rand::IsaacRng::new_unseeded(); for mut v in &mut values { rng.fill_bytes(&mut v); @@ -79,39 +76,36 @@ fn bench_big_rnd_proof_gen(b: &mut Bencher) { let tree = MerkleTree::from_vec(digest, values.clone()); - b.iter(|| { - for value in &values { - let proof = tree.gen_proof(value.clone()); - test::black_box(proof); - } + b.iter(|| for value in &values { + let proof = tree.gen_proof(value.clone()); + test::black_box(proof); }); } #[bench] fn bench_big_rnd_proof_check(b: &mut Bencher) { let mut values = vec![vec![0u8; 256]; 160]; - let mut rng = rand::IsaacRng::new_unseeded(); + let mut rng = rand::IsaacRng::new_unseeded(); for mut v in &mut values { rng.fill_bytes(&mut v); } - let tree = MerkleTree::from_vec(digest, values.clone()); - let proofs = values.into_iter() + let tree = MerkleTree::from_vec(digest, values.clone()); + let proofs = values + .into_iter() .map(|v| tree.gen_proof(v).unwrap()) .collect::>(); - b.iter(|| { - for proof in &proofs { - test::black_box(proof.validate(tree.root_hash())); - } + b.iter(|| for proof in &proofs { + test::black_box(proof.validate(tree.root_hash())); }); } #[bench] fn bench_big_rnd_iter(b: &mut Bencher) { let mut values = vec![vec![0u8; 256]; 160]; - let mut rng = rand::IsaacRng::new_unseeded(); + let mut rng = rand::IsaacRng::new_unseeded(); for mut v in &mut values { rng.fill_bytes(&mut v); @@ -119,10 +113,7 @@ fn bench_big_rnd_iter(b: &mut Bencher) { let tree = MerkleTree::from_vec(digest, values.clone()); - b.iter(|| { - for value in &tree { - test::black_box(value); - } + b.iter(|| for value in &tree { + test::black_box(value); }); } - diff --git a/src/hashutils.rs b/src/hashutils.rs index c4353d0..9da95a7 100644 --- a/src/hashutils.rs +++ b/src/hashutils.rs @@ -1,5 +1,5 @@ -use ring::digest::{ Algorithm, Context, Digest, digest }; +use ring::digest::{Algorithm, Context, Digest, digest}; /// The type of values stored in a `MerkleTree` must implement /// this trait, in order for them to be able to be fed @@ -22,16 +22,13 @@ use ring::digest::{ Algorithm, Context, Digest, digest }; /// } /// ``` pub trait Hashable { - /// Update the given `context` with `self`. /// /// See `ring::digest::Context::update` for more information. fn update_context(&self, context: &mut Context); - } -impl > Hashable for T { - +impl> Hashable for T { fn update_context(&self, context: &mut Context) { context.update(self.as_ref()); } @@ -40,33 +37,41 @@ impl > Hashable for T { /// The sole purpose of this trait is to extend the standard /// `ring::algo::Algorithm` type with a couple utility functions. pub trait HashUtils { - /// Compute the hash of the empty string fn hash_empty(&'static self) -> Digest; /// Compute the hash of the given leaf - fn hash_leaf(&'static self, bytes: &T) -> Digest where T: Hashable; + fn hash_leaf(&'static self, bytes: &T) -> Digest + where + T: Hashable; /// Compute the hash of the concatenation of `left` and `right`. // XXX: This is overly generic temporarily to make refactoring easier. // TODO: Give `left` and `right` type &Digest. - fn hash_nodes(&'static self, left: &T, right: &T) -> Digest where T: Hashable; + fn hash_nodes(&'static self, left: &T, right: &T) -> Digest + where + T: Hashable; } impl HashUtils for Algorithm { - fn hash_empty(&'static self) -> Digest { digest(self, &[]) } - fn hash_leaf(&'static self, leaf: &T) -> Digest where T: Hashable { + fn hash_leaf(&'static self, leaf: &T) -> Digest + where + T: Hashable, + { let mut ctx = Context::new(self); ctx.update(&[0x00]); leaf.update_context(&mut ctx); ctx.finish() } - fn hash_nodes(&'static self, left: &T, right: &T) -> Digest where T: Hashable { + fn hash_nodes(&'static self, left: &T, right: &T) -> Digest + where + T: Hashable, + { let mut ctx = Context::new(self); ctx.update(&[0x01]); left.update_context(&mut ctx); @@ -74,4 +79,3 @@ impl HashUtils for Algorithm { ctx.finish() } } - diff --git a/src/lib.rs b/src/lib.rs index 6b30446..caad50a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,7 +23,7 @@ mod hashutils; pub use hashutils::Hashable; mod tree; -pub use tree::{ LeavesIterator, LeavesIntoIterator }; +pub use tree::{LeavesIterator, LeavesIntoIterator}; #[cfg(feature = "serialization-protobuf")] #[allow(unused_qualifications)] @@ -31,4 +31,3 @@ mod proto; #[cfg(test)] mod tests; - diff --git a/src/merkletree.rs b/src/merkletree.rs index be9d90c..684b42e 100644 --- a/src/merkletree.rs +++ b/src/merkletree.rs @@ -1,16 +1,15 @@ use ring::digest::Algorithm; -use tree::{ Tree, LeavesIterator, LeavesIntoIterator }; -use hashutils::{ Hashable, HashUtils }; +use tree::{Tree, LeavesIterator, LeavesIntoIterator}; +use hashutils::{Hashable, HashUtils}; -use proof::{ Proof, Lemma }; +use proof::{Proof, Lemma}; /// A Merkle tree is a binary tree, with values of type `T` at the leafs, /// and where every internal node holds the hash of the concatenation of the hashes of its children nodes. #[derive(Clone, Debug)] pub struct MerkleTree { - /// The hashing algorithm used by this Merkle tree pub algorithm: &'static Algorithm, @@ -21,28 +20,29 @@ pub struct MerkleTree { height: usize, /// The number of leaf nodes in the tree - count: usize + count: usize, } -impl MerkleTree { - +impl MerkleTree { /// Constructs a Merkle Tree from a vector of data blocks. /// Returns `None` if `values` is empty. pub fn from_vec(algorithm: &'static Algorithm, values: Vec) -> Self - where T: Hashable { + where + T: Hashable, + { if values.is_empty() { return MerkleTree { algorithm: algorithm, root: Tree::empty(algorithm.hash_empty()), height: 0, - count: 0 + count: 0, }; } - let count = values.len(); + let count = values.len(); let mut height = 0; - let mut cur = Vec::with_capacity(count); + let mut cur = Vec::with_capacity(count); for v in values { let leaf = Tree::new_leaf(algorithm, v); @@ -54,20 +54,16 @@ impl MerkleTree { while !cur.is_empty() { if cur.len() == 1 { next.push(cur.remove(0)); - } - else { - let left = cur.remove(0); + } else { + let left = cur.remove(0); let right = cur.remove(0); - let combined_hash = algorithm.hash_nodes( - left.hash(), - right.hash() - ); + let combined_hash = algorithm.hash_nodes(left.hash(), right.hash()); let node = Tree::Node { - hash: combined_hash.as_ref().into(), - left: Box::new(left), - right: Box::new(right) + hash: combined_hash.as_ref().into(), + left: Box::new(left), + right: Box::new(right), }; next.push(node); @@ -87,7 +83,7 @@ impl MerkleTree { algorithm: algorithm, root: root, height: height, - count: count + count: count, } } @@ -114,26 +110,26 @@ impl MerkleTree { /// Generate an inclusion proof for the given value. /// Returns `None` if the given value is not found in the tree. pub fn gen_proof(&self, value: T) -> Option> - where T: Hashable { + where + T: Hashable, + { - let root_hash = self.root_hash().clone(); - let leaf_hash = self.algorithm.hash_leaf(&value); + let root_hash = self.root_hash().clone(); + let leaf_hash = self.algorithm.hash_leaf(&value); - Lemma::new(&self.root, leaf_hash.as_ref()).map(|lemma| + Lemma::new(&self.root, leaf_hash.as_ref()).map(|lemma| { Proof::new(self.algorithm, root_hash, lemma, value) - ) + }) } /// Creates an `Iterator` over the values contained in this Merkle tree. pub fn iter(&self) -> LeavesIterator { self.root.iter() } - } -impl IntoIterator for MerkleTree { - - type Item = T; +impl IntoIterator for MerkleTree { + type Item = T; type IntoIter = LeavesIntoIterator; /// Creates a consuming iterator, that is, one that moves each value out of the Merkle tree. @@ -141,18 +137,14 @@ impl IntoIterator for MerkleTree { fn into_iter(self) -> Self::IntoIter { self.root.into_iter() } - } -impl <'a, T> IntoIterator for &'a MerkleTree { - - type Item = &'a T; +impl<'a, T> IntoIterator for &'a MerkleTree { + type Item = &'a T; type IntoIter = LeavesIterator<'a, T>; /// Creates a borrowing `Iterator` over the values contained in this Merkle tree. fn into_iter(self) -> Self::IntoIter { self.root.iter() } - } - diff --git a/src/proof.rs b/src/proof.rs index 85c19ea..a18614b 100644 --- a/src/proof.rs +++ b/src/proof.rs @@ -8,7 +8,6 @@ use hashutils::HashUtils; /// of a `MerkleTree` with root hash `root_hash`, and hash function `algorithm`. #[derive(Clone, Debug)] pub struct Proof { - /// The hashing algorithm used in the original `MerkleTree` pub algorithm: &'static Algorithm, @@ -19,18 +18,17 @@ pub struct Proof { pub lemma: Lemma, /// The value concerned by this `Proof` - pub value: T + pub value: T, } -impl Proof { - +impl Proof { /// Constructs a new `Proof` pub fn new(algo: &'static Algorithm, root_hash: Vec, lemma: Lemma, value: T) -> Self { Proof { algorithm: algo, root_hash: root_hash, lemma: lemma, - value: value + value: value, } } @@ -38,7 +36,7 @@ impl Proof { /// and whether its root hash matches the given `root_hash`. pub fn validate(&self, root_hash: &[u8]) -> bool { if self.root_hash != root_hash || self.lemma.node_hash != root_hash { - return false + return false; } self.validate_lemma(&self.lemma) @@ -47,13 +45,11 @@ impl Proof { fn validate_lemma(&self, lemma: &Lemma) -> bool { match lemma.sub_lemma { - None => - lemma.sibling_hash.is_none(), + None => lemma.sibling_hash.is_none(), - Some(ref sub) => + Some(ref sub) => { match lemma.sibling_hash { - None => - false, + None => false, Some(Positioned::Left(ref hash)) => { let combined = self.algorithm.hash_nodes(hash, &sub.node_hash); @@ -68,9 +64,9 @@ impl Proof { } } + } } } - } @@ -81,22 +77,22 @@ impl Proof { pub struct Lemma { pub node_hash: Vec, pub sibling_hash: Option>>, - pub sub_lemma: Option> + pub sub_lemma: Option>, } impl Lemma { - /// Attempts to generate a proof that the a value with hash `needle` is a member of the given `tree`. pub fn new(tree: &Tree, needle: &[u8]) -> Option { match *tree { - Tree::Empty {.. } => - None, + Tree::Empty { .. } => None, - Tree::Leaf { ref hash, .. } => - Lemma::new_leaf_proof(hash, needle), + Tree::Leaf { ref hash, .. } => Lemma::new_leaf_proof(hash, needle), - Tree::Node { ref hash, ref left, ref right } => - Lemma::new_tree_proof(hash, needle, left, right) + Tree::Node { + ref hash, + ref left, + ref right, + } => Lemma::new_tree_proof(hash, needle, left, right), } } @@ -105,14 +101,19 @@ impl Lemma { Some(Lemma { node_hash: hash.into(), sibling_hash: None, - sub_lemma: None + sub_lemma: None, }) } else { None } } - fn new_tree_proof(hash: &[u8], needle: &[u8], left: &Tree, right: &Tree) -> Option { + fn new_tree_proof( + hash: &[u8], + needle: &[u8], + left: &Tree, + right: &Tree, + ) -> Option { Lemma::new(left, needle) .map(|lemma| { let right_hash = right.hash().clone(); @@ -131,20 +132,18 @@ impl Lemma { Lemma { node_hash: hash.into(), sibling_hash: sibling_hash, - sub_lemma: Some(Box::new(sub_lemma)) + sub_lemma: Some(Box::new(sub_lemma)), } }) } - } /// Tags a value so that we know from which branch of a `Tree` (if any) it was found. #[derive(Clone, Debug, PartialEq)] pub enum Positioned { - /// The value was found in the left branch Left(T), /// The value was found in the right branch - Right(T) + Right(T), } diff --git a/src/proto/mod.rs b/src/proto/mod.rs index 4f43894..b990008 100644 --- a/src/proto/mod.rs +++ b/src/proto/mod.rs @@ -3,54 +3,69 @@ mod proof; use ring::digest::Algorithm; -use proof::{ Proof, Lemma, Positioned }; -pub use self::proof::{ ProofProto, LemmaProto }; +use proof::{Proof, Lemma, Positioned}; +pub use self::proof::{ProofProto, LemmaProto}; use protobuf::Message; use protobuf::error::ProtobufResult; use protobuf::core::parse_from_bytes; -impl Proof { - +impl Proof { /// Constructs a `Proof` struct from its Protobuf representation. pub fn from_protobuf(algorithm: &'static Algorithm, proto: ProofProto) -> Option - where T: From> { + where + T: From>, + { proto.into_proof(algorithm) } /// Encode this `Proof` to its Protobuf representation. pub fn into_protobuf(self) -> ProofProto - where T: Into> { + where + T: Into>, + { ProofProto::from_proof(self) } /// Parse a `Proof` from its Protobuf binary representation. - pub fn parse_from_bytes(bytes: &[u8], algorithm: &'static Algorithm) -> ProtobufResult> - where T: From> { + pub fn parse_from_bytes( + bytes: &[u8], + algorithm: &'static Algorithm, + ) -> ProtobufResult> + where + T: From>, + { parse_from_bytes::(bytes).map(|proto| proto.into_proof(algorithm)) } /// Serialize this `Proof` with Protobuf. pub fn write_to_bytes(self) -> ProtobufResult> - where T: Into> { + where + T: Into>, + { self.into_protobuf().write_to_bytes() } - } impl ProofProto { - pub fn from_proof(proof: Proof) -> Self - where T: Into> { + where + T: Into>, + { let mut proto = Self::new(); match proof { - Proof { root_hash, lemma, value, .. } => { + Proof { + root_hash, + lemma, + value, + .. + } => { proto.set_root_hash(root_hash); proto.set_lemma(LemmaProto::from_lemma(lemma)); proto.set_value(value.into()); @@ -61,7 +76,9 @@ impl ProofProto { } pub fn into_proof(mut self, algorithm: &'static Algorithm) -> Option> - where T: From> { + where + T: From>, + { if !self.has_root_hash() || !self.has_lemma() { return None; @@ -72,20 +89,22 @@ impl ProofProto { algorithm, self.take_root_hash(), lemma, - self.take_value().into() + self.take_value().into(), ) }) } - } impl LemmaProto { - pub fn from_lemma(lemma: Lemma) -> Self { let mut proto = Self::new(); match lemma { - Lemma { node_hash, sibling_hash, sub_lemma } => { + Lemma { + node_hash, + sibling_hash, + sub_lemma, + } => { proto.set_node_hash(node_hash); if let Some(sub_proto) = sub_lemma.map(|l| Self::from_lemma(*l)) { @@ -93,11 +112,9 @@ impl LemmaProto { } match sibling_hash { - Some(Positioned::Left(hash)) => - proto.set_left_sibling_hash(hash), + Some(Positioned::Left(hash)) => proto.set_left_sibling_hash(hash), - Some(Positioned::Right(hash)) => - proto.set_right_sibling_hash(hash), + Some(Positioned::Right(hash)) => proto.set_right_sibling_hash(hash), None => {} } @@ -114,16 +131,13 @@ impl LemmaProto { let node_hash = self.take_node_hash(); - let sibling_hash = - if self.has_left_sibling_hash() { - Some(Positioned::Left(self.take_left_sibling_hash())) - } - else if self.has_right_sibling_hash() { - Some(Positioned::Right(self.take_right_sibling_hash())) - } - else { - None - }; + let sibling_hash = if self.has_left_sibling_hash() { + Some(Positioned::Left(self.take_left_sibling_hash())) + } else if self.has_right_sibling_hash() { + Some(Positioned::Right(self.take_right_sibling_hash())) + } else { + None + }; if self.has_sub_lemma() { // If a `sub_lemma` is present is the Protobuf, @@ -133,21 +147,18 @@ impl LemmaProto { Lemma { node_hash: node_hash, sibling_hash: sibling_hash, - sub_lemma: Some(Box::new(sub_lemma)) + sub_lemma: Some(Box::new(sub_lemma)), } }) - } - else { + } else { // We might very well not have a sub_lemma, // in which case we just set it to `None`, // but still return a potentially valid `Lemma`. Some(Lemma { node_hash: node_hash, sibling_hash: sibling_hash, - sub_lemma: None + sub_lemma: None, }) } } - } - diff --git a/src/tests.rs b/src/tests.rs index 55a988d..a90a006 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,10 +1,10 @@ #![cfg(test)] -use ring::digest::{ Algorithm, Context, SHA512 }; +use ring::digest::{Algorithm, Context, SHA512}; use merkletree::MerkleTree; -use hashutils::{ Hashable, HashUtils }; +use hashutils::{Hashable, HashUtils}; use proof::Positioned; #[allow(non_upper_case_globals)] @@ -18,11 +18,11 @@ fn test_from_str_vec() { digest.hash_leaf(&values[0].as_bytes()), digest.hash_leaf(&values[1].as_bytes()), digest.hash_leaf(&values[2].as_bytes()), - digest.hash_leaf(&values[3].as_bytes()) + digest.hash_leaf(&values[3].as_bytes()), ]; let count = values.len(); - let tree = MerkleTree::from_vec(digest, values); + let tree = MerkleTree::from_vec(digest, values); let h01 = digest.hash_nodes(&hashes[0], &hashes[1]); let h23 = digest.hash_nodes(&hashes[2], &hashes[3]); @@ -40,7 +40,7 @@ fn test_from_vec_empty() { let values: Vec> = vec![]; let tree = MerkleTree::from_vec(digest, values); let empty_hash: Vec = digest.hash_empty().as_ref().into(); - let root_hash= tree.root_hash().clone(); + let root_hash = tree.root_hash().clone(); assert_eq!(root_hash, empty_hash); } @@ -48,7 +48,7 @@ fn test_from_vec_empty() { #[test] fn test_from_vec1() { let values = vec!["hello, world".to_string()]; - let tree = MerkleTree::from_vec(digest, values); + let tree = MerkleTree::from_vec(digest, values); let root_hash = &digest.hash_leaf(&"hello, world".as_bytes()); @@ -61,16 +61,16 @@ fn test_from_vec1() { #[test] fn test_from_vec3() { let values = vec![vec![1], vec![2], vec![3]]; - let tree = MerkleTree::from_vec(digest, values); + let tree = MerkleTree::from_vec(digest, values); let hashes = vec![ digest.hash_leaf(&vec![1]), digest.hash_leaf(&vec![2]), - digest.hash_leaf(&vec![3]) + digest.hash_leaf(&vec![3]), ]; - let h01 = digest.hash_nodes(&hashes[0], &hashes[1]); - let h2 = &hashes[2]; + let h01 = digest.hash_nodes(&hashes[0], &hashes[1]); + let h2 = &hashes[2]; let root_hash = &digest.hash_nodes(&h01, h2); assert_eq!(tree.count(), 3); @@ -81,15 +81,18 @@ fn test_from_vec3() { #[test] fn test_from_vec9() { let values = (1..10).map(|x| vec![x]).collect::>(); - let tree = MerkleTree::from_vec(digest, values.clone()); + let tree = MerkleTree::from_vec(digest, values.clone()); - let hashes = values.iter().map(|v| digest.hash_leaf(v)).collect::>(); + let hashes = values + .iter() + .map(|v| digest.hash_leaf(v)) + .collect::>(); - let h01 = digest.hash_nodes(&hashes[0], &hashes[1]); - let h23 = digest.hash_nodes(&hashes[2], &hashes[3]); - let h45 = digest.hash_nodes(&hashes[4], &hashes[5]); - let h67 = digest.hash_nodes(&hashes[6], &hashes[7]); - let h8 = &hashes[8]; + let h01 = digest.hash_nodes(&hashes[0], &hashes[1]); + let h23 = digest.hash_nodes(&hashes[2], &hashes[3]); + let h45 = digest.hash_nodes(&hashes[4], &hashes[5]); + let h67 = digest.hash_nodes(&hashes[6], &hashes[7]); + let h8 = &hashes[8]; let h0123 = digest.hash_nodes(&h01, &h23); let h4567 = digest.hash_nodes(&h45, &h67); let h1to7 = digest.hash_nodes(&h0123, &h4567); @@ -103,12 +106,12 @@ fn test_from_vec9() { #[test] fn test_valid_proof() { - let values = (1..10).map(|x| vec![x]).collect::>(); - let tree = MerkleTree::from_vec(digest, values.clone()); + let values = (1..10).map(|x| vec![x]).collect::>(); + let tree = MerkleTree::from_vec(digest, values.clone()); let root_hash = tree.root_hash(); for value in values { - let proof = tree.gen_proof(value); + let proof = tree.gen_proof(value); let is_valid = proof.map(|p| p.validate(&root_hash)).unwrap_or(false); assert!(is_valid); @@ -117,13 +120,13 @@ fn test_valid_proof() { #[test] fn test_valid_proof_str() { - let values = vec!["Hello", "my", "name", "is", "Rusty"]; - let tree = MerkleTree::from_vec(digest, values); + let values = vec!["Hello", "my", "name", "is", "Rusty"]; + let tree = MerkleTree::from_vec(digest, values); let root_hash = tree.root_hash(); let value = "Rusty"; - let proof = tree.gen_proof(&value); + let proof = tree.gen_proof(&value); let is_valid = proof.map(|p| p.validate(&root_hash)).unwrap_or(false); assert!(is_valid); @@ -131,16 +134,16 @@ fn test_valid_proof_str() { #[test] fn test_wrong_proof() { - let values1 = vec![vec![1], vec![2], vec![3], vec![4]]; - let tree1 = MerkleTree::from_vec(digest, values1.clone()); + let values1 = vec![vec![1], vec![2], vec![3], vec![4]]; + let tree1 = MerkleTree::from_vec(digest, values1.clone()); - let values2 = vec![vec![4], vec![5], vec![6], vec![7]]; - let tree2 = MerkleTree::from_vec(digest, values2.clone()); + let values2 = vec![vec![4], vec![5], vec![6], vec![7]]; + let tree2 = MerkleTree::from_vec(digest, values2.clone()); let root_hash = tree2.root_hash(); for value in values1 { - let proof = tree1.gen_proof(value); + let proof = tree1.gen_proof(value); let is_valid = proof.map(|p| p.validate(root_hash)).unwrap_or(false); assert_eq!(is_valid, false); @@ -149,8 +152,8 @@ fn test_wrong_proof() { #[test] fn test_mutate_proof_first_lemma() { - let values = (1..10).map(|x| vec![x]).collect::>(); - let tree = MerkleTree::from_vec(digest, values.clone()); + let values = (1..10).map(|x| vec![x]).collect::>(); + let tree = MerkleTree::from_vec(digest, values.clone()); let root_hash = tree.root_hash(); let mut i = 0; @@ -161,10 +164,10 @@ fn test_mutate_proof_first_lemma() { match i % 3 { 0 => { proof.lemma.node_hash = vec![1, 2, 3]; - }, + } 1 => { proof.lemma.sibling_hash = Some(Positioned::Left(vec![1, 2, 3])); - }, + } _ => { proof.lemma.sibling_hash = Some(Positioned::Right(vec![1, 2, 3])); } @@ -179,26 +182,26 @@ fn test_mutate_proof_first_lemma() { #[test] fn test_tree_iter() { - let values = (1..10).map(|x| vec![x]).collect::>(); - let tree = MerkleTree::from_vec(digest, values.clone()); - let iter = tree.iter().map(|x| x.clone()).collect::>(); + let values = (1..10).map(|x| vec![x]).collect::>(); + let tree = MerkleTree::from_vec(digest, values.clone()); + let iter = tree.iter().map(|x| x.clone()).collect::>(); assert_eq!(values, iter); } #[test] fn test_tree_into_iter() { - let values = (1..10).map(|x| vec![x]).collect::>(); - let tree = MerkleTree::from_vec(digest, values.clone()); - let iter = tree.into_iter().map(|x| x.clone()).collect::>(); + let values = (1..10).map(|x| vec![x]).collect::>(); + let tree = MerkleTree::from_vec(digest, values.clone()); + let iter = tree.into_iter().map(|x| x.clone()).collect::>(); assert_eq!(values, iter); } #[test] fn test_tree_into_iter_loop() { - let values = (1..10).map(|x| vec![x]).collect::>(); - let tree = MerkleTree::from_vec(digest, values.clone()); + let values = (1..10).map(|x| vec![x]).collect::>(); + let tree = MerkleTree::from_vec(digest, values.clone()); let mut collected = Vec::new(); @@ -211,8 +214,8 @@ fn test_tree_into_iter_loop() { #[test] fn test_tree_into_iter_loop_borrow() { - let values = (1..10).map(|x| vec![x]).collect::>(); - let tree = MerkleTree::from_vec(digest, values.clone()); + let values = (1..10).map(|x| vec![x]).collect::>(); + let tree = MerkleTree::from_vec(digest, values.clone()); let mut collected = Vec::new(); @@ -228,43 +231,44 @@ fn test_tree_into_iter_loop_borrow() { pub struct PublicKey { zero_values: Vec>, - one_values: Vec> + one_values: Vec>, } impl PublicKey { - pub fn new(zero_values: Vec>, one_values: Vec>) -> Self { PublicKey { zero_values: zero_values, - one_values: one_values + one_values: one_values, } } pub fn to_bytes(&self) -> Vec { - self.zero_values.iter().chain(self.one_values.iter()) - .fold(Vec::new(), |mut acc, i| { + self.zero_values.iter().chain(self.one_values.iter()).fold( + Vec::new(), + |mut acc, i| { acc.append(&mut i.clone()); acc - }) + }, + ) } } impl Hashable for PublicKey { - fn update_context(&self, context: &mut Context) { context.update(&self.to_bytes()); } - } #[test] fn test_custom_hashable_impl() { - let keys = (0..10).map(|i| { - let zero_values = vec![vec![i], vec![i + 1], vec![i + 2]]; - let one_values = vec![vec![i + 3], vec![i + 4], vec![i + 5]]; + let keys = (0..10) + .map(|i| { + let zero_values = vec![vec![i], vec![i + 1], vec![i + 2]]; + let one_values = vec![vec![i + 3], vec![i + 4], vec![i + 5]]; - PublicKey::new(zero_values, one_values) - }).collect::>(); + PublicKey::new(zero_values, one_values) + }) + .collect::>(); let tree = MerkleTree::from_vec(digest, keys); diff --git a/src/tree.rs b/src/tree.rs index 8194292..e42f1bd 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -1,53 +1,43 @@ -use ring::digest::{ Algorithm, Digest }; +use ring::digest::{Algorithm, Digest}; -use hashutils::{ Hashable, HashUtils }; +use hashutils::{Hashable, HashUtils}; -pub use proof::{ - Proof, - Lemma, - Positioned -}; +pub use proof::{Proof, Lemma, Positioned}; /// Binary Tree where leaves hold a stand-alone value. #[derive(Clone, Debug, PartialEq)] pub enum Tree { - Empty { - hash: Vec - }, + Empty { hash: Vec }, - Leaf { - hash: Vec, - value: T - }, + Leaf { hash: Vec, value: T }, Node { hash: Vec, left: Box>, - right: Box> - } + right: Box>, + }, } -impl Tree { - +impl Tree { /// Create an empty tree pub fn empty(hash: Digest) -> Self { - Tree::Empty { - hash: hash.as_ref().into() - } + Tree::Empty { hash: hash.as_ref().into() } } /// Create a new tree pub fn new(hash: Digest, value: T) -> Self { Tree::Leaf { hash: hash.as_ref().into(), - value: value + value: value, } } /// Create a new leaf pub fn new_leaf(algo: &'static Algorithm, value: T) -> Tree - where T: Hashable { + where + T: Hashable, + { let hash = algo.hash_leaf(&value); Tree::new(hash, value) @@ -56,9 +46,9 @@ impl Tree { /// Returns a hash from the tree. pub fn hash(&self) -> &Vec { match *self { - Tree::Empty { ref hash } => hash, + Tree::Empty { ref hash } => hash, Tree::Leaf { ref hash, .. } => hash, - Tree::Node { ref hash, .. } => hash + Tree::Node { ref hash, .. } => hash, } } @@ -66,23 +56,24 @@ impl Tree { pub fn iter(&self) -> LeavesIterator { LeavesIterator::new(self) } - } -/// An borrowing iterator over the leaves of a `Tree`. +/// An borrowing iterator over the leaves of a `Tree`. /// Adapted from http://codereview.stackexchange.com/q/110283. #[allow(missing_debug_implementations)] -pub struct LeavesIterator<'a, T> where T: 'a { +pub struct LeavesIterator<'a, T> +where + T: 'a, +{ current_value: Option<&'a T>, - right_nodes: Vec<&'a Tree> + right_nodes: Vec<&'a Tree>, } -impl <'a, T> LeavesIterator<'a, T> { - +impl<'a, T> LeavesIterator<'a, T> { fn new(root: &'a Tree) -> Self { let mut iter = LeavesIterator { current_value: None, - right_nodes: Vec::new() + right_nodes: Vec::new(), }; iter.add_left(root); @@ -96,12 +87,16 @@ impl <'a, T> LeavesIterator<'a, T> { Tree::Empty { .. } => { self.current_value = None; break; - }, + } - Tree::Node { ref left, ref right, .. } => { + Tree::Node { + ref left, + ref right, + .. + } => { self.right_nodes.push(right); tree = left; - }, + } Tree::Leaf { ref value, .. } => { self.current_value = Some(value); @@ -110,11 +105,9 @@ impl <'a, T> LeavesIterator<'a, T> { } } } - } -impl <'a, T> Iterator for LeavesIterator<'a, T> { - +impl<'a, T> Iterator for LeavesIterator<'a, T> { type Item = &'a T; fn next(&mut self) -> Option<&'a T> { @@ -126,22 +119,20 @@ impl <'a, T> Iterator for LeavesIterator<'a, T> { result } - } /// An iterator over the leaves of a `Tree`. #[allow(missing_debug_implementations)] pub struct LeavesIntoIterator { current_value: Option, - right_nodes: Vec> + right_nodes: Vec>, } -impl LeavesIntoIterator { - +impl LeavesIntoIterator { fn new(root: Tree) -> Self { let mut iter = LeavesIntoIterator { current_value: None, - right_nodes: Vec::new() + right_nodes: Vec::new(), }; iter.add_left(root); @@ -155,12 +146,12 @@ impl LeavesIntoIterator { Tree::Empty { .. } => { self.current_value = None; break; - }, + } Tree::Node { left, right, .. } => { self.right_nodes.push(*right); tree = *left; - }, + } Tree::Leaf { value, .. } => { self.current_value = Some(value); @@ -169,11 +160,9 @@ impl LeavesIntoIterator { } } } - } -impl Iterator for LeavesIntoIterator { - +impl Iterator for LeavesIntoIterator { type Item = T; fn next(&mut self) -> Option { @@ -185,17 +174,13 @@ impl Iterator for LeavesIntoIterator { result } - } -impl IntoIterator for Tree { - - type Item = T; +impl IntoIterator for Tree { + type Item = T; type IntoIter = LeavesIntoIterator; fn into_iter(self) -> Self::IntoIter { LeavesIntoIterator::new(self) } - } - diff --git a/tests/proto.rs b/tests/proto.rs index cd58554..aefee73 100644 --- a/tests/proto.rs +++ b/tests/proto.rs @@ -5,9 +5,9 @@ extern crate ring; extern crate merkle; extern crate protobuf; -use ring::digest::{ Algorithm, Context, SHA512 }; +use ring::digest::{Algorithm, Context, SHA512}; -use merkle::{ MerkleTree, Proof, Hashable }; +use merkle::{MerkleTree, Proof, Hashable}; #[allow(non_upper_case_globals)] static digest: &'static Algorithm = &SHA512; @@ -21,7 +21,9 @@ fn test_protobuf_inverse() { for value in values { let proof = tree.gen_proof(value).unwrap(); let bytes = proof.clone().write_to_bytes().unwrap(); - let res = Proof::>::parse_from_bytes(&bytes, digest).unwrap().unwrap(); + let res = Proof::>::parse_from_bytes(&bytes, digest) + .unwrap() + .unwrap(); assert_eq!(proof.root_hash, res.root_hash); assert_eq!(proof.value, res.value); @@ -32,27 +34,30 @@ fn test_protobuf_inverse() { #[derive(Clone, Debug, PartialEq)] pub struct PublicKey { zero_values: Vec, - one_values: Vec + one_values: Vec, } impl PublicKey { - pub fn new(zero_values: Vec, one_values: Vec) -> Self { PublicKey { zero_values: zero_values, - one_values: one_values + one_values: one_values, } } pub fn to_bytes(&self) -> Vec { - self.zero_values.iter().chain(self.one_values.iter()).cloned().collect() + self.zero_values + .iter() + .chain(self.one_values.iter()) + .cloned() + .collect() } } impl From> for PublicKey { fn from(mut bytes: Vec) -> Self { - let len = bytes.len(); - let ones = bytes.split_off(len/2); + let len = bytes.len(); + let ones = bytes.split_off(len / 2); let zeros = bytes; PublicKey::new(zeros, ones) @@ -66,32 +71,31 @@ impl Into> for PublicKey { } impl Hashable for PublicKey { - fn update_context(&self, context: &mut Context) { context.update(&self.to_bytes()); } - } #[test] fn test_protobuf_custom_hashable_impl() { - let keys = (0..10).map(|i| { - let zero_values = (i .. i+16).collect::>(); - let one_values = (i*10 .. i*10+16).collect::>(); + let keys = (0..10) + .map(|i| { + let zero_values = (i..i + 16).collect::>(); + let one_values = (i * 10..i * 10 + 16).collect::>(); - PublicKey::new(zero_values, one_values) - }).collect::>(); + PublicKey::new(zero_values, one_values) + }) + .collect::>(); let tree = MerkleTree::from_vec(digest, keys.clone()); for key in keys { let proof = tree.gen_proof(key).unwrap(); let bytes = proof.clone().write_to_bytes().unwrap(); - let res = Proof::parse_from_bytes(&bytes, digest).unwrap().unwrap(); + let res = Proof::parse_from_bytes(&bytes, digest).unwrap().unwrap(); assert_eq!(proof.root_hash, res.root_hash); assert_eq!(proof.value, res.value); assert_eq!(proof.lemma, res.lemma); } } -