use crate::{simplex::scheme::Scheme, types::Round, Block};
use commonware_codec::{Codec, Read};
use commonware_cryptography::{Digest, Digestible, PublicKey};
use commonware_p2p::Recipients;
use commonware_utils::channel::oneshot;
use std::{future::Future, marker::PhantomData, sync::Arc};
pub trait Variant: Clone + Send + Sync + 'static {
type Block: Block<Digest = <Self::ApplicationBlock as Digestible>::Digest>
+ Into<Self::StoredBlock>;
type ApplicationBlock: Block;
type StoredBlock: Block<Digest = <Self::Block as Digestible>::Digest>
+ Into<Self::Block>
+ Codec<Cfg = <Self::ApplicationBlock as Read>::Cfg>;
type Commitment: Digest;
fn commitment(block: &Self::Block) -> Self::Commitment;
fn stored_commitment(block: &Self::StoredBlock) -> Self::Commitment;
fn commitment_to_inner(commitment: Self::Commitment) -> <Self::Block as Digestible>::Digest;
fn parent_commitment(block: &Self::Block) -> Self::Commitment;
fn check_payload<S>(scheme: &S, payload: Self::Commitment) -> bool
where
S: Scheme<Self::Commitment>;
fn block_cfg(
block_cfg: &<Self::ApplicationBlock as Read>::Cfg,
expected: Self::Commitment,
) -> <Self::Block as Read>::Cfg;
fn into_inner(block: Self::Block) -> Self::ApplicationBlock;
fn into_inner_shared(block: Arc<Self::Block>) -> Arc<Self::ApplicationBlock>;
fn owned_into_inner_shared(block: Self::Block) -> Arc<Self::ApplicationBlock>;
fn from_application_block(
block: Self::ApplicationBlock,
payload: Self::Commitment,
) -> Self::Block;
}
pub trait Buffer<V: Variant>: Clone + Send + Sync + 'static {
type PublicKey: PublicKey;
fn find_by_digest(
&self,
digest: <V::Block as Digestible>::Digest,
) -> impl Future<Output = Option<Arc<V::Block>>> + Send;
fn find_by_commitment(
&self,
commitment: V::Commitment,
) -> impl Future<Output = Option<Arc<V::Block>>> + Send;
fn subscribe_by_digest(
&self,
digest: <V::Block as Digestible>::Digest,
) -> Option<oneshot::Receiver<Arc<V::Block>>>;
fn subscribe_by_commitment(
&self,
commitment: V::Commitment,
) -> Option<oneshot::Receiver<Arc<V::Block>>>;
fn finalized(&self, commitment: V::Commitment);
fn send(&self, round: Round, block: Arc<V::Block>, recipients: Recipients<Self::PublicKey>);
}
pub(super) struct NoBuffer<P> {
_public_key: PhantomData<fn() -> P>,
}
impl<P> NoBuffer<P> {
pub(super) const fn new() -> Self {
Self {
_public_key: PhantomData,
}
}
}
impl<P> Clone for NoBuffer<P> {
fn clone(&self) -> Self {
*self
}
}
impl<P> Copy for NoBuffer<P> {}
impl<V, P> Buffer<V> for NoBuffer<P>
where
V: Variant,
P: PublicKey,
{
type PublicKey = P;
async fn find_by_digest(&self, _: <V::Block as Digestible>::Digest) -> Option<Arc<V::Block>> {
None
}
async fn find_by_commitment(&self, _: V::Commitment) -> Option<Arc<V::Block>> {
None
}
fn subscribe_by_digest(
&self,
_: <V::Block as Digestible>::Digest,
) -> Option<oneshot::Receiver<Arc<V::Block>>> {
None
}
fn subscribe_by_commitment(
&self,
_: V::Commitment,
) -> Option<oneshot::Receiver<Arc<V::Block>>> {
None
}
fn finalized(&self, _: V::Commitment) {}
fn send(&self, _: Round, _: Arc<V::Block>, _: Recipients<Self::PublicKey>) {}
}