Disallow genesis sync outside blob pruning window (#5038)
* Disallow Syncing From Genesis By Default * Fix CLI Tests * Perform checks in the `ClientBuilder` * Tidy, fix tests * Return an error based on the Deneb fork * Fix typos * Fix failing test * Add missing CLI flag * Fix CLI flags * Add suggestion from Sean * Fix conflict with blob sidecars epochs --------- Co-authored-by: Mark Mackey <mark@sigmaprime.io>
This commit is contained in:
parent
b47e3f252e
commit
12d3d237cd
@ -35,6 +35,7 @@ use std::net::TcpListener;
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
use timer::spawn_timer;
|
use timer::spawn_timer;
|
||||||
use tokio::sync::oneshot;
|
use tokio::sync::oneshot;
|
||||||
use types::{
|
use types::{
|
||||||
@ -45,6 +46,11 @@ use types::{
|
|||||||
/// Interval between polling the eth1 node for genesis information.
|
/// Interval between polling the eth1 node for genesis information.
|
||||||
pub const ETH1_GENESIS_UPDATE_INTERVAL_MILLIS: u64 = 7_000;
|
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 manage to sync the chain.
|
||||||
|
const BLOB_AVAILABILITY_REDUCTION_EPOCHS: u64 = 2;
|
||||||
|
|
||||||
/// Builds a `Client` instance.
|
/// Builds a `Client` instance.
|
||||||
///
|
///
|
||||||
/// ## Notes
|
/// ## Notes
|
||||||
@ -252,6 +258,45 @@ where
|
|||||||
|
|
||||||
let genesis_state = genesis_state(&runtime_context, &config, log).await?;
|
let genesis_state = genesis_state(&runtime_context, &config, log).await?;
|
||||||
|
|
||||||
|
// If the user has not explicitly allowed genesis sync, prevent
|
||||||
|
// them 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 {
|
||||||
|
if let Some(deneb_fork_epoch) = spec.deneb_fork_epoch {
|
||||||
|
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 deneb_time =
|
||||||
|
genesis_time + (deneb_fork_epoch.as_u64() * 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_p2p_availability_epochs = spec
|
||||||
|
.min_epochs_for_blob_sidecars_requests
|
||||||
|
.saturating_sub(BLOB_AVAILABILITY_REDUCTION_EPOCHS);
|
||||||
|
let blob_availability_window = reduced_p2p_availability_epochs
|
||||||
|
* TEthSpec::slots_per_epoch()
|
||||||
|
* spec.seconds_per_slot;
|
||||||
|
|
||||||
|
if now > deneb_time + 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: https://eth-clients.github.io/checkpoint-sync-endpoints/ \
|
||||||
|
Alternatively, use --allow-insecure-genesis-sync if the risks are understood."
|
||||||
|
.to_string(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
builder.genesis_state(genesis_state).map(|v| (v, None))?
|
builder.genesis_state(genesis_state).map(|v| (v, None))?
|
||||||
}
|
}
|
||||||
ClientGenesis::WeakSubjSszBytes {
|
ClientGenesis::WeakSubjSszBytes {
|
||||||
|
@ -78,6 +78,7 @@ pub struct Config {
|
|||||||
pub beacon_processor: BeaconProcessorConfig,
|
pub beacon_processor: BeaconProcessorConfig,
|
||||||
pub genesis_state_url: Option<String>,
|
pub genesis_state_url: Option<String>,
|
||||||
pub genesis_state_url_timeout: Duration,
|
pub genesis_state_url_timeout: Duration,
|
||||||
|
pub allow_insecure_genesis_sync: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
@ -108,6 +109,7 @@ impl Default for Config {
|
|||||||
genesis_state_url: <_>::default(),
|
genesis_state_url: <_>::default(),
|
||||||
// This default value should always be overwritten by the CLI default value.
|
// This default value should always be overwritten by the CLI default value.
|
||||||
genesis_state_url_timeout: Duration::from_secs(60),
|
genesis_state_url_timeout: Duration::from_secs(60),
|
||||||
|
allow_insecure_genesis_sync: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -955,6 +955,16 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
|
|||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.default_value("180")
|
.default_value("180")
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("allow-insecure-genesis-sync")
|
||||||
|
.long("allow-insecure-genesis-sync")
|
||||||
|
.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)
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("reconstruct-historic-states")
|
Arg::with_name("reconstruct-historic-states")
|
||||||
.long("reconstruct-historic-states")
|
.long("reconstruct-historic-states")
|
||||||
|
@ -497,6 +497,8 @@ pub fn get_config<E: EthSpec>(
|
|||||||
None
|
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() {
|
client_config.genesis = if eth2_network_config.genesis_state_is_known() {
|
||||||
// Set up weak subjectivity sync, or start from the hardcoded genesis state.
|
// Set up weak subjectivity sync, or start from the hardcoded genesis state.
|
||||||
if let (Some(initial_state_path), Some(initial_block_path)) = (
|
if let (Some(initial_state_path), Some(initial_block_path)) = (
|
||||||
|
@ -9,6 +9,10 @@ USAGE:
|
|||||||
lighthouse beacon_node [FLAGS] [OPTIONS]
|
lighthouse beacon_node [FLAGS] [OPTIONS]
|
||||||
|
|
||||||
FLAGS:
|
FLAGS:
|
||||||
|
--allow-insecure-genesis-sync 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!
|
||||||
--always-prefer-builder-payload This flag is deprecated and has no effect.
|
--always-prefer-builder-payload This flag is deprecated and has no effect.
|
||||||
--always-prepare-payload Send payload attributes with every fork choice update. This is intended
|
--always-prepare-payload Send payload attributes with every fork choice update. This is intended
|
||||||
for use by block builders, relays and developers. You should set a fee
|
for use by block builders, relays and developers. You should set a fee
|
||||||
|
@ -92,6 +92,22 @@ fn staking_flag() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn allow_insecure_genesis_sync() {
|
||||||
|
CommandLineTest::new()
|
||||||
|
.run_with_zero_port()
|
||||||
|
.with_config(|config| {
|
||||||
|
assert_eq!(config.allow_insecure_genesis_sync, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
CommandLineTest::new()
|
||||||
|
.flag("allow-insecure-genesis-sync", None)
|
||||||
|
.run_with_zero_port()
|
||||||
|
.with_config(|config| {
|
||||||
|
assert_eq!(config.allow_insecure_genesis_sync, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn wss_checkpoint_flag() {
|
fn wss_checkpoint_flag() {
|
||||||
let state = Some(Checkpoint {
|
let state = Some(Checkpoint {
|
||||||
|
Loading…
Reference in New Issue
Block a user