Fix infinite retry loop on blob/column processing failure in lookup sync

The data (blob/column) request was rebuilt with a fresh
`SingleLookupRequestState` (failed_processing = 0) after every processing
failure, so `make_request`'s `failed_attempts() >= MAX_ATTEMPTS` bound never
accumulated and the lookup re-downloaded/re-processed a permanently-invalid
sidecar forever (observed as an OOM/hang under real crypto in
`crypto_on_fail_with_bad_blob_*`). Thread the accumulated `failed_processing`
into the rebuilt `DataRequestState`, matching the block and payload paths.

Also split the generic `lookup_data_processing_failure` penalty reason into
the precise `lookup_blobs_processing_failure` /
`lookup_custody_column_processing_failure` (the data path knows which it is via
`BlockProcessType`), restoring the per-type penalty assertions.

Verified under the CI command (real crypto):
  FORK_NAME=electra ... crypto_on_fail_with_bad_blob_*   -> pass
  FORK_NAME=fulu    ... crypto_on_fail_with_bad_column_* -> pass
This commit is contained in:
dapplion
2026-06-01 06:34:05 +02:00
parent d137620ce5
commit a70a120d55
2 changed files with 21 additions and 10 deletions

View File

@@ -475,7 +475,13 @@ impl<E: EthSpec> PayloadRequestState<E> {
}
impl<E: EthSpec> DataRequestState<E> {
fn new(slot: Slot, block_root: Hash256, expected_blobs: usize, spec: &ChainSpec) -> Self {
fn new(
slot: Slot,
block_root: Hash256,
expected_blobs: usize,
failed_processing: u8,
spec: &ChainSpec,
) -> Self {
let block_fork = spec.fork_name_at_slot::<E>(slot);
match block_fork {
@@ -487,7 +493,9 @@ impl<E: EthSpec> DataRequestState<E> {
Self::Downloading(DataDownload::Blobs {
block_root,
expected_blobs,
state: SingleLookupRequestState::new(),
state: SingleLookupRequestState::new_with_processing_failures(
failed_processing,
),
})
} else {
Self::Complete
@@ -497,7 +505,9 @@ impl<E: EthSpec> DataRequestState<E> {
if expected_blobs > 0 {
Self::Downloading(DataDownload::Columns {
block_root,
state: SingleLookupRequestState::new(),
state: SingleLookupRequestState::new_with_processing_failures(
failed_processing,
),
})
} else {
Self::Complete
@@ -507,7 +517,9 @@ impl<E: EthSpec> DataRequestState<E> {
if expected_blobs > 0 {
Self::Downloading(DataDownload::Columns {
block_root,
state: SingleLookupRequestState::new(),
state: SingleLookupRequestState::new_with_processing_failures(
failed_processing,
),
})
// Gloas: data peers start at 0, populated when children arrive
} else {
@@ -811,6 +823,7 @@ impl<T: BeaconChainTypes> SingleBlockLookup<T> {
block.slot(),
self.block_root,
block.num_expected_blobs(),
self.failed_processing,
cx.spec(),
),
});