Skip to main content

commonware_storage/qmdb/current/unordered/
variable.rs

1//! An _unordered_ variant of a [crate::qmdb::current] authenticated database for variable-size
2//! values.
3//!
4//! This variant does not maintain key ordering, so it cannot generate exclusion proofs. Use
5//! [crate::qmdb::current::ordered::variable] if exclusion proofs are required.
6//!
7//! See [Db] for the main database type.
8
9pub use super::db::KeyValueProof;
10use crate::{
11    index::unordered::Index,
12    journal::contiguous::variable::Journal,
13    merkle::{Graftable, Location},
14    qmdb::{
15        any::{unordered::variable::Operation, value::VariableEncoding, VariableValue},
16        current::VariableConfig as Config,
17        Error,
18    },
19    translator::Translator,
20    Context,
21};
22use commonware_codec::Read;
23use commonware_cryptography::Hasher;
24use commonware_utils::Array;
25
26pub type Db<F, E, K, V, H, T, const N: usize> = super::db::Db<
27    F,
28    E,
29    Journal<E, Operation<F, K, V>>,
30    K,
31    VariableEncoding<V>,
32    Index<T, Location<F>>,
33    H,
34    N,
35>;
36
37impl<
38        F: Graftable,
39        E: Context,
40        K: Array,
41        V: VariableValue,
42        H: Hasher,
43        T: Translator,
44        const N: usize,
45    > Db<F, E, K, V, H, T, N>
46where
47    Operation<F, K, V>: Read,
48{
49    /// Initializes a [Db] from the given `config`. Leverages parallel Merkleization to initialize
50    /// the bitmap Merkle tree if a thread pool is provided.
51    pub async fn init(
52        context: E,
53        config: Config<T, <Operation<F, K, V> as Read>::Cfg>,
54    ) -> Result<Self, Error<F>> {
55        crate::qmdb::current::init(context, config).await
56    }
57}
58
59pub mod partitioned {
60    //! A variant of [super] that uses a partitioned index for the snapshot.
61
62    use super::*;
63    use crate::index::partitioned::unordered::Index;
64
65    /// A partitioned variant of [super::Db].
66    ///
67    /// The const generic `P` specifies the number of prefix bytes used for partitioning:
68    /// - `P = 1`: 256 partitions
69    /// - `P = 2`: 65,536 partitions
70    /// - `P = 3`: ~16 million partitions
71    pub type Db<F, E, K, V, H, T, const P: usize, const N: usize> =
72        crate::qmdb::current::unordered::db::Db<
73            F,
74            E,
75            Journal<E, Operation<F, K, V>>,
76            K,
77            VariableEncoding<V>,
78            Index<T, Location<F>, P>,
79            H,
80            N,
81        >;
82
83    impl<
84            F: Graftable,
85            E: Context,
86            K: Array,
87            V: VariableValue,
88            H: Hasher,
89            T: Translator,
90            const P: usize,
91            const N: usize,
92        > Db<F, E, K, V, H, T, P, N>
93    where
94        Operation<F, K, V>: Read,
95    {
96        /// Initializes a [Db] from the given `config`. Leverages parallel Merkleization to initialize
97        /// the bitmap Merkle tree if a thread pool is provided.
98        pub async fn init(
99            context: E,
100            config: Config<T, <Operation<F, K, V> as Read>::Cfg>,
101        ) -> Result<Self, Error<F>> {
102            crate::qmdb::current::init(context, config).await
103        }
104    }
105}
106
107#[cfg(test)]
108mod test {
109    use super::*;
110    use crate::{
111        mmr,
112        qmdb::current::{tests::variable_config, unordered::tests as shared},
113        translator::TwoCap,
114    };
115    use commonware_cryptography::{sha256::Digest, Sha256};
116    use commonware_macros::test_traced;
117    use commonware_runtime::deterministic;
118
119    /// A type alias for the concrete [Db] type used in these unit tests.
120    type CurrentTest = Db<mmr::Family, deterministic::Context, Digest, Digest, Sha256, TwoCap, 32>;
121
122    /// Return a [Db] database initialized with a variable config.
123    async fn open_db(context: deterministic::Context, partition_prefix: String) -> CurrentTest {
124        let cfg = variable_config::<TwoCap>(&partition_prefix, &context);
125        CurrentTest::init(context, cfg).await.unwrap()
126    }
127
128    #[test_traced("DEBUG")]
129    pub fn test_current_db_verify_proof_over_bits_in_uncommitted_chunk() {
130        shared::test_verify_proof_over_bits_in_uncommitted_chunk(open_db);
131    }
132
133    #[test_traced("DEBUG")]
134    pub fn test_current_db_range_proofs() {
135        shared::test_range_proofs(open_db);
136    }
137
138    #[test_traced("DEBUG")]
139    pub fn test_current_db_key_value_proof() {
140        shared::test_key_value_proof(open_db);
141    }
142
143    #[test_traced("WARN")]
144    pub fn test_current_db_proving_repeated_updates() {
145        shared::test_proving_repeated_updates(open_db);
146    }
147}