Skip to main content

pez_fork_tree/
lib.rs

1// This file is part of Bizinikiwi.
2
3// Copyright (C) Parity Technologies (UK) Ltd. and Dijital Kurdistan Tech Institute
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//! Utility library for managing tree-like ordered data with logic for pruning
19//! the tree while finalizing nodes.
20
21#![warn(missing_docs)]
22
23use codec::{Decode, Encode};
24use std::{cmp::Reverse, fmt};
25
26/// Error occurred when iterating with the tree.
27#[derive(Clone, Debug, PartialEq)]
28pub enum Error<E> {
29	/// Adding duplicate node to tree.
30	Duplicate,
31	/// Finalizing descendent of tree node without finalizing ancestor(s).
32	UnfinalizedAncestor,
33	/// Imported or finalized node that is an ancestor of previously finalized node.
34	Revert,
35	/// Error thrown by user when checking for node ancestry.
36	Client(E),
37}
38
39impl<E: std::error::Error> fmt::Display for Error<E> {
40	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
41		let message = match *self {
42			Error::Duplicate => "Hash already exists in Tree".into(),
43			Error::UnfinalizedAncestor => "Finalized descendent of Tree node without finalizing its ancestor(s) first".into(),
44			Error::Revert => "Tried to import or finalize node that is an ancestor of a previously finalized node".into(),
45			Error::Client(ref err) => format!("Client error: {}", err),
46		};
47		write!(f, "{}", message)
48	}
49}
50
51impl<E: std::error::Error> std::error::Error for Error<E> {}
52
53impl<E: std::error::Error> From<E> for Error<E> {
54	fn from(err: E) -> Error<E> {
55		Error::Client(err)
56	}
57}
58
59/// Result of finalizing a node (that could be a part of the tree or not).
60#[derive(Debug, PartialEq)]
61pub enum FinalizationResult<V> {
62	/// The tree has changed, optionally return the value associated with the finalized node.
63	Changed(Option<V>),
64	/// The tree has not changed.
65	Unchanged,
66}
67
68/// Filtering action.
69#[derive(Debug, PartialEq)]
70pub enum FilterAction {
71	/// Remove the node and its subtree.
72	Remove,
73	/// Maintain the node.
74	KeepNode,
75	/// Maintain the node and its subtree.
76	KeepTree,
77}
78
79/// A tree data structure that stores several nodes across multiple branches.
80///
81/// Top-level branches are called roots. The tree has functionality for
82/// finalizing nodes, which means that node is traversed, and all competing
83/// branches are pruned. It also guarantees that nodes in the tree are finalized
84/// in order. Each node is uniquely identified by its hash but can be ordered by
85/// its number. In order to build the tree an external function must be provided
86/// when interacting with the tree to establish a node's ancestry.
87#[derive(Clone, Debug, Decode, Encode, PartialEq)]
88pub struct ForkTree<H, N, V> {
89	roots: Vec<Node<H, N, V>>,
90	best_finalized_number: Option<N>,
91}
92
93impl<H, N, V> ForkTree<H, N, V>
94where
95	H: PartialEq,
96	N: Ord,
97{
98	/// Create a new empty tree instance.
99	pub fn new() -> ForkTree<H, N, V> {
100		ForkTree { roots: Vec::new(), best_finalized_number: None }
101	}
102
103	/// Rebalance the tree.
104	///
105	/// For each tree level sort child nodes by max branch depth (decreasing).
106	///
107	/// Most operations in the tree are performed with depth-first search
108	/// starting from the leftmost node at every level, since this tree is meant
109	/// to be used in a blockchain context, a good heuristic is that the node
110	/// we'll be looking for at any point will likely be in one of the deepest chains
111	/// (i.e. the longest ones).
112	pub fn rebalance(&mut self) {
113		self.roots.sort_by_key(|n| Reverse(n.max_depth()));
114		let mut stack: Vec<_> = self.roots.iter_mut().collect();
115		while let Some(node) = stack.pop() {
116			node.children.sort_by_key(|n| Reverse(n.max_depth()));
117			stack.extend(node.children.iter_mut());
118		}
119	}
120
121	/// Import a new node into the tree.
122	///
123	/// The given function `is_descendent_of` should return `true` if the second
124	/// hash (target) is a descendent of the first hash (base).
125	///
126	/// This method assumes that nodes in the same branch are imported in order.
127	///
128	/// Returns `true` if the imported node is a root.
129	// WARNING: some users of this method (i.e. consensus epoch changes tree) currently silently
130	// rely on a **post-order DFS** traversal. If we are using instead a top-down traversal method
131	// then the `is_descendent_of` closure, when used after a warp-sync, may end up querying the
132	// backend for a block (the one corresponding to the root) that is not present and thus will
133	// return a wrong result.
134	pub fn import<F, E>(
135		&mut self,
136		hash: H,
137		number: N,
138		data: V,
139		is_descendent_of: &F,
140	) -> Result<bool, Error<E>>
141	where
142		E: std::error::Error,
143		F: Fn(&H, &H) -> Result<bool, E>,
144	{
145		if let Some(ref best_finalized_number) = self.best_finalized_number {
146			if number <= *best_finalized_number {
147				return Err(Error::Revert);
148			}
149		}
150
151		let (children, is_root) =
152			match self.find_node_where_mut(&hash, &number, is_descendent_of, &|_| true)? {
153				Some(parent) => (&mut parent.children, false),
154				None => (&mut self.roots, true),
155			};
156
157		if children.iter().any(|elem| elem.hash == hash) {
158			return Err(Error::Duplicate);
159		}
160
161		children.push(Node { data, hash, number, children: Default::default() });
162
163		if children.len() == 1 {
164			// Rebalance may be required only if we've extended the branch depth.
165			self.rebalance();
166		}
167
168		Ok(is_root)
169	}
170
171	/// Iterates over the existing roots in the tree.
172	pub fn roots(&self) -> impl Iterator<Item = (&H, &N, &V)> {
173		self.roots.iter().map(|node| (&node.hash, &node.number, &node.data))
174	}
175
176	fn node_iter(&self) -> impl Iterator<Item = &Node<H, N, V>> {
177		// we need to reverse the order of roots to maintain the expected
178		// ordering since the iterator uses a stack to track state.
179		ForkTreeIterator { stack: self.roots.iter().rev().collect() }
180	}
181
182	/// Iterates the nodes in the tree in pre-order.
183	pub fn iter(&self) -> impl Iterator<Item = (&H, &N, &V)> {
184		self.node_iter().map(|node| (&node.hash, &node.number, &node.data))
185	}
186
187	/// Map fork tree into values of new types.
188	///
189	/// Tree traversal technique (e.g. BFS vs DFS) is left as not specified and
190	/// may be subject to change in the future. In other words, your predicates
191	/// should not rely on the observed traversal technique currently in use.
192	pub fn map<VT, F>(self, f: &mut F) -> ForkTree<H, N, VT>
193	where
194		F: FnMut(&H, &N, V) -> VT,
195	{
196		let mut queue: Vec<_> =
197			self.roots.into_iter().rev().map(|node| (usize::MAX, node)).collect();
198		let mut next_queue = Vec::new();
199		let mut output = Vec::new();
200
201		while !queue.is_empty() {
202			for (parent_index, node) in queue.drain(..) {
203				let new_data = f(&node.hash, &node.number, node.data);
204				let new_node = Node {
205					hash: node.hash,
206					number: node.number,
207					data: new_data,
208					children: Vec::with_capacity(node.children.len()),
209				};
210
211				let node_id = output.len();
212				output.push((parent_index, new_node));
213
214				for child in node.children.into_iter().rev() {
215					next_queue.push((node_id, child));
216				}
217			}
218
219			std::mem::swap(&mut queue, &mut next_queue);
220		}
221
222		let mut roots = Vec::new();
223		while let Some((parent_index, new_node)) = output.pop() {
224			if parent_index == usize::MAX {
225				roots.push(new_node);
226			} else {
227				output[parent_index].1.children.push(new_node);
228			}
229		}
230
231		ForkTree { roots, best_finalized_number: self.best_finalized_number }
232	}
233
234	/// Find a node in the tree that is the deepest ancestor of the given
235	/// block hash and which passes the given predicate.
236	///
237	/// The given function `is_descendent_of` should return `true` if the
238	/// second hash (target) is a descendent of the first hash (base).
239	pub fn find_node_where<F, E, P>(
240		&self,
241		hash: &H,
242		number: &N,
243		is_descendent_of: &F,
244		predicate: &P,
245	) -> Result<Option<&Node<H, N, V>>, Error<E>>
246	where
247		E: std::error::Error,
248		F: Fn(&H, &H) -> Result<bool, E>,
249		P: Fn(&V) -> bool,
250	{
251		let maybe_path = self.find_node_index_where(hash, number, is_descendent_of, predicate)?;
252		Ok(maybe_path.map(|path| {
253			let children =
254				path.iter().take(path.len() - 1).fold(&self.roots, |curr, &i| &curr[i].children);
255			&children[path[path.len() - 1]]
256		}))
257	}
258
259	/// Same as [`find_node_where`](ForkTree::find_node_where), but returns mutable reference.
260	pub fn find_node_where_mut<F, E, P>(
261		&mut self,
262		hash: &H,
263		number: &N,
264		is_descendent_of: &F,
265		predicate: &P,
266	) -> Result<Option<&mut Node<H, N, V>>, Error<E>>
267	where
268		E: std::error::Error,
269		F: Fn(&H, &H) -> Result<bool, E>,
270		P: Fn(&V) -> bool,
271	{
272		let maybe_path = self.find_node_index_where(hash, number, is_descendent_of, predicate)?;
273		Ok(maybe_path.map(|path| {
274			let children = path
275				.iter()
276				.take(path.len() - 1)
277				.fold(&mut self.roots, |curr, &i| &mut curr[i].children);
278			&mut children[path[path.len() - 1]]
279		}))
280	}
281
282	/// Same as [`find_node_where`](ForkTree::find_node_where), but returns indices.
283	///
284	/// The returned indices represent the full path to reach the matching node starting
285	/// from one of the roots, i.e. the earliest index in the traverse path goes first,
286	/// and the final index in the traverse path goes last.
287	///
288	/// If a node is found that matches the predicate the returned path should always
289	/// contain at least one index, otherwise `None` is returned.
290	//
291	// WARNING: some users of this method (i.e. consensus epoch changes tree) currently silently
292	// rely on a **post-order DFS** traversal. If we are using instead a top-down traversal method
293	// then the `is_descendent_of` closure, when used after a warp-sync, will end up querying the
294	// backend for a block (the one corresponding to the root) that is not present and thus will
295	// return a wrong result.
296	pub fn find_node_index_where<F, E, P>(
297		&self,
298		hash: &H,
299		number: &N,
300		is_descendent_of: &F,
301		predicate: &P,
302	) -> Result<Option<Vec<usize>>, Error<E>>
303	where
304		E: std::error::Error,
305		F: Fn(&H, &H) -> Result<bool, E>,
306		P: Fn(&V) -> bool,
307	{
308		let mut stack = vec![];
309		let mut root_idx = 0;
310		let mut found = false;
311		let mut is_descendent = false;
312
313		while root_idx < self.roots.len() {
314			if *number <= self.roots[root_idx].number {
315				root_idx += 1;
316				continue;
317			}
318			// The second element in the stack tuple tracks what is the **next** children
319			// index to search into. If we find an ancestor then we stop searching into
320			// alternative branches and we focus on the current path up to the root.
321			stack.push((&self.roots[root_idx], 0));
322			while let Some((node, i)) = stack.pop() {
323				if i < node.children.len() && !is_descendent {
324					stack.push((node, i + 1));
325					if node.children[i].number < *number {
326						stack.push((&node.children[i], 0));
327					}
328				} else if is_descendent || is_descendent_of(&node.hash, hash)? {
329					is_descendent = true;
330					if predicate(&node.data) {
331						found = true;
332						break;
333					}
334				}
335			}
336
337			// If the element we are looking for is a descendent of the current root
338			// then we can stop the search.
339			if is_descendent {
340				break;
341			}
342			root_idx += 1;
343		}
344
345		Ok(if found {
346			// The path is the root index followed by the indices of all the children
347			// we were processing when we found the element (remember the stack
348			// contains the index of the **next** children to process).
349			let path: Vec<_> =
350				std::iter::once(root_idx).chain(stack.iter().map(|(_, i)| *i - 1)).collect();
351			Some(path)
352		} else {
353			None
354		})
355	}
356
357	/// Prune the tree, removing all non-canonical nodes.
358	///
359	/// We find the node in the tree that is the deepest ancestor of the given hash
360	/// and that passes the given predicate. If such a node exists, we re-root the
361	/// tree to this node. Otherwise the tree remains unchanged.
362	///
363	/// The given function `is_descendent_of` should return `true` if the second
364	/// hash (target) is a descendent of the first hash (base).
365	///
366	/// Returns all pruned nodes data.
367	pub fn prune<F, E, P>(
368		&mut self,
369		hash: &H,
370		number: &N,
371		is_descendent_of: &F,
372		predicate: &P,
373	) -> Result<impl Iterator<Item = (H, N, V)>, Error<E>>
374	where
375		E: std::error::Error,
376		F: Fn(&H, &H) -> Result<bool, E>,
377		P: Fn(&V) -> bool,
378	{
379		let new_root_path =
380			match self.find_node_index_where(hash, number, is_descendent_of, predicate)? {
381				Some(path) => path,
382				None => return Ok(RemovedIterator { stack: Vec::new() }),
383			};
384
385		let mut removed = std::mem::take(&mut self.roots);
386
387		// Find and detach the new root from the removed nodes
388		let root_siblings = new_root_path
389			.iter()
390			.take(new_root_path.len() - 1)
391			.fold(&mut removed, |curr, idx| &mut curr[*idx].children);
392		let root = root_siblings.remove(new_root_path[new_root_path.len() - 1]);
393		self.roots = vec![root];
394
395		// If, because of the `predicate`, the new root is not the deepest ancestor
396		// of `hash` then we can remove all the nodes that are descendants of the new
397		// `root` but not ancestors of `hash`.
398		let mut curr = &mut self.roots[0];
399		loop {
400			let mut maybe_ancestor_idx = None;
401			for (idx, child) in curr.children.iter().enumerate() {
402				if child.number < *number && is_descendent_of(&child.hash, hash)? {
403					maybe_ancestor_idx = Some(idx);
404					break;
405				}
406			}
407			let Some(ancestor_idx) = maybe_ancestor_idx else {
408				// Now we are positioned just above block identified by `hash`
409				break;
410			};
411			// Preserve only the ancestor node, the siblings are removed
412			let mut next_siblings = std::mem::take(&mut curr.children);
413			let next = next_siblings.remove(ancestor_idx);
414			curr.children = vec![next];
415			removed.append(&mut next_siblings);
416			curr = &mut curr.children[0];
417		}
418
419		// Curr now points to our direct ancestor, if necessary remove any node that is
420		// not a descendant of `hash`.
421		let children = std::mem::take(&mut curr.children);
422		for child in children {
423			if child.number == *number && child.hash == *hash
424				|| *number < child.number && is_descendent_of(hash, &child.hash)?
425			{
426				curr.children.push(child);
427			} else {
428				removed.push(child);
429			}
430		}
431
432		self.rebalance();
433
434		Ok(RemovedIterator { stack: removed })
435	}
436
437	/// Finalize a root in the tree and return it, return `None` in case no root
438	/// with the given hash exists. All other roots are pruned, and the children
439	/// of the finalized node become the new roots.
440	pub fn finalize_root(&mut self, hash: &H) -> Option<V> {
441		self.roots
442			.iter()
443			.position(|node| node.hash == *hash)
444			.map(|position| self.finalize_root_at(position))
445	}
446
447	/// Finalize root at given position. See `finalize_root` comment for details.
448	fn finalize_root_at(&mut self, position: usize) -> V {
449		let node = self.roots.swap_remove(position);
450		self.roots = node.children;
451		self.best_finalized_number = Some(node.number);
452		node.data
453	}
454
455	/// Finalize a node in the tree. This method will make sure that the node
456	/// being finalized is either an existing root (and return its data), or a
457	/// node from a competing branch (not in the tree), tree pruning is done
458	/// accordingly. The given function `is_descendent_of` should return `true`
459	/// if the second hash (target) is a descendent of the first hash (base).
460	pub fn finalize<F, E>(
461		&mut self,
462		hash: &H,
463		number: N,
464		is_descendent_of: &F,
465	) -> Result<FinalizationResult<V>, Error<E>>
466	where
467		E: std::error::Error,
468		F: Fn(&H, &H) -> Result<bool, E>,
469	{
470		if let Some(ref best_finalized_number) = self.best_finalized_number {
471			if number <= *best_finalized_number {
472				return Err(Error::Revert);
473			}
474		}
475
476		// check if one of the current roots is being finalized
477		if let Some(root) = self.finalize_root(hash) {
478			return Ok(FinalizationResult::Changed(Some(root)));
479		}
480
481		// make sure we're not finalizing a descendent of any root
482		for root in self.roots.iter() {
483			if number > root.number && is_descendent_of(&root.hash, hash)? {
484				return Err(Error::UnfinalizedAncestor);
485			}
486		}
487
488		// we finalized a block earlier than any existing root (or possibly
489		// another fork not part of the tree). make sure to only keep roots that
490		// are part of the finalized branch
491		let mut changed = false;
492		let roots = std::mem::take(&mut self.roots);
493
494		for root in roots {
495			if root.number > number && is_descendent_of(hash, &root.hash)? {
496				self.roots.push(root);
497			} else {
498				changed = true;
499			}
500		}
501
502		self.best_finalized_number = Some(number);
503
504		if changed {
505			Ok(FinalizationResult::Changed(None))
506		} else {
507			Ok(FinalizationResult::Unchanged)
508		}
509	}
510
511	/// Finalize a node in the tree and all its ancestors. The given function
512	/// `is_descendent_of` should return `true` if the second hash (target) is
513	// a descendent of the first hash (base).
514	pub fn finalize_with_ancestors<F, E>(
515		&mut self,
516		hash: &H,
517		number: N,
518		is_descendent_of: &F,
519	) -> Result<FinalizationResult<V>, Error<E>>
520	where
521		E: std::error::Error,
522		F: Fn(&H, &H) -> Result<bool, E>,
523	{
524		if let Some(ref best_finalized_number) = self.best_finalized_number {
525			if number <= *best_finalized_number {
526				return Err(Error::Revert);
527			}
528		}
529
530		// check if one of the current roots is being finalized
531		if let Some(root) = self.finalize_root(hash) {
532			return Ok(FinalizationResult::Changed(Some(root)));
533		}
534
535		// we need to:
536		// 1) remove all roots that are not ancestors AND not descendants of finalized block;
537		// 2) if node is descendant - just leave it;
538		// 3) if node is ancestor - 'open it'
539		let mut changed = false;
540		let mut idx = 0;
541		while idx != self.roots.len() {
542			let (is_finalized, is_descendant, is_ancestor) = {
543				let root = &self.roots[idx];
544				let is_finalized = root.hash == *hash;
545				let is_descendant =
546					!is_finalized && root.number > number && is_descendent_of(hash, &root.hash)?;
547				let is_ancestor = !is_finalized
548					&& !is_descendant
549					&& root.number < number
550					&& is_descendent_of(&root.hash, hash)?;
551				(is_finalized, is_descendant, is_ancestor)
552			};
553
554			// if we have met finalized root - open it and return
555			if is_finalized {
556				return Ok(FinalizationResult::Changed(Some(self.finalize_root_at(idx))));
557			}
558
559			// if node is descendant of finalized block - just leave it as is
560			if is_descendant {
561				idx += 1;
562				continue;
563			}
564
565			// if node is ancestor of finalized block - remove it and continue with children
566			if is_ancestor {
567				let root = self.roots.swap_remove(idx);
568				self.roots.extend(root.children);
569				changed = true;
570				continue;
571			}
572
573			// if node is neither ancestor, nor descendant of the finalized block - remove it
574			self.roots.swap_remove(idx);
575			changed = true;
576		}
577
578		self.best_finalized_number = Some(number);
579
580		if changed {
581			Ok(FinalizationResult::Changed(None))
582		} else {
583			Ok(FinalizationResult::Unchanged)
584		}
585	}
586
587	/// Checks if any node in the tree is finalized by either finalizing the
588	/// node itself or a node's descendent that's not in the tree, guaranteeing
589	/// that the node being finalized isn't a descendent of (or equal to) any of
590	/// the node's children. Returns `Some(true)` if the node being finalized is
591	/// a root, `Some(false)` if the node being finalized is not a root, and
592	/// `None` if no node in the tree is finalized. The given `predicate` is
593	/// checked on the prospective finalized root and must pass for finalization
594	/// to occur. The given function `is_descendent_of` should return `true` if
595	/// the second hash (target) is a descendent of the first hash (base).
596	pub fn finalizes_any_with_descendent_if<F, P, E>(
597		&self,
598		hash: &H,
599		number: N,
600		is_descendent_of: &F,
601		predicate: P,
602	) -> Result<Option<bool>, Error<E>>
603	where
604		E: std::error::Error,
605		F: Fn(&H, &H) -> Result<bool, E>,
606		P: Fn(&V) -> bool,
607	{
608		if let Some(ref best_finalized_number) = self.best_finalized_number {
609			if number <= *best_finalized_number {
610				return Err(Error::Revert);
611			}
612		}
613
614		// check if the given hash is equal or a descendent of any node in the
615		// tree, if we find a valid node that passes the predicate then we must
616		// ensure that we're not finalizing past any of its child nodes.
617		for node in self.node_iter() {
618			if predicate(&node.data) && (node.hash == *hash || is_descendent_of(&node.hash, hash)?)
619			{
620				for child in node.children.iter() {
621					if child.number <= number
622						&& (child.hash == *hash || is_descendent_of(&child.hash, hash)?)
623					{
624						return Err(Error::UnfinalizedAncestor);
625					}
626				}
627
628				return Ok(Some(self.roots.iter().any(|root| root.hash == node.hash)));
629			}
630		}
631
632		Ok(None)
633	}
634
635	/// Finalize a root in the tree by either finalizing the node itself or a
636	/// node's descendent that's not in the tree, guaranteeing that the node
637	/// being finalized isn't a descendent of (or equal to) any of the root's
638	/// children. The given `predicate` is checked on the prospective finalized
639	/// root and must pass for finalization to occur. The given function
640	/// `is_descendent_of` should return `true` if the second hash (target) is a
641	/// descendent of the first hash (base).
642	pub fn finalize_with_descendent_if<F, P, E>(
643		&mut self,
644		hash: &H,
645		number: N,
646		is_descendent_of: &F,
647		predicate: P,
648	) -> Result<FinalizationResult<V>, Error<E>>
649	where
650		E: std::error::Error,
651		F: Fn(&H, &H) -> Result<bool, E>,
652		P: Fn(&V) -> bool,
653	{
654		if let Some(ref best_finalized_number) = self.best_finalized_number {
655			if number <= *best_finalized_number {
656				return Err(Error::Revert);
657			}
658		}
659
660		// check if the given hash is equal or a a descendent of any root, if we
661		// find a valid root that passes the predicate then we must ensure that
662		// we're not finalizing past any children node.
663		let mut position = None;
664		for (i, root) in self.roots.iter().enumerate() {
665			if predicate(&root.data) && (root.hash == *hash || is_descendent_of(&root.hash, hash)?)
666			{
667				for child in root.children.iter() {
668					if child.number <= number
669						&& (child.hash == *hash || is_descendent_of(&child.hash, hash)?)
670					{
671						return Err(Error::UnfinalizedAncestor);
672					}
673				}
674
675				position = Some(i);
676				break;
677			}
678		}
679
680		let node_data = position.map(|i| {
681			let node = self.roots.swap_remove(i);
682			self.roots = node.children;
683			self.best_finalized_number = Some(node.number);
684			node.data
685		});
686
687		// Retain only roots that are descendants of the finalized block (this
688		// happens if the node has been properly finalized) or that are
689		// ancestors (or equal) to the finalized block (in this case the node
690		// wasn't finalized earlier presumably because the predicate didn't
691		// pass).
692		let mut changed = false;
693		let roots = std::mem::take(&mut self.roots);
694
695		for root in roots {
696			let retain = root.number > number && is_descendent_of(hash, &root.hash)?
697				|| root.number == number && root.hash == *hash
698				|| is_descendent_of(&root.hash, hash)?;
699
700			if retain {
701				self.roots.push(root);
702			} else {
703				changed = true;
704			}
705		}
706
707		self.best_finalized_number = Some(number);
708
709		match (node_data, changed) {
710			(Some(data), _) => Ok(FinalizationResult::Changed(Some(data))),
711			(None, true) => Ok(FinalizationResult::Changed(None)),
712			(None, false) => Ok(FinalizationResult::Unchanged),
713		}
714	}
715
716	/// Remove from the tree some nodes (and their subtrees) using a `filter` predicate.
717	///
718	/// The `filter` is called over tree nodes and returns a filter action:
719	/// - `Remove` if the node and its subtree should be removed;
720	/// - `KeepNode` if we should maintain the node and keep processing the tree.
721	/// - `KeepTree` if we should maintain the node and its entire subtree.
722	///
723	/// An iterator over all the pruned nodes is returned.
724	pub fn drain_filter<F>(&mut self, filter: F) -> impl Iterator<Item = (H, N, V)>
725	where
726		F: Fn(&H, &N, &V) -> FilterAction,
727	{
728		let mut removed = vec![];
729		let mut retained = Vec::new();
730
731		let mut queue: Vec<_> = std::mem::take(&mut self.roots)
732			.into_iter()
733			.rev()
734			.map(|node| (usize::MAX, node))
735			.collect();
736		let mut next_queue = Vec::new();
737
738		while !queue.is_empty() {
739			for (parent_idx, mut node) in queue.drain(..) {
740				match filter(&node.hash, &node.number, &node.data) {
741					FilterAction::KeepNode => {
742						let node_idx = retained.len();
743						let children = std::mem::take(&mut node.children);
744						retained.push((parent_idx, node));
745						for child in children.into_iter().rev() {
746							next_queue.push((node_idx, child));
747						}
748					},
749					FilterAction::KeepTree => {
750						retained.push((parent_idx, node));
751					},
752					FilterAction::Remove => {
753						removed.push(node);
754					},
755				}
756			}
757
758			std::mem::swap(&mut queue, &mut next_queue);
759		}
760
761		while let Some((parent_idx, node)) = retained.pop() {
762			if parent_idx == usize::MAX {
763				self.roots.push(node);
764			} else {
765				retained[parent_idx].1.children.push(node);
766			}
767		}
768
769		if !removed.is_empty() {
770			self.rebalance();
771		}
772		RemovedIterator { stack: removed }
773	}
774}
775
776// Workaround for: https://github.com/rust-lang/rust/issues/34537
777use node_implementation::Node;
778
779mod node_implementation {
780	use super::*;
781
782	#[derive(Clone, Debug, Decode, Encode, PartialEq)]
783	pub struct Node<H, N, V> {
784		pub hash: H,
785		pub number: N,
786		pub data: V,
787		pub children: Vec<Node<H, N, V>>,
788	}
789
790	impl<H: PartialEq, N: Ord, V> Node<H, N, V> {
791		/// Finds the max depth among all branches descendent from this node.
792		pub fn max_depth(&self) -> usize {
793			let mut max: usize = 0;
794			let mut stack = vec![(self, 0)];
795			while let Some((node, height)) = stack.pop() {
796				if height > max {
797					max = height;
798				}
799				node.children.iter().for_each(|n| stack.push((n, height + 1)));
800			}
801			max
802		}
803	}
804}
805
806struct ForkTreeIterator<'a, H, N, V> {
807	stack: Vec<&'a Node<H, N, V>>,
808}
809
810impl<'a, H, N, V> Iterator for ForkTreeIterator<'a, H, N, V> {
811	type Item = &'a Node<H, N, V>;
812
813	fn next(&mut self) -> Option<Self::Item> {
814		self.stack.pop().inspect(|node| {
815			// child nodes are stored ordered by max branch height (decreasing),
816			// we want to keep this ordering while iterating but since we're
817			// using a stack for iterator state we need to reverse it.
818			self.stack.extend(node.children.iter().rev());
819		})
820	}
821}
822
823struct RemovedIterator<H, N, V> {
824	stack: Vec<Node<H, N, V>>,
825}
826
827impl<H, N, V> Iterator for RemovedIterator<H, N, V> {
828	type Item = (H, N, V);
829
830	fn next(&mut self) -> Option<Self::Item> {
831		self.stack.pop().map(|mut node| {
832			// child nodes are stored ordered by max branch height (decreasing),
833			// we want to keep this ordering while iterating but since we're
834			// using a stack for iterator state we need to reverse it.
835			let children = std::mem::take(&mut node.children);
836
837			self.stack.extend(children.into_iter().rev());
838			(node.hash, node.number, node.data)
839		})
840	}
841}
842
843#[cfg(test)]
844mod test {
845	use crate::FilterAction;
846
847	use super::{Error, FinalizationResult, ForkTree};
848
849	#[derive(Debug, PartialEq)]
850	struct TestError;
851
852	impl std::fmt::Display for TestError {
853		fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
854			write!(f, "TestError")
855		}
856	}
857
858	impl std::error::Error for TestError {}
859
860	fn test_pez_fork_tree<'a>(
861	) -> (ForkTree<&'a str, u64, u32>, impl Fn(&&str, &&str) -> Result<bool, TestError>) {
862		let mut tree = ForkTree::new();
863
864		#[rustfmt::skip]
865		//
866		//     +---B-c-C---D---E
867		//     |
868		//     |   +---G
869		//     |   | 
870		// 0---A---F---H---I
871		//     |       |
872		//     |       +---L-m-M---N
873		//     |           |
874		//     |           +---O
875		//     +---J---K
876		//
877		// (where N is not a part of fork tree)
878		//
879		// NOTE: the tree will get automatically rebalance on import and won't be laid out like the
880		// diagram above. the children will be ordered by subtree depth and the longest branches
881		// will be on the leftmost side of the tree.
882		let is_descendent_of = |base: &&str, block: &&str| -> Result<bool, TestError> {
883			let letters = vec!["B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O"];
884			// This is a trick to have lowercase blocks be direct parents of their
885			// uppercase correspondent (A excluded)
886			let block = block.to_uppercase();
887			match (*base, block) {
888				("A", b) => Ok(letters.into_iter().any(|n| n == b)),
889				("B" | "c", b) => Ok(b == "C" || b == "D" || b == "E"),
890				("C", b) => Ok(b == "D" || b == "E"),
891				("D", b) => Ok(b == "E"),
892				("E", _) => Ok(false),
893				("F", b) =>
894					Ok(b == "G" || b == "H" || b == "I" || b == "L" || b == "M" || b == "N" || b == "O"),
895				("G", _) => Ok(false),
896				("H", b) => Ok(b == "I" || b == "L" || b == "M" || b == "N" || b == "O"),
897				("I", _) => Ok(false),
898				("J", b) => Ok(b == "K"),
899				("K", _) => Ok(false),
900				("L", b) => Ok(b == "M" || b == "N" || b == "O"),
901				("m", b) => Ok(b == "M" || b == "N"),
902				("M", b) => Ok(b == "N"),
903				("O", _) => Ok(false),
904				("0", _) => Ok(true),
905				_ => Ok(false),
906			}
907		};
908
909		tree.import("A", 10, 1, &is_descendent_of).unwrap();
910		tree.import("B", 20, 2, &is_descendent_of).unwrap();
911		tree.import("C", 30, 3, &is_descendent_of).unwrap();
912		tree.import("D", 40, 4, &is_descendent_of).unwrap();
913		tree.import("E", 50, 5, &is_descendent_of).unwrap();
914		tree.import("F", 20, 2, &is_descendent_of).unwrap();
915		tree.import("G", 30, 3, &is_descendent_of).unwrap();
916		tree.import("H", 30, 3, &is_descendent_of).unwrap();
917		tree.import("I", 40, 4, &is_descendent_of).unwrap();
918		tree.import("L", 40, 4, &is_descendent_of).unwrap();
919		tree.import("M", 50, 5, &is_descendent_of).unwrap();
920		tree.import("O", 50, 5, &is_descendent_of).unwrap();
921		tree.import("J", 20, 2, &is_descendent_of).unwrap();
922		tree.import("K", 30, 3, &is_descendent_of).unwrap();
923
924		(tree, is_descendent_of)
925	}
926
927	#[test]
928	fn import_doesnt_revert() {
929		let (mut tree, is_descendent_of) = test_pez_fork_tree();
930
931		tree.finalize_root(&"A");
932
933		assert_eq!(tree.best_finalized_number, Some(10));
934
935		assert_eq!(tree.import("A", 10, 1, &is_descendent_of), Err(Error::Revert));
936	}
937
938	#[test]
939	fn import_doesnt_add_duplicates() {
940		let (mut tree, is_descendent_of) = test_pez_fork_tree();
941
942		assert_eq!(tree.import("A", 10, 1, &is_descendent_of), Err(Error::Duplicate));
943
944		assert_eq!(tree.import("I", 40, 4, &is_descendent_of), Err(Error::Duplicate));
945
946		assert_eq!(tree.import("G", 30, 3, &is_descendent_of), Err(Error::Duplicate));
947
948		assert_eq!(tree.import("K", 30, 3, &is_descendent_of), Err(Error::Duplicate));
949	}
950
951	#[test]
952	fn finalize_root_works() {
953		let finalize_a = || {
954			let (mut tree, ..) = test_pez_fork_tree();
955
956			assert_eq!(tree.roots().map(|(h, n, _)| (*h, *n)).collect::<Vec<_>>(), vec![("A", 10)]);
957
958			// finalizing "A" opens up three possible forks
959			tree.finalize_root(&"A");
960
961			assert_eq!(
962				tree.roots().map(|(h, n, _)| (*h, *n)).collect::<Vec<_>>(),
963				vec![("B", 20), ("F", 20), ("J", 20)],
964			);
965
966			tree
967		};
968
969		{
970			let mut tree = finalize_a();
971
972			// finalizing "B" will progress on its fork and remove any other competing forks
973			tree.finalize_root(&"B");
974
975			assert_eq!(tree.roots().map(|(h, n, _)| (*h, *n)).collect::<Vec<_>>(), vec![("C", 30)],);
976
977			// all the other forks have been pruned
978			assert!(tree.roots.len() == 1);
979		}
980
981		{
982			let mut tree = finalize_a();
983
984			// finalizing "J" will progress on its fork and remove any other competing forks
985			tree.finalize_root(&"J");
986
987			assert_eq!(tree.roots().map(|(h, n, _)| (*h, *n)).collect::<Vec<_>>(), vec![("K", 30)],);
988
989			// all the other forks have been pruned
990			assert!(tree.roots.len() == 1);
991		}
992	}
993
994	#[test]
995	fn finalize_works() {
996		let (mut tree, is_descendent_of) = test_pez_fork_tree();
997
998		let original_roots = tree.roots.clone();
999
1000		// finalizing a block prior to any in the node doesn't change the tree
1001		assert_eq!(tree.finalize(&"0", 0, &is_descendent_of), Ok(FinalizationResult::Unchanged));
1002
1003		assert_eq!(tree.roots, original_roots);
1004
1005		// finalizing "A" opens up three possible forks
1006		assert_eq!(
1007			tree.finalize(&"A", 10, &is_descendent_of),
1008			Ok(FinalizationResult::Changed(Some(1))),
1009		);
1010
1011		assert_eq!(
1012			tree.roots().map(|(h, n, _)| (*h, *n)).collect::<Vec<_>>(),
1013			vec![("B", 20), ("F", 20), ("J", 20)],
1014		);
1015
1016		// finalizing anything lower than what we observed will fail
1017		assert_eq!(tree.best_finalized_number, Some(10));
1018
1019		assert_eq!(tree.finalize(&"Z", 10, &is_descendent_of), Err(Error::Revert));
1020
1021		// trying to finalize a node without finalizing its ancestors first will fail
1022		assert_eq!(tree.finalize(&"H", 30, &is_descendent_of), Err(Error::UnfinalizedAncestor));
1023
1024		// after finalizing "F" we can finalize "H"
1025		assert_eq!(
1026			tree.finalize(&"F", 20, &is_descendent_of),
1027			Ok(FinalizationResult::Changed(Some(2))),
1028		);
1029
1030		assert_eq!(
1031			tree.finalize(&"H", 30, &is_descendent_of),
1032			Ok(FinalizationResult::Changed(Some(3))),
1033		);
1034
1035		assert_eq!(
1036			tree.roots().map(|(h, n, _)| (*h, *n)).collect::<Vec<_>>(),
1037			vec![("L", 40), ("I", 40)],
1038		);
1039
1040		// finalizing a node from another fork that isn't part of the tree clears the tree
1041		assert_eq!(
1042			tree.finalize(&"Z", 50, &is_descendent_of),
1043			Ok(FinalizationResult::Changed(None)),
1044		);
1045
1046		assert!(tree.roots.is_empty());
1047	}
1048
1049	#[test]
1050	fn finalize_with_ancestor_works() {
1051		let (mut tree, is_descendent_of) = test_pez_fork_tree();
1052
1053		let original_roots = tree.roots.clone();
1054
1055		// finalizing a block prior to any in the node doesn't change the tree
1056		assert_eq!(
1057			tree.finalize_with_ancestors(&"0", 0, &is_descendent_of),
1058			Ok(FinalizationResult::Unchanged),
1059		);
1060
1061		assert_eq!(tree.roots, original_roots);
1062
1063		// finalizing "A" opens up three possible forks
1064		assert_eq!(
1065			tree.finalize_with_ancestors(&"A", 10, &is_descendent_of),
1066			Ok(FinalizationResult::Changed(Some(1))),
1067		);
1068
1069		assert_eq!(
1070			tree.roots().map(|(h, n, _)| (*h, *n)).collect::<Vec<_>>(),
1071			vec![("B", 20), ("F", 20), ("J", 20)],
1072		);
1073
1074		// finalizing H:
1075		// 1) removes roots that are not ancestors/descendants of H (B, J)
1076		// 2) opens root that is ancestor of H (F -> G+H)
1077		// 3) finalizes the just opened root H (H -> I + L)
1078		assert_eq!(
1079			tree.finalize_with_ancestors(&"H", 30, &is_descendent_of),
1080			Ok(FinalizationResult::Changed(Some(3))),
1081		);
1082
1083		assert_eq!(
1084			tree.roots().map(|(h, n, _)| (*h, *n)).collect::<Vec<_>>(),
1085			vec![("L", 40), ("I", 40)],
1086		);
1087
1088		assert_eq!(tree.best_finalized_number, Some(30));
1089
1090		// finalizing N (which is not a part of the tree):
1091		// 1) removes roots that are not ancestors/descendants of N (I)
1092		// 2) opens root that is ancestor of N (L -> M+O)
1093		// 3) removes roots that are not ancestors/descendants of N (O)
1094		// 4) opens root that is ancestor of N (M -> {})
1095		assert_eq!(
1096			tree.finalize_with_ancestors(&"N", 60, &is_descendent_of),
1097			Ok(FinalizationResult::Changed(None)),
1098		);
1099
1100		assert_eq!(tree.roots().map(|(h, n, _)| (*h, *n)).collect::<Vec<_>>(), vec![],);
1101
1102		assert_eq!(tree.best_finalized_number, Some(60));
1103	}
1104
1105	#[test]
1106	fn finalize_with_descendent_works() {
1107		#[derive(Debug, PartialEq)]
1108		struct Change {
1109			effective: u64,
1110		}
1111
1112		let (mut tree, is_descendent_of) = {
1113			let mut tree = ForkTree::new();
1114
1115			let is_descendent_of = |base: &&str, block: &&str| -> Result<bool, TestError> {
1116				// A0 #1 - (B #2) - (C #5) - D #10 - E #15 - (F #100)
1117				//                            \
1118				//                             - (G #100)
1119				//
1120				// A1 #1
1121				//
1122				// Nodes B, C, F and G  are not part of the tree.
1123				match (*base, *block) {
1124					("A0", b) => Ok(b == "B" || b == "C" || b == "D" || b == "E" || b == "G"),
1125					("A1", _) => Ok(false),
1126					("C", b) => Ok(b == "D"),
1127					("D", b) => Ok(b == "E" || b == "F" || b == "G"),
1128					("E", b) => Ok(b == "F"),
1129					_ => Ok(false),
1130				}
1131			};
1132
1133			let is_root = tree.import("A0", 1, Change { effective: 5 }, &is_descendent_of).unwrap();
1134			assert!(is_root);
1135			let is_root = tree.import("A1", 1, Change { effective: 5 }, &is_descendent_of).unwrap();
1136			assert!(is_root);
1137			let is_root =
1138				tree.import("D", 10, Change { effective: 10 }, &is_descendent_of).unwrap();
1139			assert!(!is_root);
1140			let is_root =
1141				tree.import("E", 15, Change { effective: 50 }, &is_descendent_of).unwrap();
1142			assert!(!is_root);
1143
1144			(tree, is_descendent_of)
1145		};
1146
1147		assert_eq!(
1148			tree.finalizes_any_with_descendent_if(
1149				&"B",
1150				2,
1151				&is_descendent_of,
1152				|c| c.effective <= 2,
1153			),
1154			Ok(None),
1155		);
1156
1157		// finalizing "D" is not allowed since it is not a root.
1158		assert_eq!(
1159			tree.finalize_with_descendent_if(&"D", 10, &is_descendent_of, |c| c.effective <= 10),
1160			Err(Error::UnfinalizedAncestor)
1161		);
1162
1163		// finalizing "D" will finalize a block from the tree, but it can't be applied yet
1164		// since it is not a root change.
1165		assert_eq!(
1166			tree.finalizes_any_with_descendent_if(&"D", 10, &is_descendent_of, |c| c.effective
1167				== 10),
1168			Ok(Some(false)),
1169		);
1170
1171		// finalizing "E" is not allowed since there are not finalized ancestors.
1172		assert_eq!(
1173			tree.finalizes_any_with_descendent_if(&"E", 15, &is_descendent_of, |c| c.effective
1174				== 10),
1175			Err(Error::UnfinalizedAncestor)
1176		);
1177
1178		// finalizing "B" doesn't finalize "A0" since the predicate doesn't pass,
1179		// although it will clear out "A1" from the tree
1180		assert_eq!(
1181			tree.finalize_with_descendent_if(&"B", 2, &is_descendent_of, |c| c.effective <= 2),
1182			Ok(FinalizationResult::Changed(None)),
1183		);
1184
1185		assert_eq!(tree.roots().map(|(h, n, _)| (*h, *n)).collect::<Vec<_>>(), vec![("A0", 1)],);
1186
1187		// finalizing "C" will finalize the node "A0" and prune it out of the tree
1188		assert_eq!(
1189			tree.finalizes_any_with_descendent_if(
1190				&"C",
1191				5,
1192				&is_descendent_of,
1193				|c| c.effective <= 5,
1194			),
1195			Ok(Some(true)),
1196		);
1197
1198		assert_eq!(
1199			tree.finalize_with_descendent_if(&"C", 5, &is_descendent_of, |c| c.effective <= 5),
1200			Ok(FinalizationResult::Changed(Some(Change { effective: 5 }))),
1201		);
1202
1203		assert_eq!(tree.roots().map(|(h, n, _)| (*h, *n)).collect::<Vec<_>>(), vec![("D", 10)],);
1204
1205		// finalizing "F" will fail since it would finalize past "E" without finalizing "D" first
1206		assert_eq!(
1207			tree.finalizes_any_with_descendent_if(&"F", 100, &is_descendent_of, |c| c.effective
1208				<= 100,),
1209			Err(Error::UnfinalizedAncestor),
1210		);
1211
1212		// it will work with "G" though since it is not in the same branch as "E"
1213		assert_eq!(
1214			tree.finalizes_any_with_descendent_if(&"G", 100, &is_descendent_of, |c| c.effective
1215				<= 100),
1216			Ok(Some(true)),
1217		);
1218
1219		assert_eq!(
1220			tree.finalize_with_descendent_if(&"G", 100, &is_descendent_of, |c| c.effective <= 100),
1221			Ok(FinalizationResult::Changed(Some(Change { effective: 10 }))),
1222		);
1223
1224		// "E" will be pruned out
1225		assert_eq!(tree.roots().count(), 0);
1226	}
1227
1228	#[test]
1229	fn iter_iterates_in_preorder() {
1230		let (tree, ..) = test_pez_fork_tree();
1231		assert_eq!(
1232			tree.iter().map(|(h, n, _)| (*h, *n)).collect::<Vec<_>>(),
1233			vec![
1234				("A", 10),
1235				("B", 20),
1236				("C", 30),
1237				("D", 40),
1238				("E", 50),
1239				("F", 20),
1240				("H", 30),
1241				("L", 40),
1242				("M", 50),
1243				("O", 50),
1244				("I", 40),
1245				("G", 30),
1246				("J", 20),
1247				("K", 30),
1248			],
1249		);
1250	}
1251
1252	#[test]
1253	fn minimizes_calls_to_is_descendent_of() {
1254		use std::sync::atomic::{AtomicUsize, Ordering};
1255
1256		let n_is_descendent_of_calls = AtomicUsize::new(0);
1257
1258		let is_descendent_of = |_: &&str, _: &&str| -> Result<bool, TestError> {
1259			n_is_descendent_of_calls.fetch_add(1, Ordering::SeqCst);
1260			Ok(true)
1261		};
1262
1263		{
1264			// Deep tree where we want to call `finalizes_any_with_descendent_if`. The
1265			// search for the node should first check the predicate (which is cheaper) and
1266			// only then call `is_descendent_of`
1267			let mut tree = ForkTree::new();
1268			let letters = vec!["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"];
1269
1270			for (i, letter) in letters.iter().enumerate() {
1271				tree.import::<_, TestError>(*letter, i, i, &|_, _| Ok(true)).unwrap();
1272			}
1273
1274			// "L" is a descendent of "K", but the predicate will only pass for "K",
1275			// therefore only one call to `is_descendent_of` should be made
1276			assert_eq!(
1277				tree.finalizes_any_with_descendent_if(&"L", 11, &is_descendent_of, |i| *i == 10,),
1278				Ok(Some(false)),
1279			);
1280
1281			assert_eq!(n_is_descendent_of_calls.load(Ordering::SeqCst), 1);
1282		}
1283
1284		n_is_descendent_of_calls.store(0, Ordering::SeqCst);
1285
1286		{
1287			// Multiple roots in the tree where we want to call `finalize_with_descendent_if`.
1288			// The search for the root node should first check the predicate (which is cheaper)
1289			// and only then call `is_descendent_of`
1290			let mut tree = ForkTree::new();
1291			let letters = vec!["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"];
1292
1293			for (i, letter) in letters.iter().enumerate() {
1294				tree.import::<_, TestError>(*letter, i, i, &|_, _| Ok(false)).unwrap();
1295			}
1296
1297			// "L" is a descendent of "K", but the predicate will only pass for "K",
1298			// therefore only one call to `is_descendent_of` should be made
1299			assert_eq!(
1300				tree.finalize_with_descendent_if(&"L", 11, &is_descendent_of, |i| *i == 10,),
1301				Ok(FinalizationResult::Changed(Some(10))),
1302			);
1303
1304			assert_eq!(n_is_descendent_of_calls.load(Ordering::SeqCst), 1);
1305		}
1306	}
1307
1308	#[test]
1309	fn map_works() {
1310		let (mut tree, _) = test_pez_fork_tree();
1311
1312		// Extend the single root pez-fork-tree to also exercise the roots order during map.
1313		let is_descendent_of = |_: &&str, _: &&str| -> Result<bool, TestError> { Ok(false) };
1314		let is_root = tree.import("A1", 10, 1, &is_descendent_of).unwrap();
1315		assert!(is_root);
1316		let is_root = tree.import("A2", 10, 1, &is_descendent_of).unwrap();
1317		assert!(is_root);
1318
1319		let old_tree = tree.clone();
1320		let new_tree = tree.map(&mut |hash, _, _| hash.to_owned());
1321
1322		// Check content and order
1323		assert!(new_tree.iter().all(|(hash, _, data)| hash == data));
1324		assert_eq!(
1325			old_tree.iter().map(|(hash, _, _)| *hash).collect::<Vec<_>>(),
1326			new_tree.iter().map(|(hash, _, _)| *hash).collect::<Vec<_>>(),
1327		);
1328	}
1329
1330	#[test]
1331	fn prune_works_for_in_tree_hashes() {
1332		let (mut tree, is_descendent_of) = test_pez_fork_tree();
1333
1334		let removed = tree.prune(&"C", &30, &is_descendent_of, &|_| true).unwrap();
1335
1336		assert_eq!(tree.roots.iter().map(|node| node.hash).collect::<Vec<_>>(), vec!["B"]);
1337
1338		assert_eq!(
1339			tree.iter().map(|(hash, _, _)| *hash).collect::<Vec<_>>(),
1340			vec!["B", "C", "D", "E"],
1341		);
1342
1343		assert_eq!(
1344			removed.map(|(hash, _, _)| hash).collect::<Vec<_>>(),
1345			vec!["A", "F", "H", "L", "M", "O", "I", "G", "J", "K"]
1346		);
1347
1348		let removed = tree.prune(&"E", &50, &is_descendent_of, &|_| true).unwrap();
1349
1350		assert_eq!(tree.roots.iter().map(|node| node.hash).collect::<Vec<_>>(), vec!["D"]);
1351
1352		assert_eq!(tree.iter().map(|(hash, _, _)| *hash).collect::<Vec<_>>(), vec!["D", "E"]);
1353
1354		assert_eq!(removed.map(|(hash, _, _)| hash).collect::<Vec<_>>(), vec!["B", "C"]);
1355	}
1356
1357	#[test]
1358	fn prune_works_for_out_of_tree_hashes() {
1359		let (mut tree, is_descendent_of) = test_pez_fork_tree();
1360
1361		let removed = tree.prune(&"c", &25, &is_descendent_of, &|_| true).unwrap();
1362
1363		assert_eq!(tree.roots.iter().map(|node| node.hash).collect::<Vec<_>>(), vec!["B"]);
1364
1365		assert_eq!(
1366			tree.iter().map(|(hash, _, _)| *hash).collect::<Vec<_>>(),
1367			vec!["B", "C", "D", "E"],
1368		);
1369
1370		assert_eq!(
1371			removed.map(|(hash, _, _)| hash).collect::<Vec<_>>(),
1372			vec!["A", "F", "H", "L", "M", "O", "I", "G", "J", "K"]
1373		);
1374	}
1375
1376	#[test]
1377	fn prune_works_for_not_direct_ancestor() {
1378		let (mut tree, is_descendent_of) = test_pez_fork_tree();
1379
1380		// This is to re-root the tree not at the immediate ancestor, but the one just before.
1381		let removed = tree.prune(&"m", &45, &is_descendent_of, &|height| *height == 3).unwrap();
1382
1383		assert_eq!(tree.roots.iter().map(|node| node.hash).collect::<Vec<_>>(), vec!["H"]);
1384
1385		assert_eq!(tree.iter().map(|(hash, _, _)| *hash).collect::<Vec<_>>(), vec!["H", "L", "M"],);
1386
1387		assert_eq!(
1388			removed.map(|(hash, _, _)| hash).collect::<Vec<_>>(),
1389			vec!["O", "I", "A", "B", "C", "D", "E", "F", "G", "J", "K"]
1390		);
1391	}
1392
1393	#[test]
1394	fn prune_works_for_far_away_ancestor() {
1395		let (mut tree, is_descendent_of) = test_pez_fork_tree();
1396
1397		let removed = tree.prune(&"m", &45, &is_descendent_of, &|height| *height == 2).unwrap();
1398
1399		assert_eq!(tree.roots.iter().map(|node| node.hash).collect::<Vec<_>>(), vec!["F"]);
1400
1401		assert_eq!(
1402			tree.iter().map(|(hash, _, _)| *hash).collect::<Vec<_>>(),
1403			vec!["F", "H", "L", "M"],
1404		);
1405
1406		assert_eq!(
1407			removed.map(|(hash, _, _)| hash).collect::<Vec<_>>(),
1408			vec!["O", "I", "G", "A", "B", "C", "D", "E", "J", "K"]
1409		);
1410	}
1411
1412	#[test]
1413	fn find_node_backtracks_after_finding_highest_descending_node() {
1414		let mut tree = ForkTree::new();
1415
1416		// A - B
1417		//  \
1418		//   — C
1419		//
1420		let is_descendent_of = |base: &&str, block: &&str| -> Result<bool, TestError> {
1421			match (*base, *block) {
1422				("A", b) => Ok(b == "B" || b == "C" || b == "D"),
1423				("B", b) | ("C", b) => Ok(b == "D"),
1424				("0", _) => Ok(true),
1425				_ => Ok(false),
1426			}
1427		};
1428
1429		tree.import("A", 1, 1, &is_descendent_of).unwrap();
1430		tree.import("B", 2, 2, &is_descendent_of).unwrap();
1431		tree.import("C", 2, 4, &is_descendent_of).unwrap();
1432
1433		// when searching the tree we reach node `C`, but the
1434		// predicate doesn't pass. we should backtrack to `B`, but not to `A`,
1435		// since "B" fulfills the predicate.
1436		let node = tree.find_node_where(&"D", &3, &is_descendent_of, &|data| *data < 3).unwrap();
1437
1438		assert_eq!(node.unwrap().hash, "B");
1439	}
1440
1441	#[test]
1442	fn rebalance_works() {
1443		let (mut tree, _) = test_pez_fork_tree();
1444
1445		// the tree is automatically rebalanced on import, therefore we should iterate in preorder
1446		// exploring the longest forks first. check the ascii art above to understand the expected
1447		// output below.
1448		assert_eq!(
1449			tree.iter().map(|(h, _, _)| *h).collect::<Vec<_>>(),
1450			vec!["A", "B", "C", "D", "E", "F", "H", "L", "M", "O", "I", "G", "J", "K"],
1451		);
1452
1453		// let's add a block "P" which is a descendent of block "O"
1454		let is_descendent_of = |base: &&str, block: &&str| -> Result<bool, TestError> {
1455			match (*base, *block) {
1456				(b, "P") => Ok(vec!["A", "F", "H", "L", "O"].into_iter().any(|n| n == b)),
1457				_ => Ok(false),
1458			}
1459		};
1460
1461		tree.import("P", 60, 6, &is_descendent_of).unwrap();
1462
1463		// this should re-order the tree, since the branch "A -> B -> C -> D -> E" is no longer tied
1464		// with 5 blocks depth. additionally "O" should be visited before "M" now, since it has one
1465		// descendent "P" which makes that branch 6 blocks long.
1466		assert_eq!(
1467			tree.iter().map(|(h, _, _)| *h).collect::<Vec<_>>(),
1468			["A", "F", "H", "L", "O", "P", "M", "I", "G", "B", "C", "D", "E", "J", "K"]
1469		);
1470	}
1471
1472	#[test]
1473	fn drain_filter_works() {
1474		let (mut tree, _) = test_pez_fork_tree();
1475
1476		let filter = |h: &&str, _: &u64, _: &u32| match *h {
1477			"A" | "B" | "F" | "G" => FilterAction::KeepNode,
1478			"C" => FilterAction::KeepTree,
1479			"H" | "J" => FilterAction::Remove,
1480			_ => panic!("Unexpected filtering for node: {}", *h),
1481		};
1482
1483		let removed = tree.drain_filter(filter);
1484
1485		assert_eq!(
1486			tree.iter().map(|(h, _, _)| *h).collect::<Vec<_>>(),
1487			["A", "B", "C", "D", "E", "F", "G"]
1488		);
1489
1490		assert_eq!(
1491			removed.map(|(h, _, _)| h).collect::<Vec<_>>(),
1492			["H", "L", "M", "O", "I", "J", "K"]
1493		);
1494	}
1495
1496	#[test]
1497	fn find_node_index_works() {
1498		let (tree, is_descendent_of) = test_pez_fork_tree();
1499
1500		let path = tree
1501			.find_node_index_where(&"D", &40, &is_descendent_of, &|_| true)
1502			.unwrap()
1503			.unwrap();
1504		assert_eq!(path, [0, 0, 0]);
1505
1506		let path = tree
1507			.find_node_index_where(&"O", &50, &is_descendent_of, &|_| true)
1508			.unwrap()
1509			.unwrap();
1510		assert_eq!(path, [0, 1, 0, 0]);
1511
1512		let path = tree
1513			.find_node_index_where(&"N", &60, &is_descendent_of, &|_| true)
1514			.unwrap()
1515			.unwrap();
1516		assert_eq!(path, [0, 1, 0, 0, 0]);
1517	}
1518
1519	#[test]
1520	fn find_node_index_with_predicate_works() {
1521		let is_descendent_of = |parent: &char, child: &char| match *parent {
1522			'A' => Ok(['B', 'C', 'D', 'E', 'F'].contains(child)),
1523			'B' => Ok(['C', 'D'].contains(child)),
1524			'C' => Ok(['D'].contains(child)),
1525			'E' => Ok(['F'].contains(child)),
1526			'D' | 'F' => Ok(false),
1527			_ => Err(TestError),
1528		};
1529
1530		// A(t) --- B(f) --- C(t) --- D(f)
1531		//      \-- E(t) --- F(f)
1532		let mut tree: ForkTree<char, u8, bool> = ForkTree::new();
1533		tree.import('A', 1, true, &is_descendent_of).unwrap();
1534		tree.import('B', 2, false, &is_descendent_of).unwrap();
1535		tree.import('C', 3, true, &is_descendent_of).unwrap();
1536		tree.import('D', 4, false, &is_descendent_of).unwrap();
1537
1538		tree.import('E', 2, true, &is_descendent_of).unwrap();
1539		tree.import('F', 3, false, &is_descendent_of).unwrap();
1540
1541		let path = tree
1542			.find_node_index_where(&'D', &4, &is_descendent_of, &|&value| !value)
1543			.unwrap()
1544			.unwrap();
1545		assert_eq!(path, [0, 0]);
1546
1547		let path = tree
1548			.find_node_index_where(&'D', &4, &is_descendent_of, &|&value| value)
1549			.unwrap()
1550			.unwrap();
1551		assert_eq!(path, [0, 0, 0]);
1552
1553		let path = tree
1554			.find_node_index_where(&'F', &3, &is_descendent_of, &|&value| !value)
1555			.unwrap();
1556		assert_eq!(path, None);
1557
1558		let path = tree
1559			.find_node_index_where(&'F', &3, &is_descendent_of, &|&value| value)
1560			.unwrap()
1561			.unwrap();
1562		assert_eq!(path, [0, 1]);
1563	}
1564
1565	#[test]
1566	fn find_node_works() {
1567		let (tree, is_descendent_of) = test_pez_fork_tree();
1568
1569		let node = tree.find_node_where(&"B", &20, &is_descendent_of, &|_| true).unwrap().unwrap();
1570		assert_eq!((node.hash, node.number), ("A", 10));
1571
1572		let node = tree.find_node_where(&"D", &40, &is_descendent_of, &|_| true).unwrap().unwrap();
1573		assert_eq!((node.hash, node.number), ("C", 30));
1574
1575		let node = tree.find_node_where(&"O", &50, &is_descendent_of, &|_| true).unwrap().unwrap();
1576		assert_eq!((node.hash, node.number), ("L", 40));
1577
1578		let node = tree.find_node_where(&"N", &60, &is_descendent_of, &|_| true).unwrap().unwrap();
1579		assert_eq!((node.hash, node.number), ("M", 50));
1580	}
1581
1582	#[test]
1583	fn post_order_traversal_requirement() {
1584		let (mut tree, is_descendent_of) = test_pez_fork_tree();
1585
1586		// Test for the post-order DFS traversal requirement as specified by the
1587		// `find_node_index_where` and `import` comments.
1588		let is_descendent_of_for_post_order = |parent: &&str, child: &&str| match *parent {
1589			"A" => Err(TestError),
1590			"K" if *child == "Z" => Ok(true),
1591			_ => is_descendent_of(parent, child),
1592		};
1593
1594		// Post order traversal requirement for `find_node_index_where`
1595		let path = tree
1596			.find_node_index_where(&"N", &60, &is_descendent_of_for_post_order, &|_| true)
1597			.unwrap()
1598			.unwrap();
1599		assert_eq!(path, [0, 1, 0, 0, 0]);
1600
1601		// Post order traversal requirement for `import`
1602		let res = tree.import(&"Z", 100, 10, &is_descendent_of_for_post_order);
1603		assert_eq!(res, Ok(false));
1604		assert_eq!(
1605			tree.iter().map(|node| *node.0).collect::<Vec<_>>(),
1606			vec!["A", "B", "C", "D", "E", "F", "H", "L", "M", "O", "I", "G", "J", "K", "Z"],
1607		);
1608	}
1609}