Skip to content

Commit

Permalink
Outline algos::compute_depth
Browse files Browse the repository at this point in the history
  • Loading branch information
DrChat committed Jan 1, 2025
1 parent 40f2eca commit f2ded02
Showing 1 changed file with 30 additions and 19 deletions.
49 changes: 30 additions & 19 deletions atrium-repo/src/mst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,31 @@ mod algos {
Stop(R),
}

/// Compute the depth of the specified node.
///
/// If both the node and its nested subtrees do not contain leaves, this will return `None`.
pub async fn compute_depth(
mut bs: impl AsyncBlockStoreRead,
node: Cid,
) -> Result<Option<usize>, Error> {
// Recursively iterate through the tree until we encounter a leaf node, and then
// use that to calculate the depth of the entire tree.
let mut subtrees = vec![(node, 0usize)];

loop {
if let Some((subtree, depth)) = subtrees.pop() {
let node = Node::read_from(&mut bs, subtree).await?;
if let Some(layer) = node.layer() {
return Ok(Some(depth + layer));
}

subtrees.extend(node.trees().cloned().zip(std::iter::repeat(depth + 1)));
} else {
return Ok(None);
}
}
}

/// Traverse a merkle search tree.
///
/// This executes the closure provided in `f` and takes the action
Expand Down Expand Up @@ -385,7 +410,7 @@ impl<S: AsyncBlockStoreRead + AsyncBlockStoreWrite> Tree<S> {
// 2) The target layer is contained within the tree (and we will traverse to find it).
// 3) The tree is currently empty (trivial).
let mut node = match self.depth(None).await {
Ok(layer) => {
Ok(Some(layer)) => {
match layer.cmp(&target_layer) {
// The new key can be inserted into the root node.
Ordering::Equal => Node::read_from(&mut self.storage, node_cid).await?,
Expand Down Expand Up @@ -458,7 +483,7 @@ impl<S: AsyncBlockStoreRead + AsyncBlockStoreWrite> Tree<S> {
}
}
}
Err(Error::EmptyTree) => {
Ok(None) => {
// The tree is currently empty.
Node { entries: vec![] }
}
Expand Down Expand Up @@ -632,23 +657,8 @@ impl<S: AsyncBlockStoreRead> Tree<S> {
}

/// Compute the depth of the merkle search tree from either the specified node or the root
pub async fn depth(&mut self, node: Option<Cid>) -> Result<usize, Error> {
// Recursively iterate through the tree until we encounter a leaf node, and then
// use that to calculate the depth of the entire tree.
let mut subtrees = vec![(node.unwrap_or(self.root), 0usize)];

loop {
if let Some((subtree, depth)) = subtrees.pop() {
let node = Node::read_from(&mut self.storage, subtree).await?;
if let Some(layer) = node.layer() {
return Ok(depth + layer);
}

subtrees.extend(node.trees().cloned().zip(std::iter::repeat(depth + 1)));
} else {
return Err(Error::EmptyTree);
}
}
pub async fn depth(&mut self, node: Option<Cid>) -> Result<Option<usize>, Error> {
algos::compute_depth(&mut self.storage, node.unwrap_or(self.root)).await
}

/// Returns a stream of all entries in this tree, in lexicographic order.
Expand Down Expand Up @@ -994,6 +1004,7 @@ pub enum Error {
mod test {
use std::str::FromStr;

use futures::TryStreamExt;
use ipld_core::cid::multihash::Multihash;

use crate::blockstore::{MemoryBlockStore, SHA2_256};
Expand Down

0 comments on commit f2ded02

Please sign in to comment.