use crate::{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};
pub trait Variant: Clone + Send + Sync + 'static {
type Block: Block<Digest = <Self::ApplicationBlock as Digestible>::Digest>
+ Into<Self::StoredBlock>
+ Clone;
type ApplicationBlock: Block + Clone;
type StoredBlock: Block<Digest = <Self::Block as Digestible>::Digest>
+ Into<Self::Block>
+ Clone
+ Codec<Cfg = <Self::ApplicationBlock as Read>::Cfg>;
type Commitment: Digest;
fn commitment(block: &Self::Block) -> Self::Commitment;
fn commitment_to_inner(commitment: Self::Commitment) -> <Self::Block as Digestible>::Digest;
fn parent_commitment(block: &Self::Block) -> 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;
}
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<V::Block>> + Send;
fn find_by_commitment(
&self,
commitment: V::Commitment,
) -> impl Future<Output = Option<V::Block>> + Send;
fn subscribe_by_digest(
&self,
digest: <V::Block as Digestible>::Digest,
) -> Option<oneshot::Receiver<V::Block>>;
fn subscribe_by_commitment(
&self,
commitment: V::Commitment,
) -> Option<oneshot::Receiver<V::Block>>;
fn finalized(&self, commitment: V::Commitment);
fn send(&self, round: Round, block: 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<V::Block> {
None
}
async fn find_by_commitment(&self, _: V::Commitment) -> Option<V::Block> {
None
}
fn subscribe_by_digest(
&self,
_: <V::Block as Digestible>::Digest,
) -> Option<oneshot::Receiver<V::Block>> {
None
}
fn subscribe_by_commitment(&self, _: V::Commitment) -> Option<oneshot::Receiver<V::Block>> {
None
}
fn finalized(&self, _: V::Commitment) {}
fn send(&self, _: Round, _: V::Block, _: Recipients<Self::PublicKey>) {}
}