1#![cfg_attr(not(feature = "std"), no_std)]
20
21#[cfg(not(feature = "std"))]
22extern crate alloc;
23
24#[cfg(feature = "std")]
25mod rstd {
26 pub use std::{
27 cmp,
28 collections::{BTreeMap, VecDeque},
29 vec::Vec,
30 };
31}
32
33#[cfg(not(feature = "std"))]
34mod rstd {
35 pub use alloc::{
36 collections::{BTreeMap, VecDeque},
37 vec::Vec,
38 };
39 pub use core::cmp;
40}
41
42use self::rstd::*;
43
44pub use hash_db::Hasher;
45
46#[derive(Clone)]
48pub enum Value<'a> {
49 Inline(&'a [u8]),
51 Node(Vec<u8>),
53}
54
55impl<'a> Value<'a> {
56 fn new<H: Hasher>(value: &'a [u8], threshold: Option<u32>) -> Value<'a> {
57 if let Some(threshold) = threshold {
58 if value.len() >= threshold as usize {
59 Value::Node(H::hash(value).as_ref().to_vec())
60 } else {
61 Value::Inline(value)
62 }
63 } else {
64 Value::Inline(value)
65 }
66 }
67}
68
69pub trait TrieStream {
71 fn new() -> Self;
73 fn append_empty_data(&mut self);
75 fn begin_branch(
78 &mut self,
79 maybe_key: Option<&[u8]>,
80 maybe_value: Option<Value>,
81 has_children: impl Iterator<Item = bool>,
82 );
83 fn append_empty_child(&mut self) {}
85 fn end_branch(&mut self, _value: Option<Value>) {}
88 fn append_leaf(&mut self, key: &[u8], value: Value);
90 fn append_extension(&mut self, key: &[u8]);
92 fn append_substream<H: Hasher>(&mut self, other: Self);
94 fn out(self) -> Vec<u8>;
96}
97
98fn shared_prefix_length<T: Eq>(first: &[T], second: &[T]) -> usize {
99 first
100 .iter()
101 .zip(second.iter())
102 .position(|(f, s)| f != s)
103 .unwrap_or_else(|| cmp::min(first.len(), second.len()))
104}
105
106pub fn trie_root<H, S, I, A, B>(input: I, threshold: Option<u32>) -> H::Out
124where
125 I: IntoIterator<Item = (A, B)>,
126 A: AsRef<[u8]> + Ord,
127 B: AsRef<[u8]>,
128 H: Hasher,
129 S: TrieStream,
130{
131 trie_root_inner::<H, S, I, A, B>(input, false, threshold)
132}
133
134fn trie_root_inner<H, S, I, A, B>(input: I, no_extension: bool, threshold: Option<u32>) -> H::Out
135where
136 I: IntoIterator<Item = (A, B)>,
137 A: AsRef<[u8]> + Ord,
138 B: AsRef<[u8]>,
139 H: Hasher,
140 S: TrieStream,
141{
142 let input = input.into_iter().collect::<BTreeMap<_, _>>();
144
145 let mut nibbles = Vec::with_capacity(input.keys().map(|k| k.as_ref().len()).sum::<usize>() * 2);
147 let mut lens = Vec::with_capacity(input.len() + 1);
148 lens.push(0);
149 for k in input.keys() {
150 for &b in k.as_ref() {
151 nibbles.push(b >> 4);
152 nibbles.push(b & 0x0F);
153 }
154 lens.push(nibbles.len());
155 }
156
157 let input = input
159 .into_iter()
160 .zip(lens.windows(2))
161 .map(|((_, v), w)| (&nibbles[w[0]..w[1]], v))
162 .collect::<Vec<_>>();
163
164 let mut stream = S::new();
165 build_trie::<H, S, _, _>(&input, 0, &mut stream, no_extension, threshold);
166 H::hash(&stream.out())
167}
168
169pub fn trie_root_no_extension<H, S, I, A, B>(input: I, threshold: Option<u32>) -> H::Out
172where
173 I: IntoIterator<Item = (A, B)>,
174 A: AsRef<[u8]> + Ord,
175 B: AsRef<[u8]>,
176 H: Hasher,
177 S: TrieStream,
178{
179 trie_root_inner::<H, S, I, A, B>(input, true, threshold)
180}
181
182pub fn unhashed_trie<H, S, I, A, B>(input: I, threshold: Option<u32>) -> Vec<u8>
187where
188 I: IntoIterator<Item = (A, B)>,
189 A: AsRef<[u8]> + Ord,
190 B: AsRef<[u8]>,
191 H: Hasher,
192 S: TrieStream,
193{
194 unhashed_trie_inner::<H, S, I, A, B>(input, false, threshold)
195}
196
197fn unhashed_trie_inner<H, S, I, A, B>(
198 input: I,
199 no_extension: bool,
200 threshold: Option<u32>,
201) -> Vec<u8>
202where
203 I: IntoIterator<Item = (A, B)>,
204 A: AsRef<[u8]> + Ord,
205 B: AsRef<[u8]>,
206 H: Hasher,
207 S: TrieStream,
208{
209 let input = input.into_iter().collect::<BTreeMap<_, _>>();
211
212 let mut nibbles = Vec::with_capacity(input.keys().map(|k| k.as_ref().len()).sum::<usize>() * 2);
213 let mut lens = Vec::with_capacity(input.len() + 1);
214 lens.push(0);
215 for k in input.keys() {
216 for &b in k.as_ref() {
217 nibbles.push(b >> 4);
218 nibbles.push(b & 0x0F);
219 }
220 lens.push(nibbles.len());
221 }
222
223 let input = input
225 .into_iter()
226 .zip(lens.windows(2))
227 .map(|((_, v), w)| (&nibbles[w[0]..w[1]], v))
228 .collect::<Vec<_>>();
229
230 let mut stream = S::new();
231 build_trie::<H, S, _, _>(&input, 0, &mut stream, no_extension, threshold);
232 stream.out()
233}
234
235pub fn unhashed_trie_no_extension<H, S, I, A, B>(input: I, threshold: Option<u32>) -> Vec<u8>
238where
239 I: IntoIterator<Item = (A, B)>,
240 A: AsRef<[u8]> + Ord,
241 B: AsRef<[u8]>,
242 H: Hasher,
243 S: TrieStream,
244{
245 unhashed_trie_inner::<H, S, I, A, B>(input, true, threshold)
246}
247
248pub fn sec_trie_root<H, S, I, A, B>(input: I, threshold: Option<u32>) -> H::Out
266where
267 I: IntoIterator<Item = (A, B)>,
268 A: AsRef<[u8]>,
269 B: AsRef<[u8]>,
270 H: Hasher,
271 H::Out: Ord,
272 S: TrieStream,
273{
274 trie_root::<H, S, _, _, _>(input.into_iter().map(|(k, v)| (H::hash(k.as_ref()), v)), threshold)
275}
276
277fn build_trie<H, S, A, B>(
280 input: &[(A, B)],
281 cursor: usize,
282 stream: &mut S,
283 no_extension: bool,
284 threshold: Option<u32>,
285) where
286 A: AsRef<[u8]>,
287 B: AsRef<[u8]>,
288 H: Hasher,
289 S: TrieStream,
290{
291 match input.len() {
292 0 => stream.append_empty_data(),
294 1 => {
296 let value = Value::new::<H>(input[0].1.as_ref(), threshold);
297 stream.append_leaf(&input[0].0.as_ref()[cursor..], value)
298 },
299 _ => {
302 let (key, value) = (&input[0].0.as_ref(), input[0].1.as_ref());
303 let shared_nibble_count = input.iter().skip(1).fold(key.len(), |acc, &(ref k, _)| {
307 cmp::min(shared_prefix_length(key, k.as_ref()), acc)
308 });
309 let (cursor, o_branch_slice) = if no_extension {
314 if shared_nibble_count > cursor {
315 (shared_nibble_count, Some(&key[cursor..shared_nibble_count]))
316 } else {
317 (cursor, Some(&key[0..0]))
318 }
319 } else if shared_nibble_count > cursor {
320 stream.append_extension(&key[cursor..shared_nibble_count]);
321 build_trie_trampoline::<H, _, _, _>(
322 input,
323 shared_nibble_count,
324 stream,
325 no_extension,
326 threshold,
327 );
328 return
329 } else {
330 (cursor, None)
331 };
332
333 let value = if cursor == key.len() { Some(value) } else { None };
339
340 let mut shared_nibble_counts = [0usize; 16];
342 {
343 let mut begin = match value {
348 None => 0,
349 _ => 1,
350 };
351 for i in 0..16 {
352 shared_nibble_counts[i] = input[begin..]
353 .iter()
354 .take_while(|(k, _)| k.as_ref()[cursor] == i as u8)
355 .count();
356 begin += shared_nibble_counts[i];
357 }
358 }
359
360 let value = value.map(|v| Value::new::<H>(v, threshold));
362 stream.begin_branch(
363 o_branch_slice,
364 value.clone(),
365 shared_nibble_counts.iter().map(|&n| n > 0),
366 );
367
368 let mut begin = match value {
371 None => 0,
372 _ => 1,
373 };
374 for &count in &shared_nibble_counts {
375 if count > 0 {
376 build_trie_trampoline::<H, S, _, _>(
377 &input[begin..(begin + count)],
378 cursor + 1,
379 stream,
380 no_extension,
381 threshold.clone(),
382 );
383 begin += count;
384 } else {
385 stream.append_empty_child();
386 }
387 }
388
389 stream.end_branch(value);
390 },
391 }
392}
393
394fn build_trie_trampoline<H, S, A, B>(
395 input: &[(A, B)],
396 cursor: usize,
397 stream: &mut S,
398 no_extension: bool,
399 threshold: Option<u32>,
400) where
401 A: AsRef<[u8]>,
402 B: AsRef<[u8]>,
403 H: Hasher,
404 S: TrieStream,
405{
406 let mut substream = S::new();
407 build_trie::<H, _, _, _>(input, cursor, &mut substream, no_extension, threshold);
408 stream.append_substream::<H>(substream);
409}