Grafting

Struct Grafting 

Source
pub struct Grafting<'a, H: CHasher> { /* private fields */ }
Expand description

Hasher for computing leaf, node and root digests when the tree is being grafted onto another MMR.

§Terminology

  • Peak Tree: The MMR or Merkle tree that is being grafted.
  • Base MMR: The MMR onto which we are grafting (cannot be a Merkle tree).

Grafting involves mapping the leaves of the peak tree to corresponding nodes in the base MMR. It allows for shorter inclusion proofs over the combined trees compared to treating them as independent.

One example use case is the crate::adb::current::Current authenticated database, where a MMR is built over a log of operations, and a merkle tree over a bitmap indicating the activity state of each operation. If we were to treat the two trees as independent, then an inclusion proof for an operation and its activity state would involve a full branch from each structure. When using grafting, we can trim the branch from the base MMR at the point it “flows” up into the peak tree, reducing the size of the proof by a constant factor up to 2.

For concreteness, let’s assume we have a base MMR over a log of 8 operations represented by the 8 leaves:

   Height
     3              14
                  /    \
                 /      \
                /        \
               /          \
     2        6            13
            /   \        /    \
     1     2     5      9     12
          / \   / \    / \   /  \
     0   0   1 3   4  7   8 10  11

Let’s assume each leaf in our peak tree corresponds to 4 leaves in the base MMR. The structure of the peak tree can be obtained by chopping off the bottom log2(4)=2 levels of the base MMR structure:

   Height
     1              2 (was 14)
                  /    \
                 /      \
                /        \
               /          \
     0        0 (was 6)    1 (was 13)

The inverse of this procedure provides our algorithm for mapping a peak tree leaf’s position to a base MMR node position: take the leaf’s position in the peak tree, map it to any of the corresponding leaves in the base MMR, then walk up the base MMR structure exactly the number of levels we removed.

In this example, leaf 0 in the peak tree corresponds to leaves [0,1,3,4] in the base MMR. Walking up two levels from any of these base MMR leaves produces node 6 of the base MMR, which is thus its grafting point. Leaf 1 in the peak tree corresponds to leaves [7,8,10,11] in the base MMR, yielding node 13 as its grafting point.

Implementations§

Source§

impl<'a, H: CHasher> Grafting<'a, H>

Source

pub fn new(hasher: &'a mut Standard<H>, height: u32) -> Self

Source

pub fn standard(&mut self) -> &mut Standard<H>

Access the underlying Standard (non-grafting) hasher.

Source

pub async fn load_grafted_digests( &mut self, leaves: &[u64], mmr: &impl Storage<H::Digest>, ) -> Result<(), Error>

Loads the grafted digests for the specified leaves into the internal map. Does not clear out any previously loaded digests. This method must be used to provide grafted digests for any leaf whose leaf_digest needs to be computed.

§Warning

Panics if any of the grafted digests are missing from the MMR.

Trait Implementations§

Source§

impl<H: CHasher> Hasher<H> for Grafting<'_, H>

Source§

fn leaf_digest(&mut self, pos: u64, element: &[u8]) -> H::Digest

Computes the digest of a leaf in the peak_tree of a grafted MMR.

§Warning

Panics if the grafted_digest was not previously loaded for the leaf.

Source§

fn fork(&self) -> impl Hasher<H>

Fork the hasher to provide equivalent functionality in another thread. This is different than Clone::clone because the forked hasher need not be a deep copy, and may share non-mutable state with the hasher from which it was forked.
Source§

fn node_digest( &mut self, pos: u64, left_digest: &H::Digest, right_digest: &H::Digest, ) -> H::Digest

Computes the digest for a node given its position and the digests of its children.
Source§

fn root<'a>( &mut self, size: u64, peak_digests: impl Iterator<Item = &'a H::Digest>, ) -> H::Digest

Computes the root for an MMR given its size and an iterator over the digests of its peaks in decreasing order of height.
Source§

fn digest(&mut self, data: &[u8]) -> H::Digest

Compute the digest of a byte slice.
Source§

fn inner(&mut self) -> &mut H

Access the inner CHasher hasher.

Auto Trait Implementations§

§

impl<'a, H> Freeze for Grafting<'a, H>

§

impl<'a, H> RefUnwindSafe for Grafting<'a, H>

§

impl<'a, H> Send for Grafting<'a, H>

§

impl<'a, H> Sync for Grafting<'a, H>

§

impl<'a, H> Unpin for Grafting<'a, H>
where <H as Hasher>::Digest: Unpin,

§

impl<'a, H> !UnwindSafe for Grafting<'a, H>

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> 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<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FutureExt for T

Source§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
Source§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

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

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

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

Source§

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>,

Source§

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.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,