Skip to main content

commonware_sync/databases/
mod.rs

1//! Database-specific modules for the sync example.
2
3use crate::Key;
4use commonware_codec::Encode;
5use commonware_storage::{
6    merkle::{self, Location, Proof},
7    qmdb::{self, operation::Operation},
8};
9use std::{future::Future, num::NonZeroU64};
10
11pub mod any;
12pub mod current;
13pub mod immutable;
14
15/// Database type to sync.
16#[derive(Debug, Clone, Copy)]
17pub enum DatabaseType {
18    Any,
19    Current,
20    Immutable,
21}
22
23impl std::str::FromStr for DatabaseType {
24    type Err = String;
25
26    fn from_str(s: &str) -> Result<Self, Self::Err> {
27        match s.to_lowercase().as_str() {
28            "any" => Ok(Self::Any),
29            "current" => Ok(Self::Current),
30            "immutable" => Ok(Self::Immutable),
31            _ => Err(format!(
32                "Invalid database type: '{s}'. Must be 'any', 'current', or 'immutable'",
33            )),
34        }
35    }
36}
37
38impl DatabaseType {
39    pub const fn as_str(&self) -> &'static str {
40        match self {
41            Self::Any => "any",
42            Self::Current => "current",
43            Self::Immutable => "immutable",
44        }
45    }
46}
47
48/// Helper trait for databases that can be synced.
49#[allow(clippy::type_complexity)]
50pub trait Syncable: Sized {
51    /// The merkle family used by this database.
52    type Family: merkle::Family;
53
54    /// The type of operations in the database.
55    type Operation: Operation<Self::Family> + Encode + Sync + 'static;
56
57    /// Create test operations with the given count and seed.
58    /// The returned operations must end with a commit operation.
59    fn create_test_operations(count: usize, seed: u64) -> Vec<Self::Operation>;
60
61    /// Add operations to the database, ignoring any input that doesn't end with a commit
62    /// operation.
63    fn add_operations(
64        &mut self,
65        operations: Vec<Self::Operation>,
66    ) -> impl Future<Output = Result<(), qmdb::Error<Self::Family>>>;
67
68    /// Get the database's root digest.
69    fn root(&self) -> Key;
70
71    /// Get the total number of operations in the database (including pruned operations).
72    fn size(&self) -> impl Future<Output = Location<Self::Family>> + Send;
73
74    /// Get the inactivity floor, the location below which all operations are inactive.
75    fn inactivity_floor(&self) -> impl Future<Output = Location<Self::Family>> + Send;
76
77    /// Get historical proof and operations.
78    fn historical_proof(
79        &self,
80        op_count: Location<Self::Family>,
81        start_loc: Location<Self::Family>,
82        max_ops: NonZeroU64,
83    ) -> impl Future<
84        Output = Result<
85            (Proof<Self::Family, Key>, Vec<Self::Operation>),
86            qmdb::Error<Self::Family>,
87        >,
88    > + Send;
89
90    /// Get the pinned nodes for a lower operation boundary of `loc`.
91    fn pinned_nodes_at(
92        &self,
93        loc: Location<Self::Family>,
94    ) -> impl Future<Output = Result<Vec<Key>, qmdb::Error<Self::Family>>> + Send;
95
96    /// Get the database type name for logging.
97    fn name() -> &'static str;
98}