1use std::{sync::Arc, collections::HashMap};
21use parking_lot::RwLock;
22use codec::{Decode, Codec};
23use log::debug;
24use tetsy_hash_db::{Hasher, HashDB, EMPTY_PREFIX, Prefix};
25use tp_trie::{
26 MemoryDB, empty_child_trie_root, read_trie_value_with, read_child_trie_value_with,
27 record_all_keys, StorageProof,
28};
29pub use tp_trie::{Recorder, trie_types::{Layout, TrieError}};
30use crate::trie_backend::TrieBackend;
31use crate::trie_backend_essence::{Ephemeral, TrieBackendEssence, TrieBackendStorage};
32use crate::{Error, ExecutionError, Backend, DBValue};
33use tet_core::storage::ChildInfo;
34
35pub struct ProvingBackendRecorder<'a, S: 'a + TrieBackendStorage<H>, H: 'a + Hasher> {
37 pub(crate) backend: &'a TrieBackendEssence<S, H>,
38 pub(crate) proof_recorder: &'a mut Recorder<H::Out>,
39}
40
41impl<'a, S, H> ProvingBackendRecorder<'a, S, H>
42 where
43 S: TrieBackendStorage<H>,
44 H: Hasher,
45 H::Out: Codec,
46{
47 pub fn storage(&mut self, key: &[u8]) -> Result<Option<Vec<u8>>, String> {
49 let mut read_overlay = S::Overlay::default();
50 let eph = Ephemeral::new(
51 self.backend.backend_storage(),
52 &mut read_overlay,
53 );
54
55 let map_e = |e| format!("Trie lookup error: {}", e);
56
57 read_trie_value_with::<Layout<H>, _, Ephemeral<S, H>>(
58 &eph,
59 self.backend.root(),
60 key,
61 &mut *self.proof_recorder,
62 ).map_err(map_e)
63 }
64
65 pub fn child_storage(
67 &mut self,
68 child_info: &ChildInfo,
69 key: &[u8]
70 ) -> Result<Option<Vec<u8>>, String> {
71 let storage_key = child_info.storage_key();
72 let root = self.storage(storage_key)?
73 .and_then(|r| Decode::decode(&mut &r[..]).ok())
74 .unwrap_or_else(|| empty_child_trie_root::<Layout<H>>());
75
76 let mut read_overlay = S::Overlay::default();
77 let eph = Ephemeral::new(
78 self.backend.backend_storage(),
79 &mut read_overlay,
80 );
81
82 let map_e = |e| format!("Trie lookup error: {}", e);
83
84 read_child_trie_value_with::<Layout<H>, _, _>(
85 child_info.keyspace(),
86 &eph,
87 &root.as_ref(),
88 key,
89 &mut *self.proof_recorder
90 ).map_err(map_e)
91 }
92
93 pub fn record_all_keys(&mut self) {
95 let mut read_overlay = S::Overlay::default();
96 let eph = Ephemeral::new(
97 self.backend.backend_storage(),
98 &mut read_overlay,
99 );
100
101 let mut iter = move || -> Result<(), Box<TrieError<H::Out>>> {
102 let root = self.backend.root();
103 record_all_keys::<Layout<H>, _>(&eph, root, &mut *self.proof_recorder)
104 };
105
106 if let Err(e) = iter() {
107 debug!(target: "trie", "Error while recording all keys: {}", e);
108 }
109 }
110}
111
112pub type ProofRecorder<H> = Arc<RwLock<HashMap<<H as Hasher>::Out, Option<DBValue>>>>;
115
116pub struct ProvingBackend<'a, S: 'a + TrieBackendStorage<H>, H: 'a + Hasher> (
119 TrieBackend<ProofRecorderBackend<'a, S, H>, H>,
120);
121
122pub struct ProofRecorderBackend<'a, S: 'a + TrieBackendStorage<H>, H: 'a + Hasher> {
124 backend: &'a S,
125 proof_recorder: ProofRecorder<H>,
126}
127
128impl<'a, S: 'a + TrieBackendStorage<H>, H: 'a + Hasher> ProvingBackend<'a, S, H>
129 where H::Out: Codec
130{
131 pub fn new(backend: &'a TrieBackend<S, H>) -> Self {
133 let proof_recorder = Default::default();
134 Self::new_with_recorder(backend, proof_recorder)
135 }
136
137 pub fn new_with_recorder(
139 backend: &'a TrieBackend<S, H>,
140 proof_recorder: ProofRecorder<H>,
141 ) -> Self {
142 let essence = backend.essence();
143 let root = essence.root().clone();
144 let recorder = ProofRecorderBackend {
145 backend: essence.backend_storage(),
146 proof_recorder,
147 };
148 ProvingBackend(TrieBackend::new(recorder, root))
149 }
150
151 pub fn extract_proof(&self) -> StorageProof {
153 let trie_nodes = self.0.essence().backend_storage().proof_recorder
154 .read()
155 .iter()
156 .filter_map(|(_k, v)| v.as_ref().map(|v| v.to_vec()))
157 .collect();
158 StorageProof::new(trie_nodes)
159 }
160}
161
162impl<'a, S: 'a + TrieBackendStorage<H>, H: 'a + Hasher> TrieBackendStorage<H>
163 for ProofRecorderBackend<'a, S, H>
164{
165 type Overlay = S::Overlay;
166
167 fn get(&self, key: &H::Out, prefix: Prefix) -> Result<Option<DBValue>, String> {
168 if let Some(v) = self.proof_recorder.read().get(key) {
169 return Ok(v.clone());
170 }
171 let backend_value = self.backend.get(key, prefix)?;
172 self.proof_recorder.write().insert(key.clone(), backend_value.clone());
173 Ok(backend_value)
174 }
175}
176
177impl<'a, S: 'a + TrieBackendStorage<H>, H: 'a + Hasher> std::fmt::Debug
178 for ProvingBackend<'a, S, H>
179{
180 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
181 write!(f, "ProvingBackend")
182 }
183}
184
185impl<'a, S, H> Backend<H> for ProvingBackend<'a, S, H>
186 where
187 S: 'a + TrieBackendStorage<H>,
188 H: 'a + Hasher,
189 H::Out: Ord + Codec,
190{
191 type Error = String;
192 type Transaction = S::Overlay;
193 type TrieBackendStorage = S;
194
195 fn storage(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
196 self.0.storage(key)
197 }
198
199 fn child_storage(
200 &self,
201 child_info: &ChildInfo,
202 key: &[u8],
203 ) -> Result<Option<Vec<u8>>, Self::Error> {
204 self.0.child_storage(child_info, key)
205 }
206
207 fn apply_to_child_keys_while<F: FnMut(&[u8]) -> bool>(
208 &self,
209 child_info: &ChildInfo,
210 f: F,
211 ) {
212 self.0.apply_to_child_keys_while(child_info, f)
213 }
214
215 fn next_storage_key(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
216 self.0.next_storage_key(key)
217 }
218
219 fn next_child_storage_key(
220 &self,
221 child_info: &ChildInfo,
222 key: &[u8],
223 ) -> Result<Option<Vec<u8>>, Self::Error> {
224 self.0.next_child_storage_key(child_info, key)
225 }
226
227 fn for_keys_with_prefix<F: FnMut(&[u8])>(&self, prefix: &[u8], f: F) {
228 self.0.for_keys_with_prefix(prefix, f)
229 }
230
231 fn for_key_values_with_prefix<F: FnMut(&[u8], &[u8])>(&self, prefix: &[u8], f: F) {
232 self.0.for_key_values_with_prefix(prefix, f)
233 }
234
235 fn for_child_keys_with_prefix<F: FnMut(&[u8])>(
236 &self,
237 child_info: &ChildInfo,
238 prefix: &[u8],
239 f: F,
240 ) {
241 self.0.for_child_keys_with_prefix( child_info, prefix, f)
242 }
243
244 fn pairs(&self) -> Vec<(Vec<u8>, Vec<u8>)> {
245 self.0.pairs()
246 }
247
248 fn keys(&self, prefix: &[u8]) -> Vec<Vec<u8>> {
249 self.0.keys(prefix)
250 }
251
252 fn child_keys(
253 &self,
254 child_info: &ChildInfo,
255 prefix: &[u8],
256 ) -> Vec<Vec<u8>> {
257 self.0.child_keys(child_info, prefix)
258 }
259
260 fn storage_root<'b>(
261 &self,
262 delta: impl Iterator<Item=(&'b [u8], Option<&'b [u8]>)>,
263 ) -> (H::Out, Self::Transaction) where H::Out: Ord {
264 self.0.storage_root(delta)
265 }
266
267 fn child_storage_root<'b>(
268 &self,
269 child_info: &ChildInfo,
270 delta: impl Iterator<Item=(&'b [u8], Option<&'b [u8]>)>,
271 ) -> (H::Out, bool, Self::Transaction) where H::Out: Ord {
272 self.0.child_storage_root(child_info, delta)
273 }
274
275 fn register_overlay_stats(&mut self, _stats: &crate::stats::StateMachineStats) { }
276
277 fn usage_info(&self) -> crate::stats::UsageInfo {
278 self.0.usage_info()
279 }
280}
281
282pub fn create_proof_check_backend<H>(
284 root: H::Out,
285 proof: StorageProof,
286) -> Result<TrieBackend<MemoryDB<H>, H>, Box<dyn Error>>
287where
288 H: Hasher,
289 H::Out: Codec,
290{
291 let db = proof.into_memory_db();
292
293 if db.contains(&root, EMPTY_PREFIX) {
294 Ok(TrieBackend::new(db, root))
295 } else {
296 Err(Box::new(ExecutionError::InvalidProof))
297 }
298}
299
300#[cfg(test)]
301mod tests {
302 use crate::InMemoryBackend;
303 use crate::trie_backend::tests::test_trie;
304 use super::*;
305 use crate::proving_backend::create_proof_check_backend;
306 use tp_trie::PrefixedMemoryDB;
307 use tp_runtime::traits::BlakeTwo256;
308
309 fn test_proving<'a>(
310 trie_backend: &'a TrieBackend<PrefixedMemoryDB<BlakeTwo256>,BlakeTwo256>,
311 ) -> ProvingBackend<'a, PrefixedMemoryDB<BlakeTwo256>, BlakeTwo256> {
312 ProvingBackend::new(trie_backend)
313 }
314
315 #[test]
316 fn proof_is_empty_until_value_is_read() {
317 let trie_backend = test_trie();
318 assert!(test_proving(&trie_backend).extract_proof().is_empty());
319 }
320
321 #[test]
322 fn proof_is_non_empty_after_value_is_read() {
323 let trie_backend = test_trie();
324 let backend = test_proving(&trie_backend);
325 assert_eq!(backend.storage(b"key").unwrap(), Some(b"value".to_vec()));
326 assert!(!backend.extract_proof().is_empty());
327 }
328
329 #[test]
330 fn proof_is_invalid_when_does_not_contains_root() {
331 use tet_core::H256;
332 let result = create_proof_check_backend::<BlakeTwo256>(
333 H256::from_low_u64_be(1),
334 StorageProof::empty()
335 );
336 assert!(result.is_err());
337 }
338
339 #[test]
340 fn passes_through_backend_calls() {
341 let trie_backend = test_trie();
342 let proving_backend = test_proving(&trie_backend);
343 assert_eq!(trie_backend.storage(b"key").unwrap(), proving_backend.storage(b"key").unwrap());
344 assert_eq!(trie_backend.pairs(), proving_backend.pairs());
345
346 let (trie_root, mut trie_mdb) = trie_backend.storage_root(::std::iter::empty());
347 let (proving_root, mut proving_mdb) = proving_backend.storage_root(::std::iter::empty());
348 assert_eq!(trie_root, proving_root);
349 assert_eq!(trie_mdb.drain(), proving_mdb.drain());
350 }
351
352 #[test]
353 fn proof_recorded_and_checked() {
354 let contents = (0..64).map(|i| (vec![i], Some(vec![i]))).collect::<Vec<_>>();
355 let in_memory = InMemoryBackend::<BlakeTwo256>::default();
356 let mut in_memory = in_memory.update(vec![(None, contents)]);
357 let in_memory_root = in_memory.storage_root(::std::iter::empty()).0;
358 (0..64).for_each(|i| assert_eq!(in_memory.storage(&[i]).unwrap().unwrap(), vec![i]));
359
360 let trie = in_memory.as_trie_backend().unwrap();
361 let trie_root = trie.storage_root(::std::iter::empty()).0;
362 assert_eq!(in_memory_root, trie_root);
363 (0..64).for_each(|i| assert_eq!(trie.storage(&[i]).unwrap().unwrap(), vec![i]));
364
365 let proving = ProvingBackend::new(trie);
366 assert_eq!(proving.storage(&[42]).unwrap().unwrap(), vec![42]);
367
368 let proof = proving.extract_proof();
369
370 let proof_check = create_proof_check_backend::<BlakeTwo256>(in_memory_root.into(), proof).unwrap();
371 assert_eq!(proof_check.storage(&[42]).unwrap().unwrap(), vec![42]);
372 }
373
374 #[test]
375 fn proof_recorded_and_checked_with_child() {
376 let child_info_1 = ChildInfo::new_default(b"sub1");
377 let child_info_2 = ChildInfo::new_default(b"sub2");
378 let child_info_1 = &child_info_1;
379 let child_info_2 = &child_info_2;
380 let contents = vec![
381 (None, (0..64).map(|i| (vec![i], Some(vec![i]))).collect()),
382 (Some(child_info_1.clone()),
383 (28..65).map(|i| (vec![i], Some(vec![i]))).collect()),
384 (Some(child_info_2.clone()),
385 (10..15).map(|i| (vec![i], Some(vec![i]))).collect()),
386 ];
387 let in_memory = InMemoryBackend::<BlakeTwo256>::default();
388 let mut in_memory = in_memory.update(contents);
389 let child_storage_keys = vec![child_info_1.to_owned(), child_info_2.to_owned()];
390 let in_memory_root = in_memory.full_storage_root(
391 std::iter::empty(),
392 child_storage_keys.iter().map(|k|(k, std::iter::empty()))
393 ).0;
394 (0..64).for_each(|i| assert_eq!(
395 in_memory.storage(&[i]).unwrap().unwrap(),
396 vec![i]
397 ));
398 (28..65).for_each(|i| assert_eq!(
399 in_memory.child_storage(child_info_1, &[i]).unwrap().unwrap(),
400 vec![i]
401 ));
402 (10..15).for_each(|i| assert_eq!(
403 in_memory.child_storage(child_info_2, &[i]).unwrap().unwrap(),
404 vec![i]
405 ));
406
407 let trie = in_memory.as_trie_backend().unwrap();
408 let trie_root = trie.storage_root(::std::iter::empty()).0;
409 assert_eq!(in_memory_root, trie_root);
410 (0..64).for_each(|i| assert_eq!(
411 trie.storage(&[i]).unwrap().unwrap(),
412 vec![i]
413 ));
414
415 let proving = ProvingBackend::new(trie);
416 assert_eq!(proving.storage(&[42]).unwrap().unwrap(), vec![42]);
417
418 let proof = proving.extract_proof();
419
420 let proof_check = create_proof_check_backend::<BlakeTwo256>(
421 in_memory_root.into(),
422 proof
423 ).unwrap();
424 assert!(proof_check.storage(&[0]).is_err());
425 assert_eq!(proof_check.storage(&[42]).unwrap().unwrap(), vec![42]);
426 assert_eq!(proof_check.storage(&[41]).unwrap().unwrap(), vec![41]);
428 assert_eq!(proof_check.storage(&[64]).unwrap(), None);
429
430 let proving = ProvingBackend::new(trie);
431 assert_eq!(proving.child_storage(child_info_1, &[64]), Ok(Some(vec![64])));
432
433 let proof = proving.extract_proof();
434 let proof_check = create_proof_check_backend::<BlakeTwo256>(
435 in_memory_root.into(),
436 proof
437 ).unwrap();
438 assert_eq!(
439 proof_check.child_storage(child_info_1, &[64]).unwrap().unwrap(),
440 vec![64]
441 );
442 }
443}