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
use {
agave_votor_messages::consensus_message::Block,
crossbeam_channel::{Receiver, Sender},
solana_clock::Slot,
solana_hash::Hash,
solana_runtime::bank::Bank,
std::{sync::Arc, time::Instant},
};
#[derive(Debug, Clone)]
pub struct CompletedBlock {
pub slot: Slot,
// TODO: once we have the async execution changes this can be (block_id, parent_block_id) instead
pub bank: Arc<Bank>,
}
/// Context for the block creation loop to start a leader window
#[derive(Copy, Clone, Debug)]
pub struct LeaderWindowInfo {
pub start_slot: Slot,
pub end_slot: Slot,
pub parent_block: Block,
pub block_timer: Instant,
}
pub type VotorEventSender = Sender<VotorEvent>;
pub type VotorEventReceiver = Receiver<VotorEvent>;
/// Events that trigger actions in Votor
/// TODO: remove bank hash once we update votes
#[derive(Debug, Clone)]
pub enum VotorEvent {
/// A block has completed replay and is ready for voting
Block(CompletedBlock),
/// The block has received a notarization certificate
BlockNotarized(Block),
/// The block has received a notar-fallback certificate
BlockNotarFallback(Block),
/// Received the first shred for the slot.
FirstShred(Slot),
/// The pool has marked the given block as a ready parent for `slot`
ParentReady { slot: Slot, parent_block: Block },
//// Timeout to early detect that a honest that has crashed and
/// if the leader window should be skipped.
TimeoutCrashedLeader(Slot),
/// Timeout to inspect whether the remaining leader window should be skipped.
Timeout(Slot),
/// The given block has reached the safe to notar status
SafeToNotar(Block),
/// The given slot has reached the safe to skip status
SafeToSkip(Slot),
/// We are the leader for this window and have reached the parent ready status
/// Produce the window
ProduceWindow(LeaderWindowInfo),
/// The block has received a slow or fast finalization certificate and is eligible for rooting
/// The second bool indicates whether the block is a fast finalization
Finalized(Block, bool),
/// We have not observed a finalization and reached the standstill timeout
/// The slot is the highest finalized slot
Standstill(Slot),
/// The identity keypair has changed due to an operator calling set-identity
SetIdentity,
}
impl VotorEvent {
/// Ignore old events
pub(crate) fn should_ignore(&self, root: Slot) -> bool {
match self {
VotorEvent::Block(completed_block) => completed_block.slot <= root,
VotorEvent::Timeout(s)
| VotorEvent::SafeToSkip(s)
| VotorEvent::TimeoutCrashedLeader(s)
| VotorEvent::FirstShred(s)
| VotorEvent::SafeToNotar((s, _))
| VotorEvent::Finalized((s, _), _)
| VotorEvent::BlockNotarized((s, _))
| VotorEvent::BlockNotarFallback((s, _))
| VotorEvent::ParentReady {
slot: s,
parent_block: _,
} => s <= &root,
VotorEvent::Standstill(s) => s < &root,
VotorEvent::ProduceWindow(info) => info.start_slot <= root,
VotorEvent::SetIdentity => false,
}
}
}
pub type RepairEventSender = Sender<RepairEvent>;
pub type RepairEventReceiver = Receiver<RepairEvent>;
/// Event sent by votor to the block id repair service for informed repair
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum RepairEvent {
/// We require that this block be fetched. This can happen for the following reasons:
/// - The block has received a NotarizeFallback certificate or stronger
/// - TODO(ashwin): An intrawindow block has reached the SafeToNotar threshold, however we need
/// to check that the parent has reached notarize-fallback requiring us to fetch this block
FetchBlock { slot: Slot, block_id: Hash },
}
impl RepairEvent {
pub fn slot(&self) -> Slot {
match self {
RepairEvent::FetchBlock { slot, .. } => *slot,
}
}
}