mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-08 17:26:04 +00:00
Added Spec Restrictions on Optimistic Block Import
This commit is contained in:
@@ -55,9 +55,11 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use eth2::types::EventKind;
|
use eth2::types::EventKind;
|
||||||
use execution_layer::PayloadStatusV1Status;
|
use execution_layer::PayloadStatusV1Status;
|
||||||
use fork_choice::{ForkChoice, ForkChoiceStore, PayloadVerificationStatus};
|
use fork_choice::{
|
||||||
|
Error as ForkChoiceError, ForkChoice, ForkChoiceStore, PayloadVerificationStatus,
|
||||||
|
};
|
||||||
use parking_lot::RwLockReadGuard;
|
use parking_lot::RwLockReadGuard;
|
||||||
use proto_array::Block as ProtoBlock;
|
use proto_array::{Block as ProtoBlock, ExecutionStatus};
|
||||||
use safe_arith::ArithError;
|
use safe_arith::ArithError;
|
||||||
use slog::{debug, error, Logger};
|
use slog::{debug, error, Logger};
|
||||||
use slot_clock::SlotClock;
|
use slot_clock::SlotClock;
|
||||||
@@ -315,6 +317,8 @@ pub enum ExecutionPayloadError {
|
|||||||
///
|
///
|
||||||
/// The peer is not necessarily invalid.
|
/// The peer is not necessarily invalid.
|
||||||
PoWParentMissing(Hash256),
|
PoWParentMissing(Hash256),
|
||||||
|
/// The execution node is syncing but we fail the conditions for optimistic sync
|
||||||
|
UnverifiedNonOptimisticCandidate,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<execution_layer::Error> for ExecutionPayloadError {
|
impl From<execution_layer::Error> for ExecutionPayloadError {
|
||||||
@@ -1131,6 +1135,34 @@ impl<'a, T: BeaconChainTypes> FullyVerifiedBlock<'a, T> {
|
|||||||
// `randao` may change.
|
// `randao` may change.
|
||||||
let payload_verification_status = notify_new_payload(chain, &state, block.message())?;
|
let payload_verification_status = notify_new_payload(chain, &state, block.message())?;
|
||||||
|
|
||||||
|
if payload_verification_status == PayloadVerificationStatus::NotVerified {
|
||||||
|
// Check the optimistic sync conditions before going further
|
||||||
|
// https://github.com/sigp/consensus-specs/blob/opt-sync-2/sync/optimistic.md#when-to-optimistically-import-blocks
|
||||||
|
let current_slot = chain
|
||||||
|
.slot_clock
|
||||||
|
.now()
|
||||||
|
.ok_or(BeaconChainError::UnableToReadSlot)?;
|
||||||
|
// pass if current slot is at least SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY ahead of the block
|
||||||
|
if current_slot - block.slot() < chain.spec.safe_slots_to_import_optimistically {
|
||||||
|
// pass if the justified checkpoint has execution enabled
|
||||||
|
let justified_root = state.current_justified_checkpoint().root;
|
||||||
|
let justified_checkpoint_execution_status = chain
|
||||||
|
.fork_choice
|
||||||
|
.read()
|
||||||
|
.get_block(&justified_root)
|
||||||
|
.map(|block| block.execution_status)
|
||||||
|
.ok_or(BeaconChainError::ForkChoiceError(
|
||||||
|
ForkChoiceError::MissingProtoArrayBlock(justified_root),
|
||||||
|
))?;
|
||||||
|
if matches!(
|
||||||
|
justified_checkpoint_execution_status,
|
||||||
|
ExecutionStatus::Irrelevant(_)
|
||||||
|
) {
|
||||||
|
return Err(ExecutionPayloadError::UnverifiedNonOptimisticCandidate.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If the block is sufficiently recent, notify the validator monitor.
|
// If the block is sufficiently recent, notify the validator monitor.
|
||||||
if let Some(slot) = chain.slot_clock.now() {
|
if let Some(slot) = chain.slot_clock.now() {
|
||||||
let epoch = slot.epoch(T::EthSpec::slots_per_epoch());
|
let epoch = slot.epoch(T::EthSpec::slots_per_epoch());
|
||||||
|
|||||||
@@ -137,6 +137,15 @@ pub fn validate_merge_block<T: BeaconChainTypes>(
|
|||||||
}
|
}
|
||||||
.into()),
|
.into()),
|
||||||
None => {
|
None => {
|
||||||
|
let current_slot = chain
|
||||||
|
.slot_clock
|
||||||
|
.now()
|
||||||
|
.ok_or(BeaconChainError::UnableToReadSlot)?;
|
||||||
|
// Check the optimistic sync conditions. Note that because this is the merge block,
|
||||||
|
// the justified checkpoint can't have execution enabled so we only need to check the
|
||||||
|
// current slot is at least SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY ahead of the block
|
||||||
|
// https://github.com/sigp/consensus-specs/blob/opt-sync-2/sync/optimistic.md#when-to-optimistically-import-blocks
|
||||||
|
if current_slot - block.slot() >= chain.spec.safe_slots_to_import_optimistically {
|
||||||
debug!(
|
debug!(
|
||||||
chain.log,
|
chain.log,
|
||||||
"Optimistically accepting terminal block";
|
"Optimistically accepting terminal block";
|
||||||
@@ -144,6 +153,9 @@ pub fn validate_merge_block<T: BeaconChainTypes>(
|
|||||||
"msg" => "the terminal block/parent was unavailable"
|
"msg" => "the terminal block/parent was unavailable"
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(ExecutionPayloadError::UnverifiedNonOptimisticCandidate.into())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,12 @@ pub fn get_eth2_network_config(cli_args: &ArgMatches) -> Result<Eth2NetworkConfi
|
|||||||
.terminal_block_hash_activation_epoch = epoch;
|
.terminal_block_hash_activation_epoch = epoch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(slots) = parse_optional(cli_args, "safe-slots-to-import-optimistically")? {
|
||||||
|
eth2_network_config
|
||||||
|
.config
|
||||||
|
.safe_slots_to_import_optimistically = slots;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(eth2_network_config)
|
Ok(eth2_network_config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -146,6 +146,7 @@ pub struct ChainSpec {
|
|||||||
pub terminal_total_difficulty: Uint256,
|
pub terminal_total_difficulty: Uint256,
|
||||||
pub terminal_block_hash: Hash256,
|
pub terminal_block_hash: Hash256,
|
||||||
pub terminal_block_hash_activation_epoch: Epoch,
|
pub terminal_block_hash_activation_epoch: Epoch,
|
||||||
|
pub safe_slots_to_import_optimistically: u64,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Networking
|
* Networking
|
||||||
@@ -551,6 +552,7 @@ impl ChainSpec {
|
|||||||
.expect("addition does not overflow"),
|
.expect("addition does not overflow"),
|
||||||
terminal_block_hash: Hash256::zero(),
|
terminal_block_hash: Hash256::zero(),
|
||||||
terminal_block_hash_activation_epoch: Epoch::new(u64::MAX),
|
terminal_block_hash_activation_epoch: Epoch::new(u64::MAX),
|
||||||
|
safe_slots_to_import_optimistically: 128u64,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Network specific
|
* Network specific
|
||||||
@@ -791,6 +793,9 @@ pub struct Config {
|
|||||||
// TODO(merge): remove this default
|
// TODO(merge): remove this default
|
||||||
#[serde(default = "default_terminal_block_hash_activation_epoch")]
|
#[serde(default = "default_terminal_block_hash_activation_epoch")]
|
||||||
pub terminal_block_hash_activation_epoch: Epoch,
|
pub terminal_block_hash_activation_epoch: Epoch,
|
||||||
|
// TODO(merge): remove this default
|
||||||
|
#[serde(default = "default_safe_slots_to_import_optimistically")]
|
||||||
|
pub safe_slots_to_import_optimistically: u64,
|
||||||
|
|
||||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||||
min_genesis_active_validator_count: u64,
|
min_genesis_active_validator_count: u64,
|
||||||
@@ -878,6 +883,10 @@ fn default_terminal_block_hash_activation_epoch() -> Epoch {
|
|||||||
Epoch::new(u64::MAX)
|
Epoch::new(u64::MAX)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_safe_slots_to_import_optimistically() -> u64 {
|
||||||
|
128u64
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let chain_spec = MainnetEthSpec::default_spec();
|
let chain_spec = MainnetEthSpec::default_spec();
|
||||||
@@ -935,6 +944,7 @@ impl Config {
|
|||||||
terminal_total_difficulty: spec.terminal_total_difficulty,
|
terminal_total_difficulty: spec.terminal_total_difficulty,
|
||||||
terminal_block_hash: spec.terminal_block_hash,
|
terminal_block_hash: spec.terminal_block_hash,
|
||||||
terminal_block_hash_activation_epoch: spec.terminal_block_hash_activation_epoch,
|
terminal_block_hash_activation_epoch: spec.terminal_block_hash_activation_epoch,
|
||||||
|
safe_slots_to_import_optimistically: spec.safe_slots_to_import_optimistically,
|
||||||
|
|
||||||
min_genesis_active_validator_count: spec.min_genesis_active_validator_count,
|
min_genesis_active_validator_count: spec.min_genesis_active_validator_count,
|
||||||
min_genesis_time: spec.min_genesis_time,
|
min_genesis_time: spec.min_genesis_time,
|
||||||
@@ -985,6 +995,7 @@ impl Config {
|
|||||||
terminal_total_difficulty,
|
terminal_total_difficulty,
|
||||||
terminal_block_hash,
|
terminal_block_hash,
|
||||||
terminal_block_hash_activation_epoch,
|
terminal_block_hash_activation_epoch,
|
||||||
|
safe_slots_to_import_optimistically,
|
||||||
min_genesis_active_validator_count,
|
min_genesis_active_validator_count,
|
||||||
min_genesis_time,
|
min_genesis_time,
|
||||||
genesis_fork_version,
|
genesis_fork_version,
|
||||||
@@ -1040,6 +1051,7 @@ impl Config {
|
|||||||
terminal_total_difficulty,
|
terminal_total_difficulty,
|
||||||
terminal_block_hash,
|
terminal_block_hash,
|
||||||
terminal_block_hash_activation_epoch,
|
terminal_block_hash_activation_epoch,
|
||||||
|
safe_slots_to_import_optimistically,
|
||||||
..chain_spec.clone()
|
..chain_spec.clone()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -251,6 +251,19 @@ fn main() {
|
|||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.global(true)
|
.global(true)
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("safe-slots-to-import-optimistically")
|
||||||
|
.long("safe-slots-to-import-optimistically")
|
||||||
|
.value_name("INTEGER")
|
||||||
|
.help("Used to coordinate manual overrides of the SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY \
|
||||||
|
parameter. This flag should only be used if the user has a clear understanding \
|
||||||
|
that the broad Ethereum community has elected to override this parameter in the event \
|
||||||
|
of an attack at the PoS transition block. Incorrect use of this flag can cause your \
|
||||||
|
node to possibly accept an invalid chain or sync more slowly. Be extremely careful with \
|
||||||
|
this flag.")
|
||||||
|
.takes_value(true)
|
||||||
|
.global(true)
|
||||||
|
)
|
||||||
.subcommand(beacon_node::cli_app())
|
.subcommand(beacon_node::cli_app())
|
||||||
.subcommand(boot_node::cli_app())
|
.subcommand(boot_node::cli_app())
|
||||||
.subcommand(validator_client::cli_app())
|
.subcommand(validator_client::cli_app())
|
||||||
|
|||||||
Reference in New Issue
Block a user