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