oasis_core_runtime/storage/mkvs/sync/
merge.rs

1use anyhow::{anyhow, Result};
2
3use crate::storage::mkvs::tree::*;
4
5/// Merges a previously verified subtree with an existing tree.
6pub fn merge_verified_subtree(
7    dst: NodePtrRef,
8    subtree: NodePtrRef,
9    updater: &mut Vec<NodePtrRef>,
10) -> Result<()> {
11    let dst_ref = dst;
12    let mut dst = dst_ref.borrow_mut();
13    let subtree = subtree.borrow();
14    if dst.is_null() || subtree.is_null() {
15        return Ok(());
16    }
17
18    if !dst.clean {
19        // TODO: Support merging into non-clean subtrees. If a subtree
20        //       is not clean, this means that the tree structure may
21        //       be changed.
22        return Err(anyhow!(
23            "merger: merging into non-clean subtree not yet supported"
24        ));
25    }
26
27    // If the destination pointer is clean, sanity check that we are
28    // merging correct nodes.
29    if dst.hash != subtree.hash {
30        return Err(anyhow!(
31            "merger: hash mismatch during merge (expected: {:?} got: {:?})",
32            dst.hash,
33            subtree.hash,
34        ));
35    }
36
37    // If the subtree node is nil, there is nothing more to merge.
38    if subtree.node.is_none() {
39        return Ok(());
40    }
41
42    // If destination node is nil, we can simply replace the whole subtree.
43    if dst.node.is_none() {
44        dst.node = subtree.node.clone();
45        drop(dst);
46        updater.push(dst_ref);
47        return Ok(());
48    }
49
50    if let NodeBox::Internal(ref int_dst) = *dst.node.as_ref().unwrap().borrow() {
51        if let NodeBox::Internal(ref int_subtree) = *subtree.node.as_ref().unwrap().borrow() {
52            // Proceed with merging children.
53            merge_verified_subtree(int_dst.left.clone(), int_subtree.left.clone(), updater)?;
54            merge_verified_subtree(int_dst.right.clone(), int_subtree.right.clone(), updater)?;
55        } else {
56            panic!("hash was the same so nodes must be of the same type");
57        }
58    }
59
60    Ok(())
61}