commonware_consensus/marshal/coding/
variant.rs1use crate::{
2 marshal::{
3 ancestry::BlockProvider,
4 coding::{
5 shards,
6 types::{CodedBlock, CodedBlockCfg, StoredCodedBlock},
7 },
8 core::{Buffer, CommitmentFallback, Mailbox, Variant},
9 },
10 simplex::types::Context,
11 types::{coding::Commitment, Round},
12 CertifiableBlock,
13};
14use commonware_codec::Read;
15use commonware_coding::Scheme as CodingScheme;
16use commonware_cryptography::{certificate::Scheme, Committable, Digestible, Hasher, PublicKey};
17use commonware_p2p::Recipients;
18use commonware_utils::channel::oneshot;
19use std::future::Future;
20
21#[derive(Default, Clone, Copy)]
26pub struct Coding<B, C, H, P>(std::marker::PhantomData<(B, C, H, P)>)
27where
28 B: CertifiableBlock<Context = Context<Commitment, P>>,
29 C: CodingScheme,
30 H: Hasher,
31 P: PublicKey;
32
33impl<B, C, H, P> Variant for Coding<B, C, H, P>
34where
35 B: CertifiableBlock<Context = Context<Commitment, P>>,
36 C: CodingScheme,
37 H: Hasher,
38 P: PublicKey,
39{
40 type ApplicationBlock = B;
41 type Block = CodedBlock<B, C, H>;
42 type StoredBlock = StoredCodedBlock<B, C, H>;
43 type Commitment = Commitment;
44
45 fn commitment(block: &Self::Block) -> Self::Commitment {
46 block.commitment()
48 }
49
50 fn commitment_to_inner(commitment: Self::Commitment) -> <Self::Block as Digestible>::Digest {
51 commitment.block()
53 }
54
55 fn parent_commitment(block: &Self::Block) -> Self::Commitment {
56 block.context().parent.1
58 }
59
60 fn block_cfg(
61 block_cfg: &<Self::ApplicationBlock as Read>::Cfg,
62 expected: Self::Commitment,
63 ) -> <Self::Block as Read>::Cfg {
64 CodedBlockCfg {
65 inner: block_cfg.clone(),
66 expected,
67 }
68 }
69
70 fn into_inner(block: Self::Block) -> Self::ApplicationBlock {
71 block.into_inner()
72 }
73}
74
75impl<B, C, H, P> Buffer<Coding<B, C, H, P>> for shards::Mailbox<B, C, H, P>
76where
77 B: CertifiableBlock<Context = Context<Commitment, P>>,
78 C: CodingScheme,
79 H: Hasher,
80 P: PublicKey,
81{
82 type PublicKey = P;
83
84 async fn find_by_digest(
85 &self,
86 digest: <CodedBlock<B, C, H> as Digestible>::Digest,
87 ) -> Option<CodedBlock<B, C, H>> {
88 self.get_by_digest(digest).await
89 }
90
91 async fn find_by_commitment(&self, commitment: Commitment) -> Option<CodedBlock<B, C, H>> {
92 self.get(commitment).await
93 }
94
95 fn subscribe_by_digest(
96 &self,
97 digest: <CodedBlock<B, C, H> as Digestible>::Digest,
98 ) -> Option<oneshot::Receiver<CodedBlock<B, C, H>>> {
99 Some(self.subscribe_by_digest(digest))
100 }
101
102 fn subscribe_by_commitment(
103 &self,
104 commitment: Commitment,
105 ) -> Option<oneshot::Receiver<CodedBlock<B, C, H>>> {
106 Some(self.subscribe(commitment))
107 }
108
109 fn finalized(&self, commitment: Commitment) {
110 self.prune(commitment);
111 }
112
113 fn send(&self, round: Round, block: CodedBlock<B, C, H>, _recipients: Recipients<P>) {
114 self.proposed(round, block);
116 }
117}
118
119impl<S, B, C, H, P> BlockProvider for Mailbox<S, Coding<B, C, H, P>>
120where
121 S: Scheme,
122 B: CertifiableBlock<Context = Context<Commitment, P>>,
123 C: CodingScheme,
124 H: Hasher,
125 P: PublicKey,
126{
127 type Block = B;
128
129 fn subscribe_parent(
130 &self,
131 block: &Self::Block,
132 ) -> impl Future<Output = Option<Self::Block>> + Send + 'static {
133 let receiver = block.height().previous().map(|parent_height| {
134 self.subscribe_by_commitment(
135 block.context().parent.1,
136 CommitmentFallback::FetchByCommitment {
137 height: parent_height,
138 },
139 )
140 });
141 async move {
142 let receiver = receiver?;
143 receiver
144 .await
145 .ok()
146 .map(<Coding<B, C, H, P> as Variant>::into_inner)
147 }
148 }
149}