pub mod memory;
#[cfg(feature = "persistent-forest")]
pub mod persistent;
use alloc::{boxed::Box, string::String, vec::Vec};
use core::fmt::Debug;
use thiserror::Error;
use crate::{
Word,
merkle::{
MerkleError,
smt::{
LeafIndex, SMT_DEPTH, SmtLeaf, SmtProof,
large_forest::{
operation::SmtForestUpdateBatch,
root::{LineageId, TreeEntry, TreeWithRoot, VersionId},
utils::{AppliedLineageMutation, LineageMutation},
},
},
},
};
pub trait BackendReader
where
Self: Debug,
{
fn open(&self, lineage: LineageId, key: Word) -> Result<SmtProof>;
fn get_leaf(&self, lineage: LineageId, leaf_index: LeafIndex<SMT_DEPTH>) -> Result<SmtLeaf>;
fn get(&self, lineage: LineageId, key: Word) -> Result<Option<Word>>;
fn version(&self, lineage: LineageId) -> Result<VersionId>;
fn lineages(&self) -> Result<impl Iterator<Item = LineageId>>;
fn trees(&self) -> Result<impl Iterator<Item = TreeWithRoot>>;
fn entry_count(&self, lineage: LineageId) -> Result<usize>;
fn entries(&self, lineage: LineageId) -> Result<impl Iterator<Item = Result<TreeEntry>>>;
}
pub trait Backend: BackendReader {
type Reader: BackendReader;
type PreparedMutations;
fn reader(&self) -> Result<Self::Reader>;
fn compute_mutations(
&self,
new_version: VersionId,
updates: SmtForestUpdateBatch,
) -> Result<(Vec<LineageMutation>, Self::PreparedMutations)>;
fn apply_mutations(
&mut self,
mutations: Self::PreparedMutations,
) -> Result<Vec<AppliedLineageMutation>>;
}
#[derive(Debug, Error)]
pub enum BackendError {
#[error("Version {provided} is not current backend version {latest}")]
BadVersion { provided: VersionId, latest: VersionId },
#[error("Backend data corruption encountered: {0}")]
CorruptedData(String),
#[error("Duplicate lineage ID {0} provided")]
DuplicateLineage(LineageId),
#[error(transparent)]
Internal(Box<dyn core::error::Error + Sync + Send>),
#[error(transparent)]
Merkle(#[from] MerkleError),
#[error(transparent)]
Other(Box<dyn core::error::Error + Sync + Send>),
#[error("Lineage {0} is not known by the backend")]
UnknownLineage(LineageId),
#[error("Unspecified error: {0}")]
Unspecified(String),
}
impl BackendError {
fn internal_from<E: core::error::Error + Sync + Send + 'static>(e: E) -> Self {
Self::Internal(Box::new(e))
}
#[cfg(feature = "persistent-forest")]
fn internal_from_message(message: impl Into<String>) -> Self {
Self::internal_from(Self::Unspecified(message.into()))
}
}
pub type Result<T> = core::result::Result<T, BackendError>;