commonware_sync/databases/
immutable.rs1use crate::{Hasher, Key, Translator, Value};
4use commonware_cryptography::{Hasher as CryptoHasher, Sha256};
5use commonware_runtime::{BufferPooler, Clock, Metrics, Storage};
6use commonware_storage::{
7 mmr::{Location, Proof},
8 qmdb::{
9 self,
10 immutable::{self, Config},
11 store::LogStore,
12 },
13};
14use commonware_utils::{NZUsize, NZU16, NZU64};
15use std::{future::Future, num::NonZeroU64};
16use tracing::error;
17
18pub type Database<E> = immutable::Immutable<E, Key, Value, Hasher, Translator>;
20
21pub type Operation = immutable::Operation<Key, Value>;
23
24pub fn create_config(context: &impl BufferPooler) -> Config<Translator, ()> {
26 Config {
27 mmr_journal_partition: "mmr-journal".into(),
28 mmr_metadata_partition: "mmr-metadata".into(),
29 mmr_items_per_blob: NZU64!(4096),
30 mmr_write_buffer: NZUsize!(4096),
31 log_partition: "log".into(),
32 log_items_per_section: NZU64!(4096),
33 log_compression: None,
34 log_codec_config: (),
35 log_write_buffer: NZUsize!(4096),
36 translator: commonware_storage::translator::EightCap,
37 thread_pool: None,
38 page_cache: commonware_runtime::buffer::paged::CacheRef::from_pooler(
39 context,
40 NZU16!(2048),
41 NZUsize!(10),
42 ),
43 }
44}
45
46pub fn create_test_operations(count: usize, seed: u64) -> Vec<Operation> {
49 let mut operations = Vec::new();
50 let mut hasher = <Hasher as CryptoHasher>::new();
51
52 for i in 0..count {
53 let key = {
54 hasher.update(&i.to_be_bytes());
55 hasher.update(&seed.to_be_bytes());
56 hasher.finalize()
57 };
58
59 let value = {
60 hasher.update(&key);
61 hasher.update(b"value");
62 hasher.finalize()
63 };
64
65 operations.push(Operation::Set(key, value));
66
67 if (i + 1) % 10 == 0 {
68 operations.push(Operation::Commit(None));
69 }
70 }
71
72 operations.push(Operation::Commit(Some(Sha256::fill(1))));
74 operations
75}
76
77impl<E> super::Syncable for Database<E>
78where
79 E: Storage + Clock + Metrics,
80{
81 type Operation = Operation;
82
83 fn create_test_operations(count: usize, seed: u64) -> Vec<Self::Operation> {
84 create_test_operations(count, seed)
85 }
86
87 async fn add_operations(
88 &mut self,
89 operations: Vec<Self::Operation>,
90 ) -> Result<(), commonware_storage::qmdb::Error> {
91 if operations.last().is_none() || !operations.last().unwrap().is_commit() {
92 error!("operations must end with a commit");
94 return Ok(());
95 }
96
97 let mut batch = self.new_batch();
98 for operation in operations {
99 match operation {
100 Operation::Set(key, value) => {
101 batch.set(key, value);
102 }
103 Operation::Commit(metadata) => {
104 let finalized = batch.merkleize(metadata).finalize();
105 self.apply_batch(finalized).await?;
106 batch = self.new_batch();
107 }
108 }
109 }
110 Ok(())
111 }
112
113 fn root(&self) -> Key {
114 self.root()
115 }
116
117 async fn size(&self) -> Location {
118 LogStore::bounds(self).await.end
119 }
120
121 async fn inactivity_floor(&self) -> Location {
122 LogStore::bounds(self).await.start
125 }
126
127 fn historical_proof(
128 &self,
129 op_count: Location,
130 start_loc: Location,
131 max_ops: NonZeroU64,
132 ) -> impl Future<Output = Result<(Proof<Key>, Vec<Self::Operation>), qmdb::Error>> + Send {
133 self.historical_proof(op_count, start_loc, max_ops)
134 }
135
136 fn name() -> &'static str {
137 "immutable"
138 }
139}