1use tetsy_hash_db::HashDB;
29use crate::{
30 CError, ChildReference, DBValue, NibbleVec, NodeCodec, Result,
31 TrieHash, TrieError, TrieDB, TrieDBNodeIterator, TrieLayout,
32 nibble_ops::NIBBLE_LENGTH, node::{Node, NodeHandle, NodeHandlePlan, NodePlan, OwnedNode},
33};
34use crate::rstd::{
35 boxed::Box, convert::TryInto, marker::PhantomData, rc::Rc, result, vec, vec::Vec,
36};
37
38struct EncoderStackEntry<C: NodeCodec> {
39 prefix: NibbleVec,
41 node: Rc<OwnedNode<DBValue>>,
42 child_index: usize,
45 omit_children: Vec<bool>,
47 output_index: usize,
50 _marker: PhantomData<C>,
51}
52
53impl<C: NodeCodec> EncoderStackEntry<C> {
54 fn advance_child_index(&mut self, child_prefix: &NibbleVec)
63 -> result::Result<(), &'static str>
64 {
65 match self.node.node_plan() {
66 NodePlan::Empty | NodePlan::Leaf { .. } =>
67 return Err("empty and leaf nodes have no children"),
68 NodePlan::Extension { .. } => {
69 if self.child_index != 0 {
70 return Err("extension node cannot have multiple children")
71 }
72 }
73 NodePlan::Branch { .. } => {
74 if child_prefix.len() <= self.prefix.len() {
75 return Err("child_prefix does not contain prefix");
76 }
77 let child_index = child_prefix.at(self.prefix.len()) as usize;
78 if child_index < self.child_index {
79 return Err("iterator returned children in non-ascending order by prefix");
80 }
81 self.child_index = child_index;
82 }
83 NodePlan::NibbledBranch { partial, .. } => {
84 if child_prefix.len() <= self.prefix.len() + partial.len() {
85 return Err("child_prefix does not contain prefix and node partial");
86 }
87 let child_index = child_prefix.at(self.prefix.len() + partial.len()) as usize;
88 if child_index < self.child_index {
89 return Err("iterator returned children in non-ascending order by prefix");
90 }
91 self.child_index = child_index;
92 }
93 }
94 Ok(())
95 }
96
97 fn encode_node(&self) -> Result<Vec<u8>, C::HashOut, C::Error> {
99 let node_data = self.node.data();
100 Ok(match self.node.node_plan() {
101 NodePlan::Empty | NodePlan::Leaf { .. } => node_data.to_vec(),
102 NodePlan::Extension { partial, child: _ } => {
103 if !self.omit_children[0] {
104 node_data.to_vec()
105 } else {
106 let partial = partial.build(node_data);
107 let empty_child = ChildReference::Inline(C::HashOut::default(), 0);
108 C::extension_node(partial.right_iter(), partial.len(), empty_child)
109 }
110 }
111 NodePlan::Branch { value, children } => {
112 C::branch_node(
113 Self::branch_children(node_data, &children, &self.omit_children)?.iter(),
114 value.clone().map(|range| &node_data[range])
115 )
116 }
117 NodePlan::NibbledBranch { partial, value, children } => {
118 let partial = partial.build(node_data);
119 C::branch_node_nibbled(
120 partial.right_iter(),
121 partial.len(),
122 Self::branch_children(node_data, &children, &self.omit_children)?.iter(),
123 value.clone().map(|range| &node_data[range])
124 )
125 }
126 })
127 }
128
129 fn branch_children(
135 node_data: &[u8],
136 child_handles: &[Option<NodeHandlePlan>; NIBBLE_LENGTH],
137 omit_children: &[bool],
138 ) -> Result<[Option<ChildReference<C::HashOut>>; NIBBLE_LENGTH], C::HashOut, C::Error>
139 {
140 let empty_child = ChildReference::Inline(C::HashOut::default(), 0);
141 let mut children = [None; NIBBLE_LENGTH];
142 for i in 0..NIBBLE_LENGTH {
143 children[i] = if omit_children[i] {
144 Some(empty_child)
145 } else if let Some(child_plan) = &child_handles[i] {
146 let child_ref = child_plan
147 .build(node_data)
148 .try_into()
149 .map_err(|hash| Box::new(
150 TrieError::InvalidHash(C::HashOut::default(), hash)
151 ))?;
152 Some(child_ref)
153 } else {
154 None
155 };
156 }
157 Ok(children)
158 }
159}
160
161pub fn encode_compact<L>(db: &TrieDB<L>) -> Result<Vec<Vec<u8>>, TrieHash<L>, CError<L>>
169 where
170 L: TrieLayout
171{
172 let mut output = Vec::new();
173
174 let mut stack: Vec<EncoderStackEntry<L::Codec>> = Vec::new();
177
178 let iter = TrieDBNodeIterator::new(db)?;
183
184 for item in iter {
189 match item {
190 Ok((prefix, node_hash, node)) => {
191 if node_hash.is_none() {
194 continue;
195 }
196
197 while let Some(mut last_entry) = stack.pop() {
202 if prefix.starts_with(&last_entry.prefix) {
203 last_entry.advance_child_index(&prefix)
206 .expect(
207 "all errors from advance_child_index indicate bugs with \
208 TrieDBNodeIterator or this function"
209 );
210 last_entry.omit_children[last_entry.child_index] = true;
211 last_entry.child_index += 1;
212 stack.push(last_entry);
213 break;
214 } else {
215 output[last_entry.output_index] = last_entry.encode_node()?;
216 }
217 }
218
219 let children_len = match node.node_plan() {
220 NodePlan::Empty | NodePlan::Leaf { .. } => 0,
221 NodePlan::Extension { .. } => 1,
222 NodePlan::Branch { .. } | NodePlan::NibbledBranch { .. } => NIBBLE_LENGTH,
223 };
224 stack.push(EncoderStackEntry {
225 prefix,
226 node,
227 child_index: 0,
228 omit_children: vec![false; children_len],
229 output_index: output.len(),
230 _marker: PhantomData::default(),
231 });
232 output.push(Vec::new());
235 }
236 Err(err) => match *err {
237 TrieError::IncompleteDatabase(_) => {},
241 _ => return Err(err),
242 }
243 }
244 }
245
246 while let Some(entry) = stack.pop() {
247 output[entry.output_index] = entry.encode_node()?;
248 }
249
250 Ok(output)
251}
252
253struct DecoderStackEntry<'a, C: NodeCodec> {
254 node: Node<'a>,
255 child_index: usize,
258 children: Vec<Option<ChildReference<C::HashOut>>>,
260 _marker: PhantomData<C>,
261}
262
263impl<'a, C: NodeCodec> DecoderStackEntry<'a, C> {
264 fn advance_child_index(&mut self) -> Result<bool, C::HashOut, C::Error> {
273 match self.node {
274 Node::Extension(_, child) if self.child_index == 0 => {
275 match child {
276 NodeHandle::Inline(data) if data.is_empty() =>
277 return Ok(false),
278 _ => {
279 let child_ref = child.try_into()
280 .map_err(|hash| Box::new(
281 TrieError::InvalidHash(C::HashOut::default(), hash)
282 ))?;
283 self.children[self.child_index] = Some(child_ref);
284 }
285 }
286 self.child_index += 1;
287 }
288 Node::Branch(children, _) | Node::NibbledBranch(_, children, _) => {
289 while self.child_index < NIBBLE_LENGTH {
290 match children[self.child_index] {
291 Some(NodeHandle::Inline(data)) if data.is_empty() =>
292 return Ok(false),
293 Some(child) => {
294 let child_ref = child.try_into()
295 .map_err(|hash| Box::new(
296 TrieError::InvalidHash(C::HashOut::default(), hash)
297 ))?;
298 self.children[self.child_index] = Some(child_ref);
299 }
300 None => {}
301 }
302 self.child_index += 1;
303 }
304 }
305 _ => {}
306 }
307 Ok(true)
308 }
309
310 fn push_to_prefix(&self, prefix: &mut NibbleVec) {
313 match self.node {
314 Node::Empty => {}
315 Node::Leaf(partial, _) | Node::Extension(partial, _) => {
316 prefix.append_partial(partial.right());
317 }
318 Node::Branch(_, _) => {
319 prefix.push(self.child_index as u8);
320 }
321 Node::NibbledBranch(partial, _, _) => {
322 prefix.append_partial(partial.right());
323 prefix.push(self.child_index as u8);
324 }
325 }
326 }
327
328 fn pop_from_prefix(&self, prefix: &mut NibbleVec) {
331 match self.node {
332 Node::Empty => {}
333 Node::Leaf(partial, _) | Node::Extension(partial, _) => {
334 prefix.drop_lasts(partial.len());
335 }
336 Node::Branch(_, _) => {
337 prefix.pop();
338 }
339 Node::NibbledBranch(partial, _, _) => {
340 prefix.pop();
341 prefix.drop_lasts(partial.len());
342 }
343 }
344 }
345
346 fn encode_node(self) -> Vec<u8> {
351 match self.node {
352 Node::Empty =>
353 C::empty_node().to_vec(),
354 Node::Leaf(partial, value) =>
355 C::leaf_node(partial.right(), value),
356 Node::Extension(partial, _) =>
357 C::extension_node(
358 partial.right_iter(),
359 partial.len(),
360 self.children[0]
361 .expect("required by method precondition; qed"),
362 ),
363 Node::Branch(_, value) =>
364 C::branch_node(self.children.into_iter(), value),
365 Node::NibbledBranch(partial, _, value) =>
366 C::branch_node_nibbled(
367 partial.right_iter(),
368 partial.len(),
369 self.children.iter(),
370 value,
371 ),
372 }
373 }
374}
375
376pub fn decode_compact<L, DB, T>(db: &mut DB, encoded: &[Vec<u8>])
389 -> Result<(TrieHash<L>, usize), TrieHash<L>, CError<L>>
390 where
391 L: TrieLayout,
392 DB: HashDB<L::Hash, T>,
393{
394 decode_compact_from_iter::<L, DB, T, _>(db, encoded.iter().map(Vec::as_slice))
395}
396
397pub fn decode_compact_from_iter<'a, L, DB, T, I>(db: &mut DB, encoded: I)
399 -> Result<(TrieHash<L>, usize), TrieHash<L>, CError<L>>
400 where
401 L: TrieLayout,
402 DB: HashDB<L::Hash, T>,
403 I: IntoIterator<Item = &'a [u8]>,
404{
405 let mut stack: Vec<DecoderStackEntry<L::Codec>> = Vec::new();
408
409 let mut prefix = NibbleVec::new();
411
412 for (i, encoded_node) in encoded.into_iter().enumerate() {
413 let node = L::Codec::decode(encoded_node)
414 .map_err(|err| Box::new(TrieError::DecoderError(<TrieHash<L>>::default(), err)))?;
415
416 let children_len = match node {
417 Node::Empty | Node::Leaf(..) => 0,
418 Node::Extension(..) => 1,
419 Node::Branch(..) | Node::NibbledBranch(..) => NIBBLE_LENGTH,
420 };
421 let mut last_entry = DecoderStackEntry {
422 node,
423 child_index: 0,
424 children: vec![None; children_len],
425 _marker: PhantomData::default(),
426 };
427
428 loop {
429 if !last_entry.advance_child_index()? {
430 last_entry.push_to_prefix(&mut prefix);
431 stack.push(last_entry);
432 break;
433 }
434
435 let node_data = last_entry.encode_node();
438 let node_hash = db.insert(prefix.as_prefix(), node_data.as_ref());
439
440 if let Some(entry) = stack.pop() {
441 last_entry = entry;
442 last_entry.pop_from_prefix(&mut prefix);
443 last_entry.children[last_entry.child_index] =
444 Some(ChildReference::Hash(node_hash));
445 last_entry.child_index += 1;
446 } else {
447 return Ok((node_hash, i + 1));
448 }
449 }
450 }
451
452 Err(Box::new(TrieError::IncompleteDatabase(<TrieHash<L>>::default())))
453}