mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-19 12:56:12 +00:00
Add data column timestamp tracking
- Add seen_timestamp field to KzgVerifiedDataColumn and KzgVerifiedCustodyDataColumn - Update all creation points to capture and pass timestamps - Add all_data_columns_observed field to Timestamps and BlockDelays - Add set_time_data_column_observed method to BlockTimesCache - Update beacon_chain.rs to record data column timestamps - Update overflow_lru_cache to compute data column timestamps - Replace blob_delay_ms with data_column_delay_ms in logs and metrics Co-authored-by: michaelsproul <4452260+michaelsproul@users.noreply.github.com>
This commit is contained in:
@@ -16,6 +16,7 @@ use ssz_types::VariableList;
|
||||
use std::iter;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tracing::{debug, instrument};
|
||||
use types::data::ColumnIndex;
|
||||
use types::{
|
||||
@@ -254,6 +255,8 @@ impl<T: BeaconChainTypes, O: ObservationStrategy> GossipVerifiedDataColumn<T, O>
|
||||
) -> Result<Self, GossipDataColumnError> {
|
||||
verify_data_column_sidecar(&column_sidecar, &chain.spec)?;
|
||||
|
||||
let seen_timestamp = chain.slot_clock.now_duration().unwrap_or_default();
|
||||
|
||||
// Check if the data column is already in the DA checker cache. This happens when data columns
|
||||
// are made available through the `engine_getBlobs` method. If it exists in the cache, we know
|
||||
// it has already passed the gossip checks, even though this particular instance hasn't been
|
||||
@@ -274,7 +277,10 @@ impl<T: BeaconChainTypes, O: ObservationStrategy> GossipVerifiedDataColumn<T, O>
|
||||
|
||||
Ok(Self {
|
||||
block_root: column_sidecar.block_root(),
|
||||
data_column: KzgVerifiedDataColumn::from_execution_verified(column_sidecar),
|
||||
data_column: KzgVerifiedDataColumn::from_execution_verified(
|
||||
column_sidecar,
|
||||
seen_timestamp,
|
||||
),
|
||||
_phantom: Default::default(),
|
||||
})
|
||||
}
|
||||
@@ -320,35 +326,51 @@ impl<T: BeaconChainTypes, O: ObservationStrategy> GossipVerifiedDataColumn<T, O>
|
||||
#[ssz(struct_behaviour = "transparent")]
|
||||
pub struct KzgVerifiedDataColumn<E: EthSpec> {
|
||||
data: Arc<DataColumnSidecar<E>>,
|
||||
#[ssz(skip_serializing, skip_deserializing)]
|
||||
seen_timestamp: Duration,
|
||||
}
|
||||
|
||||
impl<E: EthSpec> KzgVerifiedDataColumn<E> {
|
||||
pub fn new(
|
||||
data_column: Arc<DataColumnSidecar<E>>,
|
||||
kzg: &Kzg,
|
||||
seen_timestamp: Duration,
|
||||
) -> Result<Self, (Option<ColumnIndex>, KzgError)> {
|
||||
verify_kzg_for_data_column(data_column, kzg)
|
||||
verify_kzg_for_data_column(data_column, kzg, seen_timestamp)
|
||||
}
|
||||
|
||||
/// Mark a data column as KZG verified. Caller must ONLY use this on columns constructed
|
||||
/// from EL blobs.
|
||||
pub fn from_execution_verified(data_column: Arc<DataColumnSidecar<E>>) -> Self {
|
||||
Self { data: data_column }
|
||||
pub fn from_execution_verified(
|
||||
data_column: Arc<DataColumnSidecar<E>>,
|
||||
seen_timestamp: Duration,
|
||||
) -> Self {
|
||||
Self {
|
||||
data: data_column,
|
||||
seen_timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a `KzgVerifiedDataColumn` from `DataColumnSidecar` for testing ONLY.
|
||||
pub(crate) fn __new_for_testing(data_column: Arc<DataColumnSidecar<E>>) -> Self {
|
||||
Self { data: data_column }
|
||||
Self {
|
||||
data: data_column,
|
||||
seen_timestamp: Duration::from_secs(0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_batch_with_scoring(
|
||||
data_columns: Vec<Arc<DataColumnSidecar<E>>>,
|
||||
kzg: &Kzg,
|
||||
seen_timestamp: Duration,
|
||||
) -> Result<Vec<Self>, (Option<ColumnIndex>, KzgError)> {
|
||||
verify_kzg_for_data_column_list(data_columns.iter(), kzg)?;
|
||||
Ok(data_columns
|
||||
.into_iter()
|
||||
.map(|column| Self { data: column })
|
||||
.map(|column| Self {
|
||||
data: column,
|
||||
seen_timestamp,
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
|
||||
@@ -366,6 +388,10 @@ impl<E: EthSpec> KzgVerifiedDataColumn<E> {
|
||||
pub fn index(&self) -> ColumnIndex {
|
||||
*self.data.index()
|
||||
}
|
||||
|
||||
pub fn seen_timestamp(&self) -> Duration {
|
||||
self.seen_timestamp
|
||||
}
|
||||
}
|
||||
|
||||
pub type CustodyDataColumnList<E> =
|
||||
@@ -407,14 +433,18 @@ impl<E: EthSpec> CustodyDataColumn<E> {
|
||||
#[ssz(struct_behaviour = "transparent")]
|
||||
pub struct KzgVerifiedCustodyDataColumn<E: EthSpec> {
|
||||
data: Arc<DataColumnSidecar<E>>,
|
||||
#[ssz(skip_serializing, skip_deserializing)]
|
||||
seen_timestamp: Duration,
|
||||
}
|
||||
|
||||
impl<E: EthSpec> KzgVerifiedCustodyDataColumn<E> {
|
||||
/// Mark a column as custody column. Caller must ensure that our current custody requirements
|
||||
/// include this column
|
||||
pub fn from_asserted_custody(kzg_verified: KzgVerifiedDataColumn<E>) -> Self {
|
||||
let seen_timestamp = kzg_verified.seen_timestamp();
|
||||
Self {
|
||||
data: kzg_verified.to_data_column(),
|
||||
seen_timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,10 +452,12 @@ impl<E: EthSpec> KzgVerifiedCustodyDataColumn<E> {
|
||||
pub fn new(
|
||||
data_column: CustodyDataColumn<E>,
|
||||
kzg: &Kzg,
|
||||
seen_timestamp: Duration,
|
||||
) -> Result<Self, (Option<ColumnIndex>, KzgError)> {
|
||||
verify_kzg_for_data_column(data_column.clone_arc(), kzg)?;
|
||||
verify_kzg_for_data_column(data_column.clone_arc(), kzg, seen_timestamp)?;
|
||||
Ok(Self {
|
||||
data: data_column.data,
|
||||
seen_timestamp,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -443,10 +475,18 @@ impl<E: EthSpec> KzgVerifiedCustodyDataColumn<E> {
|
||||
spec,
|
||||
)?;
|
||||
|
||||
// Use the maximum timestamp from the partial set for reconstructed columns
|
||||
let seen_timestamp = partial_set_of_columns
|
||||
.iter()
|
||||
.map(|col| col.seen_timestamp)
|
||||
.max()
|
||||
.unwrap_or_default();
|
||||
|
||||
Ok(all_data_columns
|
||||
.into_iter()
|
||||
.map(|data| {
|
||||
KzgVerifiedCustodyDataColumn::from_asserted_custody(KzgVerifiedDataColumn { data })
|
||||
.map(|data| KzgVerifiedCustodyDataColumn {
|
||||
data,
|
||||
seen_timestamp,
|
||||
})
|
||||
.collect::<Vec<_>>())
|
||||
}
|
||||
@@ -464,6 +504,10 @@ impl<E: EthSpec> KzgVerifiedCustodyDataColumn<E> {
|
||||
pub fn index(&self) -> ColumnIndex {
|
||||
*self.data.index()
|
||||
}
|
||||
|
||||
pub fn seen_timestamp(&self) -> Duration {
|
||||
self.seen_timestamp
|
||||
}
|
||||
}
|
||||
|
||||
/// Complete kzg verification for a `DataColumnSidecar`.
|
||||
@@ -473,10 +517,14 @@ impl<E: EthSpec> KzgVerifiedCustodyDataColumn<E> {
|
||||
pub fn verify_kzg_for_data_column<E: EthSpec>(
|
||||
data_column: Arc<DataColumnSidecar<E>>,
|
||||
kzg: &Kzg,
|
||||
seen_timestamp: Duration,
|
||||
) -> Result<KzgVerifiedDataColumn<E>, (Option<ColumnIndex>, KzgError)> {
|
||||
let _timer = metrics::start_timer(&metrics::KZG_VERIFICATION_DATA_COLUMN_SINGLE_TIMES);
|
||||
validate_data_columns(kzg, iter::once(&data_column))?;
|
||||
Ok(KzgVerifiedDataColumn { data: data_column })
|
||||
Ok(KzgVerifiedDataColumn {
|
||||
data: data_column,
|
||||
seen_timestamp,
|
||||
})
|
||||
}
|
||||
|
||||
/// Complete kzg verification for a list of `DataColumnSidecar`s.
|
||||
@@ -518,6 +566,8 @@ pub fn validate_data_column_sidecar_for_gossip_fulu<T: BeaconChainTypes, O: Obse
|
||||
verify_slot_greater_than_latest_finalized_slot(chain, column_slot)?;
|
||||
verify_is_unknown_sidecar(chain, &data_column)?;
|
||||
|
||||
let seen_timestamp = chain.slot_clock.now_duration().unwrap_or_default();
|
||||
|
||||
// Check if the data column is already in the DA checker cache. This happens when data columns
|
||||
// are made available through the `engine_getBlobs` method. If it exists in the cache, we know
|
||||
// it has already passed the gossip checks, even though this particular instance hasn't been
|
||||
@@ -539,8 +589,9 @@ pub fn validate_data_column_sidecar_for_gossip_fulu<T: BeaconChainTypes, O: Obse
|
||||
verify_slot_higher_than_parent(&parent_block, column_slot)?;
|
||||
verify_proposer_and_signature(data_column_fulu, &parent_block, chain)?;
|
||||
let kzg = &chain.kzg;
|
||||
let kzg_verified_data_column = verify_kzg_for_data_column(data_column.clone(), kzg)
|
||||
.map_err(|(_, e)| GossipDataColumnError::InvalidKzgProof(e))?;
|
||||
let kzg_verified_data_column =
|
||||
verify_kzg_for_data_column(data_column.clone(), kzg, seen_timestamp)
|
||||
.map_err(|(_, e)| GossipDataColumnError::InvalidKzgProof(e))?;
|
||||
|
||||
chain
|
||||
.observed_slashable
|
||||
|
||||
Reference in New Issue
Block a user