pub(crate) mod bitpath;
pub(crate) mod cache;
pub(crate) mod codec;
pub(crate) mod mutation;
pub(crate) mod proof;
pub(crate) mod query;
pub(crate) use bitpath::BitPath;
pub use proof::SmtProof;
use crate::trie::error::{Result, TrieError};
use std::fmt;
pub const TREE_DEPTH: usize = 256;
pub const EMPTY_HASH: [u8; 32] = [0u8; 32];
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum SmtHandle {
InMemory(Box<SmtNode>),
Cached(Vec<u8>, Box<SmtNode>),
}
impl Default for SmtHandle {
fn default() -> Self {
SmtHandle::InMemory(Box::new(SmtNode::Empty))
}
}
impl SmtHandle {
pub fn node(&self) -> &SmtNode {
match self {
SmtHandle::InMemory(n) | SmtHandle::Cached(_, n) => n,
}
}
pub fn into_node(self) -> SmtNode {
match self {
SmtHandle::InMemory(n) | SmtHandle::Cached(_, n) => *n,
}
}
pub fn is_empty(&self) -> bool {
matches!(self.node(), SmtNode::Empty)
}
pub(crate) fn expect_hash(&self) -> Result<&[u8]> {
match self {
SmtHandle::Cached(h, _) => Ok(h),
SmtHandle::InMemory(n) if **n == SmtNode::Empty => Ok(&EMPTY_HASH),
_ => Err(TrieError::InvalidState(
"unhashed non-empty node — call root_hash() first".into(),
)),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Default)]
pub enum SmtNode {
#[default]
Empty,
Leaf {
path: BitPath,
key_hash: [u8; 32],
value: Vec<u8>,
},
Internal {
path: BitPath,
left: SmtHandle,
right: SmtHandle,
},
}
impl fmt::Display for SmtNode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SmtNode::Empty => write!(f, "Empty"),
SmtNode::Leaf { path, .. } => write!(f, "Leaf({}bits)", path.len()),
SmtNode::Internal { path, .. } => {
write!(f, "Internal({}bits)", path.len())
}
}
}
}