diem_types/proof/position/
mod.rs

1// Copyright (c) The Diem Core Contributors
2// SPDX-License-Identifier: Apache-2.0
3
4// Copyright 2021 Conflux Foundation. All rights reserved.
5// Conflux is free software and distributed under GNU General Public License.
6// See http://www.gnu.org/licenses/
7
8//! This module provides an abstraction for positioning a node in a binary tree,
9//! A `Position` uniquely identifies the location of a node
10//!
11//! In this implementation, `Position` is represented by the in-order-traversal
12//! sequence number of the node.  The process of locating a node and jumping
13//! between nodes is done through in-order position calculation, which can be
14//! done with bit manipulation.
15//!
16//! For example
17//! ```text
18//!      3
19//!     /  \
20//!    /    \
21//!   1      5 <-[Node index, a.k.a, Position]
22//!  / \    / \
23//! 0   2  4   6
24//!
25//! 0   1  2   3 <[Leaf index]
26//! ```
27//! Note1: The in-order-traversal counts from 0
28//! Note2: The level of tree counts from leaf level, start from 0
29//! Note3: The leaf index starting from left-most leaf, starts from 0
30
31use crate::proof::definition::{
32    LeafCount, MAX_ACCUMULATOR_LEAVES, MAX_ACCUMULATOR_PROOF_DEPTH,
33};
34use anyhow::{ensure, Result};
35use mirai_annotations::*;
36use std::fmt;
37
38#[cfg(test)]
39mod position_test;
40
41#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
42pub struct Position(u64);
43// invariant Position.0 < u64::max_value() - 1
44
45#[derive(Debug, Eq, PartialEq)]
46pub enum NodeDirection {
47    Left,
48    Right,
49}
50
51impl Position {
52    /// What level is this node in the tree, 0 if the node is a leaf,
53    /// 1 if the level is one above a leaf, etc.
54    pub fn level(self) -> u32 { (!self.0).trailing_zeros() }
55
56    fn is_leaf(self) -> bool { self.0 & 1 == 0 }
57
58    /// What position is the node within the level? i.e. how many nodes
59    /// are to the left of this node at the same level
60    #[cfg(test)]
61    fn pos_counting_from_left(self) -> u64 { self.0 >> (self.level() + 1) }
62
63    /// pos count start from 0 on each level
64    pub fn from_level_and_pos(level: u32, pos: u64) -> Self {
65        precondition!(level < 64);
66        assume!(1u64 << level > 0); // bitwise and integer operations don't mix.
67        let level_one_bits = (1u64 << level) - 1;
68        let shifted_pos = if level == 63 { 0 } else { pos << (level + 1) };
69        Position(shifted_pos | level_one_bits)
70    }
71
72    pub fn from_inorder_index(index: u64) -> Self { Position(index) }
73
74    pub fn to_inorder_index(self) -> u64 { self.0 }
75
76    pub fn from_postorder_index(index: u64) -> Result<Self> {
77        ensure!(
78            index < !0u64,
79            "node index {} is invalid (equal to 2^64 - 1)",
80            index
81        );
82        Ok(Position(postorder_to_inorder(index)))
83    }
84
85    pub fn to_postorder_index(self) -> u64 {
86        inorder_to_postorder(self.to_inorder_index())
87    }
88
89    /// What is the parent of this node?
90    pub fn parent(self) -> Self {
91        assume!(self.0 < u64::max_value() - 1); // invariant
92        Self(
93            (self.0 | isolate_rightmost_zero_bit(self.0))
94                & !(isolate_rightmost_zero_bit(self.0) << 1),
95        )
96    }
97
98    /// What is the left node of this node? Will overflow if the node is a leaf
99    pub fn left_child(self) -> Self {
100        checked_precondition!(!self.is_leaf());
101        Self::child(self, NodeDirection::Left)
102    }
103
104    /// What is the right node of this node? Will overflow if the node is a leaf
105    pub fn right_child(self) -> Self {
106        checked_precondition!(!self.is_leaf());
107        Self::child(self, NodeDirection::Right)
108    }
109
110    fn child(self, dir: NodeDirection) -> Self {
111        checked_precondition!(!self.is_leaf());
112        assume!(self.0 < u64::max_value() - 1); // invariant
113
114        let direction_bit = match dir {
115            NodeDirection::Left => 0,
116            NodeDirection::Right => isolate_rightmost_zero_bit(self.0),
117        };
118        Self(
119            (self.0 | direction_bit)
120                & !(isolate_rightmost_zero_bit(self.0) >> 1),
121        )
122    }
123
124    /// Whether this position is a left child of its parent.  The observation is
125    /// that, after stripping out all right-most 1 bits, a left child will
126    /// have a bit pattern of xxx00(11..), while a right child will be
127    /// represented by xxx10(11..)
128    pub fn is_left_child(self) -> bool {
129        assume!(self.0 < u64::max_value() - 1); // invariant
130        self.0 & (isolate_rightmost_zero_bit(self.0) << 1) == 0
131    }
132
133    pub fn is_right_child(self) -> bool { !self.is_left_child() }
134
135    // Opposite of get_left_node_count_from_position.
136    pub fn from_leaf_index(leaf_index: u64) -> Self {
137        Self::from_level_and_pos(0, leaf_index)
138    }
139
140    /// This method takes in a node position and return its sibling position
141    ///
142    /// The observation is that, after stripping out the right-most common bits,
143    /// two sibling nodes flip the next right-most bits with each other.
144    /// To find out the right-most common bits, first remove all the right-most
145    /// ones because they are corresponding to level's indicator. Then
146    /// remove next zero right after.
147    pub fn sibling(self) -> Self {
148        assume!(self.0 < u64::max_value() - 1); // invariant
149        Self(self.0 ^ (isolate_rightmost_zero_bit(self.0) << 1))
150    }
151
152    // Given a leaf index, calculate the position of a minimum root which
153    // contains this leaf
154    /// This method calculates the index of the smallest root which contains
155    /// this leaf. Observe that, the root position is composed by a "height"
156    /// number of ones
157    ///
158    /// For example
159    /// ```text
160    ///     0010010(node)
161    ///     0011111(smearing)
162    ///     -------
163    ///     0001111(root)
164    /// ```
165    pub fn root_from_leaf_index(leaf_index: u64) -> Self {
166        let leaf = Self::from_leaf_index(leaf_index);
167        Self(smear_ones_for_u64(leaf.0) >> 1)
168    }
169
170    pub fn root_from_leaf_count(leaf_count: LeafCount) -> Self {
171        assert!(leaf_count > 0);
172        Self::root_from_leaf_index((leaf_count - 1) as u64)
173    }
174
175    pub fn root_level_from_leaf_count(leaf_count: LeafCount) -> u32 {
176        assert!(leaf_count > 0);
177        let index = (leaf_count - 1) as u64;
178        MAX_ACCUMULATOR_PROOF_DEPTH as u32 + 1 - index.leading_zeros()
179    }
180
181    /// Given a node, find its right most child in its subtree.
182    /// Right most child is a Position, could be itself, at level 0
183    pub fn right_most_child(self) -> Self {
184        let level = self.level();
185        Self(self.0 + (1_u64 << level) - 1)
186    }
187
188    /// Given a node, find its left most child in its subtree
189    /// Left most child is a node, could be itself, at level 0
190    pub fn left_most_child(self) -> Self {
191        // Turn off its right most x bits. while x=level of node
192        let level = self.level();
193        Self(turn_off_right_most_n_bits(self.0, level))
194    }
195}
196
197// Some helper functions to perform general bit manipulation
198
199/// Smearing all the bits starting from MSB with ones
200fn smear_ones_for_u64(v: u64) -> u64 {
201    let mut n = v;
202    n |= n >> 1;
203    n |= n >> 2;
204    n |= n >> 4;
205    n |= n >> 8;
206    n |= n >> 16;
207    n |= n >> 32;
208    n
209}
210
211/// Turn off n right most bits
212///
213/// For example
214/// ```text
215///     00010010101
216///     -----------
217///     00010010100 n=1
218///     00010010000 n=3
219/// ```
220fn turn_off_right_most_n_bits(v: u64, n: u32) -> u64 {
221    debug_checked_precondition!(n < 64);
222    (v >> n) << n
223}
224
225/// Finds the rightmost 0-bit, turns off all bits, and sets this bit to 1 in
226/// the result. For example:
227///
228/// ```text
229///     01110111  (x)
230///     --------
231///     10001000  (~x)
232/// &   01111000  (x+1)
233///     --------
234///     00001000
235/// ```
236/// http://www.catonmat.net/blog/low-level-bit-hacks-you-absolutely-must-know/
237fn isolate_rightmost_zero_bit(v: u64) -> u64 { !v & v.overflowing_add(1).0 }
238
239// The following part of the position implementation is logically separate and
240// depends on our notion of freezable.  It should probably move to another
241// module.
242impl Position {
243    // Given index of right most leaf, calculate if a position is the root
244    // of a perfect subtree that does not contain any placeholder nodes.
245    //
246    // First find its right most child
247    // the right most child of any node will be at leaf level, which will be a
248    // either placeholder node or leaf node. if right most child is a leaf
249    // node, then it is freezable. if right most child is larger than
250    // max_leaf_node, it is a placeholder node, and not freezable.
251    pub fn is_freezable(self, leaf_index: u64) -> bool {
252        let leaf = Self::from_leaf_index(leaf_index);
253        let right_most_child = self.right_most_child();
254        right_most_child.0 <= leaf.0
255    }
256
257    // Given index of right most leaf, calculate if a position should contain
258    // a placeholder node at this moment
259    // A node is a placeholder if both two conditions below are true:
260    // 1, the node's in order traversal seq > max_leaf_node's, and
261    // 2, the node does not have left child or right child.
262    pub fn is_placeholder(self, leaf_index: u64) -> bool {
263        let leaf = Self::from_leaf_index(leaf_index);
264        if self.0 <= leaf.0 {
265            return false;
266        }
267        if self.left_most_child().0 <= leaf.0 {
268            return false;
269        }
270        true
271    }
272
273    /// Creates an `AncestorIterator` using this position.
274    pub fn iter_ancestor(self) -> AncestorIterator {
275        AncestorIterator { position: self }
276    }
277
278    /// Creates an `AncestorSiblingIterator` using this position.
279    pub fn iter_ancestor_sibling(self) -> AncestorSiblingIterator {
280        AncestorSiblingIterator { position: self }
281    }
282}
283
284impl fmt::Display for Position {
285    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
286        write!(f, "Pos({})", self.to_inorder_index())
287    }
288}
289
290/// `AncestorSiblingIterator` generates current sibling position and moves
291/// itself to its parent position for each iteration.
292#[derive(Debug)]
293pub struct AncestorSiblingIterator {
294    position: Position,
295}
296
297impl Iterator for AncestorSiblingIterator {
298    type Item = Position;
299
300    fn next(&mut self) -> Option<Position> {
301        let current_sibling_position = self.position.sibling();
302        self.position = self.position.parent();
303        Some(current_sibling_position)
304    }
305}
306
307/// `AncestorIterator` generates current position and moves itself to its parent
308/// position for each iteration.
309#[derive(Debug)]
310pub struct AncestorIterator {
311    position: Position,
312}
313
314impl Iterator for AncestorIterator {
315    type Item = Position;
316
317    fn next(&mut self) -> Option<Position> {
318        let current_position = self.position;
319        self.position = self.position.parent();
320        Some(current_position)
321    }
322}
323
324/// Traverse leaves from left to right in groups that forms full subtrees,
325/// yielding root positions of such subtrees.
326/// Note that each 1-bit in num_leaves corresponds to a full subtree.
327/// For example, in the below tree of 5=0b101 leaves, the two 1-bits corresponds
328/// to Fzn2 and L4 accordingly.
329///
330/// ```text
331///            Non-fzn
332///           /       \
333///          /         \
334///         /           \
335///       Fzn2         Non-fzn
336///      /   \           /   \
337///     /     \         /     \
338///    Fzn1    Fzn3  Non-fzn  [Placeholder]
339///   /  \    /  \    /    \
340///  L0  L1  L2  L3 L4   [Placeholder]
341/// ```
342pub struct FrozenSubTreeIterator {
343    bitmap: u64,
344    seen_leaves: u64,
345    // invariant seen_leaves < u64::max_value() - bitmap
346}
347
348impl FrozenSubTreeIterator {
349    pub fn new(num_leaves: LeafCount) -> Self {
350        Self {
351            bitmap: num_leaves,
352            seen_leaves: 0,
353        }
354    }
355}
356
357impl Iterator for FrozenSubTreeIterator {
358    type Item = Position;
359
360    fn next(&mut self) -> Option<Position> {
361        assume!(self.seen_leaves < u64::max_value() - self.bitmap); // invariant
362
363        if self.bitmap == 0 {
364            return None;
365        }
366
367        // Find the remaining biggest full subtree.
368        // The MSB of the bitmap represents it. For example for a tree of
369        // 0b1010=10 leaves, the biggest and leftmost full subtree has
370        // 0b1000=8 leaves, which can be got by smearing all bits after
371        // MSB with 1-bits (got 0b1111), right shift once (got 0b0111) and add 1
372        // (got 0b1000=8). At the same time, we also observe that the
373        // in-order numbering of a full subtree root is (num_leaves - 1)
374        // greater than that of the leftmost leaf, and also (num_leaves
375        // - 1) less than that of the rightmost leaf.
376        let root_offset = smear_ones_for_u64(self.bitmap) >> 1;
377        assume!(root_offset < self.bitmap); // relate bit logic to integer logic
378        let num_leaves = root_offset + 1;
379        let leftmost_leaf = Position::from_leaf_index(self.seen_leaves);
380        let root = Position::from_inorder_index(
381            leftmost_leaf.to_inorder_index() + root_offset,
382        );
383
384        // Mark it consumed.
385        self.bitmap &= !num_leaves;
386        self.seen_leaves += num_leaves;
387
388        Some(root)
389    }
390}
391
392/// Given an accumulator of size `current_num_leaves`,
393/// `FrozenSubtreeSiblingIterator` yields the positions of required subtrees if
394/// we want to append these subtrees to the existing accumulator to generate a
395/// bigger one of size `new_num_leaves`.
396pub struct FrozenSubtreeSiblingIterator {
397    current_num_leaves: LeafCount,
398    remaining_new_leaves: LeafCount,
399}
400
401impl FrozenSubtreeSiblingIterator {
402    /// Constructs a new `FrozenSubtreeSiblingIterator` given the size of
403    /// current accumulator and the size of the bigger accumulator.
404    pub fn new(
405        current_num_leaves: LeafCount, new_num_leaves: LeafCount,
406    ) -> Self {
407        assert!(
408            new_num_leaves <= MAX_ACCUMULATOR_LEAVES,
409            "An accumulator can have at most 2^{} leaves. Provided num_leaves: {}.",
410            MAX_ACCUMULATOR_PROOF_DEPTH,
411            new_num_leaves,
412        );
413        assert!(
414            current_num_leaves <= new_num_leaves,
415            "Number of leaves needs to be increasing: current_num_leaves: {}, new_num_leaves: {}",
416            current_num_leaves,
417            new_num_leaves
418        );
419
420        Self {
421            current_num_leaves,
422            remaining_new_leaves: new_num_leaves - current_num_leaves,
423        }
424    }
425
426    /// Helper function to return the next set of leaves that form a complete
427    /// subtree.  For example, if there are 5 leaves (..0101), 2 ^ (63 - 61
428    /// leading zeros) = 4 leaves should be taken next.
429    fn next_new_leaf_batch(&self) -> LeafCount {
430        let zeros = self.remaining_new_leaves.leading_zeros();
431        1 << (MAX_ACCUMULATOR_PROOF_DEPTH - zeros as usize)
432    }
433}
434
435impl Iterator for FrozenSubtreeSiblingIterator {
436    type Item = Position;
437
438    fn next(&mut self) -> Option<Self::Item> {
439        if self.remaining_new_leaves == 0 {
440            return None;
441        }
442
443        // Now we compute the size of the next subtree. If there is a rightmost
444        // frozen subtree, we may combine it with a subtree of the same
445        // size, or append a smaller one on the right. In
446        // case self.current_num_leaves is zero and there is no rightmost frozen
447        // subtree, the largest possible one is appended.
448        let next_subtree_leaves = if self.current_num_leaves > 0 {
449            let rightmost_frozen_subtree_leaves =
450                1 << self.current_num_leaves.trailing_zeros();
451            if self.remaining_new_leaves >= rightmost_frozen_subtree_leaves {
452                rightmost_frozen_subtree_leaves
453            } else {
454                self.next_new_leaf_batch()
455            }
456        } else {
457            self.next_new_leaf_batch()
458        };
459
460        // Now that the size of the next subtree is known, we compute the
461        // leftmost and rightmost leaves in this subtree. The root of
462        // the subtree is then the middle of these two leaves.
463        let first_leaf_index = self.current_num_leaves;
464        let last_leaf_index = first_leaf_index + next_subtree_leaves - 1;
465        self.current_num_leaves += next_subtree_leaves;
466        self.remaining_new_leaves -= next_subtree_leaves;
467
468        Some(Position::from_inorder_index(
469            (first_leaf_index + last_leaf_index) as u64,
470        ))
471    }
472}
473
474fn children_of_node(node: u64) -> u64 {
475    (isolate_rightmost_zero_bit(node) << 1) - 2
476}
477
478/// In a post-order tree traversal, how many nodes are traversed before `node`
479/// not including nodes that are children of `node`.
480fn nodes_to_left_of(node: u64) -> u64 {
481    // If node = 0b0100111, ones_up_to_level = 0b111
482    let ones_up_to_level = isolate_rightmost_zero_bit(node) - 1;
483    // Unset all the 1s due to the level
484    let unset_level_zeros = node ^ ones_up_to_level;
485
486    // What remains is a 1 bit set every time a node navigated right
487    // For example, consider node=5=0b101. unset_level_zeros=0b100.
488    // the 1 bit in unset_level_zeros at position 2 represents the
489    // fact that 5 is the right child at the level 1. At this level
490    // there are 2^2 - 1 children on the left hand side.
491    //
492    // So what we do is subtract the count of one bits from unset_level_zeros
493    // to account for the fact that if the node is the right child at level
494    // n that there are 2^n - 1 children.
495    unset_level_zeros - u64::from(unset_level_zeros.count_ones())
496}
497
498/// Given `node`, an index in an in-order traversal of a perfect binary tree,
499/// what order would the node be visited in post-order traversal?
500/// For example, consider this tree of in-order nodes.
501///
502/// ```text
503///      3
504///     /  \
505///    /    \
506///   1      5
507///  / \    / \
508/// 0   2  4   6
509/// ```
510///
511/// The post-order ordering of the nodes is:
512/// ```text
513///      6
514///     /  \
515///    /    \
516///   2      5
517///  / \    / \
518/// 0   1  3   4
519/// ```
520///
521/// post_order_index(1) == 2
522/// post_order_index(4) == 3
523pub fn inorder_to_postorder(node: u64) -> u64 {
524    let children = children_of_node(node);
525    let left_nodes = nodes_to_left_of(node);
526
527    children + left_nodes
528}
529
530pub fn postorder_to_inorder(mut node: u64) -> u64 {
531    // The number of nodes in a full binary tree with height `n` is `2^n - 1`.
532    let mut full_binary_size = !0u64;
533    let mut bitmap = 0u64;
534    for i in (0..64).rev() {
535        if node >= full_binary_size {
536            node -= full_binary_size;
537            bitmap |= 1 << i;
538        }
539        full_binary_size >>= 1;
540    }
541    let level = node as u32;
542    let pos = bitmap >> level;
543    Position::from_level_and_pos(level, pos).to_inorder_index()
544}