Skip to content

Commit

Permalink
Remove path again
Browse files Browse the repository at this point in the history
  • Loading branch information
richardpringle committed Nov 21, 2023
1 parent d31155e commit f12df2b
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 113 deletions.
149 changes: 44 additions & 105 deletions firewood/src/merkle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl<S: ShaleStore<Node> + Send + Sync> Merkle<S> {
self.store
.put_item(
Node::branch(BranchNode {
path: vec![].into(),
// path: vec![].into(),
children: [None; MAX_CHILDREN],
value: None,
children_encoded: Default::default(),
Expand Down Expand Up @@ -167,18 +167,17 @@ impl<S: ShaleStore<Node> + Send + Sync> Merkle<S> {
Ok(())
}

// TODO: replace `split` with a `split_at` function. Handle the logic for matching paths in `insert` instead.
#[allow(clippy::too_many_arguments)]
fn split<'a>(
&'a self,
mut node_to_split: ObjRef<'a>,
parents: &mut [(ObjRef<'a>, u8)],
fn split(
&self,
mut node_to_split: ObjRef,
parents: &mut [(ObjRef, u8)],
insert_path: &[u8],
n_path: Vec<u8>,
n_value: Option<Data>,
val: Vec<u8>,
deleted: &mut Vec<DiskAddress>,
) -> Result<Option<(ObjRef<'a>, Vec<u8>)>, MerkleError> {
) -> Result<Option<Vec<u8>>, MerkleError> {
let node_to_split_address = node_to_split.as_ptr();
let split_index = insert_path
.iter()
Expand Down Expand Up @@ -218,19 +217,30 @@ impl<S: ShaleStore<Node> + Send + Sync> Merkle<S> {
chd[n_path[idx] as usize] = Some(address);

let new_branch = Node::branch(BranchNode {
path: PartialPath(matching_path[..idx].to_vec()),
// path: PartialPath(matching_path[..idx].to_vec()),
children: chd,
value: None,
children_encoded: Default::default(),
});

self.put_node(new_branch)?.as_ptr()
let new_branch_address = self.put_node(new_branch)?.as_ptr();

if idx > 0 {
self.put_node(Node::from(NodeType::Extension(ExtNode {
path: PartialPath(matching_path[..idx].to_vec()),
child: new_branch_address,
child_encoded: None,
})))?
.as_ptr()
} else {
new_branch_address
}
} else {
// paths do not diverge
let (leaf_address, prefix, idx, value) =
match (insert_path.len().cmp(&n_path.len()), n_value) {
// no node-value means this is an extension node and we can therefore continue walking the tree
(Ordering::Greater, None) => return Ok(Some((node_to_split, val))),
(Ordering::Greater, None) => return Ok(Some(val)),

// if the paths are equal, we overwrite the data
(Ordering::Equal, _) => {
Expand Down Expand Up @@ -270,9 +280,7 @@ impl<S: ShaleStore<Node> + Send + Sync> Merkle<S> {
result = Err(e);
}
}
NodeType::Branch(u) => {
u.value = Some(Data(val));
}
NodeType::Branch(_) => unreachable!(),
}

u.rehash();
Expand Down Expand Up @@ -338,13 +346,24 @@ impl<S: ShaleStore<Node> + Send + Sync> Merkle<S> {

children[idx] = leaf_address.into();

self.put_node(Node::branch(BranchNode {
path: PartialPath(prefix.to_vec()),
children,
value,
children_encoded: Default::default(),
}))?
.as_ptr()
let branch_address = self
.put_node(Node::branch(BranchNode {
children,
value,
children_encoded: Default::default(),
}))?
.as_ptr();

if !prefix.is_empty() {
self.put_node(Node::from(NodeType::Extension(ExtNode {
path: PartialPath(prefix.to_vec()),
child: branch_address,
child_encoded: None,
})))?
.as_ptr()
} else {
branch_address
}
};

// observation:
Expand Down Expand Up @@ -430,7 +449,7 @@ impl<S: ShaleStore<Node> + Send + Sync> Merkle<S> {
break None;
}

NodeType::Branch(n) if n.path.len() == 0 => {
NodeType::Branch(n) => {
match n.children[current_nibble as usize] {
Some(c) => (node, c),
None => {
Expand All @@ -455,62 +474,6 @@ impl<S: ShaleStore<Node> + Send + Sync> Merkle<S> {
}
}

NodeType::Branch(n) => {
let n_path = n.path.to_vec();
let rem_path = once(current_nibble)
.chain(key_nibbles.clone())
.collect::<Vec<_>>();
let n_path_len = n_path.len();
let n_value = n.value.clone();

// TODO: don't always call split if the paths match (avoids an allocation)
if let Some((mut node, v)) = self.split(
node,
&mut parents,
&rem_path,
n_path,
n_value,
val,
&mut deleted,
)? {
(0..n_path_len).for_each(|_| {
key_nibbles.next();
});

val = v;

let next_nibble = rem_path[n_path_len] as usize;
// we're already in the match-arm that states that this was a branch-node
// TODO: cleaning up the split-logic should fix this awkwardness
let n_ptr = node.inner.as_branch().unwrap().children[next_nibble];

match n_ptr {
Some(n_ptr) => (self.get_node(n_ptr)?, n_ptr),
None => {
// insert the leaf to the empty slot
// create a new leaf
let leaf_ptr = self
.put_node(Node::leaf(
PartialPath(key_nibbles.collect()),
Data(val),
))?
.as_ptr();
// set the current child to point to this leaf
node.write(|u| {
let uu = u.inner.as_branch_mut().unwrap();
uu.children[next_nibble] = Some(leaf_ptr);
u.rehash();
})
.unwrap();

break None;
}
}
} else {
break None;
}
}

NodeType::Extension(n) => {
let n_path = n.path.to_vec();
let n_ptr = n.chd();
Expand All @@ -519,7 +482,7 @@ impl<S: ShaleStore<Node> + Send + Sync> Merkle<S> {
.collect::<Vec<_>>();
let n_path_len = n_path.len();

if let Some((_ext_node, v)) = self.split(
if let Some(v) = self.split(
node,
&mut parents,
&rem_path,
Expand Down Expand Up @@ -613,7 +576,7 @@ impl<S: ShaleStore<Node> + Send + Sync> Merkle<S> {

let branch = self
.put_node(Node::branch(BranchNode {
path: vec![].into(),
// path: vec![].into(),
children: chd,
value: Some(Data(val)),
children_encoded: Default::default(),
Expand Down Expand Up @@ -1047,34 +1010,10 @@ impl<S: ShaleStore<Node> + Send + Sync> Merkle<S> {
};

let next_ptr = match &node_ref.inner {
NodeType::Branch(n) if n.path.len() == 0 => match n.children[nib as usize] {
NodeType::Branch(n) => match n.children[nib as usize] {
Some(c) => c,
None => return Ok(None),
},
NodeType::Branch(n) => {
let mut n_path_iter = n.path.iter().copied();

if n_path_iter.next() != Some(nib) {
return Ok(None);
}

let path_matches = n_path_iter
.map(Some)
.all(|n_path_nibble| key_nibbles.next() == n_path_nibble);

if !path_matches {
return Ok(None);
}

let Some(nib) = key_nibbles.next() else {
break;
};

match n.children[nib as usize] {
Some(c) => c,
None => return Ok(None),
}
}
NodeType::Leaf(n) => {
let node_ref = if once(nib).chain(key_nibbles).eq(n.path.iter().copied()) {
Some(node_ref)
Expand Down Expand Up @@ -1758,7 +1697,7 @@ mod tests {
}

Node::branch(BranchNode {
path: vec![].into(),
// path: vec![].into(),
children,
value,
children_encoded,
Expand Down
8 changes: 4 additions & 4 deletions firewood/src/merkle/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ impl NodeType {

pub fn path_mut(&mut self) -> &mut PartialPath {
match self {
NodeType::Branch(u) => &mut u.path,
NodeType::Branch(_u) => todo!(),
NodeType::Leaf(node) => &mut node.path,
NodeType::Extension(node) => &mut node.path,
}
Expand Down Expand Up @@ -208,7 +208,7 @@ impl Node {
is_encoded_longer_than_hash_len: OnceLock::new(),
encoded: OnceLock::new(),
inner: NodeType::Branch(BranchNode {
path: vec![].into(),
// path: vec![].into(),
children: [Some(DiskAddress::null()); MAX_CHILDREN],
value: Some(Data(Vec::new())),
children_encoded: Default::default(),
Expand Down Expand Up @@ -385,7 +385,7 @@ impl Storable for Node {
root_hash,
is_encoded_longer_than_hash_len,
NodeType::Branch(BranchNode {
path: vec![].into(),
// path: vec![].into(),
children: chd,
value,
children_encoded: chd_encoded,
Expand Down Expand Up @@ -667,7 +667,7 @@ pub(super) mod tests {
.unwrap_or_default();

Node::branch(BranchNode {
path: vec![].into(),
// path: vec![].into(),
children,
value: value.map(Data),
children_encoded,
Expand Down
8 changes: 4 additions & 4 deletions firewood/src/merkle/node/branch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub const SIZE: usize = MAX_CHILDREN + 1;

#[derive(PartialEq, Eq, Clone)]
pub struct BranchNode {
pub(crate) path: PartialPath,
// pub(crate) path: PartialPath,
pub(crate) children: [Option<DiskAddress>; MAX_CHILDREN],
pub(crate) value: Option<Data>,
pub(crate) children_encoded: [Option<Vec<u8>>; MAX_CHILDREN],
Expand All @@ -27,7 +27,7 @@ pub struct BranchNode {
impl Debug for BranchNode {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
write!(f, "[Branch")?;
write!(f, " path={:?}", self.path)?;
// write!(f, " path={:?}", self.path)?;

for (i, c) in self.children.iter().enumerate() {
if let Some(c) = c {
Expand All @@ -54,13 +54,13 @@ impl Debug for BranchNode {

impl BranchNode {
pub fn new(
path: PartialPath,
_path: PartialPath,
chd: [Option<DiskAddress>; MAX_CHILDREN],
value: Option<Vec<u8>>,
chd_encoded: [Option<Vec<u8>>; MAX_CHILDREN],
) -> Self {
BranchNode {
path,
// path,
children: chd,
value: value.map(Data),
children_encoded: chd_encoded,
Expand Down

0 comments on commit f12df2b

Please sign in to comment.