1use crate::{
7 index::unordered::Index,
8 journal::contiguous::{Contiguous, MutableContiguous},
9 kv::{self, Batchable},
10 mmr::Location,
11 qmdb::{
12 any::{
13 operation::update::Unordered as UnorderedUpdate,
14 unordered::{Operation, Update},
15 ValueEncoding,
16 },
17 current::{
18 db::{Merkleized, State, Unmerkleized},
19 proof::OperationProof,
20 },
21 store, DurabilityState, Durable, Error, NonDurable,
22 },
23 translator::Translator,
24};
25use commonware_codec::Codec;
26use commonware_cryptography::{DigestOf, Hasher};
27use commonware_runtime::{Clock, Metrics, Storage};
28use commonware_utils::Array;
29
30pub type KeyValueProof<D, const N: usize> = OperationProof<D, N>;
32
33pub type Db<E, C, K, V, H, T, const N: usize, S = Merkleized<DigestOf<H>>, D = Durable> =
35 super::super::db::Db<E, C, Index<T, Location>, H, Update<K, V>, N, S, D>;
36
37impl<
39 E: Storage + Clock + Metrics,
40 C: Contiguous<Item = Operation<K, V>>,
41 K: Array,
42 V: ValueEncoding,
43 H: Hasher,
44 T: Translator,
45 const N: usize,
46 S: State<DigestOf<H>>,
47 D: DurabilityState,
48 > Db<E, C, K, V, H, T, N, S, D>
49where
50 Operation<K, V>: Codec,
51 V::Value: Send + Sync,
52{
53 pub async fn get(&self, key: &K) -> Result<Option<V::Value>, Error> {
55 self.any.get(key).await
56 }
57
58 pub fn verify_key_value_proof(
61 hasher: &mut H,
62 key: K,
63 value: V::Value,
64 proof: &KeyValueProof<H::Digest, N>,
65 root: &H::Digest,
66 ) -> bool {
67 let op = Operation::Update(UnorderedUpdate(key, value));
68
69 proof.verify(hasher, Self::grafting_height(), op, root)
70 }
71}
72
73impl<
75 E: Storage + Clock + Metrics,
76 C: MutableContiguous<Item = Operation<K, V>>,
77 K: Array,
78 V: ValueEncoding,
79 H: Hasher,
80 T: Translator,
81 const N: usize,
82 D: store::State,
83 > Db<E, C, K, V, H, T, N, Merkleized<DigestOf<H>>, D>
84where
85 Operation<K, V>: Codec,
86 V::Value: Send + Sync,
87{
88 pub async fn key_value_proof(
96 &self,
97 hasher: &mut H,
98 key: K,
99 ) -> Result<KeyValueProof<H::Digest, N>, Error> {
100 let op_loc = self.any.get_with_loc(&key).await?;
101 let Some((_, loc)) = op_loc else {
102 return Err(Error::KeyNotFound);
103 };
104 let height = Self::grafting_height();
105 let mmr = &self.any.log.mmr;
106
107 OperationProof::<H::Digest, N>::new(hasher, &self.status, height, mmr, loc).await
108 }
109}
110
111impl<
113 E: Storage + Clock + Metrics,
114 C: MutableContiguous<Item = Operation<K, V>>,
115 K: Array,
116 V: ValueEncoding,
117 H: Hasher,
118 T: Translator,
119 const N: usize,
120 > Db<E, C, K, V, H, T, N, Unmerkleized, NonDurable>
121where
122 Operation<K, V>: Codec,
123 V::Value: Send + Sync,
124{
125 pub async fn update(&mut self, key: K, value: V::Value) -> Result<(), Error> {
128 if let Some(old_loc) = self.any.update_key(key, value).await? {
129 self.status.set_bit(*old_loc, false);
130 }
131 self.status.push(true);
132
133 Ok(())
134 }
135
136 pub async fn create(&mut self, key: K, value: V::Value) -> Result<bool, Error> {
140 if !self.any.create(key, value).await? {
141 return Ok(false);
142 }
143 self.status.push(true);
144
145 Ok(true)
146 }
147
148 pub async fn delete(&mut self, key: K) -> Result<bool, Error> {
152 let Some(loc) = self.any.delete_key(key).await? else {
153 return Ok(false);
154 };
155
156 self.status.push(false);
157 self.status.set_bit(*loc, false);
158
159 Ok(true)
160 }
161}
162
163impl<
165 E: Storage + Clock + Metrics,
166 C: Contiguous<Item = Operation<K, V>>,
167 K: Array,
168 V: ValueEncoding,
169 H: Hasher,
170 T: Translator,
171 const N: usize,
172 S: State<DigestOf<H>>,
173 D: DurabilityState,
174 > kv::Gettable for Db<E, C, K, V, H, T, N, S, D>
175where
176 Operation<K, V>: Codec,
177 V::Value: Send + Sync,
178{
179 type Key = K;
180 type Value = V::Value;
181 type Error = Error;
182
183 async fn get(&self, key: &Self::Key) -> Result<Option<Self::Value>, Self::Error> {
184 self.get(key).await
185 }
186}
187
188impl<
190 E: Storage + Clock + Metrics,
191 C: MutableContiguous<Item = Operation<K, V>>,
192 K: Array,
193 V: ValueEncoding,
194 H: Hasher,
195 T: Translator,
196 const N: usize,
197 > kv::Updatable for Db<E, C, K, V, H, T, N, Unmerkleized, NonDurable>
198where
199 Operation<K, V>: Codec,
200 V::Value: Send + Sync,
201{
202 async fn update(&mut self, key: Self::Key, value: Self::Value) -> Result<(), Self::Error> {
203 self.update(key, value).await
204 }
205}
206
207impl<
209 E: Storage + Clock + Metrics,
210 C: MutableContiguous<Item = Operation<K, V>>,
211 K: Array,
212 V: ValueEncoding,
213 H: Hasher,
214 T: Translator,
215 const N: usize,
216 > kv::Deletable for Db<E, C, K, V, H, T, N, Unmerkleized, NonDurable>
217where
218 Operation<K, V>: Codec,
219 V::Value: Send + Sync,
220{
221 async fn delete(&mut self, key: Self::Key) -> Result<bool, Self::Error> {
222 self.delete(key).await
223 }
224}
225
226impl<E, C, K, V, T, H, const N: usize> Batchable
228 for Db<E, C, K, V, H, T, N, Unmerkleized, NonDurable>
229where
230 E: Storage + Clock + Metrics,
231 C: MutableContiguous<Item = Operation<K, V>>,
232 K: Array,
233 V: ValueEncoding,
234 T: Translator,
235 H: Hasher,
236 Operation<K, V>: Codec,
237 V::Value: Send + Sync,
238{
239 async fn write_batch<'a, Iter>(&'a mut self, iter: Iter) -> Result<(), Error>
240 where
241 Iter: Iterator<Item = (K, Option<V::Value>)> + Send + 'a,
242 {
243 let status = &mut self.status;
244 self.any
245 .write_batch_with_callback(iter, move |append: bool, loc: Option<Location>| {
246 status.push(append);
247 if let Some(loc) = loc {
248 status.set_bit(*loc, false);
249 }
250 })
251 .await
252 }
253}