use crate::{
marshal::{
ancestry::BlockProvider,
core::{Buffer, CommitmentFallback, Mailbox, Variant},
},
types::Round,
Block,
};
use commonware_broadcast::{buffered, Broadcaster};
use commonware_codec::Read;
use commonware_cryptography::{certificate::Scheme, Digestible, PublicKey};
use commonware_p2p::Recipients;
use commonware_utils::channel::oneshot;
use std::future::Future;
#[derive(Default, Clone, Copy)]
pub struct Standard<B: Block>(std::marker::PhantomData<B>);
impl<B> Variant for Standard<B>
where
B: Block,
{
type ApplicationBlock = B;
type Block = B;
type StoredBlock = B;
type Commitment = <B as Digestible>::Digest;
fn commitment(block: &Self::Block) -> Self::Commitment {
block.digest()
}
fn commitment_to_inner(commitment: Self::Commitment) -> <Self::Block as Digestible>::Digest {
commitment
}
fn parent_commitment(block: &Self::Block) -> Self::Commitment {
block.parent()
}
fn block_cfg(
block_cfg: &<Self::ApplicationBlock as Read>::Cfg,
_expected: Self::Commitment,
) -> <Self::Block as Read>::Cfg {
block_cfg.clone()
}
fn into_inner(block: Self::Block) -> Self::ApplicationBlock {
block
}
}
impl<B, K> Buffer<Standard<B>> for buffered::Mailbox<K, B>
where
B: Block,
K: PublicKey,
{
type PublicKey = K;
async fn find_by_digest(&self, digest: B::Digest) -> Option<B> {
self.get(digest).await
}
async fn find_by_commitment(&self, commitment: B::Digest) -> Option<B> {
self.find_by_digest(commitment).await
}
fn subscribe_by_digest(&self, digest: B::Digest) -> Option<oneshot::Receiver<B>> {
let (tx, rx) = oneshot::channel();
self.subscribe_prepared(digest, tx);
Some(rx)
}
fn subscribe_by_commitment(&self, commitment: B::Digest) -> Option<oneshot::Receiver<B>> {
self.subscribe_by_digest(commitment)
}
fn finalized(&self, _commitment: B::Digest) {
}
fn send(&self, _round: Round, block: B, recipients: Recipients<K>) {
Broadcaster::broadcast(self, recipients, block);
}
}
impl<S, B> BlockProvider for Mailbox<S, Standard<B>>
where
S: Scheme,
B: Block,
{
type Block = B;
fn subscribe_parent(
&self,
block: &Self::Block,
) -> impl Future<Output = Option<Self::Block>> + Send + 'static {
let receiver = block.height().previous().map(|parent_height| {
self.subscribe_by_commitment(
block.parent(),
CommitmentFallback::FetchByCommitment {
height: parent_height,
},
)
});
async move {
let receiver = receiver?;
receiver.await.ok()
}
}
}