mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-22 22:34:45 +00:00
Improving blob propagation post-PeerDAS with Decentralized Blob Building (#6268)
* Get blobs from EL. Co-authored-by: Michael Sproul <michael@sigmaprime.io> * Avoid cloning blobs after fetching blobs. * Address review comments and refactor code. * Fix lint. * Move blob computation metric to the right spot. * Merge branch 'unstable' into das-fetch-blobs * Merge branch 'unstable' into das-fetch-blobs # Conflicts: # beacon_node/beacon_chain/src/beacon_chain.rs # beacon_node/beacon_chain/src/block_verification.rs # beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs * Merge branch 'unstable' into das-fetch-blobs # Conflicts: # beacon_node/beacon_chain/src/beacon_chain.rs * Gradual publication of data columns for supernodes. * Recompute head after importing block with blobs from the EL. * Fix lint * Merge branch 'unstable' into das-fetch-blobs * Use blocking task instead of async when computing cells. * Merge branch 'das-fetch-blobs' of github.com:jimmygchen/lighthouse into das-fetch-blobs * Merge remote-tracking branch 'origin/unstable' into das-fetch-blobs * Fix semantic conflicts * Downgrade error log. * Merge branch 'unstable' into das-fetch-blobs # Conflicts: # beacon_node/beacon_chain/src/data_availability_checker.rs # beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs # beacon_node/execution_layer/src/engine_api.rs # beacon_node/execution_layer/src/engine_api/json_structures.rs # beacon_node/network/src/network_beacon_processor/gossip_methods.rs # beacon_node/network/src/network_beacon_processor/mod.rs # beacon_node/network/src/network_beacon_processor/sync_methods.rs * Merge branch 'unstable' into das-fetch-blobs * Publish block without waiting for blob and column proof computation. * Address review comments and refactor. * Merge branch 'unstable' into das-fetch-blobs * Fix test and docs. * Comment cleanups. * Merge branch 'unstable' into das-fetch-blobs * Address review comments and cleanup * Address review comments and cleanup * Refactor to de-duplicate gradual publication logic. * Add more logging. * Merge remote-tracking branch 'origin/unstable' into das-fetch-blobs # Conflicts: # Cargo.lock * Fix incorrect comparison on `num_fetched_blobs`. * Implement gradual blob publication. * Merge branch 'unstable' into das-fetch-blobs * Inline `publish_fn`. * Merge branch 'das-fetch-blobs' of github.com:jimmygchen/lighthouse into das-fetch-blobs * Gossip verify blobs before publishing * Avoid queries for 0 blobs and error for duplicates * Gossip verified engine blob before processing them, and use observe cache to detect duplicates before publishing. * Merge branch 'das-fetch-blobs' of github.com:jimmygchen/lighthouse into das-fetch-blobs # Conflicts: # beacon_node/network/src/network_beacon_processor/mod.rs * Merge branch 'unstable' into das-fetch-blobs * Fix invalid commitment inclusion proofs in blob sidecars created from EL blobs. * Only publish EL blobs triggered from gossip block, and not RPC block. * Downgrade gossip blob log to `debug`. * Merge branch 'unstable' into das-fetch-blobs * Merge branch 'unstable' into das-fetch-blobs * Grammar
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
use derivative::Derivative;
|
||||
use slot_clock::SlotClock;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::beacon_chain::{BeaconChain, BeaconChainTypes};
|
||||
@@ -8,11 +9,11 @@ use crate::block_verification::{
|
||||
BlockSlashInfo,
|
||||
};
|
||||
use crate::kzg_utils::{validate_blob, validate_blobs};
|
||||
use crate::observed_data_sidecars::{DoNotObserve, ObservationStrategy, Observe};
|
||||
use crate::{metrics, BeaconChainError};
|
||||
use kzg::{Error as KzgError, Kzg, KzgCommitment};
|
||||
use slog::debug;
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use ssz_types::VariableList;
|
||||
use std::time::Duration;
|
||||
use tree_hash::TreeHash;
|
||||
use types::blob_sidecar::BlobIdentifier;
|
||||
@@ -156,20 +157,16 @@ impl From<BeaconStateError> for GossipBlobError {
|
||||
}
|
||||
}
|
||||
|
||||
pub type GossipVerifiedBlobList<T> = VariableList<
|
||||
GossipVerifiedBlob<T>,
|
||||
<<T as BeaconChainTypes>::EthSpec as EthSpec>::MaxBlobsPerBlock,
|
||||
>;
|
||||
|
||||
/// A wrapper around a `BlobSidecar` that indicates it has been approved for re-gossiping on
|
||||
/// the p2p network.
|
||||
#[derive(Debug)]
|
||||
pub struct GossipVerifiedBlob<T: BeaconChainTypes> {
|
||||
pub struct GossipVerifiedBlob<T: BeaconChainTypes, O: ObservationStrategy = Observe> {
|
||||
block_root: Hash256,
|
||||
blob: KzgVerifiedBlob<T::EthSpec>,
|
||||
_phantom: PhantomData<O>,
|
||||
}
|
||||
|
||||
impl<T: BeaconChainTypes> GossipVerifiedBlob<T> {
|
||||
impl<T: BeaconChainTypes, O: ObservationStrategy> GossipVerifiedBlob<T, O> {
|
||||
pub fn new(
|
||||
blob: Arc<BlobSidecar<T::EthSpec>>,
|
||||
subnet_id: u64,
|
||||
@@ -178,7 +175,7 @@ impl<T: BeaconChainTypes> GossipVerifiedBlob<T> {
|
||||
let header = blob.signed_block_header.clone();
|
||||
// We only process slashing info if the gossip verification failed
|
||||
// since we do not process the blob any further in that case.
|
||||
validate_blob_sidecar_for_gossip(blob, subnet_id, chain).map_err(|e| {
|
||||
validate_blob_sidecar_for_gossip::<T, O>(blob, subnet_id, chain).map_err(|e| {
|
||||
process_block_slash_info::<_, GossipBlobError>(
|
||||
chain,
|
||||
BlockSlashInfo::from_early_error_blob(header, e),
|
||||
@@ -195,6 +192,7 @@ impl<T: BeaconChainTypes> GossipVerifiedBlob<T> {
|
||||
blob,
|
||||
seen_timestamp: Duration::from_secs(0),
|
||||
},
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
pub fn id(&self) -> BlobIdentifier {
|
||||
@@ -335,6 +333,25 @@ impl<E: EthSpec> KzgVerifiedBlobList<E> {
|
||||
verified_blobs: blobs,
|
||||
})
|
||||
}
|
||||
|
||||
/// Create a `KzgVerifiedBlobList` from `blobs` that are already KZG verified.
|
||||
///
|
||||
/// This should be used with caution, as used incorrectly it could result in KZG verification
|
||||
/// being skipped and invalid blobs being deemed valid.
|
||||
pub fn from_verified<I: IntoIterator<Item = Arc<BlobSidecar<E>>>>(
|
||||
blobs: I,
|
||||
seen_timestamp: Duration,
|
||||
) -> Self {
|
||||
Self {
|
||||
verified_blobs: blobs
|
||||
.into_iter()
|
||||
.map(|blob| KzgVerifiedBlob {
|
||||
blob,
|
||||
seen_timestamp,
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> IntoIterator for KzgVerifiedBlobList<E> {
|
||||
@@ -364,11 +381,11 @@ where
|
||||
validate_blobs::<E>(kzg, commitments.as_slice(), blobs, proofs.as_slice())
|
||||
}
|
||||
|
||||
pub fn validate_blob_sidecar_for_gossip<T: BeaconChainTypes>(
|
||||
pub fn validate_blob_sidecar_for_gossip<T: BeaconChainTypes, O: ObservationStrategy>(
|
||||
blob_sidecar: Arc<BlobSidecar<T::EthSpec>>,
|
||||
subnet: u64,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<GossipVerifiedBlob<T>, GossipBlobError> {
|
||||
) -> Result<GossipVerifiedBlob<T, O>, GossipBlobError> {
|
||||
let blob_slot = blob_sidecar.slot();
|
||||
let blob_index = blob_sidecar.index;
|
||||
let block_parent_root = blob_sidecar.block_parent_root();
|
||||
@@ -568,16 +585,45 @@ pub fn validate_blob_sidecar_for_gossip<T: BeaconChainTypes>(
|
||||
)
|
||||
.map_err(|e| GossipBlobError::BeaconChainError(e.into()))?;
|
||||
|
||||
if O::observe() {
|
||||
observe_gossip_blob(&kzg_verified_blob.blob, chain)?;
|
||||
}
|
||||
|
||||
Ok(GossipVerifiedBlob {
|
||||
block_root,
|
||||
blob: kzg_verified_blob,
|
||||
_phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
impl<T: BeaconChainTypes> GossipVerifiedBlob<T, DoNotObserve> {
|
||||
pub fn observe(
|
||||
self,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<GossipVerifiedBlob<T, Observe>, GossipBlobError> {
|
||||
observe_gossip_blob(&self.blob.blob, chain)?;
|
||||
Ok(GossipVerifiedBlob {
|
||||
block_root: self.block_root,
|
||||
blob: self.blob,
|
||||
_phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn observe_gossip_blob<T: BeaconChainTypes>(
|
||||
blob_sidecar: &BlobSidecar<T::EthSpec>,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<(), GossipBlobError> {
|
||||
// Now the signature is valid, store the proposal so we don't accept another blob sidecar
|
||||
// with the same `BlobIdentifier`.
|
||||
// It's important to double-check that the proposer still hasn't been observed so we don't
|
||||
// have a race-condition when verifying two blocks simultaneously.
|
||||
// with the same `BlobIdentifier`. It's important to double-check that the proposer still
|
||||
// hasn't been observed so we don't have a race-condition when verifying two blocks
|
||||
// simultaneously.
|
||||
//
|
||||
// Note: If this BlobSidecar goes on to fail full verification, we do not evict it from the seen_cache
|
||||
// as alternate blob_sidecars for the same identifier can still be retrieved
|
||||
// over rpc. Evicting them from this cache would allow faster propagation over gossip. So we allow
|
||||
// retrieval of potentially valid blocks over rpc, but try to punish the proposer for signing
|
||||
// invalid messages. Issue for more background
|
||||
// Note: If this BlobSidecar goes on to fail full verification, we do not evict it from the
|
||||
// seen_cache as alternate blob_sidecars for the same identifier can still be retrieved over
|
||||
// rpc. Evicting them from this cache would allow faster propagation over gossip. So we
|
||||
// allow retrieval of potentially valid blocks over rpc, but try to punish the proposer for
|
||||
// signing invalid messages. Issue for more background
|
||||
// https://github.com/ethereum/consensus-specs/issues/3261
|
||||
if chain
|
||||
.observed_blob_sidecars
|
||||
@@ -586,16 +632,12 @@ pub fn validate_blob_sidecar_for_gossip<T: BeaconChainTypes>(
|
||||
.map_err(|e| GossipBlobError::BeaconChainError(e.into()))?
|
||||
{
|
||||
return Err(GossipBlobError::RepeatBlob {
|
||||
proposer: proposer_index as u64,
|
||||
slot: blob_slot,
|
||||
index: blob_index,
|
||||
proposer: blob_sidecar.block_proposer_index(),
|
||||
slot: blob_sidecar.slot(),
|
||||
index: blob_sidecar.index,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(GossipVerifiedBlob {
|
||||
block_root,
|
||||
blob: kzg_verified_blob,
|
||||
})
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns the canonical root of the given `blob`.
|
||||
|
||||
Reference in New Issue
Block a user