1#[cfg(feature = "std")]
22use std::sync::Arc;
23use tetcore_std::{ops::Deref, boxed::Box, vec::Vec};
24use crate::{warn, debug};
25use tetsy_hash_db::{self, Hasher, Prefix};
26use tp_trie::{Trie, MemoryDB, PrefixedMemoryDB, DBValue,
27 empty_child_trie_root, read_trie_value, read_child_trie_value,
28 for_keys_in_child_trie, KeySpacedDB, TrieDBIterator};
29use tp_trie::trie_types::{TrieDB, TrieError, Layout};
30use crate::{backend::Consolidate, StorageKey, StorageValue};
31use tet_core::storage::ChildInfo;
32use codec::Encode;
33
34#[cfg(not(feature = "std"))]
35macro_rules! format {
36 ($($arg:tt)+) => (
37 crate::DefaultError
38 );
39}
40
41type Result<V> = tetcore_std::result::Result<V, crate::DefaultError>;
42
43pub trait Storage<H: Hasher>: Send + Sync {
45 fn get(&self, key: &H::Out, prefix: Prefix) -> Result<Option<DBValue>>;
47}
48
49pub struct TrieBackendEssence<S: TrieBackendStorage<H>, H: Hasher> {
51 storage: S,
52 root: H::Out,
53 empty: H::Out,
54}
55
56impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackendEssence<S, H> where H::Out: Encode {
57 pub fn new(storage: S, root: H::Out) -> Self {
59 TrieBackendEssence {
60 storage,
61 root,
62 empty: H::hash(&[0u8]),
63 }
64 }
65
66 pub fn backend_storage(&self) -> &S {
68 &self.storage
69 }
70
71 pub fn backend_storage_mut(&mut self) -> &mut S {
73 &mut self.storage
74 }
75
76 pub fn root(&self) -> &H::Out {
78 &self.root
79 }
80
81 pub fn set_root(&mut self, root: H::Out) {
83 self.root = root;
84 }
85
86 pub fn into_storage(self) -> S {
88 self.storage
89 }
90
91 pub fn next_storage_key(&self, key: &[u8]) -> Result<Option<StorageKey>> {
94 self.next_storage_key_from_root(&self.root, None, key)
95 }
96
97 fn child_root(&self, child_info: &ChildInfo) -> Result<Option<StorageValue>> {
99 self.storage(child_info.prefixed_storage_key().as_slice())
100 }
101
102 pub fn next_child_storage_key(
105 &self,
106 child_info: &ChildInfo,
107 key: &[u8],
108 ) -> Result<Option<StorageKey>> {
109 let child_root = match self.child_root(child_info)? {
110 Some(child_root) => child_root,
111 None => return Ok(None),
112 };
113
114 let mut hash = H::Out::default();
115
116 if child_root.len() != hash.as_ref().len() {
117 return Err(format!("Invalid child storage hash at {:?}", child_info.storage_key()));
118 }
119 hash.as_mut().copy_from_slice(&child_root[..]);
121
122 self.next_storage_key_from_root(&hash, Some(child_info), key)
123 }
124
125 fn next_storage_key_from_root(
127 &self,
128 root: &H::Out,
129 child_info: Option<&ChildInfo>,
130 key: &[u8],
131 ) -> Result<Option<StorageKey>> {
132 let dyn_eph: &dyn tetsy_hash_db::HashDBRef<_, _>;
133 let keyspace_eph;
134 if let Some(child_info) = child_info.as_ref() {
135 keyspace_eph = KeySpacedDB::new(self, child_info.keyspace());
136 dyn_eph = &keyspace_eph;
137 } else {
138 dyn_eph = self;
139 }
140
141 let trie = TrieDB::<H>::new(dyn_eph, root)
142 .map_err(|e| format!("TrieDB creation error: {}", e))?;
143 let mut iter = trie.iter()
144 .map_err(|e| format!("TrieDB iteration error: {}", e))?;
145
146 let mut potential_next_key = Vec::with_capacity(key.len() + 1);
151 potential_next_key.extend_from_slice(key);
152 potential_next_key.push(0);
153
154 iter.seek(&potential_next_key)
155 .map_err(|e| format!("TrieDB iterator seek error: {}", e))?;
156
157 let next_element = iter.next();
158
159 let next_key = if let Some(next_element) = next_element {
160 let (next_key, _) = next_element
161 .map_err(|e| format!("TrieDB iterator next error: {}", e))?;
162 Some(next_key)
163 } else {
164 None
165 };
166
167 Ok(next_key)
168 }
169
170 pub fn storage(&self, key: &[u8]) -> Result<Option<StorageValue>> {
172 let map_e = |e| format!("Trie lookup error: {}", e);
173
174 read_trie_value::<Layout<H>, _>(self, &self.root, key).map_err(map_e)
175 }
176
177 pub fn child_storage(
179 &self,
180 child_info: &ChildInfo,
181 key: &[u8],
182 ) -> Result<Option<StorageValue>> {
183 let root = self.child_root(child_info)?
184 .unwrap_or_else(|| empty_child_trie_root::<Layout<H>>().encode());
185
186 let map_e = |e| format!("Trie lookup error: {}", e);
187
188 read_child_trie_value::<Layout<H>, _>(child_info.keyspace(), self, &root, key)
189 .map_err(map_e)
190 }
191
192 pub fn apply_to_child_keys_while<F: FnMut(&[u8]) -> bool>(
195 &self,
196 child_info: &ChildInfo,
197 f: F,
198 ) {
199 let root = match self.child_root(child_info) {
200 Ok(v) => v.unwrap_or_else(|| empty_child_trie_root::<Layout<H>>().encode()),
201 Err(e) => {
202 debug!(target: "trie", "Error while iterating child storage: {}", e);
203 return;
204 }
205 };
206
207 if let Err(e) = for_keys_in_child_trie::<Layout<H>, _, _>(
208 child_info.keyspace(),
209 self,
210 &root,
211 f,
212 ) {
213 debug!(target: "trie", "Error while iterating child storage: {}", e);
214 }
215 }
216
217 pub fn for_child_keys_with_prefix<F: FnMut(&[u8])>(
219 &self,
220 child_info: &ChildInfo,
221 prefix: &[u8],
222 mut f: F,
223 ) {
224 let root_vec = match self.child_root(child_info) {
225 Ok(v) => v.unwrap_or_else(|| empty_child_trie_root::<Layout<H>>().encode()),
226 Err(e) => {
227 debug!(target: "trie", "Error while iterating child storage: {}", e);
228 return;
229 }
230 };
231 let mut root = H::Out::default();
232 root.as_mut().copy_from_slice(&root_vec);
233 self.keys_values_with_prefix_inner(&root, prefix, |k, _v| f(k), Some(child_info))
234 }
235
236 pub fn for_keys_with_prefix<F: FnMut(&[u8])>(&self, prefix: &[u8], mut f: F) {
238 self.keys_values_with_prefix_inner(&self.root, prefix, |k, _v| f(k), None)
239 }
240
241 fn keys_values_with_prefix_inner<F: FnMut(&[u8], &[u8])>(
242 &self,
243 root: &H::Out,
244 prefix: &[u8],
245 mut f: F,
246 child_info: Option<&ChildInfo>,
247 ) {
248 let mut iter = move |db| -> tetcore_std::result::Result<(), Box<TrieError<H::Out>>> {
249 let trie = TrieDB::<H>::new(db, root)?;
250
251 for x in TrieDBIterator::new_prefixed(&trie, prefix)? {
252 let (key, value) = x?;
253
254 debug_assert!(key.starts_with(prefix));
255
256 f(&key, &value);
257 }
258
259 Ok(())
260 };
261
262 let result = if let Some(child_info) = child_info {
263 let db = KeySpacedDB::new(self, child_info.keyspace());
264 iter(&db)
265 } else {
266 iter(self)
267 };
268 if let Err(e) = result {
269 debug!(target: "trie", "Error while iterating by prefix: {}", e);
270 }
271 }
272
273 pub fn for_key_values_with_prefix<F: FnMut(&[u8], &[u8])>(&self, prefix: &[u8], f: F) {
275 self.keys_values_with_prefix_inner(&self.root, prefix, f, None)
276 }
277}
278
279pub(crate) struct Ephemeral<'a, S: 'a + TrieBackendStorage<H>, H: 'a + Hasher> {
280 storage: &'a S,
281 overlay: &'a mut S::Overlay,
282}
283
284impl<'a, S: 'a + TrieBackendStorage<H>, H: 'a + Hasher> tetsy_hash_db::AsHashDB<H, DBValue>
285 for Ephemeral<'a, S, H>
286{
287 fn as_hash_db<'b>(&'b self) -> &'b (dyn tetsy_hash_db::HashDB<H, DBValue> + 'b) { self }
288 fn as_hash_db_mut<'b>(&'b mut self) -> &'b mut (dyn tetsy_hash_db::HashDB<H, DBValue> + 'b) { self }
289}
290
291impl<'a, S: TrieBackendStorage<H>, H: Hasher> Ephemeral<'a, S, H> {
292 pub fn new(storage: &'a S, overlay: &'a mut S::Overlay) -> Self {
293 Ephemeral {
294 storage,
295 overlay,
296 }
297 }
298}
299
300impl<'a, S: 'a + TrieBackendStorage<H>, H: Hasher> tetsy_hash_db::HashDB<H, DBValue>
301 for Ephemeral<'a, S, H>
302{
303 fn get(&self, key: &H::Out, prefix: Prefix) -> Option<DBValue> {
304 if let Some(val) = tetsy_hash_db::HashDB::get(self.overlay, key, prefix) {
305 Some(val)
306 } else {
307 match self.storage.get(&key, prefix) {
308 Ok(x) => x,
309 Err(e) => {
310 warn!(target: "trie", "Failed to read from DB: {}", e);
311 None
312 },
313 }
314 }
315 }
316
317 fn contains(&self, key: &H::Out, prefix: Prefix) -> bool {
318 tetsy_hash_db::HashDB::get(self, key, prefix).is_some()
319 }
320
321 fn insert(&mut self, prefix: Prefix, value: &[u8]) -> H::Out {
322 tetsy_hash_db::HashDB::insert(self.overlay, prefix, value)
323 }
324
325 fn emplace(&mut self, key: H::Out, prefix: Prefix, value: DBValue) {
326 tetsy_hash_db::HashDB::emplace(self.overlay, key, prefix, value)
327 }
328
329 fn remove(&mut self, key: &H::Out, prefix: Prefix) {
330 tetsy_hash_db::HashDB::remove(self.overlay, key, prefix)
331 }
332}
333
334impl<'a, S: 'a + TrieBackendStorage<H>, H: Hasher> tetsy_hash_db::HashDBRef<H, DBValue>
335 for Ephemeral<'a, S, H>
336{
337 fn get(&self, key: &H::Out, prefix: Prefix) -> Option<DBValue> {
338 tetsy_hash_db::HashDB::get(self, key, prefix)
339 }
340
341 fn contains(&self, key: &H::Out, prefix: Prefix) -> bool {
342 tetsy_hash_db::HashDB::contains(self, key, prefix)
343 }
344}
345
346pub trait TrieBackendStorage<H: Hasher>: Send + Sync {
348 type Overlay: tetsy_hash_db::HashDB<H, DBValue> + Default + Consolidate;
350 fn get(&self, key: &H::Out, prefix: Prefix) -> Result<Option<DBValue>>;
352}
353
354#[cfg(feature = "std")]
356impl<H: Hasher> TrieBackendStorage<H> for Arc<dyn Storage<H>> {
357 type Overlay = PrefixedMemoryDB<H>;
358
359 fn get(&self, key: &H::Out, prefix: Prefix) -> Result<Option<DBValue>> {
360 Storage::<H>::get(self.deref(), key, prefix)
361 }
362}
363
364impl<H: Hasher> TrieBackendStorage<H> for PrefixedMemoryDB<H> {
366 type Overlay = PrefixedMemoryDB<H>;
367
368 fn get(&self, key: &H::Out, prefix: Prefix) -> Result<Option<DBValue>> {
369 Ok(tetsy_hash_db::HashDB::get(self, key, prefix))
370 }
371}
372
373impl<H: Hasher> TrieBackendStorage<H> for MemoryDB<H> {
374 type Overlay = MemoryDB<H>;
375
376 fn get(&self, key: &H::Out, prefix: Prefix) -> Result<Option<DBValue>> {
377 Ok(tetsy_hash_db::HashDB::get(self, key, prefix))
378 }
379}
380
381impl<S: TrieBackendStorage<H>, H: Hasher> tetsy_hash_db::AsHashDB<H, DBValue>
382 for TrieBackendEssence<S, H>
383{
384 fn as_hash_db<'b>(&'b self) -> &'b (dyn tetsy_hash_db::HashDB<H, DBValue> + 'b) { self }
385 fn as_hash_db_mut<'b>(&'b mut self) -> &'b mut (dyn tetsy_hash_db::HashDB<H, DBValue> + 'b) { self }
386}
387
388impl<S: TrieBackendStorage<H>, H: Hasher> tetsy_hash_db::HashDB<H, DBValue>
389 for TrieBackendEssence<S, H>
390{
391 fn get(&self, key: &H::Out, prefix: Prefix) -> Option<DBValue> {
392 if *key == self.empty {
393 return Some([0u8].to_vec())
394 }
395 match self.storage.get(&key, prefix) {
396 Ok(x) => x,
397 Err(e) => {
398 warn!(target: "trie", "Failed to read from DB: {}", e);
399 None
400 },
401 }
402 }
403
404 fn contains(&self, key: &H::Out, prefix: Prefix) -> bool {
405 tetsy_hash_db::HashDB::get(self, key, prefix).is_some()
406 }
407
408 fn insert(&mut self, _prefix: Prefix, _value: &[u8]) -> H::Out {
409 unimplemented!();
410 }
411
412 fn emplace(&mut self, _key: H::Out, _prefix: Prefix, _value: DBValue) {
413 unimplemented!();
414 }
415
416 fn remove(&mut self, _key: &H::Out, _prefix: Prefix) {
417 unimplemented!();
418 }
419}
420
421impl<S: TrieBackendStorage<H>, H: Hasher> tetsy_hash_db::HashDBRef<H, DBValue>
422 for TrieBackendEssence<S, H>
423{
424 fn get(&self, key: &H::Out, prefix: Prefix) -> Option<DBValue> {
425 tetsy_hash_db::HashDB::get(self, key, prefix)
426 }
427
428 fn contains(&self, key: &H::Out, prefix: Prefix) -> bool {
429 tetsy_hash_db::HashDB::contains(self, key, prefix)
430 }
431}
432
433
434#[cfg(test)]
435mod test {
436 use tet_core::{Blake2Hasher, H256};
437 use tp_trie::{TrieMut, PrefixedMemoryDB, trie_types::TrieDBMut, KeySpacedDBMut};
438 use super::*;
439
440 #[test]
441 fn next_storage_key_and_next_child_storage_key_work() {
442 let child_info = ChildInfo::new_default(b"MyChild");
443 let child_info = &child_info;
444 let mut root_1 = H256::default();
446 let mut root_2 = H256::default();
448
449 let mut mdb = PrefixedMemoryDB::<Blake2Hasher>::default();
450 {
451 let mut trie = TrieDBMut::new(&mut mdb, &mut root_1);
452 trie.insert(b"3", &[1]).expect("insert failed");
453 trie.insert(b"4", &[1]).expect("insert failed");
454 trie.insert(b"6", &[1]).expect("insert failed");
455 }
456 {
457 let mut mdb = KeySpacedDBMut::new(&mut mdb, child_info.keyspace());
458 let mut trie = TrieDBMut::new(&mut mdb, &mut root_1);
461 trie.insert(b"3", &[1]).expect("insert failed");
462 trie.insert(b"4", &[1]).expect("insert failed");
463 trie.insert(b"6", &[1]).expect("insert failed");
464 }
465 {
466 let mut trie = TrieDBMut::new(&mut mdb, &mut root_2);
467 trie.insert(child_info.prefixed_storage_key().as_slice(), root_1.as_ref())
468 .expect("insert failed");
469 };
470
471 let essence_1 = TrieBackendEssence::new(mdb, root_1);
472
473 assert_eq!(essence_1.next_storage_key(b"2"), Ok(Some(b"3".to_vec())));
474 assert_eq!(essence_1.next_storage_key(b"3"), Ok(Some(b"4".to_vec())));
475 assert_eq!(essence_1.next_storage_key(b"4"), Ok(Some(b"6".to_vec())));
476 assert_eq!(essence_1.next_storage_key(b"5"), Ok(Some(b"6".to_vec())));
477 assert_eq!(essence_1.next_storage_key(b"6"), Ok(None));
478
479 let mdb = essence_1.into_storage();
480 let essence_2 = TrieBackendEssence::new(mdb, root_2);
481
482 assert_eq!(
483 essence_2.next_child_storage_key(child_info, b"2"), Ok(Some(b"3".to_vec()))
484 );
485 assert_eq!(
486 essence_2.next_child_storage_key(child_info, b"3"), Ok(Some(b"4".to_vec()))
487 );
488 assert_eq!(
489 essence_2.next_child_storage_key(child_info, b"4"), Ok(Some(b"6".to_vec()))
490 );
491 assert_eq!(
492 essence_2.next_child_storage_key(child_info, b"5"), Ok(Some(b"6".to_vec()))
493 );
494 assert_eq!(
495 essence_2.next_child_storage_key(child_info, b"6"), Ok(None)
496 );
497 }
498}