Skip to main content

iota_config/
node.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use std::{
6    net::{IpAddr, Ipv4Addr, SocketAddr},
7    num::NonZeroUsize,
8    path::{Path, PathBuf},
9    sync::Arc,
10    time::Duration,
11};
12
13use anyhow::Result;
14use iota_keys::keypair_file::{read_authority_keypair_from_file, read_keypair_from_file};
15use iota_names::config::IotaNamesConfig;
16use iota_types::{
17    base_types::IotaAddress,
18    committee::EpochId,
19    crypto::{
20        AccountKeyPair, AuthorityKeyPair, AuthorityPublicKeyBytes, IotaKeyPair, KeypairTraits,
21        NetworkKeyPair, get_key_pair_from_rng,
22    },
23    messages_checkpoint::CheckpointSequenceNumber,
24    multiaddr::Multiaddr,
25    supported_protocol_versions::{Chain, SupportedProtocolVersions},
26    traffic_control::{PolicyConfig, RemoteFirewallConfig},
27};
28use once_cell::sync::OnceCell;
29use rand::rngs::OsRng;
30use serde::{Deserialize, Serialize};
31use starfish_config::Parameters as StarfishParameters;
32use tracing::info;
33
34use crate::{
35    Config, certificate_deny_config::CertificateDenyConfig, genesis,
36    migration_tx_data::MigrationTxData, object_storage_config::ObjectStoreConfig, p2p::P2pConfig,
37    transaction_deny_config::TransactionDenyConfig, verifier_signing_config::VerifierSigningConfig,
38};
39
40// Default max number of concurrent requests served
41pub const DEFAULT_GRPC_CONCURRENCY_LIMIT: usize = 20000000000;
42
43/// Default gas price of 1000 Nanos
44pub const DEFAULT_VALIDATOR_GAS_PRICE: u64 = iota_types::transaction::DEFAULT_VALIDATOR_GAS_PRICE;
45
46/// Default commission rate of 2%
47pub const DEFAULT_COMMISSION_RATE: u64 = 200;
48
49#[derive(Clone, Debug, Deserialize, Serialize)]
50#[serde(rename_all = "kebab-case")]
51pub struct NodeConfig {
52    /// The public key bytes corresponding to the private key that the validator
53    /// holds to sign transactions.
54    #[serde(default = "default_authority_key_pair")]
55    pub authority_key_pair: AuthorityKeyPairWithPath,
56    /// The public key bytes corresponding to the private key that the validator
57    /// holds to sign consensus blocks.
58    #[serde(default = "default_key_pair")]
59    pub protocol_key_pair: KeyPairWithPath,
60    #[serde(default = "default_key_pair")]
61    pub account_key_pair: KeyPairWithPath,
62    /// The public key bytes corresponding to the private key that the validator
63    /// uses to establish TLS connections.
64    #[serde(default = "default_key_pair")]
65    pub network_key_pair: KeyPairWithPath,
66    pub db_path: PathBuf,
67
68    /// The network address for gRPC communication.
69    ///
70    /// Can be overwritten with args `listen-address` parameters.
71    #[serde(default = "default_grpc_address")]
72    pub network_address: Multiaddr,
73    #[serde(default = "default_json_rpc_address")]
74    pub json_rpc_address: SocketAddr,
75
76    /// The address for Prometheus metrics.
77    #[serde(default = "default_metrics_address")]
78    pub metrics_address: SocketAddr,
79
80    /// The address for the admin interface that is
81    /// run in the metrics separate runtime and provides access to
82    /// admin node commands such as logging and tracing options.
83    #[serde(default = "default_admin_interface_address")]
84    pub admin_interface_address: SocketAddr,
85
86    /// Configuration struct for the consensus.
87    #[serde(skip_serializing_if = "Option::is_none")]
88    pub consensus_config: Option<ConsensusConfig>,
89
90    /// Flag to enable index processing for a full node.
91    ///
92    /// If set to true, node creates `IndexStore` for transaction
93    /// data including ownership and balance information.
94    #[serde(default = "default_enable_index_processing")]
95    pub enable_index_processing: bool,
96
97    // only allow websocket connections for jsonrpc traffic
98    #[serde(default)]
99    /// Determines the jsonrpc server type as either:
100    /// - 'websocket' for a websocket based service (deprecated)
101    /// - 'http' for an http based service
102    /// - 'both' for both a websocket and http based service (deprecated)
103    pub jsonrpc_server_type: Option<ServerType>,
104
105    /// Flag to enable gRPC load shedding to manage and
106    /// mitigate overload conditions by shedding excess
107    /// load with `LoadShedLayer` middleware.
108    #[serde(default)]
109    pub grpc_load_shed: Option<bool>,
110
111    #[serde(default = "default_concurrency_limit")]
112    pub grpc_concurrency_limit: Option<usize>,
113
114    /// Configuration struct for P2P.
115    #[serde(default)]
116    pub p2p_config: P2pConfig,
117
118    /// Contains genesis location that might be `InPlace`
119    /// for reading all genesis data to memory or `InFile`,
120    /// and `OnceCell` pointer to a genesis struct.
121    pub genesis: Genesis,
122
123    /// Contains the path where to find the migration blob.
124    pub migration_tx_data_path: Option<PathBuf>,
125
126    /// Configuration for pruning of the authority store, to define when
127    /// an old data is removed from the storage space.
128    #[serde(default = "default_authority_store_pruning_config")]
129    pub authority_store_pruning_config: AuthorityStorePruningConfig,
130
131    /// Size of the broadcast channel used for notifying other systems of end of
132    /// epoch.
133    ///
134    /// If unspecified, this will default to `128`.
135    #[serde(default = "default_end_of_epoch_broadcast_channel_capacity")]
136    pub end_of_epoch_broadcast_channel_capacity: usize,
137
138    /// Configuration for the checkpoint executor for limiting
139    /// the number of checkpoints to execute concurrently,
140    /// and to allow for checkpoint post-processing.
141    #[serde(default)]
142    pub checkpoint_executor_config: CheckpointExecutorConfig,
143
144    #[serde(skip_serializing_if = "Option::is_none")]
145    pub metrics: Option<MetricsConfig>,
146
147    /// In a `iota-node` binary, this is set to
148    /// SupportedProtocolVersions::SYSTEM_DEFAULT in iota-node/src/main.rs.
149    /// It is present in the config so that it can be changed by tests in
150    /// order to test protocol upgrades.
151    #[serde(skip)]
152    pub supported_protocol_versions: Option<SupportedProtocolVersions>,
153
154    /// Configuration to manage database checkpoints,
155    /// including whether to perform checkpoints at the end of an epoch,
156    /// the path for storing checkpoints, and other related settings.
157    #[serde(default)]
158    pub db_checkpoint_config: DBCheckpointConfig,
159
160    /// Configuration for enabling/disabling expensive safety checks.
161    #[serde(default)]
162    pub expensive_safety_check_config: ExpensiveSafetyCheckConfig,
163
164    /// Configuration to specify rules for denying transactions
165    /// based on `objectsIDs`, `addresses`, or enable/disable many
166    /// features such as publishing new packages or using shared objects.
167    #[serde(default)]
168    pub transaction_deny_config: TransactionDenyConfig,
169
170    /// Config used to deny execution for certificate digests
171    /// know for crashing or hanging validator nodes.
172    ///
173    /// Should be used for a fast temporary fixes and
174    /// removed once the issue is fixed.
175    #[serde(default)]
176    pub certificate_deny_config: CertificateDenyConfig,
177
178    /// Used to determine how state debug information is dumped
179    /// when a node forks.
180    #[serde(default)]
181    pub state_debug_dump_config: StateDebugDumpConfig,
182
183    /// Configuration for writing state archive. If `ObjectStorage`
184    /// config is provided, `ArchiveWriter` will be created
185    /// for checkpoints archival.
186    #[serde(default)]
187    pub state_archive_write_config: StateArchiveConfig,
188
189    #[serde(default)]
190    pub state_archive_read_config: Vec<StateArchiveConfig>,
191
192    /// Determines if snapshot should be uploaded to the remote storage.
193    #[serde(default)]
194    pub state_snapshot_write_config: StateSnapshotConfig,
195
196    #[serde(default)]
197    pub indexer_max_subscriptions: Option<usize>,
198
199    #[serde(default = "default_transaction_kv_store_config")]
200    pub transaction_kv_store_read_config: TransactionKeyValueStoreReadConfig,
201
202    // TODO: write config seem to be unused.
203    #[serde(skip_serializing_if = "Option::is_none")]
204    pub transaction_kv_store_write_config: Option<TransactionKeyValueStoreWriteConfig>,
205
206    /// Configuration for defining thresholds and settings
207    /// for managing system overload conditions in a node.
208    #[serde(default = "default_authority_overload_config")]
209    pub authority_overload_config: AuthorityOverloadConfig,
210
211    /// Specifies the ending epoch for a node for debugging purposes.
212    ///
213    ///  Ignored if set by config, can be configured only by cli arguments.
214    #[serde(skip_serializing_if = "Option::is_none")]
215    pub run_with_range: Option<RunWithRange>,
216
217    // For killswitch use None
218    #[serde(
219        skip_serializing_if = "Option::is_none",
220        default = "default_traffic_controller_policy_config"
221    )]
222    pub policy_config: Option<PolicyConfig>,
223
224    #[serde(skip_serializing_if = "Option::is_none")]
225    pub firewall_config: Option<RemoteFirewallConfig>,
226
227    #[serde(default)]
228    pub execution_cache: ExecutionCacheType,
229
230    #[serde(default)]
231    pub execution_cache_config: ExecutionCacheConfig,
232
233    #[serde(default = "bool_true")]
234    pub enable_validator_tx_finalizer: bool,
235
236    #[serde(default)]
237    pub verifier_signing_config: VerifierSigningConfig,
238
239    /// If a value is set, it determines if writes to DB can stall, which can
240    /// halt the whole process. By default, write stall is enabled on
241    /// validators but not on fullnodes.
242    #[serde(skip_serializing_if = "Option::is_none")]
243    pub enable_db_write_stall: Option<bool>,
244
245    #[serde(default, skip_serializing_if = "Option::is_none")]
246    pub iota_names_config: Option<IotaNamesConfig>,
247
248    /// Flag to enable the gRPC API.
249    #[serde(default)]
250    pub enable_grpc_api: bool,
251    #[serde(
252        default = "default_grpc_api_config",
253        skip_serializing_if = "Option::is_none"
254    )]
255    pub grpc_api_config: Option<GrpcApiConfig>,
256
257    /// Allow overriding the chain for testing purposes. For instance, it allows
258    /// you to create a test network that believes it is mainnet or testnet.
259    /// Attempting to override this value on production networks will result
260    /// in an error.
261    #[serde(skip_serializing_if = "Option::is_none")]
262    pub chain_override_for_testing: Option<Chain>,
263}
264
265#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
266#[serde(rename_all = "kebab-case")]
267pub struct TlsConfig {
268    /// File path to a PEM formatted TLS certificate chain
269    cert: String,
270    /// File path to a PEM formatted TLS private key
271    key: String,
272}
273
274impl TlsConfig {
275    pub fn cert(&self) -> &str {
276        &self.cert
277    }
278
279    pub fn key(&self) -> &str {
280        &self.key
281    }
282}
283
284/// Configuration for the gRPC API service
285#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
286#[serde(rename_all = "kebab-case")]
287pub struct GrpcApiConfig {
288    /// The address to bind the gRPC server to
289    #[serde(default = "default_grpc_api_address")]
290    pub address: SocketAddr,
291
292    /// TLS configuration for the gRPC server.
293    ///
294    /// If not provided, the gRPC server will use plain TCP without TLS.
295    #[serde(skip_serializing_if = "Option::is_none")]
296    pub tls: Option<TlsConfig>,
297
298    /// Maximum message size for gRPC responses (in bytes)
299    #[serde(default = "default_grpc_api_max_message_size_bytes")]
300    pub max_message_size_bytes: u32,
301
302    /// Buffer size for broadcast channels used for streaming
303    #[serde(default = "default_grpc_api_broadcast_buffer_size")]
304    pub broadcast_buffer_size: u32,
305
306    /// Maximum number of concurrent subscribers to checkpoint streaming RPCs.
307    /// Once the cap is reached, additional subscribe requests are rejected
308    /// with `Unavailable` to protect the server from being overwhelmed by
309    /// unbounded streaming clients. Values below 1 are clamped to 1 at
310    /// server startup.
311    #[serde(default = "default_grpc_api_max_concurrent_stream_subscribers")]
312    pub max_concurrent_stream_subscribers: u32,
313
314    /// Maximum size for Move values when rendering to JSON
315    /// in bytes.
316    #[serde(default = "default_grpc_api_max_json_move_value_size")]
317    pub max_json_move_value_size: usize,
318
319    /// Maximum number of transactions allowed in a single ExecuteTransactions
320    /// batch request.
321    #[serde(default = "default_grpc_api_max_execute_transaction_batch_size")]
322    pub max_execute_transaction_batch_size: u32,
323
324    /// Maximum number of transactions allowed in a single SimulateTransactions
325    /// batch request.
326    #[serde(default = "default_grpc_api_max_simulate_transaction_batch_size")]
327    pub max_simulate_transaction_batch_size: u32,
328
329    /// Maximum allowed timeout in milliseconds for waiting for checkpoint
330    /// inclusion in ExecuteTransactions requests. Client-specified timeouts
331    /// are clamped to this value.
332    #[serde(default = "default_grpc_api_max_checkpoint_inclusion_timeout_ms")]
333    pub max_checkpoint_inclusion_timeout_ms: u64,
334}
335
336fn default_grpc_api_address() -> SocketAddr {
337    SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 50051)
338}
339
340fn default_grpc_api_broadcast_buffer_size() -> u32 {
341    100
342}
343
344fn default_grpc_api_max_concurrent_stream_subscribers() -> u32 {
345    1024
346}
347
348fn default_grpc_api_max_message_size_bytes() -> u32 {
349    128 * 1024 * 1024 // 128MB
350}
351
352fn default_grpc_api_max_json_move_value_size() -> usize {
353    1024 * 1024 // 1 MB
354}
355
356fn default_grpc_api_max_execute_transaction_batch_size() -> u32 {
357    20
358}
359
360fn default_grpc_api_max_simulate_transaction_batch_size() -> u32 {
361    20
362}
363
364fn default_grpc_api_max_checkpoint_inclusion_timeout_ms() -> u64 {
365    60_000 // 60 seconds
366}
367
368impl Default for GrpcApiConfig {
369    fn default() -> Self {
370        Self {
371            address: default_grpc_api_address(),
372            tls: None,
373            max_message_size_bytes: default_grpc_api_max_message_size_bytes(),
374            broadcast_buffer_size: default_grpc_api_broadcast_buffer_size(),
375            max_concurrent_stream_subscribers: default_grpc_api_max_concurrent_stream_subscribers(),
376            max_json_move_value_size: default_grpc_api_max_json_move_value_size(),
377            max_execute_transaction_batch_size: default_grpc_api_max_execute_transaction_batch_size(
378            ),
379            max_simulate_transaction_batch_size:
380                default_grpc_api_max_simulate_transaction_batch_size(),
381            max_checkpoint_inclusion_timeout_ms:
382                default_grpc_api_max_checkpoint_inclusion_timeout_ms(),
383        }
384    }
385}
386
387impl GrpcApiConfig {
388    // The default maximum uncompressed size in bytes for a message, based on
389    // tonic's default.
390    const GRPC_TONIC_DEFAULT_MAX_RECV_MESSAGE_SIZE: u32 = 4 * 1024 * 1024; // 4MB
391    const GRPC_MIN_CLIENT_MAX_MESSAGE_SIZE_BYTES: u32 =
392        Self::GRPC_TONIC_DEFAULT_MAX_RECV_MESSAGE_SIZE;
393
394    pub fn tls_config(&self) -> Option<&TlsConfig> {
395        self.tls.as_ref()
396    }
397
398    pub fn max_message_size_bytes(&self) -> u32 {
399        // Ensure max message size is at least the minimum allowed
400        self.max_message_size_bytes
401            .max(Self::GRPC_MIN_CLIENT_MAX_MESSAGE_SIZE_BYTES)
402    }
403
404    /// Calculate the maximum size for a message that can be
405    /// sent to a client, taking into account the client's max message size
406    /// preference.
407    pub fn max_message_size_client_bytes(&self, client_max_message_size_bytes: Option<u32>) -> u32 {
408        client_max_message_size_bytes
409            // if the client did not specify a max message size, use the tonic default receive
410            // message size
411            .unwrap_or(Self::GRPC_TONIC_DEFAULT_MAX_RECV_MESSAGE_SIZE)
412            // clamp the value between the tonic default and the service max message size
413            .clamp(
414                Self::GRPC_MIN_CLIENT_MAX_MESSAGE_SIZE_BYTES,
415                self.max_message_size_bytes(),
416            )
417    }
418}
419
420#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize)]
421#[serde(rename_all = "kebab-case")]
422pub enum ExecutionCacheType {
423    #[default]
424    WritebackCache,
425    PassthroughCache,
426}
427
428impl From<ExecutionCacheType> for u8 {
429    fn from(cache_type: ExecutionCacheType) -> Self {
430        match cache_type {
431            ExecutionCacheType::WritebackCache => 0,
432            ExecutionCacheType::PassthroughCache => 1,
433        }
434    }
435}
436
437impl From<&u8> for ExecutionCacheType {
438    fn from(cache_type: &u8) -> Self {
439        match cache_type {
440            0 => ExecutionCacheType::WritebackCache,
441            1 => ExecutionCacheType::PassthroughCache,
442            _ => unreachable!("Invalid value for ExecutionCacheType"),
443        }
444    }
445}
446
447/// Type alias for atomic representation of ExecutionCacheType for lock-free
448/// operations
449pub type ExecutionCacheTypeAtomicU8 = std::sync::atomic::AtomicU8;
450
451impl From<ExecutionCacheType> for ExecutionCacheTypeAtomicU8 {
452    fn from(cache_type: ExecutionCacheType) -> Self {
453        ExecutionCacheTypeAtomicU8::new(u8::from(cache_type))
454    }
455}
456
457impl ExecutionCacheType {
458    pub fn cache_type(self) -> Self {
459        if std::env::var("DISABLE_WRITEBACK_CACHE").is_ok() {
460            Self::PassthroughCache
461        } else {
462            self
463        }
464    }
465}
466
467#[derive(Clone, Debug, Default, Deserialize, Serialize)]
468#[serde(rename_all = "kebab-case")]
469pub struct ExecutionCacheConfig {
470    #[serde(default)]
471    pub writeback_cache: WritebackCacheConfig,
472}
473
474#[derive(Clone, Debug, Default, Deserialize, Serialize)]
475#[serde(rename_all = "kebab-case")]
476pub struct WritebackCacheConfig {
477    /// Maximum number of entries in each cache. (There are several
478    /// different caches).
479    #[serde(default, skip_serializing_if = "Option::is_none")]
480    pub max_cache_size: Option<u64>, // defaults to 100000
481
482    #[serde(default, skip_serializing_if = "Option::is_none")]
483    pub package_cache_size: Option<u64>, // defaults to 1000
484
485    #[serde(default, skip_serializing_if = "Option::is_none")]
486    pub object_cache_size: Option<u64>, // defaults to max_cache_size
487    #[serde(default, skip_serializing_if = "Option::is_none")]
488    pub marker_cache_size: Option<u64>, // defaults to object_cache_size
489    #[serde(default, skip_serializing_if = "Option::is_none")]
490    pub object_by_id_cache_size: Option<u64>, // defaults to object_cache_size
491
492    #[serde(default, skip_serializing_if = "Option::is_none")]
493    pub transaction_cache_size: Option<u64>, // defaults to max_cache_size
494    #[serde(default, skip_serializing_if = "Option::is_none")]
495    pub executed_effect_cache_size: Option<u64>, // defaults to transaction_cache_size
496    #[serde(default, skip_serializing_if = "Option::is_none")]
497    pub effect_cache_size: Option<u64>, // defaults to executed_effect_cache_size
498
499    #[serde(default, skip_serializing_if = "Option::is_none")]
500    pub events_cache_size: Option<u64>, // defaults to transaction_cache_size
501
502    #[serde(default, skip_serializing_if = "Option::is_none")]
503    pub transaction_objects_cache_size: Option<u64>, // defaults to 1000
504
505    /// Number of uncommitted transactions at which to pause consensus
506    /// handler.
507    #[serde(default, skip_serializing_if = "Option::is_none")]
508    pub backpressure_threshold: Option<u64>, // defaults to 100_000
509
510    /// Number of uncommitted transactions at which to refuse new
511    /// transaction submissions. Defaults to backpressure_threshold
512    /// if unset.
513    #[serde(default, skip_serializing_if = "Option::is_none")]
514    pub backpressure_threshold_for_rpc: Option<u64>, // defaults to backpressure_threshold
515}
516
517impl WritebackCacheConfig {
518    pub fn max_cache_size(&self) -> u64 {
519        std::env::var("IOTA_CACHE_WRITEBACK_SIZE_MAX")
520            .ok()
521            .and_then(|s| s.parse().ok())
522            .or(self.max_cache_size)
523            .unwrap_or(100000)
524    }
525
526    pub fn package_cache_size(&self) -> u64 {
527        std::env::var("IOTA_CACHE_WRITEBACK_SIZE_PACKAGE")
528            .ok()
529            .and_then(|s| s.parse().ok())
530            .or(self.package_cache_size)
531            .unwrap_or(1000)
532    }
533
534    pub fn object_cache_size(&self) -> u64 {
535        std::env::var("IOTA_CACHE_WRITEBACK_SIZE_OBJECT")
536            .ok()
537            .and_then(|s| s.parse().ok())
538            .or(self.object_cache_size)
539            .unwrap_or_else(|| self.max_cache_size())
540    }
541
542    pub fn marker_cache_size(&self) -> u64 {
543        std::env::var("IOTA_CACHE_WRITEBACK_SIZE_MARKER")
544            .ok()
545            .and_then(|s| s.parse().ok())
546            .or(self.marker_cache_size)
547            .unwrap_or_else(|| self.object_cache_size())
548    }
549
550    pub fn object_by_id_cache_size(&self) -> u64 {
551        std::env::var("IOTA_CACHE_WRITEBACK_SIZE_OBJECT_BY_ID")
552            .ok()
553            .and_then(|s| s.parse().ok())
554            .or(self.object_by_id_cache_size)
555            .unwrap_or_else(|| self.object_cache_size())
556    }
557
558    pub fn transaction_cache_size(&self) -> u64 {
559        std::env::var("IOTA_CACHE_WRITEBACK_SIZE_TRANSACTION")
560            .ok()
561            .and_then(|s| s.parse().ok())
562            .or(self.transaction_cache_size)
563            .unwrap_or_else(|| self.max_cache_size())
564    }
565
566    pub fn executed_effect_cache_size(&self) -> u64 {
567        std::env::var("IOTA_CACHE_WRITEBACK_SIZE_EXECUTED_EFFECT")
568            .ok()
569            .and_then(|s| s.parse().ok())
570            .or(self.executed_effect_cache_size)
571            .unwrap_or_else(|| self.transaction_cache_size())
572    }
573
574    pub fn effect_cache_size(&self) -> u64 {
575        std::env::var("IOTA_CACHE_WRITEBACK_SIZE_EFFECT")
576            .ok()
577            .and_then(|s| s.parse().ok())
578            .or(self.effect_cache_size)
579            .unwrap_or_else(|| self.executed_effect_cache_size())
580    }
581
582    pub fn events_cache_size(&self) -> u64 {
583        std::env::var("IOTA_CACHE_WRITEBACK_SIZE_EVENTS")
584            .ok()
585            .and_then(|s| s.parse().ok())
586            .or(self.events_cache_size)
587            .unwrap_or_else(|| self.transaction_cache_size())
588    }
589
590    pub fn transaction_objects_cache_size(&self) -> u64 {
591        std::env::var("IOTA_CACHE_WRITEBACK_SIZE_TRANSACTION_OBJECTS")
592            .ok()
593            .and_then(|s| s.parse().ok())
594            .or(self.transaction_objects_cache_size)
595            .unwrap_or(1000)
596    }
597
598    pub fn backpressure_threshold(&self) -> u64 {
599        std::env::var("IOTA_CACHE_WRITEBACK_BACKPRESSURE_THRESHOLD")
600            .ok()
601            .and_then(|s| s.parse().ok())
602            .or(self.backpressure_threshold)
603            .unwrap_or(100_000)
604    }
605
606    pub fn backpressure_threshold_for_rpc(&self) -> u64 {
607        std::env::var("IOTA_CACHE_WRITEBACK_BACKPRESSURE_THRESHOLD_FOR_RPC")
608            .ok()
609            .and_then(|s| s.parse().ok())
610            .or(self.backpressure_threshold_for_rpc)
611            .unwrap_or(self.backpressure_threshold())
612    }
613}
614
615#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
616#[serde(rename_all = "lowercase")]
617pub enum ServerType {
618    WebSocket,
619    Http,
620    Both,
621}
622
623#[derive(Clone, Debug, Deserialize, Serialize)]
624#[serde(rename_all = "kebab-case")]
625pub struct TransactionKeyValueStoreReadConfig {
626    #[serde(default = "default_base_url")]
627    pub base_url: String,
628
629    #[serde(default = "default_cache_size")]
630    pub cache_size: u64,
631}
632
633impl Default for TransactionKeyValueStoreReadConfig {
634    fn default() -> Self {
635        Self {
636            base_url: default_base_url(),
637            cache_size: default_cache_size(),
638        }
639    }
640}
641
642fn default_base_url() -> String {
643    "".to_string()
644}
645
646fn default_cache_size() -> u64 {
647    100_000
648}
649
650fn default_transaction_kv_store_config() -> TransactionKeyValueStoreReadConfig {
651    TransactionKeyValueStoreReadConfig::default()
652}
653
654fn default_authority_store_pruning_config() -> AuthorityStorePruningConfig {
655    AuthorityStorePruningConfig::default()
656}
657
658pub fn default_enable_index_processing() -> bool {
659    true
660}
661
662fn default_grpc_address() -> Multiaddr {
663    "/ip4/0.0.0.0/tcp/8080".parse().unwrap()
664}
665fn default_authority_key_pair() -> AuthorityKeyPairWithPath {
666    AuthorityKeyPairWithPath::new(get_key_pair_from_rng::<AuthorityKeyPair, _>(&mut OsRng).1)
667}
668
669fn default_key_pair() -> KeyPairWithPath {
670    KeyPairWithPath::new(
671        get_key_pair_from_rng::<AccountKeyPair, _>(&mut OsRng)
672            .1
673            .into(),
674    )
675}
676
677fn default_metrics_address() -> SocketAddr {
678    SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 9184)
679}
680
681pub fn default_admin_interface_address() -> SocketAddr {
682    SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 1337)
683}
684
685pub fn default_json_rpc_address() -> SocketAddr {
686    SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 9000)
687}
688
689pub fn default_grpc_api_config() -> Option<GrpcApiConfig> {
690    Some(GrpcApiConfig::default())
691}
692
693pub fn default_concurrency_limit() -> Option<usize> {
694    Some(DEFAULT_GRPC_CONCURRENCY_LIMIT)
695}
696
697pub fn default_end_of_epoch_broadcast_channel_capacity() -> usize {
698    128
699}
700
701pub fn bool_true() -> bool {
702    true
703}
704
705fn is_true(value: &bool) -> bool {
706    *value
707}
708
709impl Config for NodeConfig {}
710
711impl NodeConfig {
712    pub fn authority_key_pair(&self) -> &AuthorityKeyPair {
713        self.authority_key_pair.authority_keypair()
714    }
715
716    pub fn protocol_key_pair(&self) -> &NetworkKeyPair {
717        match self.protocol_key_pair.keypair() {
718            IotaKeyPair::Ed25519(kp) => kp,
719            other => {
720                panic!("invalid keypair type: {other:?}, only Ed25519 is allowed for protocol key")
721            }
722        }
723    }
724
725    pub fn network_key_pair(&self) -> &NetworkKeyPair {
726        match self.network_key_pair.keypair() {
727            IotaKeyPair::Ed25519(kp) => kp,
728            other => {
729                panic!("invalid keypair type: {other:?}, only Ed25519 is allowed for network key")
730            }
731        }
732    }
733
734    pub fn authority_public_key(&self) -> AuthorityPublicKeyBytes {
735        self.authority_key_pair().public().into()
736    }
737
738    pub fn db_path(&self) -> PathBuf {
739        self.db_path.join("live")
740    }
741
742    pub fn db_checkpoint_path(&self) -> PathBuf {
743        self.db_path.join("db_checkpoints")
744    }
745
746    pub fn archive_path(&self) -> PathBuf {
747        self.db_path.join("archive")
748    }
749
750    pub fn snapshot_path(&self) -> PathBuf {
751        self.db_path.join("snapshot")
752    }
753
754    pub fn network_address(&self) -> &Multiaddr {
755        &self.network_address
756    }
757
758    pub fn consensus_config(&self) -> Option<&ConsensusConfig> {
759        self.consensus_config.as_ref()
760    }
761
762    pub fn genesis(&self) -> Result<&genesis::Genesis> {
763        self.genesis.genesis()
764    }
765
766    pub fn load_migration_tx_data(&self) -> Result<MigrationTxData> {
767        let Some(location) = &self.migration_tx_data_path else {
768            anyhow::bail!("no file location set");
769        };
770
771        // Load from file
772        let migration_tx_data = MigrationTxData::load(location)?;
773
774        // Validate migration content in order to avoid corrupted or malicious data
775        migration_tx_data.validate_from_genesis(self.genesis.genesis()?)?;
776        Ok(migration_tx_data)
777    }
778
779    pub fn iota_address(&self) -> IotaAddress {
780        (&self.account_key_pair.keypair().public()).into()
781    }
782
783    pub fn archive_reader_config(&self) -> Vec<ArchiveReaderConfig> {
784        self.state_archive_read_config
785            .iter()
786            .flat_map(|config| {
787                config
788                    .object_store_config
789                    .as_ref()
790                    .map(|remote_store_config| ArchiveReaderConfig {
791                        remote_store_config: remote_store_config.clone(),
792                        download_concurrency: NonZeroUsize::new(config.concurrency)
793                            .unwrap_or(NonZeroUsize::new(5).unwrap()),
794                        use_for_pruning_watermark: config.use_for_pruning_watermark,
795                    })
796            })
797            .collect()
798    }
799
800    pub fn jsonrpc_server_type(&self) -> ServerType {
801        self.jsonrpc_server_type.unwrap_or(ServerType::Http)
802    }
803}
804
805#[derive(Debug, Clone, Deserialize, Serialize)]
806#[serde(rename_all = "kebab-case")]
807pub struct ConsensusConfig {
808    // Base consensus DB path for all epochs.
809    pub db_path: PathBuf,
810
811    // The number of epochs for which to retain the consensus DBs. Setting it to 0 will make a
812    // consensus DB getting dropped as soon as system is switched to a new epoch.
813    pub db_retention_epochs: Option<u64>,
814
815    // Pruner will run on every epoch change but it will also check periodically on every
816    // `db_pruner_period_secs` seconds to see if there are any epoch DBs to remove.
817    pub db_pruner_period_secs: Option<u64>,
818
819    /// Maximum number of pending transactions to submit to consensus, including
820    /// those in submission wait.
821    ///
822    /// Default to 20_000 inflight limit, assuming 20_000 txn tps * 1 sec
823    /// consensus latency.
824    pub max_pending_transactions: Option<usize>,
825
826    /// When defined caps the calculated submission position to the
827    /// max_submit_position.
828    ///
829    /// Even if the is elected to submit from a higher
830    /// position than this, it will "reset" to the max_submit_position.
831    pub max_submit_position: Option<usize>,
832
833    /// The submit delay step to consensus defined in milliseconds.
834    ///
835    /// When provided it will override the current back off logic otherwise the
836    /// default backoff logic will be applied based on consensus latency
837    /// estimates.
838    pub submit_delay_step_override_millis: Option<u64>,
839
840    /// Parameters for Starfish consensus
841    #[serde(skip_serializing_if = "Option::is_none", alias = "starfish_parameters")]
842    pub parameters: Option<StarfishParameters>,
843}
844
845impl ConsensusConfig {
846    pub fn db_path(&self) -> &Path {
847        &self.db_path
848    }
849
850    pub fn max_pending_transactions(&self) -> usize {
851        self.max_pending_transactions.unwrap_or(20_000)
852    }
853
854    pub fn submit_delay_step_override(&self) -> Option<Duration> {
855        self.submit_delay_step_override_millis
856            .map(Duration::from_millis)
857    }
858
859    pub fn db_retention_epochs(&self) -> u64 {
860        self.db_retention_epochs.unwrap_or(0)
861    }
862
863    pub fn db_pruner_period(&self) -> Duration {
864        // Default to 1 hour
865        self.db_pruner_period_secs
866            .map(Duration::from_secs)
867            .unwrap_or(Duration::from_secs(3_600))
868    }
869}
870
871#[derive(Clone, Debug, Deserialize, Serialize)]
872#[serde(rename_all = "kebab-case")]
873pub struct CheckpointExecutorConfig {
874    /// Upper bound on the number of checkpoints that can be concurrently
875    /// executed.
876    ///
877    /// If unspecified, this will default to `200`
878    #[serde(default = "default_checkpoint_execution_max_concurrency")]
879    pub checkpoint_execution_max_concurrency: usize,
880
881    /// Number of seconds to wait for effects of a batch of transactions
882    /// before logging a warning. Note that we will continue to retry
883    /// indefinitely.
884    ///
885    /// If unspecified, this will default to `10`.
886    #[serde(default = "default_local_execution_timeout_sec")]
887    pub local_execution_timeout_sec: u64,
888
889    /// Optional directory used for data ingestion pipeline.
890    ///
891    /// When specified, each executed checkpoint will be saved in a local
892    /// directory for post-processing
893    #[serde(default, skip_serializing_if = "Option::is_none")]
894    pub data_ingestion_dir: Option<PathBuf>,
895}
896
897#[derive(Clone, Debug, Default, Deserialize, Serialize)]
898#[serde(rename_all = "kebab-case")]
899pub struct ExpensiveSafetyCheckConfig {
900    /// If enabled, at epoch boundary, we will check that the storage
901    /// fund balance is always identical to the sum of the storage
902    /// rebate of all live objects, and that the total IOTA in the network
903    /// remains the same.
904    #[serde(default)]
905    enable_epoch_iota_conservation_check: bool,
906
907    /// If enabled, we will check that the total IOTA in all input objects of a
908    /// tx (both the Move part and the storage rebate) matches the total IOTA
909    /// in all output objects of the tx + gas fees.
910    #[serde(default)]
911    enable_deep_per_tx_iota_conservation_check: bool,
912
913    /// Disable epoch IOTA conservation check even when we are running in debug
914    /// mode.
915    #[serde(default)]
916    force_disable_epoch_iota_conservation_check: bool,
917
918    /// If enabled, at epoch boundary, we will check that the accumulated
919    /// live object state matches the end of epoch root state digest.
920    #[serde(default)]
921    enable_state_consistency_check: bool,
922
923    /// Disable state consistency check even when we are running in debug mode.
924    #[serde(default)]
925    force_disable_state_consistency_check: bool,
926
927    #[serde(default)]
928    enable_secondary_index_checks: bool,
929    // TODO: Add more expensive checks here
930}
931
932impl ExpensiveSafetyCheckConfig {
933    pub fn new_enable_all() -> Self {
934        Self {
935            enable_epoch_iota_conservation_check: true,
936            enable_deep_per_tx_iota_conservation_check: true,
937            force_disable_epoch_iota_conservation_check: false,
938            enable_state_consistency_check: true,
939            force_disable_state_consistency_check: false,
940            enable_secondary_index_checks: false, // Disable by default for now
941        }
942    }
943
944    pub fn new_disable_all() -> Self {
945        Self {
946            enable_epoch_iota_conservation_check: false,
947            enable_deep_per_tx_iota_conservation_check: false,
948            force_disable_epoch_iota_conservation_check: true,
949            enable_state_consistency_check: false,
950            force_disable_state_consistency_check: true,
951            enable_secondary_index_checks: false,
952        }
953    }
954
955    pub fn force_disable_epoch_iota_conservation_check(&mut self) {
956        self.force_disable_epoch_iota_conservation_check = true;
957    }
958
959    pub fn enable_epoch_iota_conservation_check(&self) -> bool {
960        (self.enable_epoch_iota_conservation_check || cfg!(debug_assertions))
961            && !self.force_disable_epoch_iota_conservation_check
962    }
963
964    pub fn force_disable_state_consistency_check(&mut self) {
965        self.force_disable_state_consistency_check = true;
966    }
967
968    pub fn enable_state_consistency_check(&self) -> bool {
969        (self.enable_state_consistency_check || cfg!(debug_assertions))
970            && !self.force_disable_state_consistency_check
971    }
972
973    pub fn enable_deep_per_tx_iota_conservation_check(&self) -> bool {
974        self.enable_deep_per_tx_iota_conservation_check || cfg!(debug_assertions)
975    }
976
977    pub fn enable_secondary_index_checks(&self) -> bool {
978        self.enable_secondary_index_checks
979    }
980}
981
982fn default_checkpoint_execution_max_concurrency() -> usize {
983    4
984}
985
986fn default_local_execution_timeout_sec() -> u64 {
987    30
988}
989
990impl Default for CheckpointExecutorConfig {
991    fn default() -> Self {
992        Self {
993            checkpoint_execution_max_concurrency: default_checkpoint_execution_max_concurrency(),
994            local_execution_timeout_sec: default_local_execution_timeout_sec(),
995            data_ingestion_dir: None,
996        }
997    }
998}
999
1000#[derive(Debug, Clone, Deserialize, Serialize)]
1001#[serde(rename_all = "kebab-case")]
1002pub struct AuthorityStorePruningConfig {
1003    /// number of the latest epoch dbs to retain
1004    #[serde(default = "default_num_latest_epoch_dbs_to_retain")]
1005    pub num_latest_epoch_dbs_to_retain: usize,
1006    /// number of epochs to keep the latest version of objects for.
1007    /// Note that a zero value corresponds to an aggressive pruner.
1008    /// This mode is experimental and needs to be used with caution.
1009    /// Use `u64::MAX` to disable the pruner for the objects.
1010    #[serde(default)]
1011    pub num_epochs_to_retain: u64,
1012    /// pruner's runtime interval used for aggressive mode
1013    #[serde(skip_serializing_if = "Option::is_none")]
1014    pub pruning_run_delay_seconds: Option<u64>,
1015    /// maximum number of checkpoints in the pruning batch. Can be adjusted to
1016    /// increase performance
1017    #[serde(default = "default_max_checkpoints_in_batch")]
1018    pub max_checkpoints_in_batch: usize,
1019    /// maximum number of transaction in the pruning batch
1020    #[serde(default = "default_max_transactions_in_batch")]
1021    pub max_transactions_in_batch: usize,
1022    /// enables periodic background compaction for old SST files whose last
1023    /// modified time is older than `periodic_compaction_threshold_days`
1024    /// days. That ensures that all sst files eventually go through the
1025    /// compaction process
1026    #[serde(
1027        default = "default_periodic_compaction_threshold_days",
1028        skip_serializing_if = "Option::is_none"
1029    )]
1030    pub periodic_compaction_threshold_days: Option<usize>,
1031    /// number of epochs to keep the latest version of transactions and effects
1032    /// for
1033    #[serde(skip_serializing_if = "Option::is_none")]
1034    pub num_epochs_to_retain_for_checkpoints: Option<u64>,
1035    #[serde(default = "default_smoothing", skip_serializing_if = "is_true")]
1036    pub smooth: bool,
1037    /// Enables the compaction filter for pruning the objects table.
1038    /// If disabled, a range deletion approach is used instead.
1039    /// While it is generally safe to switch between the two modes,
1040    /// switching from the compaction filter approach back to range deletion
1041    /// may result in some old versions that will never be pruned.
1042    #[serde(default, skip_serializing_if = "std::ops::Not::not")]
1043    pub enable_compaction_filter: bool,
1044    #[serde(skip_serializing_if = "Option::is_none")]
1045    pub num_epochs_to_retain_for_indexes: Option<u64>,
1046}
1047
1048fn default_num_latest_epoch_dbs_to_retain() -> usize {
1049    3
1050}
1051
1052fn default_max_transactions_in_batch() -> usize {
1053    1000
1054}
1055
1056fn default_max_checkpoints_in_batch() -> usize {
1057    10
1058}
1059
1060fn default_smoothing() -> bool {
1061    cfg!(not(test))
1062}
1063
1064fn default_periodic_compaction_threshold_days() -> Option<usize> {
1065    Some(1)
1066}
1067
1068impl Default for AuthorityStorePruningConfig {
1069    fn default() -> Self {
1070        Self {
1071            num_latest_epoch_dbs_to_retain: default_num_latest_epoch_dbs_to_retain(),
1072            num_epochs_to_retain: 0,
1073            pruning_run_delay_seconds: if cfg!(msim) { Some(2) } else { None },
1074            max_checkpoints_in_batch: default_max_checkpoints_in_batch(),
1075            max_transactions_in_batch: default_max_transactions_in_batch(),
1076            periodic_compaction_threshold_days: None,
1077            num_epochs_to_retain_for_checkpoints: if cfg!(msim) { Some(2) } else { None },
1078            smooth: true,
1079            enable_compaction_filter: cfg!(test) || cfg!(msim),
1080            num_epochs_to_retain_for_indexes: None,
1081        }
1082    }
1083}
1084
1085impl AuthorityStorePruningConfig {
1086    pub fn set_num_epochs_to_retain(&mut self, num_epochs_to_retain: u64) {
1087        self.num_epochs_to_retain = num_epochs_to_retain;
1088    }
1089
1090    pub fn set_num_epochs_to_retain_for_checkpoints(&mut self, num_epochs_to_retain: Option<u64>) {
1091        self.num_epochs_to_retain_for_checkpoints = num_epochs_to_retain;
1092    }
1093
1094    pub fn num_epochs_to_retain_for_checkpoints(&self) -> Option<u64> {
1095        self.num_epochs_to_retain_for_checkpoints
1096            // if n less than 2, coerce to 2 and log
1097            .map(|n| {
1098                if n < 2 {
1099                    info!("num_epochs_to_retain_for_checkpoints must be at least 2, rounding up from {}", n);
1100                    2
1101                } else {
1102                    n
1103                }
1104            })
1105    }
1106}
1107
1108#[derive(Debug, Clone, Deserialize, Serialize)]
1109#[serde(rename_all = "kebab-case")]
1110pub struct MetricsConfig {
1111    #[serde(skip_serializing_if = "Option::is_none")]
1112    pub push_interval_seconds: Option<u64>,
1113    #[serde(skip_serializing_if = "Option::is_none")]
1114    pub push_url: Option<String>,
1115}
1116
1117#[derive(Default, Debug, Clone, Deserialize, Serialize)]
1118#[serde(rename_all = "kebab-case")]
1119pub struct DBCheckpointConfig {
1120    #[serde(default)]
1121    pub perform_db_checkpoints_at_epoch_end: bool,
1122    #[serde(skip_serializing_if = "Option::is_none")]
1123    pub checkpoint_path: Option<PathBuf>,
1124    #[serde(skip_serializing_if = "Option::is_none")]
1125    pub object_store_config: Option<ObjectStoreConfig>,
1126    #[serde(skip_serializing_if = "Option::is_none")]
1127    pub perform_index_db_checkpoints_at_epoch_end: Option<bool>,
1128    #[serde(skip_serializing_if = "Option::is_none")]
1129    pub prune_and_compact_before_upload: Option<bool>,
1130}
1131
1132#[derive(Debug, Clone)]
1133pub struct ArchiveReaderConfig {
1134    pub remote_store_config: ObjectStoreConfig,
1135    pub download_concurrency: NonZeroUsize,
1136    pub use_for_pruning_watermark: bool,
1137}
1138
1139#[derive(Default, Debug, Clone, Deserialize, Serialize)]
1140#[serde(rename_all = "kebab-case")]
1141pub struct StateArchiveConfig {
1142    #[serde(skip_serializing_if = "Option::is_none")]
1143    pub object_store_config: Option<ObjectStoreConfig>,
1144    pub concurrency: usize,
1145    pub use_for_pruning_watermark: bool,
1146}
1147
1148#[derive(Default, Debug, Clone, Deserialize, Serialize)]
1149#[serde(rename_all = "kebab-case")]
1150pub struct StateSnapshotConfig {
1151    #[serde(skip_serializing_if = "Option::is_none")]
1152    pub object_store_config: Option<ObjectStoreConfig>,
1153    pub concurrency: usize,
1154}
1155
1156#[derive(Default, Debug, Clone, Deserialize, Serialize)]
1157#[serde(rename_all = "kebab-case")]
1158pub struct TransactionKeyValueStoreWriteConfig {
1159    pub aws_access_key_id: String,
1160    pub aws_secret_access_key: String,
1161    pub aws_region: String,
1162    pub table_name: String,
1163    pub bucket_name: String,
1164    pub concurrency: usize,
1165}
1166
1167/// Configuration for the threshold(s) at which we consider the system
1168/// to be overloaded. When one of the threshold is passed, the node may
1169/// stop processing new transactions and/or certificates until the congestion
1170/// resolves.
1171#[derive(Clone, Debug, Deserialize, Serialize)]
1172#[serde(rename_all = "kebab-case")]
1173pub struct AuthorityOverloadConfig {
1174    #[serde(default = "default_max_txn_age_in_queue")]
1175    pub max_txn_age_in_queue: Duration,
1176
1177    // The interval of checking overload signal.
1178    #[serde(default = "default_overload_monitor_interval")]
1179    pub overload_monitor_interval: Duration,
1180
1181    // The execution queueing latency when entering load shedding mode.
1182    #[serde(default = "default_execution_queue_latency_soft_limit")]
1183    pub execution_queue_latency_soft_limit: Duration,
1184
1185    // The execution queueing latency when entering aggressive load shedding mode.
1186    #[serde(default = "default_execution_queue_latency_hard_limit")]
1187    pub execution_queue_latency_hard_limit: Duration,
1188
1189    // The maximum percentage of transactions to shed in load shedding mode.
1190    #[serde(default = "default_max_load_shedding_percentage")]
1191    pub max_load_shedding_percentage: u32,
1192
1193    // When in aggressive load shedding mode, the minimum percentage of
1194    // transactions to shed.
1195    #[serde(default = "default_min_load_shedding_percentage_above_hard_limit")]
1196    pub min_load_shedding_percentage_above_hard_limit: u32,
1197
1198    // If transaction ready rate is below this rate, we consider the validator
1199    // is well under used, and will not enter load shedding mode.
1200    #[serde(default = "default_safe_transaction_ready_rate")]
1201    pub safe_transaction_ready_rate: u32,
1202
1203    // When set to true, transaction signing may be rejected when the validator
1204    // is overloaded.
1205    #[serde(default = "default_check_system_overload_at_signing")]
1206    pub check_system_overload_at_signing: bool,
1207
1208    // When set to true, transaction execution may be rejected when the validator
1209    // is overloaded.
1210    #[serde(default, skip_serializing_if = "std::ops::Not::not")]
1211    pub check_system_overload_at_execution: bool,
1212
1213    // Reject a transaction if transaction manager queue length is above this threshold.
1214    // 100_000 = 10k TPS * 5s resident time in transaction manager (pending + executing) * 2.
1215    #[serde(default = "default_max_transaction_manager_queue_length")]
1216    pub max_transaction_manager_queue_length: usize,
1217
1218    // Reject a transaction if the number of pending transactions depending on the object
1219    // is above the threshold.
1220    #[serde(default = "default_max_transaction_manager_per_object_queue_length")]
1221    pub max_transaction_manager_per_object_queue_length: usize,
1222}
1223
1224fn default_max_txn_age_in_queue() -> Duration {
1225    Duration::from_millis(500)
1226}
1227
1228fn default_overload_monitor_interval() -> Duration {
1229    Duration::from_secs(10)
1230}
1231
1232fn default_execution_queue_latency_soft_limit() -> Duration {
1233    Duration::from_secs(1)
1234}
1235
1236fn default_execution_queue_latency_hard_limit() -> Duration {
1237    Duration::from_secs(10)
1238}
1239
1240fn default_max_load_shedding_percentage() -> u32 {
1241    95
1242}
1243
1244fn default_min_load_shedding_percentage_above_hard_limit() -> u32 {
1245    50
1246}
1247
1248fn default_safe_transaction_ready_rate() -> u32 {
1249    100
1250}
1251
1252fn default_check_system_overload_at_signing() -> bool {
1253    true
1254}
1255
1256fn default_max_transaction_manager_queue_length() -> usize {
1257    100_000
1258}
1259
1260fn default_max_transaction_manager_per_object_queue_length() -> usize {
1261    20
1262}
1263
1264impl Default for AuthorityOverloadConfig {
1265    fn default() -> Self {
1266        Self {
1267            max_txn_age_in_queue: default_max_txn_age_in_queue(),
1268            overload_monitor_interval: default_overload_monitor_interval(),
1269            execution_queue_latency_soft_limit: default_execution_queue_latency_soft_limit(),
1270            execution_queue_latency_hard_limit: default_execution_queue_latency_hard_limit(),
1271            max_load_shedding_percentage: default_max_load_shedding_percentage(),
1272            min_load_shedding_percentage_above_hard_limit:
1273                default_min_load_shedding_percentage_above_hard_limit(),
1274            safe_transaction_ready_rate: default_safe_transaction_ready_rate(),
1275            check_system_overload_at_signing: true,
1276            check_system_overload_at_execution: false,
1277            max_transaction_manager_queue_length: default_max_transaction_manager_queue_length(),
1278            max_transaction_manager_per_object_queue_length:
1279                default_max_transaction_manager_per_object_queue_length(),
1280        }
1281    }
1282}
1283
1284fn default_authority_overload_config() -> AuthorityOverloadConfig {
1285    AuthorityOverloadConfig::default()
1286}
1287
1288fn default_traffic_controller_policy_config() -> Option<PolicyConfig> {
1289    Some(PolicyConfig::default_dos_protection_policy())
1290}
1291
1292#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, Eq)]
1293pub struct Genesis {
1294    #[serde(flatten)]
1295    location: Option<GenesisLocation>,
1296
1297    #[serde(skip)]
1298    genesis: once_cell::sync::OnceCell<genesis::Genesis>,
1299}
1300
1301impl Genesis {
1302    pub fn new(genesis: genesis::Genesis) -> Self {
1303        Self {
1304            location: Some(GenesisLocation::InPlace {
1305                genesis: Box::new(genesis),
1306            }),
1307            genesis: Default::default(),
1308        }
1309    }
1310
1311    pub fn new_from_file<P: Into<PathBuf>>(path: P) -> Self {
1312        Self {
1313            location: Some(GenesisLocation::File {
1314                genesis_file_location: path.into(),
1315            }),
1316            genesis: Default::default(),
1317        }
1318    }
1319
1320    pub fn new_empty() -> Self {
1321        Self {
1322            location: None,
1323            genesis: Default::default(),
1324        }
1325    }
1326
1327    pub fn genesis(&self) -> Result<&genesis::Genesis> {
1328        match &self.location {
1329            Some(GenesisLocation::InPlace { genesis }) => Ok(genesis),
1330            Some(GenesisLocation::File {
1331                genesis_file_location,
1332            }) => self
1333                .genesis
1334                .get_or_try_init(|| genesis::Genesis::load(genesis_file_location)),
1335            None => anyhow::bail!("no genesis location set"),
1336        }
1337    }
1338}
1339
1340#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, Eq)]
1341#[serde(untagged)]
1342enum GenesisLocation {
1343    InPlace {
1344        genesis: Box<genesis::Genesis>,
1345    },
1346    File {
1347        #[serde(rename = "genesis-file-location")]
1348        genesis_file_location: PathBuf,
1349    },
1350}
1351
1352/// Wrapper struct for IotaKeyPair that can be deserialized from a file path.
1353/// Used by network, worker, and account keypair.
1354#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
1355pub struct KeyPairWithPath {
1356    #[serde(flatten)]
1357    location: KeyPairLocation,
1358
1359    #[serde(skip)]
1360    keypair: OnceCell<Arc<IotaKeyPair>>,
1361}
1362
1363#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, Eq)]
1364#[serde(untagged)]
1365enum KeyPairLocation {
1366    InPlace {
1367        #[serde(with = "bech32_formatted_keypair")]
1368        value: Arc<IotaKeyPair>,
1369    },
1370    File {
1371        path: PathBuf,
1372    },
1373}
1374
1375impl KeyPairWithPath {
1376    pub fn new(kp: IotaKeyPair) -> Self {
1377        let cell: OnceCell<Arc<IotaKeyPair>> = OnceCell::new();
1378        let arc_kp = Arc::new(kp);
1379        // OK to unwrap panic because authority should not start without all keypairs
1380        // loaded.
1381        cell.set(arc_kp.clone()).expect("failed to set keypair");
1382        Self {
1383            location: KeyPairLocation::InPlace { value: arc_kp },
1384            keypair: cell,
1385        }
1386    }
1387
1388    pub fn new_from_path(path: PathBuf) -> Self {
1389        let cell: OnceCell<Arc<IotaKeyPair>> = OnceCell::new();
1390        // OK to unwrap panic because authority should not start without all keypairs
1391        // loaded.
1392        cell.set(Arc::new(read_keypair_from_file(&path).unwrap_or_else(
1393            |e| panic!("invalid keypair file at path {:?}: {e}", &path),
1394        )))
1395        .expect("failed to set keypair");
1396        Self {
1397            location: KeyPairLocation::File { path },
1398            keypair: cell,
1399        }
1400    }
1401
1402    pub fn keypair(&self) -> &IotaKeyPair {
1403        self.keypair
1404            .get_or_init(|| match &self.location {
1405                KeyPairLocation::InPlace { value } => value.clone(),
1406                KeyPairLocation::File { path } => {
1407                    // OK to unwrap panic because authority should not start without all keypairs
1408                    // loaded.
1409                    Arc::new(
1410                        read_keypair_from_file(path).unwrap_or_else(|e| {
1411                            panic!("invalid keypair file at path {path:?}: {e}")
1412                        }),
1413                    )
1414                }
1415            })
1416            .as_ref()
1417    }
1418}
1419
1420/// Wrapper struct for AuthorityKeyPair that can be deserialized from a file
1421/// path.
1422#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
1423pub struct AuthorityKeyPairWithPath {
1424    #[serde(flatten)]
1425    location: AuthorityKeyPairLocation,
1426
1427    #[serde(skip)]
1428    keypair: OnceCell<Arc<AuthorityKeyPair>>,
1429}
1430
1431#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, Eq)]
1432#[serde(untagged)]
1433enum AuthorityKeyPairLocation {
1434    InPlace { value: Arc<AuthorityKeyPair> },
1435    File { path: PathBuf },
1436}
1437
1438impl AuthorityKeyPairWithPath {
1439    pub fn new(kp: AuthorityKeyPair) -> Self {
1440        let cell: OnceCell<Arc<AuthorityKeyPair>> = OnceCell::new();
1441        let arc_kp = Arc::new(kp);
1442        // OK to unwrap panic because authority should not start without all keypairs
1443        // loaded.
1444        cell.set(arc_kp.clone())
1445            .expect("failed to set authority keypair");
1446        Self {
1447            location: AuthorityKeyPairLocation::InPlace { value: arc_kp },
1448            keypair: cell,
1449        }
1450    }
1451
1452    pub fn new_from_path(path: PathBuf) -> Self {
1453        let cell: OnceCell<Arc<AuthorityKeyPair>> = OnceCell::new();
1454        // OK to unwrap panic because authority should not start without all keypairs
1455        // loaded.
1456        cell.set(Arc::new(
1457            read_authority_keypair_from_file(&path)
1458                .unwrap_or_else(|_| panic!("invalid authority keypair file at path {:?}", &path)),
1459        ))
1460        .expect("failed to set authority keypair");
1461        Self {
1462            location: AuthorityKeyPairLocation::File { path },
1463            keypair: cell,
1464        }
1465    }
1466
1467    pub fn authority_keypair(&self) -> &AuthorityKeyPair {
1468        self.keypair
1469            .get_or_init(|| match &self.location {
1470                AuthorityKeyPairLocation::InPlace { value } => value.clone(),
1471                AuthorityKeyPairLocation::File { path } => {
1472                    // OK to unwrap panic because authority should not start without all keypairs
1473                    // loaded.
1474                    Arc::new(
1475                        read_authority_keypair_from_file(path).unwrap_or_else(|_| {
1476                            panic!("invalid authority keypair file {:?}", &path)
1477                        }),
1478                    )
1479                }
1480            })
1481            .as_ref()
1482    }
1483}
1484
1485/// Configurations which determine how we dump state debug info.
1486/// Debug info is dumped when a node forks.
1487#[derive(Clone, Debug, Deserialize, Serialize, Default)]
1488#[serde(rename_all = "kebab-case")]
1489pub struct StateDebugDumpConfig {
1490    #[serde(skip_serializing_if = "Option::is_none")]
1491    pub dump_file_directory: Option<PathBuf>,
1492}
1493
1494#[cfg(test)]
1495mod tests {
1496    use std::path::PathBuf;
1497
1498    use fastcrypto::traits::KeyPair;
1499    use iota_keys::keypair_file::{write_authority_keypair_to_file, write_keypair_to_file};
1500    use iota_types::crypto::{
1501        AuthorityKeyPair, IotaKeyPair, NetworkKeyPair, get_key_pair_from_rng,
1502    };
1503    use rand::{SeedableRng, rngs::StdRng};
1504
1505    use super::Genesis;
1506    use crate::NodeConfig;
1507
1508    #[test]
1509    fn serialize_genesis_from_file() {
1510        let g = Genesis::new_from_file("path/to/file");
1511
1512        let s = serde_yaml::to_string(&g).unwrap();
1513        assert_eq!("---\ngenesis-file-location: path/to/file\n", s);
1514        let loaded_genesis: Genesis = serde_yaml::from_str(&s).unwrap();
1515        assert_eq!(g, loaded_genesis);
1516    }
1517
1518    #[test]
1519    fn fullnode_template() {
1520        const TEMPLATE: &str = include_str!("../data/fullnode-template.yaml");
1521
1522        let _template: NodeConfig = serde_yaml::from_str(TEMPLATE).unwrap();
1523    }
1524
1525    #[test]
1526    fn load_key_pairs_to_node_config() {
1527        let authority_key_pair: AuthorityKeyPair =
1528            get_key_pair_from_rng(&mut StdRng::from_seed([0; 32])).1;
1529        let protocol_key_pair: NetworkKeyPair =
1530            get_key_pair_from_rng(&mut StdRng::from_seed([0; 32])).1;
1531        let network_key_pair: NetworkKeyPair =
1532            get_key_pair_from_rng(&mut StdRng::from_seed([0; 32])).1;
1533
1534        write_authority_keypair_to_file(&authority_key_pair, PathBuf::from("authority.key"))
1535            .unwrap();
1536        write_keypair_to_file(
1537            &IotaKeyPair::Ed25519(protocol_key_pair.copy()),
1538            PathBuf::from("protocol.key"),
1539        )
1540        .unwrap();
1541        write_keypair_to_file(
1542            &IotaKeyPair::Ed25519(network_key_pair.copy()),
1543            PathBuf::from("network.key"),
1544        )
1545        .unwrap();
1546
1547        const TEMPLATE: &str = include_str!("../data/fullnode-template-with-path.yaml");
1548        let template: NodeConfig = serde_yaml::from_str(TEMPLATE).unwrap();
1549        assert_eq!(
1550            template.authority_key_pair().public(),
1551            authority_key_pair.public()
1552        );
1553        assert_eq!(
1554            template.network_key_pair().public(),
1555            network_key_pair.public()
1556        );
1557        assert_eq!(
1558            template.protocol_key_pair().public(),
1559            protocol_key_pair.public()
1560        );
1561    }
1562}
1563
1564// RunWithRange is used to specify the ending epoch/checkpoint to process.
1565// this is intended for use with disaster recovery debugging and verification
1566// workflows, never in normal operations
1567#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize)]
1568pub enum RunWithRange {
1569    Epoch(EpochId),
1570    Checkpoint(CheckpointSequenceNumber),
1571}
1572
1573impl RunWithRange {
1574    // is epoch_id > RunWithRange::Epoch
1575    pub fn is_epoch_gt(&self, epoch_id: EpochId) -> bool {
1576        matches!(self, RunWithRange::Epoch(e) if epoch_id > *e)
1577    }
1578
1579    pub fn matches_checkpoint(&self, seq_num: CheckpointSequenceNumber) -> bool {
1580        matches!(self, RunWithRange::Checkpoint(seq) if *seq == seq_num)
1581    }
1582
1583    pub fn into_checkpoint_bound(self) -> Option<CheckpointSequenceNumber> {
1584        match self {
1585            RunWithRange::Epoch(_) => None,
1586            RunWithRange::Checkpoint(seq) => Some(seq),
1587        }
1588    }
1589}
1590
1591/// A serde helper module used with #[serde(with = "...")] to change the
1592/// de/serialization format of an `IotaKeyPair` to Bech32 when written to or
1593/// read from a node config.
1594mod bech32_formatted_keypair {
1595    use std::ops::Deref;
1596
1597    use iota_types::crypto::{EncodeDecodeBase64, IotaKeyPair};
1598    use serde::{Deserialize, Deserializer, Serializer};
1599
1600    pub fn serialize<S, T>(kp: &T, serializer: S) -> Result<S::Ok, S::Error>
1601    where
1602        S: Serializer,
1603        T: Deref<Target = IotaKeyPair>,
1604    {
1605        use serde::ser::Error;
1606
1607        // Serialize the keypair to a Bech32 string
1608        let s = kp.encode().map_err(Error::custom)?;
1609
1610        serializer.serialize_str(&s)
1611    }
1612
1613    pub fn deserialize<'de, D, T>(deserializer: D) -> Result<T, D::Error>
1614    where
1615        D: Deserializer<'de>,
1616        T: From<IotaKeyPair>,
1617    {
1618        use serde::de::Error;
1619
1620        let s = String::deserialize(deserializer)?;
1621
1622        // Try to deserialize the keypair from a Bech32 formatted string
1623        IotaKeyPair::decode(&s)
1624            .or_else(|_| {
1625                // For backwards compatibility try Base64 if Bech32 failed
1626                IotaKeyPair::decode_base64(&s)
1627            })
1628            .map(Into::into)
1629            .map_err(Error::custom)
1630    }
1631}