pub(crate) fn create_proof(
        &mut self,
        hasher: &mut HasherWithStats<'_>,
        key: Key,
        parent_nibbles: &Nibbles,
        root_nibble_count: usize,
    ) -> (Option<LeafNode>, MerklePath) {
        let traverse_outcome = self.traverse(key, parent_nibbles);
        let merkle_path = match traverse_outcome {
            TraverseOutcome::MissingChild(_) | TraverseOutcome::LeafMatch(..) => None,
            TraverseOutcome::LeafMismatch(nibbles, leaf) => {
                // Find the level at which `leaf.full_key` and `key` diverge.
                // Note the addition of 1; e.g., if the keys differ at 0th bit, they
                // differ at level 1 of the tree.
                let diverging_level = utils::find_diverging_bit(key, leaf.full_key) + 1;
                let nibble_count = nibbles.nibble_count();
                debug_assert!(diverging_level > 4 * nibble_count);
                let mut path = MerklePath::new(diverging_level);
                // Find the hash of the existing `leaf` at the level, and include it
                // as the first hash on the Merkle path.
                let adjacent_hash = leaf.hash(hasher, diverging_level);
                path.push(hasher, Some(adjacent_hash));
                // Fill the path with empty hashes until we've reached the leaf level.
                for _ in (4 * nibble_count + 1)..diverging_level {
                    path.push(hasher, None);
                }
                Some(path)
            }
        };

        let mut nibbles = traverse_outcome.position();
        let leaf_level = nibbles.nibble_count() * 4;
        debug_assert!(leaf_level >= root_nibble_count);

        let mut merkle_path = merkle_path.unwrap_or_else(|| MerklePath::new(leaf_level));
        while let Some((parent_nibbles, last_nibble)) = nibbles.split_last() {
            if parent_nibbles.nibble_count() < root_nibble_count {
                break;
            }

            let parent = self.get_mut(&parent_nibbles);
            let Some(Node::Internal(parent)) = parent else {
                unreachable!()
            };
            let parent_level = parent_nibbles.nibble_count() * 4;
            parent
                .updater(hasher, parent_level, last_nibble)
                .extend_merkle_path(&mut merkle_path);
            nibbles = parent_nibbles;
        }

        let leaf = match traverse_outcome {
            TraverseOutcome::MissingChild(_) | TraverseOutcome::LeafMismatch(..) => None,
            TraverseOutcome::LeafMatch(_, leaf) => Some(leaf),
        };
        (leaf, merkle_path)
    }
Creates a Merkle proof for the specified `key`, which has given `parent_nibbles`
in this patch set. `root_nibble_count` specifies to which level the proof needs to be constructed.
core/lib/merkle_tree/src/storage/patch.rs