1use crate::{
2 merkle::{Family, Location, Proof},
3 qmdb::{
4 self,
5 any::{
6 ordered::{
7 fixed::{Db as OrderedFixedDb, Operation as OrderedFixedOperation},
8 variable::{Db as OrderedVariableDb, Operation as OrderedVariableOperation},
9 },
10 unordered::{
11 fixed::{Db as FixedDb, Operation as FixedOperation},
12 variable::{Db as VariableDb, Operation as VariableOperation},
13 },
14 FixedValue, VariableValue,
15 },
16 immutable::{
17 fixed::{Db as ImmutableFixedDb, Operation as ImmutableFixedOp},
18 variable::{Db as ImmutableVariableDb, Operation as ImmutableVariableOp},
19 },
20 keyless::{
21 fixed::{Db as KeylessFixedDb, Operation as KeylessFixedOp},
22 variable::{Db as KeylessVariableDb, Operation as KeylessVariableOp},
23 },
24 operation::Key,
25 },
26 translator::Translator,
27 Context,
28};
29use commonware_cryptography::{Digest, Hasher};
30use commonware_parallel::Strategy;
31use commonware_utils::{
32 channel::oneshot,
33 sync::{AsyncRwLock, TracedAsyncRwLock},
34 Array,
35};
36use std::{future::Future, num::NonZeroU64, sync::Arc};
37
38pub struct FetchResult<F: Family, Op, D: Digest> {
40 pub proof: Proof<F, D>,
42 pub operations: Vec<Op>,
44 pub pinned_nodes: Option<Vec<D>>,
46 pub callback: Option<oneshot::Sender<bool>>,
48}
49
50impl<F: Family, Op, D: Digest> FetchResult<F, Op, D> {
51 pub const fn new(
53 proof: Proof<F, D>,
54 operations: Vec<Op>,
55 pinned_nodes: Option<Vec<D>>,
56 ) -> Self {
57 Self {
58 proof,
59 operations,
60 pinned_nodes,
61 callback: None,
62 }
63 }
64
65 pub const fn with_callback(
67 proof: Proof<F, D>,
68 operations: Vec<Op>,
69 pinned_nodes: Option<Vec<D>>,
70 callback: oneshot::Sender<bool>,
71 ) -> Self {
72 Self {
73 proof,
74 operations,
75 pinned_nodes,
76 callback: Some(callback),
77 }
78 }
79}
80
81pub struct FetchedOperations<F: Family, Op, D: Digest> {
83 pub proof: Proof<F, D>,
85 pub operations: Vec<Op>,
87 pub pinned_nodes: Option<Vec<D>>,
89}
90
91impl<F: Family, Op, D: Digest> FetchedOperations<F, Op, D> {
92 pub const fn new(
94 proof: Proof<F, D>,
95 operations: Vec<Op>,
96 pinned_nodes: Option<Vec<D>>,
97 ) -> Self {
98 Self {
99 proof,
100 operations,
101 pinned_nodes,
102 }
103 }
104}
105
106impl<F: Family, Op: std::fmt::Debug, D: Digest> std::fmt::Debug for FetchResult<F, Op, D> {
107 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108 f.debug_struct("FetchResult")
109 .field("proof", &self.proof)
110 .field("operations", &self.operations)
111 .field("pinned_nodes", &self.pinned_nodes)
112 .field("callback", &self.callback.as_ref().map(|_| "<callback>"))
113 .finish()
114 }
115}
116
117pub async fn fetch_operation_range<F, Op, D, Error, Fetch, FetchFuture>(
123 op_count: Location<F>,
124 start_loc: Location<F>,
125 max_ops: NonZeroU64,
126 include_pinned_nodes: bool,
127 fetch: Fetch,
128) -> Result<FetchResult<F, Op, D>, Error>
129where
130 F: Family,
131 D: Digest,
132 Fetch: FnOnce(Location<F>, Location<F>, NonZeroU64, bool) -> FetchFuture,
133 FetchFuture: Future<Output = Result<FetchedOperations<F, Op, D>, Error>>,
134{
135 let FetchedOperations {
136 proof,
137 operations,
138 pinned_nodes,
139 } = fetch(op_count, start_loc, max_ops, include_pinned_nodes).await?;
140 Ok(FetchResult::new(proof, operations, pinned_nodes))
141}
142
143pub async fn fetch_operations<
149 F,
150 Op,
151 D,
152 Error,
153 HistoricalProof,
154 HistoricalFuture,
155 Pins,
156 PinsFuture,
157>(
158 op_count: Location<F>,
159 start_loc: Location<F>,
160 max_ops: NonZeroU64,
161 include_pinned_nodes: bool,
162 historical_proof: HistoricalProof,
163 pinned_nodes_at: Pins,
164) -> Result<FetchResult<F, Op, D>, Error>
165where
166 F: Family,
167 D: Digest,
168 HistoricalProof: FnOnce(Location<F>, Location<F>, NonZeroU64) -> HistoricalFuture,
169 HistoricalFuture: Future<Output = Result<(Proof<F, D>, Vec<Op>), Error>>,
170 Pins: FnOnce(Location<F>) -> PinsFuture,
171 PinsFuture: Future<Output = Result<Vec<D>, Error>>,
172{
173 fetch_operation_range(
174 op_count,
175 start_loc,
176 max_ops,
177 include_pinned_nodes,
178 |op_count, start_loc, max_ops, include_pinned_nodes| async move {
179 let (proof, operations) = historical_proof(op_count, start_loc, max_ops).await?;
180 let pinned_nodes = if include_pinned_nodes {
181 Some(pinned_nodes_at(start_loc).await?)
182 } else {
183 None
184 };
185 Ok(FetchedOperations::new(proof, operations, pinned_nodes))
186 },
187 )
188 .await
189}
190
191pub trait Resolver: Send + Sync + Clone + 'static {
193 type Family: Family;
195
196 type Digest: Digest;
198
199 type Op;
201
202 type Error: std::error::Error + Send + 'static;
204
205 #[allow(clippy::type_complexity)]
214 fn get_operations<'a>(
215 &'a self,
216 op_count: Location<Self::Family>,
217 start_loc: Location<Self::Family>,
218 max_ops: NonZeroU64,
219 include_pinned_nodes: bool,
220 cancel_rx: oneshot::Receiver<()>,
221 ) -> impl Future<Output = Result<FetchResult<Self::Family, Self::Op, Self::Digest>, Self::Error>>
222 + Send
223 + 'a;
224}
225
226macro_rules! impl_resolver {
227 ($db:ident, $op:ident, $val_bound:ident) => {
228 impl<F, E, K, V, H, T, S> Resolver for Arc<$db<F, E, K, V, H, T, S>>
229 where
230 F: Family,
231 E: Context,
232 K: Array,
233 V: $val_bound + Send + Sync + 'static,
234 H: Hasher,
235 T: Translator + Send + Sync + 'static,
236 T::Key: Send + Sync,
237 S: Strategy,
238 {
239 type Family = F;
240 type Digest = H::Digest;
241 type Op = $op<F, K, V>;
242 type Error = qmdb::Error<F>;
243
244 async fn get_operations(
245 &self,
246 op_count: Location<Self::Family>,
247 start_loc: Location<Self::Family>,
248 max_ops: NonZeroU64,
249 include_pinned_nodes: bool,
250 _cancel_rx: oneshot::Receiver<()>,
251 ) -> Result<FetchResult<Self::Family, Self::Op, Self::Digest>, Self::Error> {
252 fetch_operations(
253 op_count,
254 start_loc,
255 max_ops,
256 include_pinned_nodes,
257 |op_count, start_loc, max_ops| {
258 self.historical_proof(op_count, start_loc, max_ops)
259 },
260 |start_loc| self.pinned_nodes_at(start_loc),
261 )
262 .await
263 }
264 }
265 impl_resolver!(@locked $db, $op, $val_bound, AsyncRwLock);
266 impl_resolver!(@locked $db, $op, $val_bound, TracedAsyncRwLock);
267 };
268 (@locked $db:ident, $op:ident, $val_bound:ident, $lock:ident) => {
269
270 impl<F, E, K, V, H, T, S> Resolver for Arc<$lock<$db<F, E, K, V, H, T, S>>>
271 where
272 F: Family,
273 E: Context,
274 K: Array,
275 V: $val_bound + Send + Sync + 'static,
276 H: Hasher,
277 T: Translator + Send + Sync + 'static,
278 T::Key: Send + Sync,
279 S: Strategy,
280 {
281 type Family = F;
282 type Digest = H::Digest;
283 type Op = $op<F, K, V>;
284 type Error = qmdb::Error<F>;
285
286 async fn get_operations(
287 &self,
288 op_count: Location<Self::Family>,
289 start_loc: Location<Self::Family>,
290 max_ops: NonZeroU64,
291 include_pinned_nodes: bool,
292 _cancel_rx: oneshot::Receiver<()>,
293 ) -> Result<FetchResult<Self::Family, Self::Op, Self::Digest>, Self::Error> {
294 let db = self.read().await;
295 fetch_operations(
296 op_count,
297 start_loc,
298 max_ops,
299 include_pinned_nodes,
300 |op_count, start_loc, max_ops| {
301 db.historical_proof(op_count, start_loc, max_ops)
302 },
303 |start_loc| db.pinned_nodes_at(start_loc),
304 )
305 .await
306 }
307 }
308
309 impl<F, E, K, V, H, T, S> Resolver for Arc<$lock<Option<$db<F, E, K, V, H, T, S>>>>
310 where
311 F: Family,
312 E: Context,
313 K: Array,
314 V: $val_bound + Send + Sync + 'static,
315 H: Hasher,
316 T: Translator + Send + Sync + 'static,
317 T::Key: Send + Sync,
318 S: Strategy,
319 {
320 type Family = F;
321 type Digest = H::Digest;
322 type Op = $op<F, K, V>;
323 type Error = qmdb::Error<F>;
324
325 async fn get_operations(
326 &self,
327 op_count: Location<Self::Family>,
328 start_loc: Location<Self::Family>,
329 max_ops: NonZeroU64,
330 include_pinned_nodes: bool,
331 _cancel_rx: oneshot::Receiver<()>,
332 ) -> Result<FetchResult<Self::Family, Self::Op, Self::Digest>, Self::Error> {
333 let guard = self.read().await;
334 let db = guard.as_ref().ok_or(qmdb::Error::KeyNotFound)?;
335 fetch_operations(
336 op_count,
337 start_loc,
338 max_ops,
339 include_pinned_nodes,
340 |op_count, start_loc, max_ops| {
341 db.historical_proof(op_count, start_loc, max_ops)
342 },
343 |start_loc| db.pinned_nodes_at(start_loc),
344 )
345 .await
346 }
347 }
348 };
349}
350
351impl_resolver!(FixedDb, FixedOperation, FixedValue);
353
354impl_resolver!(VariableDb, VariableOperation, VariableValue);
356
357impl_resolver!(OrderedFixedDb, OrderedFixedOperation, FixedValue);
359
360impl_resolver!(OrderedVariableDb, OrderedVariableOperation, VariableValue);
362
363macro_rules! impl_resolver_immutable {
367 ($db:ident, $op:ident, $val_bound:ident, $key_bound:path) => {
368 impl<F, E, K, V, H, T, S> Resolver for Arc<$db<F, E, K, V, H, T, S>>
369 where
370 F: Family,
371 E: Context,
372 K: $key_bound,
373 V: $val_bound + Send + Sync + 'static,
374 H: Hasher,
375 T: Translator + Send + Sync + 'static,
376 T::Key: Send + Sync,
377 S: Strategy,
378 {
379 type Family = F;
380 type Digest = H::Digest;
381 type Op = $op<F, K, V>;
382 type Error = qmdb::Error<F>;
383
384 async fn get_operations(
385 &self,
386 op_count: Location<Self::Family>,
387 start_loc: Location<Self::Family>,
388 max_ops: NonZeroU64,
389 include_pinned_nodes: bool,
390 _cancel_rx: oneshot::Receiver<()>,
391 ) -> Result<FetchResult<Self::Family, Self::Op, Self::Digest>, Self::Error> {
392 fetch_operations(
393 op_count,
394 start_loc,
395 max_ops,
396 include_pinned_nodes,
397 |op_count, start_loc, max_ops| {
398 self.historical_proof(op_count, start_loc, max_ops)
399 },
400 |start_loc| self.pinned_nodes_at(start_loc),
401 )
402 .await
403 }
404 }
405 impl_resolver_immutable!(@locked $db, $op, $val_bound, $key_bound, AsyncRwLock);
406 impl_resolver_immutable!(@locked $db, $op, $val_bound, $key_bound, TracedAsyncRwLock);
407 };
408 (@locked $db:ident, $op:ident, $val_bound:ident, $key_bound:path, $lock:ident) => {
409
410 impl<F, E, K, V, H, T, S> Resolver for Arc<$lock<$db<F, E, K, V, H, T, S>>>
411 where
412 F: Family,
413 E: Context,
414 K: $key_bound,
415 V: $val_bound + Send + Sync + 'static,
416 H: Hasher,
417 T: Translator + Send + Sync + 'static,
418 T::Key: Send + Sync,
419 S: Strategy,
420 {
421 type Family = F;
422 type Digest = H::Digest;
423 type Op = $op<F, K, V>;
424 type Error = qmdb::Error<F>;
425
426 async fn get_operations(
427 &self,
428 op_count: Location<Self::Family>,
429 start_loc: Location<Self::Family>,
430 max_ops: NonZeroU64,
431 include_pinned_nodes: bool,
432 _cancel_rx: oneshot::Receiver<()>,
433 ) -> Result<FetchResult<Self::Family, Self::Op, Self::Digest>, Self::Error> {
434 let db = self.read().await;
435 fetch_operations(
436 op_count,
437 start_loc,
438 max_ops,
439 include_pinned_nodes,
440 |op_count, start_loc, max_ops| {
441 db.historical_proof(op_count, start_loc, max_ops)
442 },
443 |start_loc| db.pinned_nodes_at(start_loc),
444 )
445 .await
446 }
447 }
448
449 impl<F, E, K, V, H, T, S> Resolver for Arc<$lock<Option<$db<F, E, K, V, H, T, S>>>>
450 where
451 F: Family,
452 E: Context,
453 K: $key_bound,
454 V: $val_bound + Send + Sync + 'static,
455 H: Hasher,
456 T: Translator + Send + Sync + 'static,
457 T::Key: Send + Sync,
458 S: Strategy,
459 {
460 type Family = F;
461 type Digest = H::Digest;
462 type Op = $op<F, K, V>;
463 type Error = qmdb::Error<F>;
464
465 async fn get_operations(
466 &self,
467 op_count: Location<Self::Family>,
468 start_loc: Location<Self::Family>,
469 max_ops: NonZeroU64,
470 include_pinned_nodes: bool,
471 _cancel_rx: oneshot::Receiver<()>,
472 ) -> Result<FetchResult<Self::Family, Self::Op, Self::Digest>, Self::Error> {
473 let guard = self.read().await;
474 let db = guard.as_ref().ok_or(qmdb::Error::KeyNotFound)?;
475 fetch_operations(
476 op_count,
477 start_loc,
478 max_ops,
479 include_pinned_nodes,
480 |op_count, start_loc, max_ops| {
481 db.historical_proof(op_count, start_loc, max_ops)
482 },
483 |start_loc| db.pinned_nodes_at(start_loc),
484 )
485 .await
486 }
487 }
488 };
489}
490
491impl_resolver_immutable!(ImmutableFixedDb, ImmutableFixedOp, FixedValue, Array);
493
494impl_resolver_immutable!(ImmutableVariableDb, ImmutableVariableOp, VariableValue, Key);
496
497macro_rules! impl_resolver_keyless {
499 ($db:ident, $op:ident, $val_bound:ident) => {
500 impl<F, E, V, H, S> Resolver for Arc<$db<F, E, V, H, S>>
501 where
502 F: Family,
503 E: Context,
504 V: $val_bound + Send + Sync + 'static,
505 H: Hasher,
506 S: Strategy,
507 {
508 type Family = F;
509 type Digest = H::Digest;
510 type Op = $op<F, V>;
511 type Error = qmdb::Error<F>;
512
513 async fn get_operations(
514 &self,
515 op_count: Location<Self::Family>,
516 start_loc: Location<Self::Family>,
517 max_ops: NonZeroU64,
518 include_pinned_nodes: bool,
519 _cancel_rx: oneshot::Receiver<()>,
520 ) -> Result<FetchResult<Self::Family, Self::Op, Self::Digest>, Self::Error> {
521 fetch_operations(
522 op_count,
523 start_loc,
524 max_ops,
525 include_pinned_nodes,
526 |op_count, start_loc, max_ops| {
527 self.historical_proof(op_count, start_loc, max_ops)
528 },
529 |start_loc| self.pinned_nodes_at(start_loc),
530 )
531 .await
532 }
533 }
534 impl_resolver_keyless!(@locked $db, $op, $val_bound, AsyncRwLock);
535 impl_resolver_keyless!(@locked $db, $op, $val_bound, TracedAsyncRwLock);
536 };
537 (@locked $db:ident, $op:ident, $val_bound:ident, $lock:ident) => {
538
539 impl<F, E, V, H, S> Resolver for Arc<$lock<$db<F, E, V, H, S>>>
540 where
541 F: Family,
542 E: Context,
543 V: $val_bound + Send + Sync + 'static,
544 H: Hasher,
545 S: Strategy,
546 {
547 type Family = F;
548 type Digest = H::Digest;
549 type Op = $op<F, V>;
550 type Error = qmdb::Error<F>;
551
552 async fn get_operations(
553 &self,
554 op_count: Location<Self::Family>,
555 start_loc: Location<Self::Family>,
556 max_ops: NonZeroU64,
557 include_pinned_nodes: bool,
558 _cancel_rx: oneshot::Receiver<()>,
559 ) -> Result<FetchResult<Self::Family, Self::Op, Self::Digest>, Self::Error> {
560 let db = self.read().await;
561 fetch_operations(
562 op_count,
563 start_loc,
564 max_ops,
565 include_pinned_nodes,
566 |op_count, start_loc, max_ops| {
567 db.historical_proof(op_count, start_loc, max_ops)
568 },
569 |start_loc| db.pinned_nodes_at(start_loc),
570 )
571 .await
572 }
573 }
574
575 impl<F, E, V, H, S> Resolver for Arc<$lock<Option<$db<F, E, V, H, S>>>>
576 where
577 F: Family,
578 E: Context,
579 V: $val_bound + Send + Sync + 'static,
580 H: Hasher,
581 S: Strategy,
582 {
583 type Family = F;
584 type Digest = H::Digest;
585 type Op = $op<F, V>;
586 type Error = qmdb::Error<F>;
587
588 async fn get_operations(
589 &self,
590 op_count: Location<Self::Family>,
591 start_loc: Location<Self::Family>,
592 max_ops: NonZeroU64,
593 include_pinned_nodes: bool,
594 _cancel_rx: oneshot::Receiver<()>,
595 ) -> Result<FetchResult<Self::Family, Self::Op, Self::Digest>, Self::Error> {
596 let guard = self.read().await;
597 let db = guard.as_ref().ok_or(qmdb::Error::KeyNotFound)?;
598 fetch_operations(
599 op_count,
600 start_loc,
601 max_ops,
602 include_pinned_nodes,
603 |op_count, start_loc, max_ops| {
604 db.historical_proof(op_count, start_loc, max_ops)
605 },
606 |start_loc| db.pinned_nodes_at(start_loc),
607 )
608 .await
609 }
610 }
611 };
612}
613
614impl_resolver_keyless!(KeylessFixedDb, KeylessFixedOp, FixedValue);
616
617impl_resolver_keyless!(KeylessVariableDb, KeylessVariableOp, VariableValue);
619
620#[cfg(test)]
621pub(crate) mod tests {
622 use super::*;
623 use crate::{
624 merkle::mmr,
625 translator::{OneCap, TwoCap},
626 };
627 use commonware_cryptography::{sha256::Digest as ShaDigest, Sha256};
628 use commonware_parallel::Rayon;
629 use commonware_runtime::deterministic;
630 use commonware_utils::sync::AsyncRwLock;
631 use std::{marker::PhantomData, sync::Arc};
632
633 macro_rules! assert_resolver_variants {
634 ($db:ty) => {
635 assert_resolver::<Arc<$db>>();
636 assert_resolver::<Arc<AsyncRwLock<$db>>>();
637 assert_resolver::<Arc<AsyncRwLock<Option<$db>>>>();
638 };
639 }
640
641 fn assert_resolver<R: Resolver>() {}
642
643 fn empty_proof() -> Proof<mmr::Family, ShaDigest> {
644 Proof {
645 leaves: Location::new(0),
646 inactive_peaks: 0,
647 digests: vec![],
648 }
649 }
650
651 #[test]
652 fn test_fetch_result_new_has_no_success_acknowledgement() {
653 let result = FetchResult::<mmr::Family, (), ShaDigest>::new(empty_proof(), vec![], None);
654 assert!(result.callback.is_none());
655 }
656
657 #[test]
658 fn test_fetch_result_with_callback_reports_to_external_receiver() {
659 let (success_tx, mut success_rx) = oneshot::channel();
660 let result = FetchResult::<mmr::Family, (), ShaDigest>::with_callback(
661 empty_proof(),
662 vec![],
663 None,
664 success_tx,
665 );
666 assert!(result.callback.expect("success sender").send(true).is_ok());
667 assert_eq!(success_rx.try_recv(), Ok(true));
668 }
669
670 #[derive(Clone)]
672 pub struct FailResolver<F: Family, Op, D> {
673 _phantom: PhantomData<(F, Op, D)>,
674 }
675
676 impl<F, Op, D> Resolver for FailResolver<F, Op, D>
677 where
678 F: Family,
679 D: Digest,
680 Op: Send + Sync + Clone + 'static,
681 {
682 type Family = F;
683 type Digest = D;
684 type Op = Op;
685 type Error = qmdb::Error<F>;
686
687 async fn get_operations(
688 &self,
689 _op_count: Location<F>,
690 _start_loc: Location<F>,
691 _max_ops: NonZeroU64,
692 _include_pinned_nodes: bool,
693 _cancel: oneshot::Receiver<()>,
694 ) -> Result<FetchResult<F, Op, D>, qmdb::Error<F>> {
695 Err(qmdb::Error::KeyNotFound) }
697 }
698
699 impl<F: Family, Op, D> FailResolver<F, Op, D> {
700 pub fn new() -> Self {
701 Self {
702 _phantom: PhantomData,
703 }
704 }
705 }
706
707 #[test]
708 fn test_all_qmdb_variants_implement_strategy_resolvers() {
709 type AnyOrderedFixed = crate::qmdb::any::ordered::fixed::Db<
710 mmr::Family,
711 deterministic::Context,
712 ShaDigest,
713 ShaDigest,
714 Sha256,
715 OneCap,
716 Rayon,
717 >;
718 type AnyOrderedVariable = crate::qmdb::any::ordered::variable::Db<
719 mmr::Family,
720 deterministic::Context,
721 ShaDigest,
722 Vec<u8>,
723 Sha256,
724 OneCap,
725 Rayon,
726 >;
727 type AnyUnorderedFixed = crate::qmdb::any::unordered::fixed::Db<
728 mmr::Family,
729 deterministic::Context,
730 ShaDigest,
731 ShaDigest,
732 Sha256,
733 TwoCap,
734 Rayon,
735 >;
736 type AnyUnorderedVariable = crate::qmdb::any::unordered::variable::Db<
737 mmr::Family,
738 deterministic::Context,
739 ShaDigest,
740 Vec<u8>,
741 Sha256,
742 TwoCap,
743 Rayon,
744 >;
745 type CurrentOrderedFixed = crate::qmdb::current::ordered::fixed::Db<
746 mmr::Family,
747 deterministic::Context,
748 ShaDigest,
749 ShaDigest,
750 Sha256,
751 OneCap,
752 32,
753 Rayon,
754 >;
755 type CurrentOrderedVariable = crate::qmdb::current::ordered::variable::Db<
756 mmr::Family,
757 deterministic::Context,
758 ShaDigest,
759 Vec<u8>,
760 Sha256,
761 OneCap,
762 32,
763 Rayon,
764 >;
765 type CurrentUnorderedFixed = crate::qmdb::current::unordered::fixed::Db<
766 mmr::Family,
767 deterministic::Context,
768 ShaDigest,
769 ShaDigest,
770 Sha256,
771 TwoCap,
772 32,
773 Rayon,
774 >;
775 type CurrentUnorderedVariable = crate::qmdb::current::unordered::variable::Db<
776 mmr::Family,
777 deterministic::Context,
778 ShaDigest,
779 Vec<u8>,
780 Sha256,
781 TwoCap,
782 32,
783 Rayon,
784 >;
785 type ImmutableFixed = crate::qmdb::immutable::fixed::Db<
786 mmr::Family,
787 deterministic::Context,
788 ShaDigest,
789 ShaDigest,
790 Sha256,
791 TwoCap,
792 Rayon,
793 >;
794 type ImmutableVariable = crate::qmdb::immutable::variable::Db<
795 mmr::Family,
796 deterministic::Context,
797 ShaDigest,
798 Vec<u8>,
799 Sha256,
800 TwoCap,
801 Rayon,
802 >;
803 type KeylessFixed = crate::qmdb::keyless::fixed::Db<
804 mmr::Family,
805 deterministic::Context,
806 ShaDigest,
807 Sha256,
808 Rayon,
809 >;
810 type KeylessVariable = crate::qmdb::keyless::variable::Db<
811 mmr::Family,
812 deterministic::Context,
813 Vec<u8>,
814 Sha256,
815 Rayon,
816 >;
817
818 assert_resolver_variants!(AnyOrderedFixed);
819 assert_resolver_variants!(AnyOrderedVariable);
820 assert_resolver_variants!(AnyUnorderedFixed);
821 assert_resolver_variants!(AnyUnorderedVariable);
822 assert_resolver_variants!(CurrentOrderedFixed);
823 assert_resolver_variants!(CurrentOrderedVariable);
824 assert_resolver_variants!(CurrentUnorderedFixed);
825 assert_resolver_variants!(CurrentUnorderedVariable);
826 assert_resolver_variants!(ImmutableFixed);
827 assert_resolver_variants!(ImmutableVariable);
828 assert_resolver_variants!(KeylessFixed);
829 assert_resolver_variants!(KeylessVariable);
830 }
831}