mirror of
https://github.com/sigp/lighthouse.git
synced 2026-07-01 20:04:41 +00:00
Moar Progress
This commit is contained in:
@@ -1135,6 +1135,23 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the full block at the given root, if it's available in the database.
|
||||||
|
///
|
||||||
|
/// Should always return a full block for pre-merge and post-gloas blocks.
|
||||||
|
/// An
|
||||||
|
pub fn get_full_block(
|
||||||
|
&self,
|
||||||
|
block_root: &Hash256,
|
||||||
|
) -> Result<Option<SignedBeaconBlock<T::EthSpec>>, Error> {
|
||||||
|
match self.store.try_get_full_block(block_root)? {
|
||||||
|
Some(DatabaseBlock::Full(block)) => Ok(Some(block)),
|
||||||
|
Some(DatabaseBlock::Blinded(_)) => {
|
||||||
|
Err(Error::ExecutionPayloadMissingFromDatabase(*block_root))
|
||||||
|
}
|
||||||
|
None => Ok(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the block at the given root, if any.
|
/// Returns the block at the given root, if any.
|
||||||
///
|
///
|
||||||
/// ## Errors
|
/// ## Errors
|
||||||
|
|||||||
@@ -708,7 +708,8 @@ pub struct SignatureVerifiedBlock<T: BeaconChainTypes> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Used to await the result of executing payload with an EE.
|
/// Used to await the result of executing payload with an EE.
|
||||||
type PayloadVerificationHandle = JoinHandle<Option<Result<PayloadVerificationOutcome, BlockError>>>;
|
pub type PayloadVerificationHandle =
|
||||||
|
JoinHandle<Option<Result<PayloadVerificationOutcome, BlockError>>>;
|
||||||
|
|
||||||
/// A wrapper around a `SignedBeaconBlock` that indicates that this block is fully verified and
|
/// A wrapper around a `SignedBeaconBlock` that indicates that this block is fully verified and
|
||||||
/// ready to import into the `BeaconChain`. The validation includes:
|
/// ready to import into the `BeaconChain`. The validation includes:
|
||||||
|
|||||||
@@ -4,48 +4,50 @@
|
|||||||
//! diagram below).
|
//! diagram below).
|
||||||
//!
|
//!
|
||||||
//! ```ignore
|
//! ```ignore
|
||||||
//! START
|
//! START
|
||||||
//! |
|
//! |
|
||||||
//! ▼
|
//! ▼
|
||||||
//! SignedExecutionPayloadEnvelope
|
//! SignedExecutionPayloadEnvelope
|
||||||
//! |
|
//! |
|
||||||
//! |---------------
|
//! |---------------
|
||||||
//! | |
|
//! | |
|
||||||
//! | ▼
|
//! | ▼
|
||||||
//! | GossipVerifiedEnvelope
|
//! | GossipVerifiedEnvelope
|
||||||
//! | |
|
//! | |
|
||||||
//! |---------------
|
//! |---------------
|
||||||
//! |
|
//! |
|
||||||
//! ▼
|
//! ▼
|
||||||
//! ExecutionPendingEnvelope
|
//! SignatureVerifiedEnvelope
|
||||||
//! |
|
//! |
|
||||||
//! await
|
//! ▼
|
||||||
//! |
|
//! ExecutionPendingEnvelope
|
||||||
//! ▼
|
//! |
|
||||||
//! END
|
//! await
|
||||||
|
//! |
|
||||||
|
//! ▼
|
||||||
|
//! END
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use crate::block_verification::{PayloadVerificationHandle, PayloadVerificationOutcome};
|
|
||||||
use crate::data_availability_checker::MaybeAvailableEnvelope;
|
|
||||||
use crate::envelope_verification_types::EnvelopeImportData;
|
|
||||||
use crate::execution_payload::PayloadNotifier;
|
|
||||||
use crate::NotifyExecutionLayer;
|
use crate::NotifyExecutionLayer;
|
||||||
|
use crate::block_verification::{PayloadVerificationHandle, PayloadVerificationOutcome};
|
||||||
|
use crate::envelope_verification_types::{EnvelopeImportData, MaybeAvailableEnvelope};
|
||||||
|
use crate::execution_payload::PayloadNotifier;
|
||||||
use crate::{BeaconChain, BeaconChainError, BeaconChainTypes};
|
use crate::{BeaconChain, BeaconChainError, BeaconChainTypes};
|
||||||
use derivative::Derivative;
|
use derivative::Derivative;
|
||||||
use safe_arith::ArithError;
|
use safe_arith::ArithError;
|
||||||
use slot_clock::SlotClock;
|
use slot_clock::SlotClock;
|
||||||
use state_processing::envelope_processing::{envelope_processing, EnvelopeProcessingError};
|
use state_processing::envelope_processing::{EnvelopeProcessingError, envelope_processing};
|
||||||
use state_processing::per_block_processing::compute_timestamp_at_slot;
|
use state_processing::per_block_processing::compute_timestamp_at_slot;
|
||||||
use state_processing::{BlockProcessingError, VerifySignatures};
|
use state_processing::{BlockProcessingError, VerifySignatures};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tree_hash::TreeHash;
|
use tree_hash::TreeHash;
|
||||||
use types::{
|
use types::{
|
||||||
BeaconState, BeaconStateError, EthSpec, ExecutionBlockHash, Hash256, SignedBlindedBeaconBlock,
|
BeaconState, BeaconStateError, ExecutionBlockHash, Hash256, SignedBeaconBlock,
|
||||||
SignedExecutionPayloadEnvelope,
|
SignedExecutionPayloadEnvelope, Slot,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO(EIP7732): don't use this redefinition..
|
// TODO(gloas): don't use this redefinition..
|
||||||
macro_rules! envelope_verify {
|
macro_rules! envelope_verify {
|
||||||
($condition: expr, $result: expr) => {
|
($condition: expr, $result: expr) => {
|
||||||
if !$condition {
|
if !$condition {
|
||||||
@@ -54,7 +56,7 @@ macro_rules! envelope_verify {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum EnvelopeError {
|
pub enum EnvelopeError {
|
||||||
/// The envelope's block root is unknown.
|
/// The envelope's block root is unknown.
|
||||||
BlockRootUnknown {
|
BlockRootUnknown {
|
||||||
@@ -117,11 +119,13 @@ pub enum EnvelopeError {
|
|||||||
state: Hash256,
|
state: Hash256,
|
||||||
envelope: Hash256,
|
envelope: Hash256,
|
||||||
},
|
},
|
||||||
// The payload was withheld but the block hash
|
// The slot doesn't match the parent block
|
||||||
// matched the committed bid
|
SlotMismatch {
|
||||||
PayloadWithheldBlockHashMismatch,
|
parent_block: Slot,
|
||||||
|
envelope: Slot,
|
||||||
|
},
|
||||||
// Some Beacon Chain Error
|
// Some Beacon Chain Error
|
||||||
BeaconChainError(BeaconChainError),
|
BeaconChainError(Arc<BeaconChainError>),
|
||||||
// Some Beacon State error
|
// Some Beacon State error
|
||||||
BeaconStateError(BeaconStateError),
|
BeaconStateError(BeaconStateError),
|
||||||
// Some ArithError
|
// Some ArithError
|
||||||
@@ -132,7 +136,7 @@ pub enum EnvelopeError {
|
|||||||
|
|
||||||
impl From<BeaconChainError> for EnvelopeError {
|
impl From<BeaconChainError> for EnvelopeError {
|
||||||
fn from(e: BeaconChainError) -> Self {
|
fn from(e: BeaconChainError) -> Self {
|
||||||
EnvelopeError::BeaconChainError(e)
|
EnvelopeError::BeaconChainError(Arc::new(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +170,7 @@ impl From<EnvelopeProcessingError> for EnvelopeError {
|
|||||||
#[derivative(Debug(bound = "T: BeaconChainTypes"))]
|
#[derivative(Debug(bound = "T: BeaconChainTypes"))]
|
||||||
pub struct GossipVerifiedEnvelope<T: BeaconChainTypes> {
|
pub struct GossipVerifiedEnvelope<T: BeaconChainTypes> {
|
||||||
pub signed_envelope: Arc<SignedExecutionPayloadEnvelope<T::EthSpec>>,
|
pub signed_envelope: Arc<SignedExecutionPayloadEnvelope<T::EthSpec>>,
|
||||||
pub parent_block: Arc<SignedBlindedBeaconBlock<T::EthSpec>>,
|
pub parent_block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
||||||
pub pre_state: Box<BeaconState<T::EthSpec>>,
|
pub pre_state: Box<BeaconState<T::EthSpec>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +183,7 @@ impl<T: BeaconChainTypes> GossipVerifiedEnvelope<T> {
|
|||||||
let payload = envelope.payload();
|
let payload = envelope.payload();
|
||||||
let block_root = envelope.beacon_block_root();
|
let block_root = envelope.beacon_block_root();
|
||||||
|
|
||||||
// TODO(EIP7732): this check would fail if the block didn't pass validation right?
|
// TODO(gloas): this check would fail if the block didn't pass validation right?
|
||||||
|
|
||||||
// check that we've seen the parent block of this envelope
|
// check that we've seen the parent block of this envelope
|
||||||
let fork_choice_read_lock = chain.canonical_head.fork_choice_read_lock();
|
let fork_choice_read_lock = chain.canonical_head.fork_choice_read_lock();
|
||||||
@@ -189,7 +193,7 @@ impl<T: BeaconChainTypes> GossipVerifiedEnvelope<T> {
|
|||||||
drop(fork_choice_read_lock);
|
drop(fork_choice_read_lock);
|
||||||
|
|
||||||
let parent_block = chain
|
let parent_block = chain
|
||||||
.get_blinded_block(&block_root)?
|
.get_full_block(&block_root)?
|
||||||
.ok_or_else(|| EnvelopeError::from(BeaconChainError::MissingBeaconBlock(block_root)))
|
.ok_or_else(|| EnvelopeError::from(BeaconChainError::MissingBeaconBlock(block_root)))
|
||||||
.map(Arc::new)?;
|
.map(Arc::new)?;
|
||||||
let execution_bid = &parent_block
|
let execution_bid = &parent_block
|
||||||
@@ -198,10 +202,17 @@ impl<T: BeaconChainTypes> GossipVerifiedEnvelope<T> {
|
|||||||
.signed_execution_bid()?
|
.signed_execution_bid()?
|
||||||
.message;
|
.message;
|
||||||
|
|
||||||
// TODO(EIP7732): check we're within the bounds of the slot (probably)
|
// TODO(gloas): check we're within the bounds of the slot (probably)
|
||||||
|
// I think a timestamp check like this is on the beacon block but need to check.
|
||||||
|
if envelope.slot() != parent_block.slot() {
|
||||||
|
return Err(EnvelopeError::SlotMismatch {
|
||||||
|
parent_block: parent_block.slot(),
|
||||||
|
envelope: envelope.slot(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(EIP7732): check that we haven't seen another valid `SignedExecutionPayloadEnvelope`
|
// TODO(gloas): check that we haven't seen another valid `SignedExecutionPayloadEnvelope`
|
||||||
// for this block root from this builder
|
// for this block root from this builder - envelope status table check
|
||||||
|
|
||||||
// builder index matches committed bid
|
// builder index matches committed bid
|
||||||
if envelope.builder_index() != execution_bid.builder_index {
|
if envelope.builder_index() != execution_bid.builder_index {
|
||||||
@@ -211,15 +222,21 @@ impl<T: BeaconChainTypes> GossipVerifiedEnvelope<T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// if payload is withheld, the block hash should not match the committed bid
|
// the block hash should match the block hash of the execution bid
|
||||||
if !envelope.payload_withheld() && payload.block_hash() == execution_bid.block_hash {
|
if payload.block_hash() != execution_bid.block_hash {
|
||||||
return Err(EnvelopeError::PayloadWithheldBlockHashMismatch);
|
return Err(EnvelopeError::BlockHashMismatch {
|
||||||
|
committed_bid: execution_bid.block_hash,
|
||||||
|
envelope: payload.block_hash(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(gloas): expensive load here.. check this
|
||||||
let parent_state = chain
|
let parent_state = chain
|
||||||
|
// TODO(gloas): may need a get_block_state to get the right state here..
|
||||||
.get_state(
|
.get_state(
|
||||||
&parent_block.message().state_root(),
|
&parent_block.message().state_root(),
|
||||||
Some(parent_block.slot()),
|
Some(parent_block.slot()),
|
||||||
|
true,
|
||||||
)?
|
)?
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
EnvelopeError::from(BeaconChainError::MissingBeaconState(
|
EnvelopeError::from(BeaconChainError::MissingBeaconState(
|
||||||
@@ -271,15 +288,24 @@ impl<T: BeaconChainTypes> IntoExecutionPendingEnvelope<T> for GossipVerifiedEnve
|
|||||||
// verify signature already done
|
// verify signature already done
|
||||||
let mut state = *self.pre_state;
|
let mut state = *self.pre_state;
|
||||||
|
|
||||||
// setting state.latest_block_header happens in envelope_processing
|
// all state modifications are done in envelope_processing (called at the bottom of this function)
|
||||||
|
// so here perform the consistency check with the beacon block on a copy of the latest block header
|
||||||
|
// and let it be modified later in envelope_processing
|
||||||
|
let previous_state_root = state.canonical_root()?;
|
||||||
|
if state.latest_block_header().state_root == Hash256::default() {
|
||||||
|
let mut copy_of_latest_block_header = state.latest_block_header().clone();
|
||||||
|
copy_of_latest_block_header.state_root = previous_state_root;
|
||||||
|
|
||||||
// Verify consistency with the beacon block
|
// Verify consistency with the beacon block
|
||||||
if !envelope.tree_hash_root() == state.latest_block_header().tree_hash_root() {
|
if !envelope.beacon_block_root() == copy_of_latest_block_header.tree_hash_root() {
|
||||||
return Err(EnvelopeError::LatestBlockHeaderMismatch {
|
return Err(EnvelopeError::LatestBlockHeaderMismatch {
|
||||||
envelope_root: envelope.tree_hash_root(),
|
envelope_root: envelope.beacon_block_root(),
|
||||||
block_header_root: state.latest_block_header().tree_hash_root(),
|
block_header_root: copy_of_latest_block_header.tree_hash_root(),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// the check about the slots matching is already done in the GossipVerifiedEnvelope
|
||||||
|
|
||||||
// Verify consistency with the committed bid
|
// Verify consistency with the committed bid
|
||||||
let committed_bid = state.latest_execution_bid()?;
|
let committed_bid = state.latest_execution_bid()?;
|
||||||
@@ -293,79 +319,68 @@ impl<T: BeaconChainTypes> IntoExecutionPendingEnvelope<T> for GossipVerifiedEnve
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if !envelope.payload_withheld() {
|
// Verify the withdrawals root
|
||||||
// Verify the withdrawals root
|
envelope_verify!(
|
||||||
envelope_verify!(
|
payload.withdrawals()?.tree_hash_root() == *state.latest_withdrawals_root()?,
|
||||||
payload.withdrawals()?.tree_hash_root() == state.latest_withdrawals_root()?,
|
EnvelopeError::WithdrawalsRootMismatch {
|
||||||
EnvelopeError::WithdrawalsRootMismatch {
|
state: *state.latest_withdrawals_root()?,
|
||||||
state: state.latest_withdrawals_root()?,
|
envelope: payload.withdrawals()?.tree_hash_root(),
|
||||||
envelope: payload.withdrawals()?.tree_hash_root(),
|
}
|
||||||
}
|
.into()
|
||||||
.into()
|
);
|
||||||
);
|
|
||||||
|
|
||||||
// Verify the gas limit
|
// Verify the gas limit
|
||||||
envelope_verify!(
|
envelope_verify!(
|
||||||
payload.gas_limit() == committed_bid.gas_limit,
|
payload.gas_limit() == committed_bid.gas_limit,
|
||||||
EnvelopeError::GasLimitMismatch {
|
EnvelopeError::GasLimitMismatch {
|
||||||
committed_bid: committed_bid.gas_limit,
|
committed_bid: committed_bid.gas_limit,
|
||||||
envelope: payload.gas_limit(),
|
envelope: payload.gas_limit(),
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
);
|
);
|
||||||
// Verify the block hash
|
// Verify the block hash already done in the GossipVerifiedEnvelope
|
||||||
envelope_verify!(
|
|
||||||
committed_bid.block_hash == payload.block_hash(),
|
|
||||||
EnvelopeError::BlockHashMismatch {
|
|
||||||
committed_bid: committed_bid.block_hash,
|
|
||||||
envelope: payload.block_hash(),
|
|
||||||
}
|
|
||||||
.into()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Verify consistency of the parent hash with respect to the previous execution payload
|
// Verify consistency of the parent hash with respect to the previous execution payload
|
||||||
envelope_verify!(
|
envelope_verify!(
|
||||||
payload.parent_hash() == state.latest_block_hash()?,
|
payload.parent_hash() == *state.latest_block_hash()?,
|
||||||
EnvelopeError::ParentHashMismatch {
|
EnvelopeError::ParentHashMismatch {
|
||||||
state: state.latest_block_hash()?,
|
state: *state.latest_block_hash()?,
|
||||||
envelope: payload.parent_hash(),
|
envelope: payload.parent_hash(),
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
);
|
);
|
||||||
|
|
||||||
// Verify prev_randao
|
// Verify prev_randao
|
||||||
envelope_verify!(
|
envelope_verify!(
|
||||||
payload.prev_randao() == *state.get_randao_mix(state.current_epoch())?,
|
payload.prev_randao() == *state.get_randao_mix(state.current_epoch())?,
|
||||||
EnvelopeError::PrevRandaoMismatch {
|
EnvelopeError::PrevRandaoMismatch {
|
||||||
state: *state.get_randao_mix(state.current_epoch())?,
|
state: *state.get_randao_mix(state.current_epoch())?,
|
||||||
envelope: payload.prev_randao(),
|
envelope: payload.prev_randao(),
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
);
|
);
|
||||||
|
|
||||||
// Verify the timestamp
|
// Verify the timestamp
|
||||||
let state_timestamp =
|
let state_timestamp = compute_timestamp_at_slot(&state, state.slot(), chain.spec.as_ref())?;
|
||||||
compute_timestamp_at_slot(&state, state.slot(), chain.spec.as_ref())?;
|
envelope_verify!(
|
||||||
envelope_verify!(
|
payload.timestamp() == state_timestamp,
|
||||||
payload.timestamp() == state_timestamp,
|
EnvelopeError::TimestampMismatch {
|
||||||
EnvelopeError::TimestampMismatch {
|
state: state_timestamp,
|
||||||
state: state_timestamp,
|
envelope: payload.timestamp(),
|
||||||
envelope: payload.timestamp(),
|
}
|
||||||
}
|
.into()
|
||||||
.into()
|
);
|
||||||
);
|
|
||||||
|
|
||||||
// Verify the commitments are under limit
|
// Verify the commitments are under limit
|
||||||
envelope_verify!(
|
let max_blobs = chain.spec.max_blobs_per_block(state.current_epoch()) as usize;
|
||||||
envelope.blob_kzg_commitments().len()
|
envelope_verify!(
|
||||||
<= T::EthSpec::max_blob_commitments_per_block(),
|
envelope.blob_kzg_commitments().len() <= max_blobs,
|
||||||
EnvelopeError::BlobLimitExceeded {
|
EnvelopeError::BlobLimitExceeded {
|
||||||
max: T::EthSpec::max_blob_commitments_per_block(),
|
max: max_blobs,
|
||||||
envelope: envelope.blob_kzg_commitments().len(),
|
envelope: envelope.blob_kzg_commitments().len(),
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
// Verify the execution payload is valid
|
// Verify the execution payload is valid
|
||||||
let payload_notifier =
|
let payload_notifier =
|
||||||
@@ -375,7 +390,7 @@ impl<T: BeaconChainTypes> IntoExecutionPendingEnvelope<T> for GossipVerifiedEnve
|
|||||||
|
|
||||||
let payload_verification_future = async move {
|
let payload_verification_future = async move {
|
||||||
let chain = payload_notifier.chain.clone();
|
let chain = payload_notifier.chain.clone();
|
||||||
// TODO:(EIP7732): timing
|
// TODO:(gloas): timing
|
||||||
if let Some(started_execution) = chain.slot_clock.now_duration() {
|
if let Some(started_execution) = chain.slot_clock.now_duration() {
|
||||||
chain.block_times_cache.write().set_time_started_execution(
|
chain.block_times_cache.write().set_time_started_execution(
|
||||||
block_root,
|
block_root,
|
||||||
@@ -410,7 +425,7 @@ impl<T: BeaconChainTypes> IntoExecutionPendingEnvelope<T> for GossipVerifiedEnve
|
|||||||
&chain.spec,
|
&chain.spec,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// TODO(EIP7732): if verify
|
// TODO(gloas): if verify
|
||||||
envelope_verify!(
|
envelope_verify!(
|
||||||
state.canonical_root()? == envelope.state_root(),
|
state.canonical_root()? == envelope.state_root(),
|
||||||
EnvelopeError::InvalidStateRoot {
|
EnvelopeError::InvalidStateRoot {
|
||||||
@@ -421,7 +436,7 @@ impl<T: BeaconChainTypes> IntoExecutionPendingEnvelope<T> for GossipVerifiedEnve
|
|||||||
|
|
||||||
Ok(ExecutionPendingEnvelope {
|
Ok(ExecutionPendingEnvelope {
|
||||||
signed_envelope: MaybeAvailableEnvelope::AvailabilityPending {
|
signed_envelope: MaybeAvailableEnvelope::AvailabilityPending {
|
||||||
block_root,
|
block_hash: payload.block_hash(),
|
||||||
envelope: signed_envelope,
|
envelope: signed_envelope,
|
||||||
},
|
},
|
||||||
import_data: EnvelopeImportData {
|
import_data: EnvelopeImportData {
|
||||||
@@ -442,8 +457,8 @@ impl<T: BeaconChainTypes> IntoExecutionPendingEnvelope<T>
|
|||||||
chain: &Arc<BeaconChain<T>>,
|
chain: &Arc<BeaconChain<T>>,
|
||||||
notify_execution_layer: NotifyExecutionLayer,
|
notify_execution_layer: NotifyExecutionLayer,
|
||||||
) -> Result<ExecutionPendingEnvelope<T>, EnvelopeError> {
|
) -> Result<ExecutionPendingEnvelope<T>, EnvelopeError> {
|
||||||
// TODO(EIP7732): figure out how this should be refactored..
|
// TODO(gloas): figure out how this should be refactored..
|
||||||
GossipVerifiedEnvelope::new(self, chain)?
|
GossipVerifiedEnvelope::new(self, chain)?
|
||||||
.into_execution_pending_envelope(chain, notify_execution_layer)
|
.into_execution_pending_envelope(chain, notify_execution_layer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,136 +1,30 @@
|
|||||||
use crate::data_availability_checker::{AvailableEnvelope, MaybeAvailableEnvelope};
|
|
||||||
use crate::PayloadVerificationOutcome;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use types::{
|
use types::{
|
||||||
BeaconState, BlobIdentifier, EthSpec, Hash256, SignedBlindedBeaconBlock,
|
BeaconState, ChainSpec, DataColumnSidecarList, EthSpec, ExecutionBlockHash, Hash256,
|
||||||
SignedExecutionPayloadEnvelope,
|
SignedBeaconBlock, SignedExecutionPayloadEnvelope,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A block that has completed all pre-deneb block processing checks including verification
|
|
||||||
/// by an EL client **and** has all requisite blob data to be imported into fork choice.
|
|
||||||
#[derive(PartialEq)]
|
|
||||||
pub struct AvailableExecutedEnvelope<E: EthSpec> {
|
|
||||||
pub envelope: AvailableEnvelope<E>,
|
|
||||||
pub import_data: EnvelopeImportData<E>,
|
|
||||||
pub payload_verification_outcome: PayloadVerificationOutcome,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E: EthSpec> AvailableExecutedEnvelope<E> {
|
|
||||||
pub fn new(
|
|
||||||
envelope: AvailableEnvelope<E>,
|
|
||||||
import_data: EnvelopeImportData<E>,
|
|
||||||
payload_verification_outcome: PayloadVerificationOutcome,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
envelope,
|
|
||||||
import_data,
|
|
||||||
payload_verification_outcome,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_all_blob_ids(&self) -> Vec<BlobIdentifier> {
|
|
||||||
let num_blobs_expected = self
|
|
||||||
.envelope
|
|
||||||
.envelope()
|
|
||||||
.message()
|
|
||||||
.blob_kzg_commitments()
|
|
||||||
.len();
|
|
||||||
let mut blob_ids = Vec::with_capacity(num_blobs_expected);
|
|
||||||
for i in 0..num_blobs_expected {
|
|
||||||
blob_ids.push(BlobIdentifier {
|
|
||||||
block_root: self.import_data.block_root,
|
|
||||||
index: i as u64,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
blob_ids
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub struct EnvelopeImportData<E: EthSpec> {
|
pub struct EnvelopeImportData<E: EthSpec> {
|
||||||
pub block_root: Hash256,
|
pub block_root: Hash256,
|
||||||
pub parent_block: Arc<SignedBlindedBeaconBlock<E>>,
|
pub parent_block: Arc<SignedBeaconBlock<E>>,
|
||||||
pub post_state: Box<BeaconState<E>>,
|
pub post_state: Box<BeaconState<E>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AvailabilityPendingExecutedEnvelope<E: EthSpec> {
|
#[derive(Debug)]
|
||||||
pub envelope: Arc<SignedExecutionPayloadEnvelope<E>>,
|
#[allow(dead_code)]
|
||||||
pub import_data: EnvelopeImportData<E>,
|
pub struct AvailableEnvelope<E: EthSpec> {
|
||||||
pub payload_verification_outcome: PayloadVerificationOutcome,
|
block_hash: ExecutionBlockHash,
|
||||||
|
envelope: Arc<SignedExecutionPayloadEnvelope<E>>,
|
||||||
|
columns: DataColumnSidecarList<E>,
|
||||||
|
/// Timestamp at which this block first became available (UNIX timestamp, time since 1970).
|
||||||
|
columns_available_timestamp: Option<std::time::Duration>,
|
||||||
|
pub spec: Arc<ChainSpec>,
|
||||||
}
|
}
|
||||||
|
pub enum MaybeAvailableEnvelope<E: EthSpec> {
|
||||||
impl<E: EthSpec> AvailabilityPendingExecutedEnvelope<E> {
|
Available(AvailableEnvelope<E>),
|
||||||
pub fn new(
|
AvailabilityPending {
|
||||||
|
block_hash: ExecutionBlockHash,
|
||||||
envelope: Arc<SignedExecutionPayloadEnvelope<E>>,
|
envelope: Arc<SignedExecutionPayloadEnvelope<E>>,
|
||||||
import_data: EnvelopeImportData<E>,
|
},
|
||||||
payload_verification_outcome: PayloadVerificationOutcome,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
envelope,
|
|
||||||
import_data,
|
|
||||||
payload_verification_outcome,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_envelope(&self) -> &SignedExecutionPayloadEnvelope<E> {
|
|
||||||
self.envelope.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn num_blobs_expected(&self) -> usize {
|
|
||||||
self.envelope.message().blob_kzg_commitments().len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An envelope that has gone through all envelope processing checks including envelope processing
|
|
||||||
/// and execution by an EL client. This block hasn't necessarily completed data availability checks.
|
|
||||||
///
|
|
||||||
///
|
|
||||||
/// It contains 2 variants:
|
|
||||||
/// 1. `Available`: This envelope has been executed and also contains all data to consider it a
|
|
||||||
/// fully available envelope.
|
|
||||||
/// 2. `AvailabilityPending`: This envelope hasn't received all required blobs to consider it a
|
|
||||||
/// fully available envelope.
|
|
||||||
pub enum ExecutedEnvelope<E: EthSpec> {
|
|
||||||
Available(AvailableExecutedEnvelope<E>),
|
|
||||||
AvailabilityPending(AvailabilityPendingExecutedEnvelope<E>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E: EthSpec> ExecutedEnvelope<E> {
|
|
||||||
pub fn new(
|
|
||||||
envelope: MaybeAvailableEnvelope<E>,
|
|
||||||
import_data: EnvelopeImportData<E>,
|
|
||||||
payload_verification_outcome: PayloadVerificationOutcome,
|
|
||||||
) -> Self {
|
|
||||||
match envelope {
|
|
||||||
MaybeAvailableEnvelope::Available(available_envelope) => {
|
|
||||||
Self::Available(AvailableExecutedEnvelope::new(
|
|
||||||
available_envelope,
|
|
||||||
import_data,
|
|
||||||
payload_verification_outcome,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
MaybeAvailableEnvelope::AvailabilityPending {
|
|
||||||
block_root: _,
|
|
||||||
envelope,
|
|
||||||
} => Self::AvailabilityPending(AvailabilityPendingExecutedEnvelope::new(
|
|
||||||
envelope,
|
|
||||||
import_data,
|
|
||||||
payload_verification_outcome,
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_envelope(&self) -> &SignedExecutionPayloadEnvelope<E> {
|
|
||||||
match self {
|
|
||||||
Self::Available(available) => available.envelope.envelope(),
|
|
||||||
Self::AvailabilityPending(pending) => pending.envelope.as_ref(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn block_root(&self) -> Hash256 {
|
|
||||||
match self {
|
|
||||||
Self::Available(available) => available.import_data.block_root,
|
|
||||||
Self::AvailabilityPending(pending) => pending.import_data.block_root,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -148,6 +148,7 @@ pub enum BeaconChainError {
|
|||||||
EngineGetCapabilititesFailed(Box<execution_layer::Error>),
|
EngineGetCapabilititesFailed(Box<execution_layer::Error>),
|
||||||
ExecutionLayerGetBlockByNumberFailed(Box<execution_layer::Error>),
|
ExecutionLayerGetBlockByNumberFailed(Box<execution_layer::Error>),
|
||||||
ExecutionLayerGetBlockByHashFailed(Box<execution_layer::Error>),
|
ExecutionLayerGetBlockByHashFailed(Box<execution_layer::Error>),
|
||||||
|
ExecutionPayloadMissingFromDatabase(Hash256),
|
||||||
BlockHashMissingFromExecutionLayer(ExecutionBlockHash),
|
BlockHashMissingFromExecutionLayer(ExecutionBlockHash),
|
||||||
InconsistentPayloadReconstructed {
|
InconsistentPayloadReconstructed {
|
||||||
slot: Slot,
|
slot: Slot,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
BeaconChain, BeaconChainError, BeaconChainTypes, BlockError, BlockProductionError,
|
BeaconChain, BeaconChainError, BeaconChainTypes, BlockError, BlockProductionError,
|
||||||
ExecutionPayloadError,
|
EnvelopeError, ExecutionPayloadError,
|
||||||
};
|
};
|
||||||
use execution_layer::{
|
use execution_layer::{
|
||||||
BlockProposalContents, BlockProposalContentsType, BuilderParams, NewPayloadRequest,
|
BlockProposalContents, BlockProposalContentsType, BuilderParams, NewPayloadRequest,
|
||||||
@@ -108,6 +108,16 @@ impl<T: BeaconChainTypes> PayloadNotifier<T> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_envelope(
|
||||||
|
_chain: Arc<BeaconChain<T>>,
|
||||||
|
_envelope: ExecutionPayloadEnvelopeRef<T::EthSpec>,
|
||||||
|
_notify_execution_layer: NotifyExecutionLayer,
|
||||||
|
) -> Result<Self, EnvelopeError> {
|
||||||
|
todo!(
|
||||||
|
"this isn't a real method but something like this will be needed after refactoring this a bit"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn notify_new_payload(self) -> Result<PayloadVerificationStatus, BlockError> {
|
pub async fn notify_new_payload(self) -> Result<PayloadVerificationStatus, BlockError> {
|
||||||
if let Some(precomputed_status) = self.payload_verification_status {
|
if let Some(precomputed_status) = self.payload_verification_status {
|
||||||
Ok(precomputed_status)
|
Ok(precomputed_status)
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ pub use block_verification_types::AvailabilityPendingExecutedBlock;
|
|||||||
pub use block_verification_types::ExecutedBlock;
|
pub use block_verification_types::ExecutedBlock;
|
||||||
pub use canonical_head::{CachedHead, CanonicalHead, CanonicalHeadRwLock};
|
pub use canonical_head::{CachedHead, CanonicalHead, CanonicalHeadRwLock};
|
||||||
pub use custody_context::CustodyContext;
|
pub use custody_context::CustodyContext;
|
||||||
|
pub use envelope_verification::{EnvelopeError, GossipVerifiedEnvelope};
|
||||||
pub use events::ServerSentEventHandler;
|
pub use events::ServerSentEventHandler;
|
||||||
pub use execution_layer::EngineState;
|
pub use execution_layer::EngineState;
|
||||||
pub use execution_payload::NotifyExecutionLayer;
|
pub use execution_payload::NotifyExecutionLayer;
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
|
use crate::BlockProcessingError;
|
||||||
|
use crate::VerifySignatures;
|
||||||
use crate::per_block_processing::process_operations::{
|
use crate::per_block_processing::process_operations::{
|
||||||
process_consolidation_requests, process_deposit_requests, process_withdrawal_requests,
|
process_consolidation_requests, process_deposit_requests, process_withdrawal_requests,
|
||||||
};
|
};
|
||||||
use crate::BlockProcessingError;
|
use types::{
|
||||||
use crate::VerifySignatures;
|
BeaconState, BeaconStateError, ChainSpec, EthSpec, Hash256, SignedExecutionPayloadEnvelope,
|
||||||
use types::{BeaconState, BeaconStateError, ChainSpec, EthSpec, Hash256, SignedExecutionPayloadEnvelope};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum EnvelopeProcessingError {
|
pub enum EnvelopeProcessingError {
|
||||||
@@ -47,8 +49,6 @@ pub fn envelope_processing<E: EthSpec>(
|
|||||||
state.latest_block_header_mut().state_root = previous_state_root;
|
state.latest_block_header_mut().state_root = previous_state_root;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify consistency with the beacon block
|
|
||||||
|
|
||||||
// process electra operations
|
// process electra operations
|
||||||
let envelope = signed_envelope.message();
|
let envelope = signed_envelope.message();
|
||||||
let payload = envelope.payload();
|
let payload = envelope.payload();
|
||||||
@@ -62,4 +62,4 @@ pub fn envelope_processing<E: EthSpec>(
|
|||||||
|
|
||||||
todo!("the rest of process_execution_payload()");
|
todo!("the rest of process_execution_payload()");
|
||||||
//Ok(())
|
//Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ use types::{
|
|||||||
BeaconStateError, ChainSpec, DepositData, Domain, Epoch, EthSpec, Fork, Hash256,
|
BeaconStateError, ChainSpec, DepositData, Domain, Epoch, EthSpec, Fork, Hash256,
|
||||||
InconsistentFork, IndexedAttestation, IndexedAttestationRef, ProposerSlashing, PublicKey,
|
InconsistentFork, IndexedAttestation, IndexedAttestationRef, ProposerSlashing, PublicKey,
|
||||||
PublicKeyBytes, Signature, SignedAggregateAndProof, SignedBeaconBlock, SignedBeaconBlockHeader,
|
PublicKeyBytes, Signature, SignedAggregateAndProof, SignedBeaconBlock, SignedBeaconBlockHeader,
|
||||||
SignedBlsToExecutionChange, SignedContributionAndProof, SignedRoot, SignedVoluntaryExit,
|
SignedBlsToExecutionChange, SignedContributionAndProof, SignedExecutionPayloadEnvelope,
|
||||||
SigningData, Slot, SyncAggregate, SyncAggregatorSelectionData, Unsigned, SignedExecutionPayloadEnvelope,
|
SignedRoot, SignedVoluntaryExit, SigningData, Slot, SyncAggregate, SyncAggregatorSelectionData,
|
||||||
|
Unsigned,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|||||||
Reference in New Issue
Block a user