cfx_storage/impls/
state_proof.rs1#[derive(Clone, Debug, Default, PartialEq, RlpEncodable, RlpDecodable)]
12pub struct StateProof {
13 pub delta_proof: Option<TrieProof>,
14 pub intermediate_proof: Option<TrieProof>,
15 pub snapshot_proof: Option<TrieProof>,
16}
17
18impl StateProof {
19 pub fn with_delta(
20 &mut self, maybe_delta_proof: Option<TrieProof>,
21 ) -> &mut Self {
22 self.delta_proof = maybe_delta_proof;
23 self
24 }
25
26 pub fn with_intermediate(
27 &mut self, maybe_intermediate_proof: Option<TrieProof>,
28 ) -> &mut Self {
29 self.intermediate_proof = maybe_intermediate_proof;
30 self
31 }
32
33 pub fn with_snapshot(
34 &mut self, maybe_snapshot_proof: Option<TrieProof>,
35 ) -> &mut Self {
36 self.snapshot_proof = maybe_snapshot_proof;
37 self
38 }
39
40 pub fn is_valid_kv(
41 &self, key: &Vec<u8>, value: Option<&[u8]>, root: StateRoot,
42 maybe_intermediate_padding: Option<DeltaMptKeyPadding>,
43 ) -> bool {
44 if self.intermediate_proof.is_some()
47 && maybe_intermediate_padding.is_none()
48 {
49 return false;
50 }
51
52 let delta_root = &root.delta_root;
53 let intermediate_root = &root.intermediate_delta_root;
54 let snapshot_root = &root.snapshot_root;
55
56 let delta_mpt_padding = StorageKeyWithSpace::delta_mpt_padding(
57 &snapshot_root,
58 &intermediate_root,
59 );
60
61 let storage_key =
62 match StorageKeyWithSpace::from_key_bytes::<CheckInput>(&key) {
63 Ok(k) => k,
64 Err(e) => {
65 warn!("Checking proof with invalid key: {:?}", e);
66 return false;
67 }
68 };
69
70 let delta_mpt_key =
71 storage_key.to_delta_mpt_key_bytes(&delta_mpt_padding);
72 let maybe_intermediate_mpt_key = maybe_intermediate_padding
73 .as_ref()
74 .map(|p| storage_key.to_delta_mpt_key_bytes(p));
75
76 let tombstone_value = MptValue::<Box<[u8]>>::TombStone.unwrap();
77 let delta_value = if value.is_some() {
78 value.clone()
80 } else {
81 Some(&*tombstone_value)
83 };
84
85 match &self.delta_proof {
87 Some(proof) => {
88 if proof.is_valid_kv(&delta_mpt_key, delta_value, delta_root) {
90 return true;
91 }
92 if !proof.is_valid_kv(&delta_mpt_key, None, delta_root) {
94 return false;
95 }
96 }
97 None => {
98 if delta_root.ne(&MERKLE_NULL_NODE) {
100 return false;
101 }
102 }
103 }
104
105 match &self.intermediate_proof {
107 Some(proof) => {
108 if proof.is_valid_kv(
109 maybe_intermediate_mpt_key.as_ref().unwrap(),
112 delta_value,
113 intermediate_root,
114 ) {
115 return true;
116 }
117 if !proof.is_valid_kv(
118 maybe_intermediate_mpt_key.as_ref().unwrap(),
119 None,
120 intermediate_root,
121 ) {
122 return false;
123 }
124 }
125 None => {
126 if intermediate_root.ne(&MERKLE_NULL_NODE) {
128 return false;
129 }
130 }
131 }
132
133 match &self.snapshot_proof {
135 None => false,
136 Some(proof) => proof.is_valid_kv(key, value, snapshot_root),
137 }
138 }
139}
140
141use crate::impls::merkle_patricia_trie::TrieProof;
142use primitives::{
143 CheckInput, DeltaMptKeyPadding, MptValue, StateRoot, StorageKeyWithSpace,
144 MERKLE_NULL_NODE,
145};
146use rlp_derive::{RlpDecodable, RlpEncodable};