1#[cfg(msim)]
6use std::sync::atomic::Ordering;
7use std::{
8 collections::HashMap,
9 fmt,
10 future::Future,
11 num::NonZeroUsize,
12 path::PathBuf,
13 sync::{Arc, Weak},
14 time::Duration,
15};
16
17use anemo::Network;
18use anemo_tower::{
19 callback::CallbackLayer,
20 trace::{DefaultMakeSpan, DefaultOnFailure, TraceLayer},
21};
22use anyhow::{Result, anyhow};
23use arc_swap::ArcSwap;
24use futures::future::BoxFuture;
25pub use handle::IotaNodeHandle;
26use iota_common::{debug_fatal, fatal};
27use iota_config::{
28 ConsensusConfig, NodeConfig,
29 node::{DBCheckpointConfig, RunWithRange},
30 node_config_metrics::NodeConfigMetrics,
31};
32use iota_core::{
33 authority::{
34 AuthorityState, AuthorityStore, RandomnessRoundReceiver,
35 authority_per_epoch_store::AuthorityPerEpochStore,
36 authority_store_pruner::ObjectsCompactionFilter,
37 authority_store_tables::{
38 AuthorityPerpetualTables, AuthorityPerpetualTablesOptions, AuthorityPrunerTables,
39 },
40 backpressure::BackpressureManager,
41 epoch_start_configuration::{EpochFlag, EpochStartConfigTrait, EpochStartConfiguration},
42 },
43 authority_aggregator::{
44 AggregatorSendCapabilityNotificationError, AuthAggMetrics, AuthorityAggregator,
45 },
46 authority_client::NetworkAuthorityClient,
47 authority_server::{
48 ValidatorService, ValidatorServiceMetrics, soft_lock::PreConsensusSoftLocks,
49 },
50 checkpoint_progress_tracker::CheckpointProgressTracker,
51 checkpoints::{
52 CheckpointMetrics, CheckpointService, CheckpointStore, FullCheckpointContentsCache,
53 FullCheckpointContentsCacheMetrics, SendCheckpointToStateSync, SubmitCheckpointToConsensus,
54 checkpoint_executor::{CheckpointExecutor, StopReason, metrics::CheckpointExecutorMetrics},
55 },
56 connection_monitor::ConnectionMonitor,
57 consensus_adapter::{
58 CheckConnection, ConnectionMonitorStatus, ConsensusAdapter, ConsensusAdapterMetrics,
59 ConsensusClient,
60 },
61 consensus_handler::ConsensusHandlerInitializer,
62 consensus_manager::{ConsensusManager, ConsensusManagerTrait, UpdatableConsensusClient},
63 consensus_validator::{IotaTxValidator, IotaTxValidatorMetrics},
64 db_checkpoint_handler::DBCheckpointHandler,
65 epoch::{
66 committee_store::CommitteeStore, consensus_store_pruner::ConsensusStorePruner,
67 epoch_metrics::EpochMetrics, randomness::RandomnessManager,
68 reconfiguration::ReconfigurationInitiator,
69 },
70 execution_cache::build_execution_cache,
71 global_state_hasher::{GlobalStateHashMetrics, GlobalStateHasher},
72 grpc_indexes::{GRPC_INDEXES_DIR, GrpcIndexesStore},
73 jsonrpc_index::IndexStore,
74 module_cache_metrics::ResolverMetrics,
75 overload_monitor::{consensus_queue_overload_monitor, overload_monitor},
76 safe_client::SafeClientMetricsBase,
77 signature_verifier::SignatureVerifierMetrics,
78 storage::{GrpcReadStore, RocksDbStore},
79 transaction_orchestrator::TransactionOrchestrator,
80 validator_tx_finalizer::ValidatorTxFinalizer,
81};
82use iota_grpc_server::{GrpcReader, GrpcServerHandle, start_grpc_server};
83use iota_json_rpc::{
84 JsonRpcServerBuilder, coin_api::CoinReadApi, governance_api::GovernanceReadApi,
85 indexer_api::IndexerApi, move_utils::MoveUtils, read_api::ReadApi,
86 transaction_builder_api::TransactionBuilderApi,
87 transaction_execution_api::TransactionExecutionApi,
88};
89use iota_json_rpc_api::JsonRpcMetrics;
90use iota_macros::{fail_point, fail_point_async, replay_log};
91use iota_metrics::{
92 RegistryID, RegistryService,
93 metrics_network::{MetricsMakeCallbackHandler, NetworkConnectionMetrics, NetworkMetrics},
94 server_timing_middleware, spawn_monitored_task,
95};
96use iota_names::config::IotaNamesConfig;
97use iota_network::{
98 api::{ValidatorPeerServer, ValidatorServer, ValidatorV2Server},
99 discovery,
100 discovery::TrustedPeerChangeEvent,
101 randomness, state_sync,
102};
103use iota_network_stack::server::{IOTA_TLS_SERVER_NAME, ServerBuilder};
104use iota_protocol_config::{ProtocolConfig, ProtocolVersion};
105use iota_sdk_types::{
106 RandomnessRound,
107 crypto::{Intent, IntentMessage, IntentScope},
108};
109use iota_snapshot::uploader::StateSnapshotUploader;
110use iota_storage::{
111 http_key_value_store::HttpKVStore,
112 key_value_store::{FallbackTransactionKVStore, TransactionKeyValueStore},
113 key_value_store_metrics::KeyValueStoreMetrics,
114};
115use iota_types::{
116 base_types::{AuthorityName, ConciseableName, EpochId},
117 committee::Committee,
118 crypto::{AuthoritySignature, IotaAuthoritySignature, KeypairTraits},
119 deny_rule_governance::DenyRuleSet,
120 digests::ChainIdentifier,
121 error::{IotaError, IotaResult},
122 executable_transaction::VerifiedExecutableTransaction,
123 execution_config_utils::to_binary_config,
124 full_checkpoint_content::CheckpointData,
125 iota_system_state::{
126 IotaSystemState, IotaSystemStateTrait,
127 epoch_start_iota_system_state::{EpochStartSystemState, EpochStartSystemStateTrait},
128 },
129 messages_checkpoint::CheckpointSummaryExt,
130 messages_consensus::{
131 AuthorityCapabilitiesV1, ConsensusTransaction, ConsensusTransactionKind,
132 SignedAuthorityCapabilitiesV1, TransactionDenyRuleProposal,
133 },
134 messages_grpc::HandleCapabilityNotificationRequestV1,
135 quorum_driver_types::QuorumDriverEffectsQueueResult,
136 supported_protocol_versions::SupportedProtocolVersions,
137 transaction::{SenderSignedTransactionAPI, Transaction, VerifiedCertificate},
138};
139use prometheus_filtered::Registry;
140#[cfg(msim)]
141use simulator::*;
142use tap::tap::TapFallible;
143use tokio::{
144 sync::{Mutex, broadcast, mpsc, watch},
145 task::{JoinHandle, JoinSet},
146};
147use tokio_util::sync::CancellationToken;
148use tower::ServiceBuilder;
149use tracing::{Instrument, debug, error, error_span, info, trace_span, warn};
150use typed_store::{
151 DBMetrics,
152 rocks::{check_and_mark_db_corruption, default_db_options, unmark_db_corruption},
153};
154
155use crate::metrics::{GrpcMetrics, IotaNodeMetrics};
156
157pub mod admin;
158mod handle;
159pub mod metrics;
160
161pub struct ValidatorComponents {
162 validator_server_handle: SpawnOnce,
163 validator_overload_monitor_handle: Option<JoinHandle<()>>,
164 consensus_queue_overload_monitor_handle: Option<JoinHandle<()>>,
169 soft_lock_sweep_handle: JoinHandle<()>,
172 overload_notifier_handle: Option<JoinHandle<()>>,
173 consensus_manager: Arc<ConsensusManager>,
174 consensus_store_pruner: ConsensusStorePruner,
175 consensus_adapter: Arc<ConsensusAdapter>,
176 soft_locks: Arc<PreConsensusSoftLocks>,
177 checkpoint_service_tasks: JoinSet<()>,
179 checkpoint_metrics: Arc<CheckpointMetrics>,
180 iota_tx_validator_metrics: Arc<IotaTxValidatorMetrics>,
181 validator_registry_id: RegistryID,
182}
183
184#[cfg(msim)]
185mod simulator {
186 use std::sync::atomic::AtomicBool;
187
188 pub(super) struct SimState {
189 pub sim_node: iota_simulator::runtime::NodeHandle,
190 pub sim_safe_mode_expected: AtomicBool,
191 _leak_detector: iota_simulator::NodeLeakDetector,
192 }
193
194 impl Default for SimState {
195 fn default() -> Self {
196 Self {
197 sim_node: iota_simulator::runtime::NodeHandle::current(),
198 sim_safe_mode_expected: AtomicBool::new(false),
199 _leak_detector: iota_simulator::NodeLeakDetector::new(),
200 }
201 }
202 }
203}
204
205#[derive(Clone)]
206pub struct ServerVersion {
207 pub bin: &'static str,
208 pub version: &'static str,
209}
210
211impl ServerVersion {
212 pub fn new(bin: &'static str, version: &'static str) -> Self {
213 Self { bin, version }
214 }
215}
216
217impl std::fmt::Display for ServerVersion {
218 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
219 f.write_str(self.bin)?;
220 f.write_str("/")?;
221 f.write_str(self.version)
222 }
223}
224
225pub struct IotaNode {
226 config: NodeConfig,
227 validator_components: Mutex<Option<ValidatorComponents>>,
228 _http_server: Option<iota_http::ServerHandle>,
230 state: Arc<AuthorityState>,
231 transaction_orchestrator: Option<Arc<TransactionOrchestrator<NetworkAuthorityClient>>>,
232 registry_service: RegistryService,
233 metrics: Arc<IotaNodeMetrics>,
234
235 _discovery: discovery::Handle,
236 state_sync_handle: state_sync::Handle,
237 randomness_handle: randomness::Handle,
238 checkpoint_store: Arc<CheckpointStore>,
239 global_state_hasher: Mutex<Option<Arc<GlobalStateHasher>>>,
240 connection_monitor_status: Arc<ConnectionMonitorStatus>,
241
242 end_of_epoch_channel: broadcast::Sender<IotaSystemState>,
244
245 trusted_peer_change_tx: watch::Sender<TrustedPeerChangeEvent>,
248
249 backpressure_manager: Arc<BackpressureManager>,
250
251 checkpoint_progress_tracker: Arc<CheckpointProgressTracker>,
252
253 _db_checkpoint_handle: Option<tokio::sync::broadcast::Sender<()>>,
254
255 #[cfg(msim)]
256 sim_state: SimState,
257
258 _state_snapshot_uploader_handle: Option<broadcast::Sender<()>>,
259 shutdown_channel_tx: broadcast::Sender<Option<RunWithRange>>,
261
262 grpc_server_handle: Mutex<Option<GrpcServerHandle>>,
264
265 auth_agg: Arc<ArcSwap<AuthorityAggregator<NetworkAuthorityClient>>>,
271
272 serving_rt_handle: tokio::runtime::Handle,
275}
276
277impl fmt::Debug for IotaNode {
278 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
279 f.debug_struct("IotaNode")
280 .field("name", &self.state.name.concise())
281 .finish()
282 }
283}
284
285impl IotaNode {
286 pub async fn start(
297 config: NodeConfig,
298 registry_service: RegistryService,
299 ) -> Result<Arc<IotaNode>> {
300 Self::start_async(
301 config,
302 registry_service,
303 ServerVersion::new("iota-node", "unknown"),
304 tokio::runtime::Handle::current(),
305 )
306 .await
307 }
308
309 fn start_overload_notifier(
314 config: &NodeConfig,
315 state: Arc<AuthorityState>,
316 epoch_store: Arc<AuthorityPerEpochStore>,
317 consensus_adapter: Arc<ConsensusAdapter>,
318 ) -> Option<JoinHandle<()>> {
319 if !epoch_store.protocol_config().enable_pcool_flow() {
320 return None;
321 }
322
323 let poll_interval = config.authority_overload_config.overload_monitor_interval;
324 let authority_name = state.name;
325
326 Some(spawn_monitored_task!(async move {
327 let mut last_notified_percentage: u32 = epoch_store
329 .load_overload_notification(&authority_name)
330 .unwrap_or(0) as u32;
331 loop {
332 tokio::time::sleep(poll_interval).await;
333 let current = state
334 .overload_info
335 .local_load_shedding_percentage
336 .load(std::sync::atomic::Ordering::Relaxed);
337 if current != last_notified_percentage {
338 last_notified_percentage = current;
339 let transaction = ConsensusTransaction::new_overload_notification_v1(
340 authority_name,
341 current as u8,
342 );
343 if let Err(e) = consensus_adapter.submit(transaction, None, &epoch_store) {
344 tracing::warn!(
345 "Failed to submit overload notification to consensus: {:?}",
346 e
347 );
348 }
349 }
350 }
351 }))
352 }
353
354 pub async fn start_async(
355 config: NodeConfig,
356 registry_service: RegistryService,
357 server_version: ServerVersion,
358 serving_rt_handle: tokio::runtime::Handle,
359 ) -> Result<Arc<IotaNode>> {
360 NodeConfigMetrics::new(®istry_service.default_registry()).record_metrics(&config);
361 let mut config = config.clone();
362 if config.supported_protocol_versions.is_none() {
363 info!(
364 "populating config.supported_protocol_versions with default {:?}",
365 SupportedProtocolVersions::SYSTEM_DEFAULT
366 );
367 config.supported_protocol_versions = Some(SupportedProtocolVersions::SYSTEM_DEFAULT);
368 }
369
370 let run_with_range = config.run_with_range;
371 let is_validator = config.consensus_config().is_some();
372 let is_full_node = !is_validator;
373 let prometheus_registry = registry_service.default_registry();
374
375 info!(node =? config.authority_public_key(),
376 "Initializing iota-node listening on {}", config.network_address
377 );
378
379 let genesis = config.genesis()?.clone();
380
381 let chain_identifier = ChainIdentifier::from(*genesis.checkpoint().digest());
382 info!("IOTA chain identifier: {chain_identifier}");
383
384 let db_corrupted_path = &config.db_path().join("status");
386 if let Err(err) = check_and_mark_db_corruption(db_corrupted_path) {
387 panic!("Failed to check database corruption: {err}");
388 }
389
390 DBMetrics::init(&prometheus_registry);
392
393 iota_metrics::init_metrics(&prometheus_registry);
395 #[cfg(not(msim))]
398 iota_metrics::thread_stall_monitor::start_thread_stall_monitor();
399
400 #[cfg(not(msim))]
404 {
405 let runtime_monitor_metrics =
406 iota_metrics::runtime_metrics::RuntimeMonitorMetrics::new(&prometheus_registry);
407 iota_metrics::runtime_metrics::start_runtime_monitor(
408 "iota_node",
409 &tokio::runtime::Handle::current(),
410 runtime_monitor_metrics.clone(),
411 );
412 iota_metrics::runtime_metrics::start_runtime_monitor(
413 "serving",
414 &serving_rt_handle,
415 runtime_monitor_metrics,
416 );
417 }
418
419 prometheus_registry
421 .register(iota_metrics::uptime_metric(
422 if is_validator {
423 "validator"
424 } else {
425 "fullnode"
426 },
427 server_version.version,
428 &chain_identifier.to_string(),
429 ))
430 .expect("Failed registering uptime metric");
431
432 let migration_tx_data = if genesis.contains_migrations() {
435 Some(config.load_migration_tx_data()?)
438 } else {
439 None
440 };
441
442 let secret = Arc::pin(config.authority_key_pair().copy());
443 let genesis_committee = genesis.committee()?;
444 let committee_store = Arc::new(CommitteeStore::new(
445 config.db_path().join("epochs"),
446 &genesis_committee,
447 None,
448 ));
449
450 let mut pruner_db = None;
451 if config
452 .authority_store_pruning_config
453 .enable_compaction_filter
454 {
455 pruner_db = Some(Arc::new(AuthorityPrunerTables::open(
456 &config.db_path().join("store"),
457 )));
458 }
459 let compaction_filter = pruner_db
460 .clone()
461 .map(|db| ObjectsCompactionFilter::new(db, &prometheus_registry));
462
463 let enable_write_stall = config.enable_db_write_stall.unwrap_or(is_validator);
465 let perpetual_tables_options = AuthorityPerpetualTablesOptions {
466 enable_write_stall,
467 compaction_filter,
468 };
469 let perpetual_tables = Arc::new(AuthorityPerpetualTables::open(
470 &config.db_path().join("store"),
471 Some(perpetual_tables_options),
472 ));
473 let is_genesis = perpetual_tables
474 .database_is_empty()
475 .expect("Database read should not fail at init.");
476 let checkpoint_store = CheckpointStore::new_with_contents_cache(
477 &config.db_path().join("checkpoints"),
478 FullCheckpointContentsCache::new(
479 config
480 .full_checkpoint_contents_cache_size_mb
481 .saturating_mul(1024 * 1024),
482 FullCheckpointContentsCacheMetrics::new(&prometheus_registry),
483 ),
484 );
485 let backpressure_manager =
486 BackpressureManager::new_from_checkpoint_store(&checkpoint_store);
487
488 let perpetual_tables_for_progress = perpetual_tables.clone();
489 let store = AuthorityStore::open(
490 perpetual_tables,
491 &genesis,
492 &config,
493 &prometheus_registry,
494 migration_tx_data.as_ref(),
495 )
496 .await?;
497
498 let cur_epoch = store.get_recovery_epoch_at_restart()?;
499 let committee = committee_store
500 .get_committee(&cur_epoch)?
501 .expect("Committee of the current epoch must exist");
502 let epoch_start_configuration = store
503 .get_epoch_start_configuration()?
504 .expect("EpochStartConfiguration of the current epoch must exist");
505 let cache_metrics = Arc::new(ResolverMetrics::new(&prometheus_registry));
506 let signature_verifier_metrics = SignatureVerifierMetrics::new(&prometheus_registry);
507
508 let cache_traits = build_execution_cache(
509 &config.execution_cache_config,
510 &prometheus_registry,
511 &store,
512 backpressure_manager.clone(),
513 );
514
515 let auth_agg = {
516 let safe_client_metrics_base = SafeClientMetricsBase::new(&prometheus_registry);
517 let auth_agg_metrics = Arc::new(AuthAggMetrics::new(&prometheus_registry));
518 Arc::new(ArcSwap::new(Arc::new(
519 AuthorityAggregator::new_from_epoch_start_state(
520 epoch_start_configuration.epoch_start_state(),
521 &committee_store,
522 safe_client_metrics_base,
523 auth_agg_metrics,
524 ),
525 )))
526 };
527
528 let chain = match config.chain_override_for_testing {
529 Some(chain) => chain,
530 None => chain_identifier.chain(),
531 };
532
533 let epoch_options = default_db_options().optimize_db_for_write_throughput(4);
534 let epoch_store = AuthorityPerEpochStore::new(
535 config.authority_public_key(),
536 committee.clone(),
537 &config.db_path().join("store"),
538 Some(epoch_options.options),
539 EpochMetrics::new(®istry_service.default_registry()),
540 epoch_start_configuration,
541 cache_traits.backing_package_store.clone(),
542 cache_metrics,
543 signature_verifier_metrics,
544 &config.expensive_safety_check_config,
545 (chain_identifier, chain),
546 checkpoint_store
547 .get_highest_executed_checkpoint_seq_number()
548 .expect("checkpoint store read cannot fail")
549 .unwrap_or(0),
550 )?;
551
552 info!("created epoch store");
553
554 replay_log!(
555 "Beginning replay run. Epoch: {:?}, Protocol config: {:?}",
556 epoch_store.epoch(),
557 epoch_store.protocol_config()
558 );
559
560 if is_genesis {
562 info!("checking IOTA conservation at genesis");
563 cache_traits
568 .reconfig_api
569 .try_expensive_check_iota_conservation(&epoch_store, None)
570 .expect("IOTA conservation check cannot fail at genesis");
571 }
572
573 let effective_buffer_stake = epoch_store.get_effective_buffer_stake_bps();
574 let default_buffer_stake = epoch_store
575 .protocol_config()
576 .buffer_stake_for_protocol_upgrade_bps();
577 if effective_buffer_stake != default_buffer_stake {
578 warn!(
579 ?effective_buffer_stake,
580 ?default_buffer_stake,
581 "buffer_stake_for_protocol_upgrade_bps is currently overridden"
582 );
583 }
584
585 checkpoint_store.insert_genesis_checkpoint(
586 genesis.checkpoint(),
587 genesis.checkpoint_contents().clone(),
588 &epoch_store,
589 );
590
591 unmark_db_corruption(db_corrupted_path)?;
593
594 info!("creating state sync store");
595 let state_sync_store = RocksDbStore::new(
596 cache_traits.clone(),
597 committee_store.clone(),
598 checkpoint_store.clone(),
599 );
600
601 let index_store = if is_full_node && config.enable_index_processing {
602 info!("creating index store");
603 Some(Arc::new(IndexStore::new(
604 config.db_path().join("indexes"),
605 &prometheus_registry,
606 epoch_store
607 .protocol_config()
608 .max_move_identifier_len_as_option(),
609 )))
610 } else {
611 None
612 };
613
614 let grpc_indexes_store = if is_full_node && config.enable_grpc_api {
615 Some(Arc::new(
616 GrpcIndexesStore::new(
617 config.db_path().join(GRPC_INDEXES_DIR),
618 Arc::clone(&store),
619 &checkpoint_store,
620 )
621 .await,
622 ))
623 } else {
624 None
625 };
626
627 checkpoint_store
629 .seed_epoch_info(&store, chain_identifier)
630 .expect("failed to seed the epoch_info chain");
631
632 info!("creating archive reader");
633 let (trusted_peer_change_tx, trusted_peer_change_rx) = watch::channel(Default::default());
638 let (randomness_tx, randomness_rx) = mpsc::channel(
639 config
640 .p2p_config
641 .randomness
642 .clone()
643 .unwrap_or_default()
644 .mailbox_capacity(),
645 );
646 let (p2p_network, discovery_handle, state_sync_handle, randomness_handle) =
647 Self::create_p2p_network(
648 &config,
649 state_sync_store.clone(),
650 chain_identifier,
651 trusted_peer_change_rx,
652 randomness_tx,
653 &prometheus_registry,
654 )?;
655
656 send_trusted_peer_change(
659 &config,
660 &trusted_peer_change_tx,
661 epoch_store.epoch_start_state(),
662 );
663
664 info!("start snapshot upload");
665 let state_snapshot_handle = Self::start_state_snapshot(
667 &config,
668 &prometheus_registry,
669 checkpoint_store.clone(),
670 is_full_node,
671 )?;
672
673 let checkpoint_progress_tracker = Arc::new(CheckpointProgressTracker::new());
674
675 info!("start db checkpoint");
677 let (db_checkpoint_config, db_checkpoint_handle) = Self::start_db_checkpoint(
678 &config,
679 &prometheus_registry,
680 state_snapshot_handle.is_some(),
681 Some(checkpoint_progress_tracker.clone()),
682 )?;
683
684 let mut genesis_objects = genesis.objects().to_vec();
685 if let Some(migration_tx_data) = migration_tx_data.as_ref() {
686 genesis_objects.extend(migration_tx_data.get_objects());
687 }
688
689 let authority_name = config.authority_public_key();
690 let validator_tx_finalizer =
691 config
692 .enable_validator_tx_finalizer
693 .then_some(Arc::new(ValidatorTxFinalizer::new(
694 auth_agg.clone(),
695 authority_name,
696 &prometheus_registry,
697 )));
698
699 info!("create authority state");
700 let state = AuthorityState::new(
701 authority_name,
702 secret,
703 config.supported_protocol_versions.unwrap(),
704 store.clone(),
705 cache_traits.clone(),
706 epoch_store.clone(),
707 committee_store.clone(),
708 index_store.clone(),
709 grpc_indexes_store,
710 checkpoint_store.clone(),
711 &prometheus_registry,
712 &genesis_objects,
713 &db_checkpoint_config,
714 config.clone(),
715 validator_tx_finalizer,
716 chain_identifier,
717 pruner_db,
718 Some(checkpoint_progress_tracker.clone()),
719 config.policy_config.clone(),
720 config.firewall_config.clone(),
721 )
722 .await;
723
724 if epoch_store.epoch() == 0 {
726 let genesis_tx = &genesis.transaction();
727 let span = error_span!("genesis_txn", tx_digest = ?genesis_tx.digest());
728 Self::execute_transaction_immediately_at_zero_epoch(
730 &state,
731 &epoch_store,
732 genesis_tx,
733 span,
734 )
735 .await;
736
737 if let Some(migration_tx_data) = migration_tx_data {
739 for (tx_digest, (tx, _, _)) in migration_tx_data.txs_data() {
740 let span = error_span!("migration_txn", tx_digest = ?tx_digest);
741 Self::execute_transaction_immediately_at_zero_epoch(
742 &state,
743 &epoch_store,
744 tx,
745 span,
746 )
747 .await;
748 }
749 }
750 }
751
752 RandomnessRoundReceiver::spawn(state.clone(), randomness_rx);
755
756 if config
757 .expensive_safety_check_config
758 .enable_secondary_index_checks()
759 {
760 if let Some(indexes) = state.indexes.clone() {
761 iota_core::verify_indexes::verify_indexes(
762 state.get_global_state_hash_store().as_ref(),
763 indexes,
764 )
765 .expect("secondary indexes are inconsistent");
766 }
767 }
768
769 let (end_of_epoch_channel, end_of_epoch_receiver) =
770 broadcast::channel(config.end_of_epoch_broadcast_channel_capacity);
771
772 let transaction_orchestrator = if is_full_node && run_with_range.is_none() {
773 Some(Arc::new(TransactionOrchestrator::new_with_auth_aggregator(
774 auth_agg.load_full(),
775 state.clone(),
776 end_of_epoch_receiver,
777 &config.db_path(),
778 &prometheus_registry,
779 Some(&config),
780 )))
781 } else {
782 None
783 };
784
785 let http_server = serving_rt_handle
789 .spawn({
790 let state = state.clone();
791 let transaction_orchestrator = transaction_orchestrator.clone();
792 let config = config.clone();
793 let prometheus_registry = prometheus_registry.clone();
794 async move {
795 build_http_server(
796 state,
797 &transaction_orchestrator,
798 &config,
799 &prometheus_registry,
800 )
801 .await
802 }
803 })
804 .await
805 .expect("Failed to join JSON-RPC server startup task")?;
806
807 let global_state_hasher = Arc::new(GlobalStateHasher::new(
808 cache_traits.global_state_hash_store.clone(),
809 GlobalStateHashMetrics::new(&prometheus_registry),
810 ));
811
812 let authority_names_to_peer_ids = epoch_store
813 .epoch_start_state()
814 .get_authority_names_to_peer_ids();
815
816 let network_connection_metrics =
817 NetworkConnectionMetrics::new("iota", ®istry_service.default_registry());
818
819 let authority_names_to_peer_ids = ArcSwap::from_pointee(authority_names_to_peer_ids);
820
821 let (_connection_monitor_handle, connection_statuses) = ConnectionMonitor::spawn(
822 p2p_network.downgrade(),
823 network_connection_metrics,
824 HashMap::new(),
825 None,
826 );
827
828 let connection_monitor_status = ConnectionMonitorStatus {
829 connection_statuses,
830 authority_names_to_peer_ids,
831 };
832
833 let connection_monitor_status = Arc::new(connection_monitor_status);
834 let iota_node_metrics =
835 Arc::new(IotaNodeMetrics::new(®istry_service.default_registry()));
836
837 iota_node_metrics
838 .binary_max_protocol_version
839 .set(ProtocolVersion::MAX.as_u64() as i64);
840 iota_node_metrics
841 .configured_max_protocol_version
842 .set(config.supported_protocol_versions.unwrap().max.as_u64() as i64);
843
844 let executor: Option<Arc<dyn iota_types::transaction_executor::TransactionExecutor>> =
848 transaction_orchestrator
849 .clone()
850 .map(|o| o as Arc<dyn iota_types::transaction_executor::TransactionExecutor>);
851
852 let grpc_server_handle = serving_rt_handle
855 .spawn({
856 let config = config.clone();
857 let state = state.clone();
858 let state_sync_store = state_sync_store.clone();
859 let prometheus_registry = prometheus_registry.clone();
860 async move {
861 build_grpc_server(
862 &config,
863 state,
864 state_sync_store,
865 executor,
866 &prometheus_registry,
867 server_version,
868 )
869 .await
870 }
871 })
872 .await
873 .expect("Failed to join gRPC server startup task")?;
874
875 let validator_components = if state.is_committee_validator(&epoch_store) {
876 let (components, _) = futures::join!(
877 Self::construct_validator_components(
878 config.clone(),
879 state.clone(),
880 committee,
881 epoch_store.clone(),
882 checkpoint_store.clone(),
883 state_sync_handle.clone(),
884 randomness_handle.clone(),
885 Arc::downgrade(&global_state_hasher),
886 backpressure_manager.clone(),
887 connection_monitor_status.clone(),
888 ®istry_service,
889 serving_rt_handle.clone(),
890 ),
891 Self::reexecute_pending_consensus_certs(&epoch_store, &state,)
892 );
893 let mut components = components?;
894
895 components.consensus_adapter.submit_recovered(&epoch_store);
896
897 components.validator_server_handle = components.validator_server_handle.start().await;
899
900 Some(components)
901 } else {
902 None
903 };
904
905 let (shutdown_channel, _) = broadcast::channel::<Option<RunWithRange>>(1);
907
908 let node = Self {
909 config,
910 validator_components: Mutex::new(validator_components),
911 _http_server: http_server,
912 state,
913 transaction_orchestrator,
914 registry_service,
915 metrics: iota_node_metrics,
916
917 _discovery: discovery_handle,
918 state_sync_handle,
919 randomness_handle,
920 checkpoint_store,
921 global_state_hasher: Mutex::new(Some(global_state_hasher)),
922 end_of_epoch_channel,
923 connection_monitor_status,
924 trusted_peer_change_tx,
925 backpressure_manager,
926 checkpoint_progress_tracker: checkpoint_progress_tracker.clone(),
927
928 _db_checkpoint_handle: db_checkpoint_handle,
929
930 #[cfg(msim)]
931 sim_state: Default::default(),
932
933 _state_snapshot_uploader_handle: state_snapshot_handle,
934 shutdown_channel_tx: shutdown_channel,
935
936 grpc_server_handle: Mutex::new(grpc_server_handle),
937
938 auth_agg,
939
940 serving_rt_handle,
941 };
942
943 info!("IotaNode started!");
944 let node = Arc::new(node);
945 let node_copy = node.clone();
946 spawn_monitored_task!(async move {
947 let result = Self::monitor_reconfiguration(node_copy, epoch_store).await;
948 if let Err(error) = result {
949 warn!("Reconfiguration finished with error {:?}", error);
950 }
951 });
952
953 node.checkpoint_progress_tracker
954 .spawn_logging_task(node.checkpoint_store.clone(), perpetual_tables_for_progress);
955
956 Ok(node)
957 }
958
959 pub fn subscribe_to_epoch_change(&self) -> broadcast::Receiver<IotaSystemState> {
960 self.end_of_epoch_channel.subscribe()
961 }
962
963 pub fn subscribe_to_shutdown_channel(&self) -> broadcast::Receiver<Option<RunWithRange>> {
964 self.shutdown_channel_tx.subscribe()
965 }
966
967 pub fn current_epoch_for_testing(&self) -> EpochId {
968 self.state.current_epoch_for_testing()
969 }
970
971 pub fn db_checkpoint_path(&self) -> PathBuf {
972 self.config.db_checkpoint_path()
973 }
974
975 pub async fn close_epoch(&self, epoch_store: &Arc<AuthorityPerEpochStore>) -> IotaResult {
977 info!("close_epoch (current epoch = {})", epoch_store.epoch());
978 self.validator_components
979 .lock()
980 .await
981 .as_ref()
982 .ok_or_else(|| IotaError::from("Node is not a validator"))?
983 .consensus_adapter
984 .close_epoch(epoch_store);
985 Ok(())
986 }
987
988 pub fn clear_override_protocol_upgrade_buffer_stake(&self, epoch: EpochId) -> IotaResult {
989 self.state
990 .clear_override_protocol_upgrade_buffer_stake(epoch)
991 }
992
993 pub fn set_override_protocol_upgrade_buffer_stake(
994 &self,
995 epoch: EpochId,
996 buffer_stake_bps: u64,
997 ) -> IotaResult {
998 self.state
999 .set_override_protocol_upgrade_buffer_stake(epoch, buffer_stake_bps)
1000 }
1001
1002 pub async fn close_epoch_for_testing(&self) -> IotaResult {
1005 let epoch_store = self.state.epoch_store_for_testing();
1006 self.close_epoch(&epoch_store).await
1007 }
1008
1009 fn start_state_snapshot(
1012 config: &NodeConfig,
1013 prometheus_registry: &Registry,
1014 checkpoint_store: Arc<CheckpointStore>,
1015 is_full_node: bool,
1016 ) -> Result<Option<tokio::sync::broadcast::Sender<()>>> {
1017 if let Some(remote_store_config) = &config.state_snapshot_write_config.object_store_config {
1018 anyhow::ensure!(
1020 is_full_node,
1021 "Snapshot upload is configured, but this node is a validator. \
1022 Snapshot publication is only supported on fullnodes. Remove the \
1023 `state_snapshot_write_config.object_store_config` setting, or move \
1024 the upload to a fullnode."
1025 );
1026 let snapshot_uploader = StateSnapshotUploader::new(
1027 &config.db_checkpoint_path(),
1028 &config.snapshot_path(),
1029 remote_store_config.clone(),
1030 config.state_snapshot_write_config.concurrency,
1031 60,
1032 prometheus_registry,
1033 checkpoint_store,
1034 )?;
1035 Ok(Some(snapshot_uploader.start()))
1036 } else {
1037 Ok(None)
1038 }
1039 }
1040
1041 fn start_db_checkpoint(
1042 config: &NodeConfig,
1043 prometheus_registry: &Registry,
1044 state_snapshot_enabled: bool,
1045 checkpoint_progress_tracker: Option<Arc<CheckpointProgressTracker>>,
1046 ) -> Result<(
1047 DBCheckpointConfig,
1048 Option<tokio::sync::broadcast::Sender<()>>,
1049 )> {
1050 let checkpoint_path = Some(
1051 config
1052 .db_checkpoint_config
1053 .checkpoint_path
1054 .clone()
1055 .unwrap_or_else(|| config.db_checkpoint_path()),
1056 );
1057 let db_checkpoint_config = if config.db_checkpoint_config.checkpoint_path.is_none() {
1058 DBCheckpointConfig {
1059 checkpoint_path,
1060 perform_db_checkpoints_at_epoch_end: if state_snapshot_enabled {
1061 true
1062 } else {
1063 config
1064 .db_checkpoint_config
1065 .perform_db_checkpoints_at_epoch_end
1066 },
1067 ..config.db_checkpoint_config.clone()
1068 }
1069 } else {
1070 config.db_checkpoint_config.clone()
1071 };
1072
1073 match (
1074 db_checkpoint_config.object_store_config.as_ref(),
1075 state_snapshot_enabled,
1076 ) {
1077 (None, false) => Ok((db_checkpoint_config, None)),
1082 (_, _) => {
1083 let handler = DBCheckpointHandler::new(
1084 &db_checkpoint_config.checkpoint_path.clone().unwrap(),
1085 db_checkpoint_config.object_store_config.as_ref(),
1086 60,
1087 db_checkpoint_config
1088 .prune_and_compact_before_upload
1089 .unwrap_or(true),
1090 config.authority_store_pruning_config.clone(),
1091 prometheus_registry,
1092 state_snapshot_enabled,
1093 checkpoint_progress_tracker,
1094 )?;
1095 Ok((
1096 db_checkpoint_config,
1097 Some(DBCheckpointHandler::start(handler)),
1098 ))
1099 }
1100 }
1101 }
1102
1103 fn create_p2p_network(
1104 config: &NodeConfig,
1105 state_sync_store: RocksDbStore,
1106 chain_identifier: ChainIdentifier,
1107 trusted_peer_change_rx: watch::Receiver<TrustedPeerChangeEvent>,
1108 randomness_tx: mpsc::Sender<(EpochId, RandomnessRound, Vec<u8>)>,
1109 prometheus_registry: &Registry,
1110 ) -> Result<(
1111 Network,
1112 discovery::Handle,
1113 state_sync::Handle,
1114 randomness::Handle,
1115 )> {
1116 let (state_sync, state_sync_server) = state_sync::Builder::new()
1117 .config(config.p2p_config.state_sync.clone().unwrap_or_default())
1118 .store(state_sync_store)
1119 .checkpoint_archive_config(config.checkpoint_archive_config().cloned())
1120 .with_metrics(prometheus_registry)
1121 .build();
1122
1123 let (discovery, discovery_server) = discovery::Builder::new(trusted_peer_change_rx)
1124 .config(config.p2p_config.clone())
1125 .build();
1126
1127 let (randomness, randomness_router) =
1128 randomness::Builder::new(config.authority_public_key(), randomness_tx)
1129 .config(config.p2p_config.randomness.clone().unwrap_or_default())
1130 .with_metrics(prometheus_registry)
1131 .build();
1132
1133 let p2p_network = {
1134 let routes = anemo::Router::new()
1135 .add_rpc_service(discovery_server)
1136 .add_rpc_service(state_sync_server);
1137 let routes = routes.merge(randomness_router);
1138
1139 let inbound_network_metrics =
1140 NetworkMetrics::new("iota", "inbound", prometheus_registry);
1141 let outbound_network_metrics =
1142 NetworkMetrics::new("iota", "outbound", prometheus_registry);
1143
1144 let service = ServiceBuilder::new()
1145 .layer(
1146 TraceLayer::new_for_server_errors()
1147 .make_span_with(DefaultMakeSpan::new().level(tracing::Level::INFO))
1148 .on_failure(DefaultOnFailure::new().level(tracing::Level::WARN)),
1149 )
1150 .layer(CallbackLayer::new(MetricsMakeCallbackHandler::new(
1151 Arc::new(inbound_network_metrics),
1152 config.p2p_config.excessive_message_size(),
1153 )))
1154 .service(routes);
1155
1156 let outbound_layer = ServiceBuilder::new()
1157 .layer(
1158 TraceLayer::new_for_client_and_server_errors()
1159 .make_span_with(DefaultMakeSpan::new().level(tracing::Level::INFO))
1160 .on_failure(DefaultOnFailure::new().level(tracing::Level::DEBUG)),
1161 )
1162 .layer(CallbackLayer::new(MetricsMakeCallbackHandler::new(
1163 Arc::new(outbound_network_metrics),
1164 config.p2p_config.excessive_message_size(),
1165 )))
1166 .into_inner();
1167
1168 let mut anemo_config = config.p2p_config.anemo_config.clone().unwrap_or_default();
1169 anemo_config.max_frame_size = Some(1 << 30);
1172
1173 let mut quic_config = anemo_config.quic.unwrap_or_default();
1176 if quic_config.socket_send_buffer_size.is_none() {
1177 quic_config.socket_send_buffer_size = Some(20 << 20);
1178 }
1179 if quic_config.socket_receive_buffer_size.is_none() {
1180 quic_config.socket_receive_buffer_size = Some(20 << 20);
1181 }
1182 quic_config.allow_failed_socket_buffer_size_setting = true;
1183
1184 if quic_config.max_concurrent_bidi_streams.is_none() {
1187 quic_config.max_concurrent_bidi_streams = Some(500);
1188 }
1189 if quic_config.max_concurrent_uni_streams.is_none() {
1190 quic_config.max_concurrent_uni_streams = Some(500);
1191 }
1192 if quic_config.stream_receive_window.is_none() {
1193 quic_config.stream_receive_window = Some(100 << 20);
1194 }
1195 if quic_config.receive_window.is_none() {
1196 quic_config.receive_window = Some(200 << 20);
1197 }
1198 if quic_config.send_window.is_none() {
1199 quic_config.send_window = Some(200 << 20);
1200 }
1201 if quic_config.crypto_buffer_size.is_none() {
1202 quic_config.crypto_buffer_size = Some(1 << 20);
1203 }
1204 if quic_config.max_idle_timeout_ms.is_none() {
1205 quic_config.max_idle_timeout_ms = Some(30_000);
1206 }
1207 if quic_config.keep_alive_interval_ms.is_none() {
1208 quic_config.keep_alive_interval_ms = Some(5_000);
1209 }
1210 anemo_config.quic = Some(quic_config);
1211
1212 let server_name = format!("iota-{chain_identifier}");
1213 let network = Network::bind(config.p2p_config.listen_address)
1214 .server_name(&server_name)
1215 .private_key(config.network_key_pair().copy().private().0.to_bytes())
1216 .config(anemo_config)
1217 .outbound_request_layer(outbound_layer)
1218 .start(service)?;
1219 info!(
1220 server_name = server_name,
1221 "P2p network started on {}",
1222 network.local_addr()
1223 );
1224
1225 network
1226 };
1227
1228 let discovery_handle =
1229 discovery.start(p2p_network.clone(), config.network_key_pair().copy());
1230 let state_sync_handle = state_sync.start(p2p_network.clone());
1231 let randomness_handle = randomness.start(p2p_network.clone());
1232
1233 Ok((
1234 p2p_network,
1235 discovery_handle,
1236 state_sync_handle,
1237 randomness_handle,
1238 ))
1239 }
1240
1241 async fn construct_validator_components(
1244 config: NodeConfig,
1245 state: Arc<AuthorityState>,
1246 committee: Arc<Committee>,
1247 epoch_store: Arc<AuthorityPerEpochStore>,
1248 checkpoint_store: Arc<CheckpointStore>,
1249 state_sync_handle: state_sync::Handle,
1250 randomness_handle: randomness::Handle,
1251 global_state_hasher: Weak<GlobalStateHasher>,
1252 backpressure_manager: Arc<BackpressureManager>,
1253 connection_monitor_status: Arc<ConnectionMonitorStatus>,
1254 registry_service: &RegistryService,
1255 serving_rt_handle: tokio::runtime::Handle,
1256 ) -> Result<ValidatorComponents> {
1257 let mut config_clone = config.clone();
1258 let consensus_config = config_clone
1259 .consensus_config
1260 .as_mut()
1261 .ok_or_else(|| anyhow!("Validator is missing consensus config"))?;
1262 let validator_registry = registry_service.new_registry_custom(None, None)?;
1263 let validator_registry_id = registry_service.add(validator_registry.clone());
1264
1265 let client = Arc::new(UpdatableConsensusClient::new());
1266 let consensus_adapter = Arc::new(Self::construct_consensus_adapter(
1267 &committee,
1268 consensus_config,
1269 state.name,
1270 connection_monitor_status.clone(),
1271 &validator_registry,
1272 client.clone(),
1273 checkpoint_store.clone(),
1274 ));
1275 let consensus_manager = Arc::new(ConsensusManager::new(
1276 &config,
1277 consensus_config,
1278 registry_service,
1279 &validator_registry,
1280 client,
1281 ));
1282
1283 let consensus_store_pruner = ConsensusStorePruner::new(
1286 consensus_manager.get_storage_base_path(),
1287 consensus_config.db_retention_epochs(),
1288 consensus_config.db_pruner_period(),
1289 &validator_registry,
1290 );
1291
1292 let soft_locks = Arc::new(if config.enable_soft_locking {
1293 PreConsensusSoftLocks::new()
1294 } else {
1295 info!("pre-consensus soft-locking disabled via node config");
1296 PreConsensusSoftLocks::disabled()
1297 });
1298
1299 let checkpoint_metrics = CheckpointMetrics::new(&validator_registry);
1300 let iota_tx_validator_metrics = IotaTxValidatorMetrics::new(&validator_registry);
1301 let validator_service_metrics = Arc::new(ValidatorServiceMetrics::new(&validator_registry));
1302
1303 let soft_lock_sweep_handle = PreConsensusSoftLocks::spawn_sweep(
1314 Arc::downgrade(&soft_locks),
1315 validator_service_metrics.clone(),
1316 );
1317
1318 let validator_server_handle = Self::start_grpc_validator_service(
1319 &config,
1320 state.clone(),
1321 consensus_adapter.clone(),
1322 &validator_registry,
1323 soft_locks.clone(),
1324 validator_service_metrics.clone(),
1325 serving_rt_handle,
1326 )
1327 .await?;
1328
1329 let validator_overload_monitor_handle = if config
1332 .authority_overload_config
1333 .max_load_shedding_percentage
1334 > 0
1335 {
1336 let authority_state = Arc::downgrade(&state);
1337 let overload_config = config.authority_overload_config.clone();
1338 fail_point!("starting_overload_monitor");
1339 Some(spawn_monitored_task!(overload_monitor(
1340 authority_state,
1341 overload_config,
1342 )))
1343 } else {
1344 None
1345 };
1346
1347 let consensus_queue_overload_monitor_handle =
1354 if epoch_store.protocol_config().enable_pcool_flow() {
1355 let consensus_queue_monitor_authority_state = Arc::downgrade(&state);
1356 let consensus_queue_monitor_consensus_adapter = Arc::downgrade(&consensus_adapter);
1357 let consensus_queue_monitor_interval =
1358 config.authority_overload_config.overload_monitor_interval;
1359 Some(spawn_monitored_task!(consensus_queue_overload_monitor(
1360 consensus_queue_monitor_authority_state,
1361 consensus_queue_monitor_consensus_adapter,
1362 consensus_queue_monitor_interval,
1363 )))
1364 } else {
1365 None
1366 };
1367
1368 Self::start_epoch_specific_validator_components(
1369 &config,
1370 state.clone(),
1371 consensus_adapter,
1372 checkpoint_store,
1373 epoch_store,
1374 state_sync_handle,
1375 randomness_handle,
1376 consensus_manager,
1377 consensus_store_pruner,
1378 global_state_hasher,
1379 backpressure_manager,
1380 soft_locks,
1381 validator_server_handle,
1382 validator_overload_monitor_handle,
1383 consensus_queue_overload_monitor_handle,
1384 soft_lock_sweep_handle,
1385 checkpoint_metrics,
1386 iota_tx_validator_metrics,
1387 validator_registry_id,
1388 )
1389 .await
1390 }
1391
1392 async fn start_epoch_specific_validator_components(
1395 config: &NodeConfig,
1396 state: Arc<AuthorityState>,
1397 consensus_adapter: Arc<ConsensusAdapter>,
1398 checkpoint_store: Arc<CheckpointStore>,
1399 epoch_store: Arc<AuthorityPerEpochStore>,
1400 state_sync_handle: state_sync::Handle,
1401 randomness_handle: randomness::Handle,
1402 consensus_manager: Arc<ConsensusManager>,
1403 consensus_store_pruner: ConsensusStorePruner,
1404 global_state_hasher: Weak<GlobalStateHasher>,
1405 backpressure_manager: Arc<BackpressureManager>,
1406 soft_locks: Arc<PreConsensusSoftLocks>,
1407 validator_server_handle: SpawnOnce,
1408 validator_overload_monitor_handle: Option<JoinHandle<()>>,
1409 consensus_queue_overload_monitor_handle: Option<JoinHandle<()>>,
1410 soft_lock_sweep_handle: JoinHandle<()>,
1411 checkpoint_metrics: Arc<CheckpointMetrics>,
1412 iota_tx_validator_metrics: Arc<IotaTxValidatorMetrics>,
1413 validator_registry_id: RegistryID,
1414 ) -> Result<ValidatorComponents> {
1415 let checkpoint_service = Self::build_checkpoint_service(
1416 config,
1417 consensus_adapter.clone(),
1418 checkpoint_store.clone(),
1419 epoch_store.clone(),
1420 state.clone(),
1421 state_sync_handle,
1422 global_state_hasher,
1423 checkpoint_metrics.clone(),
1424 );
1425
1426 let low_scoring_authorities = Arc::new(ArcSwap::new(Arc::new(HashMap::new())));
1431
1432 consensus_adapter.swap_low_scoring_authorities(low_scoring_authorities.clone());
1433
1434 soft_locks.clear();
1439 epoch_store.set_soft_locks(soft_locks.clone());
1440
1441 let randomness_manager = match RandomnessManager::try_new(
1446 Arc::downgrade(&epoch_store),
1447 Box::new(consensus_adapter.clone()),
1448 randomness_handle,
1449 config.authority_key_pair(),
1450 )
1451 .await
1452 {
1453 Ok(randomness_manager) => randomness_manager,
1454 Err(err) => {
1455 fatal!(
1456 "validator cannot start epoch {} without a randomness manager: {err}",
1457 epoch_store.epoch()
1458 );
1459 }
1460 };
1461 epoch_store
1462 .set_randomness_manager(randomness_manager)
1463 .await?;
1464
1465 let consensus_handler_initializer = ConsensusHandlerInitializer::new(
1466 state.clone(),
1467 checkpoint_service.clone(),
1468 epoch_store.clone(),
1469 low_scoring_authorities,
1470 backpressure_manager,
1471 );
1472
1473 info!("Starting consensus manager asynchronously");
1474
1475 tokio::spawn({
1477 let config = config.clone();
1478 let epoch_store = epoch_store.clone();
1479 let iota_tx_validator = IotaTxValidator::new(
1480 epoch_store.clone(),
1481 checkpoint_service.clone(),
1482 state.transaction_manager().clone(),
1483 iota_tx_validator_metrics.clone(),
1484 );
1485 let consensus_manager = consensus_manager.clone();
1486 async move {
1487 consensus_manager
1488 .start(
1489 &config,
1490 epoch_store,
1491 consensus_handler_initializer,
1492 iota_tx_validator,
1493 )
1494 .await;
1495 }
1496 });
1497 let replay_waiter = consensus_manager.replay_waiter();
1498
1499 info!("Spawning checkpoint service");
1500 let replay_waiter = if std::env::var("DISABLE_REPLAY_WAITER").is_ok() {
1501 None
1502 } else {
1503 Some(replay_waiter)
1504 };
1505 let checkpoint_service_tasks = checkpoint_service.spawn(replay_waiter).await;
1506
1507 let overload_notifier_handle = Self::start_overload_notifier(
1508 config,
1509 state.clone(),
1510 epoch_store.clone(),
1511 consensus_adapter.clone(),
1512 );
1513
1514 Ok(ValidatorComponents {
1515 validator_server_handle,
1516 validator_overload_monitor_handle,
1517 consensus_queue_overload_monitor_handle,
1518 soft_lock_sweep_handle,
1519 overload_notifier_handle,
1520 consensus_manager,
1521 consensus_store_pruner,
1522 consensus_adapter,
1523 soft_locks,
1524 checkpoint_service_tasks,
1525 checkpoint_metrics,
1526 iota_tx_validator_metrics,
1527 validator_registry_id,
1528 })
1529 }
1530
1531 fn build_checkpoint_service(
1538 config: &NodeConfig,
1539 consensus_adapter: Arc<ConsensusAdapter>,
1540 checkpoint_store: Arc<CheckpointStore>,
1541 epoch_store: Arc<AuthorityPerEpochStore>,
1542 state: Arc<AuthorityState>,
1543 state_sync_handle: state_sync::Handle,
1544 global_state_hasher: Weak<GlobalStateHasher>,
1545 checkpoint_metrics: Arc<CheckpointMetrics>,
1546 ) -> Arc<CheckpointService> {
1547 let epoch_start_timestamp_ms = epoch_store.epoch_start_state().epoch_start_timestamp_ms();
1548 let epoch_duration_ms = epoch_store.epoch_start_state().epoch_duration_ms();
1549
1550 debug!(
1551 "Starting checkpoint service with epoch start timestamp {}
1552 and epoch duration {}",
1553 epoch_start_timestamp_ms, epoch_duration_ms
1554 );
1555
1556 let checkpoint_output = Box::new(SubmitCheckpointToConsensus {
1557 sender: consensus_adapter,
1558 signer: state.secret.clone(),
1559 authority: config.authority_public_key(),
1560 next_reconfiguration_timestamp_ms: epoch_start_timestamp_ms
1561 .checked_add(epoch_duration_ms)
1562 .expect("Overflow calculating next_reconfiguration_timestamp_ms"),
1563 metrics: checkpoint_metrics.clone(),
1564 });
1565
1566 let certified_checkpoint_output = SendCheckpointToStateSync::new(state_sync_handle);
1567 let max_tx_per_checkpoint = max_tx_per_checkpoint(epoch_store.protocol_config());
1568 let max_checkpoint_size_bytes =
1569 epoch_store.protocol_config().max_checkpoint_size_bytes() as usize;
1570
1571 CheckpointService::build(
1572 state.clone(),
1573 checkpoint_store,
1574 epoch_store,
1575 state.get_transaction_cache_reader().clone(),
1576 global_state_hasher,
1577 checkpoint_output,
1578 Box::new(certified_checkpoint_output),
1579 checkpoint_metrics,
1580 max_tx_per_checkpoint,
1581 max_checkpoint_size_bytes,
1582 )
1583 }
1584
1585 fn construct_consensus_adapter(
1586 committee: &Committee,
1587 consensus_config: &ConsensusConfig,
1588 authority: AuthorityName,
1589 connection_monitor_status: Arc<ConnectionMonitorStatus>,
1590 prometheus_registry: &Registry,
1591 consensus_client: Arc<dyn ConsensusClient>,
1592 checkpoint_store: Arc<CheckpointStore>,
1593 ) -> ConsensusAdapter {
1594 let ca_metrics = ConsensusAdapterMetrics::new(prometheus_registry);
1595 ConsensusAdapter::new(
1599 consensus_client,
1600 checkpoint_store,
1601 authority,
1602 connection_monitor_status,
1603 consensus_config.max_pending_transactions(),
1604 consensus_config.max_pending_transactions() * 2 / committee.num_members(),
1605 consensus_config.max_submit_position,
1606 consensus_config.submit_delay_step_override(),
1607 ca_metrics,
1608 consensus_config.graduated_load_shedding_soft_limit_pct(),
1609 )
1610 }
1611
1612 async fn start_grpc_validator_service(
1613 config: &NodeConfig,
1614 state: Arc<AuthorityState>,
1615 consensus_adapter: Arc<ConsensusAdapter>,
1616 prometheus_registry: &Registry,
1617 soft_locks: Arc<PreConsensusSoftLocks>,
1618 validator_service_metrics: Arc<ValidatorServiceMetrics>,
1619 serving_rt_handle: tokio::runtime::Handle,
1620 ) -> Result<SpawnOnce> {
1621 let validator_service = ValidatorService::new(
1622 state,
1623 consensus_adapter,
1624 validator_service_metrics,
1625 config.policy_config.clone().map(|p| p.client_id_source),
1626 soft_locks,
1627 );
1628
1629 let concurrency_limit = config.grpc_concurrency_limit_per_core.saturating_mul(
1636 NonZeroUsize::new(iota_core::runtime::available_cpu_cores())
1637 .unwrap_or(NonZeroUsize::MIN),
1638 );
1639 let load_shed = config.grpc_load_shed.unwrap_or_default();
1640
1641 let server_conf = iota_network_stack::config::Config::new();
1642 let server_builder =
1643 ServerBuilder::from_config(&server_conf, GrpcMetrics::new(prometheus_registry))
1644 .add_service_with_concurrency_limit(
1645 ValidatorServer::new(validator_service.clone()),
1646 concurrency_limit,
1647 load_shed,
1648 )
1649 .add_service_with_concurrency_limit(
1650 ValidatorV2Server::new(validator_service.clone()),
1651 concurrency_limit,
1652 load_shed,
1653 )
1654 .add_service_with_concurrency_limit(
1655 ValidatorPeerServer::new(validator_service),
1656 concurrency_limit,
1657 load_shed,
1658 );
1659
1660 let tls_config = iota_tls::create_rustls_server_config(
1661 config.network_key_pair().copy().private(),
1662 IOTA_TLS_SERVER_NAME.to_string(),
1663 );
1664
1665 let network_address = config.network_address().clone();
1666
1667 let bind_future = async move {
1668 let server = server_builder
1669 .bind(&network_address, Some(tls_config))
1670 .await
1671 .map_err(|err| anyhow!("Failed to bind to {network_address}: {err}"))?;
1672
1673 let local_addr = server.local_addr();
1674 info!("Listening to traffic on {local_addr}");
1675
1676 Ok(server)
1677 };
1678
1679 Ok(SpawnOnce::new(bind_future, serving_rt_handle))
1680 }
1681
1682 async fn reexecute_pending_consensus_certs(
1700 epoch_store: &Arc<AuthorityPerEpochStore>,
1701 state: &Arc<AuthorityState>,
1702 ) {
1703 let mut pending_consensus_certificates = Vec::new();
1704 let mut additional_certs = Vec::new();
1705
1706 for tx in epoch_store.get_all_pending_consensus_transactions() {
1707 match tx.kind {
1708 ConsensusTransactionKind::CertifiedTransaction(tx)
1718 if !tx.contains_shared_object() =>
1719 {
1720 let tx = *tx;
1721 let tx = VerifiedExecutableTransaction::new_from_certificate(
1724 VerifiedCertificate::new_unchecked(tx),
1725 );
1726 if let Some(fx_digest) = epoch_store
1729 .get_signed_effects_digest(tx.digest())
1730 .expect("db error")
1731 {
1732 pending_consensus_certificates.push((tx, fx_digest));
1733 } else {
1734 additional_certs.push(tx);
1735 }
1736 }
1737 _ => (),
1738 }
1739 }
1740
1741 let digests = pending_consensus_certificates
1742 .iter()
1743 .map(|(tx, _)| *tx.digest())
1744 .collect::<Vec<_>>();
1745
1746 info!(
1747 "reexecuting {} pending consensus certificates: {:?}",
1748 digests.len(),
1749 digests
1750 );
1751
1752 state.enqueue_with_expected_effects_digest(pending_consensus_certificates, epoch_store);
1753 state.enqueue_transactions_for_execution(additional_certs, epoch_store);
1754
1755 let timeout = if cfg!(msim) { 120 } else { 60 };
1761 if tokio::time::timeout(
1762 std::time::Duration::from_secs(timeout),
1763 state
1764 .get_transaction_cache_reader()
1765 .try_notify_read_executed_effects_digests(&digests),
1766 )
1767 .await
1768 .is_err()
1769 {
1770 if let Ok(executed_effects_digests) = state
1772 .get_transaction_cache_reader()
1773 .try_multi_get_executed_effects_digests(&digests)
1774 {
1775 let pending_digests = digests
1776 .iter()
1777 .zip(executed_effects_digests.iter())
1778 .filter_map(|(digest, executed_effects_digest)| {
1779 if executed_effects_digest.is_none() {
1780 Some(digest)
1781 } else {
1782 None
1783 }
1784 })
1785 .collect::<Vec<_>>();
1786 debug_fatal!(
1787 "Timed out waiting for effects digests to be executed: {:?}",
1788 pending_digests
1789 );
1790 } else {
1791 debug_fatal!(
1792 "Timed out waiting for effects digests to be executed, digests not found"
1793 );
1794 }
1795 }
1796 }
1797
1798 pub fn state(&self) -> Arc<AuthorityState> {
1799 self.state.clone()
1800 }
1801
1802 pub fn reference_gas_price_for_testing(&self) -> Result<u64, anyhow::Error> {
1804 self.state.reference_gas_price_for_testing()
1805 }
1806
1807 pub fn clone_committee_store(&self) -> Arc<CommitteeStore> {
1808 self.state.committee_store().clone()
1809 }
1810
1811 pub fn clone_authority_aggregator(
1821 &self,
1822 ) -> Option<Arc<AuthorityAggregator<NetworkAuthorityClient>>> {
1823 self.transaction_orchestrator
1824 .as_ref()
1825 .map(|to| to.clone_authority_aggregator())
1826 }
1827
1828 pub fn transaction_orchestrator(
1829 &self,
1830 ) -> Option<Arc<TransactionOrchestrator<NetworkAuthorityClient>>> {
1831 self.transaction_orchestrator.clone()
1832 }
1833
1834 pub fn subscribe_to_transaction_orchestrator_effects(
1835 &self,
1836 ) -> Result<tokio::sync::broadcast::Receiver<QuorumDriverEffectsQueueResult>> {
1837 self.transaction_orchestrator
1838 .as_ref()
1839 .ok_or_else(|| {
1840 anyhow::anyhow!("Transaction Orchestrator is not enabled in this node.")
1841 })?
1842 .subscribe_to_effects_queue()
1843 .ok_or_else(|| anyhow::anyhow!("Effects queue is not available under the P-COOL flow."))
1844 }
1845
1846 pub async fn monitor_reconfiguration(
1852 self: Arc<Self>,
1853 mut epoch_store: Arc<AuthorityPerEpochStore>,
1854 ) -> Result<()> {
1855 let checkpoint_executor_metrics =
1856 CheckpointExecutorMetrics::new(&self.registry_service.default_registry());
1857
1858 loop {
1859 let mut hasher_guard = self.global_state_hasher.lock().await;
1860 let hasher = hasher_guard.take().unwrap();
1861 info!(
1862 "Creating checkpoint executor for epoch {}",
1863 epoch_store.epoch()
1864 );
1865
1866 let data_sender = if let Ok(guard) = self.grpc_server_handle.try_lock() {
1868 guard.as_ref().map(|handle| {
1869 let tx = handle.checkpoint_data_broadcaster().clone();
1870 Box::new(move |data: &CheckpointData| {
1871 tx.send_traced(data);
1872 }) as Box<dyn Fn(&CheckpointData) + Send + Sync>
1873 })
1874 } else {
1875 None
1876 };
1877
1878 let checkpoint_executor = CheckpointExecutor::new(
1879 epoch_store.clone(),
1880 self.checkpoint_store.clone(),
1881 self.state.clone(),
1882 hasher.clone(),
1883 self.backpressure_manager.clone(),
1884 self.config.checkpoint_executor_config.clone(),
1885 checkpoint_executor_metrics.clone(),
1886 data_sender,
1887 Some(self.checkpoint_progress_tracker.clone()),
1888 );
1889
1890 let run_with_range = self.config.run_with_range;
1891
1892 let cur_epoch_store = self.state.load_epoch_store_one_call_per_task();
1893
1894 self.metrics
1896 .current_protocol_version
1897 .set(cur_epoch_store.protocol_config().version.as_u64() as i64);
1898
1899 if let Some(components) = &*self.validator_components.lock().await {
1901 tokio::time::sleep(Duration::from_millis(1)).await;
1903
1904 let config = cur_epoch_store.protocol_config();
1905 let binary_config = to_binary_config(config);
1906 let transaction = ConsensusTransaction::new_capability_notification_v1(
1907 AuthorityCapabilitiesV1::new(
1908 self.state.name,
1909 cur_epoch_store.get_chain(),
1910 self.config
1911 .supported_protocol_versions
1912 .expect("Supported versions should be populated")
1913 .truncate_below(config.version),
1915 self.state
1916 .get_available_system_packages(&binary_config)
1917 .await,
1918 ),
1919 );
1920 info!(?transaction, "submitting capabilities to consensus");
1921 components
1922 .consensus_adapter
1923 .submit(transaction, None, &cur_epoch_store)?;
1924
1925 if config.deny_rule_governance() {
1932 let proposed_rules = self.config.transaction_deny_config.to_deny_rule_set();
1933 let recorded = cur_epoch_store.recorded_deny_rule_proposal(&self.state.name);
1934 let should_submit = proposed_rules != DenyRuleSet::default()
1935 || recorded
1936 .as_ref()
1937 .is_some_and(|p| p.proposed_rules != DenyRuleSet::default());
1938 if should_submit {
1939 let transaction = ConsensusTransaction::new_transaction_deny_rule_proposal(
1940 TransactionDenyRuleProposal::new(
1941 self.state.name,
1942 proposed_rules,
1943 recorded.map(|p| p.generation),
1944 ),
1945 );
1946 info!(
1947 tracking_id = ?transaction.get_tracking_id(),
1948 "submitting deny rule proposal to consensus"
1949 );
1950 components
1951 .consensus_adapter
1952 .submit(transaction, None, &cur_epoch_store)?;
1953 }
1954 }
1955 } else if self.state.is_active_validator(&cur_epoch_store)
1956 && cur_epoch_store
1957 .protocol_config()
1958 .track_non_committee_eligible_validators()
1959 {
1960 let epoch_store = cur_epoch_store.clone();
1964 let node_clone = self.clone();
1965 spawn_monitored_task!(epoch_store.clone().within_alive_epoch(async move {
1966 node_clone
1967 .send_signed_capability_notification_to_committee_with_retry(&epoch_store)
1968 .instrument(trace_span!(
1969 "send_signed_capability_notification_to_committee_with_retry"
1970 ))
1971 .await;
1972 }));
1973 }
1974
1975 let stop_condition = checkpoint_executor.run_epoch(run_with_range).await;
1976
1977 if stop_condition == StopReason::RunWithRangeCondition {
1978 IotaNode::shutdown(&self).await;
1979 self.shutdown_channel_tx
1980 .send(run_with_range)
1981 .expect("RunWithRangeCondition met but failed to send shutdown message");
1982 return Ok(());
1983 }
1984
1985 let latest_system_state = self
1987 .state
1988 .get_object_cache_reader()
1989 .try_get_iota_system_state_object_unsafe()
1990 .expect("Read IOTA System State object cannot fail");
1991
1992 #[cfg(msim)]
1993 if !self
1994 .sim_state
1995 .sim_safe_mode_expected
1996 .load(Ordering::Relaxed)
1997 {
1998 debug_assert!(!latest_system_state.safe_mode());
1999 }
2000
2001 #[cfg(not(msim))]
2002 debug_assert!(!latest_system_state.safe_mode());
2003
2004 if let Err(err) = self.end_of_epoch_channel.send(latest_system_state.clone()) {
2005 if self.state.is_fullnode(&cur_epoch_store) {
2006 warn!(
2007 "Failed to send end of epoch notification to subscriber: {:?}",
2008 err
2009 );
2010 }
2011 }
2012
2013 cur_epoch_store.record_is_safe_mode_metric(latest_system_state.safe_mode());
2014 let new_epoch_start_state = latest_system_state.into_epoch_start_state();
2015
2016 self.auth_agg.store(Arc::new(
2017 self.auth_agg
2018 .load()
2019 .recreate_with_new_epoch_start_state(&new_epoch_start_state),
2020 ));
2021
2022 let next_epoch_committee = new_epoch_start_state.get_iota_committee();
2023 let next_epoch = next_epoch_committee.epoch();
2024 assert_eq!(cur_epoch_store.epoch() + 1, next_epoch);
2025
2026 info!(
2027 next_epoch,
2028 "Finished executing all checkpoints in epoch. About to reconfigure the system."
2029 );
2030
2031 fail_point_async!("reconfig_delay");
2032
2033 let authority_names_to_peer_ids =
2038 new_epoch_start_state.get_authority_names_to_peer_ids();
2039 self.connection_monitor_status
2040 .update_mapping_for_epoch(authority_names_to_peer_ids);
2041
2042 cur_epoch_store.record_epoch_reconfig_start_time_metric();
2043
2044 send_trusted_peer_change(
2045 &self.config,
2046 &self.trusted_peer_change_tx,
2047 &new_epoch_start_state,
2048 );
2049
2050 let mut validator_components_lock_guard = self.validator_components.lock().await;
2051
2052 let new_epoch_store = self
2056 .reconfigure_state(
2057 &self.state,
2058 &cur_epoch_store,
2059 next_epoch_committee.clone(),
2060 new_epoch_start_state,
2061 hasher.clone(),
2062 )
2063 .await?;
2064
2065 let new_validator_components = if let Some(ValidatorComponents {
2066 validator_server_handle,
2067 validator_overload_monitor_handle,
2068 consensus_queue_overload_monitor_handle,
2069 soft_lock_sweep_handle,
2070 overload_notifier_handle,
2071 consensus_manager,
2072 consensus_store_pruner,
2073 consensus_adapter,
2074 soft_locks,
2075 mut checkpoint_service_tasks,
2076 checkpoint_metrics,
2077 iota_tx_validator_metrics,
2078 validator_registry_id,
2079 }) = validator_components_lock_guard.take()
2080 {
2081 info!("Reconfiguring the validator.");
2082 if let Some(handle) = overload_notifier_handle {
2085 handle.abort();
2086 }
2087 checkpoint_service_tasks.abort_all();
2092 while let Some(result) = checkpoint_service_tasks.join_next().await {
2093 if let Err(err) = result {
2094 if err.is_panic() {
2095 std::panic::resume_unwind(err.into_panic());
2096 }
2097 warn!("Error in checkpoint service task: {:?}", err);
2098 }
2099 }
2100 info!("Checkpoint service has shut down.");
2101
2102 consensus_manager.shutdown().await;
2103 info!("Consensus has shut down.");
2104
2105 info!("Epoch store finished reconfiguration.");
2106
2107 let global_state_hasher_metrics = Arc::into_inner(hasher)
2110 .expect("Object state hasher should have no other references at this point")
2111 .metrics();
2112 let new_hasher = Arc::new(GlobalStateHasher::new(
2113 self.state.get_global_state_hash_store().clone(),
2114 global_state_hasher_metrics,
2115 ));
2116 let weak_hasher = Arc::downgrade(&new_hasher);
2117 *hasher_guard = Some(new_hasher);
2118
2119 consensus_store_pruner.prune(next_epoch).await;
2120
2121 if self.state.is_committee_validator(&new_epoch_store) {
2122 Some(
2124 Self::start_epoch_specific_validator_components(
2125 &self.config,
2126 self.state.clone(),
2127 consensus_adapter,
2128 self.checkpoint_store.clone(),
2129 new_epoch_store.clone(),
2130 self.state_sync_handle.clone(),
2131 self.randomness_handle.clone(),
2132 consensus_manager,
2133 consensus_store_pruner,
2134 weak_hasher,
2135 self.backpressure_manager.clone(),
2136 soft_locks,
2137 validator_server_handle,
2138 validator_overload_monitor_handle,
2139 consensus_queue_overload_monitor_handle,
2140 soft_lock_sweep_handle,
2141 checkpoint_metrics,
2142 iota_tx_validator_metrics,
2143 validator_registry_id,
2144 )
2145 .await?,
2146 )
2147 } else {
2148 info!("This node is no longer a validator after reconfiguration");
2149 if self.registry_service.remove(validator_registry_id) {
2150 debug!("Removed validator metrics registry");
2151 } else {
2152 warn!("Failed to remove validator metrics registry");
2153 }
2154 validator_server_handle.shutdown();
2155 debug!("Validator grpc server shutdown triggered");
2156
2157 None
2158 }
2159 } else {
2160 let global_state_hasher_metrics = Arc::into_inner(hasher)
2163 .expect("Object state hasher should have no other references at this point")
2164 .metrics();
2165 let new_hasher = Arc::new(GlobalStateHasher::new(
2166 self.state.get_global_state_hash_store().clone(),
2167 global_state_hasher_metrics,
2168 ));
2169 let weak_hasher = Arc::downgrade(&new_hasher);
2170 *hasher_guard = Some(new_hasher);
2171
2172 if self.state.is_committee_validator(&new_epoch_store) {
2173 info!("Promoting the node from fullnode to validator, starting grpc server");
2174
2175 let mut components = Self::construct_validator_components(
2176 self.config.clone(),
2177 self.state.clone(),
2178 Arc::new(next_epoch_committee.clone()),
2179 new_epoch_store.clone(),
2180 self.checkpoint_store.clone(),
2181 self.state_sync_handle.clone(),
2182 self.randomness_handle.clone(),
2183 weak_hasher,
2184 self.backpressure_manager.clone(),
2185 self.connection_monitor_status.clone(),
2186 &self.registry_service,
2187 self.serving_rt_handle.clone(),
2188 )
2189 .await?;
2190
2191 components.validator_server_handle =
2192 components.validator_server_handle.start().await;
2193
2194 Some(components)
2195 } else {
2196 None
2197 }
2198 };
2199 *validator_components_lock_guard = new_validator_components;
2200
2201 cur_epoch_store.release_db_handles();
2204
2205 drop(cur_epoch_store);
2209
2210 self.state.epoch_db_pruner().prune_old_epoch_dbs().await;
2214
2215 if cfg!(msim)
2216 && !matches!(
2217 self.config
2218 .authority_store_pruning_config
2219 .num_epochs_to_retain_for_checkpoints(),
2220 None | Some(u64::MAX) | Some(0)
2221 )
2222 {
2223 self.state
2224 .prune_checkpoints_for_eligible_epochs_for_testing(
2225 self.config.clone(),
2226 iota_core::authority::authority_store_pruner::AuthorityStorePruningMetrics::new_for_test(),
2227 )
2228 .await?;
2229 }
2230
2231 epoch_store = new_epoch_store;
2232 info!("Reconfiguration finished");
2233 }
2234 }
2235
2236 async fn shutdown(&self) {
2237 if let Some(validator_components) = &*self.validator_components.lock().await {
2238 validator_components.consensus_manager.shutdown().await;
2239 }
2240
2241 if let Some(grpc_handle) = self.grpc_server_handle.lock().await.take() {
2243 info!("Shutting down gRPC server");
2244 if let Err(e) = grpc_handle.shutdown().await {
2245 warn!("Failed to gracefully shutdown gRPC server: {e}");
2246 }
2247 }
2248 }
2249
2250 async fn reconfigure_state(
2253 &self,
2254 state: &Arc<AuthorityState>,
2255 cur_epoch_store: &AuthorityPerEpochStore,
2256 next_epoch_committee: Committee,
2257 next_epoch_start_system_state: EpochStartSystemState,
2258 global_state_hasher: Arc<GlobalStateHasher>,
2259 ) -> IotaResult<Arc<AuthorityPerEpochStore>> {
2260 let next_epoch = next_epoch_committee.epoch();
2261
2262 let last_checkpoint = self
2263 .checkpoint_store
2264 .get_epoch_last_checkpoint(cur_epoch_store.epoch())
2265 .expect("Error loading last checkpoint for current epoch")
2266 .expect("Could not load last checkpoint for current epoch");
2267 let epoch_supply_change = last_checkpoint
2268 .end_of_epoch_data
2269 .as_ref()
2270 .ok_or_else(|| {
2271 IotaError::from("last checkpoint in epoch should contain end of epoch data")
2272 })?
2273 .epoch_supply_change;
2274
2275 let last_checkpoint_seq = last_checkpoint.sequence_number();
2276
2277 assert_eq!(
2278 Some(last_checkpoint_seq),
2279 self.checkpoint_store
2280 .get_highest_executed_checkpoint_seq_number()
2281 .expect("Error loading highest executed checkpoint sequence number")
2282 );
2283
2284 let epoch_start_configuration = EpochStartConfiguration::new(
2285 next_epoch_start_system_state,
2286 *last_checkpoint.digest(),
2287 state.get_object_store().as_ref(),
2288 EpochFlag::default_flags_for_new_epoch(&state.config),
2289 )
2290 .expect("EpochStartConfiguration construction cannot fail");
2291
2292 let new_epoch_store = self
2293 .state
2294 .reconfigure(
2295 cur_epoch_store,
2296 self.config.supported_protocol_versions.unwrap(),
2297 next_epoch_committee,
2298 epoch_start_configuration,
2299 global_state_hasher,
2300 &self.config.expensive_safety_check_config,
2301 epoch_supply_change,
2302 last_checkpoint_seq,
2303 )
2304 .await
2305 .expect("Reconfigure authority state cannot fail");
2306 info!(next_epoch, "Node State has been reconfigured");
2307 assert_eq!(next_epoch, new_epoch_store.epoch());
2308 self.state.get_reconfig_api().update_epoch_flags_metrics(
2309 cur_epoch_store.epoch_start_config().flags(),
2310 new_epoch_store.epoch_start_config().flags(),
2311 );
2312
2313 Ok(new_epoch_store)
2314 }
2315
2316 pub fn get_config(&self) -> &NodeConfig {
2317 &self.config
2318 }
2319
2320 async fn execute_transaction_immediately_at_zero_epoch(
2321 state: &Arc<AuthorityState>,
2322 epoch_store: &Arc<AuthorityPerEpochStore>,
2323 tx: &Transaction,
2324 span: tracing::Span,
2325 ) {
2326 let _guard = span.enter();
2327 let transaction =
2328 iota_types::executable_transaction::VerifiedExecutableTransaction::new_unchecked(
2329 iota_types::executable_transaction::ExecutableTransaction::new_from_data_and_sig(
2330 tx.data().clone(),
2331 iota_types::executable_transaction::CertificateProof::Checkpoint(0, 0),
2332 ),
2333 );
2334 state
2335 .try_execute_immediately(&transaction, None, epoch_store)
2336 .unwrap();
2337 }
2338
2339 pub fn randomness_handle(&self) -> randomness::Handle {
2340 self.randomness_handle.clone()
2341 }
2342
2343 async fn send_signed_capability_notification_to_committee_with_retry(
2349 &self,
2350 epoch_store: &Arc<AuthorityPerEpochStore>,
2351 ) {
2352 const INITIAL_RETRY_INTERVAL_SECS: u64 = 5;
2353 const RETRY_INTERVAL_INCREMENT_SECS: u64 = 5;
2354 const MAX_RETRY_INTERVAL_SECS: u64 = 300; let config = epoch_store.protocol_config();
2358 let binary_config = to_binary_config(config);
2359
2360 let capabilities = AuthorityCapabilitiesV1::new(
2362 self.state.name,
2363 epoch_store.get_chain(),
2364 self.config
2365 .supported_protocol_versions
2366 .expect("Supported versions should be populated")
2367 .truncate_below(config.version),
2368 self.state
2369 .get_available_system_packages(&binary_config)
2370 .await,
2371 );
2372
2373 let signature = AuthoritySignature::new_secure(
2375 &IntentMessage::new(
2376 Intent::iota_app(IntentScope::AuthorityCapabilities),
2377 &capabilities,
2378 ),
2379 &epoch_store.epoch(),
2380 self.config.authority_key_pair(),
2381 );
2382
2383 let request = HandleCapabilityNotificationRequestV1 {
2384 message: SignedAuthorityCapabilitiesV1::new_from_data_and_sig(capabilities, signature),
2385 };
2386
2387 let mut retry_interval = Duration::from_secs(INITIAL_RETRY_INTERVAL_SECS);
2388
2389 loop {
2390 let auth_agg = self.auth_agg.load();
2391 match auth_agg
2392 .send_capability_notification_to_quorum(request.clone())
2393 .await
2394 {
2395 Ok(_) => {
2396 info!("Successfully sent capability notification to committee");
2397 break;
2398 }
2399 Err(err) => {
2400 match &err {
2401 AggregatorSendCapabilityNotificationError::RetryableNotification {
2402 errors,
2403 } => {
2404 warn!(
2405 "Failed to send capability notification to committee (retryable error), will retry in {:?}: {:?}",
2406 retry_interval, errors
2407 );
2408 }
2409 AggregatorSendCapabilityNotificationError::NonRetryableNotification {
2410 errors,
2411 } => {
2412 error!(
2413 "Failed to send capability notification to committee (non-retryable error): {:?}",
2414 errors
2415 );
2416 break;
2417 }
2418 };
2419
2420 tokio::time::sleep(retry_interval).await;
2422
2423 retry_interval = std::cmp::min(
2425 retry_interval + Duration::from_secs(RETRY_INTERVAL_INCREMENT_SECS),
2426 Duration::from_secs(MAX_RETRY_INTERVAL_SECS),
2427 );
2428 }
2429 }
2430 }
2431 }
2432}
2433
2434#[cfg(msim)]
2435impl IotaNode {
2436 pub fn get_sim_node_id(&self) -> iota_simulator::task::NodeId {
2437 self.sim_state.sim_node.id()
2438 }
2439
2440 pub fn set_safe_mode_expected(&self, new_value: bool) {
2441 info!("Setting safe mode expected to {}", new_value);
2442 self.sim_state
2443 .sim_safe_mode_expected
2444 .store(new_value, Ordering::Relaxed);
2445 }
2446}
2447
2448enum SpawnOnce {
2449 Unstarted(
2451 Mutex<BoxFuture<'static, Result<iota_network_stack::server::Server>>>,
2452 tokio::runtime::Handle,
2453 ),
2454 #[allow(unused)]
2455 Started(iota_http::ServerHandle),
2456}
2457
2458impl SpawnOnce {
2459 pub fn new(
2460 future: impl Future<Output = Result<iota_network_stack::server::Server>> + Send + 'static,
2461 serving_rt_handle: tokio::runtime::Handle,
2462 ) -> Self {
2463 Self::Unstarted(Mutex::new(Box::pin(future)), serving_rt_handle)
2464 }
2465
2466 pub async fn start(self) -> Self {
2467 match self {
2468 Self::Unstarted(future, serving_rt_handle) => {
2469 let (handle_tx, handle_rx) = tokio::sync::oneshot::channel();
2473 serving_rt_handle.spawn(async move {
2474 let server = future.into_inner().await.unwrap_or_else(|err| {
2475 panic!("Failed to start validator gRPC server: {err}")
2476 });
2477 if handle_tx.send(server.handle().clone()).is_err() {
2478 return;
2479 }
2480 if let Err(err) = server.serve().await {
2481 info!("Server stopped: {err}");
2482 }
2483 info!("Server stopped");
2484 });
2485 let handle = handle_rx
2486 .await
2487 .expect("validator gRPC server exited before returning its handle");
2488 Self::Started(handle)
2489 }
2490 Self::Started(_) => self,
2491 }
2492 }
2493
2494 pub fn shutdown(self) {
2495 if let SpawnOnce::Started(handle) = self {
2496 handle.trigger_shutdown();
2497 }
2498 }
2499}
2500
2501fn send_trusted_peer_change(
2504 config: &NodeConfig,
2505 sender: &watch::Sender<TrustedPeerChangeEvent>,
2506 new_epoch_start_state: &EpochStartSystemState,
2507) {
2508 let new_committee =
2509 new_epoch_start_state.get_validator_as_p2p_peers(config.authority_public_key());
2510
2511 sender.send_modify(|event| {
2512 core::mem::swap(&mut event.new_committee, &mut event.old_committee);
2513 event.new_committee = new_committee;
2514 })
2515}
2516
2517fn build_kv_store(
2518 state: &Arc<AuthorityState>,
2519 config: &NodeConfig,
2520 registry: &Registry,
2521) -> Result<Arc<TransactionKeyValueStore>> {
2522 let metrics = KeyValueStoreMetrics::new(registry);
2523 let db_store = TransactionKeyValueStore::new("rocksdb", metrics.clone(), state.clone());
2524
2525 let base_url = &config.transaction_kv_store_read_config.base_url;
2526
2527 if base_url.is_empty() {
2528 info!("no http kv store url provided, using local db only");
2529 return Ok(Arc::new(db_store));
2530 }
2531
2532 base_url.parse::<url::Url>().tap_err(|e| {
2533 error!(
2534 "failed to parse config.transaction_kv_store_config.base_url ({:?}) as url: {}",
2535 base_url, e
2536 )
2537 })?;
2538
2539 let http_store = HttpKVStore::new_kv(
2540 base_url,
2541 config.transaction_kv_store_read_config.cache_size,
2542 metrics.clone(),
2543 )?;
2544 info!("using local key-value store with fallback to http key-value store");
2545 Ok(Arc::new(FallbackTransactionKVStore::new_kv(
2546 db_store,
2547 http_store,
2548 metrics,
2549 "json_rpc_fallback",
2550 )))
2551}
2552
2553async fn build_grpc_server(
2568 config: &NodeConfig,
2569 state: Arc<AuthorityState>,
2570 state_sync_store: RocksDbStore,
2571 executor: Option<Arc<dyn iota_types::transaction_executor::TransactionExecutor>>,
2572 prometheus_registry: &Registry,
2573 server_version: ServerVersion,
2574) -> Result<Option<GrpcServerHandle>> {
2575 if config.consensus_config().is_some() || !config.enable_grpc_api {
2577 return Ok(None);
2578 }
2579
2580 let Some(grpc_config) = &config.grpc_api_config else {
2581 return Err(anyhow!("gRPC API is enabled but no configuration provided"));
2582 };
2583
2584 let chain_id = state.get_chain_identifier();
2586
2587 let grpc_read_store = Arc::new(GrpcReadStore::new(state.clone(), state_sync_store));
2588
2589 let shutdown_token = CancellationToken::new();
2591
2592 let grpc_reader = Arc::new(GrpcReader::new(
2594 grpc_read_store,
2595 Some(server_version.to_string()),
2596 ));
2597
2598 let grpc_server_metrics = iota_grpc_server::GrpcServerMetrics::new(prometheus_registry);
2600 let client_id_source = config
2601 .policy_config
2602 .as_ref()
2603 .map(|p| p.client_id_source.clone());
2604
2605 let handle = start_grpc_server(
2606 grpc_reader,
2607 executor,
2608 grpc_config.clone(),
2609 shutdown_token,
2610 chain_id,
2611 Some(grpc_server_metrics),
2612 state.traffic_controller.clone(),
2613 client_id_source,
2614 )
2615 .await?;
2616
2617 Ok(Some(handle))
2618}
2619
2620pub async fn build_http_server(
2635 state: Arc<AuthorityState>,
2636 transaction_orchestrator: &Option<Arc<TransactionOrchestrator<NetworkAuthorityClient>>>,
2637 config: &NodeConfig,
2638 prometheus_registry: &Registry,
2639) -> Result<Option<iota_http::ServerHandle>> {
2640 if config.consensus_config().is_some() {
2642 return Ok(None);
2643 }
2644
2645 let mut router = axum::Router::new();
2646
2647 let json_rpc_router = {
2648 let traffic_controller = state.traffic_controller.clone();
2649 let mut server = JsonRpcServerBuilder::new(
2650 env!("CARGO_PKG_VERSION"),
2651 prometheus_registry,
2652 traffic_controller,
2653 config.policy_config.clone(),
2654 );
2655
2656 let kv_store = build_kv_store(&state, config, prometheus_registry)?;
2657
2658 let metrics = Arc::new(JsonRpcMetrics::new(prometheus_registry));
2659 server.register_module(ReadApi::new(
2660 state.clone(),
2661 kv_store.clone(),
2662 metrics.clone(),
2663 ))?;
2664 server.register_module(CoinReadApi::new(
2665 state.clone(),
2666 kv_store.clone(),
2667 metrics.clone(),
2668 )?)?;
2669
2670 if config.run_with_range.is_none() {
2673 server.register_module(TransactionBuilderApi::new(state.clone()))?;
2674 }
2675 server.register_module(GovernanceReadApi::new(state.clone(), metrics.clone()))?;
2676
2677 if let Some(transaction_orchestrator) = transaction_orchestrator {
2678 server.register_module(TransactionExecutionApi::new(
2679 state.clone(),
2680 transaction_orchestrator.clone(),
2681 metrics.clone(),
2682 ))?;
2683 }
2684
2685 let iota_names_config = config
2686 .iota_names_config
2687 .clone()
2688 .unwrap_or_else(|| IotaNamesConfig::from_chain(&state.get_chain_identifier().chain()));
2689
2690 server.register_module(IndexerApi::new(
2691 state.clone(),
2692 ReadApi::new(state.clone(), kv_store.clone(), metrics.clone()),
2693 kv_store,
2694 metrics,
2695 iota_names_config,
2696 config.indexer_max_subscriptions,
2697 ))?;
2698 server.register_module(MoveUtils::new(state.clone()))?;
2699
2700 let server_type = config.jsonrpc_server_type();
2701
2702 server.to_router(server_type).await?
2703 };
2704
2705 router = router.merge(json_rpc_router);
2706
2707 router = router
2708 .route("/health", axum::routing::get(health_check_handler))
2709 .route_layer(axum::Extension(state));
2710
2711 let layers = ServiceBuilder::new()
2712 .map_request(|mut request: axum::http::Request<_>| {
2713 if let Some(connect_info) = request.extensions().get::<iota_http::ConnectInfo>() {
2714 let axum_connect_info = axum::extract::ConnectInfo(connect_info.remote_addr);
2715 request.extensions_mut().insert(axum_connect_info);
2716 }
2717 request
2718 })
2719 .layer(axum::middleware::from_fn(server_timing_middleware));
2720
2721 router = router.layer(layers);
2722
2723 let handle = iota_http::Builder::new()
2724 .serve(&config.json_rpc_address, router)
2725 .map_err(|e| anyhow::anyhow!("{e}"))?;
2726 info!(local_addr =? handle.local_addr(), "IOTA JSON-RPC server listening on {}", handle.local_addr());
2727
2728 Ok(Some(handle))
2729}
2730
2731#[derive(Debug, serde::Serialize, serde::Deserialize)]
2732pub struct Threshold {
2733 pub threshold_seconds: Option<u32>,
2734}
2735
2736async fn health_check_handler(
2737 axum::extract::Query(Threshold { threshold_seconds }): axum::extract::Query<Threshold>,
2738 axum::Extension(state): axum::Extension<Arc<AuthorityState>>,
2739) -> impl axum::response::IntoResponse {
2740 if let Some(threshold_seconds) = threshold_seconds {
2741 let summary = match state
2743 .get_checkpoint_store()
2744 .get_highest_executed_checkpoint()
2745 {
2746 Ok(Some(summary)) => summary,
2747 Ok(None) => {
2748 warn!("Highest executed checkpoint not found");
2749 return (axum::http::StatusCode::SERVICE_UNAVAILABLE, "down");
2750 }
2751 Err(err) => {
2752 warn!("Failed to retrieve highest executed checkpoint: {:?}", err);
2753 return (axum::http::StatusCode::SERVICE_UNAVAILABLE, "down");
2754 }
2755 };
2756
2757 let latest_chain_time = summary.timestamp();
2759 let threshold =
2760 std::time::SystemTime::now() - Duration::from_secs(threshold_seconds as u64);
2761
2762 if latest_chain_time < threshold {
2764 warn!(
2765 ?latest_chain_time,
2766 ?threshold,
2767 "failing health check due to checkpoint lag"
2768 );
2769 return (axum::http::StatusCode::SERVICE_UNAVAILABLE, "down");
2770 }
2771 }
2772 (axum::http::StatusCode::OK, "up")
2774}
2775
2776#[cfg(not(test))]
2777fn max_tx_per_checkpoint(protocol_config: &ProtocolConfig) -> usize {
2778 protocol_config.max_transactions_per_checkpoint() as usize
2779}
2780
2781#[cfg(test)]
2782fn max_tx_per_checkpoint(_: &ProtocolConfig) -> usize {
2783 2
2784}
2785
2786#[cfg(all(test, not(msim)))]
2789mod runtime_split_tests {
2790 use std::{
2791 sync::mpsc,
2792 time::{Duration, Instant},
2793 };
2794
2795 use anyhow::anyhow;
2796
2797 use super::SpawnOnce;
2798
2799 fn runtime(name: &'static str) -> tokio::runtime::Runtime {
2802 tokio::runtime::Builder::new_multi_thread()
2803 .worker_threads(1)
2804 .thread_name(name)
2805 .enable_all()
2806 .build()
2807 .unwrap()
2808 }
2809
2810 fn current_pool() -> String {
2812 std::thread::current()
2813 .name()
2814 .unwrap_or("<unnamed>")
2815 .to_string()
2816 }
2817
2818 #[test]
2829 fn spawn_once_binds_on_serving_not_the_core_runtime() {
2830 let node = runtime("node-core");
2831 let serving = runtime("serving");
2832 let (tx, rx) = mpsc::channel::<(&'static str, String)>();
2833
2834 let bind_tx = tx.clone();
2837 let bind_future = async move {
2838 let _ = bind_tx.send(("bind", current_pool()));
2839 let addr = "/ip4/127.0.0.1/tcp/0/http".parse().unwrap();
2840 let server = iota_network_stack::config::Config::new()
2841 .server_builder()
2842 .bind(&addr, None)
2843 .await
2844 .map_err(|e| anyhow!("bind failed: {e}"))?;
2845 Ok(server)
2846 };
2847 let once = SpawnOnce::new(bind_future, serving.handle().clone());
2848
2849 let caller_tx = tx.clone();
2851 node.spawn(async move {
2852 let _ = caller_tx.send(("caller", current_pool()));
2853 let _ = once.start().await;
2854 });
2855
2856 let (mut caller_pool, mut bind_pool) = (None, None);
2858 let deadline = Instant::now() + Duration::from_secs(10);
2859 while (caller_pool.is_none() || bind_pool.is_none()) && Instant::now() < deadline {
2860 if let Ok((which, pool)) = rx.recv_timeout(Duration::from_millis(200)) {
2861 match which {
2862 "caller" => caller_pool = Some(pool),
2863 "bind" => bind_pool = Some(pool),
2864 _ => {}
2865 }
2866 }
2867 }
2868 let caller_pool = caller_pool.expect("start() never ran");
2869 let bind_pool = bind_pool.expect("bind future never ran");
2870
2871 assert!(
2872 caller_pool.starts_with("node-core"),
2873 "start() should run on the node-core runtime, ran on: {caller_pool}"
2874 );
2875 assert!(
2876 bind_pool.starts_with("serving"),
2877 "server bind must run on the serving runtime, ran on: {bind_pool}"
2878 );
2879 assert_ne!(
2880 caller_pool, bind_pool,
2881 "the fix must move the bind off the caller (node-core) runtime onto serving"
2882 );
2883 }
2884}