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