-
Notifications
You must be signed in to change notification settings - Fork 220
Expand file tree
/
Copy pathvariant.rs
More file actions
108 lines (91 loc) · 3 KB
/
variant.rs
File metadata and controls
108 lines (91 loc) · 3 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
//! Standard variant implementation for Marshal.
//!
//! The standard variant broadcasts complete blocks to all peers. Each validator
//! receives the full block directly from the proposer or via gossip.
use crate::{
marshal::{
ancestry::BlockProvider,
core::{Buffer, DigestFallback, Mailbox, Variant},
},
types::Round,
Block,
};
use commonware_broadcast::{buffered, Broadcaster};
use commonware_codec::Read;
use commonware_cryptography::{certificate::Scheme, Digestible, PublicKey};
use commonware_p2p::Recipients;
use commonware_utils::channel::oneshot;
/// The standard variant of Marshal, which broadcasts complete blocks.
///
/// This variant sends the entire block to all peers.
#[derive(Default, Clone, Copy)]
pub struct Standard<B: Block>(std::marker::PhantomData<B>);
impl<B> Variant for Standard<B>
where
B: Block,
{
type ApplicationBlock = B;
type Block = B;
type StoredBlock = B;
type Commitment = <B as Digestible>::Digest;
fn commitment(block: &Self::Block) -> Self::Commitment {
// Standard variant commitment is exactly the block digest.
block.digest()
}
fn commitment_to_inner(commitment: Self::Commitment) -> <Self::Block as Digestible>::Digest {
// Trivial left-inverse: digest == commitment in this variant.
commitment
}
fn parent_commitment(block: &Self::Block) -> Self::Commitment {
// In standard mode, commitments are digests, so parent commitment is parent digest.
block.parent()
}
fn block_cfg(
block_cfg: &<Self::ApplicationBlock as Read>::Cfg,
_expected: Self::Commitment,
) -> <Self::Block as Read>::Cfg {
block_cfg.clone()
}
fn into_inner(block: Self::Block) -> Self::ApplicationBlock {
block
}
}
impl<B, K> Buffer<Standard<B>> for buffered::Mailbox<K, B>
where
B: Block,
K: PublicKey,
{
type PublicKey = K;
async fn find_by_digest(&self, digest: B::Digest) -> Option<B> {
self.get(digest).await
}
async fn find_by_commitment(&self, commitment: B::Digest) -> Option<B> {
self.find_by_digest(commitment).await
}
fn subscribe_by_digest(&self, digest: B::Digest) -> oneshot::Receiver<B> {
let (tx, rx) = oneshot::channel();
self.subscribe_prepared(digest, tx);
rx
}
fn subscribe_by_commitment(&self, commitment: B::Digest) -> oneshot::Receiver<B> {
self.subscribe_by_digest(commitment)
}
fn finalized(&self, _commitment: B::Digest) {
// No cleanup needed in standard mode - the buffer handles its own pruning
}
fn send(&self, _round: Round, block: B, recipients: Recipients<K>) {
Broadcaster::broadcast(self, recipients, block);
}
}
impl<S, B> BlockProvider for Mailbox<S, Standard<B>>
where
S: Scheme,
B: Block,
{
type Block = B;
async fn subscribe(self, digest: B::Digest) -> Option<Self::Block> {
self.subscribe_by_digest(digest, DigestFallback::Wait)
.await
.ok()
}
}