mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-15 02:42:38 +00:00
Merge branch 'eip4844' into deneb-free-blobs
This commit is contained in:
@@ -39,6 +39,7 @@ use lighthouse_version::version_with_platform;
|
||||
use network::{NetworkMessage, NetworkSenders, ValidatorSubscriptionMessage};
|
||||
use operation_pool::ReceivedPreCapella;
|
||||
use parking_lot::RwLock;
|
||||
use publish_blocks::ProvenancedBlock;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use slog::{crit, debug, error, info, warn, Logger};
|
||||
use slot_clock::SlotClock;
|
||||
@@ -1125,9 +1126,15 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
chain: Arc<BeaconChain<T>>,
|
||||
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>,
|
||||
log: Logger| async move {
|
||||
publish_blocks::publish_block(None, block_contents, chain, &network_tx, log)
|
||||
.await
|
||||
.map(|()| warp::reply().into_response())
|
||||
publish_blocks::publish_block(
|
||||
None,
|
||||
ProvenancedBlock::Local(block_contents),
|
||||
chain,
|
||||
&network_tx,
|
||||
log,
|
||||
)
|
||||
.await
|
||||
.map(|()| warp::reply().into_response())
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -29,9 +29,10 @@ lazy_static::lazy_static! {
|
||||
"http_api_beacon_proposer_cache_misses_total",
|
||||
"Count of times the proposer cache has been missed",
|
||||
);
|
||||
pub static ref HTTP_API_BLOCK_BROADCAST_DELAY_TIMES: Result<Histogram> = try_create_histogram(
|
||||
pub static ref HTTP_API_BLOCK_BROADCAST_DELAY_TIMES: Result<HistogramVec> = try_create_histogram_vec(
|
||||
"http_api_block_broadcast_delay_times",
|
||||
"Time between start of the slot and when the block was broadcast"
|
||||
"Time between start of the slot and when the block was broadcast",
|
||||
&["provenance"]
|
||||
);
|
||||
pub static ref HTTP_API_BLOCK_PUBLISHED_LATE_TOTAL: Result<IntCounter> = try_create_int_counter(
|
||||
"http_api_block_published_late_total",
|
||||
|
||||
@@ -1,33 +1,53 @@
|
||||
use crate::metrics;
|
||||
use beacon_chain::blob_verification::{AsBlock, BlockWrapper, IntoAvailableBlock};
|
||||
use beacon_chain::validator_monitor::{get_block_delay_ms, timestamp_now};
|
||||
use beacon_chain::NotifyExecutionLayer;
|
||||
use beacon_chain::{BeaconChain, BeaconChainTypes, BlockError, CountUnrealized};
|
||||
use beacon_chain::{
|
||||
BeaconChain, BeaconChainTypes, BlockError, CountUnrealized, NotifyExecutionLayer,
|
||||
};
|
||||
use eth2::types::SignedBlockContents;
|
||||
use execution_layer::ProvenancedPayload;
|
||||
use lighthouse_network::PubsubMessage;
|
||||
use network::NetworkMessage;
|
||||
use slog::{debug, error, info, warn, Logger};
|
||||
use slot_clock::SlotClock;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tokio::sync::mpsc::UnboundedSender;
|
||||
use tree_hash::TreeHash;
|
||||
use types::{
|
||||
AbstractExecPayload, BlindedPayload, EthSpec, ExecPayload, ExecutionBlockHash, FullPayload,
|
||||
Hash256, SignedBeaconBlock,
|
||||
AbstractExecPayload, BeaconBlockRef, BlindedPayload, EthSpec, ExecPayload, ExecutionBlockHash,
|
||||
FullPayload, Hash256, SignedBeaconBlock,
|
||||
};
|
||||
use warp::Rejection;
|
||||
|
||||
pub enum ProvenancedBlock<T: EthSpec> {
|
||||
/// The payload was built using a local EE.
|
||||
Local(SignedBlockContents<T, FullPayload<T>>),
|
||||
/// The payload was build using a remote builder (e.g., via a mev-boost
|
||||
/// compatible relay).
|
||||
Builder(SignedBlockContents<T, FullPayload<T>>),
|
||||
}
|
||||
|
||||
/// Handles a request from the HTTP API for full blocks.
|
||||
pub async fn publish_block<T: BeaconChainTypes>(
|
||||
block_root: Option<Hash256>,
|
||||
block_contents: SignedBlockContents<T::EthSpec>,
|
||||
provenanced_block: ProvenancedBlock<T::EthSpec>,
|
||||
chain: Arc<BeaconChain<T>>,
|
||||
network_tx: &UnboundedSender<NetworkMessage<T::EthSpec>>,
|
||||
log: Logger,
|
||||
) -> Result<(), Rejection> {
|
||||
let seen_timestamp = timestamp_now();
|
||||
let (block, maybe_blobs) = block_contents.deconstruct();
|
||||
let block = Arc::new(block);
|
||||
let (block, maybe_blobs, is_locally_built_block) = match provenanced_block {
|
||||
ProvenancedBlock::Local(block_contents) => {
|
||||
let (block, maybe_blobs) = block_contents.deconstruct();
|
||||
(Arc::new(block), maybe_blobs, true)
|
||||
}
|
||||
ProvenancedBlock::Builder(block_contents) => {
|
||||
let (block, maybe_blobs) = block_contents.deconstruct();
|
||||
(Arc::new(block), maybe_blobs, false)
|
||||
}
|
||||
};
|
||||
let delay = get_block_delay_ms(seen_timestamp, block.message(), &chain.slot_clock);
|
||||
|
||||
//FIXME(sean) have to move this to prior to publishing because it's included in the blobs sidecar message.
|
||||
//this may skew metrics
|
||||
@@ -62,11 +82,6 @@ pub async fn publish_block<T: BeaconChainTypes>(
|
||||
}
|
||||
};
|
||||
|
||||
// Determine the delay after the start of the slot, register it with metrics.
|
||||
let block = wrapped_block.as_block();
|
||||
let delay = get_block_delay_ms(seen_timestamp, block.message(), &chain.slot_clock);
|
||||
metrics::observe_duration(&metrics::HTTP_API_BLOCK_BROADCAST_DELAY_TIMES, delay);
|
||||
|
||||
let available_block = match wrapped_block.into_available_block(block_root, &chain) {
|
||||
Ok(available_block) => available_block,
|
||||
Err(e) => {
|
||||
@@ -111,30 +126,17 @@ pub async fn publish_block<T: BeaconChainTypes>(
|
||||
// head.
|
||||
chain.recompute_head_at_current_slot().await;
|
||||
|
||||
// Perform some logging to inform users if their blocks are being produced
|
||||
// late.
|
||||
//
|
||||
// Check to see the thresholds are non-zero to avoid logging errors with small
|
||||
// slot times (e.g., during testing)
|
||||
let too_late_threshold = chain.slot_clock.unagg_attestation_production_delay();
|
||||
let delayed_threshold = too_late_threshold / 2;
|
||||
if delay >= too_late_threshold {
|
||||
error!(
|
||||
log,
|
||||
"Block was broadcast too late";
|
||||
"msg" => "system may be overloaded, block likely to be orphaned",
|
||||
"delay_ms" => delay.as_millis(),
|
||||
"slot" => available_block.slot(),
|
||||
"root" => ?root,
|
||||
)
|
||||
} else if delay >= delayed_threshold {
|
||||
error!(
|
||||
log,
|
||||
"Block broadcast was delayed";
|
||||
"msg" => "system may be overloaded, block may be orphaned",
|
||||
"delay_ms" => delay.as_millis(),
|
||||
"slot" => available_block.slot(),
|
||||
"root" => ?root,
|
||||
// Only perform late-block logging here if the block is local. For
|
||||
// blocks built with builders we consider the broadcast time to be
|
||||
// when the blinded block is published to the builder.
|
||||
if is_locally_built_block {
|
||||
late_block_logging(
|
||||
&chain,
|
||||
seen_timestamp,
|
||||
available_block.message(),
|
||||
root,
|
||||
"local",
|
||||
&log,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -183,14 +185,7 @@ pub async fn publish_blinded_block<T: BeaconChainTypes>(
|
||||
) -> Result<(), Rejection> {
|
||||
let block_root = block.canonical_root();
|
||||
let full_block = reconstruct_block(chain.clone(), block_root, block, log.clone()).await?;
|
||||
publish_block::<T>(
|
||||
Some(block_root),
|
||||
SignedBlockContents::Block(full_block),
|
||||
chain,
|
||||
network_tx,
|
||||
log,
|
||||
)
|
||||
.await
|
||||
publish_block::<T>(Some(block_root), full_block, chain, network_tx, log).await
|
||||
}
|
||||
|
||||
/// Deconstruct the given blinded block, and construct a full block. This attempts to use the
|
||||
@@ -201,15 +196,15 @@ async fn reconstruct_block<T: BeaconChainTypes>(
|
||||
block_root: Hash256,
|
||||
block: SignedBeaconBlock<T::EthSpec, BlindedPayload<T::EthSpec>>,
|
||||
log: Logger,
|
||||
) -> Result<SignedBeaconBlock<T::EthSpec, FullPayload<T::EthSpec>>, Rejection> {
|
||||
let full_payload = if let Ok(payload_header) = block.message().body().execution_payload() {
|
||||
) -> Result<ProvenancedBlock<T::EthSpec>, Rejection> {
|
||||
let full_payload_opt = if let Ok(payload_header) = block.message().body().execution_payload() {
|
||||
let el = chain.execution_layer.as_ref().ok_or_else(|| {
|
||||
warp_utils::reject::custom_server_error("Missing execution layer".to_string())
|
||||
})?;
|
||||
|
||||
// If the execution block hash is zero, use an empty payload.
|
||||
let full_payload = if payload_header.block_hash() == ExecutionBlockHash::zero() {
|
||||
FullPayload::default_at_fork(
|
||||
let payload = FullPayload::default_at_fork(
|
||||
chain
|
||||
.spec
|
||||
.fork_name_at_epoch(block.slot().epoch(T::EthSpec::slots_per_epoch())),
|
||||
@@ -219,15 +214,30 @@ async fn reconstruct_block<T: BeaconChainTypes>(
|
||||
"Default payload construction error: {e:?}"
|
||||
))
|
||||
})?
|
||||
.into()
|
||||
// If we already have an execution payload with this transactions root cached, use it.
|
||||
.into();
|
||||
ProvenancedPayload::Local(payload)
|
||||
// If we already have an execution payload with this transactions root cached, use it.
|
||||
} else if let Some(cached_payload) =
|
||||
el.get_payload_by_root(&payload_header.tree_hash_root())
|
||||
{
|
||||
info!(log, "Reconstructing a full block using a local payload"; "block_hash" => ?cached_payload.block_hash());
|
||||
cached_payload
|
||||
// Otherwise, this means we are attempting a blind block proposal.
|
||||
ProvenancedPayload::Local(cached_payload)
|
||||
// Otherwise, this means we are attempting a blind block proposal.
|
||||
} else {
|
||||
// Perform the logging for late blocks when we publish to the
|
||||
// builder, rather than when we publish to the network. This helps
|
||||
// prevent false positive logs when the builder publishes to the P2P
|
||||
// network significantly earlier than when they return the block to
|
||||
// us.
|
||||
late_block_logging(
|
||||
&chain,
|
||||
timestamp_now(),
|
||||
block.message(),
|
||||
block_root,
|
||||
"builder",
|
||||
&log,
|
||||
);
|
||||
|
||||
let full_payload = el
|
||||
.propose_blinded_beacon_block(block_root, &block)
|
||||
.await
|
||||
@@ -238,7 +248,7 @@ async fn reconstruct_block<T: BeaconChainTypes>(
|
||||
))
|
||||
})?;
|
||||
info!(log, "Successfully published a block to the builder network"; "block_hash" => ?full_payload.block_hash());
|
||||
full_payload
|
||||
ProvenancedPayload::Builder(full_payload)
|
||||
};
|
||||
|
||||
Some(full_payload)
|
||||
@@ -246,7 +256,71 @@ async fn reconstruct_block<T: BeaconChainTypes>(
|
||||
None
|
||||
};
|
||||
|
||||
block.try_into_full_block(full_payload).ok_or_else(|| {
|
||||
match full_payload_opt {
|
||||
// A block without a payload is pre-merge and we consider it locally
|
||||
// built.
|
||||
None => block
|
||||
.try_into_full_block(None)
|
||||
.map(SignedBlockContents::Block)
|
||||
.map(ProvenancedBlock::Local),
|
||||
Some(ProvenancedPayload::Local(full_payload)) => block
|
||||
.try_into_full_block(Some(full_payload))
|
||||
.map(SignedBlockContents::Block)
|
||||
.map(ProvenancedBlock::Local),
|
||||
Some(ProvenancedPayload::Builder(full_payload)) => block
|
||||
.try_into_full_block(Some(full_payload))
|
||||
.map(SignedBlockContents::Block)
|
||||
.map(ProvenancedBlock::Builder),
|
||||
}
|
||||
.ok_or_else(|| {
|
||||
warp_utils::reject::custom_server_error("Unable to add payload to block".to_string())
|
||||
})
|
||||
}
|
||||
|
||||
/// If the `seen_timestamp` is some time after the start of the slot for
|
||||
/// `block`, create some logs to indicate that the block was published late.
|
||||
fn late_block_logging<T: BeaconChainTypes, P: AbstractExecPayload<T::EthSpec>>(
|
||||
chain: &BeaconChain<T>,
|
||||
seen_timestamp: Duration,
|
||||
block: BeaconBlockRef<T::EthSpec, P>,
|
||||
root: Hash256,
|
||||
provenance: &str,
|
||||
log: &Logger,
|
||||
) {
|
||||
let delay = get_block_delay_ms(seen_timestamp, block, &chain.slot_clock);
|
||||
|
||||
metrics::observe_timer_vec(
|
||||
&metrics::HTTP_API_BLOCK_BROADCAST_DELAY_TIMES,
|
||||
&[provenance],
|
||||
delay,
|
||||
);
|
||||
|
||||
// Perform some logging to inform users if their blocks are being produced
|
||||
// late.
|
||||
//
|
||||
// Check to see the thresholds are non-zero to avoid logging errors with small
|
||||
// slot times (e.g., during testing)
|
||||
let too_late_threshold = chain.slot_clock.unagg_attestation_production_delay();
|
||||
let delayed_threshold = too_late_threshold / 2;
|
||||
if delay >= too_late_threshold {
|
||||
error!(
|
||||
log,
|
||||
"Block was broadcast too late";
|
||||
"msg" => "system may be overloaded, block likely to be orphaned",
|
||||
"provenance" => provenance,
|
||||
"delay_ms" => delay.as_millis(),
|
||||
"slot" => block.slot(),
|
||||
"root" => ?root,
|
||||
)
|
||||
} else if delay >= delayed_threshold {
|
||||
error!(
|
||||
log,
|
||||
"Block broadcast was delayed";
|
||||
"msg" => "system may be overloaded, block may be orphaned",
|
||||
"provenance" => provenance,
|
||||
"delay_ms" => delay.as_millis(),
|
||||
"slot" => block.slot(),
|
||||
"root" => ?root,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user