Struct fuel_merkle::common::Position

source ·
pub struct Position(/* private fields */);
Expand description

§Position

A Position represents a node’s position in a binary tree by encapsulating the node’s index data. Indices are calculated through in-order traversal of the nodes, starting with the first leaf node. Indexing starts at 0.

Merkle Trees

In the context of Merkle trees, trees are constructed “upwards” from leaf nodes. Therefore, indexing is done from the bottom up, starting with the leaves, rather than top down, starting with the root, and we can guarantee a deterministic construction of index data.

              07
             /  \
            /    \
           /      \
          /        \
         /          \
        /            \
      03              11
     /  \            /  \
    /    \          /    \
  01      05      09      13
 /  \    /  \    /  \    /  \
00  02  04  06  08  10  12  14

In-order indices can be considered internal to the Position struct and are used to facilitate the calculation of positional attributes and the construction of other nodes. Leaf nodes have both an in-order index as part of the tree, and a leaf index determined by its position in the bottom row. Because of the in-order traversal used to calculate the in-order indices, leaf nodes have the property that their in-order index is always equal to their leaf index multiplied by 2.

                   /  \    /  \    /  \    /  \
    Leaf indices: 00  01  02  03  04  05  06  07
In-order indices: 00  02  04  06  08  10  12  14

This allows us to construct a Position (and its in-order index) by providing either an in-order index directly or, in the case of a leaf, a leaf index. This functionality is captured by from_in_order_index() and from_leaf_index() respectively.

Traversal of a Merkle Tree can be performed by the methods on a given Position to retrieve its sibling, parent, or uncle Position.

Merkle Mountain Ranges

Because the Position indices are calculated from in-order traversal starting with the leaves, the deterministic quality of the indices holds true for imbalanced binary trees, including Merkle Mountain Ranges. Consider the following binary tree construction composed of seven leaves (with leaf indices 0 through 6):

      03
     /  \
    /    \
  01      05      09
 /  \    /  \    /  \
00  02  04  06  08  10  12

Note the absence of internal nodes that would be present in a fully balanced tree: inner nodes with indices 7 and 11 are absent. This is owing to the fact that node indices are calculated deterministically through in-order traversal, not calculated as a sequence.

Traversal of a Merkle Mountain Range is still done in the same manner as a balanced Merkle tree, using methods to retrieve a Position's sibling, parent, or uncle Position. However, in such cases, the corresponding sibling or uncle nodes are not guaranteed to exist in the tree.

Implementations§

source§

impl Position

source

pub fn in_order_index(self) -> u64

source

pub fn leaf_index(self) -> u64

source

pub fn from_in_order_index(index: u64) -> Self

Construct a position from an in-order index.

source

pub fn from_leaf_index(index: u64) -> Option<Self>

Construct a position from a leaf index. The in-order index corresponding to the leaf index will always equal the leaf index multiplied by 2. Panics if index is too large to fit into u64.

source

pub fn parent(self) -> Result<Self, GetNodeError>

The parent position. The parent position has a height less 1 relative to this position.

source

pub fn child(self, side: Side) -> Result<Self, GetNodeError>

The child position of the current position given by the direction. A child position has a height less 1 than the current position.

A child position is calculated as a function of the current position’s index and height, and the supplied direction. The left child position has the in-order index arriving before the current index; the right child position has the in-order index arriving after the current index.

source

pub fn left_child(self) -> Result<Self, GetNodeError>

Returns the left child of the current position.

source

pub fn right_child(self) -> Result<Self, GetNodeError>

Returns the right child of the current position.

source

pub fn height(self) -> u32

The height of the index in a binary tree. Leaf nodes represent height 0. A leaf’s parent represents height 1. Height values monotonically increase as you ascend the tree.

Height is deterministically calculated as the number of trailing zeros of the complement of the position’s index. The following table demonstrates the relationship between a position’s height and the trailing zeros.

Index (Dec)Index (Bin)!Index (Bin)Trailing 0sHeight
00000111100
20010110100
40100101100
10001111011
50101101011
91001011011
30011110022
111011010022
source

pub fn is_leaf(self) -> bool

Whether or not this position represents a leaf node. Returns true if the position is a leaf node. Returns false if the position is an internal node.

A position is a leaf node if and only if its in-order index is even. A position is an internal node if and only if its in-order index is odd.

source

pub fn is_node(self) -> bool

Whether or not this position represents an internal node. Returns false if the position is a leaf node. Returns true if the position is an internal node.

When a position is an internal node, the position will have both a left and right child.

source

pub fn path(self, leaf: &Self, leaves_count: u64) -> PositionPath

Given a leaf position and the total count of leaves in a tree, get the path from this position to the given leaf position. The shape of the tree is defined by the leaves_count parameter and constrains the path. See PositionPath.

Trait Implementations§

source§

impl Clone for Position

source§

fn clone(&self) -> Position

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Position

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl PartialEq for Position

source§

fn eq(&self, other: &Position) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl Copy for Position

source§

impl Eq for Position

source§

impl StructuralPartialEq for Position

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> AsPathIterator<T> for T
where T: ParentNode + Clone, <T as Node>::Key: Clone,

source§

fn as_path_iter(&self, leaf_key: &<T as Node>::Key) -> PathIter<T>

source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<T> StorageAsMut for T

source§

fn storage<Type>(&mut self) -> StorageMut<'_, Self, Type>
where Type: Mappable,

source§

fn storage_as_mut<Type>(&mut self) -> StorageMut<'_, Self, Type>
where Type: Mappable,

source§

impl<T> StorageAsRef for T

source§

fn storage<Type>(&self) -> StorageRef<'_, Self, Type>
where Type: Mappable,

source§

fn storage_as_ref<Type>(&self) -> StorageRef<'_, Self, Type>
where Type: Mappable,

source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.