commonware_storage/qmdb/keyless/sync/
mod.rs1use crate::{
2 Context,
3 journal::{authenticated, contiguous::Mutable},
4 merkle::{
5 Family, Location,
6 full::{self, Merkle},
7 },
8 qmdb::{
9 self,
10 keyless::{CompactDb, Keyless, Metrics, Operation, operation::Codec},
11 sync,
12 },
13};
14use commonware_codec::{EncodeShared, Read};
15use commonware_cryptography::Hasher;
16use commonware_parallel::Strategy;
17use commonware_utils::range::NonEmptyRange;
18use std::num::NonZeroU64;
19
20impl<F, E, V, C, H, S> sync::Database for Keyless<F, E, V, C, H, S>
21where
22 F: Family,
23 E: Context,
24 V: Codec,
25 C: Mutable<Item = Operation<F, V>> + sync::Journal<F, Context = E, Op = Operation<F, V>>,
26 H: Hasher,
27 S: Strategy,
28 Operation<F, V>: EncodeShared,
29{
30 type Family = F;
31 type Op = Operation<F, V>;
32 type Journal = C;
33 type Hasher = H;
34 type Config = super::Config<C::Config, S>;
35 type Digest = H::Digest;
36 type Context = E;
37
38 async fn from_sync_result(
54 context: Self::Context,
55 config: Self::Config,
56 log: Self::Journal,
57 pinned_nodes: Option<Vec<Self::Digest>>,
58 range: NonEmptyRange<Location<F>>,
59 apply_batch_size: NonZeroU64,
60 ) -> Result<Self, qmdb::Error<F>> {
61 let hasher = qmdb::hasher::<H>();
62
63 let merkle = Merkle::<F, _, _, S>::init_sync(
64 context.child("merkle"),
65 full::SyncConfig {
66 config: config.merkle.clone(),
67 range: range.clone(),
68 pinned_nodes,
69 },
70 )
71 .await?;
72
73 let journal = authenticated::Journal::<F, _, _, _, S>::from_components(
74 merkle,
75 log,
76 hasher,
77 apply_batch_size,
78 )
79 .await?;
80
81 let size = journal.size();
82 if size == 0 {
83 return Err(qmdb::Error::HistoricalFloorPruned(size));
84 }
85 let inactivity_floor_loc = qmdb::find_inactivity_floor_at::<F, _>(&journal, size).await?;
86 let inactive_peaks = F::inactive_peaks(size, inactivity_floor_loc);
87 let root = journal.root(inactive_peaks)?;
88
89 let metrics = Metrics::new(context);
90 let db = Self {
91 journal,
92 root,
93 inactivity_floor_loc,
94 metrics,
95 };
96 db.update_metrics();
97
98 db.sync().await
99 }
100
101 async fn persist_sync_result(self) -> Result<Self, qmdb::Error<F>> {
102 Ok(self)
103 }
104
105 async fn local_pinned_nodes(
106 context: Self::Context,
107 config: &Self::Config,
108 target: &sync::Target<F, Self::Digest>,
109 journal: &Self::Journal,
110 ) -> Result<Option<Vec<Self::Digest>>, qmdb::Error<F>> {
111 if target.range.start() == Location::new(0)
112 || !sync::journal_covers_range(journal.bounds(), &target.range)
113 {
114 return Ok(None);
115 }
116
117 let inactivity_floor =
120 qmdb::find_inactivity_floor_at::<F, _>(journal, target.range.end()).await?;
121
122 sync::local_pinned_nodes::<F, _, H, S>(
123 context,
124 config.merkle.clone(),
125 target,
126 inactivity_floor,
127 )
128 .await
129 }
130
131 fn root(&self) -> Self::Digest {
132 self.root()
133 }
134}
135
136impl<F, E, V, H, S> sync::Database for CompactDb<F, E, V, H, S>
137where
138 F: Family,
139 E: Context,
140 V: Codec,
141 H: Hasher,
142 S: Strategy,
143 Operation<F, V>: EncodeShared,
144 Operation<F, V>: Read,
145{
146 type Family = F;
147 type Op = Operation<F, V>;
148 type Journal = sync::journal::Memory<F, E, Operation<F, V>>;
149 type Config = super::CompactConfig<<Operation<F, V> as Read>::Cfg, S>;
150 type Digest = H::Digest;
151 type Context = E;
152 type Hasher = H;
153
154 async fn from_sync_result(
155 context: Self::Context,
156 config: Self::Config,
157 log: Self::Journal,
158 pinned_nodes: Option<Vec<Self::Digest>>,
159 range: NonEmptyRange<Location<F>>,
160 _apply_batch_size: NonZeroU64,
161 ) -> Result<Self, qmdb::Error<F>> {
162 crate::qmdb::compact::from_sync_result(
163 context,
164 config,
165 log,
166 pinned_nodes,
167 range,
168 Self::init_from_sync,
169 )
170 .await
171 }
172
173 async fn persist_sync_result(self) -> Result<Self, qmdb::Error<F>> {
174 self.sync().await
175 }
176
177 async fn local_pinned_nodes(
178 _context: Self::Context,
179 _config: &Self::Config,
180 _target: &sync::Target<F, Self::Digest>,
181 _journal: &Self::Journal,
182 ) -> Result<Option<Vec<Self::Digest>>, qmdb::Error<F>> {
183 Ok(None)
184 }
185
186 fn root(&self) -> Self::Digest {
187 self.root()
188 }
189}
190
191#[cfg(test)]
192mod tests;