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