referrerpolicy=no-referrer-when-downgrade

snowbridge_merkle_tree/
lib.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
3// SPDX-FileCopyrightText: 2021-2022 Parity Technologies (UK) Ltd.
4#![cfg_attr(not(feature = "std"), no_std)]
5#![warn(missing_docs)]
6
7//! This crate implements a simple binary Merkle Tree utilities required for inter-op with Ethereum
8//! bridge & Solidity contract.
9//!
10//! The implementation is optimised for usage within Substrate Runtime and supports no-std
11//! compilation targets.
12//!
13//! Merkle Tree is constructed from arbitrary-length leaves, that are initially hashed using the
14//! same `\[`Hasher`\]` as the inner nodes.
15//! Inner nodes are created by concatenating child hashes and hashing again. The implementation
16//! does not perform any sorting of the input data (leaves) nor when inner nodes are created.
17//!
18//! If the number of leaves is not even, last leaf (hash of) is promoted to the upper layer.
19
20#[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
32/// Construct a root hash of a Binary Merkle Tree created from given leaves.
33///
34/// See crate-level docs for details about Merkle Tree construction.
35///
36/// In case an empty list of leaves is passed the function returns a 0-filled hash.
37pub 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				// swap collections to avoid allocations
66				upper = next;
67				next = t;
68			},
69		};
70	}
71}
72
73/// A generated merkle proof.
74///
75/// The structure contains all necessary data to later on verify the proof and the leaf itself.
76#[derive(Encode, Decode, RuntimeDebug, PartialEq, Eq, TypeInfo)]
77pub struct MerkleProof {
78	/// Root hash of generated merkle tree.
79	pub root: H256,
80	/// Proof items (does not contain the leaf hash, nor the root obviously).
81	///
82	/// This vec contains all inner node hashes necessary to reconstruct the root hash given the
83	/// leaf hash.
84	pub proof: Vec<H256>,
85	/// Number of leaves in the original tree.
86	///
87	/// This is needed to detect a case where we have an odd number of leaves that "get promoted"
88	/// to upper layers.
89	pub number_of_leaves: u64,
90	/// Index of the leaf the proof is for (0-based).
91	pub leaf_index: u64,
92	/// Leaf content (hashed).
93	pub leaf: H256,
94}
95
96/// A trait of object inspecting merkle root creation.
97///
98/// It can be passed to [`merkelize_row`] or [`merkelize`] functions and will be notified
99/// about tree traversal.
100trait Visitor {
101	/// We are moving one level up in the tree.
102	fn move_up(&mut self);
103
104	/// We are creating an inner node from given `left` and `right` nodes.
105	///
106	/// Note that in case of last odd node in the row `right` might be empty.
107	/// The method will also visit the `root` hash (level 0).
108	///
109	/// The `index` is an index of `left` item.
110	fn visit(&mut self, index: u64, left: &Option<H256>, right: &Option<H256>);
111}
112
113/// No-op implementation of the visitor.
114impl Visitor for () {
115	fn move_up(&mut self) {}
116	fn visit(&mut self, _index: u64, _left: &Option<H256>, _right: &Option<H256>) {}
117}
118
119/// Construct a Merkle Proof for leaves given by indices.
120///
121/// The function constructs a (partial) Merkle Tree first and stores all elements required
122/// to prove the requested item (leaf) given the root hash.
123///
124/// Both the Proof and the Root Hash are returned.
125///
126/// # Panic
127///
128/// The function will panic if given `leaf_index` is greater than the number of leaves.
129pub 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		// count the leaves
139		number_of_leaves = idx + 1;
140		hashes.push(l);
141		// find the leaf for the proof
142		if idx == leaf_index {
143			leaf = Some(l);
144		}
145	}
146
147	/// The struct collects a proof for single leaf.
148	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			// we are at left branch - right goes to the proof.
166			if self.position == index {
167				if let Some(right) = right {
168					self.proof.push(*right);
169				}
170			}
171			// we are at right branch - left goes to the proof.
172			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/// Leaf node for proof verification.
189///
190/// Can be either a value that needs to be hashed first,
191/// or the hash itself.
192#[derive(Debug, PartialEq, Eq)]
193pub enum Leaf<'a> {
194	/// Leaf content.
195	Value(&'a [u8]),
196	/// Hash of the leaf content.
197	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
212/// Verify Merkle Proof correctness versus given root hash.
213///
214/// The proof is NOT expected to contain leaf hash as the first
215/// element, but only all adjacent nodes required to eventually by process of
216/// concatenating and hashing end up with given root hash.
217///
218/// The proof must not contain the root hash.
219pub 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
256/// Processes a single row (layer) of a tree by taking pairs of elements,
257/// concatenating them, hashing and placing into resulting vector.
258///
259/// In case only one element is provided it is returned via `Ok` result, in any other case (also an
260/// empty iterator) an `Err` with the inner nodes of upper layer is returned.
261fn 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			// Odd number of items. Promote the item to the upper layer.
295			(Some(a), None) if !next.is_empty() => {
296				next.push(a);
297			},
298			// Last item = root.
299			(Some(a), None) => return Ok(a),
300			// Finish up, no more items.
301			_ => 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		// given
320		sp_tracing::init_for_tests();
321		let data = vec![];
322
323		// when
324		let out = merkle_root::<Keccak256, _>(data.into_iter());
325
326		// then
327		assert_eq!(
328			hex::encode(out),
329			"0000000000000000000000000000000000000000000000000000000000000000"
330		);
331	}
332
333	#[test]
334	fn should_generate_single_root() {
335		// given
336		sp_tracing::init_for_tests();
337		let data = make_leaves(1);
338
339		// when
340		let out = merkle_root::<Keccak256, _>(data.into_iter());
341
342		// then
343		assert_eq!(
344			hex::encode(out),
345			"011b4d03dd8c01f1049143cf9c4c817e4b167f1d1b83e5c6f0f10d89ba1e7bce"
346		);
347	}
348
349	#[test]
350	fn should_generate_root_pow_2() {
351		// given
352		sp_tracing::init_for_tests();
353		let data = make_leaves(2);
354
355		// when
356		let out = merkle_root::<Keccak256, _>(data.into_iter());
357
358		// then
359		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		// given
386		sp_tracing::init_for_tests();
387		let data: Vec<H256> = make_leaves(3);
388
389		// when
390		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		// then
418		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}