Skip to content

Commit ee54bab

Browse files
committed
Merge remote-tracking branch 'network/unstable' into ux-network-fixes
2 parents 1faf0e7 + b1a19a8 commit ee54bab

File tree

76 files changed

+1256
-1073
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+1256
-1073
lines changed

beacon_node/beacon_chain/src/beacon_chain.rs

Lines changed: 104 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ use store::{
121121
KeyValueStoreOp, StoreItem, StoreOp,
122122
};
123123
use task_executor::{ShutdownReason, TaskExecutor};
124-
use tokio::sync::mpsc::Receiver;
124+
use tokio::sync::oneshot;
125125
use tokio_stream::Stream;
126126
use tree_hash::TreeHash;
127127
use types::blob_sidecar::FixedBlobSidecarList;
@@ -3088,7 +3088,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
30883088
slot: Slot,
30893089
block_root: Hash256,
30903090
blobs: FixedBlobSidecarList<T::EthSpec>,
3091-
data_column_recv: Option<Receiver<DataColumnSidecarList<T::EthSpec>>>,
3091+
data_column_recv: Option<oneshot::Receiver<DataColumnSidecarList<T::EthSpec>>>,
30923092
) -> Result<AvailabilityProcessingStatus, BlockError> {
30933093
// If this block has already been imported to forkchoice it must have been available, so
30943094
// we don't need to process its blobs again.
@@ -3216,7 +3216,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
32163216
};
32173217

32183218
let r = self
3219-
.process_availability(slot, availability, None, || Ok(()))
3219+
.process_availability(slot, availability, || Ok(()))
32203220
.await;
32213221
self.remove_notified(&block_root, r)
32223222
.map(|availability_processing_status| {
@@ -3344,7 +3344,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
33443344

33453345
match executed_block {
33463346
ExecutedBlock::Available(block) => {
3347-
self.import_available_block(Box::new(block), None).await
3347+
self.import_available_block(Box::new(block)).await
33483348
}
33493349
ExecutedBlock::AvailabilityPending(block) => {
33503350
self.check_block_availability_and_import(block).await
@@ -3476,7 +3476,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
34763476
let availability = self
34773477
.data_availability_checker
34783478
.put_pending_executed_block(block)?;
3479-
self.process_availability(slot, availability, None, || Ok(()))
3479+
self.process_availability(slot, availability, || Ok(()))
34803480
.await
34813481
}
34823482

@@ -3492,7 +3492,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
34923492
}
34933493
let availability = self.data_availability_checker.put_gossip_blob(blob)?;
34943494

3495-
self.process_availability(slot, availability, None, || Ok(()))
3495+
self.process_availability(slot, availability, || Ok(()))
34963496
.await
34973497
}
34983498

@@ -3515,7 +3515,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
35153515
.data_availability_checker
35163516
.put_gossip_data_columns(block_root, data_columns)?;
35173517

3518-
self.process_availability(slot, availability, None, publish_fn)
3518+
self.process_availability(slot, availability, publish_fn)
35193519
.await
35203520
}
35213521

@@ -3559,7 +3559,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
35593559
.data_availability_checker
35603560
.put_rpc_blobs(block_root, blobs)?;
35613561

3562-
self.process_availability(slot, availability, None, || Ok(()))
3562+
self.process_availability(slot, availability, || Ok(()))
35633563
.await
35643564
}
35653565

@@ -3568,14 +3568,14 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
35683568
slot: Slot,
35693569
block_root: Hash256,
35703570
blobs: FixedBlobSidecarList<T::EthSpec>,
3571-
data_column_recv: Option<Receiver<DataColumnSidecarList<T::EthSpec>>>,
3571+
data_column_recv: Option<oneshot::Receiver<DataColumnSidecarList<T::EthSpec>>>,
35723572
) -> Result<AvailabilityProcessingStatus, BlockError> {
35733573
self.check_blobs_for_slashability(block_root, &blobs)?;
3574-
let availability = self
3575-
.data_availability_checker
3576-
.put_engine_blobs(block_root, blobs)?;
3574+
let availability =
3575+
self.data_availability_checker
3576+
.put_engine_blobs(block_root, blobs, data_column_recv)?;
35773577

3578-
self.process_availability(slot, availability, data_column_recv, || Ok(()))
3578+
self.process_availability(slot, availability, || Ok(()))
35793579
.await
35803580
}
35813581

@@ -3615,7 +3615,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
36153615
.data_availability_checker
36163616
.put_rpc_custody_columns(block_root, custody_columns)?;
36173617

3618-
self.process_availability(slot, availability, None, || Ok(()))
3618+
self.process_availability(slot, availability, || Ok(()))
36193619
.await
36203620
}
36213621

@@ -3627,14 +3627,13 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
36273627
self: &Arc<Self>,
36283628
slot: Slot,
36293629
availability: Availability<T::EthSpec>,
3630-
recv: Option<Receiver<DataColumnSidecarList<T::EthSpec>>>,
36313630
publish_fn: impl FnOnce() -> Result<(), BlockError>,
36323631
) -> Result<AvailabilityProcessingStatus, BlockError> {
36333632
match availability {
36343633
Availability::Available(block) => {
36353634
publish_fn()?;
36363635
// Block is fully available, import into fork choice
3637-
self.import_available_block(block, recv).await
3636+
self.import_available_block(block).await
36383637
}
36393638
Availability::MissingComponents(block_root) => Ok(
36403639
AvailabilityProcessingStatus::MissingComponents(slot, block_root),
@@ -3645,7 +3644,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
36453644
pub async fn import_available_block(
36463645
self: &Arc<Self>,
36473646
block: Box<AvailableExecutedBlock<T::EthSpec>>,
3648-
data_column_recv: Option<Receiver<DataColumnSidecarList<T::EthSpec>>>,
36493647
) -> Result<AvailabilityProcessingStatus, BlockError> {
36503648
let AvailableExecutedBlock {
36513649
block,
@@ -3660,6 +3658,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
36603658
parent_eth1_finalization_data,
36613659
confirmed_state_roots,
36623660
consensus_context,
3661+
data_column_recv,
36633662
} = import_data;
36643663

36653664
// Record the time at which this block's blobs became available.
@@ -3726,7 +3725,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
37263725
parent_block: SignedBlindedBeaconBlock<T::EthSpec>,
37273726
parent_eth1_finalization_data: Eth1FinalizationData,
37283727
mut consensus_context: ConsensusContext<T::EthSpec>,
3729-
data_column_recv: Option<Receiver<DataColumnSidecarList<T::EthSpec>>>,
3728+
data_column_recv: Option<oneshot::Receiver<DataColumnSidecarList<T::EthSpec>>>,
37303729
) -> Result<Hash256, BlockError> {
37313730
// ----------------------------- BLOCK NOT YET ATTESTABLE ----------------------------------
37323731
// Everything in this initial section is on the hot path between processing the block and
@@ -3894,44 +3893,32 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
38943893
// end up with blocks in fork choice that are missing from disk.
38953894
// See https://github.com/sigp/lighthouse/issues/2028
38963895
let (_, signed_block, blobs, data_columns) = signed_block.deconstruct();
3897-
// TODO(das) we currently store all subnet sampled columns. Tracking issue to exclude non
3898-
// custody columns: https://github.com/sigp/lighthouse/issues/6465
3899-
let custody_columns_count = self.data_availability_checker.get_sampling_column_count();
3900-
// if block is made available via blobs, dropped the data columns.
3901-
let data_columns = data_columns.filter(|columns| columns.len() == custody_columns_count);
3902-
3903-
let data_columns = match (data_columns, data_column_recv) {
3904-
// If the block was made available via custody columns received from gossip / rpc, use them
3905-
// since we already have them.
3906-
(Some(columns), _) => Some(columns),
3907-
// Otherwise, it means blobs were likely available via fetching from EL, in this case we
3908-
// wait for the data columns to be computed (blocking).
3909-
(None, Some(mut data_column_recv)) => {
3910-
let _column_recv_timer =
3911-
metrics::start_timer(&metrics::BLOCK_PROCESSING_DATA_COLUMNS_WAIT);
3912-
// Unable to receive data columns from sender, sender is either dropped or
3913-
// failed to compute data columns from blobs. We restore fork choice here and
3914-
// return to avoid inconsistency in database.
3915-
if let Some(columns) = data_column_recv.blocking_recv() {
3916-
Some(columns)
3917-
} else {
3918-
let err_msg = "Did not receive data columns from sender";
3919-
error!(
3920-
self.log,
3921-
"Failed to store data columns into the database";
3922-
"msg" => "Restoring fork choice from disk",
3923-
"error" => err_msg,
3924-
);
3925-
return Err(self
3926-
.handle_import_block_db_write_error(fork_choice)
3927-
.err()
3928-
.unwrap_or(BlockError::InternalError(err_msg.to_string())));
3929-
}
3896+
3897+
match self.get_blobs_or_columns_store_op(
3898+
block_root,
3899+
signed_block.epoch(),
3900+
blobs,
3901+
data_columns,
3902+
data_column_recv,
3903+
) {
3904+
Ok(Some(blobs_or_columns_store_op)) => {
3905+
ops.push(blobs_or_columns_store_op);
39303906
}
3931-
// No data columns present and compute data columns task was not spawned.
3932-
// Could either be no blobs in the block or before PeerDAS activation.
3933-
(None, None) => None,
3934-
};
3907+
Ok(None) => {}
3908+
Err(e) => {
3909+
error!(
3910+
self.log,
3911+
"Failed to store data columns into the database";
3912+
"msg" => "Restoring fork choice from disk",
3913+
"error" => &e,
3914+
"block_root" => ?block_root
3915+
);
3916+
return Err(self
3917+
.handle_import_block_db_write_error(fork_choice)
3918+
.err()
3919+
.unwrap_or(BlockError::InternalError(e)));
3920+
}
3921+
}
39353922

39363923
let block = signed_block.message();
39373924
let db_write_timer = metrics::start_timer(&metrics::BLOCK_PROCESSING_DB_WRITE);
@@ -3943,30 +3930,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
39433930
ops.push(StoreOp::PutBlock(block_root, signed_block.clone()));
39443931
ops.push(StoreOp::PutState(block.state_root(), &state));
39453932

3946-
if let Some(blobs) = blobs {
3947-
if !blobs.is_empty() {
3948-
debug!(
3949-
self.log, "Writing blobs to store";
3950-
"block_root" => %block_root,
3951-
"count" => blobs.len(),
3952-
);
3953-
ops.push(StoreOp::PutBlobs(block_root, blobs));
3954-
}
3955-
}
3956-
3957-
if let Some(data_columns) = data_columns {
3958-
// TODO(das): `available_block includes all sampled columns, but we only need to store
3959-
// custody columns. To be clarified in spec.
3960-
if !data_columns.is_empty() {
3961-
debug!(
3962-
self.log, "Writing data_columns to store";
3963-
"block_root" => %block_root,
3964-
"count" => data_columns.len(),
3965-
);
3966-
ops.push(StoreOp::PutDataColumns(block_root, data_columns));
3967-
}
3968-
}
3969-
39703933
let txn_lock = self.store.hot_db.begin_rw_transaction();
39713934

39723935
if let Err(e) = self.store.do_atomically_with_block_and_blobs_cache(ops) {
@@ -7184,6 +7147,68 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
71847147
reqresp_pre_import_cache_len: self.reqresp_pre_import_cache.read().len(),
71857148
}
71867149
}
7150+
7151+
fn get_blobs_or_columns_store_op(
7152+
&self,
7153+
block_root: Hash256,
7154+
block_epoch: Epoch,
7155+
blobs: Option<BlobSidecarList<T::EthSpec>>,
7156+
data_columns: Option<DataColumnSidecarList<T::EthSpec>>,
7157+
data_column_recv: Option<oneshot::Receiver<DataColumnSidecarList<T::EthSpec>>>,
7158+
) -> Result<Option<StoreOp<T::EthSpec>>, String> {
7159+
if self.spec.is_peer_das_enabled_for_epoch(block_epoch) {
7160+
// TODO(das) we currently store all subnet sampled columns. Tracking issue to exclude non
7161+
// custody columns: https://github.com/sigp/lighthouse/issues/6465
7162+
let custody_columns_count = self.data_availability_checker.get_sampling_column_count();
7163+
7164+
let custody_columns_available = data_columns
7165+
.as_ref()
7166+
.as_ref()
7167+
.is_some_and(|columns| columns.len() == custody_columns_count);
7168+
7169+
let data_columns_to_persist = if custody_columns_available {
7170+
// If the block was made available via custody columns received from gossip / rpc, use them
7171+
// since we already have them.
7172+
data_columns
7173+
} else if let Some(data_column_recv) = data_column_recv {
7174+
// Blobs were available from the EL, in this case we wait for the data columns to be computed (blocking).
7175+
let _column_recv_timer =
7176+
metrics::start_timer(&metrics::BLOCK_PROCESSING_DATA_COLUMNS_WAIT);
7177+
// Unable to receive data columns from sender, sender is either dropped or
7178+
// failed to compute data columns from blobs. We restore fork choice here and
7179+
// return to avoid inconsistency in database.
7180+
let computed_data_columns = data_column_recv
7181+
.blocking_recv()
7182+
.map_err(|e| format!("Did not receive data columns from sender: {e:?}"))?;
7183+
Some(computed_data_columns)
7184+
} else {
7185+
// No blobs in the block.
7186+
None
7187+
};
7188+
7189+
if let Some(data_columns) = data_columns_to_persist {
7190+
if !data_columns.is_empty() {
7191+
debug!(
7192+
self.log, "Writing data_columns to store";
7193+
"block_root" => %block_root,
7194+
"count" => data_columns.len(),
7195+
);
7196+
return Ok(Some(StoreOp::PutDataColumns(block_root, data_columns)));
7197+
}
7198+
}
7199+
} else if let Some(blobs) = blobs {
7200+
if !blobs.is_empty() {
7201+
debug!(
7202+
self.log, "Writing blobs to store";
7203+
"block_root" => %block_root,
7204+
"count" => blobs.len(),
7205+
);
7206+
return Ok(Some(StoreOp::PutBlobs(block_root, blobs)));
7207+
}
7208+
}
7209+
7210+
Ok(None)
7211+
}
71877212
}
71887213

71897214
impl<T: BeaconChainTypes> Drop for BeaconChain<T> {

beacon_node/beacon_chain/src/block_verification.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1677,6 +1677,7 @@ impl<T: BeaconChainTypes> ExecutionPendingBlock<T> {
16771677
parent_eth1_finalization_data,
16781678
confirmed_state_roots,
16791679
consensus_context,
1680+
data_column_recv: None,
16801681
},
16811682
payload_verification_handle,
16821683
})

beacon_node/beacon_chain/src/block_verification_types.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ use derivative::Derivative;
77
use state_processing::ConsensusContext;
88
use std::fmt::{Debug, Formatter};
99
use std::sync::Arc;
10+
use tokio::sync::oneshot;
1011
use types::blob_sidecar::BlobIdentifier;
1112
use types::{
12-
BeaconBlockRef, BeaconState, BlindedPayload, BlobSidecarList, ChainSpec, Epoch, EthSpec,
13-
Hash256, RuntimeVariableList, SignedBeaconBlock, SignedBeaconBlockHeader, Slot,
13+
BeaconBlockRef, BeaconState, BlindedPayload, BlobSidecarList, ChainSpec, DataColumnSidecarList,
14+
Epoch, EthSpec, Hash256, RuntimeVariableList, SignedBeaconBlock, SignedBeaconBlockHeader, Slot,
1415
};
1516

1617
/// A block that has been received over RPC. It has 2 internal variants:
@@ -164,7 +165,7 @@ impl<E: EthSpec> RpcBlock<E> {
164165
let inner = if !custody_columns.is_empty() {
165166
RpcBlockInner::BlockAndCustodyColumns(
166167
block,
167-
RuntimeVariableList::new(custody_columns, spec.number_of_columns)?,
168+
RuntimeVariableList::new(custody_columns, spec.number_of_columns as usize)?,
168169
)
169170
} else {
170171
RpcBlockInner::Block(block)
@@ -337,14 +338,21 @@ impl<E: EthSpec> AvailabilityPendingExecutedBlock<E> {
337338
}
338339
}
339340

340-
#[derive(Debug, PartialEq)]
341+
#[derive(Debug, Derivative)]
342+
#[derivative(PartialEq)]
341343
pub struct BlockImportData<E: EthSpec> {
342344
pub block_root: Hash256,
343345
pub state: BeaconState<E>,
344346
pub parent_block: SignedBeaconBlock<E, BlindedPayload<E>>,
345347
pub parent_eth1_finalization_data: Eth1FinalizationData,
346348
pub confirmed_state_roots: Vec<Hash256>,
347349
pub consensus_context: ConsensusContext<E>,
350+
#[derivative(PartialEq = "ignore")]
351+
/// An optional receiver for `DataColumnSidecarList`.
352+
///
353+
/// This field is `Some` when data columns are being computed asynchronously.
354+
/// The resulting `DataColumnSidecarList` will be sent through this receiver.
355+
pub data_column_recv: Option<oneshot::Receiver<DataColumnSidecarList<E>>>,
348356
}
349357

350358
impl<E: EthSpec> BlockImportData<E> {
@@ -363,6 +371,7 @@ impl<E: EthSpec> BlockImportData<E> {
363371
},
364372
confirmed_state_roots: vec![],
365373
consensus_context: ConsensusContext::new(Slot::new(0)),
374+
data_column_recv: None,
366375
}
367376
}
368377
}

0 commit comments

Comments
 (0)