//! Shared read-only trait for merkleized data structures. use crate::merkle::{hasher::Hasher, proof::Proof, Family, Location, Position}; use alloc::sync::Arc; use commonware_cryptography::Digest; use core::ops::Range; /// Read-only interface for a merkleized data structure. pub trait Readable: Send + Sync { /// The Merkle family implemented by this structure. type Family: Family; /// The digest type used by this structure. type Digest: Digest; /// The error type returned by proof construction. type Error; /// Total number of nodes (retained + pruned). fn size(&self) -> Position; /// Digest of the node at `pos`, or `None` if pruned / out of bounds. fn get_node(&self, pos: Position) -> Option; /// Root digest of the structure. fn root(&self) -> Self::Digest; /// Leaf location up to which pruning has been performed, or 0 if never pruned. fn pruning_boundary(&self) -> Location; /// Inclusion proof for the element at `loc`. fn proof( &self, hasher: &impl Hasher, loc: Location, ) -> Result, Self::Error>; /// Inclusion proof for all elements in `range`. fn range_proof( &self, hasher: &impl Hasher, range: Range>, ) -> Result, Self::Error>; /// Total number of leaves. fn leaves(&self) -> Location { Location::try_from(self.size()).expect("invalid merkle size") } /// `[start, end)` range of retained leaf locations. fn bounds(&self) -> Range> { self.pruning_boundary()..self.leaves() } } impl Readable for Arc { type Family = T::Family; type Digest = T::Digest; type Error = T::Error; fn size(&self) -> Position { (**self).size() } fn get_node(&self, pos: Position) -> Option { (**self).get_node(pos) } fn root(&self) -> Self::Digest { (**self).root() } fn pruning_boundary(&self) -> Location { (**self).pruning_boundary() } fn proof( &self, hasher: &impl Hasher, loc: Location, ) -> Result, Self::Error> { (**self).proof(hasher, loc) } fn range_proof( &self, hasher: &impl Hasher, range: Range>, ) -> Result, Self::Error> { (**self).range_proof(hasher, range) } }