1use super::{CodecError as Error, NodeCodec as NodeCodecT, *};
18use trie_db::node::Value;
19
20pub struct HashedValueNoExt;
22
23pub struct HashedValueNoExtThreshold<const C: u32>;
26
27impl TrieLayout for HashedValueNoExt {
28 const USE_EXTENSION: bool = false;
29 const ALLOW_EMPTY: bool = false;
30 const MAX_INLINE_VALUE: Option<u32> = None;
31
32 type Hash = RefHasher;
33 type Codec = ReferenceNodeCodecNoExtMeta<RefHasher>;
34}
35
36impl<const C: u32> TrieLayout for HashedValueNoExtThreshold<C> {
37 const USE_EXTENSION: bool = false;
38 const ALLOW_EMPTY: bool = false;
39 const MAX_INLINE_VALUE: Option<u32> = Some(C);
40
41 type Hash = RefHasher;
42 type Codec = ReferenceNodeCodecNoExtMeta<RefHasher>;
43}
44
45pub mod trie_constants {
47 const FIRST_PREFIX: u8 = 0b_00 << 6;
48 pub const NIBBLE_SIZE_BOUND: usize = u16::max_value() as usize;
49 pub const LEAF_PREFIX_MASK: u8 = 0b_01 << 6;
50 pub const BRANCH_WITHOUT_MASK: u8 = 0b_10 << 6;
51 pub const BRANCH_WITH_MASK: u8 = 0b_11 << 6;
52 pub const EMPTY_TRIE: u8 = FIRST_PREFIX | (0b_00 << 4);
53 pub const ALT_HASHING_LEAF_PREFIX_MASK: u8 = FIRST_PREFIX | (0b_1 << 5);
54 pub const ALT_HASHING_BRANCH_WITH_MASK: u8 = FIRST_PREFIX | (0b_01 << 4);
55 pub const ESCAPE_COMPACT_HEADER: u8 = EMPTY_TRIE | 0b_00_01;
56}
57
58#[derive(Default, Clone)]
59pub struct NodeCodec<H>(PhantomData<H>);
60
61impl<H: Hasher> NodeCodec<H> {
62 fn decode_plan_inner_hashed(data: &[u8]) -> Result<NodePlan, Error> {
63 let mut input = ByteSliceInput::new(data);
64
65 let header = NodeHeader::decode(&mut input)?;
66 let contains_hash = header.contains_hash_of_value();
67
68 let branch_has_value = if let NodeHeader::Branch(has_value, _) = &header {
69 *has_value
70 } else {
71 true
73 };
74
75 match header {
76 NodeHeader::Null => Ok(NodePlan::Empty),
77 NodeHeader::HashedValueBranch(nibble_count) | NodeHeader::Branch(_, nibble_count) => {
78 let padding = nibble_count % nibble_ops::NIBBLE_PER_BYTE != 0;
79 if padding && nibble_ops::pad_left(data[input.offset]) != 0 {
81 return Err(CodecError::from("Bad format"))
82 }
83 let partial = input.take(
84 (nibble_count + (nibble_ops::NIBBLE_PER_BYTE - 1)) /
85 nibble_ops::NIBBLE_PER_BYTE,
86 )?;
87 let partial_padding = nibble_ops::number_padding(nibble_count);
88 let bitmap_range = input.take(BITMAP_LENGTH)?;
89 let bitmap = Bitmap::decode(&data[bitmap_range])?;
90 let value = if branch_has_value {
91 Some(if contains_hash {
92 ValuePlan::Node(input.take(H::LENGTH)?)
93 } else {
94 let count = <Compact<u32>>::decode(&mut input)?.0 as usize;
95 ValuePlan::Inline(input.take(count)?)
96 })
97 } else {
98 None
99 };
100 let mut children = [
101 None, None, None, None, None, None, None, None, None, None, None, None, None,
102 None, None, None,
103 ];
104 for i in 0..nibble_ops::NIBBLE_LENGTH {
105 if bitmap.value_at(i) {
106 let count = <Compact<u32>>::decode(&mut input)?.0 as usize;
107 let range = input.take(count)?;
108 children[i] = Some(if count == H::LENGTH {
109 NodeHandlePlan::Hash(range)
110 } else {
111 NodeHandlePlan::Inline(range)
112 });
113 }
114 }
115 Ok(NodePlan::NibbledBranch {
116 partial: NibbleSlicePlan::new(partial, partial_padding),
117 value,
118 children,
119 })
120 },
121 NodeHeader::HashedValueLeaf(nibble_count) | NodeHeader::Leaf(nibble_count) => {
122 let padding = nibble_count % nibble_ops::NIBBLE_PER_BYTE != 0;
123 if padding && nibble_ops::pad_left(data[input.offset]) != 0 {
125 return Err(CodecError::from("Bad format"))
126 }
127 let partial = input.take(
128 (nibble_count + (nibble_ops::NIBBLE_PER_BYTE - 1)) /
129 nibble_ops::NIBBLE_PER_BYTE,
130 )?;
131 let partial_padding = nibble_ops::number_padding(nibble_count);
132 let value = if contains_hash {
133 ValuePlan::Node(input.take(H::LENGTH)?)
134 } else {
135 let count = <Compact<u32>>::decode(&mut input)?.0 as usize;
136 ValuePlan::Inline(input.take(count)?)
137 };
138
139 Ok(NodePlan::Leaf {
140 partial: NibbleSlicePlan::new(partial, partial_padding),
141 value,
142 })
143 },
144 }
145 }
146}
147
148impl<H> NodeCodecT for NodeCodec<H>
149where
150 H: Hasher,
151{
152 const ESCAPE_HEADER: Option<u8> = Some(trie_constants::ESCAPE_COMPACT_HEADER);
153 type Error = Error;
154 type HashOut = H::Out;
155
156 fn hashed_null_node() -> <H as Hasher>::Out {
157 H::hash(<Self as NodeCodecT>::empty_node())
158 }
159
160 fn decode_plan(data: &[u8]) -> Result<NodePlan, Self::Error> {
161 Self::decode_plan_inner_hashed(data)
162 }
163
164 fn is_empty_node(data: &[u8]) -> bool {
165 data == <Self as NodeCodecT>::empty_node()
166 }
167
168 fn empty_node() -> &'static [u8] {
169 &[trie_constants::EMPTY_TRIE]
170 }
171
172 fn leaf_node(partial: impl Iterator<Item = u8>, number_nibble: usize, value: Value) -> Vec<u8> {
173 let contains_hash = matches!(&value, Value::Node(..));
174 let mut output = if contains_hash {
175 partial_from_iterator_encode(partial, number_nibble, NodeKind::HashedValueLeaf)
176 } else {
177 partial_from_iterator_encode(partial, number_nibble, NodeKind::Leaf)
178 };
179 match value {
180 Value::Inline(value) => {
181 Compact(value.len() as u32).encode_to(&mut output);
182 output.extend_from_slice(value);
183 },
184 Value::Node(hash) => {
185 debug_assert!(hash.len() == H::LENGTH);
186 output.extend_from_slice(hash);
187 },
188 }
189 output
190 }
191
192 fn extension_node(
193 _partial: impl Iterator<Item = u8>,
194 _nbnibble: usize,
195 _child: ChildReference<<H as Hasher>::Out>,
196 ) -> Vec<u8> {
197 unreachable!("Codec without extension.")
198 }
199
200 fn branch_node(
201 _children: impl Iterator<Item = impl Borrow<Option<ChildReference<<H as Hasher>::Out>>>>,
202 _maybe_value: Option<Value>,
203 ) -> Vec<u8> {
204 unreachable!("Codec without extension.")
205 }
206
207 fn branch_node_nibbled(
208 partial: impl Iterator<Item = u8>,
209 number_nibble: usize,
210 children: impl Iterator<Item = impl Borrow<Option<ChildReference<<H as Hasher>::Out>>>>,
211 value: Option<Value>,
212 ) -> Vec<u8> {
213 let contains_hash = matches!(&value, Some(Value::Node(..)));
214 let mut output = match (&value, contains_hash) {
215 (&None, _) =>
216 partial_from_iterator_encode(partial, number_nibble, NodeKind::BranchNoValue),
217 (_, false) =>
218 partial_from_iterator_encode(partial, number_nibble, NodeKind::BranchWithValue),
219 (_, true) =>
220 partial_from_iterator_encode(partial, number_nibble, NodeKind::HashedValueBranch),
221 };
222
223 let bitmap_index = output.len();
224 let mut bitmap: [u8; BITMAP_LENGTH] = [0; BITMAP_LENGTH];
225 (0..BITMAP_LENGTH).for_each(|_| output.push(0));
226 match value {
227 Some(Value::Inline(value)) => {
228 Compact(value.len() as u32).encode_to(&mut output);
229 output.extend_from_slice(value);
230 },
231 Some(Value::Node(hash)) => {
232 debug_assert!(hash.len() == H::LENGTH);
233 output.extend_from_slice(hash);
234 },
235 None => (),
236 }
237 Bitmap::encode(
238 children.map(|maybe_child| match maybe_child.borrow() {
239 Some(ChildReference::Hash(h)) => {
240 h.as_ref().encode_to(&mut output);
241 true
242 },
243 &Some(ChildReference::Inline(inline_data, len)) => {
244 inline_data.as_ref()[..len].encode_to(&mut output);
245 true
246 },
247 None => false,
248 }),
249 bitmap.as_mut(),
250 );
251 output[bitmap_index..bitmap_index + BITMAP_LENGTH]
252 .copy_from_slice(&bitmap[..BITMAP_LENGTH]);
253 output
254 }
255}
256
257fn partial_from_iterator_encode<I: Iterator<Item = u8>>(
262 partial: I,
263 nibble_count: usize,
264 node_kind: NodeKind,
265) -> Vec<u8> {
266 let nibble_count = std::cmp::min(trie_constants::NIBBLE_SIZE_BOUND, nibble_count);
267
268 let mut output = Vec::with_capacity(4 + (nibble_count / nibble_ops::NIBBLE_PER_BYTE));
269 match node_kind {
270 NodeKind::Leaf => NodeHeader::Leaf(nibble_count).encode_to(&mut output),
271 NodeKind::BranchWithValue => NodeHeader::Branch(true, nibble_count).encode_to(&mut output),
272 NodeKind::BranchNoValue => NodeHeader::Branch(false, nibble_count).encode_to(&mut output),
273 NodeKind::HashedValueLeaf =>
274 NodeHeader::HashedValueLeaf(nibble_count).encode_to(&mut output),
275 NodeKind::HashedValueBranch =>
276 NodeHeader::HashedValueBranch(nibble_count).encode_to(&mut output),
277 };
278 output.extend(partial);
279 output
280}
281
282#[derive(Copy, Clone, PartialEq, Eq, Debug)]
284pub(crate) enum NodeHeader {
285 Null,
286 Branch(bool, usize),
288 Leaf(usize),
290 HashedValueBranch(usize),
292 HashedValueLeaf(usize),
294}
295
296impl NodeHeader {
297 fn contains_hash_of_value(&self) -> bool {
298 match self {
299 NodeHeader::HashedValueBranch(_) | NodeHeader::HashedValueLeaf(_) => true,
300 _ => false,
301 }
302 }
303}
304
305pub(crate) enum NodeKind {
307 Leaf,
308 BranchNoValue,
309 BranchWithValue,
310 HashedValueLeaf,
311 HashedValueBranch,
312}
313
314impl Encode for NodeHeader {
315 fn encode_to<T: Output + ?Sized>(&self, output: &mut T) {
316 match self {
317 NodeHeader::Null => output.push_byte(trie_constants::EMPTY_TRIE),
318 NodeHeader::Branch(true, nibble_count) =>
319 encode_size_and_prefix(*nibble_count, trie_constants::BRANCH_WITH_MASK, 2, output),
320 NodeHeader::Branch(false, nibble_count) => encode_size_and_prefix(
321 *nibble_count,
322 trie_constants::BRANCH_WITHOUT_MASK,
323 2,
324 output,
325 ),
326 NodeHeader::Leaf(nibble_count) =>
327 encode_size_and_prefix(*nibble_count, trie_constants::LEAF_PREFIX_MASK, 2, output),
328 NodeHeader::HashedValueBranch(nibble_count) => encode_size_and_prefix(
329 *nibble_count,
330 trie_constants::ALT_HASHING_BRANCH_WITH_MASK,
331 4,
332 output,
333 ),
334 NodeHeader::HashedValueLeaf(nibble_count) => encode_size_and_prefix(
335 *nibble_count,
336 trie_constants::ALT_HASHING_LEAF_PREFIX_MASK,
337 3,
338 output,
339 ),
340 }
341 }
342}
343
344impl parity_scale_codec::EncodeLike for NodeHeader {}
345
346impl Decode for NodeHeader {
347 fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
348 let i = input.read_byte()?;
349 if i == trie_constants::EMPTY_TRIE {
350 return Ok(NodeHeader::Null)
351 }
352 match i & (0b11 << 6) {
353 trie_constants::LEAF_PREFIX_MASK => Ok(NodeHeader::Leaf(decode_size(i, input, 2)?)),
354 trie_constants::BRANCH_WITH_MASK =>
355 Ok(NodeHeader::Branch(true, decode_size(i, input, 2)?)),
356 trie_constants::BRANCH_WITHOUT_MASK =>
357 Ok(NodeHeader::Branch(false, decode_size(i, input, 2)?)),
358 trie_constants::EMPTY_TRIE => {
359 if i & (0b111 << 5) == trie_constants::ALT_HASHING_LEAF_PREFIX_MASK {
360 Ok(NodeHeader::HashedValueLeaf(decode_size(i, input, 3)?))
361 } else if i & (0b1111 << 4) == trie_constants::ALT_HASHING_BRANCH_WITH_MASK {
362 Ok(NodeHeader::HashedValueBranch(decode_size(i, input, 4)?))
363 } else {
364 Err("Unallowed encoding".into())
366 }
367 },
368 _ => unreachable!(),
369 }
370 }
371}
372
373pub(crate) fn size_and_prefix_iterator(
377 size: usize,
378 prefix: u8,
379 prefix_mask: usize,
380) -> impl Iterator<Item = u8> {
381 let size = std::cmp::min(trie_constants::NIBBLE_SIZE_BOUND, size);
382
383 let max_value = 255u8 >> prefix_mask;
384 let l1 = std::cmp::min(max_value as usize - 1, size);
385 let (first_byte, mut rem) = if size == l1 {
386 (once(prefix + l1 as u8), 0)
387 } else {
388 (once(prefix + max_value as u8), size - l1)
389 };
390 let next_bytes = move || {
391 if rem > 0 {
392 if rem < 256 {
393 let result = rem - 1;
394 rem = 0;
395 Some(result as u8)
396 } else {
397 rem = rem.saturating_sub(255);
398 Some(255)
399 }
400 } else {
401 None
402 }
403 };
404 first_byte.chain(std::iter::from_fn(next_bytes))
405}
406
407fn encode_size_and_prefix<W>(size: usize, prefix: u8, prefix_mask: usize, out: &mut W)
409where
410 W: Output + ?Sized,
411{
412 for b in size_and_prefix_iterator(size, prefix, prefix_mask) {
413 out.push_byte(b)
414 }
415}
416
417fn decode_size(first: u8, input: &mut impl Input, prefix_mask: usize) -> Result<usize, Error> {
419 let max_value = 255u8 >> prefix_mask;
420 let mut result = (first & max_value) as usize;
421 if result < max_value as usize {
422 return Ok(result)
423 }
424 result -= 1;
425 while result <= trie_constants::NIBBLE_SIZE_BOUND {
426 let n = input.read_byte()? as usize;
427 if n < 255 {
428 return Ok(result + n + 1)
429 }
430 result += 255;
431 }
432 Ok(trie_constants::NIBBLE_SIZE_BOUND)
433}
434
435#[derive(Default, Clone)]
437pub struct ReferenceTrieStreamNoExt {
438 buffer: Vec<u8>,
440}
441
442fn fuse_nibbles_node<'a>(nibbles: &'a [u8], kind: NodeKind) -> impl Iterator<Item = u8> + 'a {
444 let size = std::cmp::min(trie_constants::NIBBLE_SIZE_BOUND, nibbles.len());
445
446 let iter_start = match kind {
447 NodeKind::Leaf => size_and_prefix_iterator(size, trie_constants::LEAF_PREFIX_MASK, 2),
448 NodeKind::BranchNoValue =>
449 size_and_prefix_iterator(size, trie_constants::BRANCH_WITHOUT_MASK, 2),
450 NodeKind::BranchWithValue =>
451 size_and_prefix_iterator(size, trie_constants::BRANCH_WITH_MASK, 2),
452 NodeKind::HashedValueLeaf =>
453 size_and_prefix_iterator(size, trie_constants::ALT_HASHING_LEAF_PREFIX_MASK, 3),
454 NodeKind::HashedValueBranch =>
455 size_and_prefix_iterator(size, trie_constants::ALT_HASHING_BRANCH_WITH_MASK, 4),
456 };
457 iter_start
458 .chain(if nibbles.len() % 2 == 1 { Some(nibbles[0]) } else { None })
459 .chain(nibbles[nibbles.len() % 2..].chunks(2).map(|ch| ch[0] << 4 | ch[1]))
460}
461
462use trie_root::Value as TrieStreamValue;
463impl TrieStream for ReferenceTrieStreamNoExt {
464 fn new() -> Self {
465 Self { buffer: Vec::new() }
466 }
467
468 fn append_empty_data(&mut self) {
469 self.buffer.push(trie_constants::EMPTY_TRIE);
470 }
471
472 fn append_leaf(&mut self, key: &[u8], value: TrieStreamValue) {
473 let kind = match &value {
474 TrieStreamValue::Inline(..) => NodeKind::Leaf,
475 TrieStreamValue::Node(..) => NodeKind::HashedValueLeaf,
476 };
477 self.buffer.extend(fuse_nibbles_node(key, kind));
478 match &value {
479 TrieStreamValue::Inline(value) => {
480 Compact(value.len() as u32).encode_to(&mut self.buffer);
481 self.buffer.extend_from_slice(value);
482 },
483 TrieStreamValue::Node(hash) => {
484 self.buffer.extend_from_slice(hash.as_slice());
485 },
486 };
487 }
488
489 fn begin_branch(
490 &mut self,
491 maybe_partial: Option<&[u8]>,
492 maybe_value: Option<TrieStreamValue>,
493 has_children: impl Iterator<Item = bool>,
494 ) {
495 if let Some(partial) = maybe_partial {
496 let kind = match &maybe_value {
497 None => NodeKind::BranchNoValue,
498 Some(TrieStreamValue::Inline(..)) => NodeKind::BranchWithValue,
499 Some(TrieStreamValue::Node(..)) => NodeKind::HashedValueBranch,
500 };
501
502 self.buffer.extend(fuse_nibbles_node(partial, kind));
503 let bm = branch_node_bit_mask(has_children);
504 self.buffer.extend([bm.0, bm.1].iter());
505 } else {
506 unreachable!("trie stream codec only for no extension trie");
507 }
508 match maybe_value {
509 None => (),
510 Some(TrieStreamValue::Inline(value)) => {
511 Compact(value.len() as u32).encode_to(&mut self.buffer);
512 self.buffer.extend_from_slice(value);
513 },
514 Some(TrieStreamValue::Node(hash)) => {
515 self.buffer.extend_from_slice(hash.as_slice());
516 },
517 }
518 }
519
520 fn append_extension(&mut self, _key: &[u8]) {
521 unreachable!("trie stream codec only for no extension trie");
522 }
523
524 fn append_substream<H: Hasher>(&mut self, other: Self) {
525 let data = other.out();
526 match data.len() {
527 0..=31 => data.encode_to(&mut self.buffer),
528 _ => H::hash(&data).as_ref().encode_to(&mut self.buffer),
529 }
530 }
531
532 fn out(self) -> Vec<u8> {
533 self.buffer
534 }
535}