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_parallel::Strategy;
25use commonware_utils::Array;
26
27pub type Db<F, E, K, V, H, T, const N: usize, S> = super::db::Db<
28    F,
29    E,
30    Journal<E, Operation<F, K, V>>,
31    K,
32    VariableEncoding<V>,
33    Index<T, Location<F>>,
34    H,
35    N,
36    S,
37>;
38
39impl<
40        F: Graftable,
41        E: Context,
42        K: Array,
43        V: VariableValue,
44        H: Hasher,
45        T: Translator,
46        const N: usize,
47        S: Strategy,
48    > Db<F, E, K, V, H, T, N, S>
49where
50    Operation<F, K, V>: Read,
51{
52    /// Initializes a [Db] from the given `config`.
53    /// The configured [`Strategy`] is used to parallelize merkleization.
54    pub async fn init(
55        context: E,
56        config: Config<T, <Operation<F, K, V> as Read>::Cfg, S>,
57    ) -> Result<Self, Error<F>> {
58        crate::qmdb::current::init(context, config).await
59    }
60}
61
62pub mod partitioned {
63    //! A variant of [super] that uses a partitioned index for the snapshot.
64
65    use super::*;
66    use crate::index::partitioned::unordered::Index;
67
68    /// A partitioned variant of [super::Db].
69    ///
70    /// The const generic `P` specifies the number of prefix bytes used for partitioning:
71    /// - `P = 1`: 256 partitions
72    /// - `P = 2`: 65,536 partitions
73    /// - `P = 3`: ~16 million partitions
74    pub type Db<F, E, K, V, H, T, const P: usize, const N: usize, S> =
75        crate::qmdb::current::unordered::db::Db<
76            F,
77            E,
78            Journal<E, Operation<F, K, V>>,
79            K,
80            VariableEncoding<V>,
81            Index<T, Location<F>, P>,
82            H,
83            N,
84            S,
85        >;
86
87    impl<
88            F: Graftable,
89            E: Context,
90            K: Array,
91            V: VariableValue,
92            H: Hasher,
93            T: Translator,
94            const P: usize,
95            const N: usize,
96            S: Strategy,
97        > Db<F, E, K, V, H, T, P, N, S>
98    where
99        Operation<F, K, V>: Read,
100    {
101        /// Initializes a [Db] from the given `config`.
102        /// The configured [`Strategy`] is used to parallelize merkleization.
103        pub async fn init(
104            context: E,
105            config: Config<T, <Operation<F, K, V> as Read>::Cfg, S>,
106        ) -> Result<Self, Error<F>> {
107            crate::qmdb::current::init(context, config).await
108        }
109    }
110}
111
112#[cfg(test)]
113mod test {
114    use super::*;
115    use crate::{
116        mmr,
117        qmdb::current::{tests::variable_config, unordered::tests as shared},
118        translator::TwoCap,
119    };
120    use commonware_cryptography::{sha256::Digest, Sha256};
121    use commonware_macros::test_traced;
122    use commonware_runtime::deterministic;
123
124    /// A type alias for the concrete [Db] type used in these unit tests.
125    type CurrentTest = Db<
126        mmr::Family,
127        deterministic::Context,
128        Digest,
129        Digest,
130        Sha256,
131        TwoCap,
132        32,
133        commonware_parallel::Sequential,
134    >;
135
136    /// Return a [Db] database initialized with a variable config.
137    async fn open_db(context: deterministic::Context, partition_prefix: String) -> CurrentTest {
138        let cfg = variable_config::<TwoCap>(&partition_prefix, &context);
139        CurrentTest::init(context, cfg).await.unwrap()
140    }
141
142    #[test_traced("DEBUG")]
143    pub fn test_current_db_verify_proof_over_bits_in_uncommitted_chunk() {
144        shared::test_verify_proof_over_bits_in_uncommitted_chunk(open_db);
145    }
146
147    #[test_traced("DEBUG")]
148    pub fn test_current_db_range_proofs() {
149        shared::test_range_proofs(open_db);
150    }
151
152    #[test_traced("DEBUG")]
153    pub fn test_current_db_key_value_proof() {
154        shared::test_key_value_proof(open_db);
155    }
156
157    #[test_traced("WARN")]
158    pub fn test_current_db_proving_repeated_updates() {
159        shared::test_proving_repeated_updates(open_db);
160    }
161}