Skip to main content

BackendReader

Trait BackendReader 

Source
pub trait BackendReader: Debug {
    // Required methods
    fn open(
        &self,
        lineage: LineageId,
        key: Word,
    ) -> Result<SmtProof, BackendError>;
    fn get_leaf(
        &self,
        lineage: LineageId,
        leaf_index: LeafIndex<miden_crypto::::merkle::smt::large_forest::backend::BackendReader::get_leaf::{constant#0}>,
    ) -> Result<SmtLeaf, BackendError>;
    fn get(
        &self,
        lineage: LineageId,
        key: Word,
    ) -> Result<Option<Word>, BackendError>;
    fn version(&self, lineage: LineageId) -> Result<u64, BackendError>;
    fn lineages(&self) -> Result<impl Iterator<Item = LineageId>, BackendError>;
    fn trees(&self) -> Result<impl Iterator<Item = TreeWithRoot>, BackendError>;
    fn entry_count(&self, lineage: LineageId) -> Result<usize, BackendError>;
    fn entries(
        &self,
        lineage: LineageId,
    ) -> Result<impl Iterator<Item = Result<TreeEntry, BackendError>>, BackendError>;
}
Expand description

The read-only interface for the SMT forest storage backend.

This trait provides the query operations necessary to read the full trees that make up the forest. It is a supertrait of Backend, which extends it with write operations.

§Backend Data Storage

Having a generic BackendReader provides no guarantees to the user about how it stores data and what patterns are used for data access under the hood. It is, however, guaranteed to store only the data necessary to describe the latest state of each tree in the forest.

§Error Handling

We separate errors in backend implementations into two semantic categories:

  1. User-Derived Errors: These are errors that arise downstream of data provided by the user. These errors must be signaled by returning an Err variant with an appropriate error.
  2. Internal Errors: These are errors that are not derived from data provided by the user. Signaling such an error is up to the implementation, but can be done through both panicking and returning the BackendError::Internal variant as appropriate. These may leave the backend in an inconsistent state as they are designed to effect program termination or perform it directly.

The only reason that BackendError::Internal exists is to allow certain failures to result in termination at the level of the forest instead of the backend as this can sometimes lead to cleaner logic. If this is not appropriate, a panic is a better option.

§Expected Behavior

The following behavior is expected of all methods in implementations of this trait:

  • For any failure derived from user input (see User-Derived Errors above), the data and the backend must be left in a consistent state when the error is returned to the caller.
  • Failures derived from user input (see User-Derived Errors above) must be signaled to the caller by returning a variant of BackendError that is not BackendError::Internal. Methods may place additional constraints on which errors are used to signal certain failures. Such failures should not lead to data corruption of any persistent data.

Required Methods§

Source

fn open(&self, lineage: LineageId, key: Word) -> Result<SmtProof, BackendError>

Returns an opening for the specified key in the SMT with the specified lineage.

It is the responsibility of the forest to ensure lineage existence before querying the backend. The backend must return an error if the lineage does not exist.

Source

fn get_leaf( &self, lineage: LineageId, leaf_index: LeafIndex<miden_crypto::::merkle::smt::large_forest::backend::BackendReader::get_leaf::{constant#0}>, ) -> Result<SmtLeaf, BackendError>

Returns the leaf stored at the provided leaf_index in the SMT with the specified lineage. If no leaf is explicitly stored at the given index, the backend must return an empty leaf for that index.

It is the responsibility of the forest to ensure lineage existence before querying the backend. The backend must return an error if the lineage does not exist.

Source

fn get( &self, lineage: LineageId, key: Word, ) -> Result<Option<Word>, BackendError>

Returns the value associated with the provided key in the SMT with the specified lineage, or None if no such value exists.

It is the responsibility of the forest to ensure lineage existence before querying the backend. The backend must return an error if the lineage does not exist.

Source

fn version(&self, lineage: LineageId) -> Result<u64, BackendError>

Returns the version of the tree with the specified lineage.

It is the responsibility of the forest to ensure lineage existence before querying the backend. The backend must return an error if the lineage does not exist.

Source

fn lineages(&self) -> Result<impl Iterator<Item = LineageId>, BackendError>

Returns an iterator over all the lineages that the backend knows about.

The iteration order is unspecified.

Source

fn trees(&self) -> Result<impl Iterator<Item = TreeWithRoot>, BackendError>

Returns an iterator over all the trees (and their corresponding roots) that the backend knows about.

The iteration order is unspecified.

Source

fn entry_count(&self, lineage: LineageId) -> Result<usize, BackendError>

Returns the total number of (key-value) entries in the specified lineage.

It is the responsibility of the forest to ensure lineage existence before querying the backend. The backend must return an error if the lineage does not exist.

§Expected Behavior

Implementations must guarantee the following behavior in addition to the global invariants:

  • This method must be cheap to call, not requiring network or disk I/O to service the result. This usually implies in-memory caching of the data.
  • This method must not return errors other than if the lineage does not exist.
Source

fn entries( &self, lineage: LineageId, ) -> Result<impl Iterator<Item = Result<TreeEntry, BackendError>>, BackendError>

Returns an iterator that yields the populated (key-value) entries for the specified lineage.

It is the responsibility of the forest to ensure lineage existence before querying the backend. The backend must return an error if the lineage does not exist.

The iterator may yield entries in any arbitrary order, but must not yield entries for which the value is the empty word.

§Expected Behavior

Implementations must guarantee the following behavior in addition to the global invariants:

  • If any kind of error occurs during iteration that should be signaled to the user, the iterator must return Some(Err(...)). The caller should stop iteration after receiving an error as the iterator state is no longer valid.
  • None will be returned upon successful completion, or at any time after an error has been returned.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§