use crate::{ marshal::{ ancestry::BlockProvider, coding::{ shards, types::{CodedBlock, CodedBlockCfg, StoredCodedBlock}, }, core::{Buffer, CommitmentFallback, Mailbox, Variant}, }, simplex::types::Context, types::{coding::Commitment, Round}, CertifiableBlock, }; use commonware_codec::Read; use commonware_coding::Scheme as CodingScheme; use commonware_cryptography::{certificate::Scheme, Committable, Digestible, Hasher, PublicKey}; use commonware_p2p::Recipients; use commonware_utils::channel::oneshot; use std::future::Future; /// The coding variant of Marshal, which uses erasure coding for block dissemination. /// /// This variant distributes blocks as erasure-coded shards, allowing reconstruction /// from a subset of shards. This reduces bandwidth requirements for block propagation. #[derive(Default, Clone, Copy)] pub struct Coding(std::marker::PhantomData<(B, C, H, P)>) where B: CertifiableBlock>, C: CodingScheme, H: Hasher, P: PublicKey; impl Variant for Coding where B: CertifiableBlock>, C: CodingScheme, H: Hasher, P: PublicKey, { type ApplicationBlock = B; type Block = CodedBlock; type StoredBlock = StoredCodedBlock; type Commitment = Commitment; fn commitment(block: &Self::Block) -> Self::Commitment { // Commitment is deterministic from the coded block contents. block.commitment() } fn commitment_to_inner(commitment: Self::Commitment) -> ::Digest { // The inner digest is embedded in the coding commitment. commitment.block() } fn parent_commitment(block: &Self::Block) -> Self::Commitment { // Parent commitment is embedded in the consensus context. block.context().parent.1 } fn block_cfg( block_cfg: &::Cfg, expected: Self::Commitment, ) -> ::Cfg { CodedBlockCfg { inner: block_cfg.clone(), expected, } } fn into_inner(block: Self::Block) -> Self::ApplicationBlock { block.into_inner() } } impl Buffer> for shards::Mailbox where B: CertifiableBlock>, C: CodingScheme, H: Hasher, P: PublicKey, { type PublicKey = P; async fn find_by_digest( &self, digest: as Digestible>::Digest, ) -> Option> { self.get_by_digest(digest).await } async fn find_by_commitment(&self, commitment: Commitment) -> Option> { self.get(commitment).await } fn subscribe_by_digest( &self, digest: as Digestible>::Digest, ) -> Option>> { Some(self.subscribe_by_digest(digest)) } fn subscribe_by_commitment( &self, commitment: Commitment, ) -> Option>> { Some(self.subscribe(commitment)) } fn finalized(&self, commitment: Commitment) { self.prune(commitment); } fn send(&self, round: Round, block: CodedBlock, _recipients: Recipients

) { // Targeted forwarding is not supported by the coding variant. self.proposed(round, block); } } impl BlockProvider for Mailbox> where S: Scheme, B: CertifiableBlock>, C: CodingScheme, H: Hasher, P: PublicKey, { type Block = B; fn subscribe_parent( &self, block: &Self::Block, ) -> impl Future> + Send + 'static { let receiver = block.height().previous().map(|parent_height| { self.subscribe_by_commitment( block.context().parent.1, CommitmentFallback::FetchByCommitment { height: parent_height, }, ) }); async move { let receiver = receiver?; receiver .await .ok() .map( as Variant>::into_inner) } } }