mirror of
https://github.com/sigp/lighthouse.git
synced 2026-07-04 21:34:36 +00:00
Allow for reimporting block+envelope in certain cases
This commit is contained in:
@@ -64,6 +64,7 @@ use crate::payload_attestation_verification::VerifiedPayloadAttestationMessage;
|
|||||||
use crate::payload_bid_verification::payload_bid_cache::GossipVerifiedPayloadBidCache;
|
use crate::payload_bid_verification::payload_bid_cache::GossipVerifiedPayloadBidCache;
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
use crate::payload_envelope_streamer::{EnvelopeRequestSource, launch_payload_envelope_stream};
|
use crate::payload_envelope_streamer::{EnvelopeRequestSource, launch_payload_envelope_stream};
|
||||||
|
use crate::payload_envelope_verification::check_envelope_relevancy;
|
||||||
use crate::pending_payload_cache::PendingPayloadCache;
|
use crate::pending_payload_cache::PendingPayloadCache;
|
||||||
use crate::pending_payload_cache::{
|
use crate::pending_payload_cache::{
|
||||||
Availability as PayloadAvailability,
|
Availability as PayloadAvailability,
|
||||||
@@ -3000,7 +3001,18 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match check_block_relevancy(block.as_block(), block_root, self) {
|
let is_envelope_relevant = if let Some(envelope) = block.as_envelope() {
|
||||||
|
// If the envelope is relevant we skip the duplicate import check in
|
||||||
|
// `check_block_relevancy`
|
||||||
|
match check_envelope_relevancy(block.as_block(), envelope, self) {
|
||||||
|
Ok(_) => true,
|
||||||
|
Err(_) => false,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
match check_block_relevancy(block.as_block(), block_root, is_envelope_relevant, self) {
|
||||||
// If the block is relevant, add it to the filtered chain segment.
|
// If the block is relevant, add it to the filtered chain segment.
|
||||||
Ok(_) => filtered_chain_segment.push((block_root, block)),
|
Ok(_) => filtered_chain_segment.push((block_root, block)),
|
||||||
// If the block is already known, simply ignore this block.
|
// If the block is already known, simply ignore this block.
|
||||||
|
|||||||
@@ -97,11 +97,10 @@ use store::{Error as DBError, KeyValueStore};
|
|||||||
use strum::{AsRefStr, IntoStaticStr};
|
use strum::{AsRefStr, IntoStaticStr};
|
||||||
use task_executor::JoinHandle;
|
use task_executor::JoinHandle;
|
||||||
use tracing::{Instrument, Span, debug, debug_span, error, info_span, instrument};
|
use tracing::{Instrument, Span, debug, debug_span, error, info_span, instrument};
|
||||||
use types::ExecutionBlockHash;
|
|
||||||
use types::{
|
use types::{
|
||||||
BeaconBlockRef, BeaconState, BeaconStateError, BlobsList, ChainSpec, DataColumnSidecarList,
|
BeaconBlockRef, BeaconState, BeaconStateError, BlobsList, ChainSpec, DataColumnSidecarList,
|
||||||
Epoch, EthSpec, FullPayload, Hash256, InconsistentFork, KzgProofs, RelativeEpoch,
|
Epoch, EthSpec, ExecutionBlockHash, FullPayload, Hash256, InconsistentFork, KzgProofs,
|
||||||
SignedBeaconBlock, SignedBeaconBlockHeader, Slot, data::DataColumnSidecarError,
|
RelativeEpoch, SignedBeaconBlock, SignedBeaconBlockHeader, Slot, data::DataColumnSidecarError,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Maximum block slot number. Block with slots bigger than this constant will NOT be processed.
|
/// Maximum block slot number. Block with slots bigger than this constant will NOT be processed.
|
||||||
@@ -1350,7 +1349,7 @@ impl<T: BeaconChainTypes> IntoExecutionPendingBlock<T> for RangeSyncBlock<T::Eth
|
|||||||
) -> Result<ExecutionPendingBlock<T>, BlockSlashInfo<BlockError>> {
|
) -> Result<ExecutionPendingBlock<T>, BlockSlashInfo<BlockError>> {
|
||||||
// Perform an early check to prevent wasting time on irrelevant blocks.
|
// Perform an early check to prevent wasting time on irrelevant blocks.
|
||||||
let header = self.signed_block_header();
|
let header = self.signed_block_header();
|
||||||
let block_root = check_block_relevancy(self.as_block(), block_root, chain)
|
let block_root = check_block_relevancy(self.as_block(), block_root, false, chain)
|
||||||
.map_err(|e| BlockSlashInfo::SignatureNotChecked(header.clone(), e))?;
|
.map_err(|e| BlockSlashInfo::SignatureNotChecked(header.clone(), e))?;
|
||||||
|
|
||||||
let (available_block, _envelope) = self.into_available_block().map_err(|e| {
|
let (available_block, _envelope) = self.into_available_block().map_err(|e| {
|
||||||
@@ -1394,7 +1393,7 @@ impl<T: BeaconChainTypes> IntoExecutionPendingBlock<T> for LookupBlock<T::EthSpe
|
|||||||
notify_execution_layer: NotifyExecutionLayer,
|
notify_execution_layer: NotifyExecutionLayer,
|
||||||
) -> Result<ExecutionPendingBlock<T>, BlockSlashInfo<BlockError>> {
|
) -> Result<ExecutionPendingBlock<T>, BlockSlashInfo<BlockError>> {
|
||||||
// Perform an early check to prevent wasting time on irrelevant blocks.
|
// Perform an early check to prevent wasting time on irrelevant blocks.
|
||||||
let block_root = check_block_relevancy(self.as_block(), block_root, chain)
|
let block_root = check_block_relevancy(self.as_block(), block_root, false, chain)
|
||||||
.map_err(|e| BlockSlashInfo::SignatureNotChecked(self.signed_block_header(), e))?;
|
.map_err(|e| BlockSlashInfo::SignatureNotChecked(self.signed_block_header(), e))?;
|
||||||
|
|
||||||
let maybe_available_block = MaybeAvailableBlock::AvailabilityPending {
|
let maybe_available_block = MaybeAvailableBlock::AvailabilityPending {
|
||||||
@@ -1467,7 +1466,7 @@ impl<T: BeaconChainTypes> ExecutionPendingBlock<T> {
|
|||||||
/*
|
/*
|
||||||
* Perform cursory checks to see if the block is even worth processing.
|
* Perform cursory checks to see if the block is even worth processing.
|
||||||
*/
|
*/
|
||||||
check_block_relevancy(block.as_block(), block_root, chain)?;
|
check_block_relevancy(block.as_block(), block_root, false, chain)?;
|
||||||
|
|
||||||
// Define a future that will verify the execution payload with an execution engine.
|
// Define a future that will verify the execution payload with an execution engine.
|
||||||
//
|
//
|
||||||
@@ -1851,6 +1850,7 @@ pub fn check_block_is_finalized_checkpoint_or_descendant<
|
|||||||
pub fn check_block_relevancy<T: BeaconChainTypes>(
|
pub fn check_block_relevancy<T: BeaconChainTypes>(
|
||||||
signed_block: &SignedBeaconBlock<T::EthSpec>,
|
signed_block: &SignedBeaconBlock<T::EthSpec>,
|
||||||
block_root: Hash256,
|
block_root: Hash256,
|
||||||
|
skip_import_check: bool,
|
||||||
chain: &BeaconChain<T>,
|
chain: &BeaconChain<T>,
|
||||||
) -> Result<Hash256, BlockError> {
|
) -> Result<Hash256, BlockError> {
|
||||||
let block = signed_block.message();
|
let block = signed_block.message();
|
||||||
@@ -1880,11 +1880,12 @@ pub fn check_block_relevancy<T: BeaconChainTypes>(
|
|||||||
check_block_against_finalized_slot(block, block_root, chain)?;
|
check_block_against_finalized_slot(block, block_root, chain)?;
|
||||||
|
|
||||||
// Check if the block is already known. We know it is post-finalization, so it is
|
// Check if the block is already known. We know it is post-finalization, so it is
|
||||||
// sufficient to check the fork choice.
|
// sufficient to check the fork choice. This check can optionally be skipped.
|
||||||
if chain
|
if skip_import_check
|
||||||
.canonical_head
|
&& chain
|
||||||
.fork_choice_read_lock()
|
.canonical_head
|
||||||
.contains_block(&block_root)
|
.fork_choice_read_lock()
|
||||||
|
.contains_block(&block_root)
|
||||||
{
|
{
|
||||||
return Err(BlockError::DuplicateFullyImported(block_root));
|
return Err(BlockError::DuplicateFullyImported(block_root));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use std::sync::Arc;
|
|||||||
use types::data::BlobIdentifier;
|
use types::data::BlobIdentifier;
|
||||||
use types::{
|
use types::{
|
||||||
BeaconBlockRef, BeaconState, BlindedPayload, ChainSpec, Epoch, EthSpec, Hash256,
|
BeaconBlockRef, BeaconState, BlindedPayload, ChainSpec, Epoch, EthSpec, Hash256,
|
||||||
SignedBeaconBlock, SignedBeaconBlockHeader, Slot,
|
SignedBeaconBlock, SignedBeaconBlockHeader, SignedExecutionPayloadEnvelope, Slot,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A wrapper around a `SignedBeaconBlock`. This varaint is constructed
|
/// A wrapper around a `SignedBeaconBlock`. This varaint is constructed
|
||||||
@@ -111,6 +111,15 @@ impl<E: EthSpec> RangeSyncBlock<E> {
|
|||||||
.filter(|columns| !columns.is_empty()),
|
.filter(|columns| !columns.is_empty()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn as_envelope(&self) -> Option<&SignedExecutionPayloadEnvelope<E>> {
|
||||||
|
match self {
|
||||||
|
RangeSyncBlock::Base(_) => None,
|
||||||
|
RangeSyncBlock::Gloas { envelope, .. } => {
|
||||||
|
envelope.as_ref().map(|e| e.envelope().as_ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: EthSpec> RangeSyncBlock<E> {
|
impl<E: EthSpec> RangeSyncBlock<E> {
|
||||||
|
|||||||
@@ -173,14 +173,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
.map_err(BeaconChainError::TokioJoin)?
|
.map_err(BeaconChainError::TokioJoin)?
|
||||||
.ok_or(BeaconChainError::RuntimeShutdown)??;
|
.ok_or(BeaconChainError::RuntimeShutdown)??;
|
||||||
|
|
||||||
// TODO(gloas): optimistic sync is not supported for Gloas, maybe we could re-add it
|
|
||||||
if payload_verification_outcome
|
|
||||||
.payload_verification_status
|
|
||||||
.is_optimistic()
|
|
||||||
{
|
|
||||||
return Err(EnvelopeError::OptimisticSyncNotSupported { block_root });
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(AvailabilityPendingExecutedEnvelope::new(
|
Ok(AvailabilityPendingExecutedEnvelope::new(
|
||||||
signed_envelope,
|
signed_envelope,
|
||||||
block_root,
|
block_root,
|
||||||
|
|||||||
@@ -25,12 +25,13 @@ use strum::AsRefStr;
|
|||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
use types::{
|
use types::{
|
||||||
BeaconState, BeaconStateError, DataColumnSidecarList, EthSpec, ExecutionBlockHash,
|
BeaconState, BeaconStateError, DataColumnSidecarList, EthSpec, ExecutionBlockHash,
|
||||||
ExecutionPayloadEnvelope, Hash256, SignedExecutionPayloadEnvelope, Slot,
|
ExecutionPayloadEnvelope, Hash256, SignedBeaconBlock, SignedExecutionPayloadEnvelope, Slot,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
BeaconChainError, BeaconChainTypes, BeaconStore, BlockError, ExecutionPayloadError,
|
BeaconChain, BeaconChainError, BeaconChainTypes, BeaconStore, BlockError,
|
||||||
PayloadVerificationError, PayloadVerificationOutcome,
|
ExecutionPayloadError, PayloadVerificationError, PayloadVerificationOutcome,
|
||||||
|
payload_envelope_verification::gossip_verified_envelope::verify_envelope_consistency,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod execution_pending_envelope;
|
pub mod execution_pending_envelope;
|
||||||
@@ -166,8 +167,6 @@ pub enum EnvelopeError {
|
|||||||
EnvelopeProcessingError(EnvelopeProcessingError),
|
EnvelopeProcessingError(EnvelopeProcessingError),
|
||||||
/// Error verifying the execution payload
|
/// Error verifying the execution payload
|
||||||
ExecutionPayloadError(ExecutionPayloadError),
|
ExecutionPayloadError(ExecutionPayloadError),
|
||||||
/// Optimistic sync is not supported for Gloas payload envelopes.
|
|
||||||
OptimisticSyncNotSupported { block_root: Hash256 },
|
|
||||||
/// The envelope's beacon block was not present in fork choice at import time.
|
/// The envelope's beacon block was not present in fork choice at import time.
|
||||||
///
|
///
|
||||||
/// Unlike [`EnvelopeError::BlockRootUnknown`] (raised during gossip verification, where the
|
/// Unlike [`EnvelopeError::BlockRootUnknown`] (raised during gossip verification, where the
|
||||||
@@ -199,7 +198,6 @@ impl EnvelopeError {
|
|||||||
| EnvelopeError::PriorToFinalization { .. }
|
| EnvelopeError::PriorToFinalization { .. }
|
||||||
| EnvelopeError::BeaconChainError(_)
|
| EnvelopeError::BeaconChainError(_)
|
||||||
| EnvelopeError::BeaconStateError(_)
|
| EnvelopeError::BeaconStateError(_)
|
||||||
| EnvelopeError::OptimisticSyncNotSupported { .. }
|
|
||||||
| EnvelopeError::BlockRootNotInForkChoice(_)
|
| EnvelopeError::BlockRootNotInForkChoice(_)
|
||||||
| EnvelopeError::InternalError(_) => false,
|
| EnvelopeError::InternalError(_) => false,
|
||||||
}
|
}
|
||||||
@@ -292,3 +290,41 @@ pub(crate) fn load_snapshot_from_state_root<T: BeaconChainTypes>(
|
|||||||
beacon_block_root,
|
beacon_block_root,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Performs simple, cheap checks to ensure that the envelope is relevant to be imported.
|
||||||
|
///
|
||||||
|
/// `Ok(block_root` is returned if the envelope passes these checks and should progress with
|
||||||
|
/// verification.
|
||||||
|
///
|
||||||
|
/// Returns an error if the envelope is not relevant or if an error occurs during a verification step.
|
||||||
|
pub fn check_envelope_relevancy<T: BeaconChainTypes>(
|
||||||
|
block: &SignedBeaconBlock<T::EthSpec>,
|
||||||
|
signed_envelope: &SignedExecutionPayloadEnvelope<T::EthSpec>,
|
||||||
|
chain: &BeaconChain<T>,
|
||||||
|
) -> Result<bool, EnvelopeError> {
|
||||||
|
let envelope = &signed_envelope.message;
|
||||||
|
let Ok(bid) = block.message().body().signed_execution_payload_bid() else {
|
||||||
|
return Err(EnvelopeError::InternalError(
|
||||||
|
"Block is pre-gloas".to_string(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
let latest_finalized_slot = chain
|
||||||
|
.canonical_head
|
||||||
|
.cached_head()
|
||||||
|
.finalized_checkpoint()
|
||||||
|
.epoch
|
||||||
|
.start_slot(T::EthSpec::slots_per_epoch());
|
||||||
|
|
||||||
|
verify_envelope_consistency(envelope, block, &bid.message, latest_finalized_slot)?;
|
||||||
|
|
||||||
|
if chain
|
||||||
|
.canonical_head
|
||||||
|
.fork_choice_read_lock()
|
||||||
|
.is_payload_received(&envelope.beacon_block_root)
|
||||||
|
{
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
|||||||
@@ -3715,7 +3715,6 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
|
|||||||
| EnvelopeError::BeaconStateError(_)
|
| EnvelopeError::BeaconStateError(_)
|
||||||
// The following variants are produced during envelope import, not gossip
|
// The following variants are produced during envelope import, not gossip
|
||||||
// verification, so they cannot be reached here. Ignore them to be safe.
|
// verification, so they cannot be reached here. Ignore them to be safe.
|
||||||
| EnvelopeError::OptimisticSyncNotSupported { .. }
|
|
||||||
| EnvelopeError::BlockRootNotInForkChoice(_)
|
| EnvelopeError::BlockRootNotInForkChoice(_)
|
||||||
| EnvelopeError::InternalError(_) => {
|
| EnvelopeError::InternalError(_) => {
|
||||||
self.propagate_validation_result(
|
self.propagate_validation_result(
|
||||||
|
|||||||
Reference in New Issue
Block a user