1#![cfg_attr(not(feature = "std"), no_std)]
19#![warn(missing_docs)]
20
21#[cfg(not(feature = "std"))]
34extern crate alloc;
35#[cfg(not(feature = "std"))]
36use alloc::vec;
37#[cfg(not(feature = "std"))]
38use alloc::vec::Vec;
39
40use codec::{Decode, Encode};
41use hash_db::Hasher;
42
43pub fn merkle_root<H, I>(leaves: I) -> H::Out
49where
50 H: Hasher,
51 H::Out: Default + AsRef<[u8]>,
52 I: IntoIterator,
53 I::Item: AsRef<[u8]>,
54{
55 let iter = leaves.into_iter().map(|l| <H as Hasher>::hash(l.as_ref()));
56 merkelize::<H, _, _>(iter, &mut ()).into()
57}
58
59fn merkelize<H, V, I>(leaves: I, visitor: &mut V) -> H::Out
60where
61 H: Hasher,
62 H::Out: Default + AsRef<[u8]>,
63 V: Visitor<H::Out>,
64 I: Iterator<Item = H::Out>,
65{
66 let upper = Vec::with_capacity((leaves.size_hint().1.unwrap_or(0).saturating_add(1)) / 2);
67 let mut next = match merkelize_row::<H, _, _>(leaves, upper, visitor) {
68 Ok(root) => return root,
69 Err(next) if next.is_empty() => return H::Out::default(),
70 Err(next) => next,
71 };
72
73 let mut upper = Vec::with_capacity((next.len().saturating_add(1)) / 2);
74 loop {
75 visitor.move_up();
76
77 match merkelize_row::<H, _, _>(next.drain(..), upper, visitor) {
78 Ok(root) => return root,
79 Err(t) => {
80 upper = next;
82 next = t;
83 },
84 };
85 }
86}
87
88#[derive(Debug, PartialEq, Eq, Encode, Decode)]
92pub struct MerkleProof<H, L> {
93 pub root: H,
95 pub proof: Vec<H>,
100 pub number_of_leaves: u32,
105 pub leaf_index: u32,
107 pub leaf: L,
109}
110
111trait Visitor<T> {
116 fn move_up(&mut self);
118
119 fn visit(&mut self, index: u32, left: &Option<T>, right: &Option<T>);
126}
127
128impl<T> Visitor<T> for () {
130 fn move_up(&mut self) {}
131 fn visit(&mut self, _index: u32, _left: &Option<T>, _right: &Option<T>) {}
132}
133
134pub fn merkle_proof<H, I, T>(leaves: I, leaf_index: u32) -> MerkleProof<H::Out, T>
145where
146 H: Hasher,
147 H::Out: Default + Copy + AsRef<[u8]>,
148 I: IntoIterator<Item = T>,
149 I::IntoIter: ExactSizeIterator,
150 T: AsRef<[u8]>,
151{
152 let mut leaf = None;
153 let iter = leaves.into_iter().enumerate().map(|(idx, l)| {
154 let hash = <H as Hasher>::hash(l.as_ref());
155 if idx as u32 == leaf_index {
156 leaf = Some(l);
157 }
158 hash
159 });
160
161 struct ProofCollection<T> {
163 proof: Vec<T>,
164 position: u32,
165 }
166
167 impl<T> ProofCollection<T> {
168 fn new(position: u32) -> Self {
169 ProofCollection { proof: Default::default(), position }
170 }
171 }
172
173 impl<T: Copy> Visitor<T> for ProofCollection<T> {
174 fn move_up(&mut self) {
175 self.position /= 2;
176 }
177
178 fn visit(&mut self, index: u32, left: &Option<T>, right: &Option<T>) {
179 if self.position == index {
181 if let Some(right) = right {
182 self.proof.push(*right);
183 }
184 }
185 if self.position == index + 1 {
187 if let Some(left) = left {
188 self.proof.push(*left);
189 }
190 }
191 }
192 }
193
194 let number_of_leaves = iter.len() as u32;
195 let mut collect_proof = ProofCollection::new(leaf_index);
196
197 let root = merkelize::<H, _, _>(iter, &mut collect_proof);
198 let leaf = leaf.expect("Requested `leaf_index` is greater than number of leaves.");
199
200 #[cfg(feature = "debug")]
201 log::debug!(
202 "[merkle_proof] Proof: {:?}",
203 collect_proof
204 .proof
205 .iter()
206 .map(|s| array_bytes::bytes2hex("", s))
207 .collect::<Vec<_>>()
208 );
209
210 MerkleProof { root, proof: collect_proof.proof, number_of_leaves, leaf_index, leaf }
211}
212
213#[derive(Debug, PartialEq, Eq)]
218pub enum Leaf<'a, H> {
219 Value(&'a [u8]),
221 Hash(H),
223}
224
225impl<'a, H, T: AsRef<[u8]>> From<&'a T> for Leaf<'a, H> {
226 fn from(v: &'a T) -> Self {
227 Leaf::Value(v.as_ref())
228 }
229}
230
231pub fn verify_proof<'a, H, P, L>(
239 root: &'a H::Out,
240 proof: P,
241 number_of_leaves: u32,
242 leaf_index: u32,
243 leaf: L,
244) -> bool
245where
246 H: Hasher,
247 H::Out: PartialEq + AsRef<[u8]>,
248 P: IntoIterator<Item = H::Out>,
249 L: Into<Leaf<'a, H::Out>>,
250{
251 if leaf_index >= number_of_leaves {
252 return false
253 }
254
255 let leaf_hash = match leaf.into() {
256 Leaf::Value(content) => <H as Hasher>::hash(content),
257 Leaf::Hash(hash) => hash,
258 };
259
260 let hash_len = <H as Hasher>::LENGTH;
261 let mut combined = vec![0_u8; hash_len * 2];
262 let mut position = leaf_index;
263 let mut width = number_of_leaves;
264 let computed = proof.into_iter().fold(leaf_hash, |a, b| {
265 if position % 2 == 1 || position + 1 == width {
266 combined[..hash_len].copy_from_slice(&b.as_ref());
267 combined[hash_len..].copy_from_slice(&a.as_ref());
268 } else {
269 combined[..hash_len].copy_from_slice(&a.as_ref());
270 combined[hash_len..].copy_from_slice(&b.as_ref());
271 }
272 let hash = <H as Hasher>::hash(&combined);
273 #[cfg(feature = "debug")]
274 log::debug!(
275 "[verify_proof]: (a, b) {:?}, {:?} => {:?} ({:?}) hash",
276 array_bytes::bytes2hex("", a),
277 array_bytes::bytes2hex("", b),
278 array_bytes::bytes2hex("", hash),
279 array_bytes::bytes2hex("", &combined)
280 );
281 position /= 2;
282 width = ((width - 1) / 2) + 1;
283 hash
284 });
285
286 root == &computed
287}
288
289fn merkelize_row<H, V, I>(
295 mut iter: I,
296 mut next: Vec<H::Out>,
297 visitor: &mut V,
298) -> Result<H::Out, Vec<H::Out>>
299where
300 H: Hasher,
301 H::Out: AsRef<[u8]>,
302 V: Visitor<H::Out>,
303 I: Iterator<Item = H::Out>,
304{
305 #[cfg(feature = "debug")]
306 log::debug!("[merkelize_row]");
307 next.clear();
308
309 let hash_len = <H as Hasher>::LENGTH;
310 let mut index = 0;
311 let mut combined = vec![0_u8; hash_len * 2];
312 loop {
313 let a = iter.next();
314 let b = iter.next();
315 visitor.visit(index, &a, &b);
316
317 #[cfg(feature = "debug")]
318 log::debug!(
319 " {:?}\n {:?}",
320 a.as_ref().map(|s| array_bytes::bytes2hex("", s)),
321 b.as_ref().map(|s| array_bytes::bytes2hex("", s))
322 );
323
324 index += 2;
325 match (a, b) {
326 (Some(a), Some(b)) => {
327 combined[..hash_len].copy_from_slice(a.as_ref());
328 combined[hash_len..].copy_from_slice(b.as_ref());
329
330 next.push(<H as Hasher>::hash(&combined));
331 },
332 (Some(a), None) if !next.is_empty() => {
334 next.push(a);
335 },
336 (Some(a), None) => return Ok(a),
338 _ => {
340 #[cfg(feature = "debug")]
341 log::debug!(
342 "[merkelize_row] Next: {:?}",
343 next.iter().map(|s| array_bytes::bytes2hex("", s)).collect::<Vec<_>>()
344 );
345 return Err(next)
346 },
347 }
348 }
349}
350
351#[cfg(test)]
352mod tests {
353 use super::*;
354 use sp_core::H256;
355 use sp_runtime::traits::Keccak256;
356
357 #[test]
358 fn should_generate_empty_root() {
359 let data: Vec<[u8; 1]> = Default::default();
361
362 let out = merkle_root::<Keccak256, _>(data);
364
365 assert_eq!(
367 array_bytes::bytes2hex("", out),
368 "0000000000000000000000000000000000000000000000000000000000000000"
369 );
370 }
371
372 #[test]
373 fn should_generate_single_root() {
374 let data = vec![array_bytes::hex2array_unchecked::<_, 20>(
376 "E04CC55ebEE1cBCE552f250e85c57B70B2E2625b",
377 )];
378
379 let out = merkle_root::<Keccak256, _>(data);
381
382 assert_eq!(
384 array_bytes::bytes2hex("", out),
385 "aeb47a269393297f4b0a3c9c9cfd00c7a4195255274cf39d83dabc2fcc9ff3d7"
386 );
387 }
388
389 #[test]
390 fn should_generate_root_pow_2() {
391 let data = vec![
393 array_bytes::hex2array_unchecked::<_, 20>("E04CC55ebEE1cBCE552f250e85c57B70B2E2625b"),
394 array_bytes::hex2array_unchecked::<_, 20>("25451A4de12dcCc2D166922fA938E900fCc4ED24"),
395 ];
396
397 let out = merkle_root::<Keccak256, _>(data);
399
400 assert_eq!(
402 array_bytes::bytes2hex("", out),
403 "697ea2a8fe5b03468548a7a413424a6292ab44a82a6f5cc594c3fa7dda7ce402"
404 );
405 }
406
407 #[test]
408 fn should_generate_root_complex() {
409 let test = |root, data| {
410 assert_eq!(array_bytes::bytes2hex("", &merkle_root::<Keccak256, _>(data)), root);
411 };
412
413 test(
414 "aff1208e69c9e8be9b584b07ebac4e48a1ee9d15ce3afe20b77a4d29e4175aa3",
415 vec!["a", "b", "c"],
416 );
417
418 test(
419 "b8912f7269068901f231a965adfefbc10f0eedcfa61852b103efd54dac7db3d7",
420 vec!["a", "b", "a"],
421 );
422
423 test(
424 "dc8e73fe6903148ff5079baecc043983625c23b39f31537e322cd0deee09fa9c",
425 vec!["a", "b", "a", "b"],
426 );
427
428 test(
429 "fb3b3be94be9e983ba5e094c9c51a7d96a4fa2e5d8e891df00ca89ba05bb1239",
430 vec!["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"],
431 );
432 }
433
434 #[test]
435 fn should_generate_and_verify_proof_simple() {
436 let data = vec!["a", "b", "c"];
438
439 let proof0 = merkle_proof::<Keccak256, _, _>(data.clone(), 0);
441 assert!(verify_proof::<Keccak256, _, _>(
442 &proof0.root,
443 proof0.proof.clone(),
444 data.len() as _,
445 proof0.leaf_index,
446 &proof0.leaf,
447 ));
448
449 let proof1 = merkle_proof::<Keccak256, _, _>(data.clone(), 1);
450 assert!(verify_proof::<Keccak256, _, _>(
451 &proof1.root,
452 proof1.proof,
453 data.len() as _,
454 proof1.leaf_index,
455 &proof1.leaf,
456 ));
457
458 let proof2 = merkle_proof::<Keccak256, _, _>(data.clone(), 2);
459 assert!(verify_proof::<Keccak256, _, _>(
460 &proof2.root,
461 proof2.proof,
462 data.len() as _,
463 proof2.leaf_index,
464 &proof2.leaf
465 ));
466
467 assert_eq!(
469 array_bytes::bytes2hex("", &proof0.root),
470 array_bytes::bytes2hex("", &proof1.root)
471 );
472 assert_eq!(
473 array_bytes::bytes2hex("", &proof2.root),
474 array_bytes::bytes2hex("", &proof1.root)
475 );
476
477 assert!(!verify_proof::<Keccak256, _, _>(
478 &array_bytes::hex2array_unchecked(
479 "fb3b3be94be9e983ba5e094c9c51a7d96a4fa2e5d8e891df00ca89ba05bb1239"
480 )
481 .into(),
482 proof0.proof,
483 data.len() as _,
484 proof0.leaf_index,
485 &proof0.leaf
486 ));
487
488 assert!(!verify_proof::<Keccak256, _, _>(
489 &proof0.root.into(),
490 vec![],
491 data.len() as _,
492 proof0.leaf_index,
493 &proof0.leaf
494 ));
495 }
496
497 #[test]
498 fn should_generate_and_verify_proof_complex() {
499 let data = vec!["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"];
501
502 for l in 0..data.len() as u32 {
503 let proof = merkle_proof::<Keccak256, _, _>(data.clone(), l);
505 assert!(verify_proof::<Keccak256, _, _>(
507 &proof.root,
508 proof.proof,
509 data.len() as _,
510 proof.leaf_index,
511 &proof.leaf
512 ));
513 }
514 }
515
516 #[test]
517 fn should_generate_and_verify_proof_large() {
518 let mut data = vec![];
520 for i in 1..16 {
521 for c in 'a'..'z' {
522 if c as usize % i != 0 {
523 data.push(c.to_string());
524 }
525 }
526
527 for l in 0..data.len() as u32 {
528 let proof = merkle_proof::<Keccak256, _, _>(data.clone(), l);
530 assert!(verify_proof::<Keccak256, _, _>(
532 &proof.root,
533 proof.proof,
534 data.len() as _,
535 proof.leaf_index,
536 &proof.leaf
537 ));
538 }
539 }
540 }
541
542 #[test]
543 fn should_generate_and_verify_proof_large_tree() {
544 let mut data = vec![];
546 for i in 0..6000 {
547 data.push(format!("{}", i));
548 }
549
550 for l in (0..data.len() as u32).step_by(13) {
551 let proof = merkle_proof::<Keccak256, _, _>(data.clone(), l);
553 assert!(verify_proof::<Keccak256, _, _>(
555 &proof.root,
556 proof.proof,
557 data.len() as _,
558 proof.leaf_index,
559 &proof.leaf
560 ));
561 }
562 }
563
564 #[test]
565 #[should_panic]
566 fn should_panic_on_invalid_leaf_index() {
567 merkle_proof::<Keccak256, _, _>(vec!["a"], 5);
568 }
569
570 #[test]
571 fn should_generate_and_verify_proof_on_test_data() {
572 let addresses = vec![
573 "0x9aF1Ca5941148eB6A3e9b9C741b69738292C533f",
574 "0xDD6ca953fddA25c496165D9040F7F77f75B75002",
575 "0x60e9C47B64Bc1C7C906E891255EaEC19123E7F42",
576 "0xfa4859480Aa6D899858DE54334d2911E01C070df",
577 "0x19B9b128470584F7209eEf65B69F3624549Abe6d",
578 "0xC436aC1f261802C4494504A11fc2926C726cB83b",
579 "0xc304C8C2c12522F78aD1E28dD86b9947D7744bd0",
580 "0xDa0C2Cba6e832E55dE89cF4033affc90CC147352",
581 "0xf850Fd22c96e3501Aad4CDCBf38E4AEC95622411",
582 "0x684918D4387CEb5E7eda969042f036E226E50642",
583 "0x963F0A1bFbb6813C0AC88FcDe6ceB96EA634A595",
584 "0x39B38ad74b8bCc5CE564f7a27Ac19037A95B6099",
585 "0xC2Dec7Fdd1fef3ee95aD88EC8F3Cd5bd4065f3C7",
586 "0x9E311f05c2b6A43C2CCF16fB2209491BaBc2ec01",
587 "0x927607C30eCE4Ef274e250d0bf414d4a210b16f0",
588 "0x98882bcf85E1E2DFF780D0eB360678C1cf443266",
589 "0xFBb50191cd0662049E7C4EE32830a4Cc9B353047",
590 "0x963854fc2C358c48C3F9F0A598B9572c581B8DEF",
591 "0xF9D7Bc222cF6e3e07bF66711e6f409E51aB75292",
592 "0xF2E3fd32D063F8bBAcB9e6Ea8101C2edd899AFe6",
593 "0x407a5b9047B76E8668570120A96d580589fd1325",
594 "0xEAD9726FAFB900A07dAd24a43AE941d2eFDD6E97",
595 "0x42f5C8D9384034A9030313B51125C32a526b6ee8",
596 "0x158fD2529Bc4116570Eb7C80CC76FEf33ad5eD95",
597 "0x0A436EE2E4dEF3383Cf4546d4278326Ccc82514E",
598 "0x34229A215db8FeaC93Caf8B5B255e3c6eA51d855",
599 "0xEb3B7CF8B1840242CB98A732BA464a17D00b5dDF",
600 "0x2079692bf9ab2d6dc7D79BBDdEE71611E9aA3B72",
601 "0x46e2A67e5d450e2Cf7317779f8274a2a630f3C9B",
602 "0xA7Ece4A5390DAB18D08201aE18800375caD78aab",
603 "0x15E1c0D24D62057Bf082Cb2253dA11Ef0d469570",
604 "0xADDEF4C9b5687Eb1F7E55F2251916200A3598878",
605 "0xe0B16Fb96F936035db2b5A68EB37D470fED2f013",
606 "0x0c9A84993feaa779ae21E39F9793d09e6b69B62D",
607 "0x3bc4D5148906F70F0A7D1e2756572655fd8b7B34",
608 "0xFf4675C26903D5319795cbd3a44b109E7DDD9fDe",
609 "0xCec4450569A8945C6D2Aba0045e4339030128a92",
610 "0x85f0584B10950E421A32F471635b424063FD8405",
611 "0xb38bEe7Bdc0bC43c096e206EFdFEad63869929E3",
612 "0xc9609466274Fef19D0e58E1Ee3b321D5C141067E",
613 "0xa08EA868cF75268E7401021E9f945BAe73872ecc",
614 "0x67C9Cb1A29E964Fe87Ff669735cf7eb87f6868fE",
615 "0x1B6BEF636aFcdd6085cD4455BbcC93796A12F6E2",
616 "0x46B37b243E09540b55cF91C333188e7D5FD786dD",
617 "0x8E719E272f62Fa97da93CF9C941F5e53AA09e44a",
618 "0xa511B7E7DB9cb24AD5c89fBb6032C7a9c2EfA0a5",
619 "0x4D11FDcAeD335d839132AD450B02af974A3A66f8",
620 "0xB8cf790a5090E709B4619E1F335317114294E17E",
621 "0x7f0f57eA064A83210Cafd3a536866ffD2C5eDCB3",
622 "0xC03C848A4521356EF800e399D889e9c2A25D1f9E",
623 "0xC6b03DF05cb686D933DD31fCa5A993bF823dc4FE",
624 "0x58611696b6a8102cf95A32c25612E4cEF32b910F",
625 "0x2ed4bC7197AEF13560F6771D930Bf907772DE3CE",
626 "0x3C5E58f334306be029B0e47e119b8977B2639eb4",
627 "0x288646a1a4FeeC560B349d210263c609aDF649a6",
628 "0xb4F4981E0d027Dc2B3c86afA0D0fC03d317e83C0",
629 "0xaAE4A87F8058feDA3971f9DEd639Ec9189aA2500",
630 "0x355069DA35E598913d8736E5B8340527099960b8",
631 "0x3cf5A0F274cd243C0A186d9fCBdADad089821B93",
632 "0xca55155dCc4591538A8A0ca322a56EB0E4aD03C4",
633 "0xE824D0268366ec5C4F23652b8eD70D552B1F2b8B",
634 "0x84C3e9B25AE8a9b39FF5E331F9A597F2DCf27Ca9",
635 "0xcA0018e278751De10d26539915d9c7E7503432FE",
636 "0xf13077dE6191D6c1509ac7E088b8BE7Fe656c28b",
637 "0x7a6bcA1ec9Db506e47ac6FD86D001c2aBc59C531",
638 "0xeA7f9A2A9dd6Ba9bc93ca615C3Ddf26973146911",
639 "0x8D0d8577e16F8731d4F8712BAbFa97aF4c453458",
640 "0xB7a7855629dF104246997e9ACa0E6510df75d0ea",
641 "0x5C1009BDC70b0C8Ab2e5a53931672ab448C17c89",
642 "0x40B47D1AfefEF5eF41e0789F0285DE7b1C31631C",
643 "0x5086933d549cEcEB20652CE00973703CF10Da373",
644 "0xeb364f6FE356882F92ae9314fa96116Cf65F47d8",
645 "0xdC4D31516A416cEf533C01a92D9a04bbdb85EE67",
646 "0x9b36E086E5A274332AFd3D8509e12ca5F6af918d",
647 "0xBC26394fF36e1673aE0608ce91A53B9768aD0D76",
648 "0x81B5AB400be9e563fA476c100BE898C09966426c",
649 "0x9d93C8ae5793054D28278A5DE6d4653EC79e90FE",
650 "0x3B8E75804F71e121008991E3177fc942b6c28F50",
651 "0xC6Eb5886eB43dD473f5BB4e21e56E08dA464D9B4",
652 "0xfdf1277b71A73c813cD0e1a94B800f4B1Db66DBE",
653 "0xc2ff2cCc98971556670e287Ff0CC39DA795231ad",
654 "0x76b7E1473f0D0A87E9B4a14E2B179266802740f5",
655 "0xA7Bc965660a6EF4687CCa4F69A97563163A3C2Ef",
656 "0xB9C2b47888B9F8f7D03dC1de83F3F55E738CebD3",
657 "0xEd400162E6Dd6bD2271728FFb04176bF770De94a",
658 "0xE3E8331156700339142189B6E555DCb2c0962750",
659 "0xbf62e342Bc7706a448EdD52AE871d9C4497A53b1",
660 "0xb9d7A1A111eed75714a0AcD2dd467E872eE6B03D",
661 "0x03942919DFD0383b8c574AB8A701d89fd4bfA69D",
662 "0x0Ef4C92355D3c8c7050DFeb319790EFCcBE6fe9e",
663 "0xA6895a3cf0C60212a73B3891948ACEcF1753f25E",
664 "0x0Ed509239DB59ef3503ded3d31013C983d52803A",
665 "0xc4CE8abD123BfAFc4deFf37c7D11DeCd5c350EE4",
666 "0x4A4Bf59f7038eDcd8597004f35d7Ee24a7Bdd2d3",
667 "0x5769E8e8A2656b5ed6b6e6fa2a2bFAeaf970BB87",
668 "0xf9E15cCE181332F4F57386687c1776b66C377060",
669 "0xc98f8d4843D56a46C21171900d3eE538Cc74dbb5",
670 "0x3605965B47544Ce4302b988788B8195601AE4dEd",
671 "0xe993BDfdcAac2e65018efeE0F69A12678031c71d",
672 "0x274fDf8801385D3FAc954BCc1446Af45f5a8304c",
673 "0xBFb3f476fcD6429F4a475bA23cEFdDdd85c6b964",
674 "0x806cD16588Fe812ae740e931f95A289aFb4a4B50",
675 "0xa89488CE3bD9C25C3aF797D1bbE6CA689De79d81",
676 "0xd412f1AfAcf0Ebf3Cd324593A231Fc74CC488B12",
677 "0xd1f715b2D7951d54bc31210BbD41852D9BF98Ed1",
678 "0xf65aD707c344171F467b2ADba3d14f312219cE23",
679 "0x2971a4b242e9566dEF7bcdB7347f5E484E11919B",
680 "0x12b113D6827E07E7D426649fBd605f427da52314",
681 "0x1c6CA45171CDb9856A6C9Dba9c5F1216913C1e97",
682 "0x11cC6ee1d74963Db23294FCE1E3e0A0555779CeA",
683 "0x8Aa1C721255CDC8F895E4E4c782D86726b068667",
684 "0xA2cDC1f37510814485129aC6310b22dF04e9Bbf0",
685 "0xCf531b71d388EB3f5889F1f78E0d77f6fb109767",
686 "0xBe703e3545B2510979A0cb0C440C0Fba55c6dCB5",
687 "0x30a35886F989db39c797D8C93880180Fdd71b0c8",
688 "0x1071370D981F60c47A9Cd27ac0A61873a372cBB2",
689 "0x3515d74A11e0Cb65F0F46cB70ecf91dD1712daaa",
690 "0x50500a3c2b7b1229c6884505D00ac6Be29Aecd0C",
691 "0x9A223c2a11D4FD3585103B21B161a2B771aDA3d1",
692 "0xd7218df03AD0907e6c08E707B15d9BD14285e657",
693 "0x76CfD72eF5f93D1a44aD1F80856797fBE060c70a",
694 "0x44d093cB745944991EFF5cBa151AA6602d6f5420",
695 "0x626516DfF43bf09A71eb6fd1510E124F96ED0Cde",
696 "0x6530824632dfe099304E2DC5701cA99E6d031E08",
697 "0x57e6c423d6a7607160d6379A0c335025A14DaFC0",
698 "0x3966D4AD461Ef150E0B10163C81E79b9029E69c3",
699 "0xF608aCfd0C286E23721a3c347b2b65039f6690F1",
700 "0xbfB8FAac31A25646681936977837f7740fCd0072",
701 "0xd80aa634a623a7ED1F069a1a3A28a173061705c7",
702 "0x9122a77B36363e24e12E1E2D73F87b32926D3dF5",
703 "0x62562f0d1cD31315bCCf176049B6279B2bfc39C2",
704 "0x48aBF7A2a7119e5675059E27a7082ba7F38498b2",
705 "0xb4596983AB9A9166b29517acD634415807569e5F",
706 "0x52519D16E20BC8f5E96Da6d736963e85b2adA118",
707 "0x7663893C3dC0850EfC5391f5E5887eD723e51B83",
708 "0x5FF323a29bCC3B5b4B107e177EccEF4272959e61",
709 "0xee6e499AdDf4364D75c05D50d9344e9daA5A9AdF",
710 "0x1631b0BD31fF904aD67dD58994C6C2051CDe4E75",
711 "0xbc208e9723D44B9811C428f6A55722a26204eEF2",
712 "0xe76103a222Ee2C7Cf05B580858CEe625C4dc00E1",
713 "0xC71Bb2DBC51760f4fc2D46D84464410760971B8a",
714 "0xB4C18811e6BFe564D69E12c224FFc57351f7a7ff",
715 "0xD11DB0F5b41061A887cB7eE9c8711438844C298A",
716 "0xB931269934A3D4432c084bAAc3d0de8143199F4f",
717 "0x070037cc85C761946ec43ea2b8A2d5729908A2a1",
718 "0x2E34aa8C95Ffdbb37f14dCfBcA69291c55Ba48DE",
719 "0x052D93e8d9220787c31d6D83f87eC7dB088E998f",
720 "0x498dAC6C69b8b9ad645217050054840f1D91D029",
721 "0xE4F7D60f9d84301e1fFFd01385a585F3A11F8E89",
722 "0xEa637992f30eA06460732EDCBaCDa89355c2a107",
723 "0x4960d8Da07c27CB6Be48a79B96dD70657c57a6bF",
724 "0x7e471A003C8C9fdc8789Ded9C3dbe371d8aa0329",
725 "0xd24265Cc10eecb9e8d355CCc0dE4b11C556E74D7",
726 "0xDE59C8f7557Af779674f41CA2cA855d571018690",
727 "0x2fA8A6b3b6226d8efC9d8f6EBDc73Ca33DDcA4d8",
728 "0xe44102664c6c2024673Ff07DFe66E187Db77c65f",
729 "0x94E3f4f90a5f7CBF2cc2623e66B8583248F01022",
730 "0x0383EdBbc21D73DEd039E9C1Ff6bf56017b4CC40",
731 "0x64C3E49898B88d1E0f0d02DA23E0c00A2Cd0cA99",
732 "0xF4ccfB67b938d82B70bAb20975acFAe402E812E1",
733 "0x4f9ee5829e9852E32E7BC154D02c91D8E203e074",
734 "0xb006312eF9713463bB33D22De60444Ba95609f6B",
735 "0x7Cbe76ef69B52110DDb2e3b441C04dDb11D63248",
736 "0x70ADEEa65488F439392B869b1Df7241EF317e221",
737 "0x64C0bf8AA36Ba590477585Bc0D2BDa7970769463",
738 "0xA4cDc98593CE52d01Fe5Ca47CB3dA5320e0D7592",
739 "0xc26B34D375533fFc4c5276282Fa5D660F3d8cbcB",
740 ];
741 let root: H256 = array_bytes::hex2array_unchecked(
742 "72b0acd7c302a84f1f6b6cefe0ba7194b7398afb440e1b44a9dbbe270394ca53",
743 )
744 .into();
745
746 let data = addresses
747 .into_iter()
748 .map(|address| array_bytes::hex2bytes_unchecked(&address))
749 .collect::<Vec<_>>();
750
751 for l in 0..data.len() as u32 {
752 let proof = merkle_proof::<Keccak256, _, _>(data.clone(), l);
754 assert_eq!(array_bytes::bytes2hex("", &proof.root), array_bytes::bytes2hex("", &root));
755 assert_eq!(proof.leaf_index, l);
756 assert_eq!(&proof.leaf, &data[l as usize]);
757
758 assert!(verify_proof::<Keccak256, _, _>(
760 &proof.root,
761 proof.proof,
762 data.len() as _,
763 proof.leaf_index,
764 &proof.leaf
765 ));
766 }
767
768 let proof = merkle_proof::<Keccak256, _, _>(data.clone(), data.len() as u32 - 1);
769
770 assert_eq!(
771 proof,
772 MerkleProof {
773 root,
774 proof: vec![
775 array_bytes::hex2array_unchecked(
776 "340bcb1d49b2d82802ddbcf5b85043edb3427b65d09d7f758fbc76932ad2da2f"
777 )
778 .into(),
779 array_bytes::hex2array_unchecked(
780 "ba0580e5bd530bc93d61276df7969fb5b4ae8f1864b4a28c280249575198ff1f"
781 )
782 .into(),
783 array_bytes::hex2array_unchecked(
784 "d02609d2bbdb28aa25f58b85afec937d5a4c85d37925bce6d0cf802f9d76ba79"
785 )
786 .into(),
787 array_bytes::hex2array_unchecked(
788 "ae3f8991955ed884613b0a5f40295902eea0e0abe5858fc520b72959bc016d4e"
789 )
790 .into(),
791 ],
792 number_of_leaves: data.len() as _,
793 leaf_index: data.len() as u32 - 1,
794 leaf: array_bytes::hex2array_unchecked::<_, 20>(
795 "c26B34D375533fFc4c5276282Fa5D660F3d8cbcB"
796 )
797 .to_vec(),
798 }
799 );
800 }
801}