commonware_sync/databases/
immutable.rs1use crate::{Hasher, Key, Translator, Value};
4use commonware_cryptography::{Hasher as CryptoHasher, Sha256};
5use commonware_parallel::Sequential;
6use commonware_runtime::BufferPooler;
7use commonware_storage::{
8 journal::contiguous::fixed::Config as FConfig,
9 merkle::{
10 full::Config as MmrConfig,
11 mmr::{self, Location, Proof},
12 },
13 qmdb::{
14 self,
15 immutable::{fixed, Config},
16 sync::compact,
17 },
18 Context,
19};
20use commonware_utils::{NZUsize, NZU16, NZU64};
21use std::{future::Future, num::NonZeroU64};
22use tracing::error;
23
24pub type Database<E> = fixed::Db<mmr::Family, E, Key, Value, Hasher, Translator, Sequential>;
26
27pub type Operation = fixed::Operation<mmr::Family, Key, Value>;
29
30pub fn create_config(context: &impl BufferPooler) -> Config<Translator, FConfig, Sequential> {
32 let page_cache = commonware_runtime::buffer::paged::CacheRef::from_pooler(
33 context,
34 NZU16!(2048),
35 NZUsize!(10),
36 );
37 Config {
38 merkle_config: MmrConfig {
39 journal_partition: "mmr-journal".into(),
40 metadata_partition: "mmr-metadata".into(),
41 items_per_blob: NZU64!(4096),
42 write_buffer: NZUsize!(4096),
43 strategy: Sequential,
44 page_cache: page_cache.clone(),
45 },
46 log: FConfig {
47 partition: "log".into(),
48 items_per_blob: NZU64!(4096),
49 write_buffer: NZUsize!(4096),
50 page_cache,
51 },
52 translator: commonware_storage::translator::EightCap,
53 init_cache_size: Some(NZUsize!(1 << 16)),
54 }
55}
56
57pub fn create_test_operations(count: usize, seed: u64, starting_loc: u64) -> Vec<Operation> {
63 let mut operations = Vec::new();
64 let mut hasher = <Hasher as CryptoHasher>::new();
65 let floor = Location::new(starting_loc);
66
67 for i in 0..count {
68 let key = {
69 hasher.update(&i.to_be_bytes());
70 hasher.update(&seed.to_be_bytes());
71 hasher.finalize()
72 };
73
74 let value = {
75 hasher.update(&key);
76 hasher.update(b"value");
77 hasher.finalize()
78 };
79
80 operations.push(Operation::Set(key, value));
81
82 if (i + 1) % 10 == 0 {
83 operations.push(Operation::Commit(None, floor));
84 }
85 }
86
87 operations.push(Operation::Commit(Some(Sha256::fill(1)), floor));
89 operations
90}
91
92impl<E> super::ExampleDatabase for Database<E>
93where
94 E: Context,
95{
96 type Family = mmr::Family;
97 type Operation = Operation;
98
99 fn create_test_operations(count: usize, seed: u64, starting_loc: u64) -> Vec<Self::Operation> {
100 create_test_operations(count, seed, starting_loc)
101 }
102
103 async fn add_operations(
104 &mut self,
105 operations: Vec<Self::Operation>,
106 ) -> Result<(), commonware_storage::qmdb::Error<mmr::Family>> {
107 if operations.last().is_none() || !operations.last().unwrap().is_commit() {
108 error!("operations must end with a commit");
110 return Ok(());
111 }
112
113 let mut batch = self.new_batch();
114 for operation in operations {
115 match operation {
116 Operation::Set(key, value) => {
117 batch = batch.set(key, value);
118 }
119 Operation::Commit(metadata, floor) => {
120 let merkleized = batch.merkleize(self, metadata, floor).await;
121 self.apply_batch(merkleized).await?;
122 self.commit().await?;
123 batch = self.new_batch();
124 }
125 }
126 }
127 Ok(())
128 }
129
130 fn current_floor(&self) -> u64 {
131 *self.inactivity_floor_loc()
132 }
133
134 fn root(&self) -> Key {
135 self.root()
136 }
137
138 fn name() -> &'static str {
139 "immutable"
140 }
141}
142
143impl<E> super::Syncable for Database<E>
144where
145 E: Context,
146{
147 fn size(&self) -> Location {
148 self.bounds().end
149 }
150
151 fn sync_boundary(&self) -> Location {
152 self.sync_boundary()
153 }
154
155 fn historical_proof(
156 &self,
157 op_count: Location,
158 start_loc: Location,
159 max_ops: NonZeroU64,
160 ) -> impl Future<Output = Result<(Proof<Key>, Vec<Self::Operation>), qmdb::Error<mmr::Family>>> + Send
161 {
162 self.historical_proof(op_count, start_loc, max_ops)
163 }
164
165 fn pinned_nodes_at(
166 &self,
167 loc: Location,
168 ) -> impl Future<Output = Result<Vec<Key>, qmdb::Error<mmr::Family>>> + Send {
169 self.pinned_nodes_at(loc)
170 }
171}
172
173impl<E> super::CompactSyncable for Database<E>
174where
175 E: Context,
176{
177 fn target(&self) -> compact::Target<Self::Family, Key> {
178 compact::Target::new(self.root(), self.bounds().end)
179 }
180}