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