pub mod batch;
#[cfg(test)]
pub(crate) mod conformance;
pub mod hasher;
#[cfg(feature = "std")]
pub mod journaled;
mod location;
pub mod mem;
pub mod mmb;
pub mod mmr;
pub(super) mod path;
mod position;
mod proof;
mod read;
#[cfg(feature = "std")]
pub mod storage;
#[cfg(feature = "std")]
pub mod verification;
use alloc::vec::Vec;
use core::fmt::Debug;
pub use location::{Location, LocationRangeExt};
pub use position::Position;
pub use proof::Proof;
pub use read::Readable;
use thiserror::Error;
pub trait Family: Copy + Clone + Debug + Default + Send + Sync + 'static {
const MAX_NODES: Position<Self>;
const MAX_LEAVES: Location<Self>;
fn location_to_position(loc: Location<Self>) -> Position<Self>;
fn position_to_location(pos: Position<Self>) -> Option<Location<Self>>;
fn is_valid_size(size: Position<Self>) -> bool;
fn to_nearest_size(size: Position<Self>) -> Position<Self>;
fn peaks(size: Position<Self>) -> impl Iterator<Item = (Position<Self>, u32)>;
fn nodes_to_pin(prune_loc: Location<Self>) -> impl Iterator<Item = Position<Self>> + Send {
let prune_pos = Self::location_to_position(prune_loc);
Self::peaks(prune_pos)
.filter(move |&(pos, _)| pos < prune_pos)
.map(|(pos, _)| pos)
.collect::<Vec<_>>()
.into_iter()
}
fn children(pos: Position<Self>, height: u32) -> (Position<Self>, Position<Self>);
fn parent_heights(leaves: Location<Self>) -> impl Iterator<Item = u32>;
fn pos_to_height(pos: Position<Self>) -> u32;
}
pub trait Graftable: Family {
fn chunk_peaks(
size: Position<Self>,
chunk_idx: u64,
grafting_height: u32,
) -> impl Iterator<Item = (Position<Self>, u32)> + Send;
fn subtree_root_position(leaf_start: Location<Self>, height: u32) -> Position<Self>;
fn leftmost_leaf(pos: Position<Self>, height: u32) -> Location<Self>;
}
#[derive(Debug, Error)]
pub enum Error<F: Family> {
#[error("{0} is not a leaf")]
NonLeaf(Position<F>),
#[error("{0} > MAX_NODES")]
PositionOverflow(Position<F>),
#[error("{0} > MAX_LEAVES")]
LocationOverflow(Location<F>),
#[error("range is empty")]
Empty,
#[error("range end out of bounds: {0}")]
RangeOutOfBounds(Location<F>),
#[error("invalid size: {0}")]
InvalidSize(u64),
#[error("leaf location out of bounds: {0}")]
LeafOutOfBounds(Location<F>),
#[error("element pruned: {0}")]
ElementPruned(Position<F>),
#[error("invalid pinned nodes")]
InvalidPinnedNodes,
#[error("stale batch: base size {expected}, current size {actual}")]
StaleBatch {
expected: Position<F>,
actual: Position<F>,
},
#[error("ancestor dropped: expected size {expected}, actual size {actual}")]
AncestorDropped {
expected: Position<F>,
actual: Position<F>,
},
#[error("invalid proof")]
InvalidProof,
#[error("root mismatch")]
RootMismatch,
#[error("missing digest: {0}")]
MissingDigest(Position<F>),
#[cfg(feature = "std")]
#[error("metadata error: {0}")]
Metadata(#[from] crate::metadata::Error),
#[cfg(feature = "std")]
#[error("journal error: {0}")]
Journal(#[from] crate::journal::Error),
#[cfg(feature = "std")]
#[error("runtime error: {0}")]
Runtime(#[from] commonware_runtime::Error),
#[error("missing node: {0}")]
MissingNode(Position<F>),
#[error("data corrupted: {0}")]
DataCorrupted(&'static str),
#[error("missing grafted leaf digest: {0}")]
MissingGraftedLeaf(Position<F>),
#[error("bit offset {0} out of bounds (size: {1})")]
BitOutOfBounds(u64, u64),
}