mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-08 01:05:47 +00:00
extended chaos
This commit is contained in:
@@ -8,7 +8,7 @@ use crate::beacon_proposer_cache::compute_proposer_duties_from_head;
|
|||||||
use crate::beacon_proposer_cache::BeaconProposerCache;
|
use crate::beacon_proposer_cache::BeaconProposerCache;
|
||||||
use crate::blob_cache::BlobCache;
|
use crate::blob_cache::BlobCache;
|
||||||
use crate::blob_verification::{
|
use crate::blob_verification::{
|
||||||
AsBlock, AvailabilityPendingBlock, AvailableBlock, BlobError, Blobs, BlockWrapper,
|
AsBlock, AvailableBlock, BlobError, Blobs, BlockWrapper,
|
||||||
IntoAvailableBlock,
|
IntoAvailableBlock,
|
||||||
};
|
};
|
||||||
use crate::block_times_cache::BlockTimesCache;
|
use crate::block_times_cache::BlockTimesCache;
|
||||||
@@ -442,8 +442,7 @@ pub struct BeaconChain<T: BeaconChainTypes> {
|
|||||||
/// Provides monitoring of a set of explicitly defined validators.
|
/// Provides monitoring of a set of explicitly defined validators.
|
||||||
pub validator_monitor: RwLock<ValidatorMonitor<T::EthSpec>>,
|
pub validator_monitor: RwLock<ValidatorMonitor<T::EthSpec>>,
|
||||||
pub blob_cache: BlobCache<T::EthSpec>,
|
pub blob_cache: BlobCache<T::EthSpec>,
|
||||||
pub blob_cache: BlobCache<T::EthSpec>,
|
pub kzg: Option<Arc<Kzg>>,
|
||||||
pub kzg: Option<Arc<kzg::Kzg>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type BeaconBlockAndState<T, Payload> = (BeaconBlock<T, Payload>, BeaconState<T>);
|
type BeaconBlockAndState<T, Payload> = (BeaconBlock<T, Payload>, BeaconState<T>);
|
||||||
@@ -1084,34 +1083,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
pub fn get_blobs(
|
pub fn get_blobs(
|
||||||
&self,
|
&self,
|
||||||
block_root: &Hash256,
|
block_root: &Hash256,
|
||||||
data_availability_boundary: Epoch,
|
) -> Result<Option<BlobSidecarList<T::EthSpec>>, Error> {
|
||||||
) -> Result<Option<BlobsSidecar<T::EthSpec>>, Error> {
|
self.store.get_blobs(block_root)
|
||||||
match self.store.get_blobs(block_root)? {
|
|
||||||
Some(blobs) => Ok(Some(blobs)),
|
|
||||||
None => {
|
|
||||||
// Check for the corresponding block to understand whether we *should* have blobs.
|
|
||||||
self.get_blinded_block(block_root)?
|
|
||||||
.map(|block| {
|
|
||||||
// If there are no KZG commitments in the block, we know the sidecar should
|
|
||||||
// be empty.
|
|
||||||
let expected_kzg_commitments =
|
|
||||||
match block.message().body().blob_kzg_commitments() {
|
|
||||||
Ok(kzg_commitments) => kzg_commitments,
|
|
||||||
Err(_) => return Err(Error::NoKzgCommitmentsFieldOnBlock),
|
|
||||||
};
|
|
||||||
if expected_kzg_commitments.is_empty() {
|
|
||||||
Ok(BlobsSidecar::empty_from_parts(*block_root, block.slot()))
|
|
||||||
} else if data_availability_boundary <= block.epoch() {
|
|
||||||
// We should have blobs for all blocks younger than the boundary.
|
|
||||||
Err(Error::BlobsUnavailable)
|
|
||||||
} else {
|
|
||||||
// We shouldn't have blobs for blocks older than the boundary.
|
|
||||||
Err(Error::BlobsOlderThanDataAvailabilityBoundary(block.epoch()))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.transpose()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_blinded_block(
|
pub fn get_blinded_block(
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ use crate::BeaconChainError;
|
|||||||
use state_processing::per_block_processing::eip4844::eip4844::verify_kzg_commitments_against_transactions;
|
use state_processing::per_block_processing::eip4844::eip4844::verify_kzg_commitments_against_transactions;
|
||||||
use types::blob_sidecar::BlobSidecar;
|
use types::blob_sidecar::BlobSidecar;
|
||||||
use types::{
|
use types::{
|
||||||
BeaconBlockRef, BeaconStateError, BlobsSidecar, EthSpec, Hash256, KzgCommitment,
|
BeaconBlockRef, BeaconStateError, EthSpec, Hash256, KzgCommitment,
|
||||||
SignedBeaconBlock, SignedBeaconBlockAndBlobsSidecar, SignedBeaconBlockHeader,
|
SignedBeaconBlock, SignedBeaconBlockHeader,
|
||||||
SignedBlobSidecar, Slot, Transactions,
|
SignedBlobSidecar, Slot, Transactions,
|
||||||
};
|
};
|
||||||
use types::{Epoch, ExecPayload};
|
use types::{Epoch, ExecPayload};
|
||||||
@@ -289,23 +289,6 @@ pub enum DataAvailabilityCheckRequired {
|
|||||||
No,
|
No,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: BeaconChainTypes> BlockWrapper<T::EthSpec> {
|
|
||||||
fn into_availablilty_pending_block(
|
|
||||||
self,
|
|
||||||
block_root: Hash256,
|
|
||||||
chain: &BeaconChain<T>,
|
|
||||||
) -> Result<AvailabilityPendingBlock<T::EthSpec>, BlobError> {
|
|
||||||
match self {
|
|
||||||
BlockWrapper::Block(block) => {
|
|
||||||
AvailabilityPendingBlock::new(block, block_root, da_check_required)
|
|
||||||
}
|
|
||||||
BlockWrapper::BlockAndBlobs(block, blobs_sidecar) => {
|
|
||||||
AvailabilityPendingBlock::new_with_blobs(block, blobs_sidecar, da_check_required)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait IntoAvailableBlock<T: BeaconChainTypes> {
|
pub trait IntoAvailableBlock<T: BeaconChainTypes> {
|
||||||
fn into_available_block(
|
fn into_available_block(
|
||||||
self,
|
self,
|
||||||
@@ -314,39 +297,32 @@ pub trait IntoAvailableBlock<T: BeaconChainTypes> {
|
|||||||
) -> Result<AvailableBlock<T::EthSpec>, BlobError>;
|
) -> Result<AvailableBlock<T::EthSpec>, BlobError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A wrapper over a [`SignedBeaconBlock`] or a [`SignedBeaconBlockAndBlobsSidecar`]. An
|
impl <T: BeaconChainTypes> IntoAvailableBlock<T> for BlockWrapper<T::EthSpec> {
|
||||||
/// `AvailableBlock` has passed any required data availability checks and should be used in
|
fn into_available_block(self, block_root: Hash256, chain: &BeaconChain<T>) -> Result<AvailableBlock<T::EthSpec>, BlobError> {
|
||||||
/// consensus.
|
todo!()
|
||||||
#[derive(Clone, Debug, Derivative)]
|
}
|
||||||
#[derivative(PartialEq, Hash(bound = "T: BeaconChainTypes"))]
|
|
||||||
pub struct AvailabilityPendingBlock<T: BeaconChainTypes> {
|
|
||||||
block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
|
||||||
data_availability_handle: DataAvailabilityHandle<T::EthSpec>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used to await the result of data availability check.
|
|
||||||
type DataAvailabilityHandle<E> = JoinHandle<Result<Option<Blobs<E>>, BlobError>>;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Derivative)]
|
#[derive(Clone, Debug, Derivative)]
|
||||||
#[derivative(PartialEq, Hash(bound = "T: BeaconChainTypes"))]
|
#[derivative(PartialEq, Hash(bound = "T: BeaconChainTypes"))]
|
||||||
pub struct AvailableBlock<T: BeaconChainTypes> {
|
pub struct AvailableBlock<T: EthSpec> {
|
||||||
block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
block: Arc<SignedBeaconBlock<T>>,
|
||||||
blobs: Blobs<T::EthSpec>,
|
blobs: Blobs<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: BeaconChainTypes> AvailableBlock<T> {
|
impl<T: EthSpec> AvailableBlock<T> {
|
||||||
pub fn blobs(&self) -> Option<Arc<BlobsSidecar<T>>> {
|
pub fn blobs(&self) -> Option<Arc<BlobsSidecar<T>>> {
|
||||||
match &self.blobs {
|
match &self.blobs {
|
||||||
Blobs::NotRequired | Blobs::None => None,
|
Blobs::NotRequired | Blobs::None => None,
|
||||||
Blobs::Available(block_sidecar) => Some(block_sidecar.clone()),
|
Blobs::Available(blob_sidecar) => Some(blob_sidecar.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deconstruct(
|
pub fn deconstruct(
|
||||||
self,
|
self,
|
||||||
) -> (
|
) -> (
|
||||||
Arc<SignedBeaconBlock<T::EthSpec>>,
|
Arc<SignedBeaconBlock<T>>,
|
||||||
Option<Arc<BlobsSidecar<T::EthSpec>>>,
|
Option<Arc<BlobsSidecar<T>>>,
|
||||||
) {
|
) {
|
||||||
match self.blobs {
|
match self.blobs {
|
||||||
Blobs::NotRequired | Blobs::None => (self.block, None),
|
Blobs::NotRequired | Blobs::None => (self.block, None),
|
||||||
@@ -365,119 +341,6 @@ pub enum Blobs<E: EthSpec> {
|
|||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO(sean) add block root to the availability pending block?
|
|
||||||
impl<T: BeaconChainTypes> AvailabilityPendingBlock<T> {
|
|
||||||
pub fn new(
|
|
||||||
beacon_block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
|
||||||
block_root: Hash256,
|
|
||||||
chain: &BeaconChain<T>,
|
|
||||||
) -> Result<Self, BlobError> {
|
|
||||||
let data_availability_boundary = chain.data_availability_boundary();
|
|
||||||
let da_check_required =
|
|
||||||
data_availability_boundary.map_or(DataAvailabilityCheckRequired::No, |boundary| {
|
|
||||||
if chain.epoch()? >= boundary {
|
|
||||||
DataAvailabilityCheckRequired::Yes
|
|
||||||
} else {
|
|
||||||
DataAvailabilityCheckRequired::No
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
match beacon_block.as_ref() {
|
|
||||||
// No data availability check required prior to Eip4844.
|
|
||||||
SignedBeaconBlock::Base(_)
|
|
||||||
| SignedBeaconBlock::Altair(_)
|
|
||||||
| SignedBeaconBlock::Capella(_)
|
|
||||||
| SignedBeaconBlock::Merge(_) => Ok(AvailabilityPendingBlock {
|
|
||||||
block: beacon_block,
|
|
||||||
data_availability_handle: async { Ok(Some(Blobs::NotRequired)) },
|
|
||||||
}),
|
|
||||||
SignedBeaconBlock::Eip4844(_) => {
|
|
||||||
match da_check_required {
|
|
||||||
DataAvailabilityCheckRequired::Yes => {
|
|
||||||
// Attempt to reconstruct empty blobs here.
|
|
||||||
let blobs_sidecar = beacon_block
|
|
||||||
.reconstruct_empty_blobs(Some(block_root))
|
|
||||||
.map(Arc::new)?;
|
|
||||||
Ok(AvailableBlock(AvailableBlockInner::BlockAndBlob(
|
|
||||||
SignedBeaconBlockAndBlobsSidecar {
|
|
||||||
beacon_block,
|
|
||||||
blobs_sidecar,
|
|
||||||
},
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
DataAvailabilityCheckRequired::No => AvailabilityPendingBlock {
|
|
||||||
block: beacon_block,
|
|
||||||
data_availability_handle: async { Ok(Some(Blobs::NotRequired)) },
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This function is private because an `AvailableBlock` should be
|
|
||||||
/// constructed via the `into_available_block` method.
|
|
||||||
//TODO(sean) do we want this to optionally cricumvent the beacon cache?
|
|
||||||
fn new_with_blobs(
|
|
||||||
beacon_block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
|
||||||
blobs_sidecar: Arc<BlobsSidecar<T::EthSpec>>,
|
|
||||||
chain: &BeaconChain<T>,
|
|
||||||
) -> Result<Self, BlobError> {
|
|
||||||
let data_availability_boundary = chain.data_availability_boundary();
|
|
||||||
let da_check_required =
|
|
||||||
data_availability_boundary.map_or(DataAvailabilityCheckRequired::No, |boundary| {
|
|
||||||
if chain.epoch()? >= boundary {
|
|
||||||
DataAvailabilityCheckRequired::Yes
|
|
||||||
} else {
|
|
||||||
DataAvailabilityCheckRequired::No
|
|
||||||
}
|
|
||||||
});
|
|
||||||
match beacon_block.as_ref() {
|
|
||||||
// This method shouldn't be called with a pre-Eip4844 block.
|
|
||||||
SignedBeaconBlock::Base(_)
|
|
||||||
| SignedBeaconBlock::Altair(_)
|
|
||||||
| SignedBeaconBlock::Capella(_)
|
|
||||||
| SignedBeaconBlock::Merge(_) => Err(BlobError::InconsistentFork),
|
|
||||||
SignedBeaconBlock::Eip4844(_) => {
|
|
||||||
match da_check_required {
|
|
||||||
DataAvailabilityCheckRequired::Yes => Ok(AvailableBlock {
|
|
||||||
block: beacon_block,
|
|
||||||
blobs: Blobs::Available(blobs_sidecar),
|
|
||||||
}),
|
|
||||||
DataAvailabilityCheckRequired::No => {
|
|
||||||
// Blobs were not verified so we drop them, we'll instead just pass around
|
|
||||||
// an available `Eip4844` block without blobs.
|
|
||||||
Ok(AvailableBlock {
|
|
||||||
block: beacon_block,
|
|
||||||
blobs: Blobs::NotRequired,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait IntoBlockWrapper<E: EthSpec>: AsBlock<E> {
|
|
||||||
fn into_block_wrapper(self) -> BlockWrapper<E>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E: EthSpec> IntoBlockWrapper<E> for BlockWrapper<E> {
|
|
||||||
fn into_block_wrapper(self) -> BlockWrapper<E> {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E: EthSpec> IntoBlockWrapper<E> for AvailabilityPendingBlock<E> {
|
|
||||||
fn into_block_wrapper(self) -> BlockWrapper<E> {
|
|
||||||
let (block, blobs) = self.deconstruct();
|
|
||||||
if let Some(blobs) = blobs {
|
|
||||||
BlockWrapper::BlockAndBlobs(block, blobs)
|
|
||||||
} else {
|
|
||||||
BlockWrapper::Block(block)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait AsBlock<E: EthSpec> {
|
pub trait AsBlock<E: EthSpec> {
|
||||||
fn slot(&self) -> Slot;
|
fn slot(&self) -> Slot;
|
||||||
fn epoch(&self) -> Epoch;
|
fn epoch(&self) -> Epoch;
|
||||||
@@ -542,7 +405,7 @@ impl<E: EthSpec> AsBlock<E> for BlockWrapper<E> {
|
|||||||
fn canonical_root(&self) -> Hash256 {
|
fn canonical_root(&self) -> Hash256 {
|
||||||
match &self {
|
match &self {
|
||||||
BlockWrapper::Block(block) => block.canonical_root(),
|
BlockWrapper::Block(block) => block.canonical_root(),
|
||||||
BlockWrapper::BlockAndBlob(block, _) => block.canonical_root(),
|
BlockWrapper::BlockAndBlobs(block, _) => block.canonical_root(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -599,82 +462,42 @@ impl<E: EthSpec> AsBlock<E> for &BlockWrapper<E> {
|
|||||||
fn canonical_root(&self) -> Hash256 {
|
fn canonical_root(&self) -> Hash256 {
|
||||||
match &self {
|
match &self {
|
||||||
BlockWrapper::Block(block) => block.canonical_root(),
|
BlockWrapper::Block(block) => block.canonical_root(),
|
||||||
BlockWrapper::BlockAndBlob(block, _) => block.canonical_root(),
|
BlockWrapper::BlockAndBlobs(block, _) => block.canonical_root(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: EthSpec> AsBlock<E> for AvailabilityPendingBlock<E> {
|
/// A wrapper over a [`SignedBeaconBlock`] or a [`SignedBeaconBlockAndBlobsSidecar`]. This makes no
|
||||||
fn slot(&self) -> Slot {
|
/// claims about data availability and should not be used in consensus. This struct is useful in
|
||||||
match &self.0 {
|
/// networking when we want to send blocks around without consensus checks.
|
||||||
AvailableBlockInner::Block(block) => block.slot(),
|
#[derive(Clone, Debug, Derivative)]
|
||||||
AvailableBlockInner::BlockAndBlob(block_sidecar_pair) => {
|
#[derivative(PartialEq, Hash(bound = "E: EthSpec"))]
|
||||||
block_sidecar_pair.beacon_block.slot()
|
pub enum BlockWrapper<E: EthSpec> {
|
||||||
|
Block(Arc<SignedBeaconBlock<E>>),
|
||||||
|
BlockAndBlobs(Arc<SignedBeaconBlock<E>>, Arc<BlobsSidecar<E>>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: EthSpec> BlockWrapper<E> {
|
||||||
|
pub fn new(
|
||||||
|
block: Arc<SignedBeaconBlock<E>>,
|
||||||
|
blobs_sidecar: Option<Arc<BlobsSidecar<E>>>,
|
||||||
|
) -> Self {
|
||||||
|
if let Some(blobs_sidecar) = blobs_sidecar {
|
||||||
|
BlockWrapper::BlockAndBlobs(block, blobs_sidecar)
|
||||||
|
} else {
|
||||||
|
BlockWrapper::Block(block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn epoch(&self) -> Epoch {
|
|
||||||
match &self.0 {
|
impl<E: EthSpec> From<SignedBeaconBlock<E>> for BlockWrapper<E> {
|
||||||
AvailableBlockInner::Block(block) => block.epoch(),
|
fn from(block: SignedBeaconBlock<E>) -> Self {
|
||||||
AvailableBlockInner::BlockAndBlob(block_sidecar_pair) => {
|
BlockWrapper::Block(Arc::new(block))
|
||||||
block_sidecar_pair.beacon_block.epoch()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn parent_root(&self) -> Hash256 {
|
|
||||||
match &self.0 {
|
|
||||||
AvailableBlockInner::Block(block) => block.parent_root(),
|
|
||||||
AvailableBlockInner::BlockAndBlob(block_sidecar_pair) => {
|
|
||||||
block_sidecar_pair.beacon_block.parent_root()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn state_root(&self) -> Hash256 {
|
|
||||||
match &self.0 {
|
|
||||||
AvailableBlockInner::Block(block) => block.state_root(),
|
|
||||||
AvailableBlockInner::BlockAndBlob(block_sidecar_pair) => {
|
|
||||||
block_sidecar_pair.beacon_block.state_root()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn signed_block_header(&self) -> SignedBeaconBlockHeader {
|
|
||||||
match &self.0 {
|
|
||||||
AvailableBlockInner::Block(block) => block.signed_block_header(),
|
|
||||||
AvailableBlockInner::BlockAndBlob(block_sidecar_pair) => {
|
|
||||||
block_sidecar_pair.beacon_block.signed_block_header()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn message(&self) -> BeaconBlockRef<E> {
|
|
||||||
match &self.0 {
|
|
||||||
AvailableBlockInner::Block(block) => block.message(),
|
|
||||||
AvailableBlockInner::BlockAndBlob(block_sidecar_pair) => {
|
|
||||||
block_sidecar_pair.beacon_block.message()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn as_block(&self) -> &SignedBeaconBlock<E> {
|
|
||||||
match &self.0 {
|
|
||||||
AvailableBlockInner::Block(block) => block,
|
|
||||||
AvailableBlockInner::BlockAndBlob(block_sidecar_pair) => {
|
|
||||||
&block_sidecar_pair.beacon_block
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn block_cloned(&self) -> Arc<SignedBeaconBlock<E>> {
|
|
||||||
match &self.0 {
|
|
||||||
AvailableBlockInner::Block(block) => block.clone(),
|
|
||||||
AvailableBlockInner::BlockAndBlob(block_sidecar_pair) => {
|
|
||||||
block_sidecar_pair.beacon_block.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn canonical_root(&self) -> Hash256 {
|
|
||||||
match &self.0 {
|
|
||||||
AvailableBlockInner::Block(block) => block.canonical_root(),
|
|
||||||
AvailableBlockInner::BlockAndBlob(block_sidecar_pair) => {
|
|
||||||
block_sidecar_pair.beacon_block.canonical_root()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<E: EthSpec> From<Arc<SignedBeaconBlock<E>>> for BlockWrapper<E> {
|
||||||
|
fn from(block: Arc<SignedBeaconBlock<E>>) -> Self {
|
||||||
|
BlockWrapper::Block(block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
#![allow(clippy::result_large_err)]
|
#![allow(clippy::result_large_err)]
|
||||||
|
|
||||||
use crate::blob_verification::{
|
use crate::blob_verification::{
|
||||||
validate_blob_for_gossip, AsBlock, AvailabilityPendingBlock, AvailableBlock, BlobError,
|
AsBlock, AvailableBlock, BlobError,
|
||||||
BlockWrapper, IntoAvailableBlock, IntoBlockWrapper,
|
BlockWrapper, IntoAvailableBlock, IntoBlockWrapper,
|
||||||
};
|
};
|
||||||
use crate::eth1_finalization_cache::Eth1FinalizationData;
|
use crate::eth1_finalization_cache::Eth1FinalizationData;
|
||||||
@@ -627,7 +627,7 @@ pub fn signature_verify_chain_segment<T: BeaconChainTypes>(
|
|||||||
#[derive(Derivative)]
|
#[derive(Derivative)]
|
||||||
#[derivative(Debug(bound = "T: BeaconChainTypes"))]
|
#[derivative(Debug(bound = "T: BeaconChainTypes"))]
|
||||||
pub struct GossipVerifiedBlock<T: BeaconChainTypes> {
|
pub struct GossipVerifiedBlock<T: BeaconChainTypes> {
|
||||||
pub block: AvailabilityPendingBlock<T>,
|
pub block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
||||||
pub block_root: Hash256,
|
pub block_root: Hash256,
|
||||||
parent: Option<PreProcessingSnapshot<T::EthSpec>>,
|
parent: Option<PreProcessingSnapshot<T::EthSpec>>,
|
||||||
consensus_context: ConsensusContext<T::EthSpec>,
|
consensus_context: ConsensusContext<T::EthSpec>,
|
||||||
@@ -636,7 +636,7 @@ pub struct GossipVerifiedBlock<T: BeaconChainTypes> {
|
|||||||
/// A wrapper around a `SignedBeaconBlock` that indicates that all signatures (except the deposit
|
/// A wrapper around a `SignedBeaconBlock` that indicates that all signatures (except the deposit
|
||||||
/// signatures) have been verified.
|
/// signatures) have been verified.
|
||||||
pub struct SignatureVerifiedBlock<T: BeaconChainTypes> {
|
pub struct SignatureVerifiedBlock<T: BeaconChainTypes> {
|
||||||
block: AvailabilityPendingBlock<T::EthSpec>,
|
block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
||||||
block_root: Hash256,
|
block_root: Hash256,
|
||||||
parent: Option<PreProcessingSnapshot<T::EthSpec>>,
|
parent: Option<PreProcessingSnapshot<T::EthSpec>>,
|
||||||
consensus_context: ConsensusContext<T::EthSpec>,
|
consensus_context: ConsensusContext<T::EthSpec>,
|
||||||
@@ -689,7 +689,7 @@ pub trait IntoExecutionPendingBlock<T: BeaconChainTypes>: Sized {
|
|||||||
block_root: Hash256,
|
block_root: Hash256,
|
||||||
chain: &Arc<BeaconChain<T>>,
|
chain: &Arc<BeaconChain<T>>,
|
||||||
notify_execution_layer: NotifyExecutionLayer,
|
notify_execution_layer: NotifyExecutionLayer,
|
||||||
) -> Result<ExecutionPendingBlock<T, B>, BlockError<T::EthSpec>> {
|
) -> Result<ExecutionPendingBlock<T>, BlockError<T::EthSpec>> {
|
||||||
self.into_execution_pending_block_slashable(block_root, chain, notify_execution_layer)
|
self.into_execution_pending_block_slashable(block_root, chain, notify_execution_layer)
|
||||||
.map(|execution_pending| {
|
.map(|execution_pending| {
|
||||||
// Supply valid block to slasher.
|
// Supply valid block to slasher.
|
||||||
@@ -707,7 +707,7 @@ pub trait IntoExecutionPendingBlock<T: BeaconChainTypes>: Sized {
|
|||||||
block_root: Hash256,
|
block_root: Hash256,
|
||||||
chain: &Arc<BeaconChain<T>>,
|
chain: &Arc<BeaconChain<T>>,
|
||||||
notify_execution_layer: NotifyExecutionLayer,
|
notify_execution_layer: NotifyExecutionLayer,
|
||||||
) -> Result<ExecutionPendingBlock<T, B>, BlockSlashInfo<BlockError<T::EthSpec>>>;
|
) -> Result<ExecutionPendingBlock<T>, BlockSlashInfo<BlockError<T::EthSpec>>>;
|
||||||
|
|
||||||
fn block(&self) -> &SignedBeaconBlock<T::EthSpec>;
|
fn block(&self) -> &SignedBeaconBlock<T::EthSpec>;
|
||||||
}
|
}
|
||||||
@@ -930,8 +930,6 @@ impl<T: BeaconChainTypes> GossipVerifiedBlock<T> {
|
|||||||
// Validate the block's execution_payload (if any).
|
// Validate the block's execution_payload (if any).
|
||||||
validate_execution_payload_for_gossip(&parent_block, block.message(), chain)?;
|
validate_execution_payload_for_gossip(&parent_block, block.message(), chain)?;
|
||||||
|
|
||||||
let available_block = validate_blob_for_gossip(block, block_root, chain)?;
|
|
||||||
|
|
||||||
// Having checked the proposer index and the block root we can cache them.
|
// Having checked the proposer index and the block root we can cache them.
|
||||||
let consensus_context = ConsensusContext::new(available_block.slot())
|
let consensus_context = ConsensusContext::new(available_block.slot())
|
||||||
.set_current_block_root(block_root)
|
.set_current_block_root(block_root)
|
||||||
@@ -969,7 +967,7 @@ impl<T: BeaconChainTypes> IntoExecutionPendingBlock<T> for GossipVerifiedBlock<T
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn block(&self) -> &SignedBeaconBlock<T::EthSpec> {
|
fn block(&self) -> &SignedBeaconBlock<T::EthSpec> {
|
||||||
self.block.as_block()
|
self.block.as_ref()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -979,7 +977,7 @@ impl<T: BeaconChainTypes> SignatureVerifiedBlock<T> {
|
|||||||
///
|
///
|
||||||
/// Returns an error if the block is invalid, or if the block was unable to be verified.
|
/// Returns an error if the block is invalid, or if the block was unable to be verified.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
block: AvailabilityPendingBlock<T::EthSpec>,
|
block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
||||||
block_root: Hash256,
|
block_root: Hash256,
|
||||||
chain: &BeaconChain<T>,
|
chain: &BeaconChain<T>,
|
||||||
) -> Result<Self, BlockError<T::EthSpec>> {
|
) -> Result<Self, BlockError<T::EthSpec>> {
|
||||||
@@ -1029,7 +1027,7 @@ impl<T: BeaconChainTypes> SignatureVerifiedBlock<T> {
|
|||||||
|
|
||||||
/// As for `new` above but producing `BlockSlashInfo`.
|
/// As for `new` above but producing `BlockSlashInfo`.
|
||||||
pub fn check_slashable(
|
pub fn check_slashable(
|
||||||
block: AvailabilityPendingBlock<T::EthSpec>,
|
block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
||||||
block_root: Hash256,
|
block_root: Hash256,
|
||||||
chain: &BeaconChain<T>,
|
chain: &BeaconChain<T>,
|
||||||
) -> Result<Self, BlockSlashInfo<BlockError<T::EthSpec>>> {
|
) -> Result<Self, BlockSlashInfo<BlockError<T::EthSpec>>> {
|
||||||
@@ -1121,7 +1119,7 @@ impl<T: BeaconChainTypes> IntoExecutionPendingBlock<T> for SignatureVerifiedBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn block(&self) -> &SignedBeaconBlock<T::EthSpec> {
|
fn block(&self) -> &SignedBeaconBlock<T::EthSpec> {
|
||||||
self.block.as_block()
|
self.block.as_ref()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1152,28 +1150,6 @@ impl<T: BeaconChainTypes> IntoExecutionPendingBlock<T> for Arc<SignedBeaconBlock
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: BeaconChainTypes> IntoExecutionPendingBlock<T> for AvailabilityPendingBlock<T::EthSpec> {
|
|
||||||
/// Verifies the `SignedBeaconBlock` by first transforming it into a `SignatureVerifiedBlock`
|
|
||||||
/// and then using that implementation of `IntoExecutionPendingBlock` to complete verification.
|
|
||||||
fn into_execution_pending_block_slashable(
|
|
||||||
self,
|
|
||||||
block_root: Hash256,
|
|
||||||
chain: &Arc<BeaconChain<T>>,
|
|
||||||
notify_execution_layer: NotifyExecutionLayer,
|
|
||||||
) -> Result<ExecutionPendingBlock<T>, BlockSlashInfo<BlockError<T::EthSpec>>> {
|
|
||||||
// Perform an early check to prevent wasting time on irrelevant blocks.
|
|
||||||
let block_root = check_block_relevancy(self.as_block(), block_root, chain)
|
|
||||||
.map_err(|e| BlockSlashInfo::SignatureNotChecked(self.signed_block_header(), e))?;
|
|
||||||
|
|
||||||
SignatureVerifiedBlock::check_slashable(self, block_root, chain)?
|
|
||||||
.into_execution_pending_block_slashable(block_root, chain, notify_execution_layer)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn block(&self) -> &SignedBeaconBlock<T::EthSpec> {
|
|
||||||
self.as_block()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: BeaconChainTypes> ExecutionPendingBlock<T> {
|
impl<T: BeaconChainTypes> ExecutionPendingBlock<T> {
|
||||||
/// Instantiates `Self`, a wrapper that indicates that the given `block` is fully valid. See
|
/// Instantiates `Self`, a wrapper that indicates that the given `block` is fully valid. See
|
||||||
/// the struct-level documentation for more information.
|
/// the struct-level documentation for more information.
|
||||||
@@ -1183,7 +1159,7 @@ impl<T: BeaconChainTypes> ExecutionPendingBlock<T> {
|
|||||||
///
|
///
|
||||||
/// Returns an error if the block is invalid, or if the block was unable to be verified.
|
/// Returns an error if the block is invalid, or if the block was unable to be verified.
|
||||||
pub fn from_signature_verified_components(
|
pub fn from_signature_verified_components(
|
||||||
block: AvailabilityPendingBlock<T::EthSpec>,
|
block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
||||||
block_root: Hash256,
|
block_root: Hash256,
|
||||||
parent: PreProcessingSnapshot<T::EthSpec>,
|
parent: PreProcessingSnapshot<T::EthSpec>,
|
||||||
mut consensus_context: ConsensusContext<T::EthSpec>,
|
mut consensus_context: ConsensusContext<T::EthSpec>,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::blob_verification::{AvailabilityPendingBlock, AvailableBlock};
|
use crate::blob_verification::{AvailableBlock};
|
||||||
use crate::{
|
use crate::{
|
||||||
attester_cache::{CommitteeLengths, Error},
|
attester_cache::{CommitteeLengths, Error},
|
||||||
metrics,
|
metrics,
|
||||||
@@ -21,7 +21,7 @@ pub struct CacheItem<E: EthSpec> {
|
|||||||
* Values used to make the block available.
|
* Values used to make the block available.
|
||||||
*/
|
*/
|
||||||
block: Arc<SignedBeaconBlock<E>>,
|
block: Arc<SignedBeaconBlock<E>>,
|
||||||
blobs: Option<Arc<BlobsSidecar<E>>>,
|
blobs: Option<Arc<BlobSidecarList<E>>>,
|
||||||
proto_block: ProtoBlock,
|
proto_block: ProtoBlock,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,7 +160,7 @@ impl<E: EthSpec> EarlyAttesterCache<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the blobs, if `block_root` matches the cached item.
|
/// Returns the blobs, if `block_root` matches the cached item.
|
||||||
pub fn get_blobs(&self, block_root: Hash256) -> Option<Arc<BlobsSidecar<E>>> {
|
pub fn get_blobs(&self, block_root: Hash256) -> Option<Arc<BlobSidecarList<E>>> {
|
||||||
self.item
|
self.item
|
||||||
.read()
|
.read()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::blob_verification::{verify_data_availability, AvailabilityPendingBlock};
|
use crate::blob_verification::{verify_data_availability};
|
||||||
use crate::block_verification::{ExecutedBlock, IntoExecutionPendingBlock};
|
use crate::block_verification::{ExecutedBlock, IntoExecutionPendingBlock};
|
||||||
use crate::kzg_utils::validate_blob;
|
use crate::kzg_utils::validate_blob;
|
||||||
use crate::{BeaconChainError, BlockError};
|
use crate::{BeaconChainError, BeaconChainTypes, BlockError};
|
||||||
use eth2::reqwest::header::Entry;
|
use eth2::reqwest::header::Entry;
|
||||||
use kzg::{Kzg, KzgCommitment};
|
use kzg::{Kzg, KzgCommitment};
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
@@ -11,27 +11,29 @@ use std::future::Future;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use types::blob_sidecar::{BlobIdentifier, BlobSidecar};
|
use types::blob_sidecar::{BlobIdentifier, BlobSidecar};
|
||||||
use types::{EthSpec, Hash256};
|
use types::{EthSpec, Hash256};
|
||||||
|
use kzg::Error as KzgError;
|
||||||
|
|
||||||
pub enum BlobCacheError {
|
pub enum BlobCacheError {
|
||||||
DuplicateBlob(Hash256),
|
DuplicateBlob(Hash256),
|
||||||
|
Kzg(KzgError),
|
||||||
}
|
}
|
||||||
/// This cache contains
|
/// This cache contains
|
||||||
/// - blobs that have been gossip verified
|
/// - blobs that have been gossip verified
|
||||||
/// - commitments for blocks that have been gossip verified, but the commitments themselves
|
/// - commitments for blocks that have been gossip verified, but the commitments themselves
|
||||||
/// have not been verified against blobs
|
/// have not been verified against blobs
|
||||||
/// - blocks that have been fully verified and only require a data availability check
|
/// - blocks that have been fully verified and only require a data availability check
|
||||||
pub struct GossipBlobCache<T: EthSpec> {
|
pub struct GossipBlobCache<T: BeaconChainTypes> {
|
||||||
rpc_blob_cache: RwLock<HashMap<BlobIdentifier, Arc<BlobSidecar<T>>>>,
|
rpc_blob_cache: RwLock<HashMap<BlobIdentifier, Arc<BlobSidecar<T::EthSpec>>>>,
|
||||||
gossip_blob_cache: Mutex<HashMap<Hash256, GossipBlobCacheInner<T>>>,
|
gossip_blob_cache: Mutex<HashMap<Hash256, GossipBlobCacheInner<T>>>,
|
||||||
kzg: Kzg,
|
kzg: Kzg,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GossipBlobCacheInner<T: EthSpec> {
|
struct GossipBlobCacheInner<T: BeaconChainTypes> {
|
||||||
verified_blobs: Vec<Arc<BlobSidecar<T>>>,
|
verified_blobs: Vec<Arc<BlobSidecar<T::EthSpec>>>,
|
||||||
executed_block: Option<ExecutedBlock<T>>,
|
executed_block: Option<ExecutedBlock<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: EthSpec> GossipBlobCache<T> {
|
impl<T: BeaconChainTypes> GossipBlobCache<T> {
|
||||||
pub fn new(kzg: Kzg) -> Self {
|
pub fn new(kzg: Kzg) -> Self {
|
||||||
Self {
|
Self {
|
||||||
rpc_blob_cache: RwLock::new(HashMap::new()),
|
rpc_blob_cache: RwLock::new(HashMap::new()),
|
||||||
@@ -45,14 +47,14 @@ impl<T: EthSpec> GossipBlobCache<T> {
|
|||||||
/// cached, verify the block and import it.
|
/// cached, verify the block and import it.
|
||||||
///
|
///
|
||||||
/// This should only accept gossip verified blobs, so we should not have to worry about dupes.
|
/// This should only accept gossip verified blobs, so we should not have to worry about dupes.
|
||||||
pub fn put_blob(&self, blob: Arc<BlobSidecar<T>>) -> Result<(), BlobCacheError> {
|
pub fn put_blob(&self, blob: Arc<BlobSidecar<T::EthSpec>>) -> Result<(), BlobCacheError> {
|
||||||
// TODO(remove clones)
|
// TODO(remove clones)
|
||||||
let verified = validate_blob(
|
let verified = validate_blob::<T::EthSpec>(
|
||||||
&self.kzg,
|
&self.kzg,
|
||||||
blob.blob.clone(),
|
blob.blob.clone(),
|
||||||
blob.kzg_commitment.clone(),
|
blob.kzg_commitment.clone(),
|
||||||
blob.kzg_proof,
|
blob.kzg_proof,
|
||||||
)?;
|
).map_err(|e|BlobCacheError::Kzg(e))?;
|
||||||
|
|
||||||
if verified {
|
if verified {
|
||||||
let mut blob_cache = self.gossip_blob_cache.lock();
|
let mut blob_cache = self.gossip_blob_cache.lock();
|
||||||
@@ -85,22 +87,29 @@ impl<T: EthSpec> GossipBlobCache<T> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn put_block(&self, block: ExecutedBlock<T>) -> () {
|
pub fn put_block(&self, executed_block: ExecutedBlock<T>) -> Result<(), BlobCacheError> {
|
||||||
let mut guard = self.gossip_blob_cache.lock();
|
let mut guard = self.gossip_blob_cache.lock();
|
||||||
guard
|
guard
|
||||||
.entry(block.block_root)
|
.entry(executed_block.block_root)
|
||||||
.and_modify(|cache| {
|
.and_modify(|cache| {
|
||||||
if cache.verified_blobs == block.block.message_eip4844().blob_kzg_commitments() {
|
if let Ok(block) = executed_block.block.message_eip4844() {
|
||||||
|
let verified_commitments_vec: Vec<_> = cache.verified_blobs.iter().map(|blob|blob.kzg_commitment).collect();
|
||||||
|
let verified_commitments = VariableList::from(verified_commitments_vec);
|
||||||
|
if verified_commitments == block.body.blob_kzg_commitments {
|
||||||
// send to reprocessing queue ?
|
// send to reprocessing queue ?
|
||||||
} else if let Some(dup) = cache.executed_block.insert(block) {
|
|
||||||
// return error
|
|
||||||
} else {
|
} else {
|
||||||
// log that we cached it
|
let _ = cache.executed_block.insert(executed_block);
|
||||||
|
// log that we cached
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// log error
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.or_insert(GossipBlobCacheInner {
|
.or_insert(GossipBlobCacheInner {
|
||||||
verified_blobs: vec![],
|
verified_blobs: vec![],
|
||||||
executed_block: Some(block),
|
executed_block: Some(executed_block),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use test_random_derive::TestRandom;
|
|||||||
use tree_hash_derive::TreeHash;
|
use tree_hash_derive::TreeHash;
|
||||||
|
|
||||||
/// Container of the data that identifies an individual blob.
|
/// Container of the data that identifies an individual blob.
|
||||||
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
|
#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct BlobIdentifier {
|
pub struct BlobIdentifier {
|
||||||
pub block_root: Hash256,
|
pub block_root: Hash256,
|
||||||
pub index: u64,
|
pub index: u64,
|
||||||
|
|||||||
Reference in New Issue
Block a user