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