Block availability data enum (#6866)

PeerDAS has undergone multiple refactors + the blending with the get_blobs optimization has generated technical debt.

A function signature like this

f008b84079/beacon_node/beacon_chain/src/beacon_chain.rs (L7171-L7178)

Allows at least the following combination of states:
- blobs: Some / None
- data_columns: Some / None
- data_column_recv: Some / None
- Block has data? Yes / No
- Block post-PeerDAS? Yes / No

In reality, we don't have that many possible states, only:

- `NoData`: pre-deneb, pre-PeerDAS with 0 blobs or post-PeerDAS with 0 blobs
- `Blobs(BlobSidecarList<E>)`: post-Deneb pre-PeerDAS with > 0 blobs
- `DataColumns(DataColumnSidecarList<E>)`: post-PeerDAS with > 0 blobs
- `DataColumnsRecv(oneshot::Receiver<DataColumnSidecarList<E>>)`: post-PeerDAS with > 0 blobs, but we obtained the columns via reconstruction

^ this are the variants of the new `AvailableBlockData` enum

So we go from 2^5 states to 4 well-defined. Downstream code benefits nicely from this clarity and I think it makes the whole feature much more maintainable.

Currently `is_available` returns a bool, and then we construct the available block in `make_available`. In a way the availability condition is duplicated in both functions. Instead, this PR constructs `AvailableBlockData` in `is_available` so the availability conditions are written once

```rust
if let Some(block_data) = is_available(..) {
let available_block = make_available(block_data);
}
```
This commit is contained in:
Lion - dapplion
2025-02-24 01:47:09 -03:00
committed by GitHub
parent 60964fc7b5
commit 3fab6a2c0b
11 changed files with 432 additions and 361 deletions

View File

@@ -1,4 +1,4 @@
use crate::data_availability_checker::AvailableBlock;
use crate::data_availability_checker::{AvailableBlock, AvailableBlockData};
use crate::{
attester_cache::{CommitteeLengths, Error},
metrics,
@@ -52,7 +52,7 @@ impl<E: EthSpec> EarlyAttesterCache<E> {
pub fn add_head_block(
&self,
beacon_block_root: Hash256,
block: AvailableBlock<E>,
block: &AvailableBlock<E>,
proto_block: ProtoBlock,
state: &BeaconState<E>,
spec: &ChainSpec,
@@ -70,14 +70,23 @@ impl<E: EthSpec> EarlyAttesterCache<E> {
},
};
let (_, block, blobs, data_columns) = block.deconstruct();
let (blobs, data_columns) = match block.data() {
AvailableBlockData::NoData => (None, None),
AvailableBlockData::Blobs(blobs) => (Some(blobs.clone()), None),
AvailableBlockData::DataColumns(data_columns) => (None, Some(data_columns.clone())),
// TODO(das): Once the columns are received, they will not be available in
// the early attester cache. If someone does a query to us via RPC we
// will get downscored.
AvailableBlockData::DataColumnsRecv(_) => (None, None),
};
let item = CacheItem {
epoch,
committee_lengths,
beacon_block_root,
source,
target,
block,
block: block.block_cloned(),
blobs,
data_columns,
proto_block,