1use crate::{
21 nibble::{nibble_ops, NibbleSlice},
22 node::Value,
23 node_codec::NodeCodec,
24 rstd::{cmp::max, marker::PhantomData, vec::Vec},
25 triedbmut::ChildReference,
26 DBValue, TrieHash, TrieLayout,
27};
28use hash_db::{HashDB, Hasher, Prefix};
29
30macro_rules! exponential_out {
31 (@3, [$($inpp:expr),*]) => { exponential_out!(@2, [$($inpp,)* $($inpp),*]) };
32 (@2, [$($inpp:expr),*]) => { exponential_out!(@1, [$($inpp,)* $($inpp),*]) };
33 (@1, [$($inpp:expr),*]) => { [$($inpp,)* $($inpp),*] };
34}
35
36type CacheNode<HO> = Option<ChildReference<HO>>;
37
38#[inline(always)]
39fn new_vec_slice_buffer<HO>() -> [CacheNode<HO>; 16] {
40 exponential_out!(@3, [None, None])
41}
42
43type ArrayNode<T> = [CacheNode<TrieHash<T>>; 16];
44
45struct CacheAccum<T: TrieLayout, V>(Vec<(ArrayNode<T>, Option<V>, usize)>);
51
52const INITIAL_DEPTH: usize = 10;
54
55impl<T, V> CacheAccum<T, V>
56where
57 T: TrieLayout,
58 V: AsRef<[u8]>,
59{
60 fn new() -> Self {
61 let v = Vec::with_capacity(INITIAL_DEPTH);
62 CacheAccum(v)
63 }
64
65 #[inline(always)]
66 fn set_cache_value(&mut self, depth: usize, value: Option<V>) {
67 if self.0.is_empty() || self.0[self.0.len() - 1].2 < depth {
68 self.0.push((new_vec_slice_buffer(), None, depth));
69 }
70 let last = self.0.len() - 1;
71 debug_assert!(self.0[last].2 <= depth);
72 self.0[last].1 = value;
73 }
74
75 #[inline(always)]
76 fn set_node(&mut self, depth: usize, nibble_index: usize, node: CacheNode<TrieHash<T>>) {
77 if self.0.is_empty() || self.0[self.0.len() - 1].2 < depth {
78 self.0.push((new_vec_slice_buffer(), None, depth));
79 }
80
81 let last = self.0.len() - 1;
82 debug_assert!(self.0[last].2 == depth);
83
84 self.0[last].0.as_mut()[nibble_index] = node;
85 }
86
87 #[inline(always)]
88 fn last_depth(&self) -> usize {
89 let ix = self.0.len();
90 if ix > 0 {
91 let last = ix - 1;
92 self.0[last].2
93 } else {
94 0
95 }
96 }
97
98 #[inline(always)]
99 fn last_last_depth(&self) -> usize {
100 let ix = self.0.len();
101 if ix > 1 {
102 let last = ix - 2;
103 self.0[last].2
104 } else {
105 0
106 }
107 }
108
109 #[inline(always)]
110 fn is_empty(&self) -> bool {
111 self.0.is_empty()
112 }
113 #[inline(always)]
114 fn is_one(&self) -> bool {
115 self.0.len() == 1
116 }
117
118 fn flush_value(
119 &mut self,
120 callback: &mut impl ProcessEncodedNode<TrieHash<T>>,
121 target_depth: usize,
122 (k2, v2): &(impl AsRef<[u8]>, impl AsRef<[u8]>),
123 ) {
124 let nibble_value = nibble_ops::left_nibble_at(&k2.as_ref()[..], target_depth);
125 let nkey = NibbleSlice::new_offset(&k2.as_ref()[..], target_depth + 1);
127 let pr = NibbleSlice::new_offset(
128 &k2.as_ref()[..],
129 k2.as_ref().len() * nibble_ops::NIBBLE_PER_BYTE - nkey.len(),
130 );
131
132 let hashed;
133 let value = if let Some(value) = Value::new_inline(v2.as_ref(), T::MAX_INLINE_VALUE) {
134 value
135 } else {
136 hashed = callback.process_inner_hashed_value((k2.as_ref(), None), v2.as_ref());
137 Value::Node(hashed.as_ref())
138 };
139 let encoded = T::Codec::leaf_node(nkey.right_iter(), nkey.len(), value);
140 let hash = callback.process(pr.left(), encoded, false);
141
142 self.set_node(target_depth, nibble_value as usize, Some(hash));
144 }
145
146 fn flush_branch(
147 &mut self,
148 callback: &mut impl ProcessEncodedNode<TrieHash<T>>,
149 ref_branch: impl AsRef<[u8]> + Ord,
150 new_depth: usize,
151 is_last: bool,
152 ) {
153 while self.last_depth() > new_depth || is_last && !self.is_empty() {
154 let lix = self.last_depth();
155 let llix = max(self.last_last_depth(), new_depth);
156
157 let (offset, slice_size, is_root) = if llix == 0 && is_last && self.is_one() {
158 (llix, lix - llix, true)
160 } else {
161 (llix + 1, lix - llix - 1, false)
162 };
163 let nkey = if slice_size > 0 { Some((offset, slice_size)) } else { None };
164
165 let h = if T::USE_EXTENSION {
166 self.standard_extension(&ref_branch.as_ref()[..], callback, lix, is_root, nkey)
167 } else {
168 self.no_extension(&ref_branch.as_ref()[..], callback, lix, is_root, nkey)
170 };
171 if !is_root {
172 let nibble: u8 = nibble_ops::left_nibble_at(&ref_branch.as_ref()[..], llix);
174 self.set_node(llix, nibble as usize, Some(h));
175 }
176 }
177 }
178
179 #[inline(always)]
180 fn standard_extension(
181 &mut self,
182 key_branch: &[u8],
183 callback: &mut impl ProcessEncodedNode<TrieHash<T>>,
184 branch_d: usize,
185 is_root: bool,
186 nkey: Option<(usize, usize)>,
187 ) -> ChildReference<TrieHash<T>> {
188 let last = self.0.len() - 1;
189 assert_eq!(self.0[last].2, branch_d);
190
191 let (children, v, depth) = self.0.pop().expect("checked");
192
193 debug_assert!(branch_d == depth);
194 let pr = NibbleSlice::new_offset(&key_branch, branch_d);
195
196 let hashed;
197 let value = if let Some(v) = v.as_ref() {
198 Some(if let Some(value) = Value::new_inline(v.as_ref(), T::MAX_INLINE_VALUE) {
199 value
200 } else {
201 let mut prefix = NibbleSlice::new_offset(&key_branch, 0);
202 prefix.advance(branch_d);
203 hashed = callback.process_inner_hashed_value(prefix.left(), v.as_ref());
204 Value::Node(hashed.as_ref())
205 })
206 } else {
207 None
208 };
209
210 let encoded = T::Codec::branch_node(children.iter(), value);
212 let branch_hash = callback.process(pr.left(), encoded, is_root && nkey.is_none());
213
214 if let Some(nkeyix) = nkey {
215 let pr = NibbleSlice::new_offset(&key_branch, nkeyix.0);
216 let nib = pr.right_range_iter(nkeyix.1);
217 let encoded = T::Codec::extension_node(nib, nkeyix.1, branch_hash);
218 callback.process(pr.left(), encoded, is_root)
219 } else {
220 branch_hash
221 }
222 }
223
224 #[inline(always)]
225 fn no_extension(
226 &mut self,
227 key_branch: &[u8],
228 callback: &mut impl ProcessEncodedNode<TrieHash<T>>,
229 branch_d: usize,
230 is_root: bool,
231 nkey: Option<(usize, usize)>,
232 ) -> ChildReference<TrieHash<T>> {
233 let (children, v, depth) = self.0.pop().expect("checked");
234
235 debug_assert!(branch_d == depth);
236 let nkeyix = nkey.unwrap_or((branch_d, 0));
238 let pr = NibbleSlice::new_offset(&key_branch, nkeyix.0);
239 let hashed;
240 let value = if let Some(v) = v.as_ref() {
241 Some(if let Some(value) = Value::new_inline(v.as_ref(), T::MAX_INLINE_VALUE) {
242 value
243 } else {
244 let mut prefix = NibbleSlice::new_offset(&key_branch, 0);
245 prefix.advance(branch_d);
246 hashed = callback.process_inner_hashed_value(prefix.left(), v.as_ref());
247 Value::Node(hashed.as_ref())
248 })
249 } else {
250 None
251 };
252
253 let encoded = T::Codec::branch_node_nibbled(
254 pr.right_range_iter(nkeyix.1),
255 nkeyix.1,
256 children.iter(),
257 value,
258 );
259 callback.process(pr.left(), encoded, is_root)
260 }
261}
262
263pub fn trie_visit<T, I, A, B, F>(input: I, callback: &mut F)
268where
269 T: TrieLayout,
270 I: IntoIterator<Item = (A, B)>,
271 A: AsRef<[u8]> + Ord,
272 B: AsRef<[u8]>,
273 F: ProcessEncodedNode<TrieHash<T>>,
274{
275 let mut depth_queue = CacheAccum::<T, B>::new();
276 let mut iter_input = input.into_iter();
278 if let Some(mut previous_value) = iter_input.next() {
279 let mut last_depth = 0;
281
282 let mut single = true;
283 for (k, v) in iter_input {
284 single = false;
285 let common_depth =
286 nibble_ops::biggest_depth(&previous_value.0.as_ref()[..], &k.as_ref()[..]);
287 let depth_item = common_depth;
289 if common_depth == previous_value.0.as_ref().len() * nibble_ops::NIBBLE_PER_BYTE {
290 depth_queue.set_cache_value(common_depth, Some(previous_value.1));
293 } else if depth_item >= last_depth {
294 depth_queue.flush_value(callback, depth_item, &previous_value);
296 } else if depth_item < last_depth {
297 depth_queue.flush_value(callback, last_depth, &previous_value);
299 let ref_branches = previous_value.0;
300 depth_queue.flush_branch(callback, ref_branches, depth_item, false);
301 }
302
303 previous_value = (k, v);
304 last_depth = depth_item;
305 }
306 if single {
308 let (k2, v2) = previous_value;
310 let nkey = NibbleSlice::new_offset(&k2.as_ref()[..], last_depth);
311 let pr = NibbleSlice::new_offset(
312 &k2.as_ref()[..],
313 k2.as_ref().len() * nibble_ops::NIBBLE_PER_BYTE - nkey.len(),
314 );
315
316 let hashed;
317 let value = if let Some(value) = Value::new_inline(v2.as_ref(), T::MAX_INLINE_VALUE) {
318 value
319 } else {
320 hashed = callback.process_inner_hashed_value((k2.as_ref(), None), v2.as_ref());
321 Value::Node(hashed.as_ref())
322 };
323
324 let encoded = T::Codec::leaf_node(nkey.right_iter(), nkey.len(), value);
325 callback.process(pr.left(), encoded, true);
326 } else {
327 depth_queue.flush_value(callback, last_depth, &previous_value);
328 let ref_branches = previous_value.0;
329 depth_queue.flush_branch(callback, ref_branches, 0, true);
330 }
331 } else {
332 callback.process(hash_db::EMPTY_PREFIX, T::Codec::empty_node().to_vec(), true);
334 }
335}
336
337pub trait ProcessEncodedNode<HO> {
339 fn process(
347 &mut self,
348 prefix: Prefix,
349 encoded_node: Vec<u8>,
350 is_root: bool,
351 ) -> ChildReference<HO>;
352
353 fn process_inner_hashed_value(&mut self, prefix: Prefix, value: &[u8]) -> HO;
355}
356
357pub struct TrieBuilder<'a, T: TrieLayout, DB> {
361 db: &'a mut DB,
362 pub root: Option<TrieHash<T>>,
363}
364
365impl<'a, T: TrieLayout, DB> TrieBuilder<'a, T, DB> {
366 pub fn new(db: &'a mut DB) -> Self {
367 TrieBuilder { db, root: None }
368 }
369}
370
371impl<'a, T, DB> ProcessEncodedNode<TrieHash<T>> for TrieBuilder<'a, T, DB>
372where
373 T: TrieLayout,
374 DB: HashDB<T::Hash, DBValue>,
375{
376 fn process(
377 &mut self,
378 prefix: Prefix,
379 encoded_node: Vec<u8>,
380 is_root: bool,
381 ) -> ChildReference<TrieHash<T>> {
382 let len = encoded_node.len();
383 if !is_root && len < <T::Hash as Hasher>::LENGTH {
384 let mut h = <<T::Hash as Hasher>::Out as Default>::default();
385 h.as_mut()[..len].copy_from_slice(&encoded_node[..len]);
386
387 return ChildReference::Inline(h, len)
388 }
389 let hash = self.db.insert(prefix, &encoded_node[..]);
390 if is_root {
391 self.root = Some(hash);
392 };
393 ChildReference::Hash(hash)
394 }
395
396 fn process_inner_hashed_value(&mut self, prefix: Prefix, value: &[u8]) -> TrieHash<T> {
397 self.db.insert(prefix, value)
398 }
399}
400
401pub struct TrieRoot<T: TrieLayout> {
403 pub root: Option<TrieHash<T>>,
405}
406
407impl<T: TrieLayout> Default for TrieRoot<T> {
408 fn default() -> Self {
409 TrieRoot { root: None }
410 }
411}
412
413impl<T: TrieLayout> ProcessEncodedNode<TrieHash<T>> for TrieRoot<T> {
414 fn process(
415 &mut self,
416 _: Prefix,
417 encoded_node: Vec<u8>,
418 is_root: bool,
419 ) -> ChildReference<TrieHash<T>> {
420 let len = encoded_node.len();
421 if !is_root && len < <T::Hash as Hasher>::LENGTH {
422 let mut h = <<T::Hash as Hasher>::Out as Default>::default();
423 h.as_mut()[..len].copy_from_slice(&encoded_node[..len]);
424
425 return ChildReference::Inline(h, len)
426 }
427 let hash = <T::Hash as Hasher>::hash(encoded_node.as_slice());
428 if is_root {
429 self.root = Some(hash);
430 };
431 ChildReference::Hash(hash)
432 }
433
434 fn process_inner_hashed_value(&mut self, _prefix: Prefix, value: &[u8]) -> TrieHash<T> {
435 <T::Hash as Hasher>::hash(value)
436 }
437}
438
439pub struct TrieRootUnhashed<T: TrieLayout> {
441 pub root: Option<Vec<u8>>,
443 _ph: PhantomData<T>,
444}
445
446impl<T: TrieLayout> Default for TrieRootUnhashed<T> {
447 fn default() -> Self {
448 TrieRootUnhashed { root: None, _ph: PhantomData }
449 }
450}
451
452#[cfg(feature = "std")]
453pub struct TrieRootPrint<T: TrieLayout> {
456 pub root: Option<TrieHash<T>>,
458 _ph: PhantomData<T>,
459}
460
461#[cfg(feature = "std")]
462impl<T: TrieLayout> Default for TrieRootPrint<T> {
463 fn default() -> Self {
464 TrieRootPrint { root: None, _ph: PhantomData }
465 }
466}
467
468#[cfg(feature = "std")]
469impl<T: TrieLayout> ProcessEncodedNode<TrieHash<T>> for TrieRootPrint<T> {
470 fn process(
471 &mut self,
472 p: Prefix,
473 encoded_node: Vec<u8>,
474 is_root: bool,
475 ) -> ChildReference<TrieHash<T>> {
476 println!("Encoded node: {:x?}", &encoded_node);
477 println!(" with prefix: {:x?}", &p);
478 let len = encoded_node.len();
479 if !is_root && len < <T::Hash as Hasher>::LENGTH {
480 let mut h = <<T::Hash as Hasher>::Out as Default>::default();
481 h.as_mut()[..len].copy_from_slice(&encoded_node[..len]);
482
483 println!(" inline len {}", len);
484 return ChildReference::Inline(h, len)
485 }
486 let hash = <T::Hash as Hasher>::hash(encoded_node.as_slice());
487 if is_root {
488 self.root = Some(hash);
489 };
490 println!(" hashed to {:x?}", hash.as_ref());
491 ChildReference::Hash(hash)
492 }
493
494 fn process_inner_hashed_value(&mut self, _prefix: Prefix, value: &[u8]) -> TrieHash<T> {
495 println!("Hashed node: {:x?}", &value);
496 <T::Hash as Hasher>::hash(value)
497 }
498}
499
500impl<T: TrieLayout> ProcessEncodedNode<TrieHash<T>> for TrieRootUnhashed<T> {
501 fn process(
502 &mut self,
503 _: Prefix,
504 encoded_node: Vec<u8>,
505 is_root: bool,
506 ) -> ChildReference<<T::Hash as Hasher>::Out> {
507 let len = encoded_node.len();
508 if !is_root && len < <T::Hash as Hasher>::LENGTH {
509 let mut h = <<T::Hash as Hasher>::Out as Default>::default();
510 h.as_mut()[..len].copy_from_slice(&encoded_node[..len]);
511
512 return ChildReference::Inline(h, len)
513 }
514 let hash = <T::Hash as Hasher>::hash(encoded_node.as_slice());
515
516 if is_root {
517 self.root = Some(encoded_node);
518 };
519 ChildReference::Hash(hash)
520 }
521
522 fn process_inner_hashed_value(&mut self, _prefix: Prefix, value: &[u8]) -> TrieHash<T> {
523 <T::Hash as Hasher>::hash(value)
524 }
525}