1use sha2::{Digest, Sha256};
2use sha3::Keccak256;
3
4pub type MerkleTreeData = Vec<u8>;
5pub type MerkleTreeHash = [u8; 32];
6pub type MerkleTreeProof = Vec<MerkleTreeHash>;
7
8#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
9pub struct MerkleTreeRoot {
10 pub hash: MerkleTreeHash,
11}
12
13pub struct MerkleTree {
14 pub root: MerkleTreeRoot,
15 pub proofs: Vec<MerkleTreeProof>,
16}
17
18impl MerkleTreeRoot {
19 pub fn new(hash: MerkleTreeHash) -> Self {
20 MerkleTreeRoot { hash }
21 }
22
23 pub fn verify(&self, data: &MerkleTreeData, proof: &MerkleTreeProof) -> bool {
24 let mut hash = keccak256_array(data);
25 for second_hash in proof {
26 let s = serde_json::to_vec(&sort_hash_pair(&hash, second_hash)).unwrap();
27 hash = keccak256_array(&s);
28 }
29 self.hash == hash
30 }
31}
32
33pub fn keccak256_array(data: &[u8]) -> MerkleTreeHash {
34 let mut hasher = Keccak256::new();
35 hasher.update(data);
36 let result = hasher.finalize();
37 let mut output = [0u8; 32];
38 output.copy_from_slice(&result);
39 output
40}
41
42pub fn sort_hash_pair(
43 first: &MerkleTreeHash,
44 second: &MerkleTreeHash,
45) -> (MerkleTreeHash, MerkleTreeHash) {
46 if first < second {
47 (first.clone(), second.clone())
48 } else {
49 (second.clone(), first.clone())
50 }
51}
52
53impl MerkleTree {
54 pub fn build(items: &Vec<MerkleTreeData>) -> Self {
55 let items_len = items.len();
56
57 let mut items = items.clone();
58
59 let mut st_sum = 0_usize;
60 let mut st = 1_usize;
61
62 while st < items.len() {
63 st_sum += st;
64
65 st <<= 1;
66 }
67
68 while items.len() < st_sum + st {
69 items.push(MerkleTreeData::new());
70 }
71
72 let mut nodes = vec![[0_u8; 32]; st_sum + st];
73
74 for i in st_sum..st_sum + st {
75 nodes[i] = keccak256_array(&items[i - st_sum]);
76 }
77
78 let mut i = st_sum.clone();
79
80 while i > 0 {
81 i -= 1;
82
83 let s = serde_json::to_vec(&sort_hash_pair(&nodes[(i << 1) + 1], &nodes[(i + 1) << 1]))
84 .unwrap();
85
86 nodes[i] = keccak256_array(&s);
87 }
88
89 let get_proof = |index: usize| -> MerkleTreeProof {
90 let mut result = MerkleTreeProof::new();
91
92 let mut v = index + st_sum;
93
94 while v > 0 {
95 let w = if v % 2 == 0 { v - 1 } else { v + 1 };
96
97 result.push(nodes[w]);
98
99 v = (v - 1) >> 1;
100 }
101
102 result
103 };
104
105 let mut proofs: Vec<MerkleTreeProof> = Vec::new();
106
107 for i in 0..items_len {
108 proofs.push(get_proof(i))
109 }
110
111 MerkleTree {
112 root: MerkleTreeRoot::new(nodes[0]),
113 proofs,
114 }
115 }
116}
117
118pub fn string_to_crypto_hash(input: &str) -> MerkleTreeHash {
119 let mut hasher = Sha256::new();
120 hasher.update(input);
121 let result = hasher.finalize();
122 let mut crypto_hash: MerkleTreeHash = [0u8; 32];
123 crypto_hash.copy_from_slice(&result);
124
125 crypto_hash
126}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131
132 #[test]
133 pub fn correct_proofs() {
134 let mut items = Vec::<MerkleTreeData>::new();
135
136 for i in 0..8 {
137 items.push(vec![i]);
138 }
139
140 let merkle_tree = MerkleTree::build(&items);
141
142 assert_eq!(merkle_tree.proofs.len(), 8);
143
144 for proof in merkle_tree.proofs {
145 assert_eq!(proof.len(), 3);
146 }
147 }
148
149 #[test]
150 pub fn verify_correct_data() {
151 let mut items = Vec::<MerkleTreeData>::new();
152
153 for i in 0..4 {
154 items.push(vec![i]);
155 }
156
157 let merkle_tree = MerkleTree::build(&items);
158 println!("root - {:?}", merkle_tree.root);
159 println!("proof - {:?} --- {:?}", merkle_tree.proofs[0], items[0]);
160
161 for i in 0..items.len() {
162 assert!(merkle_tree.root.verify(&items[i], &merkle_tree.proofs[i]));
163 }
164 }
165
166 #[test]
167 pub fn verify_incorrect_data() {
168 let mut items = Vec::<MerkleTreeData>::new();
169
170 for i in 0..4 {
171 items.push(vec![i]);
172 }
173
174 let merkle_tree = MerkleTree::build(&items);
175
176 assert!(!merkle_tree.root.verify(&items[0], &merkle_tree.proofs[2]));
177 }
178
179 #[test]
180 fn test_make_crypt_hash() {
181 let s = "abcd".to_string();
182 for x in 0..10 {
183 let stx = format!("{}:{}", x, &s);
184 let hash = string_to_crypto_hash(&stx);
185 println!("hash - 0x{}", hex::encode(hash));
186 }
187 }
188}
189
190#[test]
191fn testx() {
192 let s = "abcd";
193 let hash = keccak256_array(s.as_bytes());
194 println!("h--{:?} ", hash);
195}