1#![cfg_attr(not(feature = "std"), no_std)]
20
21#[cfg(not(feature = "std"))]
22extern crate alloc;
23
24
25#[cfg(feature = "std")]
26mod rstd {
27 pub use std::vec::Vec;
28 pub use std::cmp;
29 pub use std::collections::{BTreeMap, VecDeque};
30}
31
32#[cfg(not(feature = "std"))]
33mod rstd {
34 pub use core::cmp;
35 pub use alloc::collections::{BTreeMap, VecDeque};
36 pub use alloc::vec::Vec;
37}
38
39use self::rstd::*;
40
41pub use tetsy_hash_db::Hasher;
42
43pub trait TrieStream {
45 fn new() -> Self;
47 fn append_empty_data(&mut self);
49 fn begin_branch(
52 &mut self,
53 maybe_key: Option<&[u8]>,
54 maybe_value: Option<&[u8]>,
55 has_children: impl Iterator<Item = bool>,
56 );
57 fn append_empty_child(&mut self) {}
59 fn end_branch(&mut self, _value: Option<&[u8]>) {}
62 fn append_leaf(&mut self, key: &[u8], value: &[u8]);
64 fn append_extension(&mut self, key: &[u8]);
66 fn append_substream<H: Hasher>(&mut self, other: Self);
68 fn out(self) -> Vec<u8>;
70}
71
72fn shared_prefix_length<T: Eq>(first: &[T], second: &[T]) -> usize {
73 first.iter()
74 .zip(second.iter())
75 .position(|(f, s)| f != s)
76 .unwrap_or_else(|| cmp::min(first.len(), second.len()))
77}
78
79pub fn tetsy_trie_root<H, S, I, A, B>(input: I) -> H::Out where
97 I: IntoIterator<Item = (A, B)>,
98 A: AsRef<[u8]> + Ord,
99 B: AsRef<[u8]>,
100 H: Hasher,
101 S: TrieStream,
102{
103 tetsy_trie_root_inner::<H, S, I, A, B>(input, false)
104}
105
106fn tetsy_trie_root_inner<H, S, I, A, B>(input: I, no_extension: bool) -> H::Out where
107 I: IntoIterator<Item = (A, B)>,
108 A: AsRef<[u8]> + Ord,
109 B: AsRef<[u8]>,
110 H: Hasher,
111 S: TrieStream,
112{
113 let input = input
115 .into_iter()
116 .collect::<BTreeMap<_, _>>();
117
118 let mut nibbles = Vec::with_capacity(input.keys().map(|k| k.as_ref().len()).sum::<usize>() * 2);
120 let mut lens = Vec::with_capacity(input.len() + 1);
121 lens.push(0);
122 for k in input.keys() {
123 for &b in k.as_ref() {
124 nibbles.push(b >> 4);
125 nibbles.push(b & 0x0F);
126 }
127 lens.push(nibbles.len());
128 }
129
130 let input = input.into_iter().zip(lens.windows(2))
132 .map(|((_, v), w)| (&nibbles[w[0]..w[1]], v))
133 .collect::<Vec<_>>();
134
135 let mut stream = S::new();
136 build_trie::<H, S, _, _>(&input, 0, &mut stream, no_extension);
137 H::hash(&stream.out())
138}
139
140pub fn tetsy_trie_root_no_extension<H, S, I, A, B>(input: I) -> H::Out where
143 I: IntoIterator<Item = (A, B)>,
144 A: AsRef<[u8]> + Ord,
145 B: AsRef<[u8]>,
146 H: Hasher,
147 S: TrieStream,
148{
149 tetsy_trie_root_inner::<H, S, I, A, B>(input, true)
150}
151
152pub fn unhashed_trie<H, S, I, A, B>(input: I) -> Vec<u8> where
157 I: IntoIterator<Item = (A, B)>,
158 A: AsRef<[u8]> + Ord,
159 B: AsRef<[u8]>,
160 H: Hasher,
161 S: TrieStream,
162{
163 unhashed_trie_inner::<H, S, I, A, B>(input, false)
164}
165
166fn unhashed_trie_inner<H, S, I, A, B>(input: I, no_extension: bool) -> Vec<u8> where
167 I: IntoIterator<Item = (A, B)>,
168 A: AsRef<[u8]> + Ord,
169 B: AsRef<[u8]>,
170 H: Hasher,
171 S: TrieStream,
172{
173 let input = input
175 .into_iter()
176 .collect::<BTreeMap<_, _>>();
177
178 let mut nibbles = Vec::with_capacity(input.keys().map(|k| k.as_ref().len()).sum::<usize>() * 2);
179 let mut lens = Vec::with_capacity(input.len() + 1);
180 lens.push(0);
181 for k in input.keys() {
182 for &b in k.as_ref() {
183 nibbles.push(b >> 4);
184 nibbles.push(b & 0x0F);
185 }
186 lens.push(nibbles.len());
187 }
188
189 let input = input.into_iter().zip(lens.windows(2))
191 .map(|((_, v), w)| (&nibbles[w[0]..w[1]], v))
192 .collect::<Vec<_>>();
193
194 let mut stream = S::new();
195 build_trie::<H, S, _, _>(&input, 0, &mut stream, no_extension);
196 stream.out()
197}
198
199pub fn unhashed_trie_no_extension<H, S, I, A, B>(input: I) -> Vec<u8> where
202 I: IntoIterator<Item = (A, B)>,
203 A: AsRef<[u8]> + Ord,
204 B: AsRef<[u8]>,
205 H: Hasher,
206 S: TrieStream,
207{
208 unhashed_trie_inner::<H, S, I, A, B>(input, true)
209}
210
211pub fn sec_tetsy_trie_root<H, S, I, A, B>(input: I) -> H::Out where
229 I: IntoIterator<Item = (A, B)>,
230 A: AsRef<[u8]>,
231 B: AsRef<[u8]>,
232 H: Hasher,
233 H::Out: Ord,
234 S: TrieStream,
235{
236 tetsy_trie_root::<H, S, _, _, _>(input.into_iter().map(|(k, v)| (H::hash(k.as_ref()), v)))
237}
238
239fn build_trie<H, S, A, B>(input: &[(A, B)], cursor: usize, stream: &mut S, no_extension: bool) where
242 A: AsRef<[u8]>,
243 B: AsRef<[u8]>,
244 H: Hasher,
245 S: TrieStream,
246{
247 match input.len() {
248 0 => stream.append_empty_data(),
250 1 => stream.append_leaf(&input[0].0.as_ref()[cursor..], &input[0].1.as_ref() ),
252 _ => {
255 let (key, value) = (&input[0].0.as_ref(), input[0].1.as_ref());
256 let shared_nibble_count = input.iter().skip(1).fold(key.len(), |acc, &(ref k, _)| {
260 cmp::min( shared_prefix_length(key, k.as_ref()), acc )
261 });
262 let (cursor, o_branch_slice) = if no_extension {
267 if shared_nibble_count > cursor {
268 (shared_nibble_count, Some(&key[cursor..shared_nibble_count]))
269 } else {
270 (cursor, Some(&key[0..0]))
271 }
272 } else if shared_nibble_count > cursor {
273 stream.append_extension(&key[cursor..shared_nibble_count]);
274 build_trie_trampoline::<H, _, _, _>(
275 input,
276 shared_nibble_count,
277 stream,
278 no_extension,
279 );
280 return;
281 } else { (cursor, None) };
282
283 let value = if cursor == key.len() { Some(value) } else { None };
289
290 let mut shared_nibble_counts = [0usize; 16];
292 {
293 let mut begin = match value { None => 0, _ => 1 };
298 for i in 0..16 {
299 shared_nibble_counts[i] = input[begin..].iter()
300 .take_while(|(k, _)| k.as_ref()[cursor] == i as u8)
301 .count();
302 begin += shared_nibble_counts[i];
303 }
304 }
305
306 stream.begin_branch(o_branch_slice, value, shared_nibble_counts.iter().map(|&n| n > 0));
308
309 let mut begin = match value { None => 0, _ => 1 };
312 for &count in &shared_nibble_counts {
313 if count > 0 {
314 build_trie_trampoline::<H, S, _, _>(
315 &input[begin..(begin + count)],
316 cursor + 1,
317 stream,
318 no_extension,
319 );
320 begin += count;
321 } else {
322 stream.append_empty_child();
323 }
324 }
325
326 stream.end_branch(value);
327 }
328 }
329}
330
331fn build_trie_trampoline<H, S, A, B>(
332 input: &[(A, B)],
333 cursor: usize,
334 stream: &mut S,
335 no_extension: bool,
336) where
337 A: AsRef<[u8]>,
338 B: AsRef<[u8]>,
339 H: Hasher,
340 S: TrieStream,
341{
342 let mut substream = S::new();
343 build_trie::<H, _, _, _>(input, cursor, &mut substream, no_extension);
344 stream.append_substream::<H>(substream);
345}