//! An _ordered_ variant of a [crate::qmdb::current] authenticated database for variable-size values //! //! This variant maintains the lexicographic-next active key for each active key, enabling exclusion //! proofs (proving a key is currently inactive). Use [crate::qmdb::current::unordered::variable] if //! exclusion proofs are not needed. //! //! See [Db] for the main database type and //! [ExclusionProof](super::proof::constant::ExclusionProof) for proving key inactivity. use crate::{ Context, index::ordered::Index, journal::contiguous::variable::Journal, merkle::{Graftable, Location}, qmdb::{ Error, any::{VariableValue, ordered::variable::Operation, value::VariableEncoding}, current::VariableConfig as Config, operation::Key, }, translator::OrderedTranslator, }; use commonware_codec::Read; use commonware_cryptography::Hasher; use commonware_parallel::Strategy; use commonware_runtime::Spawner; pub type Db = super::db::Db< F, E, Journal>, K, VariableEncoding, Index>, H, N, S, >; impl< F: Graftable, E: Context + Spawner, K: Key, V: VariableValue, H: Hasher, T: OrderedTranslator, const N: usize, S: Strategy, > Db { /// Initializes a [Db] from the given `config`. /// The configured [`Strategy`] is used to parallelize merkleization. /// `Some(max_size)` selects the latest retained commit with at most `max_size` operations, /// while `None` selects the latest retained state. Initialization fails with /// [Error::HistoricalFloorPruned] if the log or bitmap has pruned the commit's inactivity floor, /// and with [Error::Journal] ([`crate::journal::Error::ItemPruned`]) if the selected commit /// itself has been pruned. pub async fn init( context: E, config: Config as Read>::Cfg, S>, max_size: Option>, ) -> Result> { crate::qmdb::current::init(context, config, max_size).await } } pub mod partitioned { //! A variant of [super] that uses a partitioned index for the snapshot. use super::*; use crate::index::partitioned::ordered::Index; /// A partitioned variant of [super::Db]. /// /// The const generic `P` specifies the number of prefix bytes used for partitioning: /// - `P = 1`: 256 partitions /// - `P = 2`: 65,536 partitions /// - `P = 3`: ~16 million partitions pub type Db = crate::qmdb::current::ordered::db::Db< F, E, Journal>, K, VariableEncoding, Index, P>, H, N, S, >; impl< F: Graftable, E: Context + Spawner, K: Key, V: VariableValue, H: Hasher, T: OrderedTranslator, const P: usize, const N: usize, S: Strategy, > Db { /// Initializes a [Db] from the given `config`. /// `Some(max_size)` selects the latest retained commit with at most `max_size` operations, /// while `None` selects the latest retained state. Initialization fails with /// [Error::HistoricalFloorPruned] if the log or bitmap has pruned the commit's inactivity /// floor, and with [Error::Journal] ([`crate::journal::Error::ItemPruned`]) if the selected /// commit itself has been pruned. pub async fn init( context: E, config: Config as Read>::Cfg, S, core::num::NonZeroUsize>, max_size: Option>, ) -> Result> { crate::qmdb::current::init(context, config, max_size).await } } } #[cfg(test)] mod test { use crate::{ merkle::Graftable, mmb, mmr, qmdb::current::{ordered::tests as shared, tests::variable_config}, translator::OneCap, }; use commonware_cryptography::{Sha256, sha256::Digest}; use commonware_macros::test_traced; use commonware_runtime::deterministic; /// A type alias for the concrete [Db] type used in these unit tests. type CurrentTest = super::Db< F, deterministic::Context, Digest, Digest, Sha256, OneCap, 32, commonware_parallel::Sequential, >; /// Return a [Db] database initialized with a variable config. async fn open_db( context: deterministic::Context, partition_prefix: String, ) -> CurrentTest { let cfg = variable_config::(&partition_prefix); CurrentTest::::init(context, cfg, None).await.unwrap() } #[test_traced("DEBUG")] pub fn test_current_db_verify_proof_over_bits_in_uncommitted_chunk() { shared::test_verify_proof_over_bits_in_uncommitted_chunk(open_db::); } #[test_traced("DEBUG")] pub fn test_current_db_range_proofs() { shared::test_range_proofs(open_db::); } #[test_traced("DEBUG")] pub fn test_current_db_key_value_proof() { shared::test_key_value_proof(open_db::); } #[test_traced("DEBUG")] fn test_current_db_dynamic_key_value_proof_mmb() { shared::test_key_value_proof(open_db::); } #[test_traced("DEBUG")] fn test_current_db_dynamic_exclusion_proofs_mmb() { shared::test_exclusion_proofs(open_db::); } #[test_traced("DEBUG")] fn test_current_db_dynamic_inactive_proof_mmb() { shared::test_verify_proof_over_bits_in_uncommitted_chunk(open_db::); } #[test_traced("WARN")] pub fn test_current_db_proving_repeated_updates() { shared::test_proving_repeated_updates(open_db::); } #[test_traced("DEBUG")] pub fn test_current_db_exclusion_proofs() { shared::test_exclusion_proofs(open_db::); } }