1#![cfg_attr(not(feature = "std"), no_std)]
5#![warn(missing_docs)]
6
7#[cfg(not(feature = "std"))]
21extern crate alloc;
22#[cfg(not(feature = "std"))]
23use alloc::vec;
24#[cfg(not(feature = "std"))]
25use alloc::vec::Vec;
26
27use codec::{Decode, Encode};
28use scale_info::TypeInfo;
29use sp_core::{RuntimeDebug, H256};
30use sp_runtime::traits::Hash;
31
32pub fn merkle_root<H, I>(leaves: I) -> H256
38where
39 H: Hash<Output = H256>,
40 I: Iterator<Item = H256>,
41{
42 merkelize::<H, _, _>(leaves, &mut ())
43}
44
45fn merkelize<H, V, I>(leaves: I, visitor: &mut V) -> H256
46where
47 H: Hash<Output = H256>,
48 V: Visitor,
49 I: Iterator<Item = H256>,
50{
51 let upper = Vec::with_capacity(leaves.size_hint().0);
52 let mut next = match merkelize_row::<H, _, _>(leaves, upper, visitor) {
53 Ok(root) => return root,
54 Err(next) if next.is_empty() => return H256::default(),
55 Err(next) => next,
56 };
57
58 let mut upper = Vec::with_capacity(next.len().div_ceil(2));
59 loop {
60 visitor.move_up();
61
62 match merkelize_row::<H, _, _>(next.drain(..), upper, visitor) {
63 Ok(root) => return root,
64 Err(t) => {
65 upper = next;
67 next = t;
68 },
69 };
70 }
71}
72
73#[derive(Encode, Decode, RuntimeDebug, PartialEq, Eq, TypeInfo)]
77pub struct MerkleProof {
78 pub root: H256,
80 pub proof: Vec<H256>,
85 pub number_of_leaves: u64,
90 pub leaf_index: u64,
92 pub leaf: H256,
94}
95
96trait Visitor {
101 fn move_up(&mut self);
103
104 fn visit(&mut self, index: u64, left: &Option<H256>, right: &Option<H256>);
111}
112
113impl Visitor for () {
115 fn move_up(&mut self) {}
116 fn visit(&mut self, _index: u64, _left: &Option<H256>, _right: &Option<H256>) {}
117}
118
119pub fn merkle_proof<H, I>(leaves: I, leaf_index: u64) -> MerkleProof
130where
131 H: Hash<Output = H256>,
132 I: Iterator<Item = H256>,
133{
134 let mut leaf = None;
135 let mut hashes = vec![];
136 let mut number_of_leaves = 0;
137 for (idx, l) in (0u64..).zip(leaves) {
138 number_of_leaves = idx + 1;
140 hashes.push(l);
141 if idx == leaf_index {
143 leaf = Some(l);
144 }
145 }
146
147 struct ProofCollection {
149 proof: Vec<H256>,
150 position: u64,
151 }
152
153 impl ProofCollection {
154 fn new(position: u64) -> Self {
155 ProofCollection { proof: Default::default(), position }
156 }
157 }
158
159 impl Visitor for ProofCollection {
160 fn move_up(&mut self) {
161 self.position /= 2;
162 }
163
164 fn visit(&mut self, index: u64, left: &Option<H256>, right: &Option<H256>) {
165 if self.position == index {
167 if let Some(right) = right {
168 self.proof.push(*right);
169 }
170 }
171 if self.position == index + 1 {
173 if let Some(left) = left {
174 self.proof.push(*left);
175 }
176 }
177 }
178 }
179
180 let mut collect_proof = ProofCollection::new(leaf_index);
181
182 let root = merkelize::<H, _, _>(hashes.into_iter(), &mut collect_proof);
183 let leaf = leaf.expect("Requested `leaf_index` is greater than number of leaves.");
184
185 MerkleProof { root, proof: collect_proof.proof, number_of_leaves, leaf_index, leaf }
186}
187
188#[derive(Debug, PartialEq, Eq)]
193pub enum Leaf<'a> {
194 Value(&'a [u8]),
196 Hash(H256),
198}
199
200impl<'a, T: AsRef<[u8]>> From<&'a T> for Leaf<'a> {
201 fn from(v: &'a T) -> Self {
202 Leaf::Value(v.as_ref())
203 }
204}
205
206impl<'a> From<H256> for Leaf<'a> {
207 fn from(v: H256) -> Self {
208 Leaf::Hash(v)
209 }
210}
211
212pub fn verify_proof<'a, H, P, L>(
220 root: &'a H256,
221 proof: P,
222 number_of_leaves: u64,
223 leaf_index: u64,
224 leaf: L,
225) -> bool
226where
227 H: Hash<Output = H256>,
228 P: IntoIterator<Item = H256>,
229 L: Into<Leaf<'a>>,
230{
231 if leaf_index >= number_of_leaves {
232 return false
233 }
234
235 let leaf_hash = match leaf.into() {
236 Leaf::Value(content) => <H as Hash>::hash(content),
237 Leaf::Hash(hash) => hash,
238 };
239
240 let hash_len = <H as sp_core::Hasher>::LENGTH;
241 let mut combined = [0_u8; 64];
242 let computed = proof.into_iter().fold(leaf_hash, |a, b| {
243 if a < b {
244 combined[..hash_len].copy_from_slice(a.as_ref());
245 combined[hash_len..].copy_from_slice(b.as_ref());
246 } else {
247 combined[..hash_len].copy_from_slice(b.as_ref());
248 combined[hash_len..].copy_from_slice(a.as_ref());
249 }
250 <H as Hash>::hash(&combined)
251 });
252
253 root == &computed
254}
255
256fn merkelize_row<H, V, I>(
262 mut iter: I,
263 mut next: Vec<H256>,
264 visitor: &mut V,
265) -> Result<H256, Vec<H256>>
266where
267 H: Hash<Output = H256>,
268 V: Visitor,
269 I: Iterator<Item = H256>,
270{
271 next.clear();
272
273 let hash_len = <H as sp_core::Hasher>::LENGTH;
274 let mut index = 0;
275 let mut combined = vec![0_u8; hash_len * 2];
276 loop {
277 let a = iter.next();
278 let b = iter.next();
279 visitor.visit(index, &a, &b);
280
281 index += 2;
282 match (a, b) {
283 (Some(a), Some(b)) => {
284 if a < b {
285 combined[..hash_len].copy_from_slice(a.as_ref());
286 combined[hash_len..].copy_from_slice(b.as_ref());
287 } else {
288 combined[..hash_len].copy_from_slice(b.as_ref());
289 combined[hash_len..].copy_from_slice(a.as_ref());
290 }
291
292 next.push(<H as Hash>::hash(&combined));
293 },
294 (Some(a), None) if !next.is_empty() => {
296 next.push(a);
297 },
298 (Some(a), None) => return Ok(a),
300 _ => return Err(next),
302 }
303 }
304}
305
306#[cfg(test)]
307mod tests {
308 use super::*;
309 use hex_literal::hex;
310 use sp_crypto_hashing::keccak_256;
311 use sp_runtime::traits::Keccak256;
312
313 fn make_leaves(count: u64) -> Vec<H256> {
314 (0..count).map(|i| keccak_256(&i.to_le_bytes()).into()).collect()
315 }
316
317 #[test]
318 fn should_generate_empty_root() {
319 sp_tracing::init_for_tests();
321 let data = vec![];
322
323 let out = merkle_root::<Keccak256, _>(data.into_iter());
325
326 assert_eq!(
328 hex::encode(out),
329 "0000000000000000000000000000000000000000000000000000000000000000"
330 );
331 }
332
333 #[test]
334 fn should_generate_single_root() {
335 sp_tracing::init_for_tests();
337 let data = make_leaves(1);
338
339 let out = merkle_root::<Keccak256, _>(data.into_iter());
341
342 assert_eq!(
344 hex::encode(out),
345 "011b4d03dd8c01f1049143cf9c4c817e4b167f1d1b83e5c6f0f10d89ba1e7bce"
346 );
347 }
348
349 #[test]
350 fn should_generate_root_pow_2() {
351 sp_tracing::init_for_tests();
353 let data = make_leaves(2);
354
355 let out = merkle_root::<Keccak256, _>(data.into_iter());
357
358 assert_eq!(
360 hex::encode(out),
361 "e497bd1c13b13a60af56fa0d2703517c232fde213ad20d2c3dd60735c6604512"
362 );
363 }
364
365 #[test]
366 fn should_generate_root_complex() {
367 sp_tracing::init_for_tests();
368 let test = |root, data: Vec<H256>| {
369 assert_eq!(
370 array_bytes::bytes2hex("", merkle_root::<Keccak256, _>(data.into_iter()).as_ref()),
371 root
372 );
373 };
374
375 test("816cc37bd8d39f7b0851838ebc875faf2afe58a03e95aca3b1333b3693f39dd3", make_leaves(3));
376
377 test("7501ea976cb92f305cca65ab11254589ea28bb8b59d3161506350adaa237d22f", make_leaves(4));
378
379 test("d26ba4eb398747bdd39255b1fadb99b803ce39696021b3b0bff7301ac146ee4e", make_leaves(10));
380 }
381
382 #[test]
383 #[ignore]
384 fn should_generate_and_verify_proof() {
385 sp_tracing::init_for_tests();
387 let data: Vec<H256> = make_leaves(3);
388
389 let proof0 = merkle_proof::<Keccak256, _>(data.clone().into_iter(), 0);
391 assert!(verify_proof::<Keccak256, _, _>(
392 &proof0.root,
393 proof0.proof.clone(),
394 data.len() as u64,
395 proof0.leaf_index,
396 &data[0],
397 ));
398
399 let proof1 = merkle_proof::<Keccak256, _>(data.clone().into_iter(), 1);
400 assert!(verify_proof::<Keccak256, _, _>(
401 &proof1.root,
402 proof1.proof,
403 data.len() as u64,
404 proof1.leaf_index,
405 &proof1.leaf,
406 ));
407
408 let proof2 = merkle_proof::<Keccak256, _>(data.clone().into_iter(), 2);
409 assert!(verify_proof::<Keccak256, _, _>(
410 &proof2.root,
411 proof2.proof,
412 data.len() as u64,
413 proof2.leaf_index,
414 &proof2.leaf
415 ));
416
417 assert_eq!(hex::encode(proof0.root), hex::encode(proof1.root));
419 assert_eq!(hex::encode(proof2.root), hex::encode(proof1.root));
420
421 assert!(!verify_proof::<Keccak256, _, _>(
422 &H256::from_slice(&hex!(
423 "fb3b3be94be9e983ba5e094c9c51a7d96a4fa2e5d8e891df00ca89ba05bb1239"
424 )),
425 proof0.proof,
426 data.len() as u64,
427 proof0.leaf_index,
428 &proof0.leaf
429 ));
430
431 assert!(!verify_proof::<Keccak256, _, _>(
432 &proof0.root,
433 vec![],
434 data.len() as u64,
435 proof0.leaf_index,
436 &proof0.leaf
437 ));
438 }
439
440 #[test]
441 #[should_panic]
442 fn should_panic_on_invalid_leaf_index() {
443 sp_tracing::init_for_tests();
444 merkle_proof::<Keccak256, _>(make_leaves(1).into_iter(), 5);
445 }
446}