Formatting

This commit is contained in:
Ignotus Peverell 2017-07-19 14:03:42 +00:00
parent 26ce1d27d7
commit 9703cba92a
No known key found for this signature in database
GPG key ID: 99CD25F39F8F8211

View file

@ -16,8 +16,8 @@
//! Generic sum-merkle tree. See `doc/merkle.md` for design and motivation for //! Generic sum-merkle tree. See `doc/merkle.md` for design and motivation for
//! this structure. Most trees in Grin are stored and transmitted as either //! this structure. Most trees in Grin are stored and transmitted as either
//! (a) only a root, or (b) the entire unpruned tree. For these it is sufficient //! (a) only a root, or (b) the entire unpruned tree. For these it is sufficient
//! to have a root-calculating function, for which the `compute_root` function should //! to have a root-calculating function, for which the `compute_root` function
//! be used. //! should be used.
//! //!
//! The output set structure has much stronger requirements, as it is updated //! The output set structure has much stronger requirements, as it is updated
//! and pruned in place, and needs to be efficiently storable even when it is //! and pruned in place, and needs to be efficiently storable even when it is
@ -29,7 +29,8 @@ use ser::{self, Readable, Reader, Writeable, Writer};
use std::collections::HashMap; use std::collections::HashMap;
use std::{self, mem, ops}; use std::{self, mem, ops};
/// Trait describing an object that has a well-defined sum that the tree can sum over /// Trait describing an object that has a well-defined sum that the tree can
/// sum over
pub trait Summable { pub trait Summable {
/// The type of an object's sum /// The type of an object's sum
type Sum: Clone + ops::Add<Output = Self::Sum> + Readable + Writeable; type Sum: Clone + ops::Add<Output = Self::Sum> + Readable + Writeable;
@ -43,7 +44,9 @@ pub trait Summable {
pub struct NullSum; pub struct NullSum;
impl ops::Add for NullSum { impl ops::Add for NullSum {
type Output = NullSum; type Output = NullSum;
fn add(self, _: NullSum) -> NullSum { NullSum } fn add(self, _: NullSum) -> NullSum {
NullSum
}
} }
impl Readable for NullSum { impl Readable for NullSum {
@ -62,7 +65,9 @@ impl Writeable for NullSum {
pub struct NoSum<T>(T); pub struct NoSum<T>(T);
impl<T> Summable for NoSum<T> { impl<T> Summable for NoSum<T> {
type Sum = NullSum; type Sum = NullSum;
fn sum(&self) -> NullSum { NullSum } fn sum(&self) -> NullSum {
NullSum
}
} }
#[derive(Clone)] #[derive(Clone)]
@ -75,7 +80,7 @@ enum NodeData<T: Summable> {
Internal { Internal {
lchild: Box<Node<T>>, lchild: Box<Node<T>>,
rchild: Box<Node<T>>, rchild: Box<Node<T>>,
sum: T::Sum sum: T::Sum,
}, },
} }
@ -85,7 +90,7 @@ impl<T: Summable> Summable for NodeData<T> {
match *self { match *self {
NodeData::Pruned(ref sum) => sum.clone(), NodeData::Pruned(ref sum) => sum.clone(),
NodeData::Leaf(ref data) => data.sum(), NodeData::Leaf(ref data) => data.sum(),
NodeData::Internal { ref sum, .. } => sum.clone() NodeData::Internal { ref sum, .. } => sum.clone(),
} }
} }
} }
@ -95,7 +100,7 @@ struct Node<T: Summable> {
full: bool, full: bool,
data: NodeData<T>, data: NodeData<T>,
hash: Hash, hash: Hash,
depth: u8 depth: u8,
} }
impl<T: Summable> Summable for Node<T> { impl<T: Summable> Summable for Node<T> {
@ -115,14 +120,18 @@ impl<T: Summable> Node<T> {
if self.full { if self.full {
1 << self.depth 1 << self.depth
} else { } else {
if let NodeData::Internal{ ref lchild, ref rchild, .. } = self.data { if let NodeData::Internal {
ref lchild,
ref rchild,
..
} = self.data
{
lchild.n_children() + rchild.n_children() lchild.n_children() + rchild.n_children()
} else { } else {
unreachable!() unreachable!()
} }
} }
} }
} }
/// An insertion ordered merkle sum tree. /// An insertion ordered merkle sum tree.
@ -131,17 +140,18 @@ pub struct SumTree<T: Summable + Writeable> {
/// Index mapping data to its index in the tree /// Index mapping data to its index in the tree
index: HashMap<Hash, usize>, index: HashMap<Hash, usize>,
/// Tree contents /// Tree contents
root: Option<Node<T>> root: Option<Node<T>>,
} }
impl<T> SumTree<T> impl<T> SumTree<T>
where T: Summable + Writeable where
T: Summable + Writeable,
{ {
/// Create a new empty tree /// Create a new empty tree
pub fn new() -> SumTree<T> { pub fn new() -> SumTree<T> {
SumTree { SumTree {
index: HashMap::new(), index: HashMap::new(),
root: None root: None,
} }
} }
@ -172,15 +182,25 @@ impl<T> SumTree<T>
full: parent_full, full: parent_full,
data: parent_data, data: parent_data,
hash: parent_hash, hash: parent_hash,
depth: parent_depth depth: parent_depth,
} }
// If we are inserting next to a partial node, we should actually be // If we are inserting next to a partial node, we should actually be
// inserting under the node, so we recurse. The right child of a partial // inserting under the node, so we recurse. The right child of a partial
// node is always another partial node or a leaf. // node is always another partial node or a leaf.
} else { } else {
if let NodeData::Internal{ ref lchild, ref mut rchild, ref mut sum } = old.data { if let NodeData::Internal {
ref lchild,
ref mut rchild,
ref mut sum,
} = old.data
{
// Recurse // Recurse
let dummy_child = Node { full: true, data: NodeData::Pruned(sum.clone()), hash: old.hash, depth: 0 }; let dummy_child = Node {
full: true,
data: NodeData::Pruned(sum.clone()),
hash: old.hash,
depth: 0,
};
let moved_rchild = mem::replace(&mut **rchild, dummy_child); let moved_rchild = mem::replace(&mut **rchild, dummy_child);
mem::replace(&mut **rchild, SumTree::insert_right_of(moved_rchild, new)); mem::replace(&mut **rchild, SumTree::insert_right_of(moved_rchild, new));
// Update this node's states to reflect the new right child // Update this node's states to reflect the new right child
@ -205,7 +225,7 @@ impl<T> SumTree<T>
pub fn unpruned_len(&self) -> usize { pub fn unpruned_len(&self) -> usize {
match self.root { match self.root {
None => 0, None => 0,
Some(ref node) => node.n_children() Some(ref node) => node.n_children(),
} }
} }
@ -227,7 +247,7 @@ impl<T> SumTree<T>
full: true, full: true,
data: NodeData::Leaf(elem), data: NodeData::Leaf(elem),
hash: elem_hash, hash: elem_hash,
depth: 0 depth: 0,
}); });
self.index.insert(index_hash, 0); self.index.insert(index_hash, 0);
return true; return true;
@ -242,7 +262,7 @@ impl<T> SumTree<T>
full: true, full: true,
data: NodeData::Leaf(elem), data: NodeData::Leaf(elem),
hash: elem_hash, hash: elem_hash,
depth: 0 depth: 0,
}; };
// Put new root in place and record insertion // Put new root in place and record insertion
@ -261,7 +281,11 @@ impl<T> SumTree<T>
node.data = NodeData::Leaf(new_elem); node.data = NodeData::Leaf(new_elem);
} else { } else {
match node.data { match node.data {
NodeData::Internal { ref mut lchild, ref mut rchild, ref mut sum } => { NodeData::Internal {
ref mut lchild,
ref mut rchild,
ref mut sum,
} => {
let bit = index & (1 << (node.depth - 1)); let bit = index & (1 << (node.depth - 1));
if bit > 0 { if bit > 0 {
SumTree::replace_recurse(rchild, index - bit, new_elem); SumTree::replace_recurse(rchild, index - bit, new_elem);
@ -273,7 +297,7 @@ impl<T> SumTree<T>
} }
// Pruned data would not have been in the index // Pruned data would not have been in the index
NodeData::Pruned(_) => unreachable!(), NodeData::Pruned(_) => unreachable!(),
NodeData::Leaf(_) => unreachable!() NodeData::Leaf(_) => unreachable!(),
} }
} }
} }
@ -286,7 +310,9 @@ impl<T> SumTree<T>
let root = match self.root { let root = match self.root {
Some(ref mut node) => node, Some(ref mut node) => node,
None => { return false; } None => {
return false;
}
}; };
match self.index.remove(&index_hash) { match self.index.remove(&index_hash) {
@ -324,14 +350,20 @@ impl<T> SumTree<T>
} else { } else {
let mut prune_me = None; let mut prune_me = None;
match node.data { match node.data {
NodeData::Internal { ref mut lchild, ref mut rchild, .. } => { NodeData::Internal {
ref mut lchild,
ref mut rchild,
..
} => {
let bit = index & (1 << (node.depth - 1)); let bit = index & (1 << (node.depth - 1));
if bit > 0 { if bit > 0 {
SumTree::prune_recurse(rchild, index - bit); SumTree::prune_recurse(rchild, index - bit);
} else { } else {
SumTree::prune_recurse(lchild, index); SumTree::prune_recurse(lchild, index);
} }
if let (&NodeData::Pruned(ref lsum), &NodeData::Pruned(ref rsum)) = (&lchild.data, &rchild.data) { if let (&NodeData::Pruned(ref lsum), &NodeData::Pruned(ref rsum)) =
(&lchild.data, &rchild.data)
{
if node.full { if node.full {
prune_me = Some(lsum.clone() + rsum.clone()); prune_me = Some(lsum.clone() + rsum.clone());
} }
@ -340,7 +372,7 @@ impl<T> SumTree<T>
NodeData::Pruned(_) => { NodeData::Pruned(_) => {
// Already pruned. Ok. // Already pruned. Ok.
} }
NodeData::Leaf(_) => unreachable!() NodeData::Leaf(_) => unreachable!(),
} }
if let Some(sum) = prune_me { if let Some(sum) = prune_me {
node.data = NodeData::Pruned(sum); node.data = NodeData::Pruned(sum);
@ -355,7 +387,9 @@ impl<T> SumTree<T>
let root = match self.root { let root = match self.root {
Some(ref mut node) => node, Some(ref mut node) => node,
None => { return false; } None => {
return false;
}
}; };
match self.index.remove(&index_hash) { match self.index.remove(&index_hash) {
@ -384,18 +418,20 @@ impl<T> SumTree<T>
// For a pruned internal node, it is followed by nothing. // For a pruned internal node, it is followed by nothing.
// //
impl<T> Writeable for SumTree<T> impl<T> Writeable for SumTree<T>
where T: Summable + Writeable where
T: Summable + Writeable,
{ {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> { fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
match self.root { match self.root {
None => writer.write_u8(0), None => writer.write_u8(0),
Some(ref node) => node.write(writer) Some(ref node) => node.write(writer),
} }
} }
} }
impl<T> Writeable for Node<T> impl<T> Writeable for Node<T>
where T: Summable + Writeable where
T: Summable + Writeable,
{ {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> { fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
assert!(self.depth < 64); assert!(self.depth < 64);
@ -414,23 +450,28 @@ impl<T> Writeable for Node<T>
try!(writer.write_u8(depth)); try!(writer.write_u8(depth));
try!(self.hash.write(writer)); try!(self.hash.write(writer));
match self.data { match self.data {
NodeData::Pruned(ref sum) => { NodeData::Pruned(ref sum) => sum.write(writer),
sum.write(writer) NodeData::Leaf(ref data) => data.write(writer),
}, NodeData::Internal {
NodeData::Leaf(ref data) => { ref lchild,
data.write(writer) ref rchild,
}, ref sum,
NodeData::Internal { ref lchild, ref rchild, ref sum } => { } => {
try!(sum.write(writer)); try!(sum.write(writer));
try!(lchild.write(writer)); try!(lchild.write(writer));
rchild.write(writer) rchild.write(writer)
}, }
} }
} }
} }
fn node_read_recurse<T>(reader: &mut Reader, index: &mut HashMap<Hash, usize>, tree_index: &mut usize) -> Result<Node<T>, ser::Error> fn node_read_recurse<T>(
where T: Summable + Readable + Hashed reader: &mut Reader,
index: &mut HashMap<Hash, usize>,
tree_index: &mut usize,
) -> Result<Node<T>, ser::Error>
where
T: Summable + Readable + Hashed,
{ {
// Read depth byte // Read depth byte
let depth = try!(reader.read_u8()); let depth = try!(reader.read_u8());
@ -462,7 +503,7 @@ fn node_read_recurse<T>(reader: &mut Reader, index: &mut HashMap<Hash, usize>, t
NodeData::Internal { NodeData::Internal {
lchild: Box::new(try!(node_read_recurse(reader, index, tree_index))), lchild: Box::new(try!(node_read_recurse(reader, index, tree_index))),
rchild: Box::new(try!(node_read_recurse(reader, index, tree_index))), rchild: Box::new(try!(node_read_recurse(reader, index, tree_index))),
sum: sum sum: sum,
} }
} }
}; };
@ -471,12 +512,13 @@ fn node_read_recurse<T>(reader: &mut Reader, index: &mut HashMap<Hash, usize>, t
full: full, full: full,
data: data, data: data,
hash: hash, hash: hash,
depth: depth depth: depth,
}) })
} }
impl<T> Readable for SumTree<T> impl<T> Readable for SumTree<T>
where T: Summable + Writeable + Readable + Hashed where
T: Summable + Writeable + Readable + Hashed,
{ {
fn read(reader: &mut Reader) -> Result<SumTree<T>, ser::Error> { fn read(reader: &mut Reader) -> Result<SumTree<T>, ser::Error> {
// Read depth byte of root node // Read depth byte of root node
@ -489,7 +531,7 @@ impl<T> Readable for SumTree<T>
if pruned && !full { if pruned && !full {
return Ok(SumTree { return Ok(SumTree {
index: HashMap::new(), index: HashMap::new(),
root: None root: None,
}); });
} }
@ -509,7 +551,7 @@ impl<T> Readable for SumTree<T>
NodeData::Internal { NodeData::Internal {
lchild: Box::new(try!(node_read_recurse(reader, &mut index, &mut tree_index))), lchild: Box::new(try!(node_read_recurse(reader, &mut index, &mut tree_index))),
rchild: Box::new(try!(node_read_recurse(reader, &mut index, &mut tree_index))), rchild: Box::new(try!(node_read_recurse(reader, &mut index, &mut tree_index))),
sum: sum sum: sum,
} }
} }
}; };
@ -520,8 +562,8 @@ impl<T> Readable for SumTree<T>
full: full, full: full,
data: data, data: data,
hash: hash, hash: hash,
depth: depth depth: depth,
}) }),
}) })
} }
} }
@ -535,8 +577,9 @@ const MAX_MMR_HEIGHT: usize = 48;
/// https://github.com/opentimestamps/opentimestamps-server/blob/master/python-opentimestamps/opentimestamps/core/timestamp.py#L324 /// https://github.com/opentimestamps/opentimestamps-server/blob/master/python-opentimestamps/opentimestamps/core/timestamp.py#L324
/// ///
fn compute_peaks<S, I>(iter: I, peaks: &mut [Option<(u8, Hash, S)>]) fn compute_peaks<S, I>(iter: I, peaks: &mut [Option<(u8, Hash, S)>])
where S: Clone + ops::Add<Output=S> + Writeable, where
I: Iterator<Item=(u8, Hash, S)> S: Clone + ops::Add<Output = S> + Writeable,
I: Iterator<Item = (u8, Hash, S)>,
{ {
for peak in peaks.iter_mut() { for peak in peaks.iter_mut() {
*peak = None; *peak = None;
@ -558,16 +601,20 @@ fn compute_peaks<S, I>(iter: I, peaks: &mut [Option<(u8, Hash, S)>])
/// Directly compute the Merkle root of a sum-tree whose contents are given /// Directly compute the Merkle root of a sum-tree whose contents are given
/// explicitly in the passed iterator. /// explicitly in the passed iterator.
pub fn compute_root<'a, T, I>(iter: I) -> Option<(Hash, T::Sum)> pub fn compute_root<'a, T, I>(iter: I) -> Option<(Hash, T::Sum)>
where T: 'a + Summable + Writeable, where
I: Iterator<Item=&'a T> T: 'a + Summable + Writeable,
I: Iterator<Item = &'a T>,
{ {
let mut peaks = vec![None; MAX_MMR_HEIGHT]; let mut peaks = vec![None; MAX_MMR_HEIGHT];
compute_peaks(iter.map(|elem| { compute_peaks(
iter.map(|elem| {
let depth = 0u8; let depth = 0u8;
let sum = elem.sum(); let sum = elem.sum();
let hash = (depth, &sum, Hashed::hash(elem)).hash(); let hash = (depth, &sum, Hashed::hash(elem)).hash();
(depth, hash, sum) (depth, hash, sum)
}), &mut peaks); }),
&mut peaks,
);
let mut ret = None; let mut ret = None;
for peak in peaks { for peak in peaks {
@ -587,8 +634,9 @@ pub fn compute_root<'a, T, I>(iter: I) -> Option<(Hash, T::Sum)>
// a couple functions that help debugging // a couple functions that help debugging
#[allow(dead_code)] #[allow(dead_code)]
fn print_node<T>(node: &Node<T>, tab_level: usize) fn print_node<T>(node: &Node<T>, tab_level: usize)
where T: Summable + Writeable, where
T::Sum: std::fmt::Debug T: Summable + Writeable,
T::Sum: std::fmt::Debug,
{ {
for _ in 0..tab_level { for _ in 0..tab_level {
print!(" "); print!(" ");
@ -597,7 +645,11 @@ fn print_node<T>(node: &Node<T>, tab_level: usize)
match node.data { match node.data {
NodeData::Pruned(_) => println!(" X"), NodeData::Pruned(_) => println!(" X"),
NodeData::Leaf(_) => println!(" L"), NodeData::Leaf(_) => println!(" L"),
NodeData::Internal { ref lchild, ref rchild, .. } => { NodeData::Internal {
ref lchild,
ref rchild,
..
} => {
println!(":"); println!(":");
print_node(lchild, tab_level + 1); print_node(lchild, tab_level + 1);
print_node(rchild, tab_level + 1); print_node(rchild, tab_level + 1);
@ -607,8 +659,9 @@ fn print_node<T>(node: &Node<T>, tab_level: usize)
#[allow(dead_code)] #[allow(dead_code)]
fn print_tree<T>(tree: &SumTree<T>) fn print_tree<T>(tree: &SumTree<T>)
where T: Summable + Writeable, where
T::Sum: std::fmt::Debug T: Summable + Writeable,
T::Sum: std::fmt::Debug,
{ {
match tree.root { match tree.root {
None => println!("[empty tree]"), None => println!("[empty tree]"),
@ -632,9 +685,7 @@ mod test {
fn sum(&self) -> u64 { fn sum(&self) -> u64 {
// sums are not allowed to overflow, so we use this simple // sums are not allowed to overflow, so we use this simple
// non-injective "sum" function that will still be homomorphic // non-injective "sum" function that will still be homomorphic
self.0[0] as u64 * 0x1000 + self.0[0] as u64 * 0x1000 + self.0[1] as u64 * 0x100 + self.0[2] as u64 * 0x10 +
self.0[1] as u64 * 0x100 +
self.0[2] as u64 * 0x10 +
self.0[3] as u64 self.0[3] as u64
} }
} }
@ -679,10 +730,16 @@ mod test {
} }
}; };
let mut elems = [TestElem([0, 0, 0, 1]), TestElem([0, 0, 0, 2]), let mut elems = [
TestElem([0, 0, 0, 3]), TestElem([0, 0, 0, 4]), TestElem([0, 0, 0, 1]),
TestElem([0, 0, 0, 5]), TestElem([0, 0, 0, 6]), TestElem([0, 0, 0, 2]),
TestElem([0, 0, 0, 7]), TestElem([1, 0, 0, 0])]; TestElem([0, 0, 0, 3]),
TestElem([0, 0, 0, 4]),
TestElem([0, 0, 0, 5]),
TestElem([0, 0, 0, 6]),
TestElem([0, 0, 0, 7]),
TestElem([1, 0, 0, 0]),
];
assert_eq!(tree.root_sum(), None); assert_eq!(tree.root_sum(), None);
assert_eq!(tree.root_sum(), compute_root(elems[0..0].iter())); assert_eq!(tree.root_sum(), compute_root(elems[0..0].iter()));
@ -702,9 +759,7 @@ mod test {
assert_eq!(tree.contains(&elems[1]), None); assert_eq!(tree.contains(&elems[1]), None);
assert!(tree.push(elems[1])); assert!(tree.push(elems[1]));
assert_eq!(tree.contains(&elems[1]), Some(1)); assert_eq!(tree.contains(&elems[1]), Some(1));
let expected = node!(leaf!(elems[0]), let expected = node!(leaf!(elems[0]), leaf!(elems[1])).hash();
leaf!(elems[1])
).hash();
assert_eq!(tree.root_sum(), Some((expected, 3))); assert_eq!(tree.root_sum(), Some((expected, 3)));
assert_eq!(tree.root_sum(), compute_root(elems[0..2].iter())); assert_eq!(tree.root_sum(), compute_root(elems[0..2].iter()));
assert_eq!(tree.unpruned_len(), 2); assert_eq!(tree.unpruned_len(), 2);
@ -714,10 +769,7 @@ mod test {
assert_eq!(tree.contains(&elems[2]), None); assert_eq!(tree.contains(&elems[2]), None);
assert!(tree.push(elems[2])); assert!(tree.push(elems[2]));
assert_eq!(tree.contains(&elems[2]), Some(2)); assert_eq!(tree.contains(&elems[2]), Some(2));
let expected = node!(node!(leaf!(elems[0]), let expected = node!(node!(leaf!(elems[0]), leaf!(elems[1])), leaf!(elems[2])).hash();
leaf!(elems[1])),
leaf!(elems[2])
).hash();
assert_eq!(tree.root_sum(), Some((expected, 6))); assert_eq!(tree.root_sum(), Some((expected, 6)));
assert_eq!(tree.root_sum(), compute_root(elems[0..3].iter())); assert_eq!(tree.root_sum(), compute_root(elems[0..3].iter()));
assert_eq!(tree.unpruned_len(), 3); assert_eq!(tree.unpruned_len(), 3);
@ -727,10 +779,9 @@ mod test {
assert_eq!(tree.contains(&elems[3]), None); assert_eq!(tree.contains(&elems[3]), None);
assert!(tree.push(elems[3])); assert!(tree.push(elems[3]));
assert_eq!(tree.contains(&elems[3]), Some(3)); assert_eq!(tree.contains(&elems[3]), Some(3));
let expected = node!(node!(leaf!(elems[0]), let expected = node!(
leaf!(elems[1])), node!(leaf!(elems[0]), leaf!(elems[1])),
node!(leaf!(elems[2]), node!(leaf!(elems[2]), leaf!(elems[3]))
leaf!(elems[3]))
).hash(); ).hash();
assert_eq!(tree.root_sum(), Some((expected, 10))); assert_eq!(tree.root_sum(), Some((expected, 10)));
assert_eq!(tree.root_sum(), compute_root(elems[0..4].iter())); assert_eq!(tree.root_sum(), compute_root(elems[0..4].iter()));
@ -741,10 +792,11 @@ mod test {
assert_eq!(tree.contains(&elems[4]), None); assert_eq!(tree.contains(&elems[4]), None);
assert!(tree.push(elems[4])); assert!(tree.push(elems[4]));
assert_eq!(tree.contains(&elems[4]), Some(4)); assert_eq!(tree.contains(&elems[4]), Some(4));
let expected = node!(node!(node!(leaf!(elems[0]), let expected = node!(
leaf!(elems[1])), node!(
node!(leaf!(elems[2]), node!(leaf!(elems[0]), leaf!(elems[1])),
leaf!(elems[3]))), node!(leaf!(elems[2]), leaf!(elems[3]))
),
leaf!(elems[4]) leaf!(elems[4])
).hash(); ).hash();
assert_eq!(tree.root_sum(), Some((expected, 15))); assert_eq!(tree.root_sum(), Some((expected, 15)));
@ -756,12 +808,12 @@ mod test {
assert_eq!(tree.contains(&elems[5]), None); assert_eq!(tree.contains(&elems[5]), None);
assert!(tree.push(elems[5])); assert!(tree.push(elems[5]));
assert_eq!(tree.contains(&elems[5]), Some(5)); assert_eq!(tree.contains(&elems[5]), Some(5));
let expected = node!(node!(node!(leaf!(elems[0]), let expected = node!(
leaf!(elems[1])), node!(
node!(leaf!(elems[2]), node!(leaf!(elems[0]), leaf!(elems[1])),
leaf!(elems[3]))), node!(leaf!(elems[2]), leaf!(elems[3]))
node!(leaf!(elems[4]), ),
leaf!(elems[5])) node!(leaf!(elems[4]), leaf!(elems[5]))
).hash(); ).hash();
assert_eq!(tree.root_sum(), Some((expected, 21))); assert_eq!(tree.root_sum(), Some((expected, 21)));
assert_eq!(tree.root_sum(), compute_root(elems[0..6].iter())); assert_eq!(tree.root_sum(), compute_root(elems[0..6].iter()));
@ -772,13 +824,12 @@ mod test {
assert_eq!(tree.contains(&elems[6]), None); assert_eq!(tree.contains(&elems[6]), None);
assert!(tree.push(elems[6])); assert!(tree.push(elems[6]));
assert_eq!(tree.contains(&elems[6]), Some(6)); assert_eq!(tree.contains(&elems[6]), Some(6));
let expected = node!(node!(node!(leaf!(elems[0]), let expected = node!(
leaf!(elems[1])), node!(
node!(leaf!(elems[2]), node!(leaf!(elems[0]), leaf!(elems[1])),
leaf!(elems[3]))), node!(leaf!(elems[2]), leaf!(elems[3]))
node!(node!(leaf!(elems[4]), ),
leaf!(elems[5])), node!(node!(leaf!(elems[4]), leaf!(elems[5])), leaf!(elems[6]))
leaf!(elems[6]))
).hash(); ).hash();
assert_eq!(tree.root_sum(), Some((expected, 28))); assert_eq!(tree.root_sum(), Some((expected, 28)));
assert_eq!(tree.root_sum(), compute_root(elems[0..7].iter())); assert_eq!(tree.root_sum(), compute_root(elems[0..7].iter()));
@ -789,14 +840,15 @@ mod test {
assert_eq!(tree.contains(&elems[7]), None); assert_eq!(tree.contains(&elems[7]), None);
assert!(tree.push(elems[7])); assert!(tree.push(elems[7]));
assert_eq!(tree.contains(&elems[7]), Some(7)); assert_eq!(tree.contains(&elems[7]), Some(7));
let expected = node!(node!(node!(leaf!(elems[0]), let expected = node!(
leaf!(elems[1])), node!(
node!(leaf!(elems[2]), node!(leaf!(elems[0]), leaf!(elems[1])),
leaf!(elems[3]))), node!(leaf!(elems[2]), leaf!(elems[3]))
node!(node!(leaf!(elems[4]), ),
leaf!(elems[5])), node!(
node!(leaf!(elems[6]), node!(leaf!(elems[4]), leaf!(elems[5])),
leaf!(elems[7]))) node!(leaf!(elems[6]), leaf!(elems[7]))
)
).hash(); ).hash();
assert_eq!(tree.root_sum(), Some((expected, 28 + 0x1000))); assert_eq!(tree.root_sum(), Some((expected, 28 + 0x1000)));
assert_eq!(tree.root_sum(), compute_root(elems[0..8].iter())); assert_eq!(tree.root_sum(), compute_root(elems[0..8].iter()));
@ -814,14 +866,15 @@ mod test {
assert_eq!(tree.contains(&elems[i]), Some(i)); assert_eq!(tree.contains(&elems[i]), Some(i));
assert_eq!(tree.contains(&old_elem), None); assert_eq!(tree.contains(&old_elem), None);
} }
let expected = node!(node!(node!(leaf!(elems[0]), let expected = node!(
leaf!(elems[1])), node!(
node!(leaf!(elems[2]), node!(leaf!(elems[0]), leaf!(elems[1])),
leaf!(elems[3]))), node!(leaf!(elems[2]), leaf!(elems[3]))
node!(node!(leaf!(elems[4]), ),
leaf!(elems[5])), node!(
node!(leaf!(elems[6]), node!(leaf!(elems[4]), leaf!(elems[5])),
leaf!(elems[7]))) node!(leaf!(elems[6]), leaf!(elems[7]))
)
).hash(); ).hash();
assert_eq!(tree.root_sum(), Some((expected, 28 + 36 * 0x10 + 0x1000))); assert_eq!(tree.root_sum(), Some((expected, 28 + 36 * 0x10 + 0x1000)));
assert_eq!(tree.root_sum(), compute_root(elems[0..8].iter())); assert_eq!(tree.root_sum(), compute_root(elems[0..8].iter()));
@ -903,6 +956,3 @@ mod test {
assert!(tree.push(elem)); assert!(tree.push(elem));
} }
} }