1use super::{
11 accumulator::InMemoryAccumulator, position::Position,
12 verify_transaction_info, MerkleTreeInternalNode, SparseMerkleInternalNode,
13 SparseMerkleLeafNode,
14};
15use crate::{
16 account_state_blob::AccountStateBlob,
17 ledger_info::LedgerInfo,
18 transaction::{TransactionInfo, Version},
19};
20use anyhow::{bail, ensure, format_err, Result};
21#[cfg(any(test, feature = "fuzzing"))]
22use diem_crypto::hash::TestOnlyHasher;
23use diem_crypto::{
24 hash::{
25 CryptoHash, CryptoHasher, EventAccumulatorHasher,
26 TransactionAccumulatorHasher, SPARSE_MERKLE_PLACEHOLDER_HASH,
27 },
28 HashValue,
29};
30#[cfg(any(test, feature = "fuzzing"))]
31use proptest_derive::Arbitrary;
32use serde::{Deserialize, Serialize};
33use std::marker::PhantomData;
34
35#[derive(Clone, Serialize, Deserialize)]
39pub struct AccumulatorProof<H> {
40 siblings: Vec<HashValue>,
43
44 phantom: PhantomData<H>,
45}
46
47pub type LeafCount = u64;
51pub const MAX_ACCUMULATOR_PROOF_DEPTH: usize = 63;
52pub const MAX_ACCUMULATOR_LEAVES: LeafCount = 1 << MAX_ACCUMULATOR_PROOF_DEPTH;
53
54impl<H> AccumulatorProof<H>
55where H: CryptoHasher
56{
57 pub fn new(siblings: Vec<HashValue>) -> Self {
59 AccumulatorProof {
60 siblings,
61 phantom: PhantomData,
62 }
63 }
64
65 pub fn siblings(&self) -> &[HashValue] { &self.siblings }
67
68 pub fn verify(
72 &self, expected_root_hash: HashValue, element_hash: HashValue,
73 element_index: u64,
74 ) -> Result<()> {
75 ensure!(
76 self.siblings.len() <= MAX_ACCUMULATOR_PROOF_DEPTH,
77 "Accumulator proof has more than {} ({}) siblings.",
78 MAX_ACCUMULATOR_PROOF_DEPTH,
79 self.siblings.len()
80 );
81
82 let actual_root_hash = self
83 .siblings
84 .iter()
85 .fold(
86 (element_hash, element_index),
87 |(hash, index), sibling_hash| {
90 (
91 if index % 2 == 0 {
92 MerkleTreeInternalNode::<H>::new(
94 hash,
95 *sibling_hash,
96 )
97 .hash()
98 } else {
99 MerkleTreeInternalNode::<H>::new(
101 *sibling_hash,
102 hash,
103 )
104 .hash()
105 },
106 index / 2,
108 )
109 },
110 )
111 .0;
112 ensure!(
113 actual_root_hash == expected_root_hash,
114 "Root hashes do not match. Actual root hash: {:x}. Expected root hash: {:x}.",
115 actual_root_hash,
116 expected_root_hash
117 );
118
119 Ok(())
120 }
121}
122
123impl<H> std::fmt::Debug for AccumulatorProof<H> {
124 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
125 write!(f, "AccumulatorProof {{ siblings: {:?} }}", self.siblings)
126 }
127}
128
129impl<H> PartialEq for AccumulatorProof<H> {
130 fn eq(&self, other: &Self) -> bool { self.siblings == other.siblings }
131}
132
133impl<H> Eq for AccumulatorProof<H> {}
134
135pub type TransactionAccumulatorProof =
136 AccumulatorProof<TransactionAccumulatorHasher>;
137pub type EventAccumulatorProof = AccumulatorProof<EventAccumulatorHasher>;
138#[cfg(any(test, feature = "fuzzing"))]
139pub type TestAccumulatorProof = AccumulatorProof<TestOnlyHasher>;
140
141#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
145pub struct SparseMerkleProof<V> {
146 leaf: Option<SparseMerkleLeafNode>,
159
160 siblings: Vec<HashValue>,
163
164 phantom: PhantomData<V>,
165}
166
167impl<V> SparseMerkleProof<V>
168where V: CryptoHash
169{
170 pub fn new(
172 leaf: Option<SparseMerkleLeafNode>, siblings: Vec<HashValue>,
173 ) -> Self {
174 SparseMerkleProof {
175 leaf,
176 siblings,
177 phantom: PhantomData,
178 }
179 }
180
181 pub fn leaf(&self) -> Option<SparseMerkleLeafNode> { self.leaf }
183
184 pub fn siblings(&self) -> &[HashValue] { &self.siblings }
186
187 pub fn verify(
193 &self, expected_root_hash: HashValue, element_key: HashValue,
194 element_value: Option<&V>,
195 ) -> Result<()> {
196 ensure!(
197 self.siblings.len() <= HashValue::LENGTH_IN_BITS,
198 "Sparse Merkle Tree proof has more than {} ({}) siblings.",
199 HashValue::LENGTH_IN_BITS,
200 self.siblings.len(),
201 );
202
203 match (element_value, self.leaf) {
204 (Some(value), Some(leaf)) => {
205 ensure!(
210 element_key == leaf.key,
211 "Keys do not match. Key in proof: {:x}. Expected key: {:x}.",
212 leaf.key,
213 element_key
214 );
215 let hash = value.hash();
216 ensure!(
217 hash == leaf.value_hash,
218 "Value hashes do not match. Value hash in proof: {:x}. \
219 Expected value hash: {:x}",
220 leaf.value_hash,
221 hash,
222 );
223 }
224 (Some(_value), None) => {
225 bail!("Expected inclusion proof. Found non-inclusion proof.")
226 }
227 (None, Some(leaf)) => {
228 ensure!(
235 element_key != leaf.key,
236 "Expected non-inclusion proof, but key exists in proof.",
237 );
238 ensure!(
239 element_key.common_prefix_bits_len(leaf.key) >= self.siblings.len(),
240 "Key would not have ended up in the subtree where the provided key in proof \
241 is the only existing key, if it existed. So this is not a valid \
242 non-inclusion proof.",
243 );
244 }
245 (None, None) => {
246 }
252 }
253
254 let current_hash = self
255 .leaf
256 .map_or(*SPARSE_MERKLE_PLACEHOLDER_HASH, |leaf| leaf.hash());
257 let actual_root_hash = self
258 .siblings
259 .iter()
260 .zip(
261 element_key
262 .iter_bits()
263 .rev()
264 .skip(HashValue::LENGTH_IN_BITS - self.siblings.len()),
265 )
266 .fold(current_hash, |hash, (sibling_hash, bit)| {
267 if bit {
268 SparseMerkleInternalNode::new(*sibling_hash, hash).hash()
269 } else {
270 SparseMerkleInternalNode::new(hash, *sibling_hash).hash()
271 }
272 });
273 ensure!(
274 actual_root_hash == expected_root_hash,
275 "Root hashes do not match. Actual root hash: {:x}. Expected root hash: {:x}.",
276 actual_root_hash,
277 expected_root_hash,
278 );
279
280 Ok(())
281 }
282}
283
284#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
294pub struct AccumulatorConsistencyProof {
295 subtrees: Vec<HashValue>,
297}
298
299impl AccumulatorConsistencyProof {
300 pub fn new(subtrees: Vec<HashValue>) -> Self { Self { subtrees } }
302
303 pub fn subtrees(&self) -> &[HashValue] { &self.subtrees }
305}
306
307#[derive(Clone, Deserialize, Serialize)]
327pub struct AccumulatorRangeProof<H> {
328 left_siblings: Vec<HashValue>,
331
332 right_siblings: Vec<HashValue>,
335
336 phantom: PhantomData<H>,
337}
338
339impl<H> AccumulatorRangeProof<H>
340where H: CryptoHasher
341{
342 pub fn new(
345 left_siblings: Vec<HashValue>, right_siblings: Vec<HashValue>,
346 ) -> Self {
347 Self {
348 left_siblings,
349 right_siblings,
350 phantom: PhantomData,
351 }
352 }
353
354 pub fn new_empty() -> Self { Self::new(vec![], vec![]) }
356
357 pub fn left_siblings(&self) -> &Vec<HashValue> { &self.left_siblings }
359
360 pub fn right_siblings(&self) -> &Vec<HashValue> { &self.right_siblings }
362
363 pub fn verify(
367 &self, expected_root_hash: HashValue, first_leaf_index: Option<u64>,
368 leaf_hashes: &[HashValue],
369 ) -> Result<()> {
370 if first_leaf_index.is_none() {
371 ensure!(
372 leaf_hashes.is_empty(),
373 "first_leaf_index indicated empty list while leaf_hashes is not empty.",
374 );
375 ensure!(
376 self.left_siblings.is_empty() && self.right_siblings.is_empty(),
377 "No siblings are needed.",
378 );
379 return Ok(());
380 }
381
382 ensure!(
383 self.left_siblings.len() <= MAX_ACCUMULATOR_PROOF_DEPTH,
384 "Proof has more than {} ({}) left siblings.",
385 MAX_ACCUMULATOR_PROOF_DEPTH,
386 self.left_siblings.len(),
387 );
388 ensure!(
389 self.right_siblings.len() <= MAX_ACCUMULATOR_PROOF_DEPTH,
390 "Proof has more than {} ({}) right siblings.",
391 MAX_ACCUMULATOR_PROOF_DEPTH,
392 self.right_siblings.len(),
393 );
394 ensure!(
395 !leaf_hashes.is_empty(),
396 "leaf_hashes is empty while first_leaf_index indicated non-empty list.",
397 );
398
399 let mut left_sibling_iter = self.left_siblings.iter().peekable();
400 let mut right_sibling_iter = self.right_siblings.iter().peekable();
401
402 let mut first_pos = Position::from_leaf_index(
403 first_leaf_index.expect("first_leaf_index should not be None."),
404 );
405 let mut current_hashes = leaf_hashes.to_vec();
406 let mut parent_hashes = vec![];
407
408 while current_hashes.len() > 1
411 || left_sibling_iter.peek().is_some()
412 || right_sibling_iter.peek().is_some()
413 {
414 let mut children_iter = current_hashes.iter();
415
416 if first_pos.is_right_child() {
419 let left_hash = *left_sibling_iter.next().ok_or_else(|| {
420 format_err!("First child is a right child, but missing sibling on the left.")
421 })?;
422 let right_hash =
423 *children_iter.next().expect("The first leaf must exist.");
424 parent_hashes.push(
425 MerkleTreeInternalNode::<H>::new(left_hash, right_hash)
426 .hash(),
427 );
428 }
429
430 let mut children_iter = children_iter.as_slice().chunks_exact(2);
432 while let Some(chunk) = children_iter.next() {
433 let left_hash = chunk[0];
434 let right_hash = chunk[1];
435 parent_hashes.push(
436 MerkleTreeInternalNode::<H>::new(left_hash, right_hash)
437 .hash(),
438 );
439 }
440
441 let remainder = children_iter.remainder();
444 assert!(remainder.len() <= 1);
445 if !remainder.is_empty() {
446 let left_hash = remainder[0];
447 let right_hash = *right_sibling_iter.next().ok_or_else(|| {
448 format_err!("Last child is a left child, but missing sibling on the right.")
449 })?;
450 parent_hashes.push(
451 MerkleTreeInternalNode::<H>::new(left_hash, right_hash)
452 .hash(),
453 );
454 }
455
456 first_pos = first_pos.parent();
457 current_hashes.clear();
458 std::mem::swap(&mut current_hashes, &mut parent_hashes);
459 }
460
461 ensure!(
462 current_hashes[0] == expected_root_hash,
463 "Root hashes do not match. Actual root hash: {:x}. Expected root hash: {:x}.",
464 current_hashes[0],
465 expected_root_hash,
466 );
467
468 Ok(())
469 }
470}
471
472impl<H> std::fmt::Debug for AccumulatorRangeProof<H> {
473 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
474 write!(
475 f,
476 "AccumulatorRangeProof {{ left_siblings: {:?}, right_siblings: {:?} }}",
477 self.left_siblings, self.right_siblings,
478 )
479 }
480}
481
482impl<H> PartialEq for AccumulatorRangeProof<H> {
483 fn eq(&self, other: &Self) -> bool {
484 self.left_siblings == other.left_siblings
485 && self.right_siblings == other.right_siblings
486 }
487}
488
489impl<H> Eq for AccumulatorRangeProof<H> {}
490
491pub type TransactionAccumulatorRangeProof =
492 AccumulatorRangeProof<TransactionAccumulatorHasher>;
493#[cfg(any(test, feature = "fuzzing"))]
494pub type TestAccumulatorRangeProof = AccumulatorRangeProof<TestOnlyHasher>;
495
496#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
517pub struct SparseMerkleRangeProof {
518 right_siblings: Vec<HashValue>,
522}
523
524impl SparseMerkleRangeProof {
525 pub fn new(right_siblings: Vec<HashValue>) -> Self {
527 Self { right_siblings }
528 }
529
530 pub fn right_siblings(&self) -> &[HashValue] { &self.right_siblings }
532}
533
534#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
537#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))]
538pub struct TransactionInfoWithProof {
539 ledger_info_to_transaction_info_proof: TransactionAccumulatorProof,
542
543 transaction_info: TransactionInfo,
545}
546
547impl TransactionInfoWithProof {
548 pub fn new(
551 ledger_info_to_transaction_info_proof: TransactionAccumulatorProof,
552 transaction_info: TransactionInfo,
553 ) -> Self {
554 Self {
555 ledger_info_to_transaction_info_proof,
556 transaction_info,
557 }
558 }
559
560 pub fn ledger_info_to_transaction_info_proof(
563 &self,
564 ) -> &TransactionAccumulatorProof {
565 &self.ledger_info_to_transaction_info_proof
566 }
567
568 pub fn transaction_info(&self) -> &TransactionInfo {
570 &self.transaction_info
571 }
572
573 pub fn verify(
576 &self, ledger_info: &LedgerInfo, transaction_version: Version,
577 ) -> Result<()> {
578 verify_transaction_info(
579 ledger_info,
580 transaction_version,
581 &self.transaction_info,
582 &self.ledger_info_to_transaction_info_proof,
583 )?;
584 Ok(())
585 }
586}
587
588#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
593#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))]
594pub struct AccountStateProof {
595 transaction_info_with_proof: TransactionInfoWithProof,
596
597 transaction_info_to_account_proof: SparseMerkleProof<AccountStateBlob>,
599}
600
601impl AccountStateProof {
602 pub fn new(
606 transaction_info_with_proof: TransactionInfoWithProof,
607 transaction_info_to_account_proof: SparseMerkleProof<AccountStateBlob>,
608 ) -> Self {
609 AccountStateProof {
610 transaction_info_with_proof,
611 transaction_info_to_account_proof,
612 }
613 }
614
615 pub fn transaction_info_with_proof(&self) -> &TransactionInfoWithProof {
617 &self.transaction_info_with_proof
618 }
619
620 pub fn transaction_info_to_account_proof(
622 &self,
623 ) -> &SparseMerkleProof<AccountStateBlob> {
624 &self.transaction_info_to_account_proof
625 }
626
627 pub fn verify(
632 &self, ledger_info: &LedgerInfo, state_version: Version,
633 account_address_hash: HashValue,
634 account_state_blob: Option<&AccountStateBlob>,
635 ) -> Result<()> {
636 self.transaction_info_to_account_proof.verify(
637 self.transaction_info_with_proof
638 .transaction_info
639 .state_root_hash(),
640 account_address_hash,
641 account_state_blob,
642 )?;
643
644 self.transaction_info_with_proof
645 .verify(ledger_info, state_version)?;
646
647 Ok(())
648 }
649}
650
651#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
656#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))]
657pub struct EventProof {
658 transaction_info_with_proof: TransactionInfoWithProof,
659
660 transaction_info_to_event_proof: EventAccumulatorProof,
662}
663
664impl EventProof {
665 pub fn new(
669 transaction_info_with_proof: TransactionInfoWithProof,
670 transaction_info_to_event_proof: EventAccumulatorProof,
671 ) -> Self {
672 EventProof {
673 transaction_info_with_proof,
674 transaction_info_to_event_proof,
675 }
676 }
677
678 pub fn transaction_info_with_proof(&self) -> &TransactionInfoWithProof {
680 &self.transaction_info_with_proof
681 }
682
683 pub fn verify(
685 &self, ledger_info: &LedgerInfo, event_hash: HashValue,
686 transaction_version: Version,
687 event_version_within_transaction: Version,
688 ) -> Result<()> {
689 self.transaction_info_to_event_proof.verify(
690 self.transaction_info_with_proof
691 .transaction_info()
692 .event_root_hash(),
693 event_hash,
694 event_version_within_transaction,
695 )?;
696
697 self.transaction_info_with_proof
698 .verify(ledger_info, transaction_version)?;
699
700 Ok(())
701 }
702}
703
704#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
706#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))]
707pub struct TransactionListProof {
708 ledger_info_to_transaction_infos_proof: TransactionAccumulatorRangeProof,
711
712 transaction_infos: Vec<TransactionInfo>,
714}
715
716impl TransactionListProof {
717 pub fn new(
720 ledger_info_to_transaction_infos_proof: TransactionAccumulatorRangeProof,
721 transaction_infos: Vec<TransactionInfo>,
722 ) -> Self {
723 Self {
724 ledger_info_to_transaction_infos_proof,
725 transaction_infos,
726 }
727 }
728
729 pub fn new_empty() -> Self {
731 Self::new(AccumulatorRangeProof::new_empty(), vec![])
732 }
733
734 pub fn transaction_infos(&self) -> &[TransactionInfo] {
736 &self.transaction_infos
737 }
738
739 pub fn left_siblings(&self) -> &Vec<HashValue> {
740 self.ledger_info_to_transaction_infos_proof.left_siblings()
741 }
742
743 pub fn unpack(
744 self,
745 ) -> (TransactionAccumulatorRangeProof, Vec<TransactionInfo>) {
746 (
747 self.ledger_info_to_transaction_infos_proof,
748 self.transaction_infos,
749 )
750 }
751
752 pub fn verify(
756 &self, ledger_info: &LedgerInfo,
757 first_transaction_version: Option<Version>,
758 transaction_hashes: &[HashValue],
759 ) -> Result<()> {
760 ensure!(
761 self.transaction_infos.len() == transaction_hashes.len(),
762 "The number of TransactionInfo objects ({}) does not match the number of \
763 transactions ({}).",
764 self.transaction_infos.len(),
765 transaction_hashes.len(),
766 );
767
768 itertools::zip_eq(transaction_hashes, &self.transaction_infos)
769 .map(|(txn_hash, txn_info)| {
770 ensure!(
771 *txn_hash == txn_info.transaction_hash(),
772 "The hash of transaction does not match the transaction info in proof. \
773 Transaction hash: {:x}. Transaction hash in txn_info: {:x}.",
774 txn_hash,
775 txn_info.transaction_hash(),
776 );
777 Ok(())
778 })
779 .collect::<Result<Vec<_>>>()?;
780
781 let txn_info_hashes: Vec<_> = self
782 .transaction_infos
783 .iter()
784 .map(CryptoHash::hash)
785 .collect();
786 self.ledger_info_to_transaction_infos_proof.verify(
787 ledger_info.transaction_accumulator_hash(),
788 first_transaction_version,
789 &txn_info_hashes,
790 )?;
791 Ok(())
792 }
793}
794
795#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
798pub struct AccumulatorExtensionProof<H> {
799 frozen_subtree_roots: Vec<HashValue>,
802 num_leaves: LeafCount,
804 leaves: Vec<HashValue>,
806
807 hasher: PhantomData<H>,
808}
809
810impl<H: CryptoHasher> AccumulatorExtensionProof<H> {
811 pub fn new(
812 frozen_subtree_roots: Vec<HashValue>, num_leaves: LeafCount,
813 leaves: Vec<HashValue>,
814 ) -> Self {
815 Self {
816 frozen_subtree_roots,
817 num_leaves,
818 leaves,
819 hasher: PhantomData,
820 }
821 }
822
823 pub fn verify(
824 &self, _original_root: HashValue,
825 ) -> anyhow::Result<InMemoryAccumulator<H>> {
826 let original_tree = InMemoryAccumulator::<H>::new(
827 self.frozen_subtree_roots.clone(),
828 self.num_leaves,
829 )?;
830 Ok(original_tree.append(self.leaves.as_slice()))
838 }
839}