diem_types/proof/
mod.rs

1// Copyright (c) The Diem Core Contributors
2// SPDX-License-Identifier: Apache-2.0
3
4// Copyright 2021 Conflux Foundation. All rights reserved.
5// Conflux is free software and distributed under GNU General Public License.
6// See http://www.gnu.org/licenses/
7
8pub mod accumulator;
9pub mod definition;
10pub mod position;
11#[cfg(any(test, feature = "fuzzing"))]
12pub mod proptest_proof;
13
14#[cfg(test)]
15mod unit_tests;
16
17use crate::{
18    ledger_info::LedgerInfo,
19    transaction::{TransactionInfo, Version},
20};
21use anyhow::{ensure, Result};
22use diem_crypto::{
23    hash::{
24        CryptoHash, CryptoHasher, EventAccumulatorHasher,
25        SparseMerkleInternalHasher, TestOnlyHasher,
26        TransactionAccumulatorHasher,
27    },
28    HashValue,
29};
30use diem_crypto_derive::CryptoHasher;
31#[cfg(any(test, feature = "fuzzing"))]
32use proptest_derive::Arbitrary;
33use serde::{Deserialize, Serialize};
34use std::marker::PhantomData;
35
36pub use self::definition::{
37    AccumulatorConsistencyProof, AccumulatorExtensionProof, AccumulatorProof,
38    AccumulatorRangeProof, EventAccumulatorProof, SparseMerkleProof,
39    TransactionAccumulatorProof, TransactionAccumulatorRangeProof,
40    TransactionInfoWithProof, TransactionListProof,
41};
42
43#[cfg(any(test, feature = "fuzzing"))]
44pub use self::definition::{TestAccumulatorProof, TestAccumulatorRangeProof};
45
46/// Verifies that a given `transaction_info` exists in the ledger using provided
47/// proof.
48fn verify_transaction_info(
49    ledger_info: &LedgerInfo, transaction_version: Version,
50    transaction_info: &TransactionInfo,
51    ledger_info_to_transaction_info_proof: &TransactionAccumulatorProof,
52) -> Result<()> {
53    ensure!(
54        transaction_version <= ledger_info.version(),
55        "Transaction version {} is newer than LedgerInfo version {}.",
56        transaction_version,
57        ledger_info.version(),
58    );
59
60    let transaction_info_hash = transaction_info.hash();
61    ledger_info_to_transaction_info_proof.verify(
62        ledger_info.transaction_accumulator_hash(),
63        transaction_info_hash,
64        transaction_version,
65    )?;
66
67    Ok(())
68}
69
70pub struct MerkleTreeInternalNode<H> {
71    left_child: HashValue,
72    right_child: HashValue,
73    hasher: PhantomData<H>,
74}
75
76impl<H: CryptoHasher> MerkleTreeInternalNode<H> {
77    pub fn new(left_child: HashValue, right_child: HashValue) -> Self {
78        Self {
79            left_child,
80            right_child,
81            hasher: PhantomData,
82        }
83    }
84}
85
86impl<H: CryptoHasher> CryptoHash for MerkleTreeInternalNode<H> {
87    type Hasher = H;
88
89    fn hash(&self) -> HashValue {
90        let mut state = Self::Hasher::default();
91        state.update(self.left_child.as_ref());
92        state.update(self.right_child.as_ref());
93        state.finish()
94    }
95}
96
97pub type SparseMerkleInternalNode =
98    MerkleTreeInternalNode<SparseMerkleInternalHasher>;
99pub type TransactionAccumulatorInternalNode =
100    MerkleTreeInternalNode<TransactionAccumulatorHasher>;
101pub type EventAccumulatorInternalNode =
102    MerkleTreeInternalNode<EventAccumulatorHasher>;
103pub type TestAccumulatorInternalNode = MerkleTreeInternalNode<TestOnlyHasher>;
104
105#[derive(
106    Clone, Copy, CryptoHasher, Debug, Eq, PartialEq, Serialize, Deserialize,
107)]
108#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))]
109pub struct SparseMerkleLeafNode {
110    key: HashValue,
111    value_hash: HashValue,
112}
113
114impl SparseMerkleLeafNode {
115    pub fn new(key: HashValue, value_hash: HashValue) -> Self {
116        SparseMerkleLeafNode { key, value_hash }
117    }
118
119    pub fn key(&self) -> HashValue { self.key }
120
121    pub fn value_hash(&self) -> HashValue { self.value_hash }
122}
123
124impl CryptoHash for SparseMerkleLeafNode {
125    type Hasher = SparseMerkleLeafNodeHasher;
126
127    fn hash(&self) -> HashValue {
128        let mut state = Self::Hasher::default();
129        state.update(self.key.as_ref());
130        state.update(self.value_hash.as_ref());
131        state.finish()
132    }
133}