use crate::{ marshal::{ coding::{ shards, types::{CodedBlock, StoredCodedBlock}, }, core::{Buffer, Variant}, }, simplex::types::Context, types::{coding::Commitment, Round}, CertifiableBlock, }; use commonware_coding::Scheme as CodingScheme; use commonware_cryptography::{Committable, Digestible, Hasher, PublicKey}; use commonware_utils::channel::oneshot; use std::sync::Arc; /// 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 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 CachedBlock = Arc>; 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 } async fn subscribe_by_digest( &self, digest: as Digestible>::Digest, ) -> oneshot::Receiver { self.subscribe_by_digest(digest).await } async fn subscribe_by_commitment( &self, commitment: Commitment, ) -> oneshot::Receiver { self.subscribe(commitment).await } async fn finalized(&self, commitment: Commitment) { self.prune(commitment).await; } async fn proposed(&self, round: Round, block: CodedBlock) { self.proposed(round, block).await; } }