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
//! 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
//! to have a root-calculating function, for which the `compute_root` function should
//! be used.
//! to have a root-calculating function, for which the `compute_root` function
//! should be used.
//!
//! 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
@ -29,10 +29,11 @@ use ser::{self, Readable, Reader, Writeable, Writer};
use std::collections::HashMap;
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 {
/// 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;
/// Obtain the sum of the object
fn sum(&self) -> Self::Sum;
@ -43,7 +44,9 @@ pub trait Summable {
pub struct NullSum;
impl ops::Add for NullSum {
type Output = NullSum;
fn add(self, _: NullSum) -> NullSum { NullSum }
fn add(self, _: NullSum) -> NullSum {
NullSum
}
}
impl Readable for NullSum {
@ -62,7 +65,9 @@ impl Writeable for NullSum {
pub struct NoSum<T>(T);
impl<T> Summable for NoSum<T> {
type Sum = NullSum;
fn sum(&self) -> NullSum { NullSum }
fn sum(&self) -> NullSum {
NullSum
}
}
#[derive(Clone)]
@ -75,7 +80,7 @@ enum NodeData<T: Summable> {
Internal {
lchild: 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 {
NodeData::Pruned(ref sum) => sum.clone(),
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,
data: NodeData<T>,
hash: Hash,
depth: u8
depth: u8,
}
impl<T: Summable> Summable for Node<T> {
@ -115,14 +120,18 @@ impl<T: Summable> Node<T> {
if self.full {
1 << self.depth
} 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()
} else {
unreachable!()
}
}
}
}
/// 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: HashMap<Hash, usize>,
/// Tree contents
root: Option<Node<T>>
root: Option<Node<T>>,
}
impl<T> SumTree<T>
where T: Summable + Writeable
where
T: Summable + Writeable,
{
/// Create a new empty tree
pub fn new() -> SumTree<T> {
SumTree {
index: HashMap::new(),
root: None
root: None,
}
}
@ -172,15 +182,25 @@ impl<T> SumTree<T>
full: parent_full,
data: parent_data,
hash: parent_hash,
depth: parent_depth
depth: parent_depth,
}
// 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
// node is always another partial node or a leaf.
} 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
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);
mem::replace(&mut **rchild, SumTree::insert_right_of(moved_rchild, new));
// 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 {
match self.root {
None => 0,
Some(ref node) => node.n_children()
Some(ref node) => node.n_children(),
}
}
@ -227,7 +247,7 @@ impl<T> SumTree<T>
full: true,
data: NodeData::Leaf(elem),
hash: elem_hash,
depth: 0
depth: 0,
});
self.index.insert(index_hash, 0);
return true;
@ -242,7 +262,7 @@ impl<T> SumTree<T>
full: true,
data: NodeData::Leaf(elem),
hash: elem_hash,
depth: 0
depth: 0,
};
// Put new root in place and record insertion
@ -261,7 +281,11 @@ impl<T> SumTree<T>
node.data = NodeData::Leaf(new_elem);
} else {
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));
if bit > 0 {
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
NodeData::Pruned(_) => unreachable!(),
NodeData::Leaf(_) => unreachable!()
NodeData::Leaf(_) => unreachable!(),
}
}
}
@ -286,7 +310,9 @@ impl<T> SumTree<T>
let root = match self.root {
Some(ref mut node) => node,
None => { return false; }
None => {
return false;
}
};
match self.index.remove(&index_hash) {
@ -324,14 +350,20 @@ impl<T> SumTree<T>
} else {
let mut prune_me = None;
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));
if bit > 0 {
SumTree::prune_recurse(rchild, index - bit);
} else {
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 {
prune_me = Some(lsum.clone() + rsum.clone());
}
@ -340,7 +372,7 @@ impl<T> SumTree<T>
NodeData::Pruned(_) => {
// Already pruned. Ok.
}
NodeData::Leaf(_) => unreachable!()
NodeData::Leaf(_) => unreachable!(),
}
if let Some(sum) = prune_me {
node.data = NodeData::Pruned(sum);
@ -355,7 +387,9 @@ impl<T> SumTree<T>
let root = match self.root {
Some(ref mut node) => node,
None => { return false; }
None => {
return false;
}
};
match self.index.remove(&index_hash) {
@ -384,18 +418,20 @@ impl<T> SumTree<T>
// For a pruned internal node, it is followed by nothing.
//
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> {
match self.root {
None => writer.write_u8(0),
Some(ref node) => node.write(writer)
Some(ref node) => node.write(writer),
}
}
}
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> {
assert!(self.depth < 64);
@ -414,23 +450,28 @@ impl<T> Writeable for Node<T>
try!(writer.write_u8(depth));
try!(self.hash.write(writer));
match self.data {
NodeData::Pruned(ref sum) => {
sum.write(writer)
},
NodeData::Leaf(ref data) => {
data.write(writer)
},
NodeData::Internal { ref lchild, ref rchild, ref sum } => {
NodeData::Pruned(ref sum) => sum.write(writer),
NodeData::Leaf(ref data) => data.write(writer),
NodeData::Internal {
ref lchild,
ref rchild,
ref sum,
} => {
try!(sum.write(writer));
try!(lchild.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>
where T: Summable + Readable + Hashed
fn node_read_recurse<T>(
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
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 {
lchild: 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,
data: data,
hash: hash,
depth: depth
depth: depth,
})
}
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> {
// Read depth byte of root node
@ -489,7 +531,7 @@ impl<T> Readable for SumTree<T>
if pruned && !full {
return Ok(SumTree {
index: HashMap::new(),
root: None
root: None,
});
}
@ -509,7 +551,7 @@ impl<T> Readable for SumTree<T>
NodeData::Internal {
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))),
sum: sum
sum: sum,
}
}
};
@ -520,8 +562,8 @@ impl<T> Readable for SumTree<T>
full: full,
data: data,
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
///
fn compute_peaks<S, I>(iter: I, peaks: &mut [Option<(u8, Hash, S)>])
where S: Clone + ops::Add<Output=S> + Writeable,
I: Iterator<Item=(u8, Hash, S)>
where
S: Clone + ops::Add<Output = S> + Writeable,
I: Iterator<Item = (u8, Hash, S)>,
{
for peak in peaks.iter_mut() {
*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
/// explicitly in the passed iterator.
pub fn compute_root<'a, T, I>(iter: I) -> Option<(Hash, T::Sum)>
where T: 'a + Summable + Writeable,
I: Iterator<Item=&'a T>
where
T: 'a + Summable + Writeable,
I: Iterator<Item = &'a T>,
{
let mut peaks = vec![None; MAX_MMR_HEIGHT];
compute_peaks(iter.map(|elem| {
compute_peaks(
iter.map(|elem| {
let depth = 0u8;
let sum = elem.sum();
let hash = (depth, &sum, Hashed::hash(elem)).hash();
(depth, hash, sum)
}), &mut peaks);
}),
&mut peaks,
);
let mut ret = None;
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
#[allow(dead_code)]
fn print_node<T>(node: &Node<T>, tab_level: usize)
where T: Summable + Writeable,
T::Sum: std::fmt::Debug
where
T: Summable + Writeable,
T::Sum: std::fmt::Debug,
{
for _ in 0..tab_level {
print!(" ");
@ -597,7 +645,11 @@ fn print_node<T>(node: &Node<T>, tab_level: usize)
match node.data {
NodeData::Pruned(_) => println!(" X"),
NodeData::Leaf(_) => println!(" L"),
NodeData::Internal { ref lchild, ref rchild, .. } => {
NodeData::Internal {
ref lchild,
ref rchild,
..
} => {
println!(":");
print_node(lchild, 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)]
fn print_tree<T>(tree: &SumTree<T>)
where T: Summable + Writeable,
T::Sum: std::fmt::Debug
where
T: Summable + Writeable,
T::Sum: std::fmt::Debug,
{
match tree.root {
None => println!("[empty tree]"),
@ -632,9 +685,7 @@ mod test {
fn sum(&self) -> u64 {
// sums are not allowed to overflow, so we use this simple
// non-injective "sum" function that will still be homomorphic
self.0[0] as u64 * 0x1000 +
self.0[1] as u64 * 0x100 +
self.0[2] as u64 * 0x10 +
self.0[0] as u64 * 0x1000 + self.0[1] as u64 * 0x100 + self.0[2] as u64 * 0x10 +
self.0[3] as u64
}
}
@ -679,10 +730,16 @@ mod test {
}
};
let mut elems = [TestElem([0, 0, 0, 1]), TestElem([0, 0, 0, 2]),
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])];
let mut elems = [
TestElem([0, 0, 0, 1]),
TestElem([0, 0, 0, 2]),
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(), compute_root(elems[0..0].iter()));
@ -702,9 +759,7 @@ mod test {
assert_eq!(tree.contains(&elems[1]), None);
assert!(tree.push(elems[1]));
assert_eq!(tree.contains(&elems[1]), Some(1));
let expected = node!(leaf!(elems[0]),
leaf!(elems[1])
).hash();
let expected = node!(leaf!(elems[0]), leaf!(elems[1])).hash();
assert_eq!(tree.root_sum(), Some((expected, 3)));
assert_eq!(tree.root_sum(), compute_root(elems[0..2].iter()));
assert_eq!(tree.unpruned_len(), 2);
@ -714,10 +769,7 @@ mod test {
assert_eq!(tree.contains(&elems[2]), None);
assert!(tree.push(elems[2]));
assert_eq!(tree.contains(&elems[2]), Some(2));
let expected = node!(node!(leaf!(elems[0]),
leaf!(elems[1])),
leaf!(elems[2])
).hash();
let expected = node!(node!(leaf!(elems[0]), leaf!(elems[1])), leaf!(elems[2])).hash();
assert_eq!(tree.root_sum(), Some((expected, 6)));
assert_eq!(tree.root_sum(), compute_root(elems[0..3].iter()));
assert_eq!(tree.unpruned_len(), 3);
@ -727,10 +779,9 @@ mod test {
assert_eq!(tree.contains(&elems[3]), None);
assert!(tree.push(elems[3]));
assert_eq!(tree.contains(&elems[3]), Some(3));
let expected = node!(node!(leaf!(elems[0]),
leaf!(elems[1])),
node!(leaf!(elems[2]),
leaf!(elems[3]))
let expected = node!(
node!(leaf!(elems[0]), leaf!(elems[1])),
node!(leaf!(elems[2]), leaf!(elems[3]))
).hash();
assert_eq!(tree.root_sum(), Some((expected, 10)));
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!(tree.push(elems[4]));
assert_eq!(tree.contains(&elems[4]), Some(4));
let expected = node!(node!(node!(leaf!(elems[0]),
leaf!(elems[1])),
node!(leaf!(elems[2]),
leaf!(elems[3]))),
let expected = node!(
node!(
node!(leaf!(elems[0]), leaf!(elems[1])),
node!(leaf!(elems[2]), leaf!(elems[3]))
),
leaf!(elems[4])
).hash();
assert_eq!(tree.root_sum(), Some((expected, 15)));
@ -756,12 +808,12 @@ mod test {
assert_eq!(tree.contains(&elems[5]), None);
assert!(tree.push(elems[5]));
assert_eq!(tree.contains(&elems[5]), Some(5));
let expected = node!(node!(node!(leaf!(elems[0]),
leaf!(elems[1])),
node!(leaf!(elems[2]),
leaf!(elems[3]))),
node!(leaf!(elems[4]),
leaf!(elems[5]))
let expected = node!(
node!(
node!(leaf!(elems[0]), leaf!(elems[1])),
node!(leaf!(elems[2]), leaf!(elems[3]))
),
node!(leaf!(elems[4]), leaf!(elems[5]))
).hash();
assert_eq!(tree.root_sum(), Some((expected, 21)));
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!(tree.push(elems[6]));
assert_eq!(tree.contains(&elems[6]), Some(6));
let expected = node!(node!(node!(leaf!(elems[0]),
leaf!(elems[1])),
node!(leaf!(elems[2]),
leaf!(elems[3]))),
node!(node!(leaf!(elems[4]),
leaf!(elems[5])),
leaf!(elems[6]))
let expected = node!(
node!(
node!(leaf!(elems[0]), leaf!(elems[1])),
node!(leaf!(elems[2]), leaf!(elems[3]))
),
node!(node!(leaf!(elems[4]), leaf!(elems[5])), leaf!(elems[6]))
).hash();
assert_eq!(tree.root_sum(), Some((expected, 28)));
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!(tree.push(elems[7]));
assert_eq!(tree.contains(&elems[7]), Some(7));
let expected = node!(node!(node!(leaf!(elems[0]),
leaf!(elems[1])),
node!(leaf!(elems[2]),
leaf!(elems[3]))),
node!(node!(leaf!(elems[4]),
leaf!(elems[5])),
node!(leaf!(elems[6]),
leaf!(elems[7])))
let expected = node!(
node!(
node!(leaf!(elems[0]), leaf!(elems[1])),
node!(leaf!(elems[2]), leaf!(elems[3]))
),
node!(
node!(leaf!(elems[4]), leaf!(elems[5])),
node!(leaf!(elems[6]), leaf!(elems[7]))
)
).hash();
assert_eq!(tree.root_sum(), Some((expected, 28 + 0x1000)));
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(&old_elem), None);
}
let expected = node!(node!(node!(leaf!(elems[0]),
leaf!(elems[1])),
node!(leaf!(elems[2]),
leaf!(elems[3]))),
node!(node!(leaf!(elems[4]),
leaf!(elems[5])),
node!(leaf!(elems[6]),
leaf!(elems[7])))
let expected = node!(
node!(
node!(leaf!(elems[0]), leaf!(elems[1])),
node!(leaf!(elems[2]), leaf!(elems[3]))
),
node!(
node!(leaf!(elems[4]), leaf!(elems[5])),
node!(leaf!(elems[6]), leaf!(elems[7]))
)
).hash();
assert_eq!(tree.root_sum(), Some((expected, 28 + 36 * 0x10 + 0x1000)));
assert_eq!(tree.root_sum(), compute_root(elems[0..8].iter()));
@ -903,6 +956,3 @@ mod test {
assert!(tree.push(elem));
}
}