commonware_sync/databases/
immutable.rs

1//! Immutable database types and helpers for the sync example.
2
3use crate::{Hasher, Key, Translator, Value};
4use commonware_cryptography::{Hasher as CryptoHasher, Sha256};
5use commonware_runtime::{Clock, Metrics, Storage};
6use commonware_storage::{
7    mmr::{Location, Proof},
8    qmdb::{
9        self,
10        immutable::{self, Config},
11    },
12};
13use commonware_utils::{NZUsize, NZU64};
14use std::{future::Future, num::NonZeroU64};
15
16/// Database type alias.
17pub type Database<E> = immutable::Immutable<E, Key, Value, Hasher, Translator>;
18
19/// Operation type alias.
20pub type Operation = immutable::Operation<Key, Value>;
21
22/// Create a database configuration with appropriate partitioning for Immutable.
23pub fn create_config() -> Config<Translator, ()> {
24    Config {
25        mmr_journal_partition: "mmr_journal".into(),
26        mmr_metadata_partition: "mmr_metadata".into(),
27        mmr_items_per_blob: NZU64!(4096),
28        mmr_write_buffer: NZUsize!(1024),
29        log_partition: "log".into(),
30        log_items_per_section: NZU64!(512),
31        log_compression: None,
32        log_codec_config: (),
33        log_write_buffer: NZUsize!(1024),
34        translator: commonware_storage::translator::EightCap,
35        thread_pool: None,
36        buffer_pool: commonware_runtime::buffer::PoolRef::new(NZUsize!(1024), NZUsize!(10)),
37    }
38}
39
40/// Create deterministic test operations for demonstration purposes.
41/// Generates Set operations and periodic Commit operations.
42pub fn create_test_operations(count: usize, seed: u64) -> Vec<Operation> {
43    let mut operations = Vec::new();
44    let mut hasher = <Hasher as CryptoHasher>::new();
45
46    for i in 0..count {
47        let key = {
48            hasher.update(&i.to_be_bytes());
49            hasher.update(&seed.to_be_bytes());
50            hasher.finalize()
51        };
52
53        let value = {
54            hasher.update(&key);
55            hasher.update(b"value");
56            hasher.finalize()
57        };
58
59        operations.push(Operation::Set(key, value));
60
61        if (i + 1) % 10 == 0 {
62            operations.push(Operation::Commit(None));
63        }
64    }
65
66    // Always end with a commit
67    operations.push(Operation::Commit(Some(Sha256::fill(1))));
68    operations
69}
70
71impl<E> super::Syncable for Database<E>
72where
73    E: Storage + Clock + Metrics,
74{
75    type Operation = Operation;
76
77    fn create_test_operations(count: usize, seed: u64) -> Vec<Self::Operation> {
78        create_test_operations(count, seed)
79    }
80
81    async fn add_operations(
82        database: &mut Self,
83        operations: Vec<Self::Operation>,
84    ) -> Result<(), commonware_storage::qmdb::Error> {
85        for operation in operations {
86            match operation {
87                Operation::Set(key, value) => {
88                    database.set(key, value).await?;
89                }
90                Operation::Commit(metadata) => {
91                    database.commit(metadata).await?;
92                }
93            }
94        }
95        Ok(())
96    }
97
98    async fn commit(&mut self) -> Result<(), commonware_storage::qmdb::Error> {
99        self.commit(None).await
100    }
101
102    fn root(&self) -> Key {
103        self.root()
104    }
105
106    fn op_count(&self) -> Location {
107        self.op_count()
108    }
109
110    fn lower_bound(&self) -> Location {
111        self.oldest_retained_loc()
112    }
113
114    fn historical_proof(
115        &self,
116        op_count: Location,
117        start_loc: Location,
118        max_ops: NonZeroU64,
119    ) -> impl Future<Output = Result<(Proof<Key>, Vec<Self::Operation>), qmdb::Error>> + Send {
120        self.historical_proof(op_count, start_loc, max_ops)
121    }
122
123    fn name() -> &'static str {
124        "immutable"
125    }
126}