1use crate::{
6 journal::{
7 authenticated,
8 contiguous::fixed::{self, Config as JournalConfig},
9 },
10 merkle::Family,
11 qmdb::{
12 any::value::{FixedEncoding, FixedValue},
13 keyless::operation::Operation as BaseOperation,
14 operation::Committable,
15 Error, ROOT_BAGGING,
16 },
17};
18use commonware_cryptography::Hasher;
19use commonware_parallel::Strategy;
20use commonware_runtime::{Clock, Metrics, Storage};
21
22pub type Operation<F, V> = BaseOperation<F, FixedEncoding<V>>;
24
25pub type Db<F, E, V, H, S> =
27 super::Keyless<F, E, FixedEncoding<V>, fixed::Journal<E, Operation<F, V>>, H, S>;
28
29pub type CompactDb<F, E, V, H, S> = super::CompactDb<F, E, FixedEncoding<V>, H, (), S>;
31
32type Journal<F, E, V, H, S> =
33 authenticated::Journal<F, E, fixed::Journal<E, Operation<F, V>>, H, S>;
34
35pub type Config<S> = super::Config<JournalConfig, S>;
37
38pub type CompactConfig<S> = super::CompactConfig<(), S>;
40
41impl<F: Family, E: Storage + Clock + Metrics, V: FixedValue, H: Hasher, S: Strategy>
42 Db<F, E, V, H, S>
43{
44 pub async fn init(context: E, cfg: Config<S>) -> Result<Self, Error<F>> {
47 let journal: Journal<F, E, V, H, S> = Journal::new(
48 context.child("journal"),
49 cfg.merkle,
50 cfg.log,
51 Operation::<F, V>::is_commit,
52 ROOT_BAGGING,
53 )
54 .await?;
55 Self::init_from_journal(journal, context).await
56 }
57}
58
59impl<F: Family, E: Storage + Clock + Metrics, V: FixedValue, H: Hasher, S: Strategy>
60 CompactDb<F, E, V, H, S>
61{
62 pub async fn init(context: E, cfg: CompactConfig<S>) -> Result<Self, Error<F>> {
64 let merkle = crate::merkle::compact::Merkle::init(context, cfg.merkle).await?;
65 Self::init_from_merkle(merkle, ()).await
66 }
67}
68
69#[cfg(test)]
70mod test {
71 use super::*;
72 use crate::{
73 merkle::{mmb, mmr},
74 qmdb::keyless::tests,
75 };
76 use commonware_cryptography::Sha256;
77 use commonware_macros::test_traced;
78 use commonware_parallel::{Rayon, Sequential, Strategy};
79 use commonware_runtime::{
80 buffer::paged::CacheRef, deterministic, BufferPooler, Runner as _, Supervisor as _,
81 };
82 use commonware_utils::{NZUsize, NZU16, NZU64};
83 use std::num::{NonZeroU16, NonZeroUsize};
84
85 const PAGE_SIZE: NonZeroU16 = NZU16!(101);
86 const PAGE_CACHE_SIZE: NonZeroUsize = NZUsize!(11);
87
88 fn db_config<S: Strategy>(suffix: &str, pooler: &impl BufferPooler, strategy: S) -> Config<S> {
89 let page_cache = CacheRef::from_pooler(pooler, PAGE_SIZE, PAGE_CACHE_SIZE);
90 Config {
91 merkle: crate::merkle::full::Config {
92 journal_partition: format!("fixed-journal-{suffix}"),
93 metadata_partition: format!("fixed-metadata-{suffix}"),
94 items_per_blob: NZU64!(11),
95 write_buffer: NZUsize!(1024),
96 strategy,
97 page_cache: page_cache.clone(),
98 },
99 log: JournalConfig {
100 partition: format!("fixed-log-journal-{suffix}"),
101 items_per_blob: NZU64!(7),
102 page_cache,
103 write_buffer: NZUsize!(1024),
104 },
105 }
106 }
107
108 type TestDb<F> =
109 Db<F, deterministic::Context, commonware_utils::sequence::U64, Sha256, Sequential>;
110 type TestRayonDb<F> =
111 Db<F, deterministic::Context, commonware_utils::sequence::U64, Sha256, Rayon>;
112 type TestCompactDb<F> =
113 CompactDb<F, deterministic::Context, commonware_utils::sequence::U64, Sha256, Sequential>;
114
115 async fn open_db<F: Family>(context: deterministic::Context) -> TestDb<F> {
116 open_db_with_suffix("partition", context).await
117 }
118
119 async fn open_db_with_suffix<F: Family>(
120 suffix: &str,
121 context: deterministic::Context,
122 ) -> TestDb<F> {
123 let cfg = db_config(suffix, &context, Sequential);
124 TestDb::init(context, cfg).await.unwrap()
125 }
126
127 async fn open_rayon_db<F: Family>(context: deterministic::Context) -> TestRayonDb<F> {
128 let cfg = db_config("rayon", &context, Rayon::new(NZUsize!(2)).unwrap());
129 TestRayonDb::init(context, cfg).await.unwrap()
130 }
131
132 async fn open_compact<F: crate::merkle::Family>(
133 context: deterministic::Context,
134 ) -> TestCompactDb<F> {
135 let cfg = CompactConfig {
136 merkle: crate::merkle::compact::Config {
137 partition: "compact-keyless-fixed".into(),
138 strategy: Sequential,
139 },
140 commit_codec_config: (),
141 };
142 TestCompactDb::init(context, cfg).await.unwrap()
143 }
144
145 fn reopen<F: Family>() -> tests::Reopen<TestDb<F>> {
146 Box::new(|ctx| Box::pin(open_db(ctx)))
147 }
148
149 #[test_traced("INFO")]
150 fn test_keyless_fixed_metrics() {
151 deterministic::Runner::default().start(|ctx| async move {
152 let mut db = open_db::<mmr::Family>(ctx.child("db")).await;
153 let value = commonware_utils::sequence::U64::new(7);
154 let floor = db.inactivity_floor_loc();
155 let batch = db
156 .new_batch()
157 .append(value.clone())
158 .merkleize(&db, None, floor);
159 let range = db.apply_batch(batch).await.unwrap();
160 assert_eq!(db.get(range.start).await.unwrap(), Some(value.clone()));
161 assert_eq!(
162 db.get_many(&[range.start]).await.unwrap(),
163 vec![Some(value)]
164 );
165 db.commit().await.unwrap();
166 db.sync().await.unwrap();
167 db.prune(crate::merkle::Location::new(0)).await.unwrap();
168
169 let metrics = ctx.encode();
170 for expected in [
171 "db_size 3",
172 "db_pruning_boundary 0",
173 "db_retained 3",
174 "db_inactivity_floor 0",
175 "db_last_commit 2",
176 "db_get_calls_total 1",
177 "db_get_many_calls_total 1",
178 "db_locations_requested_total 2",
179 "db_apply_batch_calls_total 1",
180 "db_operations_applied_total 2",
181 "db_commit_calls_total 1",
182 "db_sync_calls_total 1",
183 "db_prune_calls_total 1",
184 "db_get_duration_count 1",
185 "db_get_many_duration_count 1",
186 "db_apply_batch_duration_count 1",
187 "db_commit_duration_count 1",
188 "db_sync_duration_count 1",
189 "db_prune_duration_count 1",
190 ] {
191 assert!(metrics.contains(expected), "missing {expected}\n{metrics}");
192 }
193 });
194 }
195
196 #[test_traced("INFO")]
197 fn test_keyless_fixed_empty() {
198 deterministic::Runner::default().start(|ctx| async move {
199 let db = open_db::<mmr::Family>(ctx.child("db").with_attribute("index", 1)).await;
200 tests::test_keyless_db_empty(ctx, db, reopen::<mmr::Family>()).await;
201 });
202 }
203
204 #[test_traced("WARN")]
205 fn test_keyless_fixed_build_basic() {
206 deterministic::Runner::default().start(|ctx| async move {
207 let db = open_db::<mmr::Family>(ctx.child("db").with_attribute("index", 1)).await;
208 tests::test_keyless_db_build_basic(ctx, db, reopen::<mmr::Family>()).await;
209 });
210 }
211
212 #[test_traced("WARN")]
213 fn test_keyless_fixed_recovery() {
214 deterministic::Runner::default().start(|ctx| async move {
215 let db = open_db::<mmr::Family>(ctx.child("db").with_attribute("index", 1)).await;
216 tests::test_keyless_db_recovery(ctx, db, reopen::<mmr::Family>()).await;
217 });
218 }
219
220 #[test_traced("WARN")]
221 fn test_keyless_fixed_non_empty_recovery() {
222 deterministic::Runner::default().start(|ctx| async move {
223 let db = open_db::<mmr::Family>(ctx.child("db").with_attribute("index", 1)).await;
224 tests::test_keyless_db_non_empty_recovery(ctx, db, reopen::<mmr::Family>()).await;
225 });
226 }
227
228 #[test_traced("INFO")]
229 fn test_keyless_fixed_proof() {
230 deterministic::Runner::default().start(|ctx| async move {
231 let db = open_db::<mmr::Family>(ctx.child("storage")).await;
232 tests::test_keyless_db_proof(db).await;
233 });
234 }
235
236 #[test_traced("INFO")]
237 fn test_keyless_fixed_proof_comprehensive() {
238 deterministic::Runner::default().start(|ctx| async move {
239 let db = open_db::<mmr::Family>(ctx.child("storage")).await;
240 tests::test_keyless_db_proof_comprehensive(db).await;
241 });
242 }
243
244 #[test_traced("INFO")]
245 fn test_keyless_fixed_proof_with_pruning() {
246 deterministic::Runner::default().start(|ctx| async move {
247 let db = open_db::<mmr::Family>(ctx.child("db").with_attribute("index", 1)).await;
248 tests::test_keyless_db_proof_with_pruning(ctx, db, reopen::<mmr::Family>()).await;
249 });
250 }
251
252 #[test_traced("WARN")]
253 fn test_keyless_fixed_empty_db_recovery() {
254 deterministic::Runner::default().start(|ctx| async move {
255 let db = open_db::<mmr::Family>(ctx.child("db").with_attribute("index", 1)).await;
256 tests::test_keyless_db_empty_db_recovery(ctx, db, reopen::<mmr::Family>()).await;
257 });
258 }
259
260 #[test_traced("WARN")]
261 fn test_keyless_fixed_replay_with_trailing_appends() {
262 deterministic::Runner::default().start(|ctx| async move {
263 let db = open_db::<mmr::Family>(ctx.child("db").with_attribute("index", 1)).await;
264 tests::test_keyless_db_replay_with_trailing_appends(ctx, db, reopen::<mmr::Family>())
265 .await;
266 });
267 }
268
269 #[test_traced("INFO")]
270 fn test_keyless_fixed_get_out_of_bounds() {
271 deterministic::Runner::default().start(|ctx| async move {
272 let db = open_db::<mmr::Family>(ctx.child("storage")).await;
273 tests::test_keyless_db_get_out_of_bounds(db).await;
274 });
275 }
276
277 #[test_traced("INFO")]
278 fn test_keyless_fixed_metadata() {
279 deterministic::Runner::default().start(|ctx| async move {
280 let db = open_db::<mmr::Family>(ctx.child("db")).await;
281 tests::test_keyless_db_metadata(db).await;
282 });
283 }
284
285 #[test_traced("INFO")]
286 fn test_keyless_fixed_shared_helper_accepts_rayon_strategy() {
287 deterministic::Runner::default().start(|ctx| async move {
288 let db = open_rayon_db::<mmr::Family>(ctx.child("db").with_attribute("index", 1)).await;
289 tests::test_keyless_db_metadata(db).await;
290 });
291 }
292
293 async fn assert_compact_root_compatibility<F: crate::merkle::Family>(
294 ctx: deterministic::Context,
295 ) {
296 let mut db = open_db::<F>(ctx.child("db")).await;
297 let mut compact = open_compact::<F>(ctx.child("compact")).await;
298 assert_eq!(db.root(), compact.root());
299
300 let v1 = commonware_utils::sequence::U64::new(1);
301 let v2 = commonware_utils::sequence::U64::new(2);
302 let metadata = commonware_utils::sequence::U64::new(99);
303
304 let floor = db.inactivity_floor_loc();
305 let retained = db
306 .new_batch()
307 .append(v1.clone())
308 .append(v2.clone())
309 .merkleize(&db, Some(metadata.clone()), floor);
310 let compact_batch = compact.new_batch().append(v1).append(v2).merkleize(
311 &compact,
312 Some(metadata.clone()),
313 floor,
314 );
315
316 assert_eq!(retained.root(), compact_batch.root());
317
318 db.apply_batch(retained).await.unwrap();
319 compact.apply_batch(compact_batch).unwrap();
320 db.commit().await.unwrap();
321 compact.commit().await.unwrap();
322
323 assert_eq!(db.root(), compact.root());
324 assert_eq!(compact.get_metadata(), Some(metadata.clone()));
325
326 drop(compact);
327 let reopened = open_compact::<F>(ctx.child("reopen")).await;
328 assert_eq!(db.root(), reopened.root());
329 assert_eq!(reopened.get_metadata(), Some(metadata));
330
331 reopened.destroy().await.unwrap();
332 db.destroy().await.unwrap();
333 }
334
335 #[test_traced("INFO")]
336 fn test_keyless_fixed_compact_root_compatibility() {
337 deterministic::Runner::default().start(|ctx| async move {
338 assert_compact_root_compatibility::<mmr::Family>(ctx).await;
339 });
340 }
341
342 #[test_traced("INFO")]
343 fn test_keyless_fixed_compact_root_compatibility_mmb() {
344 deterministic::Runner::default().start(|ctx| async move {
345 assert_compact_root_compatibility::<mmb::Family>(ctx).await;
346 });
347 }
348
349 #[test_traced("INFO")]
350 fn test_keyless_fixed_pruning() {
351 deterministic::Runner::default().start(|ctx| async move {
352 let db = open_db::<mmr::Family>(ctx.child("db")).await;
353 tests::test_keyless_db_pruning(db).await;
354 });
355 }
356
357 #[test_traced("INFO")]
358 fn test_keyless_fixed_batch_get() {
359 deterministic::Runner::default().start(|ctx| async move {
360 let db = open_db::<mmr::Family>(ctx.child("db")).await;
361 tests::test_keyless_batch_get(db).await;
362 });
363 }
364
365 #[test_traced("INFO")]
366 fn test_keyless_fixed_batch_stacked_get() {
367 deterministic::Runner::default().start(|ctx| async move {
368 let db = open_db::<mmr::Family>(ctx.child("db")).await;
369 tests::test_keyless_batch_stacked_get(db).await;
370 });
371 }
372
373 #[test_traced("INFO")]
374 fn test_keyless_fixed_batch_speculative_root() {
375 deterministic::Runner::default().start(|ctx| async move {
376 let db = open_db::<mmr::Family>(ctx.child("db")).await;
377 tests::test_keyless_batch_speculative_root(db).await;
378 });
379 }
380
381 #[test_traced("INFO")]
382 fn test_keyless_fixed_merkleized_batch_get() {
383 deterministic::Runner::default().start(|ctx| async move {
384 let db = open_db::<mmr::Family>(ctx.child("db")).await;
385 tests::test_keyless_merkleized_batch_get(db).await;
386 });
387 }
388
389 #[test_traced("INFO")]
390 fn test_keyless_fixed_get_many() {
391 deterministic::Runner::default().start(|ctx| async move {
392 let db = open_db::<mmr::Family>(ctx.child("db")).await;
393 tests::test_keyless_get_many(db).await;
394 });
395 }
396
397 #[test_traced("INFO")]
398 fn test_keyless_fixed_batch_chained() {
399 deterministic::Runner::default().start(|ctx| async move {
400 let db = open_db::<mmr::Family>(ctx.child("db")).await;
401 tests::test_keyless_batch_chained(db).await;
402 });
403 }
404
405 #[test_traced("INFO")]
406 fn test_keyless_fixed_batch_chained_apply_sequential() {
407 deterministic::Runner::default().start(|ctx| async move {
408 let db = open_db::<mmr::Family>(ctx.child("db")).await;
409 tests::test_keyless_batch_chained_apply_sequential(db).await;
410 });
411 }
412
413 #[test_traced("INFO")]
414 fn test_keyless_fixed_batch_many_sequential() {
415 deterministic::Runner::default().start(|ctx| async move {
416 let db = open_db::<mmr::Family>(ctx.child("db")).await;
417 tests::test_keyless_batch_many_sequential(db).await;
418 });
419 }
420
421 #[test_traced("INFO")]
422 fn test_keyless_fixed_batch_empty() {
423 deterministic::Runner::default().start(|ctx| async move {
424 let db = open_db::<mmr::Family>(ctx.child("db")).await;
425 tests::test_keyless_batch_empty(db).await;
426 });
427 }
428
429 #[test_traced("INFO")]
430 fn test_keyless_fixed_batch_chained_merkleized_get() {
431 deterministic::Runner::default().start(|ctx| async move {
432 let db = open_db::<mmr::Family>(ctx.child("db")).await;
433 tests::test_keyless_batch_chained_merkleized_get(db).await;
434 });
435 }
436
437 #[test_traced("INFO")]
438 fn test_keyless_fixed_batch_large() {
439 deterministic::Runner::default().start(|ctx| async move {
440 let db = open_db::<mmr::Family>(ctx.child("db")).await;
441 tests::test_keyless_batch_large(db).await;
442 });
443 }
444
445 #[test_traced]
446 fn test_keyless_fixed_stale_batch() {
447 deterministic::Runner::default().start(|ctx| async move {
448 let db = open_db::<mmr::Family>(ctx.child("db")).await;
449 tests::test_keyless_stale_batch(db).await;
450 });
451 }
452
453 #[test_traced]
454 fn test_keyless_fixed_stale_batch_chained() {
455 deterministic::Runner::default().start(|ctx| async move {
456 let db = open_db::<mmr::Family>(ctx.child("db")).await;
457 tests::test_keyless_stale_batch_chained(db).await;
458 });
459 }
460
461 #[test_traced]
462 fn test_keyless_fixed_sequential_commit_parent_then_child() {
463 deterministic::Runner::default().start(|ctx| async move {
464 let db = open_db::<mmr::Family>(ctx.child("db")).await;
465 tests::test_keyless_sequential_commit_parent_then_child(db).await;
466 });
467 }
468
469 #[test_traced]
470 fn test_keyless_fixed_stale_batch_child_before_parent() {
471 deterministic::Runner::default().start(|ctx| async move {
472 let db = open_db::<mmr::Family>(ctx.child("db")).await;
473 tests::test_keyless_stale_batch_child_before_parent(db).await;
474 });
475 }
476
477 #[test_traced]
478 fn test_keyless_fixed_to_batch() {
479 deterministic::Runner::default().start(|ctx| async move {
480 let db = open_db::<mmr::Family>(ctx.child("db")).await;
481 tests::test_keyless_to_batch(db).await;
482 });
483 }
484
485 #[test_traced]
486 fn test_keyless_fixed_child_root_matches_pending_and_committed() {
487 deterministic::Runner::default().start(|ctx| async move {
488 let db = open_db::<mmr::Family>(ctx.child("db")).await;
489 tests::test_keyless_child_root_matches_pending_and_committed(db).await;
490 });
491 }
492
493 #[test_traced("INFO")]
494 fn test_keyless_fixed_rewind_recovery() {
495 deterministic::Runner::default().start(|ctx| async move {
496 let db = open_db::<mmr::Family>(ctx.child("db")).await;
497 tests::test_keyless_db_rewind_recovery(ctx, db, reopen::<mmr::Family>()).await;
498 });
499 }
500
501 #[test_traced("INFO")]
502 fn test_keyless_fixed_rewind_pruned_target_errors() {
503 deterministic::Runner::default().start(|ctx| async move {
504 let db = open_db::<mmr::Family>(ctx.child("db")).await;
505 tests::test_keyless_db_rewind_pruned_target_errors(db).await;
506 });
507 }
508
509 #[test_traced("INFO")]
510 fn test_keyless_fixed_floor_tracking() {
511 deterministic::Runner::default().start(|ctx| async move {
512 let db = open_db::<mmr::Family>(ctx.child("db").with_attribute("index", 1)).await;
513 tests::test_keyless_db_floor_tracking(ctx, db, reopen::<mmr::Family>()).await;
514 });
515 }
516
517 #[test_traced("INFO")]
518 fn test_keyless_fixed_floor_regression_rejected() {
519 deterministic::Runner::default().start(|ctx| async move {
520 let db = open_db::<mmr::Family>(ctx.child("db")).await;
521 tests::test_keyless_db_floor_regression_rejected(db).await;
522 });
523 }
524
525 #[test_traced("INFO")]
526 fn test_keyless_fixed_floor_beyond_commit_loc_rejected() {
527 deterministic::Runner::default().start(|ctx| async move {
528 let db = open_db::<mmr::Family>(ctx.child("db")).await;
529 tests::test_keyless_db_floor_beyond_commit_loc_rejected(db).await;
530 });
531 }
532
533 #[test_traced("INFO")]
534 fn test_keyless_fixed_rewind_restores_floor() {
535 deterministic::Runner::default().start(|ctx| async move {
536 let db = open_db::<mmr::Family>(ctx.child("db")).await;
537 tests::test_keyless_db_rewind_restores_floor(db).await;
538 });
539 }
540
541 #[test_traced("INFO")]
542 fn test_keyless_fixed_floor_changes_root() {
543 deterministic::Runner::default().start(|ctx| async move {
544 let db_a = open_db_with_suffix::<mmr::Family>("root-a", ctx.child("a")).await;
545 let db_b = open_db_with_suffix::<mmr::Family>("root-b", ctx.child("b")).await;
546 tests::test_keyless_db_floor_changes_root(db_a, db_b).await;
547 });
548 }
549
550 #[test_traced("INFO")]
551 fn test_keyless_fixed_floor_at_commit_loc_accepted() {
552 deterministic::Runner::default().start(|ctx| async move {
553 let db = open_db::<mmr::Family>(ctx.child("db")).await;
554 tests::test_keyless_db_floor_at_commit_loc_accepted(db).await;
555 });
556 }
557
558 #[test_traced("INFO")]
559 fn test_keyless_fixed_rewind_after_reopen_with_floor() {
560 deterministic::Runner::default().start(|ctx| async move {
561 let db = open_db::<mmr::Family>(ctx.child("db").with_attribute("index", 1)).await;
562 tests::test_keyless_db_rewind_after_reopen_with_floor(ctx, db, reopen::<mmr::Family>())
563 .await;
564 });
565 }
566
567 #[test_traced("INFO")]
568 fn test_keyless_fixed_ancestor_floor_regression_rejected() {
569 deterministic::Runner::default().start(|ctx| async move {
570 let db = open_db::<mmr::Family>(ctx.child("db")).await;
571 tests::test_keyless_db_ancestor_floor_regression_rejected(db).await;
572 });
573 }
574
575 #[test_traced("INFO")]
576 fn test_keyless_fixed_ancestor_floor_beyond_commit_loc_rejected() {
577 deterministic::Runner::default().start(|ctx| async move {
578 let db = open_db::<mmr::Family>(ctx.child("db")).await;
579 tests::test_keyless_db_ancestor_floor_beyond_commit_loc_rejected(db).await;
580 });
581 }
582
583 #[test_traced("INFO")]
584 fn test_keyless_fixed_chained_apply_with_valid_floors_succeeds() {
585 deterministic::Runner::default().start(|ctx| async move {
586 let db = open_db::<mmr::Family>(ctx.child("db")).await;
587 tests::test_keyless_db_chained_apply_with_valid_floors_succeeds(db).await;
588 });
589 }
590
591 #[test_traced("INFO")]
592 fn test_keyless_fixed_single_commit_live_set() {
593 deterministic::Runner::default().start(|ctx| async move {
594 let db = open_db::<mmr::Family>(ctx.child("db").with_attribute("index", 1)).await;
595 tests::test_keyless_db_single_commit_live_set(ctx, db, reopen::<mmr::Family>()).await;
596 });
597 }
598
599 #[test_traced("INFO")]
602 fn test_keyless_fixed_empty_mmb() {
603 deterministic::Runner::default().start(|ctx| async move {
604 let db = open_db::<mmb::Family>(ctx.child("db").with_attribute("index", 1)).await;
605 tests::test_keyless_db_empty(ctx, db, reopen::<mmb::Family>()).await;
606 });
607 }
608
609 #[test_traced("WARN")]
610 fn test_keyless_fixed_build_basic_mmb() {
611 deterministic::Runner::default().start(|ctx| async move {
612 let db = open_db::<mmb::Family>(ctx.child("db").with_attribute("index", 1)).await;
613 tests::test_keyless_db_build_basic(ctx, db, reopen::<mmb::Family>()).await;
614 });
615 }
616
617 #[test_traced("WARN")]
618 fn test_keyless_fixed_recovery_mmb() {
619 deterministic::Runner::default().start(|ctx| async move {
620 let db = open_db::<mmb::Family>(ctx.child("db").with_attribute("index", 1)).await;
621 tests::test_keyless_db_recovery(ctx, db, reopen::<mmb::Family>()).await;
622 });
623 }
624
625 #[test_traced("WARN")]
626 fn test_keyless_fixed_non_empty_recovery_mmb() {
627 deterministic::Runner::default().start(|ctx| async move {
628 let db = open_db::<mmb::Family>(ctx.child("db").with_attribute("index", 1)).await;
629 tests::test_keyless_db_non_empty_recovery(ctx, db, reopen::<mmb::Family>()).await;
630 });
631 }
632
633 #[test_traced("INFO")]
634 fn test_keyless_fixed_proof_mmb() {
635 deterministic::Runner::default().start(|ctx| async move {
636 let db = open_db::<mmb::Family>(ctx.child("storage")).await;
637 tests::test_keyless_db_proof(db).await;
638 });
639 }
640
641 #[test_traced("INFO")]
642 fn test_keyless_fixed_proof_comprehensive_mmb() {
643 deterministic::Runner::default().start(|ctx| async move {
644 let db = open_db::<mmb::Family>(ctx.child("storage")).await;
645 tests::test_keyless_db_proof_comprehensive(db).await;
646 });
647 }
648
649 #[test_traced("INFO")]
650 fn test_keyless_fixed_proof_with_pruning_mmb() {
651 deterministic::Runner::default().start(|ctx| async move {
652 let db = open_db::<mmb::Family>(ctx.child("db").with_attribute("index", 1)).await;
653 tests::test_keyless_db_proof_with_pruning(ctx, db, reopen::<mmb::Family>()).await;
654 });
655 }
656
657 #[test_traced("WARN")]
658 fn test_keyless_fixed_empty_db_recovery_mmb() {
659 deterministic::Runner::default().start(|ctx| async move {
660 let db = open_db::<mmb::Family>(ctx.child("db").with_attribute("index", 1)).await;
661 tests::test_keyless_db_empty_db_recovery(ctx, db, reopen::<mmb::Family>()).await;
662 });
663 }
664
665 #[test_traced("WARN")]
666 fn test_keyless_fixed_replay_with_trailing_appends_mmb() {
667 deterministic::Runner::default().start(|ctx| async move {
668 let db = open_db::<mmb::Family>(ctx.child("db").with_attribute("index", 1)).await;
669 tests::test_keyless_db_replay_with_trailing_appends(ctx, db, reopen::<mmb::Family>())
670 .await;
671 });
672 }
673
674 #[test_traced("INFO")]
675 fn test_keyless_fixed_get_out_of_bounds_mmb() {
676 deterministic::Runner::default().start(|ctx| async move {
677 let db = open_db::<mmb::Family>(ctx.child("storage")).await;
678 tests::test_keyless_db_get_out_of_bounds(db).await;
679 });
680 }
681
682 #[test_traced("INFO")]
683 fn test_keyless_fixed_metadata_mmb() {
684 deterministic::Runner::default().start(|ctx| async move {
685 let db = open_db::<mmb::Family>(ctx.child("db")).await;
686 tests::test_keyless_db_metadata(db).await;
687 });
688 }
689
690 #[test_traced("INFO")]
691 fn test_keyless_fixed_pruning_mmb() {
692 deterministic::Runner::default().start(|ctx| async move {
693 let db = open_db::<mmb::Family>(ctx.child("db")).await;
694 tests::test_keyless_db_pruning(db).await;
695 });
696 }
697
698 #[test_traced("INFO")]
699 fn test_keyless_fixed_batch_get_mmb() {
700 deterministic::Runner::default().start(|ctx| async move {
701 let db = open_db::<mmb::Family>(ctx.child("db")).await;
702 tests::test_keyless_batch_get(db).await;
703 });
704 }
705
706 #[test_traced("INFO")]
707 fn test_keyless_fixed_batch_stacked_get_mmb() {
708 deterministic::Runner::default().start(|ctx| async move {
709 let db = open_db::<mmb::Family>(ctx.child("db")).await;
710 tests::test_keyless_batch_stacked_get(db).await;
711 });
712 }
713
714 #[test_traced("INFO")]
715 fn test_keyless_fixed_batch_speculative_root_mmb() {
716 deterministic::Runner::default().start(|ctx| async move {
717 let db = open_db::<mmb::Family>(ctx.child("db")).await;
718 tests::test_keyless_batch_speculative_root(db).await;
719 });
720 }
721
722 #[test_traced("INFO")]
723 fn test_keyless_fixed_merkleized_batch_get_mmb() {
724 deterministic::Runner::default().start(|ctx| async move {
725 let db = open_db::<mmb::Family>(ctx.child("db")).await;
726 tests::test_keyless_merkleized_batch_get(db).await;
727 });
728 }
729
730 #[test_traced("INFO")]
731 fn test_keyless_fixed_batch_chained_mmb() {
732 deterministic::Runner::default().start(|ctx| async move {
733 let db = open_db::<mmb::Family>(ctx.child("db")).await;
734 tests::test_keyless_batch_chained(db).await;
735 });
736 }
737
738 #[test_traced("INFO")]
739 fn test_keyless_fixed_batch_chained_apply_sequential_mmb() {
740 deterministic::Runner::default().start(|ctx| async move {
741 let db = open_db::<mmb::Family>(ctx.child("db")).await;
742 tests::test_keyless_batch_chained_apply_sequential(db).await;
743 });
744 }
745
746 #[test_traced("INFO")]
747 fn test_keyless_fixed_batch_many_sequential_mmb() {
748 deterministic::Runner::default().start(|ctx| async move {
749 let db = open_db::<mmb::Family>(ctx.child("db")).await;
750 tests::test_keyless_batch_many_sequential(db).await;
751 });
752 }
753
754 #[test_traced("INFO")]
755 fn test_keyless_fixed_batch_empty_mmb() {
756 deterministic::Runner::default().start(|ctx| async move {
757 let db = open_db::<mmb::Family>(ctx.child("db")).await;
758 tests::test_keyless_batch_empty(db).await;
759 });
760 }
761
762 #[test_traced("INFO")]
763 fn test_keyless_fixed_batch_chained_merkleized_get_mmb() {
764 deterministic::Runner::default().start(|ctx| async move {
765 let db = open_db::<mmb::Family>(ctx.child("db")).await;
766 tests::test_keyless_batch_chained_merkleized_get(db).await;
767 });
768 }
769
770 #[test_traced("INFO")]
771 fn test_keyless_fixed_batch_large_mmb() {
772 deterministic::Runner::default().start(|ctx| async move {
773 let db = open_db::<mmb::Family>(ctx.child("db")).await;
774 tests::test_keyless_batch_large(db).await;
775 });
776 }
777
778 #[test_traced]
779 fn test_keyless_fixed_stale_batch_mmb() {
780 deterministic::Runner::default().start(|ctx| async move {
781 let db = open_db::<mmb::Family>(ctx.child("db")).await;
782 tests::test_keyless_stale_batch(db).await;
783 });
784 }
785
786 #[test_traced]
787 fn test_keyless_fixed_stale_batch_chained_mmb() {
788 deterministic::Runner::default().start(|ctx| async move {
789 let db = open_db::<mmb::Family>(ctx.child("db")).await;
790 tests::test_keyless_stale_batch_chained(db).await;
791 });
792 }
793
794 #[test_traced]
795 fn test_keyless_fixed_sequential_commit_parent_then_child_mmb() {
796 deterministic::Runner::default().start(|ctx| async move {
797 let db = open_db::<mmb::Family>(ctx.child("db")).await;
798 tests::test_keyless_sequential_commit_parent_then_child(db).await;
799 });
800 }
801
802 #[test_traced]
803 fn test_keyless_fixed_stale_batch_child_before_parent_mmb() {
804 deterministic::Runner::default().start(|ctx| async move {
805 let db = open_db::<mmb::Family>(ctx.child("db")).await;
806 tests::test_keyless_stale_batch_child_before_parent(db).await;
807 });
808 }
809
810 #[test_traced]
811 fn test_keyless_fixed_to_batch_mmb() {
812 deterministic::Runner::default().start(|ctx| async move {
813 let db = open_db::<mmb::Family>(ctx.child("db")).await;
814 tests::test_keyless_to_batch(db).await;
815 });
816 }
817
818 #[test_traced]
819 fn test_keyless_fixed_child_root_matches_pending_and_committed_mmb() {
820 deterministic::Runner::default().start(|ctx| async move {
821 let db = open_db::<mmb::Family>(ctx.child("db")).await;
822 tests::test_keyless_child_root_matches_pending_and_committed(db).await;
823 });
824 }
825
826 #[test_traced("INFO")]
827 fn test_keyless_fixed_rewind_recovery_mmb() {
828 deterministic::Runner::default().start(|ctx| async move {
829 let db = open_db::<mmb::Family>(ctx.child("db")).await;
830 tests::test_keyless_db_rewind_recovery(ctx, db, reopen::<mmb::Family>()).await;
831 });
832 }
833
834 #[test_traced("INFO")]
835 fn test_keyless_fixed_rewind_pruned_target_errors_mmb() {
836 deterministic::Runner::default().start(|ctx| async move {
837 let db = open_db::<mmb::Family>(ctx.child("db")).await;
838 tests::test_keyless_db_rewind_pruned_target_errors(db).await;
839 });
840 }
841
842 #[test_traced("INFO")]
843 fn test_keyless_fixed_floor_tracking_mmb() {
844 deterministic::Runner::default().start(|ctx| async move {
845 let db = open_db::<mmb::Family>(ctx.child("db").with_attribute("index", 1)).await;
846 tests::test_keyless_db_floor_tracking(ctx, db, reopen::<mmb::Family>()).await;
847 });
848 }
849
850 #[test_traced("INFO")]
851 fn test_keyless_fixed_floor_regression_rejected_mmb() {
852 deterministic::Runner::default().start(|ctx| async move {
853 let db = open_db::<mmb::Family>(ctx.child("db")).await;
854 tests::test_keyless_db_floor_regression_rejected(db).await;
855 });
856 }
857
858 #[test_traced("INFO")]
859 fn test_keyless_fixed_floor_beyond_commit_loc_rejected_mmb() {
860 deterministic::Runner::default().start(|ctx| async move {
861 let db = open_db::<mmb::Family>(ctx.child("db")).await;
862 tests::test_keyless_db_floor_beyond_commit_loc_rejected(db).await;
863 });
864 }
865
866 #[test_traced("INFO")]
867 fn test_keyless_fixed_rewind_restores_floor_mmb() {
868 deterministic::Runner::default().start(|ctx| async move {
869 let db = open_db::<mmb::Family>(ctx.child("db")).await;
870 tests::test_keyless_db_rewind_restores_floor(db).await;
871 });
872 }
873
874 #[test_traced("INFO")]
875 fn test_keyless_fixed_floor_changes_root_mmb() {
876 deterministic::Runner::default().start(|ctx| async move {
877 let db_a = open_db_with_suffix::<mmb::Family>("root-a", ctx.child("a")).await;
878 let db_b = open_db_with_suffix::<mmb::Family>("root-b", ctx.child("b")).await;
879 tests::test_keyless_db_floor_changes_root(db_a, db_b).await;
880 });
881 }
882
883 #[test_traced("INFO")]
884 fn test_keyless_fixed_floor_at_commit_loc_accepted_mmb() {
885 deterministic::Runner::default().start(|ctx| async move {
886 let db = open_db::<mmb::Family>(ctx.child("db")).await;
887 tests::test_keyless_db_floor_at_commit_loc_accepted(db).await;
888 });
889 }
890
891 #[test_traced("INFO")]
892 fn test_keyless_fixed_rewind_after_reopen_with_floor_mmb() {
893 deterministic::Runner::default().start(|ctx| async move {
894 let db = open_db::<mmb::Family>(ctx.child("db").with_attribute("index", 1)).await;
895 tests::test_keyless_db_rewind_after_reopen_with_floor(ctx, db, reopen::<mmb::Family>())
896 .await;
897 });
898 }
899
900 #[test_traced("INFO")]
901 fn test_keyless_fixed_ancestor_floor_regression_rejected_mmb() {
902 deterministic::Runner::default().start(|ctx| async move {
903 let db = open_db::<mmb::Family>(ctx.child("db")).await;
904 tests::test_keyless_db_ancestor_floor_regression_rejected(db).await;
905 });
906 }
907
908 #[test_traced("INFO")]
909 fn test_keyless_fixed_ancestor_floor_beyond_commit_loc_rejected_mmb() {
910 deterministic::Runner::default().start(|ctx| async move {
911 let db = open_db::<mmb::Family>(ctx.child("db")).await;
912 tests::test_keyless_db_ancestor_floor_beyond_commit_loc_rejected(db).await;
913 });
914 }
915
916 #[test_traced("INFO")]
917 fn test_keyless_fixed_chained_apply_with_valid_floors_succeeds_mmb() {
918 deterministic::Runner::default().start(|ctx| async move {
919 let db = open_db::<mmb::Family>(ctx.child("db")).await;
920 tests::test_keyless_db_chained_apply_with_valid_floors_succeeds(db).await;
921 });
922 }
923
924 #[test_traced("INFO")]
925 fn test_keyless_fixed_single_commit_live_set_mmb() {
926 deterministic::Runner::default().start(|ctx| async move {
927 let db = open_db::<mmb::Family>(ctx.child("db").with_attribute("index", 1)).await;
928 tests::test_keyless_db_single_commit_live_set(ctx, db, reopen::<mmb::Family>()).await;
929 });
930 }
931
932 #[test_traced("WARN")]
936 fn test_keyless_fixed_sync() {
937 use crate::{
938 merkle::Location,
939 qmdb::sync::{self, engine::Config, Target},
940 };
941 use commonware_utils::{non_empty_range, sequence::U64};
942 use std::sync::Arc;
943
944 deterministic::Runner::default().start(|ctx| async move {
945 let target_config = db_config("sync-target", &ctx, Sequential);
946 let mut target_db: TestDb<mmr::Family> =
947 TestDb::init(ctx.child("target"), target_config)
948 .await
949 .unwrap();
950
951 let mut batch = target_db.new_batch();
952 for i in 0..20u64 {
953 batch = batch.append(U64::new(i * 10 + 1));
954 }
955 let floor = target_db.inactivity_floor_loc();
956 let merkleized = batch.merkleize(&target_db, None, floor);
957 target_db.apply_batch(merkleized).await.unwrap();
958
959 let target_root = target_db.root();
960 let bounds = target_db.bounds().await;
961 let lower_bound = bounds.start;
962 let upper_bound = bounds.end;
963
964 let client_config = db_config("sync-client", &ctx, Sequential);
965 let target_db = Arc::new(target_db);
966 let config = Config {
967 db_config: client_config,
968 fetch_batch_size: NZU64!(5),
969 target: Target {
970 root: target_root,
971 range: non_empty_range!(lower_bound, upper_bound),
972 },
973 context: ctx.child("client"),
974 resolver: target_db.clone(),
975 apply_batch_size: 1024,
976 max_outstanding_requests: 1,
977 update_rx: None,
978 finish_rx: None,
979 reached_target_tx: None,
980 max_retained_roots: 8,
981 };
982 let synced_db: TestDb<mmr::Family> = sync::sync(config).await.unwrap();
983
984 assert_eq!(synced_db.root(), target_root);
985 let bounds = synced_db.bounds().await;
986 assert_eq!(bounds.end, upper_bound);
987 assert_eq!(bounds.start, lower_bound);
988
989 for i in 0..20u64 {
990 let got = synced_db.get(Location::new(i + 1)).await.unwrap();
991 assert_eq!(got, Some(U64::new(i * 10 + 1)));
992 }
993
994 synced_db.destroy().await.unwrap();
995 let target_db =
996 Arc::try_unwrap(target_db).unwrap_or_else(|_| panic!("failed to unwrap Arc"));
997 target_db.destroy().await.unwrap();
998 });
999 }
1000}