1use crate::{
2 common::{
3 path::{
4 Path,
5 Side,
6 },
7 sum,
8 Bytes32,
9 ProofSet,
10 },
11 sparse::{
12 hash::{
13 calculate_leaf_hash,
14 calculate_node_hash,
15 },
16 zero_sum,
17 MerkleTreeKey,
18 },
19};
20
21use alloc::vec::Vec;
22use core::{
23 fmt,
24 fmt::Debug,
25};
26
27#[derive(Debug, Clone, Eq, PartialEq)]
28pub enum Proof {
29 Inclusion(InclusionProof),
30 Exclusion(ExclusionProof),
31}
32
33impl Proof {
34 pub fn proof_set(&self) -> &ProofSet {
35 match self {
36 Proof::Inclusion(proof) => &proof.proof_set,
37 Proof::Exclusion(proof) => &proof.proof_set,
38 }
39 }
40
41 pub fn is_inclusion(&self) -> bool {
42 match self {
43 Proof::Inclusion(_) => true,
44 Proof::Exclusion(_) => false,
45 }
46 }
47
48 pub fn is_exclusion(&self) -> bool {
49 !self.is_inclusion()
50 }
51}
52
53#[derive(Clone, Eq, PartialEq)]
54pub struct InclusionProof {
55 pub proof_set: ProofSet,
56}
57
58impl InclusionProof {
59 pub fn verify(&self, root: &Bytes32, key: &MerkleTreeKey, value: &[u8]) -> bool {
60 let Self { proof_set } = self;
61
62 if proof_set.len() > 256usize {
63 return false;
64 }
65
66 let mut current = calculate_leaf_hash(key, &sum(value));
67 for (i, side_hash) in proof_set.iter().enumerate() {
68 #[allow(clippy::arithmetic_side_effects)] let index =
70 u32::try_from(proof_set.len() - 1 - i).expect("We've checked it above");
71 current = match key.get_instruction(index).expect("Infallible") {
72 Side::Left => calculate_node_hash(¤t, side_hash),
73 Side::Right => calculate_node_hash(side_hash, ¤t),
74 };
75 }
76 current == *root
77 }
78}
79
80impl Debug for InclusionProof {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 let proof_set = self.proof_set.iter().map(hex::encode).collect::<Vec<_>>();
83 f.debug_struct("InclusionProof")
84 .field("Proof set", &proof_set)
85 .finish()
86 }
87}
88
89#[derive(Debug, Clone, Eq, PartialEq)]
90pub enum ExclusionLeaf {
91 Leaf(ExclusionLeafData),
92 Placeholder,
93}
94
95#[derive(Clone, Eq, PartialEq)]
96pub struct ExclusionLeafData {
97 pub leaf_key: Bytes32,
99 pub leaf_value: Bytes32,
101}
102
103impl Debug for ExclusionLeafData {
104 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105 f.debug_struct("ExclusionLeafData")
106 .field("Leaf key", &hex::encode(self.leaf_key))
107 .field("Leaf value", &hex::encode(self.leaf_value))
108 .finish()
109 }
110}
111
112impl ExclusionLeaf {
113 fn hash(&self) -> Bytes32 {
114 match self {
115 ExclusionLeaf::Leaf(data) => {
116 calculate_leaf_hash(&data.leaf_key, &data.leaf_value)
117 }
118 ExclusionLeaf::Placeholder => *zero_sum(),
119 }
120 }
121}
122
123#[derive(Clone, Eq, PartialEq)]
124pub struct ExclusionProof {
125 pub proof_set: ProofSet,
126 pub leaf: ExclusionLeaf,
127}
128
129impl ExclusionProof {
130 pub fn verify(&self, root: &Bytes32, key: &MerkleTreeKey) -> bool {
131 let Self { proof_set, leaf } = self;
132
133 if let ExclusionLeaf::Leaf(data) = leaf {
134 if data.leaf_key == key.as_ref() {
135 return false;
136 }
137 }
138
139 if proof_set.len() > 256usize {
140 return false;
141 }
142
143 let mut current = leaf.hash();
144 for (i, side_hash) in proof_set.iter().enumerate() {
145 #[allow(clippy::arithmetic_side_effects)] let index =
147 u32::try_from(proof_set.len() - 1 - i).expect("We've checked it above");
148 current = match key.get_instruction(index).expect("Infallible") {
149 Side::Left => calculate_node_hash(¤t, side_hash),
150 Side::Right => calculate_node_hash(side_hash, ¤t),
151 };
152 }
153 current == *root
154 }
155}
156
157impl Debug for ExclusionProof {
158 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159 let proof_set = self.proof_set.iter().map(hex::encode).collect::<Vec<_>>();
160 f.debug_struct("ExclusionProof")
161 .field("Proof set", &proof_set)
162 .field("Leaf", &self.leaf)
163 .finish()
164 }
165}
166
167#[cfg(test)]
168#[allow(non_snake_case)]
169mod test {
170 use crate::{
171 common::{
172 Bytes32,
173 StorageMap,
174 },
175 sparse::{
176 proof::Proof,
177 MerkleTree,
178 Primitive,
179 },
180 };
181 use fuel_storage::Mappable;
182
183 #[derive(Debug)]
184 struct TestTable;
185
186 impl Mappable for TestTable {
187 type Key = Self::OwnedKey;
188 type OwnedKey = Bytes32;
189 type OwnedValue = Primitive;
190 type Value = Self::OwnedValue;
191 }
192
193 #[test]
194 fn inclusion_proof__verify__returns_true_for_correct_key_and_correct_value() {
195 let mut storage = StorageMap::<TestTable>::new();
196 let mut tree = MerkleTree::new(&mut storage);
197
198 let k0 = [0u8; 32].into();
212 let v0 = b"DATA_0";
213 tree.update(k0, v0).expect("Expected successful update");
214
215 let mut k1 = [0u8; 32];
216 k1[0] = 0b01000000;
217 let k1 = k1.into();
218 let v1 = b"DATA_1";
219 tree.update(k1, v1).expect("Expected successful update");
220
221 let mut k2 = [0u8; 32];
222 k2[0] = 0b01100000;
223 let k2 = k2.into();
224 let v2 = b"DATA_2";
225 tree.update(k2, v2).expect("Expected successful update");
226
227 let mut k3 = [0u8; 32];
228 k3[0] = 0b01001000;
229 let k3 = k3.into();
230 let v3 = b"DATA_3";
231 tree.update(k3, v3).expect("Expected successful update");
232
233 let root = tree.root();
234
235 {
236 let proof = tree.generate_proof(&k0).unwrap();
238
239 let inclusion = match proof {
241 Proof::Inclusion(proof) => proof.verify(&root, &k0, b"DATA_0"),
242 Proof::Exclusion(_) => panic!("Expected InclusionProof"),
243 };
244
245 assert!(inclusion);
247 }
248
249 {
250 let proof = tree.generate_proof(&k1).unwrap();
252
253 let inclusion = match proof {
255 Proof::Inclusion(proof) => proof.verify(&root, &k1, b"DATA_1"),
256 Proof::Exclusion(_) => panic!("Expected InclusionProof"),
257 };
258
259 assert!(inclusion);
261 }
262
263 {
264 let proof = tree.generate_proof(&k2).unwrap();
266
267 let inclusion = match proof {
269 Proof::Inclusion(proof) => proof.verify(&root, &k2, b"DATA_2"),
270 Proof::Exclusion(_) => panic!("Expected InclusionProof"),
271 };
272
273 assert!(inclusion);
275 }
276
277 {
278 let proof = tree.generate_proof(&k3).unwrap();
280
281 let inclusion = match proof {
283 Proof::Inclusion(proof) => proof.verify(&root, &k3, b"DATA_3"),
284 Proof::Exclusion(_) => panic!("Expected InclusionProof"),
285 };
286
287 assert!(inclusion);
289 }
290 }
291
292 #[test]
293 fn inclusion_proof__verify__returns_false_for_correct_key_and_incorrect_value() {
294 let mut storage = StorageMap::<TestTable>::new();
295 let mut tree = MerkleTree::new(&mut storage);
296
297 let k0 = [0u8; 32].into();
311 let v0 = b"DATA_0";
312 tree.update(k0, v0).expect("Expected successful update");
313
314 let mut k1 = [0u8; 32];
315 k1[0] = 0b01000000;
316 let k1 = k1.into();
317 let v1 = b"DATA_1";
318 tree.update(k1, v1).expect("Expected successful update");
319
320 let mut k2 = [0u8; 32];
321 k2[0] = 0b01100000;
322 let k2 = k2.into();
323 let v2 = b"DATA_2";
324 tree.update(k2, v2).expect("Expected successful update");
325
326 let mut k3 = [0u8; 32];
327 k3[0] = 0b01001000;
328 let k3 = k3.into();
329 let v3 = b"DATA_3";
330 tree.update(k3, v3).expect("Expected successful update");
331
332 let root = tree.root();
333
334 {
335 let proof = tree.generate_proof(&k0).unwrap();
337
338 let inclusion = match proof {
340 Proof::Inclusion(proof) => proof.verify(&root, &k0, b"DATA_100"),
341 Proof::Exclusion(_) => panic!("Expected InclusionProof"),
342 };
343
344 assert!(!inclusion);
346 }
347
348 {
349 let proof = tree.generate_proof(&k1).unwrap();
351
352 let inclusion = match proof {
354 Proof::Inclusion(proof) => proof.verify(&root, &k1, b"DATA_100"),
355 Proof::Exclusion(_) => panic!("Expected InclusionProof"),
356 };
357
358 assert!(!inclusion);
360 }
361
362 {
363 let proof = tree.generate_proof(&k2).unwrap();
365
366 let inclusion = match proof {
368 Proof::Inclusion(proof) => proof.verify(&root, &k2, b"DATA_100"),
369 Proof::Exclusion(_) => panic!("Expected InclusionProof"),
370 };
371
372 assert!(!inclusion);
374 }
375
376 {
377 let proof = tree.generate_proof(&k3).unwrap();
379
380 let inclusion = match proof {
382 Proof::Inclusion(proof) => proof.verify(&root, &k3, b"DATA_100"),
383 Proof::Exclusion(_) => panic!("Expected InclusionProof"),
384 };
385 assert!(!inclusion);
387 }
388 }
389
390 #[test]
391 fn inclusion_proof__verify__returns_false_for_incorrect_key() {
392 let mut storage = StorageMap::<TestTable>::new();
393 let mut tree = MerkleTree::new(&mut storage);
394
395 let k0 = [0u8; 32].into();
409 let v0 = b"DATA_0";
410 tree.update(k0, v0).expect("Expected successful update");
411
412 let mut k1 = [0u8; 32];
413 k1[0] = 0b01000000;
414 let k1 = k1.into();
415 let v1 = b"DATA_1";
416 tree.update(k1, v1).expect("Expected successful update");
417
418 let mut k2 = [0u8; 32];
419 k2[0] = 0b01100000;
420 let k2 = k2.into();
421 let v2 = b"DATA_2";
422 tree.update(k2, v2).expect("Expected successful update");
423
424 let mut k3 = [0u8; 32];
425 k3[0] = 0b01001000;
426 let k3 = k3.into();
427 let v3 = b"DATA_3";
428 tree.update(k3, v3).expect("Expected successful update");
429
430 let root = tree.root();
431
432 let proof = tree.generate_proof(&k3).unwrap();
434
435 let key = [1u8; 32].into();
437 let inclusion = match proof {
438 Proof::Inclusion(proof) => proof.verify(&root, &key, b"DATA_3"),
439 Proof::Exclusion(_) => panic!("Expected InclusionProof"),
440 };
441
442 assert!(!inclusion);
444 }
445
446 #[test]
447 fn exclusion_proof__verify__returns_true_for_correct_key() {
448 let mut storage = StorageMap::<TestTable>::new();
449 let mut tree = MerkleTree::new(&mut storage);
450
451 let k0 = [0u8; 32];
465 let v0 = b"DATA_0";
466 tree.update(k0.into(), v0)
467 .expect("Expected successful update");
468
469 let mut k1 = [0u8; 32];
470 k1[0] = 0b01000000;
471 let v1 = b"DATA_1";
472 tree.update(k1.into(), v1)
473 .expect("Expected successful update");
474
475 let mut k2 = [0u8; 32];
476 k2[0] = 0b01100000;
477 let v2 = b"DATA_2";
478 tree.update(k2.into(), v2)
479 .expect("Expected successful update");
480
481 let mut k3 = [0u8; 32];
482 k3[0] = 0b01001000;
483 let v3 = b"DATA_3";
484 tree.update(k3.into(), v3)
485 .expect("Expected successful update");
486
487 let root = tree.root();
488
489 let key = [0xffu8; 32].into();
491 let proof = tree.generate_proof(&key).unwrap();
492
493 let exclusion = match proof {
495 Proof::Inclusion(_) => panic!("Expected ExclusionProof"),
496 Proof::Exclusion(proof) => proof.verify(&root, &key),
497 };
498
499 assert!(exclusion);
501 }
502
503 #[test]
504 fn exclusion_proof__verify__returns_false_for_incorrect_key() {
505 let mut storage = StorageMap::<TestTable>::new();
506 let mut tree = MerkleTree::new(&mut storage);
507
508 let k0 = [0u8; 32].into();
522 let v0 = b"DATA_0";
523 tree.update(k0, v0).expect("Expected successful update");
524
525 let mut k1 = [0u8; 32];
526 k1[0] = 0b01000000;
527 let k1 = k1.into();
528 let v1 = b"DATA_1";
529 tree.update(k1, v1).expect("Expected successful update");
530
531 let mut k2 = [0u8; 32];
532 k2[0] = 0b01100000;
533 let k2 = k2.into();
534 let v2 = b"DATA_2";
535 tree.update(k2, v2).expect("Expected successful update");
536
537 let mut k3 = [0u8; 32];
538 k3[0] = 0b01001000;
539 let k3 = k3.into();
540 let v3 = b"DATA_3";
541 tree.update(k3, v3).expect("Expected successful update");
542
543 let root = tree.root();
544
545 let key = [0xffu8; 32].into();
547 let proof = tree.generate_proof(&key).unwrap();
548
549 let exclusion = match proof {
551 Proof::Inclusion(_) => panic!("Expected ExclusionProof"),
552 Proof::Exclusion(proof) => proof.verify(&root, &k1),
553 };
554
555 assert!(!exclusion);
557 }
558
559 #[test]
560 fn exclusion_proof__verify__returns_true_for_placeholder() {
561 let mut storage = StorageMap::<TestTable>::new();
562 let mut tree = MerkleTree::new(&mut storage);
563
564 let mut k0 = [0u8; 32];
578 k0[0] = 0b01000000;
579 let k0 = k0.into();
580 let v0 = b"DATA_0";
581 tree.update(k0, v0).expect("Expected successful update");
582
583 let mut k1 = [0u8; 32];
584 k1[0] = 0b01100000;
585 let k1 = k1.into();
586 let v1 = b"DATA_1";
587 tree.update(k1, v1).expect("Expected successful update");
588
589 let mut k2 = [0u8; 32];
590 k2[0] = 0b01001000;
591 let k2 = k2.into();
592 let v2 = b"DATA_2";
593 tree.update(k2, v2).expect("Expected successful update");
594
595 let root = tree.root();
596
597 let key = [0b00000000; 32].into();
599 let proof = tree.generate_proof(&key).unwrap();
600
601 let exclusion = match proof {
603 Proof::Inclusion(_) => panic!("Expected ExclusionProof"),
604 Proof::Exclusion(proof) => proof.verify(&root, &key),
605 };
606
607 assert!(exclusion);
609 }
610}
611
612#[cfg(test)]
613#[allow(non_snake_case)]
614mod test_random {
615 use crate::{
616 common::{
617 Bytes32,
618 StorageMap,
619 },
620 sparse::{
621 proof::Proof,
622 MerkleTree,
623 MerkleTreeKey,
624 Primitive,
625 },
626 };
627 use fuel_storage::Mappable;
628
629 use rand::{
630 prelude::StdRng,
631 SeedableRng,
632 };
633
634 #[derive(Debug)]
635 struct TestTable;
636
637 impl Mappable for TestTable {
638 type Key = Self::OwnedKey;
639 type OwnedKey = Bytes32;
640 type OwnedValue = Primitive;
641 type Value = Self::OwnedValue;
642 }
643
644 fn random_bytes32<R>(rng: &mut R) -> Bytes32
645 where
646 R: rand::Rng + ?Sized,
647 {
648 let mut bytes = [0u8; 32];
649 rng.fill(bytes.as_mut());
650 bytes
651 }
652
653 #[test]
654 fn inclusion_proof__verify__returns_true_for_correct_key_and_correct_value() {
655 let mut rng = StdRng::seed_from_u64(0xDEADBEEF);
656 let mut storage = StorageMap::<TestTable>::new();
657 let mut tree = MerkleTree::new(&mut storage);
658
659 let key = random_bytes32(&mut rng).into();
660 let value = random_bytes32(&mut rng);
661 tree.update(key, &value).unwrap();
662
663 for _ in 0..1_000 {
664 let key = random_bytes32(&mut rng).into();
665 let value = random_bytes32(&mut rng);
666 tree.update(key, &value).unwrap();
667 }
668
669 let root = tree.root();
670
671 let proof = tree.generate_proof(&key).unwrap();
673
674 let inclusion = match proof {
676 Proof::Inclusion(proof) => proof.verify(&root, &key, &value),
677 Proof::Exclusion(_) => panic!("Expected InclusionProof"),
678 };
679
680 assert!(inclusion);
682 }
683
684 #[test]
685 fn inclusion_proof__verify__returns_false_for_correct_key_and_incorrect_value() {
686 let mut rng = StdRng::seed_from_u64(0xDEADBEEF);
687 let mut storage = StorageMap::<TestTable>::new();
688 let mut tree = MerkleTree::new(&mut storage);
689
690 let key = random_bytes32(&mut rng).into();
691 let value = random_bytes32(&mut rng);
692 tree.update(key, &value).unwrap();
693
694 for _ in 0..1_000 {
695 let key = random_bytes32(&mut rng).into();
696 let value = random_bytes32(&mut rng);
697 tree.update(key, &value).unwrap();
698 }
699
700 let root = tree.root();
701
702 let proof = tree.generate_proof(&key).unwrap();
704
705 let inclusion = match proof {
707 Proof::Inclusion(proof) => proof.verify(&root, &key, b"DATA"),
708 Proof::Exclusion(_) => panic!("Expected InclusionProof"),
709 };
710
711 assert!(!inclusion);
713 }
714
715 #[test]
716 fn inclusion_proof__verify__returns_false_for_incorrect_key() {
717 let mut rng = StdRng::seed_from_u64(0xDEADBEEF);
718 let mut storage = StorageMap::<TestTable>::new();
719 let mut tree = MerkleTree::new(&mut storage);
720
721 let key_1 = random_bytes32(&mut rng).into();
722 let value_1 = random_bytes32(&mut rng);
723 tree.update(key_1, &value_1).unwrap();
724
725 let key_2 = random_bytes32(&mut rng).into();
726 let value_2 = random_bytes32(&mut rng);
727 tree.update(key_2, &value_2).unwrap();
728
729 for _ in 0..1_000 {
730 let key = random_bytes32(&mut rng).into();
731 let value = random_bytes32(&mut rng);
732 tree.update(key, &value).unwrap();
733 }
734
735 let root = tree.root();
736
737 let proof = tree.generate_proof(&key_1).unwrap();
740
741 let inclusion = match proof {
744 Proof::Inclusion(proof) => proof.verify(&root, &key_2, &value_2),
745 Proof::Exclusion(_) => panic!("Expected InclusionProof"),
746 };
747
748 assert!(!inclusion);
750 }
751
752 #[test]
753 fn exclusion_proof__verify__returns_true_for_correct_key() {
754 let mut rng = StdRng::seed_from_u64(0xDEADBEEF);
755 let mut storage = StorageMap::<TestTable>::new();
756 let mut tree = MerkleTree::new(&mut storage);
757
758 for _ in 0..1_000 {
759 let key = random_bytes32(&mut rng);
760 let value = random_bytes32(&mut rng);
761 tree.update(key.into(), &value).unwrap();
762 }
763
764 let root = tree.root();
765
766 let key: MerkleTreeKey = random_bytes32(&mut rng).into();
768 let proof = tree.generate_proof(&key).unwrap();
769
770 let exclusion = match proof {
772 Proof::Inclusion(_) => panic!("Expected ExclusionProof"),
773 Proof::Exclusion(proof) => proof.verify(&root, &key),
774 };
775
776 assert!(exclusion);
778 }
779
780 #[test]
781 fn exclusion_proof__verify__returns_true_for_any_key_in_empty_tree() {
782 let mut rng = StdRng::seed_from_u64(0xDEADBEEF);
783 let mut storage = StorageMap::<TestTable>::new();
784 let tree = MerkleTree::new(&mut storage);
785 let root = tree.root();
786
787 let key = random_bytes32(&mut rng).into();
789 let proof = tree.generate_proof(&key).unwrap();
790
791 let exclusion = match proof {
793 Proof::Inclusion(_) => panic!("Expected ExclusionProof"),
794 Proof::Exclusion(proof) => proof.verify(&root, &key),
795 };
796
797 assert!(exclusion);
799 }
800}