use crate::{
journal::contiguous::Mutable,
merkle::{Family, Location, Proof},
qmdb::{operation::Key, Error},
Persistable,
};
use commonware_codec::CodecShared;
use commonware_cryptography::Digest;
use core::num::NonZeroU64;
use std::{future::Future, ops::Range};
pub(crate) trait PersistableMutableLog<O>:
Mutable<Item = O> + Persistable<Error = crate::journal::Error>
{
}
impl<T, O> PersistableMutableLog<O> for T where
T: Mutable<Item = O> + Persistable<Error = crate::journal::Error>
{
}
pub trait UnmerkleizedBatch<Db: ?Sized>: Sized {
type Family: Family;
type K;
type V;
type Metadata;
type Merkleized: MerkleizedBatch;
fn write(self, key: Self::K, value: Option<Self::V>) -> Self;
fn merkleize(
self,
db: &Db,
metadata: Option<Self::Metadata>,
) -> impl Future<Output = Result<Self::Merkleized, Error<Self::Family>>>;
}
pub trait MerkleizedBatch: Sized {
type Digest: Digest;
fn root(&self) -> Self::Digest;
}
pub trait BatchableDb {
type Family: Family;
type K;
type V;
type Merkleized: MerkleizedBatch;
type Batch: UnmerkleizedBatch<
Self,
Family = Self::Family,
K = Self::K,
V = Self::V,
Metadata = Self::V,
Merkleized = Self::Merkleized,
>;
fn new_batch(&self) -> Self::Batch;
fn apply_batch(
&mut self,
batch: Self::Merkleized,
) -> impl Future<Output = Result<Range<Location<Self::Family>>, Error<Self::Family>>>;
}
pub trait DbAny<F: Family>:
BatchableDb<Family = F, K = <Self as DbAny<F>>::Key, V = <Self as DbAny<F>>::Value>
+ Persistable<Error = Error<F>>
+ Send
+ Sync
{
type Key: Key;
type Value: CodecShared + Clone;
type Digest: Digest;
fn get<'a>(
&'a self,
key: &'a Self::Key,
) -> impl Future<Output = Result<Option<Self::Value>, Error<F>>> + Send + use<'a, F, Self>;
fn root(&self) -> Self::Digest;
fn bounds(&self) -> impl Future<Output = Range<Location<F>>> + Send;
fn size(&self) -> impl Future<Output = Location<F>> + Send {
async { self.bounds().await.end }
}
fn get_metadata(
&self,
) -> impl Future<Output = Result<Option<<Self as DbAny<F>>::Value>, Error<F>>> + Send;
fn prune(&mut self, loc: Location<F>) -> impl Future<Output = Result<(), Error<F>>> + Send;
fn inactivity_floor_loc(&self) -> impl Future<Output = Location<F>> + Send;
}
pub trait Provable<F: Family>: DbAny<F> {
type Operation;
#[allow(clippy::type_complexity)]
fn proof(
&self,
start_loc: Location<F>,
max_ops: NonZeroU64,
) -> impl Future<Output = Result<(Proof<F, Self::Digest>, Vec<Self::Operation>), Error<F>>> + Send
{
async move {
self.historical_proof(self.bounds().await.end, start_loc, max_ops)
.await
}
}
#[allow(clippy::type_complexity)]
fn historical_proof(
&self,
historical_size: Location<F>,
start_loc: Location<F>,
max_ops: NonZeroU64,
) -> impl Future<Output = Result<(Proof<F, Self::Digest>, Vec<Self::Operation>), Error<F>>> + Send;
}
macro_rules! impl_db_any {
(
[$($gen:tt)*] $ty:ty
where { $($where_clause:tt)* }
Family = $fam:ty, Key = $key:ty, Value = $val:ty, Digest = $dig:ty
) => {
impl<$($gen)*> $crate::qmdb::any::traits::DbAny<$fam> for $ty
where $($where_clause)*
{
type Key = $key;
type Value = $val;
type Digest = $dig;
async fn get(&self, key: &$key) -> ::core::result::Result<Option<$val>, $crate::qmdb::Error<$fam>> {
self.get(key).await
}
fn root(&self) -> $dig {
self.root()
}
async fn bounds(&self) -> ::std::ops::Range<$crate::merkle::Location<$fam>> {
self.bounds().await
}
async fn get_metadata(
&self,
) -> ::core::result::Result<Option<$val>, $crate::qmdb::Error<$fam>> {
self.get_metadata().await
}
async fn prune(
&mut self,
loc: $crate::merkle::Location<$fam>,
) -> ::core::result::Result<(), $crate::qmdb::Error<$fam>> {
self.prune(loc).await
}
async fn inactivity_floor_loc(&self) -> $crate::merkle::Location<$fam> {
self.inactivity_floor_loc()
}
}
};
}
pub(crate) use impl_db_any;
macro_rules! impl_provable {
(
[$($gen:tt)*] $ty:ty
where { $($where_clause:tt)* }
Family = $fam:ty, Operation = $op:ty
) => {
impl<$($gen)*> $crate::qmdb::any::traits::Provable<$fam> for $ty
where $($where_clause)*
{
type Operation = $op;
async fn historical_proof(
&self,
historical_size: $crate::merkle::Location<$fam>,
start_loc: $crate::merkle::Location<$fam>,
max_ops: ::core::num::NonZeroU64,
) -> ::core::result::Result<
($crate::merkle::Proof<$fam, <Self as $crate::qmdb::any::traits::DbAny<$fam>>::Digest>, Vec<$op>),
$crate::qmdb::Error<$fam>,
> {
self.historical_proof(historical_size, start_loc, max_ops)
.await
}
}
};
}
pub(crate) use impl_provable;