spl_concurrent_merkle_tree/
node.rs

1use solana_program::keccak::hashv;
2
3/// Abstract type for 32 byte leaf data
4pub type Node = [u8; 32];
5
6/// An empty node is a 32 byte array of zeroes
7pub const EMPTY: Node = [0_u8; 32];
8
9/// Calculates the hash of empty nodes up to level i
10pub fn empty_node(level: u32) -> Node {
11    empty_node_cached::<0>(level, &[])
12}
13
14/// Calculates the hash of empty nodes up to level i using an existing cache
15pub fn empty_node_cached<const N: usize>(level: u32, cache: &[Node; N]) -> Node {
16    let mut data = EMPTY;
17    if level != 0 {
18        let target = (level - 1) as usize;
19        let lower_empty = if target < cache.len() && cache[target] != EMPTY {
20            cache[target]
21        } else {
22            empty_node(target as u32)
23        };
24        let hash = hashv(&[lower_empty.as_ref(), lower_empty.as_ref()]);
25        data.copy_from_slice(hash.as_ref());
26    }
27    data
28}
29
30/// Calculates and caches the hash of empty nodes up to level i
31pub fn empty_node_cached_mut<const N: usize>(level: u32, cache: &mut [Node; N]) -> Node {
32    let mut data = EMPTY;
33    if level != 0 {
34        let target = (level - 1) as usize;
35        let lower_empty = if target < cache.len() && cache[target] != EMPTY {
36            cache[target]
37        } else {
38            empty_node(target as u32)
39        };
40        let hash = hashv(&[lower_empty.as_ref(), lower_empty.as_ref()]);
41        data.copy_from_slice(hash.as_ref());
42    }
43    cache[level as usize] = data;
44    data
45}