cfx_storage/impls/
node_merkle_proof.rs

1// Copyright 2019 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5#[derive(Clone, Debug, Default, PartialEq, RlpEncodable, RlpDecodable)]
6pub struct NodeMerkleProof {
7    pub delta_proof: Option<TrieProof>,
8    pub intermediate_proof: Option<TrieProof>,
9    pub snapshot_proof: Option<TrieProof>,
10}
11
12pub type StorageRootProof = NodeMerkleProof;
13
14impl NodeMerkleProof {
15    pub fn with_delta(
16        &mut self, maybe_delta_proof: Option<TrieProof>,
17    ) -> &mut Self {
18        self.delta_proof = maybe_delta_proof;
19        self
20    }
21
22    pub fn with_intermediate(
23        &mut self, maybe_intermediate_proof: Option<TrieProof>,
24    ) -> &mut Self {
25        self.intermediate_proof = maybe_intermediate_proof;
26        self
27    }
28
29    pub fn with_snapshot(
30        &mut self, maybe_snapshot_proof: Option<TrieProof>,
31    ) -> &mut Self {
32        self.snapshot_proof = maybe_snapshot_proof;
33        self
34    }
35
36    pub fn is_valid(
37        &self, key: &Vec<u8>, storage_root: &StorageRoot,
38        state_root: StateRoot,
39        maybe_intermediate_padding: Option<DeltaMptKeyPadding>,
40    ) -> bool {
41        let delta_root = &state_root.delta_root;
42        let intermediate_root = &state_root.intermediate_delta_root;
43        let snapshot_root = &state_root.snapshot_root;
44
45        let storage_key =
46            match StorageKeyWithSpace::from_key_bytes::<CheckInput>(&key) {
47                Ok(k) => k,
48                Err(e) => {
49                    warn!("Checking proof with invalid key: {:?}", e);
50                    return false;
51                }
52            };
53
54        match self.delta_proof {
55            None => {
56                // empty proof for non-empty trie is invalid
57                if delta_root.ne(&MERKLE_NULL_NODE) {
58                    return false;
59                }
60
61                // empty proof for non-empty storage root is invalid
62                if storage_root.delta != MptValue::None {
63                    return false;
64                }
65            }
66
67            Some(ref proof) => {
68                // convert storage key into delta mpt key
69                let padding = StorageKeyWithSpace::delta_mpt_padding(
70                    &snapshot_root,
71                    &intermediate_root,
72                );
73
74                let key = storage_key.to_delta_mpt_key_bytes(&padding);
75
76                // check if delta proof is valid
77                if !proof.is_valid_node_merkle(
78                    &key,
79                    &storage_root.delta,
80                    delta_root,
81                ) {
82                    return false;
83                }
84            }
85        }
86
87        match self.intermediate_proof {
88            None => {
89                // empty proof for non-empty trie is invalid
90                if intermediate_root.ne(&MERKLE_NULL_NODE) {
91                    return false;
92                }
93
94                // empty proof for non-empty storage root is invalid
95                if storage_root.intermediate != MptValue::None {
96                    return false;
97                }
98            }
99
100            Some(ref proof) => {
101                // convert storage key into delta mpt key
102                let key = match maybe_intermediate_padding {
103                    None => return false,
104                    Some(p) => storage_key.to_delta_mpt_key_bytes(&p),
105                };
106
107                // check if intermediate proof is valid
108                if !proof.is_valid_node_merkle(
109                    &key,
110                    &storage_root.intermediate,
111                    intermediate_root,
112                ) {
113                    return false;
114                }
115            }
116        }
117
118        match self.snapshot_proof {
119            None => {
120                // empty proof for non-empty trie is invalid
121                if snapshot_root.ne(&MERKLE_NULL_NODE) {
122                    return false;
123                }
124
125                // empty proof for non-empty storage root is invalid
126                if storage_root.snapshot != None {
127                    return false;
128                }
129            }
130
131            Some(ref proof) => {
132                // check if snapshot proof is valid
133                if !proof.is_valid_node_merkle(
134                    &key,
135                    &storage_root.snapshot.into(),
136                    snapshot_root,
137                ) {
138                    return false;
139                }
140            }
141        }
142
143        true
144    }
145}
146
147use super::merkle_patricia_trie::TrieProof;
148use primitives::{
149    CheckInput, DeltaMptKeyPadding, MptValue, StateRoot, StorageKeyWithSpace,
150    StorageRoot, MERKLE_NULL_NODE,
151};
152use rlp_derive::{RlpDecodable, RlpEncodable};