1use crate::{
16 iterator::TrieDBRawIterator,
17 lookup::Lookup,
18 nibble::NibbleSlice,
19 node::{decode_hash, NodeHandle, OwnedNode},
20 rstd::boxed::Box,
21 CError, DBValue, Query, Result, Trie, TrieAccess, TrieCache, TrieError, TrieHash, TrieItem,
22 TrieIterator, TrieKeyItem, TrieLayout, TrieRecorder,
23};
24#[cfg(feature = "std")]
25use crate::{
26 nibble::NibbleVec,
27 node::Node,
28 rstd::{fmt, vec::Vec},
29};
30use hash_db::{HashDBRef, Prefix, EMPTY_PREFIX};
31
32pub struct TrieDBBuilder<'db, 'cache, L: TrieLayout> {
34 db: &'db dyn HashDBRef<L::Hash, DBValue>,
35 root: &'db TrieHash<L>,
36 cache: Option<&'cache mut dyn TrieCache<L::Codec>>,
37 recorder: Option<&'cache mut dyn TrieRecorder<TrieHash<L>>>,
38}
39
40impl<'db, 'cache, L: TrieLayout> TrieDBBuilder<'db, 'cache, L> {
41 #[inline]
46 pub fn new(db: &'db dyn HashDBRef<L::Hash, DBValue>, root: &'db TrieHash<L>) -> Self {
47 Self { db, root, cache: None, recorder: None }
48 }
49
50 #[inline]
52 pub fn with_cache(mut self, cache: &'cache mut dyn TrieCache<L::Codec>) -> Self {
53 self.cache = Some(cache);
54 self
55 }
56
57 #[inline]
59 pub fn with_optional_cache<'ocache: 'cache>(
60 mut self,
61 cache: Option<&'ocache mut dyn TrieCache<L::Codec>>,
62 ) -> Self {
63 self.cache = cache.map(|c| c as _);
65 self
66 }
67
68 #[inline]
70 pub fn with_recorder(mut self, recorder: &'cache mut dyn TrieRecorder<TrieHash<L>>) -> Self {
71 self.recorder = Some(recorder);
72 self
73 }
74
75 #[inline]
77 pub fn with_optional_recorder<'recorder: 'cache>(
78 mut self,
79 recorder: Option<&'recorder mut dyn TrieRecorder<TrieHash<L>>>,
80 ) -> Self {
81 self.recorder = recorder.map(|r| r as _);
83 self
84 }
85
86 #[inline]
88 pub fn build(self) -> TrieDB<'db, 'cache, L> {
89 TrieDB {
90 db: self.db,
91 root: self.root,
92 cache: self.cache.map(core::cell::RefCell::new),
93 recorder: self.recorder.map(core::cell::RefCell::new),
94 }
95 }
96}
97
98pub struct TrieDB<'db, 'cache, L>
121where
122 L: TrieLayout,
123{
124 db: &'db dyn HashDBRef<L::Hash, DBValue>,
125 root: &'db TrieHash<L>,
126 cache: Option<core::cell::RefCell<&'cache mut dyn TrieCache<L::Codec>>>,
127 recorder: Option<core::cell::RefCell<&'cache mut dyn TrieRecorder<TrieHash<L>>>>,
128}
129
130impl<'db, 'cache, L> TrieDB<'db, 'cache, L>
131where
132 L: TrieLayout,
133{
134 pub fn db(&'db self) -> &'db dyn HashDBRef<L::Hash, DBValue> {
136 self.db
137 }
138
139 pub(crate) fn get_raw_or_lookup(
151 &self,
152 parent_hash: TrieHash<L>,
153 node_handle: NodeHandle,
154 partial_key: Prefix,
155 record_access: bool,
156 ) -> Result<(OwnedNode<DBValue>, Option<TrieHash<L>>), TrieHash<L>, CError<L>> {
157 let (node_hash, node_data) = match node_handle {
158 NodeHandle::Hash(data) => {
159 let node_hash = decode_hash::<L::Hash>(data)
160 .ok_or_else(|| Box::new(TrieError::InvalidHash(parent_hash, data.to_vec())))?;
161 let node_data = self.db.get(&node_hash, partial_key).ok_or_else(|| {
162 if partial_key == EMPTY_PREFIX {
163 Box::new(TrieError::InvalidStateRoot(node_hash))
164 } else {
165 Box::new(TrieError::IncompleteDatabase(node_hash))
166 }
167 })?;
168
169 (Some(node_hash), node_data)
170 },
171 NodeHandle::Inline(data) => (None, data.to_vec()),
172 };
173 let owned_node = OwnedNode::new::<L::Codec>(node_data)
174 .map_err(|e| Box::new(TrieError::DecoderError(node_hash.unwrap_or(parent_hash), e)))?;
175
176 if record_access {
177 if let Some((hash, recorder)) =
178 node_hash.as_ref().and_then(|h| self.recorder.as_ref().map(|r| (h, r)))
179 {
180 recorder.borrow_mut().record(TrieAccess::EncodedNode {
181 hash: *hash,
182 encoded_node: owned_node.data().into(),
183 });
184 }
185 }
186
187 Ok((owned_node, node_hash))
188 }
189
190 pub(crate) fn fetch_value(
192 &self,
193 hash: TrieHash<L>,
194 prefix: Prefix,
195 ) -> Result<DBValue, TrieHash<L>, CError<L>> {
196 let value = self
197 .db
198 .get(&hash, prefix)
199 .ok_or_else(|| Box::new(TrieError::IncompleteDatabase(hash)))?;
200
201 if let Some(recorder) = self.recorder.as_ref() {
202 debug_assert!(prefix.1.is_none(), "A value has never a partial key; qed");
203
204 recorder.borrow_mut().record(TrieAccess::Value {
205 hash,
206 value: value.as_slice().into(),
207 full_key: prefix.0,
208 });
209 }
210
211 Ok(value)
212 }
213}
214
215impl<'db, 'cache, L> Trie<L> for TrieDB<'db, 'cache, L>
216where
217 L: TrieLayout,
218{
219 fn root(&self) -> &TrieHash<L> {
220 self.root
221 }
222
223 fn get_hash(&self, key: &[u8]) -> Result<Option<TrieHash<L>>, TrieHash<L>, CError<L>> {
224 let mut cache = self.cache.as_ref().map(|c| c.borrow_mut());
225 let mut recorder = self.recorder.as_ref().map(|r| r.borrow_mut());
226
227 Lookup::<L, _> {
228 db: self.db,
229 query: |_: &[u8]| (),
230 hash: *self.root,
231 cache: cache.as_mut().map(|c| &mut ***c as &mut dyn TrieCache<L::Codec>),
232 recorder: recorder.as_mut().map(|r| &mut ***r as &mut dyn TrieRecorder<TrieHash<L>>),
233 }
234 .look_up_hash(key, NibbleSlice::new(key))
235 }
236
237 fn get_with<Q: Query<L::Hash>>(
238 &self,
239 key: &[u8],
240 query: Q,
241 ) -> Result<Option<Q::Item>, TrieHash<L>, CError<L>> {
242 let mut cache = self.cache.as_ref().map(|c| c.borrow_mut());
243 let mut recorder = self.recorder.as_ref().map(|r| r.borrow_mut());
244
245 Lookup::<L, Q> {
246 db: self.db,
247 query,
248 hash: *self.root,
249 cache: cache.as_mut().map(|c| &mut ***c as &mut dyn TrieCache<L::Codec>),
250 recorder: recorder.as_mut().map(|r| &mut ***r as &mut dyn TrieRecorder<TrieHash<L>>),
251 }
252 .look_up(key, NibbleSlice::new(key))
253 }
254
255 fn iter<'a>(
256 &'a self,
257 ) -> Result<
258 Box<dyn TrieIterator<L, Item = TrieItem<TrieHash<L>, CError<L>>> + 'a>,
259 TrieHash<L>,
260 CError<L>,
261 > {
262 TrieDBIterator::new(self).map(|iter| Box::new(iter) as Box<_>)
263 }
264
265 fn key_iter<'a>(
266 &'a self,
267 ) -> Result<
268 Box<dyn TrieIterator<L, Item = TrieKeyItem<TrieHash<L>, CError<L>>> + 'a>,
269 TrieHash<L>,
270 CError<L>,
271 > {
272 TrieDBKeyIterator::new(self).map(|iter| Box::new(iter) as Box<_>)
273 }
274}
275
276#[cfg(feature = "std")]
278struct TrieAwareDebugNode<'db, 'cache, 'a, L>
279where
280 L: TrieLayout,
281{
282 trie: &'db TrieDB<'db, 'cache, L>,
283 node_key: NodeHandle<'a>,
284 partial_key: NibbleVec,
285 index: Option<u8>,
286}
287
288#[cfg(feature = "std")]
289impl<'db, 'cache, 'a, L> fmt::Debug for TrieAwareDebugNode<'db, 'cache, 'a, L>
290where
291 L: TrieLayout,
292{
293 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
294 match self.trie.get_raw_or_lookup(
295 <TrieHash<L>>::default(),
296 self.node_key,
297 self.partial_key.as_prefix(),
298 false,
299 ) {
300 Ok((owned_node, _node_hash)) => match owned_node.node() {
301 Node::Leaf(slice, value) => {
302 let mut disp = f.debug_struct("Node::Leaf");
303 if let Some(i) = self.index {
304 disp.field("index", &i);
305 }
306 disp.field("slice", &slice).field("value", &value);
307 disp.finish()
308 },
309 Node::Extension(slice, item) => {
310 let mut disp = f.debug_struct("Node::Extension");
311 if let Some(i) = self.index {
312 disp.field("index", &i);
313 }
314 disp.field("slice", &slice).field(
315 "item",
316 &TrieAwareDebugNode {
317 trie: self.trie,
318 node_key: item,
319 partial_key: self
320 .partial_key
321 .clone_append_optional_slice_and_nibble(Some(&slice), None),
322 index: None,
323 },
324 );
325 disp.finish()
326 },
327 Node::Branch(ref nodes, ref value) => {
328 let nodes: Vec<TrieAwareDebugNode<L>> = nodes
329 .into_iter()
330 .enumerate()
331 .filter_map(|(i, n)| n.map(|n| (i, n)))
332 .map(|(i, n)| TrieAwareDebugNode {
333 trie: self.trie,
334 index: Some(i as u8),
335 node_key: n,
336 partial_key: self
337 .partial_key
338 .clone_append_optional_slice_and_nibble(None, Some(i as u8)),
339 })
340 .collect();
341 let mut disp = f.debug_struct("Node::Branch");
342 if let Some(i) = self.index {
343 disp.field("index", &i);
344 }
345 disp.field("nodes", &nodes).field("value", &value);
346 disp.finish()
347 },
348 Node::NibbledBranch(slice, nodes, value) => {
349 let nodes: Vec<TrieAwareDebugNode<L>> = nodes
350 .iter()
351 .enumerate()
352 .filter_map(|(i, n)| n.map(|n| (i, n)))
353 .map(|(i, n)| TrieAwareDebugNode {
354 trie: self.trie,
355 index: Some(i as u8),
356 node_key: n,
357 partial_key: self.partial_key.clone_append_optional_slice_and_nibble(
358 Some(&slice),
359 Some(i as u8),
360 ),
361 })
362 .collect();
363 let mut disp = f.debug_struct("Node::NibbledBranch");
364 if let Some(i) = self.index {
365 disp.field("index", &i);
366 }
367 disp.field("slice", &slice).field("nodes", &nodes).field("value", &value);
368 disp.finish()
369 },
370 Node::Empty => {
371 let mut disp = f.debug_struct("Node::Empty");
372 disp.finish()
373 },
374 },
375 Err(e) => f
376 .debug_struct("BROKEN_NODE")
377 .field("index", &self.index)
378 .field("key", &self.node_key)
379 .field("error", &format!("ERROR fetching node: {}", e))
380 .finish(),
381 }
382 }
383}
384
385#[cfg(feature = "std")]
386impl<'db, 'cache, L> fmt::Debug for TrieDB<'db, 'cache, L>
387where
388 L: TrieLayout,
389{
390 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
391 f.debug_struct("TrieDB")
392 .field(
393 "root",
394 &TrieAwareDebugNode {
395 trie: self,
396 node_key: NodeHandle::Hash(self.root().as_ref()),
397 partial_key: NibbleVec::new(),
398 index: None,
399 },
400 )
401 .finish()
402 }
403}
404
405pub struct TrieDBIterator<'a, 'cache, L: TrieLayout> {
407 db: &'a TrieDB<'a, 'cache, L>,
408 raw_iter: TrieDBRawIterator<L>,
409}
410
411pub struct TrieDBKeyIterator<'a, 'cache, L: TrieLayout> {
413 db: &'a TrieDB<'a, 'cache, L>,
414 raw_iter: TrieDBRawIterator<L>,
415}
416
417impl<'a, 'cache, L: TrieLayout> TrieDBIterator<'a, 'cache, L> {
418 pub fn new(db: &'a TrieDB<'a, 'cache, L>) -> Result<Self, TrieHash<L>, CError<L>> {
420 Ok(Self { db, raw_iter: TrieDBRawIterator::new(db)? })
421 }
422
423 pub fn new_prefixed(
425 db: &'a TrieDB<'a, 'cache, L>,
426 prefix: &[u8],
427 ) -> Result<Self, TrieHash<L>, CError<L>> {
428 Ok(Self { db, raw_iter: TrieDBRawIterator::new_prefixed(db, prefix)? })
429 }
430
431 pub fn new_prefixed_then_seek(
435 db: &'a TrieDB<'a, 'cache, L>,
436 prefix: &[u8],
437 start_at: &[u8],
438 ) -> Result<Self, TrieHash<L>, CError<L>> {
439 Ok(Self { db, raw_iter: TrieDBRawIterator::new_prefixed_then_seek(db, prefix, start_at)? })
440 }
441
442 pub fn from_raw(db: &'a TrieDB<'a, 'cache, L>, raw_iter: TrieDBRawIterator<L>) -> Self {
444 Self { db, raw_iter }
445 }
446
447 pub fn into_raw(self) -> TrieDBRawIterator<L> {
449 self.raw_iter
450 }
451}
452
453impl<'a, 'cache, L: TrieLayout> TrieIterator<L> for TrieDBIterator<'a, 'cache, L> {
454 fn seek(&mut self, key: &[u8]) -> Result<(), TrieHash<L>, CError<L>> {
456 self.raw_iter.seek(self.db, key).map(|_| ())
457 }
458}
459
460impl<'a, 'cache, L: TrieLayout> TrieDBKeyIterator<'a, 'cache, L> {
461 pub fn new(db: &'a TrieDB<'a, 'cache, L>) -> Result<Self, TrieHash<L>, CError<L>> {
463 Ok(Self { db, raw_iter: TrieDBRawIterator::new(db)? })
464 }
465
466 pub fn new_prefixed(
468 db: &'a TrieDB<'a, 'cache, L>,
469 prefix: &[u8],
470 ) -> Result<Self, TrieHash<L>, CError<L>> {
471 Ok(Self { db, raw_iter: TrieDBRawIterator::new_prefixed(db, prefix)? })
472 }
473
474 pub fn new_prefixed_then_seek(
478 db: &'a TrieDB<'a, 'cache, L>,
479 prefix: &[u8],
480 start_at: &[u8],
481 ) -> Result<TrieDBKeyIterator<'a, 'cache, L>, TrieHash<L>, CError<L>> {
482 Ok(Self { db, raw_iter: TrieDBRawIterator::new_prefixed_then_seek(db, prefix, start_at)? })
483 }
484
485 pub fn from_raw(db: &'a TrieDB<'a, 'cache, L>, raw_iter: TrieDBRawIterator<L>) -> Self {
487 Self { db, raw_iter }
488 }
489
490 pub fn into_raw(self) -> TrieDBRawIterator<L> {
492 self.raw_iter
493 }
494}
495
496impl<'a, 'cache, L: TrieLayout> TrieIterator<L> for TrieDBKeyIterator<'a, 'cache, L> {
497 fn seek(&mut self, key: &[u8]) -> Result<(), TrieHash<L>, CError<L>> {
499 self.raw_iter.seek(self.db, key).map(|_| ())
500 }
501}
502
503impl<'a, 'cache, L: TrieLayout> Iterator for TrieDBIterator<'a, 'cache, L> {
504 type Item = TrieItem<TrieHash<L>, CError<L>>;
505
506 fn next(&mut self) -> Option<Self::Item> {
507 self.raw_iter.next_item(self.db)
508 }
509}
510
511impl<'a, 'cache, L: TrieLayout> Iterator for TrieDBKeyIterator<'a, 'cache, L> {
512 type Item = TrieKeyItem<TrieHash<L>, CError<L>>;
513
514 fn next(&mut self) -> Option<Self::Item> {
515 self.raw_iter.next_key(self.db)
516 }
517}