Skip to main content

commonware_sync/databases/
keyless_compact.rs

1//! Compact keyless database types and helpers for compact sync demonstration.
2
3use crate::{Hasher, Key, Value};
4use commonware_parallel::Sequential;
5use commonware_runtime::{buffer::paged::CacheRef, BufferPooler};
6use commonware_storage::{
7    journal::contiguous::variable,
8    merkle::mmr,
9    qmdb::{
10        self,
11        keyless::fixed::{self, CompactConfig},
12        sync::compact,
13    },
14    Context,
15};
16use commonware_utils::{NZUsize, NZU16, NZU64};
17use tracing::error;
18
19/// Database type alias.
20pub type Database<E> = fixed::CompactDb<mmr::Family, E, Value, Hasher, Sequential>;
21
22/// Operation type alias.
23pub type Operation = fixed::Operation<mmr::Family, Value>;
24
25/// Create a database configuration for the compact keyless variant.
26pub fn create_config(context: &impl BufferPooler) -> CompactConfig<Sequential> {
27    CompactConfig {
28        strategy: Sequential,
29        witness: variable::Config {
30            partition: "compact-keyless-witness".into(),
31            items_per_section: NZU64!(4096),
32            compression: None,
33            codec_config: (),
34            page_cache: CacheRef::from_pooler(context, NZU16!(1024), NZUsize!(64)),
35            write_buffer: NZUsize!(1024),
36        },
37        commit_codec_config: (),
38    }
39}
40
41impl<E> super::ExampleDatabase for Database<E>
42where
43    E: Context,
44{
45    type Family = mmr::Family;
46    type Operation = Operation;
47
48    fn create_test_operations(count: usize, seed: u64, starting_loc: u64) -> Vec<Self::Operation> {
49        super::keyless::create_test_operations(count, seed, starting_loc)
50    }
51
52    async fn add_operations(
53        &mut self,
54        operations: Vec<Self::Operation>,
55    ) -> Result<(), qmdb::Error<mmr::Family>> {
56        let Some(last) = operations.last() else {
57            error!("operations must end with a commit");
58            return Ok(());
59        };
60        if !matches!(last, Operation::Commit(..)) {
61            error!("operations must end with a commit");
62            return Ok(());
63        }
64
65        let mut batch = self.new_batch();
66        for operation in operations {
67            match operation {
68                Operation::Append(value) => {
69                    batch = batch.append(value);
70                }
71                Operation::Commit(metadata, floor) => {
72                    let merkleized = batch.merkleize(self, metadata, floor).await;
73                    self.apply_batch(merkleized)?;
74                    self.sync().await?;
75                    batch = self.new_batch();
76                }
77            }
78        }
79        Ok(())
80    }
81
82    fn current_floor(&self) -> u64 {
83        *Self::last_commit_loc(self)
84    }
85
86    fn root(&self) -> Key {
87        Self::root(self)
88    }
89
90    fn name() -> &'static str {
91        "compact keyless"
92    }
93}
94
95impl<E> super::CompactSyncable for Database<E>
96where
97    E: Context,
98{
99    fn target(&self) -> compact::Target<Self::Family, Key> {
100        Self::target(self)
101    }
102}