spl_concurrent_merkle_tree/
hash.rs

1use {
2    crate::node::{empty_node, Node},
3    solana_program::keccak::hashv,
4};
5
6/// Recomputes root of the Merkle tree from Node & proof
7pub fn recompute(leaf: Node, proof: &[Node], index: u32) -> Node {
8    let mut current_node = leaf;
9    for (depth, sibling) in proof.iter().enumerate() {
10        hash_to_parent(&mut current_node, sibling, index >> depth & 1 == 0);
11    }
12    current_node
13}
14
15/// Computes the parent node of `node` and `sibling` and copies the result into
16/// `node`
17#[inline(always)]
18pub fn hash_to_parent(node: &mut Node, sibling: &Node, is_left: bool) {
19    let parent = if is_left {
20        hashv(&[node, sibling])
21    } else {
22        hashv(&[sibling, node])
23    };
24    node.copy_from_slice(parent.as_ref())
25}
26
27/// Fills in proof to the height of the concurrent merkle tree.
28/// Missing nodes are inferred as empty node hashes.
29pub fn fill_in_proof<const MAX_DEPTH: usize>(
30    proof_vec: &[Node],
31    full_proof: &mut [Node; MAX_DEPTH],
32) {
33    solana_logging!("Attempting to fill in proof");
34    if !proof_vec.is_empty() {
35        full_proof[..proof_vec.len()].copy_from_slice(proof_vec);
36    }
37
38    for (i, item) in full_proof
39        .iter_mut()
40        .enumerate()
41        .take(MAX_DEPTH)
42        .skip(proof_vec.len())
43    {
44        *item = empty_node(i as u32);
45    }
46}