Skip to main content

commonware_storage/qmdb/compact/
mod.rs

1//! Shared compact QMDB helpers.
2
3pub(crate) mod batch;
4pub(crate) mod witness;
5
6use crate::{
7    Context,
8    journal::contiguous::variable,
9    merkle::{Family, Location},
10    qmdb::{Error, sync::journal::Memory},
11};
12use commonware_cryptography::Digest;
13use commonware_parallel::Strategy;
14use commonware_utils::range::NonEmptyRange;
15
16/// Configuration for a compact authenticated db.
17#[derive(Clone)]
18pub struct Config<C, S: Strategy> {
19    /// Strategy used to parallelize merkleization.
20    pub strategy: S,
21
22    /// Configuration for the journal that persists the witness.
23    pub witness: variable::Config<()>,
24
25    /// Codec config used to decode the persisted last commit operation on reopen.
26    pub commit_codec_config: C,
27}
28
29/// Build a compact db from state fetched by the sync engine.
30/// Returns [`Error::UnexpectedData`] if the log has more than the commit operation.
31pub(crate) async fn from_sync_result<E, F, D, C, S, Op, DB>(
32    context: E,
33    config: Config<C, S>,
34    log: Memory<F, E, Op>,
35    pinned_nodes: Option<Vec<D>>,
36    range: NonEmptyRange<Location<F>>,
37    init: impl FnOnce(S, witness::Journal<E, F, D>, C, Location<F>, Vec<D>, Op) -> Result<DB, Error<F>>,
38) -> Result<DB, Error<F>>
39where
40    E: Context,
41    F: Family,
42    D: Digest,
43    S: Strategy,
44{
45    let last_commit_loc = range.start();
46    let (start, ops) = log.into_parts();
47    let (Ok([op]), true) = (<[Op; 1]>::try_from(ops), start == last_commit_loc) else {
48        return Err(Error::UnexpectedData(last_commit_loc));
49    };
50
51    let journal = variable::Journal::init(context.child("witness"), config.witness).await?;
52    init(
53        config.strategy,
54        journal,
55        config.commit_codec_config,
56        last_commit_loc,
57        // None only happens at genesis, where nothing is pinned.
58        pinned_nodes.unwrap_or_default(),
59        op,
60    )
61}