Formatting.

This commit is contained in:
Romain Ruetschi
2017-09-24 13:10:40 +02:00
parent b20bca8d97
commit 958c8c8353
9 changed files with 266 additions and 277 deletions

View File

@ -22,9 +22,7 @@ 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]
@ -32,11 +30,9 @@ fn bench_small_str_proof_gen(b: &mut Bencher) {
let values = vec!["one", "two", "three", "four"];
let tree = MerkleTree::from_vec(digest, values.clone());
b.iter(|| {
for value in &values {
b.iter(|| for value in &values {
let proof = tree.gen_proof(value);
test::black_box(proof);
}
});
}
@ -44,12 +40,13 @@ fn bench_small_str_proof_gen(b: &mut Bencher) {
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::<Vec<_>>();
let proofs = values
.iter()
.map(|v| tree.gen_proof(v).unwrap())
.collect::<Vec<_>>();
b.iter(|| {
for proof in &proofs {
b.iter(|| for proof in &proofs {
test::black_box(proof.validate(tree.root_hash()));
}
});
}
@ -79,11 +76,9 @@ fn bench_big_rnd_proof_gen(b: &mut Bencher) {
let tree = MerkleTree::from_vec(digest, values.clone());
b.iter(|| {
for value in &values {
b.iter(|| for value in &values {
let proof = tree.gen_proof(value.clone());
test::black_box(proof);
}
});
}
@ -97,14 +92,13 @@ fn bench_big_rnd_proof_check(b: &mut Bencher) {
}
let tree = MerkleTree::from_vec(digest, values.clone());
let proofs = values.into_iter()
let proofs = values
.into_iter()
.map(|v| tree.gen_proof(v).unwrap())
.collect::<Vec<_>>();
b.iter(|| {
for proof in &proofs {
b.iter(|| for proof in &proofs {
test::black_box(proof.validate(tree.root_hash()));
}
});
}
@ -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 {
b.iter(|| for value in &tree {
test::black_box(value);
}
});
}

View File

@ -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 <T: AsRef<[u8]>> Hashable for T {
impl<T: AsRef<[u8]>> Hashable for T {
fn update_context(&self, context: &mut Context) {
context.update(self.as_ref());
}
@ -40,33 +37,41 @@ impl <T: AsRef<[u8]>> 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<T>(&'static self, bytes: &T) -> Digest where T: Hashable;
fn hash_leaf<T>(&'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<T>(&'static self, left: &T, right: &T) -> Digest where T: Hashable;
fn hash_nodes<T>(&'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<T>(&'static self, leaf: &T) -> Digest where T: Hashable {
fn hash_leaf<T>(&'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<T>(&'static self, left: &T, right: &T) -> Digest where T: Hashable {
fn hash_nodes<T>(&'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()
}
}

View File

@ -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;

View File

@ -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<T> {
/// The hashing algorithm used by this Merkle tree
pub algorithm: &'static Algorithm,
@ -21,22 +20,23 @@ pub struct MerkleTree<T> {
height: usize,
/// The number of leaf nodes in the tree
count: usize
count: usize,
}
impl <T> MerkleTree<T> {
impl<T> MerkleTree<T> {
/// 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<T>) -> 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,
};
}
@ -54,20 +54,16 @@ impl <T> MerkleTree<T> {
while !cur.is_empty() {
if cur.len() == 1 {
next.push(cur.remove(0));
}
else {
} 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)
right: Box::new(right),
};
next.push(node);
@ -87,7 +83,7 @@ impl <T> MerkleTree<T> {
algorithm: algorithm,
root: root,
height: height,
count: count
count: count,
}
}
@ -114,25 +110,25 @@ impl <T> MerkleTree<T> {
/// 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<Proof<T>>
where T: Hashable {
where
T: Hashable,
{
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<T> {
self.root.iter()
}
}
impl <T> IntoIterator for MerkleTree<T> {
impl<T> IntoIterator for MerkleTree<T> {
type Item = T;
type IntoIter = LeavesIntoIterator<T>;
@ -141,11 +137,9 @@ impl <T> IntoIterator for MerkleTree<T> {
fn into_iter(self) -> Self::IntoIter {
self.root.into_iter()
}
}
impl <'a, T> IntoIterator for &'a MerkleTree<T> {
impl<'a, T> IntoIterator for &'a MerkleTree<T> {
type Item = &'a T;
type IntoIter = LeavesIterator<'a, T>;
@ -153,6 +147,4 @@ impl <'a, T> IntoIterator for &'a MerkleTree<T> {
fn into_iter(self) -> Self::IntoIter {
self.root.iter()
}
}

View File

@ -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<T> {
/// The hashing algorithm used in the original `MerkleTree`
pub algorithm: &'static Algorithm,
@ -19,18 +18,17 @@ pub struct Proof<T> {
pub lemma: Lemma,
/// The value concerned by this `Proof`
pub value: T
pub value: T,
}
impl <T> Proof<T> {
impl<T> Proof<T> {
/// Constructs a new `Proof`
pub fn new(algo: &'static Algorithm, root_hash: Vec<u8>, lemma: Lemma, value: T) -> Self {
Proof {
algorithm: algo,
root_hash: root_hash,
lemma: lemma,
value: value
value: value,
}
}
@ -38,7 +36,7 @@ impl <T> Proof<T> {
/// 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 <T> Proof<T> {
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);
@ -70,7 +66,7 @@ impl <T> Proof<T> {
}
}
}
}
}
@ -81,22 +77,22 @@ impl <T> Proof<T> {
pub struct Lemma {
pub node_hash: Vec<u8>,
pub sibling_hash: Option<Positioned<Vec<u8>>>,
pub sub_lemma: Option<Box<Lemma>>
pub sub_lemma: Option<Box<Lemma>>,
}
impl Lemma {
/// Attempts to generate a proof that the a value with hash `needle` is a member of the given `tree`.
pub fn new<T>(tree: &Tree<T>, needle: &[u8]) -> Option<Lemma> {
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<T>(hash: &[u8], needle: &[u8], left: &Tree<T>, right: &Tree<T>) -> Option<Lemma> {
fn new_tree_proof<T>(
hash: &[u8],
needle: &[u8],
left: &Tree<T>,
right: &Tree<T>,
) -> Option<Lemma> {
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<T> {
/// The value was found in the left branch
Left(T),
/// The value was found in the right branch
Right(T)
Right(T),
}

View File

@ -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 <T> Proof<T> {
impl<T> Proof<T> {
/// Constructs a `Proof` struct from its Protobuf representation.
pub fn from_protobuf(algorithm: &'static Algorithm, proto: ProofProto) -> Option<Self>
where T: From<Vec<u8>> {
where
T: From<Vec<u8>>,
{
proto.into_proof(algorithm)
}
/// Encode this `Proof` to its Protobuf representation.
pub fn into_protobuf(self) -> ProofProto
where T: Into<Vec<u8>> {
where
T: Into<Vec<u8>>,
{
ProofProto::from_proof(self)
}
/// Parse a `Proof` from its Protobuf binary representation.
pub fn parse_from_bytes(bytes: &[u8], algorithm: &'static Algorithm) -> ProtobufResult<Option<Self>>
where T: From<Vec<u8>> {
pub fn parse_from_bytes(
bytes: &[u8],
algorithm: &'static Algorithm,
) -> ProtobufResult<Option<Self>>
where
T: From<Vec<u8>>,
{
parse_from_bytes::<ProofProto>(bytes).map(|proto| proto.into_proof(algorithm))
}
/// Serialize this `Proof` with Protobuf.
pub fn write_to_bytes(self) -> ProtobufResult<Vec<u8>>
where T: Into<Vec<u8>> {
where
T: Into<Vec<u8>>,
{
self.into_protobuf().write_to_bytes()
}
}
impl ProofProto {
pub fn from_proof<T>(proof: Proof<T>) -> Self
where T: Into<Vec<u8>> {
where
T: Into<Vec<u8>>,
{
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<T>(mut self, algorithm: &'static Algorithm) -> Option<Proof<T>>
where T: From<Vec<u8>> {
where
T: From<Vec<u8>>,
{
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,14 +131,11 @@ impl LemmaProto {
let node_hash = self.take_node_hash();
let sibling_hash =
if self.has_left_sibling_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() {
} else if self.has_right_sibling_hash() {
Some(Positioned::Right(self.take_right_sibling_hash()))
}
else {
} else {
None
};
@ -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,
})
}
}
}

View File

@ -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,7 +18,7 @@ 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();
@ -40,7 +40,7 @@ fn test_from_vec_empty() {
let values: Vec<Vec<u8>> = vec![];
let tree = MerkleTree::from_vec(digest, values);
let empty_hash: Vec<u8> = 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);
}
@ -66,7 +66,7 @@ fn test_from_vec3() {
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]);
@ -83,7 +83,10 @@ fn test_from_vec9() {
let values = (1..10).map(|x| vec![x]).collect::<Vec<_>>();
let tree = MerkleTree::from_vec(digest, values.clone());
let hashes = values.iter().map(|v| digest.hash_leaf(v)).collect::<Vec<_>>();
let hashes = values
.iter()
.map(|v| digest.hash_leaf(v))
.collect::<Vec<_>>();
let h01 = digest.hash_nodes(&hashes[0], &hashes[1]);
let h23 = digest.hash_nodes(&hashes[2], &hashes[3]);
@ -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]));
}
@ -228,43 +231,44 @@ fn test_tree_into_iter_loop_borrow() {
pub struct PublicKey {
zero_values: Vec<Vec<u8>>,
one_values: Vec<Vec<u8>>
one_values: Vec<Vec<u8>>,
}
impl PublicKey {
pub fn new(zero_values: Vec<Vec<u8>>, one_values: Vec<Vec<u8>>) -> Self {
PublicKey {
zero_values: zero_values,
one_values: one_values
one_values: one_values,
}
}
pub fn to_bytes(&self) -> Vec<u8> {
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 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::<Vec<_>>();
})
.collect::<Vec<_>>();
let tree = MerkleTree::from_vec(digest, keys);

View File

@ -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<T> {
Empty {
hash: Vec<u8>
},
Empty { hash: Vec<u8> },
Leaf {
hash: Vec<u8>,
value: T
},
Leaf { hash: Vec<u8>, value: T },
Node {
hash: Vec<u8>,
left: Box<Tree<T>>,
right: Box<Tree<T>>
}
right: Box<Tree<T>>,
},
}
impl <T> Tree<T> {
impl<T> Tree<T> {
/// 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<T>
where T: Hashable {
where
T: Hashable,
{
let hash = algo.hash_leaf(&value);
Tree::new(hash, value)
@ -58,7 +48,7 @@ impl <T> Tree<T> {
match *self {
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 <T> Tree<T> {
pub fn iter(&self) -> LeavesIterator<T> {
LeavesIterator::new(self)
}
}
/// 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<T>>
right_nodes: Vec<&'a Tree<T>>,
}
impl <'a, T> LeavesIterator<'a, T> {
impl<'a, T> LeavesIterator<'a, T> {
fn new(root: &'a Tree<T>) -> 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<T> {
current_value: Option<T>,
right_nodes: Vec<Tree<T>>
right_nodes: Vec<Tree<T>>,
}
impl <T> LeavesIntoIterator<T> {
impl<T> LeavesIntoIterator<T> {
fn new(root: Tree<T>) -> 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 <T> LeavesIntoIterator<T> {
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 <T> LeavesIntoIterator<T> {
}
}
}
}
impl <T> Iterator for LeavesIntoIterator<T> {
impl<T> Iterator for LeavesIntoIterator<T> {
type Item = T;
fn next(&mut self) -> Option<T> {
@ -185,17 +174,13 @@ impl <T> Iterator for LeavesIntoIterator<T> {
result
}
}
impl <T> IntoIterator for Tree<T> {
impl<T> IntoIterator for Tree<T> {
type Item = T;
type IntoIter = LeavesIntoIterator<T>;
fn into_iter(self) -> Self::IntoIter {
LeavesIntoIterator::new(self)
}
}

View File

@ -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::<Vec<u8>>::parse_from_bytes(&bytes, digest).unwrap().unwrap();
let res = Proof::<Vec<u8>>::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<u8>,
one_values: Vec<u8>
one_values: Vec<u8>,
}
impl PublicKey {
pub fn new(zero_values: Vec<u8>, one_values: Vec<u8>) -> Self {
PublicKey {
zero_values: zero_values,
one_values: one_values
one_values: one_values,
}
}
pub fn to_bytes(&self) -> Vec<u8> {
self.zero_values.iter().chain(self.one_values.iter()).cloned().collect()
self.zero_values
.iter()
.chain(self.one_values.iter())
.cloned()
.collect()
}
}
impl From<Vec<u8>> for PublicKey {
fn from(mut bytes: Vec<u8>) -> Self {
let len = bytes.len();
let ones = bytes.split_off(len/2);
let ones = bytes.split_off(len / 2);
let zeros = bytes;
PublicKey::new(zeros, ones)
@ -66,21 +71,21 @@ impl Into<Vec<u8>> 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::<Vec<_>>();
let one_values = (i*10 .. i*10+16).collect::<Vec<_>>();
let keys = (0..10)
.map(|i| {
let zero_values = (i..i + 16).collect::<Vec<_>>();
let one_values = (i * 10..i * 10 + 16).collect::<Vec<_>>();
PublicKey::new(zero_values, one_values)
}).collect::<Vec<_>>();
})
.collect::<Vec<_>>();
let tree = MerkleTree::from_vec(digest, keys.clone());
@ -94,4 +99,3 @@ fn test_protobuf_custom_hashable_impl() {
assert_eq!(proof.lemma, res.lemma);
}
}