commonware_sync/databases/
any.rs1use crate::{Hasher, Key, Translator, Value};
4use commonware_cryptography::Hasher as CryptoHasher;
5use commonware_runtime::{buffer, Clock, Metrics, Storage};
6use commonware_storage::{
7 adb::{
8 self,
9 any::fixed::{unordered::Any, Config},
10 operation,
11 },
12 mmr::{Location, Proof, StandardHasher as Standard},
13};
14use commonware_utils::{NZUsize, NZU64};
15use std::{future::Future, num::NonZeroU64};
16
17pub type Database<E> = Any<E, Key, Value, Hasher, Translator>;
19
20pub type Operation = operation::fixed::unordered::Operation<Key, Value>;
22
23pub fn create_config() -> Config<Translator> {
25 Config {
26 mmr_journal_partition: "mmr_journal".into(),
27 mmr_metadata_partition: "mmr_metadata".into(),
28 mmr_items_per_blob: NZU64!(4096),
29 mmr_write_buffer: NZUsize!(1024),
30 log_journal_partition: "log_journal".into(),
31 log_items_per_blob: NZU64!(4096),
32 log_write_buffer: NZUsize!(1024),
33 translator: Translator::default(),
34 thread_pool: None,
35 buffer_pool: buffer::PoolRef::new(NZUsize!(1024), NZUsize!(10)),
36 }
37}
38
39impl<E> crate::databases::Syncable for Database<E>
40where
41 E: Storage + Clock + Metrics,
42{
43 type Operation = Operation;
44
45 fn create_test_operations(count: usize, seed: u64) -> Vec<Self::Operation> {
46 let mut hasher = <Hasher as CryptoHasher>::new();
47 let mut operations = Vec::new();
48 for i in 0..count {
49 let key = {
50 hasher.update(&i.to_be_bytes());
51 hasher.update(&seed.to_be_bytes());
52 hasher.finalize()
53 };
54
55 let value = {
56 hasher.update(&key);
57 hasher.update(b"value");
58 hasher.finalize()
59 };
60
61 operations.push(Operation::Update(key, value));
62
63 if (i + 1) % 10 == 0 {
64 operations.push(Operation::CommitFloor(Location::from(i + 1)));
65 }
66 }
67
68 operations.push(Operation::CommitFloor(Location::from(count)));
70 operations
71 }
72
73 async fn add_operations(
74 database: &mut Self,
75 operations: Vec<Self::Operation>,
76 ) -> Result<(), commonware_storage::adb::Error> {
77 for operation in operations {
78 match operation {
79 Operation::Update(key, value) => {
80 database.update(key, value).await?;
81 }
82 Operation::Delete(key) => {
83 database.delete(key).await?;
84 }
85 Operation::CommitFloor(_) => {
86 database.commit().await?;
87 }
88 }
89 }
90 Ok(())
91 }
92
93 async fn commit(&mut self) -> Result<(), commonware_storage::adb::Error> {
94 self.commit().await
95 }
96
97 fn root(&self, hasher: &mut Standard<commonware_cryptography::Sha256>) -> Key {
98 self.root(hasher)
99 }
100
101 fn op_count(&self) -> Location {
102 self.op_count()
103 }
104
105 fn lower_bound(&self) -> Location {
106 self.inactivity_floor_loc()
107 }
108
109 fn historical_proof(
110 &self,
111 op_count: Location,
112 start_loc: Location,
113 max_ops: NonZeroU64,
114 ) -> impl Future<Output = Result<(Proof<Key>, Vec<Self::Operation>), adb::Error>> + Send {
115 self.historical_proof(op_count, start_loc, max_ops)
116 }
117
118 fn name() -> &'static str {
119 "any"
120 }
121}
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126 use crate::databases::Syncable;
127 use commonware_runtime::deterministic;
128
129 type AnyDb = Database<deterministic::Context>;
130
131 #[test]
132 fn test_create_test_operations() {
133 let ops = <AnyDb as Syncable>::create_test_operations(5, 12345);
134 assert_eq!(ops.len(), 6); if let Operation::CommitFloor(loc) = &ops[5] {
137 assert_eq!(*loc, 5);
138 } else {
139 panic!("Last operation should be a commit");
140 }
141 }
142
143 #[test]
144 fn test_deterministic_operations() {
145 let ops1 = <AnyDb as Syncable>::create_test_operations(3, 12345);
147 let ops2 = <AnyDb as Syncable>::create_test_operations(3, 12345);
148 assert_eq!(ops1, ops2);
149
150 let ops3 = <AnyDb as Syncable>::create_test_operations(3, 54321);
152 assert_ne!(ops1, ops3);
153 }
154}