Skip to content

Commit aa53a38

Browse files
authored
Merge of #6147
2 parents a2ab26c + a037711 commit aa53a38

File tree

26 files changed

+907
-31
lines changed

26 files changed

+907
-31
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

beacon_node/beacon_chain/src/beacon_chain.rs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use crate::chain_config::ChainConfig;
2323
use crate::data_availability_checker::{
2424
Availability, AvailabilityCheckError, AvailableBlock, DataAvailabilityChecker,
2525
};
26+
use crate::data_column_verification::{GossipDataColumnError, GossipVerifiedDataColumn};
2627
use crate::early_attester_cache::EarlyAttesterCache;
2728
use crate::errors::{BeaconChainError as Error, BlockProductionError};
2829
use crate::eth1_chain::{Eth1Chain, Eth1ChainBackend};
@@ -2118,6 +2119,19 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
21182119
})
21192120
}
21202121

2122+
pub fn verify_data_column_sidecar_for_gossip(
2123+
self: &Arc<Self>,
2124+
data_column_sidecar: Arc<DataColumnSidecar<T::EthSpec>>,
2125+
subnet_id: u64,
2126+
) -> Result<GossipVerifiedDataColumn<T>, GossipDataColumnError> {
2127+
metrics::inc_counter(&metrics::DATA_COLUMN_SIDECAR_PROCESSING_REQUESTS);
2128+
let _timer = metrics::start_timer(&metrics::DATA_COLUMN_SIDECAR_GOSSIP_VERIFICATION_TIMES);
2129+
GossipVerifiedDataColumn::new(data_column_sidecar, subnet_id, self).map(|v| {
2130+
metrics::inc_counter(&metrics::DATA_COLUMN_SIDECAR_PROCESSING_SUCCESSES);
2131+
v
2132+
})
2133+
}
2134+
21212135
pub fn verify_blob_sidecar_for_gossip(
21222136
self: &Arc<Self>,
21232137
blob_sidecar: Arc<BlobSidecar<T::EthSpec>>,
@@ -2964,6 +2978,39 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
29642978
self.remove_notified(&block_root, r)
29652979
}
29662980

2981+
/// Cache the data columns in the processing cache, process it, then evict it from the cache if it was
2982+
/// imported or errors.
2983+
pub async fn process_gossip_data_columns(
2984+
self: &Arc<Self>,
2985+
data_columns: Vec<GossipVerifiedDataColumn<T>>,
2986+
) -> Result<AvailabilityProcessingStatus, BlockError<T::EthSpec>> {
2987+
let Ok(block_root) = data_columns
2988+
.iter()
2989+
.map(|c| c.block_root())
2990+
.unique()
2991+
.exactly_one()
2992+
else {
2993+
return Err(BlockError::InternalError(
2994+
"Columns should be from the same block".to_string(),
2995+
));
2996+
};
2997+
2998+
// If this block has already been imported to forkchoice it must have been available, so
2999+
// we don't need to process its samples again.
3000+
if self
3001+
.canonical_head
3002+
.fork_choice_read_lock()
3003+
.contains_block(&block_root)
3004+
{
3005+
return Err(BlockError::BlockIsAlreadyKnown(block_root));
3006+
}
3007+
3008+
let r = self
3009+
.check_gossip_data_columns_availability_and_import(data_columns)
3010+
.await;
3011+
self.remove_notified_custody_columns(&block_root, r)
3012+
}
3013+
29673014
/// Cache the blobs in the processing cache, process it, then evict it from the cache if it was
29683015
/// imported or errors.
29693016
pub async fn process_rpc_blobs(
@@ -3013,6 +3060,21 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
30133060
r
30143061
}
30153062

3063+
/// Remove any block components from the *processing cache* if we no longer require them. If the
3064+
/// block was imported full or erred, we no longer require them.
3065+
fn remove_notified_custody_columns(
3066+
&self,
3067+
block_root: &Hash256,
3068+
r: Result<AvailabilityProcessingStatus, BlockError<T::EthSpec>>,
3069+
) -> Result<AvailabilityProcessingStatus, BlockError<T::EthSpec>> {
3070+
let has_missing_components =
3071+
matches!(r, Ok(AvailabilityProcessingStatus::MissingComponents(_, _)));
3072+
if !has_missing_components {
3073+
self.reqresp_pre_import_cache.write().remove(block_root);
3074+
}
3075+
r
3076+
}
3077+
30163078
/// Wraps `process_block` in logic to cache the block's commitments in the processing cache
30173079
/// and evict if the block was imported or errored.
30183080
pub async fn process_block_with_early_caching<B: IntoExecutionPendingBlock<T>>(
@@ -3257,6 +3319,31 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
32573319
self.process_availability(slot, availability).await
32583320
}
32593321

3322+
/// Checks if the provided data column can make any cached blocks available, and imports immediately
3323+
/// if so, otherwise caches the data column in the data availability checker.
3324+
async fn check_gossip_data_columns_availability_and_import(
3325+
self: &Arc<Self>,
3326+
data_columns: Vec<GossipVerifiedDataColumn<T>>,
3327+
) -> Result<AvailabilityProcessingStatus, BlockError<T::EthSpec>> {
3328+
if let Some(slasher) = self.slasher.as_ref() {
3329+
for data_colum in &data_columns {
3330+
slasher.accept_block_header(data_colum.signed_block_header());
3331+
}
3332+
}
3333+
3334+
let Ok(slot) = data_columns.iter().map(|c| c.slot()).unique().exactly_one() else {
3335+
return Err(BlockError::InternalError(
3336+
"Columns for the same block should have matching slot".to_string(),
3337+
));
3338+
};
3339+
3340+
let availability = self
3341+
.data_availability_checker
3342+
.put_gossip_data_columns(data_columns)?;
3343+
3344+
self.process_availability(slot, availability).await
3345+
}
3346+
32603347
/// Checks if the provided blobs can make any cached blocks available, and imports immediately
32613348
/// if so, otherwise caches the blob in the data availability checker.
32623349
async fn check_rpc_blob_availability_and_import(

beacon_node/beacon_chain/src/block_verification.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ use crate::block_verification_types::{
5454
AsBlock, BlockContentsError, BlockImportData, GossipVerifiedBlockContents, RpcBlock,
5555
};
5656
use crate::data_availability_checker::{AvailabilityCheckError, MaybeAvailableBlock};
57+
use crate::data_column_verification::GossipDataColumnError;
5758
use crate::eth1_finalization_cache::Eth1FinalizationData;
5859
use crate::execution_payload::{
5960
is_optimistic_candidate_block, validate_execution_payload_for_gossip, validate_merge_block,
@@ -303,6 +304,13 @@ pub enum BlockError<E: EthSpec> {
303304
/// TODO: We may need to penalize the peer that gave us a potentially invalid rpc blob.
304305
/// https://github.com/sigp/lighthouse/issues/4546
305306
AvailabilityCheck(AvailabilityCheckError),
307+
/// An internal error has occurred when processing the block or sidecars.
308+
///
309+
/// ## Peer scoring
310+
///
311+
/// We were unable to process this block due to an internal error. It's unclear if the block is
312+
/// valid.
313+
InternalError(String),
306314
}
307315

308316
impl<E: EthSpec> From<AvailabilityCheckError> for BlockError<E> {
@@ -523,6 +531,20 @@ impl<E: EthSpec> BlockSlashInfo<GossipBlobError<E>> {
523531
}
524532
}
525533

534+
impl BlockSlashInfo<GossipDataColumnError> {
535+
pub fn from_early_error_data_column(
536+
header: SignedBeaconBlockHeader,
537+
e: GossipDataColumnError,
538+
) -> Self {
539+
match e {
540+
GossipDataColumnError::ProposalSignatureInvalid => BlockSlashInfo::SignatureInvalid(e),
541+
// `InvalidSignature` could indicate any signature in the block, so we want
542+
// to recheck the proposer signature alone.
543+
_ => BlockSlashInfo::SignatureNotChecked(header, e),
544+
}
545+
}
546+
}
547+
526548
/// Process invalid blocks to see if they are suitable for the slasher.
527549
///
528550
/// If no slasher is configured, this is a no-op.
@@ -2007,6 +2029,23 @@ impl<E: EthSpec> BlockBlobError for GossipBlobError<E> {
20072029
}
20082030
}
20092031

2032+
impl BlockBlobError for GossipDataColumnError {
2033+
fn not_later_than_parent_error(data_column_slot: Slot, parent_slot: Slot) -> Self {
2034+
GossipDataColumnError::IsNotLaterThanParent {
2035+
data_column_slot,
2036+
parent_slot,
2037+
}
2038+
}
2039+
2040+
fn unknown_validator_error(validator_index: u64) -> Self {
2041+
GossipDataColumnError::UnknownValidator(validator_index)
2042+
}
2043+
2044+
fn proposer_signature_invalid() -> Self {
2045+
GossipDataColumnError::ProposalSignatureInvalid
2046+
}
2047+
}
2048+
20102049
/// Performs a cheap (time-efficient) state advancement so the committees and proposer shuffling for
20112050
/// `slot` can be obtained from `state`.
20122051
///

beacon_node/beacon_chain/src/data_availability_checker.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ mod error;
2020
mod overflow_lru_cache;
2121
mod state_lru_cache;
2222

23+
use crate::data_column_verification::GossipVerifiedDataColumn;
2324
pub use error::{Error as AvailabilityCheckError, ErrorCategory as AvailabilityCheckErrorCategory};
2425
use types::non_zero_usize::new_non_zero_usize;
2526

@@ -188,6 +189,14 @@ impl<T: BeaconChainTypes> DataAvailabilityChecker<T> {
188189
)
189190
}
190191

192+
pub fn put_gossip_data_columns(
193+
&self,
194+
_gossip_data_columns: Vec<GossipVerifiedDataColumn<T>>,
195+
) -> Result<Availability<T::EthSpec>, AvailabilityCheckError> {
196+
// TODO(das) to be implemented
197+
Err(AvailabilityCheckError::Unexpected)
198+
}
199+
191200
/// Check if we have all the blobs for a block. Returns `Availability` which has information
192201
/// about whether all components have been received or more are required.
193202
pub fn put_pending_executed_block(

0 commit comments

Comments
 (0)