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>
impl<'a, H: CHasher> Grafting<'a, H>
pub fn new(hasher: &'a mut Standard<H>, height: u32) -> Self
Sourcepub fn standard(&mut self) -> &mut Standard<H>
pub fn standard(&mut self) -> &mut Standard<H>
Access the underlying Standard (non-grafting) hasher.
Sourcepub async fn load_grafted_digests(
&mut self,
leaves: &[u64],
mmr: &impl Storage<H::Digest>,
) -> Result<(), Error>
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>
impl<H: CHasher> Hasher<H> for Grafting<'_, H>
Source§fn leaf_digest(&mut self, pos: u64, element: &[u8]) -> H::Digest
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>
fn fork(&self) -> impl Hasher<H>
Source§fn node_digest(
&mut self,
pos: u64,
left_digest: &H::Digest,
right_digest: &H::Digest,
) -> H::Digest
fn node_digest( &mut self, pos: u64, left_digest: &H::Digest, right_digest: &H::Digest, ) -> H::Digest
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>
impl<'a, H> !UnwindSafe for Grafting<'a, H>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
Source§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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