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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
use super::{
elector::Config as Elector,
types::{Activity, Context},
};
use crate::{
types::{Epoch, ViewDelta},
CertifiableAutomaton, Relay, Reporter,
};
use commonware_cryptography::{certificate::Scheme, Digest};
use commonware_p2p::Blocker;
use commonware_parallel::Strategy;
use commonware_runtime::buffer::PoolRef;
use std::{num::NonZeroUsize, time::Duration};
/// Configuration for the consensus engine.
pub struct Config<
S: Scheme,
L: Elector<S>,
B: Blocker<PublicKey = S::PublicKey>,
D: Digest,
A: CertifiableAutomaton<Context = Context<D, S::PublicKey>>,
R: Relay,
F: Reporter<Activity = Activity<S, D>>,
T: Strategy,
> {
/// Signing scheme for the consensus engine.
///
/// Consensus messages can be signed with a cryptosystem that differs from the static
/// participant identity keys exposed in `participants`. For example, we can authenticate peers
/// on the network with [commonware_cryptography::ed25519] keys while signing votes with shares distributed
/// via [commonware_cryptography::bls12381::dkg] (which change each epoch). The scheme implementation is
/// responsible for reusing the exact participant ordering carried by `participants` so that signer indices
/// remain stable across both key spaces; if the order diverges, validators will reject votes as coming from
/// the wrong validator.
pub scheme: S,
/// Leader election configuration.
///
/// Determines how leaders are selected for each view. Built-in options include
/// [`RoundRobin`](super::elector::RoundRobin) for deterministic rotation and
/// [`Random`](super::elector::Random) for unpredictable selection using BLS
/// threshold signatures.
pub elector: L,
/// Blocker for the network.
///
/// Blocking is handled by [commonware_p2p].
pub blocker: B,
/// Automaton for the consensus engine.
pub automaton: A,
/// Relay for the consensus engine.
pub relay: R,
/// Reporter for the consensus engine.
///
/// All activity is exported for downstream applications that benefit from total observability,
/// consider wrapping with [`crate::simplex::scheme::reporter::AttributableReporter`] to
/// automatically filter and verify activities based on scheme attributability.
pub reporter: F,
/// Strategy for parallel operations.
pub strategy: T,
/// Partition for the consensus engine.
pub partition: String,
/// Maximum number of messages to buffer on channels inside the consensus
/// engine before blocking.
pub mailbox_size: usize,
/// Epoch for the consensus engine. Each running engine should have a unique epoch.
pub epoch: Epoch,
/// Number of bytes to buffer when replaying during startup.
pub replay_buffer: NonZeroUsize,
/// The size of the write buffer to use for each blob in the journal.
pub write_buffer: NonZeroUsize,
/// Buffer pool for the journal.
pub buffer_pool: PoolRef,
/// Amount of time to wait for a leader to propose a payload
/// in a view.
pub leader_timeout: Duration,
/// Amount of time to wait for a quorum of notarizations in a view
/// before attempting to skip the view.
pub notarization_timeout: Duration,
/// Amount of time to wait before retrying a nullify broadcast if
/// stuck in a view.
pub nullify_retry: Duration,
/// Number of views behind finalized tip to track
/// and persist activity derived from validator messages.
pub activity_timeout: ViewDelta,
/// Move to nullify immediately if the selected leader has been inactive
/// for this many recent known views (we ignore views we don't have data for).
///
/// This number should be less than or equal to `activity_timeout` (how
/// many views we are tracking below the finalized tip).
pub skip_timeout: ViewDelta,
/// Timeout to wait for a peer to respond to a request.
pub fetch_timeout: Duration,
/// Number of concurrent requests to make at once.
pub fetch_concurrent: usize,
}
impl<
S: Scheme,
L: Elector<S>,
B: Blocker<PublicKey = S::PublicKey>,
D: Digest,
A: CertifiableAutomaton<Context = Context<D, S::PublicKey>>,
R: Relay,
F: Reporter<Activity = Activity<S, D>>,
T: Strategy,
> Config<S, L, B, D, A, R, F, T>
{
/// Assert enforces that all configuration values are valid.
pub fn assert(&self) {
assert!(
!self.scheme.participants().is_empty(),
"there must be at least one participant"
);
assert!(
self.leader_timeout > Duration::default(),
"leader timeout must be greater than zero"
);
assert!(
self.notarization_timeout > Duration::default(),
"notarization timeout must be greater than zero"
);
assert!(
self.leader_timeout <= self.notarization_timeout,
"leader timeout must be less than or equal to notarization timeout"
);
assert!(
self.nullify_retry > Duration::default(),
"nullify retry broadcast must be greater than zero"
);
assert!(
!self.activity_timeout.is_zero(),
"activity timeout must be greater than zero"
);
assert!(
!self.skip_timeout.is_zero(),
"skip timeout must be greater than zero"
);
assert!(
self.skip_timeout <= self.activity_timeout,
"skip timeout must be less than or equal to activity timeout"
);
assert!(
self.fetch_timeout > Duration::default(),
"fetch timeout must be greater than zero"
);
assert!(
self.fetch_concurrent > 0,
"it must be possible to fetch from at least one peer at a time"
);
}
}