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