Skip to content

Commit

Permalink
Perform checks in the ClientBuilder
Browse files Browse the repository at this point in the history
  • Loading branch information
paulhauner committed Jan 8, 2024
1 parent 328ad6c commit 5033bfa
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 15 deletions.
38 changes: 38 additions & 0 deletions beacon_node/client/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,23 @@ use std::net::TcpListener;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::time::Duration;
use std::time::{SystemTime, UNIX_EPOCH};
use timer::spawn_timer;
use tokio::sync::oneshot;
use types::{
consts::deneb::MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS,
test_utils::generate_deterministic_keypairs, BeaconState, ChainSpec, EthSpec,
ExecutionBlockHash, Hash256, SignedBeaconBlock,
};

/// Interval between polling the eth1 node for genesis information.
pub const ETH1_GENESIS_UPDATE_INTERVAL_MILLIS: u64 = 7_000;

/// Reduces the blob availability period by some epochs. Helps prevent the user
/// from starting a genesis sync so near to the blob pruning window that blobs
/// have been pruned before they can managed to sync the chain.
const BLOB_AVAILABILITY_REDUCTION_EPOCHS: u64 = 2;

/// Builds a `Client` instance.
///
/// ## Notes
Expand Down Expand Up @@ -252,6 +259,37 @@ where

let genesis_state = genesis_state(&runtime_context, &config, log).await?;

// If the user has not explicitly allowed genesis sync, prevent
// the user from trying to sync from genesis if we're outside of
// the blob P2P availability window.
//
// It doesn't make sense to try and sync the chain if we can't
// verify blob availability by downloading blobs from the P2P
// network. The user should do a checkpoint sync instead.
if !config.allow_insecure_genesis_sync {
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map_err(|e| format!("Unable to read system time: {e:}"))?
.as_secs();
let genesis_time = genesis_state.genesis_time();
let blob_availability_window = MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS.as_u64()
* TEthSpec::slots_per_epoch()
* spec.seconds_per_slot;
// Shrink the blob availability window so users don't start
// a sync right before blobs start to disappear from the P2P
// network.
let reduced_blob_availability_window = blob_availability_window.saturating_sub(TEthSpec::slots_per_epoch() * spec.seconds_per_slot * BLOB_AVAILABILITY_REDUCTION_EPOCHS)

if now > genesis_time + reduced_blob_availability_window {
return Err(
"Syncing from genesis is insecure and incompatible with data availability checks. \
You should instead perform a checkpoint sync from a trusted node using the --checkpoint-sync-url option. \
For a list of public endpoints, see:\nhttps://eth-clients.github.io/checkpoint-sync-endpoints/"
.to_string(),
);
}
}

builder.genesis_state(genesis_state).map(|v| (v, None))?
}
ClientGenesis::WeakSubjSszBytes {
Expand Down
2 changes: 2 additions & 0 deletions beacon_node/client/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ pub struct Config {
pub beacon_processor: BeaconProcessorConfig,
pub genesis_state_url: Option<String>,
pub genesis_state_url_timeout: Duration,
pub allow_insecure_genesis_sync: bool,
}

impl Default for Config {
Expand Down Expand Up @@ -108,6 +109,7 @@ impl Default for Config {
genesis_state_url: <_>::default(),
// This default value should always be overwritten by the CLI default value.
genesis_state_url_timeout: Duration::from_secs(60),
allow_insecure_genesis_sync: false,
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion beacon_node/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -958,7 +958,9 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
.arg(
Arg::with_name("allow-insecure-genesis-sync")
.long("allow-insecure-genesis-sync")
.help("Enable syncing from genesis. This is insecure after Capella due to long-range attacks. This should only be used for testing. DO NOT use on mainnet!")
.help("Enable syncing from genesis, which is generally insecure and incompatible with data availability checks. \
Checkpoint syncing is the preferred method for syncing a node. \
Only use this flag when testing. DO NOT use on mainnet!")
.conflicts_with("checkpoint-sync-url")
.conflicts_with("checkpoint-state")
.takes_value(false)
Expand Down
11 changes: 3 additions & 8 deletions beacon_node/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,8 @@ pub fn get_config<E: EthSpec>(
None
};

client_config.allow_insecure_genesis_sync = cli_args.is_present("allow-insecure-genesis-sync");

client_config.genesis = if eth2_network_config.genesis_state_is_known() {
// Set up weak subjectivity sync, or start from the hardcoded genesis state.
if let (Some(initial_state_path), Some(initial_block_path)) = (
Expand Down Expand Up @@ -518,15 +520,8 @@ pub fn get_config<E: EthSpec>(
.map_err(|e| format!("Invalid checkpoint sync URL: {:?}", e))?;

ClientGenesis::CheckpointSyncUrl { url }
} else if cli_args.is_present("allow-insecure-genesis-sync") {
ClientGenesis::GenesisState
} else {
return Err(
"Syncing from genesis is not secure post-Capella! \
You should instead perform a checkpoint sync from a trusted node using the --checkpoint-sync-url option. \
For a list of public endpoints, see:\nhttps://eth-clients.github.io/checkpoint-sync-endpoints/"
.to_string(),
);
ClientGenesis::GenesisState
}
} else {
if cli_args.is_present("checkpoint-state") || cli_args.is_present("checkpoint-sync-url") {
Expand Down
6 changes: 0 additions & 6 deletions lighthouse/tests/beacon_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,6 @@ struct CommandLineTest {
}
impl CommandLineTest {
fn new() -> CommandLineTest {
let mut base_cmd = base_cmd();
base_cmd.arg("--allow-insecure-genesis-sync");
CommandLineTest { cmd: base_cmd }
}

fn without_allow_genesis_sync() -> CommandLineTest {
let base_cmd = base_cmd();
CommandLineTest { cmd: base_cmd }
}
Expand Down

0 comments on commit 5033bfa

Please sign in to comment.