#![allow(dead_code)]
use crate::{
DefaultIx, GenericArray, Hasher, IndexType, MrkleHasher, MrkleNode, MrkleTree, Node, NodeError,
NodeIndex, Tree, TreeError, error::MrkleError, prelude::*,
};
pub struct MrkleDefaultBuilder<T, D: Digest, Ix: IndexType = DefaultIx> {
tree: Tree<MrkleNode<T, D, Ix>, Ix>,
hasher: MrkleHasher<D>,
finalized: bool,
}
impl<T, D: Digest, Ix: IndexType> Default for MrkleDefaultBuilder<T, D, Ix> {
fn default() -> Self {
Self::new()
}
}
impl<T, D: Digest, Ix: IndexType> MrkleDefaultBuilder<T, D, Ix> {
pub fn new() -> Self {
Self {
tree: Tree::new(),
hasher: MrkleHasher::new(),
finalized: false,
}
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
tree: Tree::with_capacity(capacity),
hasher: MrkleHasher::new(),
finalized: false,
}
}
#[inline]
pub fn len(&self) -> usize {
self.tree.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.tree.is_empty()
}
#[inline]
pub fn is_finalized(&self) -> bool {
self.finalized
}
pub fn capacity(&self) -> usize {
self.tree.capacity()
}
pub fn insert_leaf(&mut self, leaf: MrkleNode<T, D, Ix>) -> Result<NodeIndex<Ix>, TreeError> {
self.check_not_finalized()?;
if !leaf.is_leaf() {
return Err(TreeError::InvalidOperation {
operation: "insert_leaf",
reason: "provided node is not a leaf node".to_string(),
});
}
Ok(self.tree.push(leaf))
}
pub fn insert_internal(
&mut self,
children: Vec<NodeIndex<Ix>>,
) -> Result<NodeIndex<Ix>, MrkleError> {
self.check_not_finalized()?;
if children.is_empty() {
return Err(MrkleError::from(TreeError::InvalidOperation {
operation: "insert_internal",
reason: "internal nodes must have at least one child".to_string(),
}));
}
self.validate_children(&children)?;
let index = self
.tree
.push(MrkleNode::internal(&self.tree, children.clone())?);
self.set_parent_relationships(&children, index);
Ok(index)
}
pub fn finish(mut self, root: NodeIndex<Ix>) -> Result<MrkleTree<T, D, Ix>, MrkleError> {
self.check_not_finalized()?;
self.validate_root(root)?;
self.tree.root = Some(root);
if let Err(errors) = self.validate() {
return Err(MrkleError::from(TreeError::ValidationFailed {
count: errors.len(),
summary: "Tree structure validation failed".to_string(),
errors,
}));
}
self.finalized = true;
Ok(MrkleTree::new(self.tree))
}
fn validate(&self) -> Result<(), Vec<TreeError>> {
let mut errors = Vec::new();
if self.tree.try_root().is_err() {
errors.push(TreeError::MissingRoot);
}
let mut visited = BTreeSet::new();
for index in self.tree.iter_idx() {
let node = self.tree.get(index.index()).unwrap();
visited.insert(index.index());
if let Some(parent_idx) = node.parent() {
match self.tree.get(parent_idx.index()) {
Some(parent_node) => {
if !parent_node.children().contains(&index) {
errors.push(TreeError::InconsistentState {
details: format!(
"node {} claims parent {}, but parent doesn't list it as child",
index,
parent_idx.index()
),
});
}
}
None => {
errors.push(TreeError::IndexOutOfBounds {
index: parent_idx.index(),
len: self.tree.len(),
});
}
}
}
for child_idx in node.children() {
match self.tree.get(child_idx.index()) {
Some(child_node) => {
if child_node.parent() != Some(index) {
errors.push(TreeError::InconsistentState {
details: format!(
"node {} lists {} as child, but child has different parent",
index,
child_idx.index()
),
});
}
}
None => {
errors.push(TreeError::IndexOutOfBounds {
index: child_idx.index(),
len: self.tree.len(),
});
}
}
}
}
if visited.len() != self.len() {
errors.push(TreeError::DisjointNode);
}
if errors.is_empty() {
Ok(())
} else {
Err(errors)
}
}
fn check_not_finalized(&self) -> Result<(), TreeError> {
if self.finalized {
Err(TreeError::AlreadyFinalized)
} else {
Ok(())
}
}
fn validate_children(&self, children: &[NodeIndex<Ix>]) -> Result<(), TreeError> {
let mut seen = BTreeSet::new();
for &child in children {
if !seen.insert(child) {
return Err(NodeError::Duplicate {
child: child.index(),
}
.into());
}
}
for &child in children {
let node = self
.tree
.get(child.index())
.ok_or(TreeError::IndexOutOfBounds {
index: child.index(),
len: self.tree.len(),
})?;
if node.parent().is_some() {
return Err(TreeError::from(NodeError::ParentConflict {
parent: node.parent().unwrap().index(),
child: child.index(),
}));
}
}
Ok(())
}
fn compute_internal_hash(
&self,
children: &[NodeIndex<Ix>],
) -> Result<GenericArray<D>, TreeError> {
let mut child_hashes = Vec::with_capacity(children.len());
for &child in children {
let node = self
.tree
.get(child.index())
.expect("child already validated");
child_hashes.push(node.hash());
}
Ok(self.hasher.concat_slice(&child_hashes))
}
fn set_parent_relationships(&mut self, children: &[NodeIndex<Ix>], parent: NodeIndex<Ix>) {
for &child in children {
if let Some(node) = self.tree.nodes.get_mut(child.index()) {
node.parent = Some(parent);
}
}
}
fn validate_root(&self, root: NodeIndex<Ix>) -> Result<(), TreeError> {
let root_node = self
.tree
.get(root.index())
.ok_or(TreeError::IndexOutOfBounds {
index: root.index(),
len: self.tree.len(),
})?;
if !root_node.is_root() {
return Err(TreeError::InvalidOperation {
operation: "finish",
reason: "root node cannot have a parent".to_string(),
});
}
Ok(())
}
}
impl<T, D: Digest, Ix: IndexType> MrkleDefaultBuilder<T, D, Ix>
where
T: AsRef<[u8]> + Clone,
{
pub fn insert_leaf_data(&mut self, data: T) -> Result<NodeIndex<Ix>, TreeError> {
self.check_not_finalized()?;
Ok(self.tree.push(MrkleNode::<T, D, Ix>::leaf(data)))
}
pub fn insert_leaves<I>(&mut self, data_iter: I) -> Result<Vec<NodeIndex<Ix>>, TreeError>
where
T: Clone,
I: IntoIterator<Item = T>,
{
self.check_not_finalized()?;
data_iter
.into_iter()
.map(|data| self.insert_leaf_data(data))
.collect()
}
pub fn build_complete_tree_from_leaves(
&mut self,
mut leaves: Vec<NodeIndex<Ix>>,
) -> Result<NodeIndex<Ix>, MrkleError> {
self.check_not_finalized()?;
if leaves.is_empty() {
return Err(MrkleError::from(TreeError::InvalidOperation {
operation: "build_complete_tree_from_leaves",
reason: "cannot build tree from empty leaves vector".to_string(),
}));
}
if leaves.len() == 1 {
return self.insert_internal(leaves);
}
while leaves.len() > 1 {
let mut level = Vec::new();
for chunk in leaves.chunks(2) {
let internal = self.insert_internal(chunk.to_vec())?;
level.push(internal);
}
leaves = level;
}
Ok(leaves[0])
}
pub fn build_from_data<I>(data_iter: I) -> Result<MrkleTree<T, D, Ix>, MrkleError>
where
T: Clone,
I: IntoIterator<Item = T>,
{
let mut builder = Self::new();
let leaves = builder.insert_leaves(data_iter)?;
let root = builder.build_complete_tree_from_leaves(leaves)?;
builder.finish(root)
}
}
impl<T: AsRef<[u8]>, D: Digest, Ix: IndexType> MrkleDefaultBuilder<T, D, Ix> {
pub fn with_leaf(mut self, leaf: MrkleNode<T, D, Ix>) -> Result<Self, TreeError> {
self.insert_leaf(leaf)?;
Ok(self)
}
pub fn with_leaf_data(mut self, data: T) -> Result<Self, TreeError>
where
T: Clone,
{
self.insert_leaf_data(data)?;
Ok(self)
}
pub fn build_and_finish(mut self) -> Result<MrkleTree<T, D, Ix>, MrkleError>
where
T: Clone,
{
let leaves: Vec<NodeIndex<Ix>> = (0..self.tree.len())
.map(NodeIndex::new)
.filter(|&idx| {
self.tree
.get(idx.index())
.map(|node| node.parent().is_none())
.unwrap_or(false)
})
.collect();
let root = self.build_complete_tree_from_leaves(leaves)?;
self.finish(root)
}
}
#[cfg(test)]
mod tests {
use super::*;
use sha2::Sha256;
type TestBuilder = MrkleDefaultBuilder<Vec<u8>, Sha256, u32>;
#[test]
fn test_builder_basic_construction() -> Result<(), Box<dyn core::error::Error>> {
let mut builder = TestBuilder::new();
assert!(builder.is_empty());
assert!(!builder.is_finalized());
assert_eq!(builder.len(), 0);
let leaf1 = builder.insert_leaf_data(b"data1".to_vec()).unwrap();
let leaf2 = builder.insert_leaf_data(b"data2".to_vec()).unwrap();
assert_eq!(builder.len(), 2);
assert!(!builder.is_empty());
let root = builder.insert_internal(vec![leaf1, leaf2]).unwrap();
let tree = builder.finish(root).unwrap();
assert!(tree.root().is_root());
Ok(())
}
#[test]
fn test_builder_with_capacity() -> Result<(), Box<dyn core::error::Error>> {
let builder = TestBuilder::with_capacity(100);
assert!(builder.capacity() >= 100);
Ok(())
}
#[test]
fn test_batch_leaf_insertion() -> Result<(), Box<dyn core::error::Error>> {
let mut builder = TestBuilder::new();
let data = vec![b"a".to_vec(), b"b".to_vec(), b"c".to_vec(), b"d".to_vec()];
let leaves = builder.insert_leaves(data)?;
assert_eq!(leaves.len(), 4);
assert_eq!(builder.len(), 4);
Ok(())
}
#[test]
fn test_complete_tree_building() -> Result<(), Box<dyn core::error::Error>> {
let mut builder = TestBuilder::new();
let data = vec![b"a".to_vec(), b"b".to_vec(), b"c".to_vec(), b"d".to_vec()];
let leaves = builder.insert_leaves(data).unwrap();
let root = builder.build_complete_tree_from_leaves(leaves)?;
let tree = builder.finish(root)?;
assert!(tree.root().is_root());
assert_eq!(tree.len(), 7);
Ok(())
}
#[test]
fn test_build_from_data_convenience() -> Result<(), Box<dyn core::error::Error>> {
let data = vec![b"a".to_vec(), b"b".to_vec(), b"c".to_vec(), b"d".to_vec()];
let tree = TestBuilder::build_from_data(data)?;
assert!(tree.root().is_root());
assert_eq!(tree.len(), 7);
Ok(())
}
#[test]
fn test_method_chaining() -> Result<(), Box<dyn core::error::Error>> {
let tree = TestBuilder::new()
.with_leaf_data(b"data1".to_vec())?
.with_leaf_data(b"data2".to_vec())?
.with_leaf_data(b"data3".to_vec())?
.build_and_finish()?;
assert!(tree.root().is_root());
Ok(())
}
#[test]
fn test_validation() -> Result<(), Box<dyn core::error::Error>> {
let mut builder = TestBuilder::new();
let leaf1 = builder.insert_leaf_data(b"data1".to_vec())?;
let leaf2 = builder.insert_leaf_data(b"data2".to_vec())?;
let _root = builder.insert_internal(vec![leaf1, leaf2])?;
Ok(())
}
#[test]
fn test_finalization_prevents_modification() -> Result<(), Box<dyn core::error::Error>> {
let mut builder = TestBuilder::new();
let leaf = builder.insert_leaf_data(b"data".to_vec())?;
let root = builder.insert_internal(vec![leaf])?;
let _tree = builder.finish(root)?;
Ok(())
}
#[test]
fn test_error_conditions() -> Result<(), Box<dyn core::error::Error>> {
let mut builder = TestBuilder::new();
let result = builder.insert_internal(vec![]);
assert!(result.is_err());
let invalid_child = NodeIndex::new(999);
let result = builder.insert_internal(vec![invalid_child]);
assert!(result.is_err());
Ok(())
}
#[test]
fn test_parent_conflict_detection() -> Result<(), Box<dyn core::error::Error>> {
let mut builder = TestBuilder::new();
let leaf1 = builder.insert_leaf_data(b"data1".to_vec())?;
let leaf2 = builder.insert_leaf_data(b"data2".to_vec())?;
let _internal1 = builder.insert_internal(vec![leaf1, leaf2])?;
let result = builder.insert_internal(vec![leaf1]);
assert!(result.is_err());
Ok(())
}
}