consensus_config/
parameters.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use mysten_network::Multiaddr;
5use serde::{Deserialize, Serialize};
6use std::{path::PathBuf, time::Duration};
7
8/// Operational configurations of a consensus authority.
9///
10/// All fields should tolerate inconsistencies among authorities, without affecting safety of the
11/// protocol. Otherwise, they need to be part of Sui protocol config or epoch state on-chain.
12///
13/// NOTE: fields with default values are specified in the serde default functions. Most operators
14/// should not need to specify any field, except db_path.
15#[derive(Clone, Debug, Deserialize, Serialize)]
16pub struct Parameters {
17    /// Path to consensus DB for this epoch. Required when initializing consensus.
18    /// This is calculated based on user configuration for base directory.
19    #[serde(skip)]
20    pub db_path: PathBuf,
21
22    /// Time to wait for parent round leader before sealing a block, from when parent round
23    /// has a quorum.
24    #[serde(default = "Parameters::default_leader_timeout")]
25    pub leader_timeout: Duration,
26
27    /// Minimum delay between rounds, to avoid generating too many rounds when latency is low.
28    /// This is especially necessary for tests running locally.
29    /// If setting a non-default value, it should be set low enough to avoid reducing
30    /// round rate and increasing latency in realistic and distributed configurations.
31    #[serde(default = "Parameters::default_min_round_delay")]
32    pub min_round_delay: Duration,
33
34    /// Maximum forward time drift (how far in future) allowed for received blocks.
35    #[serde(default = "Parameters::default_max_forward_time_drift")]
36    pub max_forward_time_drift: Duration,
37
38    /// Max number of blocks to fetch per block sync request.
39    /// Block sync requests have very short (~2s) timeouts.
40    /// So this value should be limited to allow the requests
41    /// to finish on hosts with good network with this timeout.
42    /// Usually a host sends 14-16 blocks per sec to a peer, so
43    /// sending 32 blocks in 2 seconds should be reasonable.
44    #[serde(default = "Parameters::default_max_blocks_per_sync")]
45    pub max_blocks_per_sync: usize,
46
47    /// Max number of blocks to fetch per commit sync request.
48    #[serde(default = "Parameters::default_max_blocks_per_fetch")]
49    pub max_blocks_per_fetch: usize,
50
51    /// Time to wait during node start up until the node has synced the last proposed block via the
52    /// network peers. When set to `0` the sync mechanism is disabled. This property is meant to be
53    /// used for amnesia recovery.
54    #[serde(default = "Parameters::default_sync_last_known_own_block_timeout")]
55    pub sync_last_known_own_block_timeout: Duration,
56
57    /// Interval in milliseconds to probe highest received rounds of peers.
58    #[serde(default = "Parameters::default_round_prober_interval_ms")]
59    pub round_prober_interval_ms: u64,
60
61    /// Timeout in milliseconds for a round prober request.
62    #[serde(default = "Parameters::default_round_prober_request_timeout_ms")]
63    pub round_prober_request_timeout_ms: u64,
64
65    /// Proposing new block is stopped when the propagation delay is greater than this threshold.
66    /// Propagation delay is the difference between the round of the last proposed block and the
67    /// the highest round from this authority that is received by all validators in a quorum.
68    #[serde(default = "Parameters::default_propagation_delay_stop_proposal_threshold")]
69    pub propagation_delay_stop_proposal_threshold: u32,
70
71    /// The number of rounds of blocks to be kept in the Dag state cache per authority. The larger
72    /// the number the more the blocks that will be kept in memory allowing minimising any potential
73    /// disk access.
74    /// Value should be at minimum 50 rounds to ensure node performance, but being too large can be
75    /// expensive in memory usage.
76    #[serde(default = "Parameters::default_dag_state_cached_rounds")]
77    pub dag_state_cached_rounds: u32,
78
79    // Number of authorities commit syncer fetches in parallel.
80    // Both commits in a range and blocks referenced by the commits are fetched per authority.
81    #[serde(default = "Parameters::default_commit_sync_parallel_fetches")]
82    pub commit_sync_parallel_fetches: usize,
83
84    // Number of commits to fetch in a batch, also the maximum number of commits returned per fetch.
85    // If this value is set too small, fetching becomes inefficient.
86    // If this value is set too large, it can result in load imbalance and stragglers.
87    #[serde(default = "Parameters::default_commit_sync_batch_size")]
88    pub commit_sync_batch_size: u32,
89
90    // This affects the maximum number of commit batches being fetched, and those fetched but not
91    // processed as consensus output, before throttling of outgoing commit fetches starts.
92    #[serde(default = "Parameters::default_commit_sync_batches_ahead")]
93    pub commit_sync_batches_ahead: usize,
94
95    /// Tonic network settings.
96    #[serde(default = "TonicParameters::default")]
97    pub tonic: TonicParameters,
98
99    /// Internal consensus parameters.
100    #[serde(default = "InternalParameters::default")]
101    pub internal: InternalParameters,
102
103    /// Override for the address to listen on. When set, this is used instead of
104    /// deriving from the committee address.
105    #[serde(skip)]
106    pub listen_address_override: Option<Multiaddr>,
107}
108
109impl Parameters {
110    pub(crate) fn default_leader_timeout() -> Duration {
111        Duration::from_millis(200)
112    }
113
114    pub(crate) fn default_min_round_delay() -> Duration {
115        if cfg!(msim) || std::env::var("__TEST_ONLY_CONSENSUS_USE_LONG_MIN_ROUND_DELAY").is_ok() {
116            // Checkpoint building and execution cannot keep up with high commit rate in simtests,
117            // leading to long reconfiguration delays. This is because simtest is single threaded,
118            // and spending too much time in consensus can lead to starvation elsewhere.
119            Duration::from_millis(400)
120        } else if cfg!(test) {
121            // Avoid excessive CPU, data and logs in tests.
122            Duration::from_millis(250)
123        } else {
124            Duration::from_millis(50)
125        }
126    }
127
128    pub(crate) fn default_max_forward_time_drift() -> Duration {
129        Duration::from_millis(500)
130    }
131
132    pub(crate) fn default_max_blocks_per_sync() -> usize {
133        if cfg!(msim) {
134            // Exercise hitting blocks per sync limit.
135            4
136        } else {
137            32
138        }
139    }
140
141    pub(crate) fn default_max_blocks_per_fetch() -> usize {
142        if cfg!(msim) {
143            // Exercise hitting blocks per fetch limit.
144            10
145        } else {
146            1000
147        }
148    }
149
150    pub(crate) fn default_sync_last_known_own_block_timeout() -> Duration {
151        if cfg!(msim) {
152            Duration::from_millis(500)
153        } else {
154            // Here we prioritise liveness over the complete de-risking of block equivocation. 5 seconds
155            // in the majority of cases should be good enough for this given a healthy network.
156            Duration::from_secs(5)
157        }
158    }
159
160    pub(crate) fn default_round_prober_interval_ms() -> u64 {
161        if cfg!(msim) { 1000 } else { 5000 }
162    }
163
164    pub(crate) fn default_round_prober_request_timeout_ms() -> u64 {
165        if cfg!(msim) { 800 } else { 4000 }
166    }
167
168    pub(crate) fn default_propagation_delay_stop_proposal_threshold() -> u32 {
169        // Propagation delay is usually 0 round in production.
170        if cfg!(msim) { 2 } else { 5 }
171    }
172
173    pub(crate) fn default_dag_state_cached_rounds() -> u32 {
174        if cfg!(msim) {
175            // Exercise reading blocks from store.
176            5
177        } else {
178            500
179        }
180    }
181
182    pub(crate) fn default_commit_sync_parallel_fetches() -> usize {
183        8
184    }
185
186    pub(crate) fn default_commit_sync_batch_size() -> u32 {
187        if cfg!(msim) {
188            // Exercise commit sync.
189            5
190        } else {
191            100
192        }
193    }
194
195    pub(crate) fn default_commit_sync_batches_ahead() -> usize {
196        // This is set to be a multiple of default commit_sync_parallel_fetches to allow fetching ahead,
197        // while keeping the total number of inflight fetches and unprocessed fetched commits limited.
198        32
199    }
200}
201
202impl Default for Parameters {
203    fn default() -> Self {
204        Self {
205            db_path: PathBuf::default(),
206            leader_timeout: Parameters::default_leader_timeout(),
207            min_round_delay: Parameters::default_min_round_delay(),
208            max_forward_time_drift: Parameters::default_max_forward_time_drift(),
209            max_blocks_per_sync: Parameters::default_max_blocks_per_sync(),
210            max_blocks_per_fetch: Parameters::default_max_blocks_per_fetch(),
211            sync_last_known_own_block_timeout:
212                Parameters::default_sync_last_known_own_block_timeout(),
213            round_prober_interval_ms: Parameters::default_round_prober_interval_ms(),
214            round_prober_request_timeout_ms: Parameters::default_round_prober_request_timeout_ms(),
215            propagation_delay_stop_proposal_threshold:
216                Parameters::default_propagation_delay_stop_proposal_threshold(),
217            dag_state_cached_rounds: Parameters::default_dag_state_cached_rounds(),
218            commit_sync_parallel_fetches: Parameters::default_commit_sync_parallel_fetches(),
219            commit_sync_batch_size: Parameters::default_commit_sync_batch_size(),
220            commit_sync_batches_ahead: Parameters::default_commit_sync_batches_ahead(),
221            tonic: TonicParameters::default(),
222            internal: InternalParameters::default(),
223            listen_address_override: None,
224        }
225    }
226}
227
228#[derive(Clone, Debug, Deserialize, Serialize)]
229pub struct TonicParameters {
230    /// Keepalive interval and timeouts for both client and server.
231    ///
232    /// If unspecified, this will default to 5s.
233    #[serde(default = "TonicParameters::default_keepalive_interval")]
234    pub keepalive_interval: Duration,
235
236    /// Size of various per-connection buffers.
237    ///
238    /// If unspecified, this will default to 32MiB.
239    #[serde(default = "TonicParameters::default_connection_buffer_size")]
240    pub connection_buffer_size: usize,
241
242    /// Messages over this size threshold will increment a counter.
243    ///
244    /// If unspecified, this will default to 16MiB.
245    #[serde(default = "TonicParameters::default_excessive_message_size")]
246    pub excessive_message_size: usize,
247
248    /// Hard message size limit for both requests and responses.
249    /// This value is higher than strictly necessary, to allow overheads.
250    /// Message size targets and soft limits are computed based on this value.
251    ///
252    /// If unspecified, this will default to 1GiB.
253    #[serde(default = "TonicParameters::default_message_size_limit")]
254    pub message_size_limit: usize,
255}
256
257impl TonicParameters {
258    fn default_keepalive_interval() -> Duration {
259        Duration::from_secs(10)
260    }
261
262    fn default_connection_buffer_size() -> usize {
263        32 << 20
264    }
265
266    fn default_excessive_message_size() -> usize {
267        16 << 20
268    }
269
270    fn default_message_size_limit() -> usize {
271        64 << 20
272    }
273}
274
275impl Default for TonicParameters {
276    fn default() -> Self {
277        Self {
278            keepalive_interval: TonicParameters::default_keepalive_interval(),
279            connection_buffer_size: TonicParameters::default_connection_buffer_size(),
280            excessive_message_size: TonicParameters::default_excessive_message_size(),
281            message_size_limit: TonicParameters::default_message_size_limit(),
282        }
283    }
284}
285
286/// Internal parameters unrelated to operating a consensus node in the real world.
287#[derive(Clone, Debug, Deserialize, Serialize)]
288pub struct InternalParameters {
289    /// Whether to skip equivocation validation, when testing with equivocators.
290    #[serde(default = "InternalParameters::default_skip_equivocation_validation")]
291    pub skip_equivocation_validation: bool,
292}
293
294impl InternalParameters {
295    fn default_skip_equivocation_validation() -> bool {
296        false
297    }
298}
299
300impl Default for InternalParameters {
301    fn default() -> Self {
302        Self {
303            skip_equivocation_validation: InternalParameters::default_skip_equivocation_validation(
304            ),
305        }
306    }
307}