algae_merkle/
utils.rs

1/*
2    Appellation: generate <utils>
3    Contrib: FL03 <jo3mccain@icloud.com>
4    Description:
5*/
6use crate::proofs::proof_path;
7use crate::{MerkleDimension, MerkleShape};
8use decanter::prelude::{hasher, Hashable, H256};
9
10/// Combines two hashes into a single hash
11pub fn add_hash(a: &H256, b: &H256) -> H256 {
12    let c = [a.as_ref(), b.as_ref()].concat();
13    let combined = ring::digest::digest(&ring::digest::SHA256, &c);
14    hasher(combined).into()
15}
16/// Merges two hashes into a string
17pub fn combine_hash_str<T: ToString>(a: &T, b: &T) -> String {
18    format!("{}{}", a.to_string(), b.to_string())
19}
20/// Creates a Merkle tree from a slice of data
21pub fn create_merkle_tree<T>(data: &[T]) -> (Box<dyn MerkleShape>, Vec<H256>)
22where
23    T: Hashable,
24{
25    let mut length = data.len();
26    let mut nodes = Vec::new();
27    let mut last_level = Vec::new();
28    for i in data {
29        let h: H256 = i.hash();
30        last_level.push(h);
31        nodes.push(h);
32    }
33    let mut depth = 1;
34    while length > 1 {
35        if length % 2 != 0 {
36            last_level.push(data[length - 1].hash());
37            nodes.push(data[length - 1].hash());
38            length += 1;
39        }
40        let mut temp = Vec::new();
41        for i in 0..length / 2 {
42            let h: H256 = add_hash(&last_level[2 * i], &last_level[2 * i + 1]);
43            temp.push(h);
44            nodes.push(h);
45        }
46        last_level = temp.clone();
47        length /= 2;
48        depth += 1;
49    }
50    let dim = MerkleDimension::new(depth, data.len(), nodes.len());
51    (Box::new(dim), nodes)
52}
53
54/// Takes the hash of the given information to the second degree
55pub fn merkle_hash(data: impl AsRef<[u8]>) -> H256 {
56    let tmp: H256 = hasher(data).into();
57    hasher(&tmp).into()
58}
59
60/// Verify that the datum hash with a vector of proofs will produce the Merkle root. Also need the
61/// index of datum and `leaf_size`, the total number of leaves.
62pub fn is_merkle_valid(
63    root: &H256,
64    datum: &H256,
65    proof: &[H256],
66    index: usize,
67    leaf_size: usize,
68) -> bool {
69    let mut h: H256 = *datum;
70    let proof_index = proof_path(index, leaf_size);
71    for i in 0..proof.len() {
72        if proof_index[i] % 2 == 0 {
73            h = add_hash(&proof[i], &h);
74        } else {
75            h = add_hash(&h, &proof[i]);
76        }
77    }
78    *root == h
79}