grin_core/core/pmmr/
pmmr.rs

1// Copyright 2021 The Grin Developers
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::{iter, marker, ops::Range, u64};
16
17use croaring::Bitmap;
18
19use crate::core::hash::{Hash, ZERO_HASH};
20use crate::core::merkle_proof::MerkleProof;
21use crate::core::pmmr::{Backend, ReadonlyPMMR};
22use crate::core::BlockHeader;
23use crate::ser::{PMMRIndexHashable, PMMRable};
24
25/// Trait with common methods for reading from a PMMR
26pub trait ReadablePMMR {
27	/// Leaf type
28	type Item;
29
30	/// Get the hash at provided position in the MMR.
31	/// NOTE all positions are 0-based, so a size n MMR has nodes in positions 0 through n-1
32	/// just like a Rust Range 0..n
33	fn get_hash(&self, pos: u64) -> Option<Hash>;
34
35	/// Get the data element at provided position in the MMR.
36	fn get_data(&self, pos: u64) -> Option<Self::Item>;
37
38	/// Get the hash from the underlying MMR file (ignores the remove log).
39	fn get_from_file(&self, pos: u64) -> Option<Hash>;
40
41	/// Get the hash for the provided peak pos.
42	/// Optimized for reading peak hashes rather than arbitrary pos hashes.
43	/// Peaks can be assumed to not be compacted.
44	fn get_peak_from_file(&self, pos: u64) -> Option<Hash>;
45
46	/// Get the data element at provided position in the MMR (ignores the remove log).
47	fn get_data_from_file(&self, pos: u64) -> Option<Self::Item>;
48
49	/// Total size of the tree, including intermediary nodes and ignoring any pruning.
50	fn unpruned_size(&self) -> u64;
51
52	/// Iterator over current (unpruned, unremoved) leaf positions.
53	fn leaf_pos_iter(&self) -> Box<dyn Iterator<Item = u64> + '_>;
54
55	/// Iterator over current (unpruned, unremoved) leaf insertion indices.
56	fn leaf_idx_iter(&self, from_idx: u64) -> Box<dyn Iterator<Item = u64> + '_>;
57
58	/// Number of leaves in the MMR
59	fn n_unpruned_leaves(&self) -> u64;
60
61	/// Number of leaves in the MMR up to index
62	fn n_unpruned_leaves_to_index(&self, to_index: u64) -> u64;
63
64	/// Is the MMR empty?
65	fn is_empty(&self) -> bool {
66		self.unpruned_size() == 0
67	}
68
69	/// Takes a single peak position and hashes together
70	/// all the peaks to the right of this peak (if any).
71	/// If this return a hash then this is our peaks sibling.
72	/// If none then the sibling of our peak is the peak to the left.
73	fn bag_the_rhs(&self, peak_pos0: u64) -> Option<Hash> {
74		let size = self.unpruned_size();
75		let rhs = peaks(size)
76			.into_iter()
77			.filter(|&x| x > peak_pos0)
78			.filter_map(|x| self.get_from_file(x));
79
80		let mut res = None;
81		for peak in rhs.rev() {
82			res = match res {
83				None => Some(peak),
84				Some(rhash) => Some((peak, rhash).hash_with_index(size)),
85			}
86		}
87		res
88	}
89
90	/// Returns a vec of the peaks of this MMR.
91	fn peaks(&self) -> Vec<Hash> {
92		peaks(self.unpruned_size())
93			.into_iter()
94			.filter_map(move |pi0| self.get_peak_from_file(pi0))
95			.collect()
96	}
97
98	/// Hashes of the peaks excluding `peak_pos`, where the rhs is bagged together
99	fn peak_path(&self, peak_pos0: u64) -> Vec<Hash> {
100		let rhs = self.bag_the_rhs(peak_pos0);
101		let mut res = peaks(self.unpruned_size())
102			.into_iter()
103			.filter(|&x| x < peak_pos0)
104			.filter_map(|x| self.get_peak_from_file(x))
105			.collect::<Vec<_>>();
106		if let Some(rhs) = rhs {
107			res.push(rhs);
108		}
109		res.reverse();
110
111		res
112	}
113
114	/// Computes the root of the MMR. Find all the peaks in the current
115	/// tree and "bags" them to get a single peak.
116	fn root(&self) -> Result<Hash, String> {
117		if self.is_empty() {
118			return Ok(ZERO_HASH);
119		}
120		let mut res = None;
121		let peaks = self.peaks();
122		let mmr_size = self.unpruned_size();
123		for peak in peaks.into_iter().rev() {
124			res = match res {
125				None => Some(peak),
126				Some(rhash) => Some((peak, rhash).hash_with_index(mmr_size)),
127			}
128		}
129		res.ok_or_else(|| "no root, invalid tree".to_owned())
130	}
131
132	/// Build a Merkle proof for the element at the given position.
133	fn merkle_proof(&self, pos0: u64) -> Result<MerkleProof, String> {
134		let size = self.unpruned_size();
135		debug!("merkle_proof  {}, size {}", pos0, size);
136
137		// check this pos is actually a leaf in the MMR
138		if !is_leaf(pos0) {
139			return Err(format!("not a leaf at pos {}", pos0));
140		}
141
142		// check we actually have a hash in the MMR at this pos
143		self.get_hash(pos0)
144			.ok_or_else(|| format!("no element at pos {}", pos0))?;
145
146		let family_branch = family_branch(pos0, size);
147
148		let mut path = family_branch
149			.iter()
150			.filter_map(|x| self.get_from_file(x.1))
151			.collect::<Vec<_>>();
152
153		let peak_pos = match family_branch.last() {
154			Some(&(x, _)) => x,
155			None => pos0,
156		};
157
158		path.append(&mut self.peak_path(peak_pos));
159
160		Ok(MerkleProof {
161			mmr_size: size,
162			path,
163		})
164	}
165}
166
167/// Prunable Merkle Mountain Range implementation. All positions within the tree
168/// start at 0 just like array indices.
169///
170/// Heavily relies on navigation operations within a binary tree. In particular,
171/// all the implementation needs to keep track of the MMR structure is how far
172/// we are in the sequence of nodes making up the MMR.
173pub struct PMMR<'a, T, B>
174where
175	T: PMMRable,
176	B: Backend<T>,
177{
178	/// Number of nodes in the PMMR
179	pub size: u64,
180	backend: &'a mut B,
181	// only needed to parameterise Backend
182	_marker: marker::PhantomData<T>,
183}
184
185impl<'a, T, B> PMMR<'a, T, B>
186where
187	T: PMMRable,
188	B: 'a + Backend<T>,
189{
190	/// Build a new prunable Merkle Mountain Range using the provided backend.
191	pub fn new(backend: &'a mut B) -> PMMR<'_, T, B> {
192		PMMR {
193			backend,
194			size: 0,
195			_marker: marker::PhantomData,
196		}
197	}
198
199	/// Build a new prunable Merkle Mountain Range pre-initialized until
200	/// size with the provided backend.
201	pub fn at(backend: &'a mut B, size: u64) -> PMMR<'_, T, B> {
202		PMMR {
203			backend,
204			size,
205			_marker: marker::PhantomData,
206		}
207	}
208
209	/// Build a "readonly" view of this PMMR.
210	pub fn readonly_pmmr(&self) -> ReadonlyPMMR<'_, T, B> {
211		ReadonlyPMMR::at(&self.backend, self.size)
212	}
213
214	/// Push a new element into the MMR. Computes new related peaks at
215	/// the same time if applicable.
216	pub fn push(&mut self, leaf: &T) -> Result<u64, String> {
217		let leaf_pos = self.size;
218		let mut current_hash = leaf.hash_with_index(leaf_pos);
219
220		let mut hashes = vec![current_hash];
221		let mut pos = leaf_pos;
222
223		let (peak_map, height) = peak_map_height(pos);
224		if height != 0 {
225			return Err(format!("bad mmr size {}", pos));
226		}
227		// hash with all immediately preceding peaks, as indicated by peak map
228		let mut peak = 1;
229		while (peak_map & peak) != 0 {
230			let left_sibling = pos + 1 - 2 * peak;
231			let left_hash = self
232				.backend
233				.get_peak_from_file(left_sibling)
234				.ok_or("missing left sibling in tree, should not have been pruned")?;
235			peak *= 2;
236			pos += 1;
237			current_hash = (left_hash, current_hash).hash_with_index(pos);
238			hashes.push(current_hash);
239		}
240
241		// append all the new nodes and update the MMR index
242		self.backend.append(leaf, &hashes)?;
243		self.size = pos + 1;
244		Ok(leaf_pos)
245	}
246
247	/// Push a pruned subtree into the PMMR
248	pub fn push_pruned_subtree(&mut self, hash: Hash, pos0: u64) -> Result<(), String> {
249		// First append the subtree
250		self.backend.append_pruned_subtree(hash, pos0)?;
251		self.size = pos0 + 1;
252
253		let mut pos = pos0;
254		let mut current_hash = hash;
255
256		let (peak_map, _) = peak_map_height(pos);
257
258		// Then hash with all immediately preceding peaks, as indicated by peak map
259		let mut peak = 1;
260		while (peak_map & peak) != 0 {
261			let (parent, sibling) = family(pos);
262			peak *= 2;
263			if sibling > pos {
264				// is right sibling, we should be done
265				continue;
266			}
267			let left_hash = self
268				.backend
269				.get_hash(sibling)
270				.ok_or("missing left sibling in tree, should not have been pruned")?;
271			pos = parent;
272			current_hash = (left_hash, current_hash).hash_with_index(parent);
273			self.backend.append_hash(current_hash)?;
274		}
275
276		// Round size up to next leaf, ready for insertion
277		self.size = crate::core::pmmr::round_up_to_leaf_pos(pos);
278		Ok(())
279	}
280
281	/// Reset prune list
282	pub fn reset_prune_list(&mut self) {
283		self.backend.reset_prune_list();
284	}
285
286	/// Remove the specified position from the leaf set
287	pub fn remove_from_leaf_set(&mut self, pos0: u64) {
288		self.backend.remove_from_leaf_set(pos0);
289	}
290
291	/// Saves a snapshot of the MMR tagged with the block hash.
292	/// Specifically - snapshots the utxo file as we need this rewound before
293	/// sending the txhashset zip file to another node for fast-sync.
294	pub fn snapshot(&mut self, header: &BlockHeader) -> Result<(), String> {
295		self.backend.snapshot(header)?;
296		Ok(())
297	}
298
299	/// Rewind the PMMR to a previous position, as if all push operations after
300	/// that had been canceled. Expects a position in the PMMR to rewind and
301	/// bitmaps representing the positions added and removed that we want to
302	/// "undo".
303	pub fn rewind(&mut self, position: u64, rewind_rm_pos: &Bitmap) -> Result<(), String> {
304		// Identify which actual position we should rewind to as the provided
305		// position is a leaf. We traverse the MMR to include any parent(s) that
306		// need to be included for the MMR to be valid.
307		let leaf_pos = round_up_to_leaf_pos(position);
308		self.backend.rewind(leaf_pos, rewind_rm_pos)?;
309		self.size = leaf_pos;
310		Ok(())
311	}
312
313	/// Prunes (removes) the leaf from the MMR at the specified position.
314	/// Returns an error if prune is called on a non-leaf position.
315	/// Returns false if the leaf node has already been pruned.
316	/// Returns true if pruning is successful.
317	pub fn prune(&mut self, pos0: u64) -> Result<bool, String> {
318		if !is_leaf(pos0) {
319			return Err(format!("Node at {} is not a leaf, can't prune.", pos0));
320		}
321
322		if self.backend.get_hash(pos0).is_none() {
323			return Ok(false);
324		}
325
326		self.backend.remove(pos0)?;
327		Ok(true)
328	}
329
330	/// Walks all unpruned nodes in the MMR and revalidate all parent hashes
331	pub fn validate(&self) -> Result<(), String> {
332		// iterate on all parent nodes
333		for n in 0..self.size {
334			let height = bintree_postorder_height(n);
335			if height > 0 {
336				if let Some(hash) = self.get_hash(n) {
337					let left_pos = n - (1 << height);
338					let right_pos = n - 1;
339					// using get_from_file here for the children (they may have been "removed")
340					if let Some(left_child_hs) = self.get_from_file(left_pos) {
341						if let Some(right_child_hs) = self.get_from_file(right_pos) {
342							// hash the two child nodes together with parent_pos and compare
343							if (left_child_hs, right_child_hs).hash_with_index(n) != hash {
344								return Err(format!(
345									"Invalid MMR, hash of parent at {} does \
346									 not match children.",
347									n + 1
348								));
349							}
350						}
351					}
352				}
353			}
354		}
355		Ok(())
356	}
357
358	/// Debugging utility to print information about the MMRs. Short version
359	/// only prints the last 8 nodes.
360	pub fn dump(&self, short: bool) {
361		let sz = self.unpruned_size();
362		if sz > 2000 && !short {
363			return;
364		}
365		let start = if short { sz / 8 } else { 0 };
366		for n in start..(sz / 8 + 1) {
367			let mut idx = "".to_owned();
368			let mut hashes = "".to_owned();
369			for m in (n * 8)..(n + 1) * 8 {
370				if m >= sz {
371					break;
372				}
373				idx.push_str(&format!("{:>8} ", m));
374				let ohs = self.get_hash(m);
375				match ohs {
376					Some(hs) => hashes.push_str(&format!("{} ", hs)),
377					None => hashes.push_str(&format!("{:>8} ", "??")),
378				}
379			}
380			debug!("{}", idx);
381			debug!("{}", hashes);
382		}
383	}
384
385	/// Prints PMMR statistics to the logs, used for debugging.
386	pub fn dump_stats(&self) {
387		debug!("pmmr: unpruned - {}", self.unpruned_size());
388		self.backend.dump_stats();
389	}
390
391	/// Debugging utility to print information about the MMRs. Short version
392	/// only prints the last 8 nodes.
393	/// Looks in the underlying hash file and so ignores the remove log.
394	pub fn dump_from_file(&self, short: bool) {
395		let sz = self.unpruned_size();
396		if sz > 2000 && !short {
397			return;
398		}
399		let start = if short { sz / 8 } else { 0 };
400		for n in start..(sz / 8 + 1) {
401			let mut idx = "".to_owned();
402			let mut hashes = "".to_owned();
403			for m in (n * 8)..(n + 1) * 8 {
404				if m >= sz {
405					break;
406				}
407				idx.push_str(&format!("{:>8} ", m + 1));
408				let ohs = self.get_from_file(m);
409				match ohs {
410					Some(hs) => hashes.push_str(&format!("{} ", hs)),
411					None => hashes.push_str(&format!("{:>8} ", " .")),
412				}
413			}
414			debug!("{}", idx);
415			debug!("{}", hashes);
416		}
417	}
418}
419
420impl<'a, T, B> ReadablePMMR for PMMR<'a, T, B>
421where
422	T: PMMRable,
423	B: 'a + Backend<T>,
424{
425	type Item = T::E;
426
427	fn get_hash(&self, pos0: u64) -> Option<Hash> {
428		if pos0 >= self.size {
429			None
430		} else if is_leaf(pos0) {
431			// If we are a leaf then get hash from the backend.
432			self.backend.get_hash(pos0)
433		} else {
434			// If we are not a leaf get hash ignoring the remove log.
435			self.backend.get_from_file(pos0)
436		}
437	}
438
439	fn get_data(&self, pos0: u64) -> Option<Self::Item> {
440		if pos0 >= self.size {
441			// If we are beyond the rhs of the MMR return None.
442			None
443		} else if is_leaf(pos0) {
444			// If we are a leaf then get data from the backend.
445			self.backend.get_data(pos0)
446		} else {
447			// If we are not a leaf then return None as only leaves have data.
448			None
449		}
450	}
451
452	fn get_from_file(&self, pos0: u64) -> Option<Hash> {
453		if pos0 >= self.size {
454			None
455		} else {
456			self.backend.get_from_file(pos0)
457		}
458	}
459
460	fn get_peak_from_file(&self, pos0: u64) -> Option<Hash> {
461		if pos0 >= self.size {
462			None
463		} else {
464			self.backend.get_peak_from_file(pos0)
465		}
466	}
467
468	fn get_data_from_file(&self, pos0: u64) -> Option<Self::Item> {
469		if pos0 >= self.size {
470			None
471		} else {
472			self.backend.get_data_from_file(pos0)
473		}
474	}
475
476	fn unpruned_size(&self) -> u64 {
477		self.size
478	}
479
480	fn leaf_pos_iter(&self) -> Box<dyn Iterator<Item = u64> + '_> {
481		self.backend.leaf_pos_iter()
482	}
483
484	fn leaf_idx_iter(&self, from_idx: u64) -> Box<dyn Iterator<Item = u64> + '_> {
485		self.backend.leaf_idx_iter(from_idx)
486	}
487
488	fn n_unpruned_leaves(&self) -> u64 {
489		self.backend.n_unpruned_leaves()
490	}
491
492	fn n_unpruned_leaves_to_index(&self, to_index: u64) -> u64 {
493		self.backend.n_unpruned_leaves_to_index(to_index)
494	}
495}
496
497/// 64 bits all ones: 0b11111111...1
498const ALL_ONES: u64 = u64::MAX;
499
500/// peak bitmap and height of next node in mmr of given size
501/// Example: on size 4 returns (0b11, 0) as mmr tree of size 4 is
502///    2
503///   / \
504///  0   1   3
505/// with 0b11 indicating the presence of peaks of height 0 and 1,
506/// and 0 the height of the next node 4, which is a leaf
507/// NOTE:
508/// the peak map also encodes the path taken from the root to the added node
509/// since the path turns left (resp. right) if-and-only-if
510/// a peak at that height is absent (resp. present)
511pub fn peak_map_height(mut size: u64) -> (u64, u64) {
512	if size == 0 {
513		// rust can't shift right by 64
514		return (0, 0);
515	}
516	let mut peak_size = ALL_ONES >> size.leading_zeros();
517	let mut peak_map = 0;
518	while peak_size != 0 {
519		peak_map <<= 1;
520		if size >= peak_size {
521			size -= peak_size;
522			peak_map |= 1;
523		}
524		peak_size >>= 1;
525	}
526	(peak_map, size)
527}
528
529/// sizes of peaks and height of next node in mmr of given size
530/// similar to peak_map_height but replacing bitmap by vector of sizes
531/// Example: on input 5 returns ([3,1], 1) as mmr state before adding 5 was
532///    2
533///   / \
534///  0   1   3   4
535pub fn peak_sizes_height(mut size: u64) -> (Vec<u64>, u64) {
536	if size == 0 {
537		// rust can't shift right by 64
538		return (vec![], 0);
539	}
540	let mut peak_size = ALL_ONES >> size.leading_zeros();
541	let mut peak_sizes = vec![];
542	while peak_size != 0 {
543		if size >= peak_size {
544			peak_sizes.push(peak_size);
545			size -= peak_size;
546		}
547		peak_size >>= 1;
548	}
549	(peak_sizes, size)
550}
551
552/// Gets the postorder traversal 0-based index of all peaks in a MMR given its size.
553/// Starts with the top peak, which is always on the left
554/// side of the range, and navigates toward lower siblings toward the right
555/// of the range.
556/// For some odd reason, return empty when next node is not a leaf
557pub fn peaks(size: u64) -> Vec<u64> {
558	let (peak_sizes, height) = peak_sizes_height(size);
559	if height == 0 {
560		peak_sizes
561			.iter()
562			.scan(0, |acc, &x| {
563				*acc += &x;
564				Some(*acc)
565			})
566			.map(|x| x - 1) // rust doesn't allow starting scan with -1 as u64
567			.collect()
568	} else {
569		vec![]
570	}
571}
572/// The number of leaves in a MMR of the provided size.
573pub fn n_leaves(size: u64) -> u64 {
574	let (peak_map, height) = peak_map_height(size);
575	if height == 0 {
576		peak_map
577	} else {
578		peak_map + 1
579	}
580}
581
582/// returns least position >= pos0 with height 0
583pub fn round_up_to_leaf_pos(pos0: u64) -> u64 {
584	let (insert_idx, height) = peak_map_height(pos0);
585	let leaf_idx = if height == 0 {
586		insert_idx
587	} else {
588		insert_idx + 1
589	};
590	return insertion_to_pmmr_index(leaf_idx);
591}
592
593/// Returns the 0-based pmmr index of 0-based leaf index n
594pub fn insertion_to_pmmr_index(nleaf0: u64) -> u64 {
595	2 * nleaf0 - nleaf0.count_ones() as u64
596}
597
598/// Returns the insertion index of the given leaf index
599pub fn pmmr_leaf_to_insertion_index(pos0: u64) -> Option<u64> {
600	let (insert_idx, height) = peak_map_height(pos0);
601	if height == 0 {
602		Some(insert_idx)
603	} else {
604		None
605	}
606}
607
608/// The height of a node in a full binary tree from its postorder traversal
609/// index.
610pub fn bintree_postorder_height(pos0: u64) -> u64 {
611	peak_map_height(pos0).1
612}
613
614/// Is this position a leaf in the MMR?
615/// We know the positions of all leaves based on the postorder height of an MMR
616/// of any size (somewhat unintuitively but this is how the PMMR is "append
617/// only").
618pub fn is_leaf(pos0: u64) -> bool {
619	bintree_postorder_height(pos0) == 0
620}
621
622/// Calculates the positions of the parent and sibling of the node at the
623/// provided position.
624pub fn family(pos0: u64) -> (u64, u64) {
625	let (peak_map, height) = peak_map_height(pos0);
626	let peak = 1 << height;
627	if (peak_map & peak) != 0 {
628		(pos0 + 1, pos0 + 1 - 2 * peak)
629	} else {
630		(pos0 + 2 * peak, pos0 + 2 * peak - 1)
631	}
632}
633
634/// Is the node at this pos the "left" sibling of its parent?
635pub fn is_left_sibling(pos0: u64) -> bool {
636	let (peak_map, height) = peak_map_height(pos0);
637	let peak = 1 << height;
638	(peak_map & peak) == 0
639}
640
641/// For a given starting position calculate the parent and sibling positions
642/// for the branch/path from that position to the peak of the tree.
643/// We will use the sibling positions to generate the "path" of a Merkle proof.
644pub fn family_branch(pos0: u64, size: u64) -> Vec<(u64, u64)> {
645	// loop going up the tree, from node to parent, as long as we stay inside
646	// the tree (as defined by size).
647	let (peak_map, height) = peak_map_height(pos0);
648	let mut peak = 1 << height;
649	let mut branch = vec![];
650	let mut current = pos0;
651	let mut sibling;
652	while current + 1 < size {
653		if (peak_map & peak) != 0 {
654			current += 1;
655			sibling = current - 2 * peak;
656		} else {
657			current += 2 * peak;
658			sibling = current - 1;
659		};
660		if current >= size {
661			break;
662		}
663		branch.push((current, sibling));
664		peak <<= 1;
665	}
666	branch
667}
668
669/// Gets the position of the rightmost node (i.e. leaf) beneath the provided subtree root.
670pub fn bintree_rightmost(pos0: u64) -> u64 {
671	pos0 - bintree_postorder_height(pos0)
672}
673
674/// Gets the position of the leftmost node (i.e. leaf) beneath the provided subtree root.
675pub fn bintree_leftmost(pos0: u64) -> u64 {
676	let height = bintree_postorder_height(pos0);
677	pos0 + 2 - (2 << height)
678}
679
680/// Iterator over all leaf pos beneath the provided subtree root (including the root itself).
681pub fn bintree_leaf_pos_iter(pos0: u64) -> Box<dyn Iterator<Item = u64>> {
682	let leaf_start = pmmr_leaf_to_insertion_index(bintree_leftmost(pos0));
683	let leaf_end = pmmr_leaf_to_insertion_index(bintree_rightmost(pos0));
684	let leaf_start = match leaf_start {
685		Some(l) => l,
686		None => return Box::new(iter::empty::<u64>()),
687	};
688	let leaf_end = match leaf_end {
689		Some(l) => l,
690		None => return Box::new(iter::empty::<u64>()),
691	};
692	Box::new((leaf_start..=leaf_end).map(|n| insertion_to_pmmr_index(n)))
693}
694
695/// Iterator over all pos beneath the provided subtree root (including the root itself).
696pub fn bintree_pos_iter(pos0: u64) -> impl Iterator<Item = u64> {
697	let leaf_start = bintree_leftmost(pos0);
698	(leaf_start..=pos0).into_iter()
699}
700
701/// All pos in the subtree beneath the provided root, including root itself.
702pub fn bintree_range(pos0: u64) -> Range<u64> {
703	let height = bintree_postorder_height(pos0);
704	let leftmost = pos0 + 2 - (2 << height);
705	leftmost..(pos0 + 1)
706}