fn from_vec(digest: D, values: Vec<T>) -> Self
-
Constructs a Merkle Tree from a vector of data blocks
+
Methods
+
+
Constructs a Merkle Tree from a vector of data blocks.
+WARNING: Panics if values
is empty!
+
fn from_vec(digest: D, values: Vec<T>) -> Option<Self>
+
Constructs a Merkle Tree from a vector of data blocks.
+Returns None if values
is empty.
+
fn digest(&self) -> &D
+
Returns the hash function used in this Merkle tree
-
Returns the tree's root hash
+
Returns the root hash of Merkle tree
+
+
Returns the height of Merkle tree
+
+
Returns the number of leaves in the Merkle tree
Generate an inclusion proof for the given value.
-None
is returned if the given value is not found in the tree.
+Returns
None
if the given value is not found in the tree.
diff --git a/docs/merkle/struct.Proof.html b/docs/merkle/struct.Proof.html
index 8bd636f..43be851 100644
--- a/docs/merkle/struct.Proof.html
+++ b/docs/merkle/struct.Proof.html
@@ -47,22 +47,18 @@
[−]
-
[src]
+
[src]
pub struct Proof<D, T> {
- pub digest: D,
- pub root_hash: Vec<u8>,
- pub block: ProofBlock,
- pub value: T,
+ // some fields omitted
}
An inclusion proof represent the fact that a value
is a member
of a MerkleTree
with root hash root_hash
, and hash function digest
.
-
Fields
digest: D
- root_hash: Vec<u8>
- block: ProofBlock
- value: T
- Methods
-
+
Methods
+
fn new(digest: D, root_hash: Vec<u8>, lemma: Lemma) -> Self
+
+
Checks whether this inclusion proof is well-formed,
+and whether its root hash matches the given root_hash
.
+
diff --git a/docs/search-index.js b/docs/search-index.js
index ce47aca..ea78130 100644
--- a/docs/search-index.js
+++ b/docs/search-index.js
@@ -1,3 +1,3 @@
var searchIndex = {};
-searchIndex["merkle"] = {"doc":"*merkle* implements a Merkle Tree in Rust.","items":[[3,"MerkleTree","merkle","A Merkle tree is a binary tree, with values of type `T` at the leafs,\nand where every node holds the hash of the concatenation of the hashes of\nits children nodes.",null,null],[12,"digest","","The hashing function used by this Merkle tree",0,null],[12,"tree","","The inner binary tree",0,null],[12,"height","","The height of the tree",0,null],[12,"count","","The number of leaf nodes in the tree",0,null],[3,"Proof","","An inclusion proof represent the fact that a `value` is a member\nof a `MerkleTree` with root hash `root_hash`, and hash function `digest`.",null,null],[12,"digest","","",1,null],[12,"root_hash","","",1,null],[12,"block","","",1,null],[12,"value","","",1,null],[11,"from_vec","","Constructs a Merkle Tree from a vector of data blocks",0,{"inputs":[{"name":"d"},{"name":"vec"}],"output":{"name":"self"}}],[11,"root_hash","","Returns the tree's root hash",0,null],[11,"gen_proof","","Generate an inclusion proof for the given value.\n`None` is returned if the given value is not found in the tree.",0,null],[11,"validate","","",1,null],[11,"validate_block","","",1,null]],"paths":[[3,"MerkleTree"],[3,"Proof"]]};
+searchIndex["merkle"] = {"doc":"*merkle* implements a Merkle Tree in Rust.","items":[[3,"MerkleTree","merkle","A Merkle tree is a binary tree, with values of type `T` at the leafs,\nand where every node holds the hash of the concatenation of the hashes of\nits children nodes.",null,null],[3,"Proof","","An inclusion proof represent the fact that a `value` is a member\nof a `MerkleTree` with root hash `root_hash`, and hash function `digest`.",null,null],[11,"from_vec_unsafe","","Constructs a Merkle Tree from a vector of data blocks.\nWARNING: Panics if `values` is empty!",0,{"inputs":[{"name":"d"},{"name":"vec"}],"output":{"name":"self"}}],[11,"from_vec","","Constructs a Merkle Tree from a vector of data blocks.\nReturns None if `values` is empty.",0,{"inputs":[{"name":"d"},{"name":"vec"}],"output":{"name":"option"}}],[11,"digest","","Returns the hash function used in this Merkle tree",0,null],[11,"root_hash","","Returns the root hash of Merkle tree",0,null],[11,"height","","Returns the height of Merkle tree",0,null],[11,"count","","Returns the number of leaves in the Merkle tree",0,null],[11,"gen_proof","","Generate an inclusion proof for the given value.\nReturns `None` if the given value is not found in the tree.",0,null],[11,"new","","Constructs a new `Proof`",1,{"inputs":[{"name":"d"},{"name":"vec"},{"name":"lemma"}],"output":{"name":"self"}}],[11,"validate","","Checks whether this inclusion proof is well-formed,\nand whether its root hash matches the given `root_hash`.",1,null]],"paths":[[3,"MerkleTree"],[3,"Proof"]]};
initSearch(searchIndex);
diff --git a/docs/src/merkle/src/lib.rs.html b/docs/src/merkle/src/lib.rs.html
index ce41b53..84e2019 100644
--- a/docs/src/merkle/src/lib.rs.html
+++ b/docs/src/merkle/src/lib.rs.html
@@ -60,7 +60,9 @@
16
17
18
+
19
+#![warn(missing_docs)]
diff --git a/docs/src/merkle/src/merkletree.rs.html b/docs/src/merkle/src/merkletree.rs.html
index 3ca2e61..b15c1d9 100644
--- a/docs/src/merkle/src/merkletree.rs.html
+++ b/docs/src/merkle/src/merkletree.rs.html
@@ -152,46 +152,65 @@
108
109
110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+
use crypto::digest::Digest;
-use tree::{ Tree };
-use merkledigest::{ MerkleDigest };
+use tree::Tree;
+use merkledigest::MerkleDigest;
-pub use proof::{
- Proof,
- ProofBlock
-};
+use proof::{ Proof, Lemma };
pub struct MerkleTree<D, T> {
- pub digest: D,
+ digest: D,
-
- pub tree: Tree<T>,
+
+ root: Tree<T>,
- pub height: usize,
+ height: usize,
- pub count: usize
+ count: usize
}
impl <D, T> MerkleTree<D, T> where D: Digest + Clone, T: Into<Vec<u8>> + Clone {
-
- pub fn from_vec(mut digest: D, values: Vec<T>) -> Self {
+
+
+ pub fn from_vec_unsafe(digest: D, values: Vec<T>) -> Self {
+ Self::from_vec(digest, values).unwrap()
+ }
+
+
+
+ pub fn from_vec(mut digest: D, values: Vec<T>) -> Option<Self> {
if values.is_empty() {
- panic!("Cannot build a Merkle tree from an empty vector.");
+ return None
}
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.into_iter() {
let leaf = Tree::make_leaf(&mut digest, v);
@@ -209,8 +228,8 @@
let right = cur.remove(0);
let combined_hash = digest.combine_hashes(
- left.get_hash(),
- right.get_hash()
+ left.hash(),
+ right.hash()
);
let node = Tree::Node {
@@ -230,34 +249,45 @@
assert!(cur.len() == 1);
- let tree = cur.remove(0);
+ let root = cur.remove(0);
- MerkleTree {
+ Some(MerkleTree {
digest: digest,
- tree: tree,
+ root: root,
height: height,
count: count
- }
+ })
}
-
+
+ pub fn digest(&self) -> &D {
+ &self.digest
+ }
+
+
pub fn root_hash(&self) -> &Vec<u8> {
- self.tree.get_hash()
+ self.root.hash()
+ }
+
+
+ pub fn height(&self) -> usize {
+ self.height
+ }
+
+
+ pub fn count(&self) -> usize {
+ self.count
}
-
+
pub fn gen_proof(&self, value: &T) -> Option<Proof<D, T>> {
let mut digest = self.digest.clone();
- let hash = digest.hash_bytes(&value.clone().into());
+ let root_hash = self.root_hash().clone();
+ let node_hash = digest.hash_bytes(&value.clone().into());
- ProofBlock::new(&self.tree, &hash).map(|block|
- Proof {
- digest: digest,
- root_hash: self.root_hash().clone(),
- block: block,
- value: value.clone()
- }
+ Lemma::new(&self.root, &node_hash).map(|lemma|
+ Proof::new(digest, root_hash, lemma)
)
}
diff --git a/docs/src/merkle/src/proof.rs.html b/docs/src/merkle/src/proof.rs.html
index 50805ea..d4986a9 100644
--- a/docs/src/merkle/src/proof.rs.html
+++ b/docs/src/merkle/src/proof.rs.html
@@ -172,130 +172,190 @@
128
129
130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+use std::marker::PhantomData;
+
use crypto::digest::Digest;
-use merkledigest::{ MerkleDigest };
-use tree::{ Tree };
+use tree::Tree;
+use merkledigest::MerkleDigest;
pub struct Proof<D, T> {
- pub digest: D,
- pub root_hash: Vec<u8>,
- pub block: ProofBlock,
- pub value: T
+ digest: D,
+ root_hash: Vec<u8>,
+ lemma: Lemma,
+ _value_marker: PhantomData<T>
}
impl <D, T> Proof<D, T> where D: Digest + Clone, T: Into<Vec<u8>> + Clone {
+
+ pub fn new(digest: D, root_hash: Vec<u8>, lemma: Lemma) -> Self {
+ Proof {
+ digest: digest,
+ root_hash: root_hash,
+ lemma: lemma,
+ _value_marker: PhantomData
+ }
+ }
+
+
+
pub fn validate(&self, root_hash: &Vec<u8>) -> bool {
- if self.root_hash != *root_hash || self.block.node_hash != *root_hash {
+ if self.root_hash != *root_hash || self.lemma.node_hash != *root_hash {
return false
}
- self.validate_block(&self.block, &mut self.digest.clone())
+ self.validate_lemma(&self.lemma, &mut self.digest.clone())
}
- pub fn validate_block(&self, block: &ProofBlock, digest: &mut D) -> bool {
- match block.sub_proof {
+ fn validate_lemma(&self, lemma: &Lemma, digest: &mut D) -> bool {
+ match lemma.sub_lemma {
None =>
- block.sibling_hash == Positioned::Nowhere,
+ lemma.sibling_hash.is_none(),
Some(ref sub) =>
- match block.sibling_hash {
- Positioned::Nowhere =>
+ match lemma.sibling_hash {
+ None =>
false,
- Positioned::Left(ref hash) => {
- let hashes_match = digest.combine_hashes(&hash, &sub.node_hash) == block.node_hash;
- hashes_match && self.validate_block(sub, digest)
+ Some(Positioned::Left(ref hash)) => {
+ let hashes_match = digest.combine_hashes(&hash, &sub.node_hash) == lemma.node_hash;
+ hashes_match && self.validate_lemma(sub, digest)
}
- Positioned::Right(ref hash) => {
- let hashes_match = digest.combine_hashes(&sub.node_hash, &hash) == block.node_hash;
- hashes_match && self.validate_block(sub, digest)
+ Some(Positioned::Right(ref hash)) => {
+ let hashes_match = digest.combine_hashes(&sub.node_hash, &hash) == lemma.node_hash;
+ hashes_match && self.validate_lemma(sub, digest)
}
}
}
}
+ #[cfg(test)]
+ pub fn lemma_mut(&mut self) -> &mut Lemma {
+ &mut self.lemma
+ }
+
}
-
-
-pub struct ProofBlock {
- pub node_hash: Vec<u8>,
- pub sibling_hash: Positioned<Vec<u8>>,
- pub sub_proof: Option<Box<ProofBlock>>
+
+
+
+pub struct Lemma {
+ node_hash: Vec<u8>,
+ sibling_hash: Option<Positioned<Vec<u8>>>,
+ sub_lemma: Option<Box<Lemma>>
}
-impl ProofBlock {
+impl Lemma {
-
- pub fn new<T>(tree: &Tree<T>, needle: &Vec<u8>) -> Option<ProofBlock>
- where T: Into<Vec<u8>> + Clone
- {
+
+ pub fn new<T>(tree: &Tree<T>, needle: &Vec<u8>) -> Option<Lemma> where T: Into<Vec<u8>> + Clone {
match *tree {
Tree::Leaf { ref hash, .. } =>
- ProofBlock::new_leaf_proof(hash, needle),
+ Lemma::new_leaf_proof(hash, needle),
Tree::Node { ref hash, ref left, ref right } =>
- ProofBlock::new_tree_proof(hash, needle, left, right)
+ Lemma::new_tree_proof(hash, needle, left, right)
}
}
- fn new_leaf_proof(hash: &Vec<u8>, needle: &Vec<u8>) -> Option<ProofBlock> {
+ fn new_leaf_proof(hash: &Vec<u8>, needle: &Vec<u8>) -> Option<Lemma> {
if *hash == *needle {
- Some(ProofBlock {
+ Some(Lemma {
node_hash: hash.clone(),
- sibling_hash: Positioned::Nowhere,
- sub_proof: None
+ sibling_hash: None,
+ sub_lemma: None
})
} else {
None
}
}
- fn new_tree_proof<T>(hash: &Vec<u8>, needle: &Vec<u8>, left: &Tree<T>, right: &Tree<T>) -> Option<ProofBlock>
+ fn new_tree_proof<T>(hash: &Vec<u8>, needle: &Vec<u8>, left: &Tree<T>, right: &Tree<T>) -> Option<Lemma>
where T: Into<Vec<u8>> + Clone
{
- ProofBlock::new(left, needle)
- .map(|block| {
- let right_hash = right.get_hash().clone();
- let sub_proof = Positioned::Right(right_hash);
- (block, sub_proof)
+ Lemma::new(left, needle)
+ .map(|lemma| {
+ let right_hash = right.hash().clone();
+ let sub_lemma = Some(Positioned::Right(right_hash));
+ (lemma, sub_lemma)
})
.or_else(|| {
- let sub_proof = ProofBlock::new(right, needle);
- sub_proof.map(|block| {
- let left_hash = left.get_hash().clone();
- let sub_proof = Positioned::Left(left_hash);
- (block, sub_proof)
+ let sub_lemma = Lemma::new(right, needle);
+ sub_lemma.map(|lemma| {
+ let left_hash = left.hash().clone();
+ let sub_lemma = Some(Positioned::Left(left_hash));
+ (lemma, sub_lemma)
})
})
- .map(|(sub_proof, sibling_hash)| {
- ProofBlock {
+ .map(|(sub_lemma, sibling_hash)| {
+ Lemma {
node_hash: hash.clone(),
sibling_hash: sibling_hash,
- sub_proof: Some(Box::new(sub_proof))
+ sub_lemma: Some(Box::new(sub_lemma))
}
})
}
+ #[cfg(test)]
+ pub fn node_hash_mut(&mut self) -> &mut Vec<u8> {
+ &mut self.node_hash
+ }
+
+ #[cfg(test)]
+ pub fn sibling_hash_mut(&mut self) -> &mut Option<Positioned<Vec<u8>>> {
+ &mut self.sibling_hash
+ }
+
+ #[cfg(test)]
+ pub fn sub_lemma_mut(&mut self) -> &mut Option<Box<Lemma>> {
+ &mut self.sub_lemma
+ }
+
}
-
+
#[derive(PartialEq)]
pub enum Positioned<T> {
-
- Nowhere,
-
Left(T),
diff --git a/docs/src/merkle/src/tree.rs.html b/docs/src/merkle/src/tree.rs.html
index 5221b03..75857ef 100644
--- a/docs/src/merkle/src/tree.rs.html
+++ b/docs/src/merkle/src/tree.rs.html
@@ -99,7 +99,7 @@
pub use proof::{
Proof,
- ProofBlock,
+ Lemma,
Positioned
};
@@ -134,7 +134,7 @@
}
- pub fn get_hash(&self) -> &Vec<u8> {
+ pub fn hash(&self) -> &Vec<u8> {
match *self {
Tree::Leaf { ref hash, .. } => hash,
Tree::Node { ref hash, .. } => hash