referrerpolicy=no-referrer-when-downgrade

sp_trie/
node_codec.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! `NodeCodec` implementation for Substrate's trie format.
19
20use super::node_header::{NodeHeader, NodeKind};
21use crate::{error::Error, trie_constants};
22use alloc::{borrow::Borrow, vec::Vec};
23use codec::{Compact, Decode, Encode, Input};
24use core::{marker::PhantomData, ops::Range};
25use hash_db::Hasher;
26use trie_db::{
27	nibble_ops,
28	node::{NibbleSlicePlan, NodeHandlePlan, NodePlan, Value, ValuePlan},
29	ChildReference, NodeCodec as NodeCodecT,
30};
31
32/// Helper struct for trie node decoder. This implements `codec::Input` on a byte slice, while
33/// tracking the absolute position. This is similar to `std::io::Cursor` but does not implement
34/// `Read` and `io` are not in `core` or `alloc`.
35struct ByteSliceInput<'a> {
36	data: &'a [u8],
37	offset: usize,
38}
39
40impl<'a> ByteSliceInput<'a> {
41	fn new(data: &'a [u8]) -> Self {
42		ByteSliceInput { data, offset: 0 }
43	}
44
45	fn take(&mut self, count: usize) -> Result<Range<usize>, codec::Error> {
46		if self.offset + count > self.data.len() {
47			return Err("out of data".into())
48		}
49
50		let range = self.offset..(self.offset + count);
51		self.offset += count;
52		Ok(range)
53	}
54}
55
56impl<'a> Input for ByteSliceInput<'a> {
57	fn remaining_len(&mut self) -> Result<Option<usize>, codec::Error> {
58		Ok(Some(self.data.len().saturating_sub(self.offset)))
59	}
60
61	fn read(&mut self, into: &mut [u8]) -> Result<(), codec::Error> {
62		let range = self.take(into.len())?;
63		into.copy_from_slice(&self.data[range]);
64		Ok(())
65	}
66
67	fn read_byte(&mut self) -> Result<u8, codec::Error> {
68		if self.offset + 1 > self.data.len() {
69			return Err("out of data".into())
70		}
71
72		let byte = self.data[self.offset];
73		self.offset += 1;
74		Ok(byte)
75	}
76}
77
78/// Concrete implementation of a [`NodeCodecT`] with SCALE encoding.
79///
80/// It is generic over `H` the [`Hasher`].
81#[derive(Default, Clone)]
82pub struct NodeCodec<H>(PhantomData<H>);
83
84impl<H> NodeCodecT for NodeCodec<H>
85where
86	H: Hasher,
87{
88	const ESCAPE_HEADER: Option<u8> = Some(trie_constants::ESCAPE_COMPACT_HEADER);
89	type Error = Error<H::Out>;
90	type HashOut = H::Out;
91
92	fn hashed_null_node() -> <H as Hasher>::Out {
93		H::hash(<Self as NodeCodecT>::empty_node())
94	}
95
96	fn decode_plan(data: &[u8]) -> Result<NodePlan, Self::Error> {
97		let mut input = ByteSliceInput::new(data);
98
99		let header = NodeHeader::decode(&mut input)?;
100		let contains_hash = header.contains_hash_of_value();
101
102		let branch_has_value = if let NodeHeader::Branch(has_value, _) = &header {
103			*has_value
104		} else {
105			// hashed_value_branch
106			true
107		};
108
109		match header {
110			NodeHeader::Null => Ok(NodePlan::Empty),
111			NodeHeader::HashedValueBranch(nibble_count) | NodeHeader::Branch(_, nibble_count) => {
112				let padding = nibble_count % nibble_ops::NIBBLE_PER_BYTE != 0;
113				// data should be at least of size offset + 1
114				if data.len() < input.offset + 1 {
115					return Err(Error::BadFormat)
116				}
117				// check that the padding is valid (if any)
118				if padding && nibble_ops::pad_left(data[input.offset]) != 0 {
119					return Err(Error::BadFormat)
120				}
121				let partial = input.take(nibble_count.div_ceil(nibble_ops::NIBBLE_PER_BYTE))?;
122				let partial_padding = nibble_ops::number_padding(nibble_count);
123				let bitmap_range = input.take(BITMAP_LENGTH)?;
124				let bitmap = Bitmap::decode(&data[bitmap_range])?;
125				let value = if branch_has_value {
126					Some(if contains_hash {
127						ValuePlan::Node(input.take(H::LENGTH)?)
128					} else {
129						let count = <Compact<u32>>::decode(&mut input)?.0 as usize;
130						ValuePlan::Inline(input.take(count)?)
131					})
132				} else {
133					None
134				};
135				let mut children = [
136					None, None, None, None, None, None, None, None, None, None, None, None, None,
137					None, None, None,
138				];
139				for i in 0..nibble_ops::NIBBLE_LENGTH {
140					if bitmap.value_at(i) {
141						let count = <Compact<u32>>::decode(&mut input)?.0 as usize;
142						let range = input.take(count)?;
143						children[i] = Some(if count == H::LENGTH {
144							NodeHandlePlan::Hash(range)
145						} else {
146							NodeHandlePlan::Inline(range)
147						});
148					}
149				}
150				Ok(NodePlan::NibbledBranch {
151					partial: NibbleSlicePlan::new(partial, partial_padding),
152					value,
153					children,
154				})
155			},
156			NodeHeader::HashedValueLeaf(nibble_count) | NodeHeader::Leaf(nibble_count) => {
157				let padding = nibble_count % nibble_ops::NIBBLE_PER_BYTE != 0;
158				// data should be at least of size offset + 1
159				if data.len() < input.offset + 1 {
160					return Err(Error::BadFormat)
161				}
162				// check that the padding is valid (if any)
163				if padding && nibble_ops::pad_left(data[input.offset]) != 0 {
164					return Err(Error::BadFormat)
165				}
166				let partial = input.take(nibble_count.div_ceil(nibble_ops::NIBBLE_PER_BYTE))?;
167				let partial_padding = nibble_ops::number_padding(nibble_count);
168				let value = if contains_hash {
169					ValuePlan::Node(input.take(H::LENGTH)?)
170				} else {
171					let count = <Compact<u32>>::decode(&mut input)?.0 as usize;
172					ValuePlan::Inline(input.take(count)?)
173				};
174
175				Ok(NodePlan::Leaf {
176					partial: NibbleSlicePlan::new(partial, partial_padding),
177					value,
178				})
179			},
180		}
181	}
182
183	fn is_empty_node(data: &[u8]) -> bool {
184		data == <Self as NodeCodecT>::empty_node()
185	}
186
187	fn empty_node() -> &'static [u8] {
188		&[trie_constants::EMPTY_TRIE]
189	}
190
191	fn leaf_node(partial: impl Iterator<Item = u8>, number_nibble: usize, value: Value) -> Vec<u8> {
192		let contains_hash = matches!(&value, Value::Node(..));
193		let mut output = if contains_hash {
194			partial_from_iterator_encode(partial, number_nibble, NodeKind::HashedValueLeaf)
195		} else {
196			partial_from_iterator_encode(partial, number_nibble, NodeKind::Leaf)
197		};
198		match value {
199			Value::Inline(value) => {
200				Compact(value.len() as u32).encode_to(&mut output);
201				output.extend_from_slice(value);
202			},
203			Value::Node(hash) => {
204				debug_assert!(hash.len() == H::LENGTH);
205				output.extend_from_slice(hash);
206			},
207		}
208		output
209	}
210
211	fn extension_node(
212		_partial: impl Iterator<Item = u8>,
213		_nbnibble: usize,
214		_child: ChildReference<<H as Hasher>::Out>,
215	) -> Vec<u8> {
216		unreachable!("No extension codec.")
217	}
218
219	fn branch_node(
220		_children: impl Iterator<Item = impl Borrow<Option<ChildReference<<H as Hasher>::Out>>>>,
221		_maybe_value: Option<Value>,
222	) -> Vec<u8> {
223		unreachable!("No extension codec.")
224	}
225
226	fn branch_node_nibbled(
227		partial: impl Iterator<Item = u8>,
228		number_nibble: usize,
229		children: impl Iterator<Item = impl Borrow<Option<ChildReference<<H as Hasher>::Out>>>>,
230		value: Option<Value>,
231	) -> Vec<u8> {
232		let contains_hash = matches!(&value, Some(Value::Node(..)));
233		let mut output = match (&value, contains_hash) {
234			(&None, _) =>
235				partial_from_iterator_encode(partial, number_nibble, NodeKind::BranchNoValue),
236			(_, false) =>
237				partial_from_iterator_encode(partial, number_nibble, NodeKind::BranchWithValue),
238			(_, true) =>
239				partial_from_iterator_encode(partial, number_nibble, NodeKind::HashedValueBranch),
240		};
241
242		let bitmap_index = output.len();
243		let mut bitmap: [u8; BITMAP_LENGTH] = [0; BITMAP_LENGTH];
244		(0..BITMAP_LENGTH).for_each(|_| output.push(0));
245		match value {
246			Some(Value::Inline(value)) => {
247				Compact(value.len() as u32).encode_to(&mut output);
248				output.extend_from_slice(value);
249			},
250			Some(Value::Node(hash)) => {
251				debug_assert!(hash.len() == H::LENGTH);
252				output.extend_from_slice(hash);
253			},
254			None => (),
255		}
256		Bitmap::encode(
257			children.map(|maybe_child| match maybe_child.borrow() {
258				Some(ChildReference::Hash(h)) => {
259					h.as_ref().encode_to(&mut output);
260					true
261				},
262				&Some(ChildReference::Inline(inline_data, len)) => {
263					inline_data.as_ref()[..len].encode_to(&mut output);
264					true
265				},
266				None => false,
267			}),
268			bitmap.as_mut(),
269		);
270		output[bitmap_index..bitmap_index + BITMAP_LENGTH]
271			.copy_from_slice(&bitmap[..BITMAP_LENGTH]);
272		output
273	}
274}
275
276// utils
277
278/// Encode and allocate node type header (type and size), and partial value.
279/// It uses an iterator over encoded partial bytes as input.
280fn partial_from_iterator_encode<I: Iterator<Item = u8>>(
281	partial: I,
282	nibble_count: usize,
283	node_kind: NodeKind,
284) -> Vec<u8> {
285	let mut output = Vec::with_capacity(4 + (nibble_count / nibble_ops::NIBBLE_PER_BYTE));
286	match node_kind {
287		NodeKind::Leaf => NodeHeader::Leaf(nibble_count).encode_to(&mut output),
288		NodeKind::BranchWithValue => NodeHeader::Branch(true, nibble_count).encode_to(&mut output),
289		NodeKind::BranchNoValue => NodeHeader::Branch(false, nibble_count).encode_to(&mut output),
290		NodeKind::HashedValueLeaf =>
291			NodeHeader::HashedValueLeaf(nibble_count).encode_to(&mut output),
292		NodeKind::HashedValueBranch =>
293			NodeHeader::HashedValueBranch(nibble_count).encode_to(&mut output),
294	};
295	output.extend(partial);
296	output
297}
298
299const BITMAP_LENGTH: usize = 2;
300
301/// Radix 16 trie, bitmap encoding implementation,
302/// it contains children mapping information for a branch
303/// (children presence only), it encodes into
304/// a compact bitmap encoding representation.
305pub(crate) struct Bitmap(u16);
306
307impl Bitmap {
308	pub fn decode(data: &[u8]) -> Result<Self, codec::Error> {
309		let value = u16::decode(&mut &data[..])?;
310		if value == 0 {
311			Err("Bitmap without a child.".into())
312		} else {
313			Ok(Bitmap(value))
314		}
315	}
316
317	pub fn value_at(&self, i: usize) -> bool {
318		self.0 & (1u16 << i) != 0
319	}
320
321	pub fn encode<I: Iterator<Item = bool>>(has_children: I, dest: &mut [u8]) {
322		let mut bitmap: u16 = 0;
323		let mut cursor: u16 = 1;
324		for v in has_children {
325			if v {
326				bitmap |= cursor
327			}
328			cursor <<= 1;
329		}
330		dest[0] = (bitmap % 256) as u8;
331		dest[1] = (bitmap / 256) as u8;
332	}
333}