pub use super::db::KeyValueProof;
use crate::{
Context,
index::unordered::Index,
journal::contiguous::variable::Journal,
merkle::{Graftable, Location},
qmdb::{
Error,
any::{VariableValue, unordered::variable::Operation, value::VariableEncoding},
current::VariableConfig as Config,
operation::Key,
},
translator::Translator,
};
use commonware_codec::Read;
use commonware_cryptography::Hasher;
use commonware_parallel::Strategy;
use commonware_runtime::Spawner;
pub type Db<F, E, K, V, H, T, const N: usize, S> = super::db::Db<
F,
E,
Journal<E, Operation<F, K, V>>,
K,
VariableEncoding<V>,
Index<T, Location<F>>,
H,
N,
S,
>;
impl<
F: Graftable,
E: Context + Spawner,
K: Key,
V: VariableValue,
H: Hasher,
T: Translator,
const N: usize,
S: Strategy,
> Db<F, E, K, V, H, T, N, S>
where
Operation<F, K, V>: Read,
{
pub async fn init(
context: E,
config: Config<T, <Operation<F, K, V> as Read>::Cfg, S>,
) -> Result<Self, Error<F>> {
crate::qmdb::current::init(context, config).await
}
}
pub mod partitioned {
use super::*;
use crate::index::partitioned::unordered::Index;
pub type Db<F, E, K, V, H, T, const P: usize, const N: usize, S> =
crate::qmdb::current::unordered::db::Db<
F,
E,
Journal<E, Operation<F, K, V>>,
K,
VariableEncoding<V>,
Index<T, Location<F>, P>,
H,
N,
S,
>;
impl<
F: Graftable,
E: Context + Spawner,
K: Key,
V: VariableValue,
H: Hasher,
T: Translator,
const P: usize,
const N: usize,
S: Strategy,
> Db<F, E, K, V, H, T, P, N, S>
where
Operation<F, K, V>: Read,
{
pub async fn init(
context: E,
config: Config<T, <Operation<F, K, V> as Read>::Cfg, S, core::num::NonZeroUsize>,
) -> Result<Self, Error<F>> {
crate::qmdb::current::init(context, config).await
}
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::{
mmr,
qmdb::current::{tests::variable_config, unordered::tests as shared},
translator::TwoCap,
};
use commonware_cryptography::{Sha256, sha256::Digest};
use commonware_macros::test_traced;
use commonware_runtime::{Runner as _, Supervisor as _, deterministic};
type CurrentTest = Db<
mmr::Family,
deterministic::Context,
Digest,
Digest,
Sha256,
TwoCap,
32,
commonware_parallel::Sequential,
>;
async fn open_db(context: deterministic::Context, partition_prefix: String) -> CurrentTest {
let cfg = variable_config::<TwoCap>(&partition_prefix, &context);
CurrentTest::init(context, cfg).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("WARN")]
pub fn test_current_db_proving_repeated_updates() {
shared::test_proving_repeated_updates(open_db);
}
type VecKeyTest = Db<
mmr::Family,
deterministic::Context,
Vec<u8>,
Digest,
Sha256,
TwoCap,
32,
commonware_parallel::Sequential,
>;
#[test_traced("WARN")]
pub fn test_current_db_variable_length_keys() {
let executor = deterministic::Runner::default();
executor.start(|context| async move {
let base = variable_config::<TwoCap>("vec-keys", &context);
let cfg = crate::qmdb::current::VariableConfig {
merkle_config: base.merkle_config.clone(),
journal_config: crate::journal::contiguous::variable::Config {
partition: base.journal_config.partition.clone(),
items_per_section: base.journal_config.items_per_section,
compression: None,
codec_config: (((0..).into(), ()), ()),
page_cache: base.journal_config.page_cache.clone(),
write_buffer: base.journal_config.write_buffer,
replay_buffer: base.journal_config.replay_buffer,
},
grafted_metadata_partition: base.grafted_metadata_partition.clone(),
translator: TwoCap,
init_cache_size: base.init_cache_size,
init_buffer: base.init_buffer,
init_concurrency: (),
};
let db = VecKeyTest::init(context.child("first"), cfg.clone())
.await
.unwrap();
let key = b"variable-length-key".to_vec();
let value = Sha256::hash(&[b"value"]);
let merkleized = db
.new_batch()
.write(key.clone(), Some(value))
.merkleize(&db, None)
.await
.unwrap();
let (db, _) = db.apply_batch(merkleized).await.unwrap();
let db = db.commit().await.unwrap();
assert_eq!(db.get(&key).await.unwrap().unwrap(), value);
let root = db.root();
let proof = db.key_value_proof(key.clone()).await.unwrap();
assert!(VecKeyTest::verify_key_value_proof(
key.clone(),
value,
&proof,
&root
));
drop(db);
let db = VecKeyTest::init(context.child("second"), cfg)
.await
.unwrap();
assert_eq!(db.root(), root);
assert_eq!(db.get(&key).await.unwrap().unwrap(), value);
db.destroy().await.unwrap();
});
}
}