mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-21 03:21:08 +03:00
Formatting
This commit is contained in:
parent
26ce1d27d7
commit
9703cba92a
1 changed files with 743 additions and 693 deletions
|
@ -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,10 +29,11 @@ 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;
|
||||||
|
|
||||||
/// Obtain the sum of the object
|
/// Obtain the sum of the object
|
||||||
fn sum(&self) -> Self::Sum;
|
fn sum(&self) -> Self::Sum;
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue