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