snowbridge_beacon_primitives/
merkle_proof.rs1use sp_core::H256;
4use sp_io::hashing::sha2_256;
5
6pub fn verify_merkle_branch(
9 leaf: H256,
10 branch: &[H256],
11 index: usize,
12 depth: usize,
13 root: H256,
14) -> bool {
15 if branch.len() != depth {
17 return false
18 }
19 root == compute_merkle_root(leaf, branch, index)
21}
22
23fn compute_merkle_root(leaf: H256, proof: &[H256], index: usize) -> H256 {
24 let mut value: [u8; 32] = leaf.into();
25 for (i, node) in proof.iter().enumerate() {
26 let mut data = [0u8; 64];
27 if generalized_index_bit(index, i) {
28 data[0..32].copy_from_slice(node.as_bytes());
30 data[32..64].copy_from_slice(&value);
31 value = sha2_256(&data);
32 } else {
33 data[0..32].copy_from_slice(&value);
35 data[32..64].copy_from_slice(node.as_bytes());
36 value = sha2_256(&data);
37 }
38 }
39 value.into()
40}
41
42fn generalized_index_bit(index: usize, position: usize) -> bool {
44 index & (1 << position) > 0
45}
46
47pub const fn subtree_index(generalized_index: usize) -> usize {
49 generalized_index % (1 << generalized_index_length(generalized_index))
50}
51
52pub const fn generalized_index_length(generalized_index: usize) -> usize {
54 match generalized_index.checked_ilog2() {
55 Some(v) => v as usize,
56 None => panic!("checked statically; qed"),
57 }
58}