From a35dfd57d220d79b577a428a452aada79a52df10 Mon Sep 17 00:00:00 2001 From: Josh Lind Date: Thu, 27 Jul 2023 18:57:48 -0400 Subject: [PATCH] [State Sync] Don't skip fast syncing steps. --- config/src/config/state_sync_config.rs | 47 +++++++++++++++++-- .../state-sync-driver/src/bootstrapper.rs | 20 +++++++- testsuite/smoke-test/src/state_sync.rs | 28 +++++++++++ 3 files changed, 91 insertions(+), 4 deletions(-) diff --git a/config/src/config/state_sync_config.rs b/config/src/config/state_sync_config.rs index 549fc7107aab7a..0746c812163ed5 100644 --- a/config/src/config/state_sync_config.rs +++ b/config/src/config/state_sync_config.rs @@ -99,6 +99,8 @@ pub struct StateSyncDriverConfig { pub enable_auto_bootstrapping: bool, /// The interval (ms) to refresh the storage summary pub fallback_to_output_syncing_secs: u64, + /// Whether or not to wait for an epoch change when fast syncing + pub fast_sync_wait_for_epoch_change: bool, /// The interval (ms) at which to check state sync progress pub progress_check_interval_ms: u64, /// The maximum time (secs) to wait for connections from peers before auto-bootstrapping @@ -126,7 +128,8 @@ impl Default for StateSyncDriverConfig { commit_notification_timeout_ms: 5000, continuous_syncing_mode: ContinuousSyncingMode::ExecuteTransactionsOrApplyOutputs, enable_auto_bootstrapping: false, - fallback_to_output_syncing_secs: 180, // 3 minutes + fallback_to_output_syncing_secs: 180, // 3 minutes + fast_sync_wait_for_epoch_change: true, // This is required for genesis-less storage startup in fast sync progress_check_interval_ms: 50, max_connection_deadline_secs: 10, max_consecutive_stream_notifications: 10, @@ -289,10 +292,48 @@ impl Default for AptosDataClientConfig { impl ConfigSanitizer for StateSyncConfig { fn sanitize( - _node_config: &mut NodeConfig, + node_config: &mut NodeConfig, + node_type: NodeType, + chain_id: ChainId, + ) -> Result<(), Error> { + // Sanitize the state sync driver config + StateSyncDriverConfig::sanitize(node_config, node_type, chain_id) + } +} + +impl ConfigSanitizer for StateSyncDriverConfig { + fn sanitize( + node_config: &mut NodeConfig, _node_type: NodeType, - _chain_id: ChainId, + chain_id: ChainId, ) -> Result<(), Error> { + let sanitizer_name = Self::get_sanitizer_name(); + let state_sync_driver_config = &mut node_config.state_sync.state_sync_driver; + + // Verify that auto-bootstrapping is not enabled for + // nodes that are fast syncing. + let fast_sync_enabled = + state_sync_driver_config.bootstrapping_mode == BootstrappingMode::DownloadLatestStates; + if state_sync_driver_config.enable_auto_bootstrapping && fast_sync_enabled { + return Err(Error::ConfigSanitizerFailed( + sanitizer_name, + "Auto-bootstrapping should not be enabled for nodes that are fast syncing!" + .to_string(), + )); + } + + // Verify that fast sync will wait for an + // epoch change in testnet and mainnet. + if (chain_id.is_testnet() || chain_id.is_mainnet()) + && fast_sync_enabled + && !state_sync_driver_config.fast_sync_wait_for_epoch_change + { + return Err(Error::ConfigSanitizerFailed( + sanitizer_name, + "Fast sync must wait for an epoch change in testnet and mainnet!".to_string(), + )); + } + Ok(()) } } diff --git a/state-sync/state-sync-v2/state-sync-driver/src/bootstrapper.rs b/state-sync/state-sync-v2/state-sync-driver/src/bootstrapper.rs index 083f64d4b6ffff..de0d5207c4565c 100644 --- a/state-sync/state-sync-v2/state-sync-driver/src/bootstrapper.rs +++ b/state-sync/state-sync-v2/state-sync-driver/src/bootstrapper.rs @@ -463,6 +463,24 @@ impl< let highest_known_ledger_info = self.get_highest_known_ledger_info()?; let highest_known_ledger_version = highest_known_ledger_info.ledger_info().version(); + // If the node is fast syncing for the first time we + // need to wait until an epoch change is advertised. + let bootstrapping_mode = self.get_bootstrapping_mode(); + if bootstrapping_mode == BootstrappingMode::DownloadLatestStates + && self + .driver_configuration + .config + .fast_sync_wait_for_epoch_change + && highest_synced_version == GENESIS_TRANSACTION_VERSION + && highest_known_ledger_version == GENESIS_TRANSACTION_VERSION + { + info!(LogSchema::new(LogEntry::Bootstrapper).message(&format!( + "Waiting for an epoch change to be advertised! Highest synced and advertised version is {}.", + highest_synced_version + ))); + return Ok(()); + } + // If we've already synced to the highest known version, there's nothing to do if highest_synced_version >= highest_known_ledger_version { info!(LogSchema::new(LogEntry::Bootstrapper) @@ -476,7 +494,7 @@ impl< highest_synced_version, highest_known_ledger_info, self.get_bootstrapping_mode()))); // Bootstrap according to the mode - match self.get_bootstrapping_mode() { + match bootstrapping_mode { BootstrappingMode::DownloadLatestStates => { self.fetch_missing_state_snapshot_data( highest_synced_version, diff --git a/testsuite/smoke-test/src/state_sync.rs b/testsuite/smoke-test/src/state_sync.rs index 2481229e8937ae..3b7cf27f561756 100644 --- a/testsuite/smoke-test/src/state_sync.rs +++ b/testsuite/smoke-test/src/state_sync.rs @@ -352,6 +352,10 @@ async fn test_validator_bootstrap_state_snapshot() { .with_init_config(Arc::new(|_, config, _| { config.state_sync.state_sync_driver.bootstrapping_mode = BootstrappingMode::DownloadLatestStates; + config + .state_sync + .state_sync_driver + .fast_sync_wait_for_epoch_change = false; config.state_sync.storage_service.max_state_chunk_size = 1; })) .build() @@ -417,6 +421,10 @@ async fn test_validator_bootstrap_state_snapshot_no_compression() { .with_init_config(Arc::new(|_, config, _| { config.state_sync.state_sync_driver.bootstrapping_mode = BootstrappingMode::DownloadLatestStates; + config + .state_sync + .state_sync_driver + .fast_sync_wait_for_epoch_change = false; config.state_sync.state_sync_driver.continuous_syncing_mode = ContinuousSyncingMode::ApplyTransactionOutputs; config.state_sync.aptos_data_client.use_compression = false; @@ -437,6 +445,10 @@ async fn test_validator_bootstrap_state_snapshot_network_limit() { .with_init_config(Arc::new(|_, config, _| { config.state_sync.state_sync_driver.bootstrapping_mode = BootstrappingMode::DownloadLatestStates; + config + .state_sync + .state_sync_driver + .fast_sync_wait_for_epoch_change = false; config.state_sync.state_sync_driver.continuous_syncing_mode = ContinuousSyncingMode::ExecuteTransactions; config.state_sync.storage_service.max_network_chunk_bytes = 200 * 1024; @@ -458,6 +470,10 @@ async fn test_validator_bootstrap_state_snapshot_network_limit_tiny() { .with_init_config(Arc::new(|_, config, _| { config.state_sync.state_sync_driver.bootstrapping_mode = BootstrappingMode::DownloadLatestStates; + config + .state_sync + .state_sync_driver + .fast_sync_wait_for_epoch_change = false; config.state_sync.state_sync_driver.continuous_syncing_mode = ContinuousSyncingMode::ExecuteTransactions; config.state_sync.storage_service.max_network_chunk_bytes = 1; @@ -477,6 +493,10 @@ async fn test_validator_bootstrap_state_snapshot_exponential_backoff() { .with_init_config(Arc::new(|_, config, _| { config.state_sync.state_sync_driver.bootstrapping_mode = BootstrappingMode::DownloadLatestStates; + config + .state_sync + .state_sync_driver + .fast_sync_wait_for_epoch_change = false; config.state_sync.state_sync_driver.continuous_syncing_mode = ContinuousSyncingMode::ApplyTransactionOutputs; config.state_sync.aptos_data_client.use_compression = false; @@ -650,6 +670,10 @@ async fn test_validator_failure_bootstrap_outputs() { .with_init_config(Arc::new(|_, config, _| { config.state_sync.state_sync_driver.bootstrapping_mode = BootstrappingMode::DownloadLatestStates; + config + .state_sync + .state_sync_driver + .fast_sync_wait_for_epoch_change = false; config.state_sync.state_sync_driver.continuous_syncing_mode = ContinuousSyncingMode::ApplyTransactionOutputs; })) @@ -671,6 +695,10 @@ async fn test_validator_failure_bootstrap_execution() { .with_init_config(Arc::new(|_, config, _| { config.state_sync.state_sync_driver.bootstrapping_mode = BootstrappingMode::DownloadLatestStates; + config + .state_sync + .state_sync_driver + .fast_sync_wait_for_epoch_change = false; config.state_sync.state_sync_driver.continuous_syncing_mode = ContinuousSyncingMode::ExecuteTransactions; }))