diff --git a/beacon_node/beacon_chain/src/chain_config.rs b/beacon_node/beacon_chain/src/chain_config.rs index 9921435313d..a74fdced1f6 100644 --- a/beacon_node/beacon_chain/src/chain_config.rs +++ b/beacon_node/beacon_chain/src/chain_config.rs @@ -73,6 +73,9 @@ pub struct ChainConfig { pub optimistic_finalized_sync: bool, /// The size of the shuffling cache, pub shuffling_cache_size: usize, + /// If using a weak-subjectivity sync, whether we should download blocks all the way back to + /// genesis. + pub genesis_backfill: bool, /// Whether to send payload attributes every slot, regardless of connected proposers. /// /// This is useful for block builders and testing. @@ -106,6 +109,7 @@ impl Default for ChainConfig { // This value isn't actually read except in tests. optimistic_finalized_sync: true, shuffling_cache_size: crate::shuffling_cache::DEFAULT_CACHE_SIZE, + genesis_backfill: false, always_prepare_payload: false, enable_backfill_rate_limiting: true, } diff --git a/beacon_node/beacon_chain/src/historical_blocks.rs b/beacon_node/beacon_chain/src/historical_blocks.rs index 85a9ec8fb0b..657415ac8b5 100644 --- a/beacon_node/beacon_chain/src/historical_blocks.rs +++ b/beacon_node/beacon_chain/src/historical_blocks.rs @@ -193,13 +193,17 @@ impl BeaconChain { oldest_block_parent: expected_block_root, ..anchor_info }; - let backfill_complete = new_anchor.block_backfill_complete(); + let backfill_complete = new_anchor.block_backfill_complete(self.genesis_backfill_slot); self.store .compare_and_set_anchor_info_with_write(Some(anchor_info), Some(new_anchor))?; // If backfill has completed and the chain is configured to reconstruct historic states, // send a message to the background migrator instructing it to begin reconstruction. - if backfill_complete && self.config.reconstruct_historic_states { + // This can only happen if we have backfilled all the way to genesis. + if backfill_complete + && self.genesis_backfill_slot == Slot::new(0) + && self.config.reconstruct_historic_states + { self.store_migrator.process_reconstruction(); } diff --git a/beacon_node/client/src/builder.rs b/beacon_node/client/src/builder.rs index 329f0727542..39921115fc5 100644 --- a/beacon_node/client/src/builder.rs +++ b/beacon_node/client/src/builder.rs @@ -258,6 +258,12 @@ where genesis_state_bytes, } => { info!(context.log(), "Starting checkpoint sync"); + if config.chain.genesis_backfill { + info!( + context.log(), + "Blocks will downloaded all the way back to genesis" + ); + } let anchor_state = BeaconState::from_ssz_bytes(&anchor_state_bytes, &spec) .map_err(|e| format!("Unable to parse weak subj state SSZ: {:?}", e))?; @@ -279,6 +285,12 @@ where "Starting checkpoint sync"; "remote_url" => %url, ); + if config.chain.genesis_backfill { + info!( + context.log(), + "Blocks will be downloaded all the way back to genesis" + ); + } let remote = BeaconNodeHttpClient::new( url, diff --git a/beacon_node/client/src/notifier.rs b/beacon_node/client/src/notifier.rs index 1105bc41f67..1ff469fe300 100644 --- a/beacon_node/client/src/notifier.rs +++ b/beacon_node/client/src/notifier.rs @@ -142,7 +142,8 @@ pub fn spawn_notifier( .get_anchor_info() .map(|ai| ai.oldest_block_slot) { - sync_distance = current_anchor_slot; + sync_distance = current_anchor_slot + .saturating_sub(beacon_chain.genesis_backfill_slot); speedo // For backfill sync use a fake slot which is the distance we've progressed from the starting `oldest_block_slot`. .observe( @@ -207,14 +208,14 @@ pub fn spawn_notifier( "Downloading historical blocks"; "distance" => distance, "speed" => sync_speed_pretty(speed), - "est_time" => estimated_time_pretty(speedo.estimated_time_till_slot(original_anchor_slot.unwrap_or(current_slot))), + "est_time" => estimated_time_pretty(speedo.estimated_time_till_slot(original_anchor_slot.unwrap_or(current_slot).saturating_sub(beacon_chain.genesis_backfill_slot))), ); } else { info!( log, "Downloading historical blocks"; "distance" => distance, - "est_time" => estimated_time_pretty(speedo.estimated_time_till_slot(original_anchor_slot.unwrap_or(current_slot))), + "est_time" => estimated_time_pretty(speedo.estimated_time_till_slot(original_anchor_slot.unwrap_or(current_slot).saturating_sub(beacon_chain.genesis_backfill_slot))), ); } } else if !is_backfilling && last_backfill_log_slot.is_some() { diff --git a/beacon_node/lighthouse_network/src/types/sync_state.rs b/beacon_node/lighthouse_network/src/types/sync_state.rs index 5f09aec27a7..b82e63bd9c0 100644 --- a/beacon_node/lighthouse_network/src/types/sync_state.rs +++ b/beacon_node/lighthouse_network/src/types/sync_state.rs @@ -13,7 +13,7 @@ pub enum SyncState { /// The node is undertaking a backfill sync. This occurs when a user has specified a trusted /// state. The node first syncs "forward" by downloading blocks up to the current head as /// specified by its peers. Once completed, the node enters this sync state and attempts to - /// download all required historical blocks to complete its chain. + /// download all required historical blocks. BackFillSyncing { completed: usize, remaining: usize }, /// The node has completed syncing a finalized chain and is in the process of re-evaluating /// which sync state to progress to. diff --git a/beacon_node/src/cli.rs b/beacon_node/src/cli.rs index ca20ba352f8..a15a420a226 100644 --- a/beacon_node/src/cli.rs +++ b/beacon_node/src/cli.rs @@ -254,6 +254,12 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .help("One or more comma-delimited trusted peer ids which always have the highest score according to the peer scoring system.") .takes_value(true), ) + .arg( + Arg::with_name("genesis-backfill") + .long("genesis-backfill") + .help("Attempts to download blocks all the way back to genesis when checkpoint syncing.") + .takes_value(false), + ) .arg( Arg::with_name("enable-private-discovery") .long("enable-private-discovery") @@ -873,7 +879,7 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .arg( Arg::with_name("reconstruct-historic-states") .long("reconstruct-historic-states") - .help("After a checkpoint sync, reconstruct historic states in the database.") + .help("After a checkpoint sync, reconstruct historic states in the database. This requires syncing all the way back to genesis.") .takes_value(false) ) .arg( diff --git a/beacon_node/src/config.rs b/beacon_node/src/config.rs index 272ac9b3310..e2863e98388 100644 --- a/beacon_node/src/config.rs +++ b/beacon_node/src/config.rs @@ -545,6 +545,7 @@ pub fn get_config( if cli_args.is_present("reconstruct-historic-states") { client_config.chain.reconstruct_historic_states = true; + client_config.chain.genesis_backfill = true; } let raw_graffiti = if let Some(graffiti) = cli_args.value_of("graffiti") { @@ -817,6 +818,9 @@ pub fn get_config( client_config.chain.optimistic_finalized_sync = !cli_args.is_present("disable-optimistic-finalized-sync"); + if cli_args.is_present("genesis-backfill") { + client_config.chain.genesis_backfill = true; + } // Payload selection configs if cli_args.is_present("always-prefer-builder-payload") { client_config.always_prefer_builder_payload = true; diff --git a/beacon_node/store/src/metadata.rs b/beacon_node/store/src/metadata.rs index 6d27f0cc85a..4a58674936a 100644 --- a/beacon_node/store/src/metadata.rs +++ b/beacon_node/store/src/metadata.rs @@ -100,8 +100,10 @@ pub struct AnchorInfo { impl AnchorInfo { /// Returns true if the block backfill has completed. - pub fn block_backfill_complete(&self) -> bool { - self.oldest_block_slot == 0 + /// This is a comparison between the oldest block slot and the target backfill slot (which is + /// likely to be the closest WSP). + pub fn block_backfill_complete(&self, target_slot: Slot) -> bool { + self.oldest_block_slot <= target_slot } } diff --git a/lighthouse/tests/beacon_node.rs b/lighthouse/tests/beacon_node.rs index 8b924b5a511..59f5f9ee57b 100644 --- a/lighthouse/tests/beacon_node.rs +++ b/lighthouse/tests/beacon_node.rs @@ -345,6 +345,23 @@ fn trusted_peers_flag() { }); } +#[test] +fn genesis_backfill_flag() { + CommandLineTest::new() + .flag("genesis-backfill", None) + .run_with_zero_port() + .with_config(|config| assert_eq!(config.chain.genesis_backfill, true)); +} + +/// The genesis backfill flag should be enabled if historic states flag is set. +#[test] +fn genesis_backfill_with_historic_flag() { + CommandLineTest::new() + .flag("reconstruct-historic-states", None) + .run_with_zero_port() + .with_config(|config| assert_eq!(config.chain.genesis_backfill, true)); +} + #[test] fn always_prefer_builder_payload_flag() { CommandLineTest::new()