Skip to main content

commonware_storage/qmdb/current/unordered/
db.rs

1//! Shared implementation for unordered Current QMDB variants.
2//!
3//! This module contains impl blocks that are generic over `ValueEncoding`, allowing them to be
4//! used by both fixed and variable unordered QMDB implementations.
5
6use crate::{
7    index::Unordered as UnorderedIndex,
8    journal::contiguous::{Contiguous, Mutable},
9    merkle::{self, Location},
10    qmdb::{
11        any::{
12            operation::update::Unordered as UnorderedUpdate,
13            unordered::{Operation, Update},
14            ValueEncoding,
15        },
16        current::proof::OperationProof,
17        Error,
18    },
19    Context,
20};
21use commonware_codec::Codec;
22use commonware_cryptography::Hasher;
23use commonware_utils::Array;
24
25/// Proof information for verifying a key has a particular value in the database.
26pub type KeyValueProof<F, D, const N: usize> = OperationProof<F, D, N>;
27
28/// The generic Db type for unordered Current QMDB variants.
29///
30/// This type is generic over the index type `I`, allowing it to be used with both regular
31/// and partitioned indices.
32pub type Db<F, E, C, K, V, I, H, const N: usize> =
33    crate::qmdb::current::db::Db<F, E, C, I, H, Update<K, V>, N>;
34
35// Shared read-only functionality.
36impl<
37        F: merkle::Graftable,
38        E: Context,
39        C: Contiguous<Item = Operation<F, K, V>>,
40        K: Array,
41        V: ValueEncoding,
42        I: UnorderedIndex<Value = Location<F>>,
43        H: Hasher,
44        const N: usize,
45    > Db<F, E, C, K, V, I, H, N>
46where
47    Operation<F, K, V>: Codec,
48{
49    /// Get the value of `key` in the db, or None if it has no value.
50    pub async fn get(&self, key: &K) -> Result<Option<V::Value>, Error<F>> {
51        self.any.get(key).await
52    }
53
54    /// Return true if the proof authenticates that `key` currently has value `value` in the db with
55    /// the provided `root`.
56    pub fn verify_key_value_proof(
57        hasher: &mut H,
58        key: K,
59        value: V::Value,
60        proof: &KeyValueProof<F, H::Digest, N>,
61        root: &H::Digest,
62    ) -> bool {
63        let op = Operation::Update(UnorderedUpdate(key, value));
64
65        proof.verify(hasher, op, root)
66    }
67}
68
69impl<
70        F: merkle::Graftable,
71        E: Context,
72        C: Mutable<Item = Operation<F, K, V>>,
73        K: Array,
74        V: ValueEncoding,
75        I: UnorderedIndex<Value = Location<F>>,
76        H: Hasher,
77        const N: usize,
78    > Db<F, E, C, K, V, I, H, N>
79where
80    Operation<F, K, V>: Codec,
81{
82    /// Generate and return a proof of the current value of `key`, along with the other
83    /// [KeyValueProof] required to verify the proof. Returns KeyNotFound error if the key is not
84    /// currently assigned any value.
85    ///
86    /// # Errors
87    ///
88    /// Returns [Error::KeyNotFound] if the key is not currently assigned any value.
89    pub async fn key_value_proof(
90        &self,
91        hasher: &mut H,
92        key: K,
93    ) -> Result<KeyValueProof<F, H::Digest, N>, Error<F>> {
94        let op_loc = self.any.get_with_loc(&key).await?;
95        let Some((_, loc)) = op_loc else {
96            return Err(Error::<F>::KeyNotFound);
97        };
98        self.operation_proof(hasher, loc).await
99    }
100}