mirror of
https://github.com/sigp/lighthouse.git
synced 2026-07-05 05:44:30 +00:00
progress
This commit is contained in:
@@ -56,6 +56,7 @@ use crate::observed_block_producers::ObservedBlockProducers;
|
|||||||
use crate::observed_data_sidecars::ObservedDataSidecars;
|
use crate::observed_data_sidecars::ObservedDataSidecars;
|
||||||
use crate::observed_operations::{ObservationOutcome, ObservedOperations};
|
use crate::observed_operations::{ObservationOutcome, ObservedOperations};
|
||||||
use crate::observed_slashable::ObservedSlashable;
|
use crate::observed_slashable::ObservedSlashable;
|
||||||
|
use crate::payload_envelope_verification::{ExecutedEnvelope, ExecutionPendingEnvelope};
|
||||||
use crate::persisted_beacon_chain::PersistedBeaconChain;
|
use crate::persisted_beacon_chain::PersistedBeaconChain;
|
||||||
use crate::persisted_custody::persist_custody_context;
|
use crate::persisted_custody::persist_custody_context;
|
||||||
use crate::persisted_fork_choice::PersistedForkChoice;
|
use crate::persisted_fork_choice::PersistedForkChoice;
|
||||||
@@ -3547,6 +3548,33 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Accepts a fully-verified payload envelope and awaits on its payload verification handle to
|
||||||
|
/// get a fully `ExecutedEnvelope`.
|
||||||
|
///
|
||||||
|
/// An error is returned if the verification handle couldn't be awaited.
|
||||||
|
#[instrument(skip_all, level = "debug")]
|
||||||
|
pub async fn into_executed_payload_envelope(
|
||||||
|
self: Arc<Self>,
|
||||||
|
pending_envelope: ExecutionPendingEnvelope<T>,
|
||||||
|
) -> Result<ExecutedEnvelope<T::EthSpec>, BlockError> {
|
||||||
|
let ExecutionPendingEnvelope {
|
||||||
|
signed_envelope,
|
||||||
|
import_data,
|
||||||
|
payload_verification_handle,
|
||||||
|
} = pending_envelope;
|
||||||
|
|
||||||
|
let payload_verification_outcome = payload_verification_handle
|
||||||
|
.await
|
||||||
|
.map_err(BeaconChainError::TokioJoin)?
|
||||||
|
.ok_or(BeaconChainError::RuntimeShutdown)??;
|
||||||
|
|
||||||
|
Ok(ExecutedEnvelope::new(
|
||||||
|
signed_envelope,
|
||||||
|
import_data,
|
||||||
|
payload_verification_outcome,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
/* Import methods */
|
/* Import methods */
|
||||||
|
|
||||||
/// Checks if the block is available, and imports immediately if so, otherwise caches the block
|
/// Checks if the block is available, and imports immediately if so, otherwise caches the block
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
//! So, this module contains functions that one might expect to find in other crates, but they live
|
//! So, this module contains functions that one might expect to find in other crates, but they live
|
||||||
//! here for good reason.
|
//! here for good reason.
|
||||||
|
|
||||||
use crate::payload_envelope_verification::EnvelopeError;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
BeaconChain, BeaconChainError, BeaconChainTypes, BlockError, BlockProductionError,
|
BeaconChain, BeaconChainError, BeaconChainTypes, BlockError, BlockProductionError,
|
||||||
ExecutionPayloadError,
|
ExecutionPayloadError,
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ use educe::Educe;
|
|||||||
use slot_clock::SlotClock;
|
use slot_clock::SlotClock;
|
||||||
use state_processing::{VerifySignatures, envelope_processing::process_execution_payload_envelope};
|
use state_processing::{VerifySignatures, envelope_processing::process_execution_payload_envelope};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
use types::{EthSpec, SignedBeaconBlock, SignedExecutionPayloadEnvelope, consts::gloas::BUILDER_INDEX_SELF_BUILD};
|
use types::{
|
||||||
|
EthSpec, SignedBeaconBlock, SignedExecutionPayloadEnvelope,
|
||||||
|
consts::gloas::BUILDER_INDEX_SELF_BUILD,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
BeaconChain, BeaconChainError, BeaconChainTypes, NotifyExecutionLayer,
|
BeaconChain, BeaconChainError, BeaconChainTypes, NotifyExecutionLayer,
|
||||||
@@ -103,54 +106,58 @@ impl<T: BeaconChainTypes> GossipVerifiedEnvelope<T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the fork from the proposer cache so we can verify the signature.
|
// Verify the envelope signature.
|
||||||
// This is currently the most efficient way to implement envelope signature verification
|
//
|
||||||
// because the `fork` might depend on advancing the parent state.
|
// For self-build envelopes, we can use the proposer cache for the fork and the
|
||||||
|
// validator pubkey cache for the proposer's pubkey, avoiding a state load from disk.
|
||||||
|
// For external builder envelopes, we must load the state to access the builder registry.
|
||||||
|
let builder_index = envelope.builder_index;
|
||||||
let block_slot = envelope.slot;
|
let block_slot = envelope.slot;
|
||||||
let block_epoch = block_slot.epoch(T::EthSpec::slots_per_epoch());
|
let block_epoch = block_slot.epoch(T::EthSpec::slots_per_epoch());
|
||||||
let proposer_shuffling_decision_block =
|
let proposer_shuffling_decision_block =
|
||||||
proto_block.proposer_shuffling_root_for_child_block(block_epoch, &chain.spec);
|
proto_block.proposer_shuffling_root_for_child_block(block_epoch, &chain.spec);
|
||||||
let mut opt_snapshot = None;
|
|
||||||
let envelope_ref = signed_envelope.as_ref();
|
|
||||||
let proposer = chain.with_proposer_cache::<_, EnvelopeError>(
|
|
||||||
proposer_shuffling_decision_block,
|
|
||||||
block_epoch,
|
|
||||||
|proposers| proposers.get_slot::<T::EthSpec>(block_slot),
|
|
||||||
|| {
|
|
||||||
debug!(
|
|
||||||
%beacon_block_root,
|
|
||||||
block_hash = %envelope_ref.block_hash(),
|
|
||||||
"Proposer shuffling cache miss for envelope verification"
|
|
||||||
);
|
|
||||||
// The proposer index was *not* cached and we must load the parent in order to
|
|
||||||
// determine the proposer index.
|
|
||||||
let snapshot = load_snapshot(envelope_ref, chain)?;
|
|
||||||
opt_snapshot = Some(Box::new(snapshot.clone()));
|
|
||||||
Ok((snapshot.state_root, snapshot.pre_state))
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
let fork = proposer.fork;
|
|
||||||
|
|
||||||
let builder_index = envelope.builder_index;
|
let (signature_is_valid, opt_snapshot) = if builder_index == BUILDER_INDEX_SELF_BUILD {
|
||||||
let index = if builder_index == BUILDER_INDEX_SELF_BUILD {
|
// Fast path: self-build envelopes can be verified without loading the state.
|
||||||
block.message().proposer_index()
|
let envelope_ref = signed_envelope.as_ref();
|
||||||
} else {
|
let mut opt_snapshot = None;
|
||||||
builder_index
|
let proposer = chain.with_proposer_cache::<_, EnvelopeError>(
|
||||||
};
|
proposer_shuffling_decision_block,
|
||||||
|
block_epoch,
|
||||||
|
|proposers| proposers.get_slot::<T::EthSpec>(block_slot),
|
||||||
|
|| {
|
||||||
|
debug!(
|
||||||
|
%beacon_block_root,
|
||||||
|
"Proposer shuffling cache miss for envelope verification"
|
||||||
|
);
|
||||||
|
let snapshot = load_snapshot(envelope_ref, chain)?;
|
||||||
|
opt_snapshot = Some(Box::new(snapshot.clone()));
|
||||||
|
Ok((snapshot.state_root, snapshot.pre_state))
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
let fork = proposer.fork;
|
||||||
|
|
||||||
let signature_is_valid = {
|
|
||||||
// TODO(gloas) the builder pubkey wont be in the validator pubkey cache
|
|
||||||
// this will currently only work for local block building.
|
|
||||||
let pubkey_cache = chain.validator_pubkey_cache.read();
|
let pubkey_cache = chain.validator_pubkey_cache.read();
|
||||||
let pubkey = pubkey_cache
|
let pubkey = pubkey_cache
|
||||||
.get(index as usize)
|
.get(block.message().proposer_index() as usize)
|
||||||
.ok_or_else(|| EnvelopeError::UnknownValidator { builder_index: index })?;
|
.ok_or_else(|| EnvelopeError::UnknownValidator {
|
||||||
signed_envelope.verify_signature(
|
builder_index: block.message().proposer_index(),
|
||||||
|
})?;
|
||||||
|
let is_valid = signed_envelope.verify_signature(
|
||||||
pubkey,
|
pubkey,
|
||||||
&fork,
|
&fork,
|
||||||
chain.genesis_validators_root,
|
chain.genesis_validators_root,
|
||||||
&chain.spec,
|
&chain.spec,
|
||||||
)
|
);
|
||||||
|
(is_valid, opt_snapshot)
|
||||||
|
} else {
|
||||||
|
// TODO(gloas) we should probably introduce a builder cache or some type of
|
||||||
|
// global cache.
|
||||||
|
// External builder: must load the state to get the builder pubkey.
|
||||||
|
let snapshot = load_snapshot(signed_envelope.as_ref(), chain)?;
|
||||||
|
let is_valid =
|
||||||
|
signed_envelope.verify_signature_with_state(&snapshot.pre_state, &chain.spec)?;
|
||||||
|
(is_valid, Some(Box::new(snapshot)))
|
||||||
};
|
};
|
||||||
|
|
||||||
if !signature_is_valid {
|
if !signature_is_valid {
|
||||||
@@ -179,20 +186,13 @@ impl<T: BeaconChainTypes> IntoExecutionPendingEnvelope<T> for GossipVerifiedEnve
|
|||||||
let envelope = &signed_envelope.message;
|
let envelope = &signed_envelope.message;
|
||||||
let payload = &envelope.payload;
|
let payload = &envelope.payload;
|
||||||
|
|
||||||
// TODO(gloas) unwrap
|
|
||||||
let bid = chain
|
|
||||||
.get_full_block(&envelope.beacon_block_root)
|
|
||||||
.unwrap()
|
|
||||||
.unwrap()
|
|
||||||
.message()
|
|
||||||
.body()
|
|
||||||
.signed_execution_payload_bid()
|
|
||||||
.unwrap()
|
|
||||||
.message;
|
|
||||||
|
|
||||||
// Verify the execution payload is valid
|
// Verify the execution payload is valid
|
||||||
let payload_notifier =
|
let payload_notifier = PayloadNotifier::new(
|
||||||
PayloadNotifier::new(chain.clone(), envelope, notify_execution_layer)?;
|
chain.clone(),
|
||||||
|
signed_envelope.clone(),
|
||||||
|
self.block.clone(),
|
||||||
|
notify_execution_layer,
|
||||||
|
)?;
|
||||||
let block_root = envelope.beacon_block_root;
|
let block_root = envelope.beacon_block_root;
|
||||||
let slot = self.block.slot();
|
let slot = self.block.slot();
|
||||||
|
|
||||||
|
|||||||
@@ -17,9 +17,6 @@
|
|||||||
//! |---------------
|
//! |---------------
|
||||||
//! |
|
//! |
|
||||||
//! ▼
|
//! ▼
|
||||||
//! SignatureVerifiedEnvelope
|
|
||||||
//! |
|
|
||||||
//! ▼
|
|
||||||
//! ExecutionPendingEnvelope
|
//! ExecutionPendingEnvelope
|
||||||
//! |
|
//! |
|
||||||
//! await
|
//! await
|
||||||
@@ -41,15 +38,16 @@ use types::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
BeaconChain, BeaconChainError, BeaconChainTypes, NotifyExecutionLayer,
|
AvailabilityProcessingStatus, BeaconChain, BeaconChainError, BeaconChainTypes,
|
||||||
block_verification::PayloadVerificationHandle,
|
ExecutionPayloadError, NotifyExecutionLayer, PayloadVerificationOutcome,
|
||||||
|
block_verification::PayloadVerificationHandle, block_verification_types::BlockImportData,
|
||||||
payload_envelope_verification::gossip_verified_envelope::GossipVerifiedEnvelope,
|
payload_envelope_verification::gossip_verified_envelope::GossipVerifiedEnvelope,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod execution_pending_envelope;
|
pub mod execution_pending_envelope;
|
||||||
pub mod gossip_verified_envelope;
|
pub mod gossip_verified_envelope;
|
||||||
mod payload_notifier;
|
mod payload_notifier;
|
||||||
mod signature_verified_envelope;
|
mod tests;
|
||||||
|
|
||||||
pub trait IntoExecutionPendingEnvelope<T: BeaconChainTypes>: Sized {
|
pub trait IntoExecutionPendingEnvelope<T: BeaconChainTypes>: Sized {
|
||||||
fn into_execution_pending_envelope(
|
fn into_execution_pending_envelope(
|
||||||
@@ -101,7 +99,67 @@ pub struct EnvelopeProcessingSnapshot<E: EthSpec> {
|
|||||||
pub beacon_block_root: Hash256,
|
pub beacon_block_root: Hash256,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
/// A payload envelope that has gone through processing checks and execution by an EL client.
|
||||||
|
/// This envelope hasn't necessarily completed data availability checks.
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// It contains 2 variants:
|
||||||
|
/// 1. `Available`: This enelope has been executed and also contains all data to consider it
|
||||||
|
/// fully available.
|
||||||
|
/// 2. `AvailabilityPending`: This envelope hasn't received all required blobs to consider it
|
||||||
|
/// fully available.
|
||||||
|
pub enum ExecutedEnvelope<E: EthSpec> {
|
||||||
|
Available(AvailableExecutedEnvelope<E>),
|
||||||
|
// TODO(gloas) implement availability pending
|
||||||
|
AvailabilityPending(),
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
// TODO(gloas) implement availability pending
|
||||||
|
MaybeAvailableEnvelope::AvailabilityPending {
|
||||||
|
block_hash: _,
|
||||||
|
envelope: _,
|
||||||
|
} => Self::AvailabilityPending(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A payload envelope that has completed all payload processing checks including verification
|
||||||
|
/// by an EL client **and** has all requisite blob data to be imported into fork choice.
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum EnvelopeError {
|
pub enum EnvelopeError {
|
||||||
/// The envelope's block root is unknown.
|
/// The envelope's block root is unknown.
|
||||||
BlockRootUnknown {
|
BlockRootUnknown {
|
||||||
@@ -142,6 +200,8 @@ pub enum EnvelopeError {
|
|||||||
BlockProcessingError(BlockProcessingError),
|
BlockProcessingError(BlockProcessingError),
|
||||||
// Some EnvelopeProcessingError
|
// Some EnvelopeProcessingError
|
||||||
EnvelopeProcessingError(EnvelopeProcessingError),
|
EnvelopeProcessingError(EnvelopeProcessingError),
|
||||||
|
// Error verifying the execution payload
|
||||||
|
ExecutionPayloadError(ExecutionPayloadError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<BeaconChainError> for EnvelopeError {
|
impl From<BeaconChainError> for EnvelopeError {
|
||||||
@@ -150,6 +210,12 @@ impl From<BeaconChainError> for EnvelopeError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<ExecutionPayloadError> for EnvelopeError {
|
||||||
|
fn from(e: ExecutionPayloadError) -> Self {
|
||||||
|
EnvelopeError::ExecutionPayloadError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<BeaconStateError> for EnvelopeError {
|
impl From<BeaconStateError> for EnvelopeError {
|
||||||
fn from(e: BeaconStateError) -> Self {
|
fn from(e: BeaconStateError) -> Self {
|
||||||
EnvelopeError::BeaconStateError(e)
|
EnvelopeError::BeaconStateError(e)
|
||||||
|
|||||||
@@ -1,15 +1,10 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use execution_layer::NewPayloadRequest;
|
use execution_layer::{NewPayloadRequest, NewPayloadRequestGloas};
|
||||||
use fork_choice::PayloadVerificationStatus;
|
use fork_choice::PayloadVerificationStatus;
|
||||||
use state_processing::{
|
use state_processing::per_block_processing::deneb::kzg_commitment_to_versioned_hash;
|
||||||
envelope_processing::partially_verify_payload_envelope,
|
|
||||||
per_block_processing::is_execution_enabled,
|
|
||||||
};
|
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
use types::{
|
use types::{SignedBeaconBlock, SignedExecutionPayloadEnvelope};
|
||||||
BeaconState, ExecutionPayloadBid, Hash256, SignedBeaconBlock, SignedExecutionPayloadEnvelope,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
BeaconChain, BeaconChainTypes, BlockError, ExecutionPayloadError, NotifyExecutionLayer,
|
BeaconChain, BeaconChainTypes, BlockError, ExecutionPayloadError, NotifyExecutionLayer,
|
||||||
@@ -19,33 +14,26 @@ use crate::{
|
|||||||
/// Used to await the result of executing payload with a remote EE.
|
/// Used to await the result of executing payload with a remote EE.
|
||||||
pub struct PayloadNotifier<T: BeaconChainTypes> {
|
pub struct PayloadNotifier<T: BeaconChainTypes> {
|
||||||
pub chain: Arc<BeaconChain<T>>,
|
pub chain: Arc<BeaconChain<T>>,
|
||||||
pub envelope: Arc<SignedExecutionPayloadEnvelope<T::EthSpec>>,
|
envelope: Arc<SignedExecutionPayloadEnvelope<T::EthSpec>>,
|
||||||
|
block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
||||||
payload_verification_status: Option<PayloadVerificationStatus>,
|
payload_verification_status: Option<PayloadVerificationStatus>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: BeaconChainTypes> PayloadNotifier<T> {
|
impl<T: BeaconChainTypes> PayloadNotifier<T> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
chain: Arc<BeaconChain<T>>,
|
chain: Arc<BeaconChain<T>>,
|
||||||
bid: &ExecutionPayloadBid<T::EthSpec>,
|
|
||||||
envelope: Arc<SignedExecutionPayloadEnvelope<T::EthSpec>>,
|
envelope: Arc<SignedExecutionPayloadEnvelope<T::EthSpec>>,
|
||||||
state: &BeaconState<T::EthSpec>,
|
block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
||||||
notify_execution_layer: NotifyExecutionLayer,
|
notify_execution_layer: NotifyExecutionLayer,
|
||||||
) -> Result<Self, ExecutionPayloadError> {
|
) -> Result<Self, ExecutionPayloadError> {
|
||||||
let payload_verification_status = {
|
let payload_verification_status = {
|
||||||
// Perform the initial stages of payload verification.
|
|
||||||
//
|
|
||||||
// We will duplicate these checks again during `per_block_processing`, however these
|
|
||||||
// checks are cheap and doing them here ensures we have verified them before marking
|
|
||||||
// the block as optimistically imported. This is particularly relevant in the case
|
|
||||||
// where we do not send the block to the EL at all.
|
|
||||||
let payload_message = &envelope.message;
|
let payload_message = &envelope.message;
|
||||||
partially_verify_payload_envelope(state, &envelope, &chain.spec).unwrap(); // TODO(gloas) unwrap
|
|
||||||
|
|
||||||
match notify_execution_layer {
|
match notify_execution_layer {
|
||||||
NotifyExecutionLayer::No if chain.config.optimistic_finalized_sync => {
|
NotifyExecutionLayer::No if chain.config.optimistic_finalized_sync => {
|
||||||
// Create a NewPayloadRequest (no clones required) and check optimistic sync verifications
|
// TODO(gloas) unwrap
|
||||||
let new_payload_request: NewPayloadRequest<T::EthSpec> =
|
let new_payload_request =
|
||||||
payload_message.try_into()?;
|
Self::build_new_payload_request(&envelope, &block).unwrap();
|
||||||
if let Err(e) = new_payload_request.perform_optimistic_sync_verifications() {
|
if let Err(e) = new_payload_request.perform_optimistic_sync_verifications() {
|
||||||
warn!(
|
warn!(
|
||||||
block_number = ?payload_message.payload.block_number,
|
block_number = ?payload_message.payload.block_number,
|
||||||
@@ -65,6 +53,7 @@ impl<T: BeaconChainTypes> PayloadNotifier<T> {
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
chain,
|
chain,
|
||||||
envelope,
|
envelope,
|
||||||
|
block,
|
||||||
payload_verification_status,
|
payload_verification_status,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -73,13 +62,34 @@ impl<T: BeaconChainTypes> PayloadNotifier<T> {
|
|||||||
if let Some(precomputed_status) = self.payload_verification_status {
|
if let Some(precomputed_status) = self.payload_verification_status {
|
||||||
Ok(precomputed_status)
|
Ok(precomputed_status)
|
||||||
} else {
|
} else {
|
||||||
// tODO(gloas) fix zero
|
let block_root = self.envelope.message.beacon_block_root;
|
||||||
notify_new_payload(
|
let request = Self::build_new_payload_request(&self.envelope, &self.block)?;
|
||||||
&self.chain,
|
notify_new_payload(&self.chain, block_root, request).await
|
||||||
Hash256::ZERO,
|
|
||||||
self.envelope.message.try_into()?,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_new_payload_request<'a>(
|
||||||
|
envelope: &'a SignedExecutionPayloadEnvelope<T::EthSpec>,
|
||||||
|
block: &'a SignedBeaconBlock<T::EthSpec>,
|
||||||
|
) -> Result<NewPayloadRequest<'a, T::EthSpec>, BlockError> {
|
||||||
|
let bid = &block
|
||||||
|
.message()
|
||||||
|
.body()
|
||||||
|
.signed_execution_payload_bid()
|
||||||
|
.map_err(|e| BlockError::BeaconChainError(Box::new(e.into())))?
|
||||||
|
.message;
|
||||||
|
|
||||||
|
let versioned_hashes = bid
|
||||||
|
.blob_kzg_commitments
|
||||||
|
.iter()
|
||||||
|
.map(kzg_commitment_to_versioned_hash)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(NewPayloadRequest::Gloas(NewPayloadRequestGloas {
|
||||||
|
execution_payload: &envelope.message.payload,
|
||||||
|
versioned_hashes,
|
||||||
|
parent_beacon_block_root: block.message().parent_root(),
|
||||||
|
execution_requests: &envelope.message.execution_requests,
|
||||||
|
}))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use state_processing::ConsensusContext;
|
|
||||||
use types::{BeaconState, Hash256, SignedExecutionPayloadEnvelope};
|
|
||||||
|
|
||||||
use crate::{BeaconChain, BeaconChainTypes, payload_envelope_verification::{EnvelopeError, MaybeAvailableEnvelope}};
|
|
||||||
|
|
||||||
|
|
||||||
/// A wrapper around a `SignedExecutionPayloadEnvelope` that indicates that all signatures (except the deposit
|
|
||||||
/// signatures) have been verified.
|
|
||||||
pub struct SignatureVerifiedEnvelope<T: BeaconChainTypes> {
|
|
||||||
envelope: SignedExecutionPayloadEnvelope<T::EthSpec>,
|
|
||||||
block_root: Hash256,
|
|
||||||
state: Option<BeaconState<T::EthSpec>>,
|
|
||||||
consensus_context: ConsensusContext<T::EthSpec>,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
impl<T: BeaconChainTypes> SignatureVerifiedEnvelope<T> {
|
|
||||||
pub fn new(
|
|
||||||
envelope: Arc<SignedExecutionPayloadEnvelope<T::EthSpec>>,
|
|
||||||
state: &mut BeaconState<T::EthSpec>,
|
|
||||||
block_root: Hash256,
|
|
||||||
chain: &BeaconChain<T>,
|
|
||||||
) -> Result<Self, EnvelopeError> {
|
|
||||||
let is_signature_valid = envelope.verify_signature_with_state(state, &chain.spec)?;
|
|
||||||
|
|
||||||
if !is_signature_valid {
|
|
||||||
return Err(EnvelopeError::BadSignature)
|
|
||||||
}
|
|
||||||
|
|
||||||
Self {
|
|
||||||
envelope,
|
|
||||||
block_root,
|
|
||||||
state
|
|
||||||
}
|
|
||||||
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use crate::{AvailabilityProcessingStatus, BeaconChain, BeaconChainTypes, payload_envelope_verification::{ExecutedEnvelope, ExecutionPendingEnvelope}};
|
||||||
|
|
||||||
|
async fn import_execution_pending_envelope<T: BeaconChainTypes>(
|
||||||
|
chain: Arc<BeaconChain<T>>,
|
||||||
|
execution_pending_envelope: ExecutionPendingEnvelope<T>,
|
||||||
|
) -> Result<AvailabilityProcessingStatus, String> {
|
||||||
|
match chain
|
||||||
|
.clone()
|
||||||
|
.into_executed_payload_envelope(execution_pending_envelope)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
{
|
||||||
|
ExecutedEnvelope::Available(envelope) => todo!(),
|
||||||
|
ExecutedEnvelope::AvailabilityPending() => {
|
||||||
|
Err("AvailabilityPending not expected in this test. Block not imported.".to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ use state_processing::per_block_processing::deneb::kzg_commitment_to_versioned_h
|
|||||||
use superstruct::superstruct;
|
use superstruct::superstruct;
|
||||||
use types::{
|
use types::{
|
||||||
BeaconBlockRef, BeaconStateError, EthSpec, ExecutionBlockHash, ExecutionPayload,
|
BeaconBlockRef, BeaconStateError, EthSpec, ExecutionBlockHash, ExecutionPayload,
|
||||||
ExecutionPayloadEnvelope, ExecutionPayloadRef, Hash256, VersionedHash,
|
ExecutionPayloadRef, Hash256, VersionedHash,
|
||||||
};
|
};
|
||||||
use types::{
|
use types::{
|
||||||
ExecutionPayloadBellatrix, ExecutionPayloadCapella, ExecutionPayloadDeneb,
|
ExecutionPayloadBellatrix, ExecutionPayloadCapella, ExecutionPayloadDeneb,
|
||||||
|
|||||||
@@ -276,103 +276,3 @@ pub fn process_execution_payload_envelope<E: EthSpec>(
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Performs *partial* verification of the `payload envelope`.
|
|
||||||
pub fn partially_verify_payload_envelope<E: EthSpec>(
|
|
||||||
state: &BeaconState<E>,
|
|
||||||
signed_envelope: &SignedExecutionPayloadEnvelope<E>,
|
|
||||||
spec: &ChainSpec,
|
|
||||||
) -> Result<(), EnvelopeProcessingError> {
|
|
||||||
let envelope = &signed_envelope.message;
|
|
||||||
let payload = &signed_envelope.message.payload;
|
|
||||||
|
|
||||||
// Verify consistency with the beacon block
|
|
||||||
let latest_block_header_root = state.latest_block_header().tree_hash_root();
|
|
||||||
envelope_verify!(
|
|
||||||
envelope.beacon_block_root == latest_block_header_root,
|
|
||||||
EnvelopeProcessingError::LatestBlockHeaderMismatch {
|
|
||||||
envelope_root: envelope.beacon_block_root,
|
|
||||||
block_header_root: latest_block_header_root,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
envelope_verify!(
|
|
||||||
envelope.slot == state.slot(),
|
|
||||||
EnvelopeProcessingError::SlotMismatch {
|
|
||||||
envelope_slot: envelope.slot,
|
|
||||||
parent_state_slot: state.slot(),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Verify consistency with the committed bid
|
|
||||||
let committed_bid = state.latest_execution_payload_bid()?;
|
|
||||||
envelope_verify!(
|
|
||||||
envelope.builder_index == committed_bid.builder_index,
|
|
||||||
EnvelopeProcessingError::BuilderIndexMismatch {
|
|
||||||
committed_bid: committed_bid.builder_index,
|
|
||||||
envelope: envelope.builder_index,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
envelope_verify!(
|
|
||||||
committed_bid.prev_randao == payload.prev_randao,
|
|
||||||
EnvelopeProcessingError::PrevRandaoMismatch {
|
|
||||||
committed_bid: committed_bid.prev_randao,
|
|
||||||
envelope: payload.prev_randao,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Verify consistency with expected withdrawals
|
|
||||||
// NOTE: we don't bother hashing here except in case of error, because we can just compare for
|
|
||||||
// equality directly. This equality check could be more straight-forward if the types were
|
|
||||||
// changed to match (currently we are comparing VariableList to List). This could happen
|
|
||||||
// coincidentally when we adopt ProgressiveList.
|
|
||||||
envelope_verify!(
|
|
||||||
payload.withdrawals.len() == state.payload_expected_withdrawals()?.len()
|
|
||||||
&& payload
|
|
||||||
.withdrawals
|
|
||||||
.iter()
|
|
||||||
.eq(state.payload_expected_withdrawals()?.iter()),
|
|
||||||
EnvelopeProcessingError::WithdrawalsRootMismatch {
|
|
||||||
state: state.payload_expected_withdrawals()?.tree_hash_root(),
|
|
||||||
payload: payload.withdrawals.tree_hash_root(),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Verify the gas limit
|
|
||||||
envelope_verify!(
|
|
||||||
committed_bid.gas_limit == payload.gas_limit,
|
|
||||||
EnvelopeProcessingError::GasLimitMismatch {
|
|
||||||
committed_bid: committed_bid.gas_limit,
|
|
||||||
envelope: payload.gas_limit,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Verify the block hash
|
|
||||||
envelope_verify!(
|
|
||||||
committed_bid.block_hash == payload.block_hash,
|
|
||||||
EnvelopeProcessingError::BlockHashMismatch {
|
|
||||||
committed_bid: committed_bid.block_hash,
|
|
||||||
envelope: payload.block_hash,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Verify consistency of the parent hash with respect to the previous execution payload
|
|
||||||
envelope_verify!(
|
|
||||||
payload.parent_hash == *state.latest_block_hash()?,
|
|
||||||
EnvelopeProcessingError::ParentHashMismatch {
|
|
||||||
state: *state.latest_block_hash()?,
|
|
||||||
envelope: payload.parent_hash,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Verify timestamp
|
|
||||||
let state_timestamp = compute_timestamp_at_slot(state, state.slot(), spec)?;
|
|
||||||
envelope_verify!(
|
|
||||||
payload.timestamp == state_timestamp,
|
|
||||||
EnvelopeProcessingError::TimestampMismatch {
|
|
||||||
state: state_timestamp,
|
|
||||||
envelope: payload.timestamp,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user