Skip to main content

commonware_consensus/marshal/coding/
variant.rs

1use crate::{
2    marshal::{
3        coding::{
4            shards,
5            types::{CodedBlock, StoredCodedBlock},
6        },
7        core::{Buffer, Variant},
8    },
9    simplex::types::Context,
10    types::{coding::Commitment, Round},
11    CertifiableBlock,
12};
13use commonware_coding::Scheme as CodingScheme;
14use commonware_cryptography::{Committable, Digestible, Hasher, PublicKey};
15use commonware_utils::channel::oneshot;
16use std::sync::Arc;
17
18/// The coding variant of Marshal, which uses erasure coding for block dissemination.
19///
20/// This variant distributes blocks as erasure-coded shards, allowing reconstruction
21/// from a subset of shards. This reduces bandwidth requirements for block propagation.
22#[derive(Default, Clone, Copy)]
23pub struct Coding<B, C, H, P>(std::marker::PhantomData<(B, C, H, P)>)
24where
25    B: CertifiableBlock<Context = Context<Commitment, P>>,
26    C: CodingScheme,
27    H: Hasher,
28    P: PublicKey;
29
30impl<B, C, H, P> Variant for Coding<B, C, H, P>
31where
32    B: CertifiableBlock<Context = Context<Commitment, P>>,
33    C: CodingScheme,
34    H: Hasher,
35    P: PublicKey,
36{
37    type ApplicationBlock = B;
38    type Block = CodedBlock<B, C, H>;
39    type StoredBlock = StoredCodedBlock<B, C, H>;
40    type Commitment = Commitment;
41
42    fn commitment(block: &Self::Block) -> Self::Commitment {
43        // Commitment is deterministic from the coded block contents.
44        block.commitment()
45    }
46
47    fn commitment_to_inner(commitment: Self::Commitment) -> <Self::Block as Digestible>::Digest {
48        // The inner digest is embedded in the coding commitment.
49        commitment.block()
50    }
51
52    fn parent_commitment(block: &Self::Block) -> Self::Commitment {
53        // Parent commitment is embedded in the consensus context.
54        block.context().parent.1
55    }
56
57    fn into_inner(block: Self::Block) -> Self::ApplicationBlock {
58        block.into_inner()
59    }
60}
61
62impl<B, C, H, P> Buffer<Coding<B, C, H, P>> for shards::Mailbox<B, C, H, P>
63where
64    B: CertifiableBlock<Context = Context<Commitment, P>>,
65    C: CodingScheme,
66    H: Hasher,
67    P: PublicKey,
68{
69    type CachedBlock = Arc<CodedBlock<B, C, H>>;
70
71    async fn find_by_digest(
72        &self,
73        digest: <CodedBlock<B, C, H> as Digestible>::Digest,
74    ) -> Option<Self::CachedBlock> {
75        self.get_by_digest(digest).await
76    }
77
78    async fn find_by_commitment(&self, commitment: Commitment) -> Option<Self::CachedBlock> {
79        self.get(commitment).await
80    }
81
82    async fn subscribe_by_digest(
83        &self,
84        digest: <CodedBlock<B, C, H> as Digestible>::Digest,
85    ) -> oneshot::Receiver<Self::CachedBlock> {
86        self.subscribe_by_digest(digest).await
87    }
88
89    async fn subscribe_by_commitment(
90        &self,
91        commitment: Commitment,
92    ) -> oneshot::Receiver<Self::CachedBlock> {
93        self.subscribe(commitment).await
94    }
95
96    async fn finalized(&self, commitment: Commitment) {
97        self.prune(commitment).await;
98    }
99
100    async fn proposed(&self, round: Round, block: CodedBlock<B, C, H>) {
101        self.proposed(round, block).await;
102    }
103}