Offloading KZG Proof Computation from the beacon node (#7117)

Addresses #7108

- Add EL integration for `getPayloadV5` and `getBlobsV2`
- Offload proof computation and use proofs from EL RPC APIs
This commit is contained in:
Jimmy Chen
2025-04-08 17:37:16 +10:00
committed by GitHub
parent e924264e17
commit 759b0612b3
31 changed files with 721 additions and 476 deletions

View File

@@ -14,7 +14,6 @@ use std::num::NonZeroUsize;
use std::sync::Arc;
use std::time::Duration;
use task_executor::TaskExecutor;
use tokio::sync::oneshot;
use tracing::{debug, error, info_span, Instrument};
use types::blob_sidecar::{BlobIdentifier, BlobSidecar, FixedBlobSidecarList};
use types::{
@@ -226,27 +225,45 @@ impl<T: BeaconChainTypes> DataAvailabilityChecker<T> {
pub fn put_engine_blobs(
&self,
block_root: Hash256,
block_epoch: Epoch,
blobs: FixedBlobSidecarList<T::EthSpec>,
data_columns_recv: Option<oneshot::Receiver<DataColumnSidecarList<T::EthSpec>>>,
) -> Result<Availability<T::EthSpec>, AvailabilityCheckError> {
// `data_columns_recv` is always Some if block_root is post-PeerDAS
if let Some(data_columns_recv) = data_columns_recv {
self.availability_cache.put_computed_data_columns_recv(
block_root,
block_epoch,
data_columns_recv,
)
} else {
let seen_timestamp = self
.slot_clock
.now_duration()
.ok_or(AvailabilityCheckError::SlotClockError)?;
self.availability_cache.put_kzg_verified_blobs(
block_root,
KzgVerifiedBlobList::from_verified(blobs.iter().flatten().cloned(), seen_timestamp),
)
}
let seen_timestamp = self
.slot_clock
.now_duration()
.ok_or(AvailabilityCheckError::SlotClockError)?;
self.availability_cache.put_kzg_verified_blobs(
block_root,
KzgVerifiedBlobList::from_verified(blobs.iter().flatten().cloned(), seen_timestamp),
)
}
/// Put a list of data columns computed from blobs received from the EL pool into the
/// availability cache.
///
/// This DOES NOT perform KZG proof and inclusion proof verification because
/// - The KZG proofs should have been verified by the trusted EL.
/// - The KZG commitments inclusion proof should have been constructed immediately prior to
/// calling this function so they are assumed to be valid.
///
/// This method is used if the EL already has the blobs and returns them via the `getBlobsV2`
/// engine method.
/// More details in [fetch_blobs.rs](https://github.com/sigp/lighthouse/blob/44f8add41ea2252769bb967864af95b3c13af8ca/beacon_node/beacon_chain/src/fetch_blobs.rs).
pub fn put_engine_data_columns(
&self,
block_root: Hash256,
data_columns: DataColumnSidecarList<T::EthSpec>,
) -> Result<Availability<T::EthSpec>, AvailabilityCheckError> {
let kzg_verified_custody_columns = data_columns
.into_iter()
.map(|d| {
KzgVerifiedCustodyDataColumn::from_asserted_custody(
KzgVerifiedDataColumn::from_verified(d),
)
})
.collect::<Vec<_>>();
self.availability_cache
.put_kzg_verified_data_columns(block_root, kzg_verified_custody_columns)
}
/// Check if we've cached other blobs for this block. If it completes a set and we also
@@ -704,9 +721,6 @@ pub enum AvailableBlockData<E: EthSpec> {
Blobs(BlobSidecarList<E>),
/// Block is post-PeerDAS and has more than zero blobs
DataColumns(DataColumnSidecarList<E>),
/// Block is post-PeerDAS, has more than zero blobs and we recomputed the columns from the EL's
/// mempool blobs
DataColumnsRecv(oneshot::Receiver<DataColumnSidecarList<E>>),
}
/// A fully available block that is ready to be imported into fork choice.
@@ -756,7 +770,6 @@ impl<E: EthSpec> AvailableBlock<E> {
AvailableBlockData::NoData => false,
AvailableBlockData::Blobs(..) => true,
AvailableBlockData::DataColumns(_) => false,
AvailableBlockData::DataColumnsRecv(_) => false,
}
}
@@ -782,9 +795,6 @@ impl<E: EthSpec> AvailableBlock<E> {
AvailableBlockData::DataColumns(data_columns) => {
AvailableBlockData::DataColumns(data_columns.clone())
}
AvailableBlockData::DataColumnsRecv(_) => {
return Err("Can't clone DataColumnsRecv".to_owned())
}
},
blobs_available_timestamp: self.blobs_available_timestamp,
spec: self.spec.clone(),