-
Notifications
You must be signed in to change notification settings - Fork 220
Expand file tree
/
Copy pathvariant.rs
More file actions
141 lines (125 loc) · 4.09 KB
/
variant.rs
File metadata and controls
141 lines (125 loc) · 4.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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;
/// 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<B, C, H, P>(std::marker::PhantomData<(B, C, H, P)>)
where
B: CertifiableBlock<Context = Context<Commitment, P>>,
C: CodingScheme,
H: Hasher,
P: PublicKey;
impl<B, C, H, P> Variant for Coding<B, C, H, P>
where
B: CertifiableBlock<Context = Context<Commitment, P>>,
C: CodingScheme,
H: Hasher,
P: PublicKey,
{
type ApplicationBlock = B;
type Block = CodedBlock<B, C, H>;
type StoredBlock = StoredCodedBlock<B, C, H>;
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) -> <Self::Block as Digestible>::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: &<Self::ApplicationBlock as Read>::Cfg,
expected: Self::Commitment,
) -> <Self::Block as Read>::Cfg {
CodedBlockCfg {
inner: block_cfg.clone(),
expected,
}
}
fn into_inner(block: Self::Block) -> Self::ApplicationBlock {
block.into_inner()
}
}
impl<B, C, H, P> Buffer<Coding<B, C, H, P>> for shards::Mailbox<B, C, H, P>
where
B: CertifiableBlock<Context = Context<Commitment, P>>,
C: CodingScheme,
H: Hasher,
P: PublicKey,
{
type PublicKey = P;
async fn find_by_digest(
&self,
digest: <CodedBlock<B, C, H> as Digestible>::Digest,
) -> Option<CodedBlock<B, C, H>> {
self.get_by_digest(digest).await
}
async fn find_by_commitment(&self, commitment: Commitment) -> Option<CodedBlock<B, C, H>> {
self.get(commitment).await
}
fn subscribe_by_digest(
&self,
digest: <CodedBlock<B, C, H> as Digestible>::Digest,
) -> oneshot::Receiver<CodedBlock<B, C, H>> {
self.subscribe_by_digest(digest)
}
fn subscribe_by_commitment(
&self,
commitment: Commitment,
) -> oneshot::Receiver<CodedBlock<B, C, H>> {
self.subscribe(commitment)
}
fn finalized(&self, commitment: Commitment) {
self.prune(commitment);
}
fn send(&self, round: Round, block: CodedBlock<B, C, H>, _recipients: Recipients<P>) {
// Targeted forwarding is not supported by the coding variant.
self.proposed(round, block);
}
}
impl<S, B, C, H, P> BlockProvider for Mailbox<S, Coding<B, C, H, P>>
where
S: Scheme,
B: CertifiableBlock<Context = Context<Commitment, P>>,
C: CodingScheme,
H: Hasher,
P: PublicKey,
{
type Block = B;
async fn subscribe(self, block: Self::Block) -> Option<Self::Block> {
let parent_height = block.height().previous()?;
let commitment = block.context().parent.1;
self.subscribe_by_commitment(
commitment,
CommitmentFallback::FetchByCommitment {
height: parent_height,
},
)
.await
.ok()
.map(<Coding<B, C, H, P> as Variant>::into_inner)
}
}