mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-02 16:21:42 +00:00
Block v3 endpoint (#4629)
## Issue Addressed #4582 ## Proposed Changes Add a new v3 block fetching flow that can decide to return a Full OR Blinded payload ## Additional Info Co-authored-by: Michael Sproul <micsproul@gmail.com>
This commit is contained in:
@@ -466,6 +466,11 @@ impl<T: EthSpec> From<GetPayloadResponse<T>>
|
||||
}
|
||||
}
|
||||
|
||||
pub enum GetPayloadResponseType<E: EthSpec> {
|
||||
Full(GetPayloadResponse<E>),
|
||||
Blinded(GetPayloadResponse<E>),
|
||||
}
|
||||
|
||||
impl<T: EthSpec> GetPayloadResponse<T> {
|
||||
pub fn execution_payload_ref(&self) -> ExecutionPayloadRef<T> {
|
||||
self.to_ref().into()
|
||||
|
||||
@@ -42,13 +42,13 @@ use tokio_stream::wrappers::WatchStream;
|
||||
use tree_hash::TreeHash;
|
||||
use types::beacon_block_body::KzgCommitments;
|
||||
use types::builder_bid::BuilderBid;
|
||||
use types::payload::BlockProductionVersion;
|
||||
use types::sidecar::{BlobItems, Sidecar};
|
||||
use types::KzgProofs;
|
||||
use types::{AbstractExecPayload, ExecutionPayloadDeneb, KzgProofs};
|
||||
use types::{
|
||||
AbstractExecPayload, BeaconStateError, BlindedPayload, BlockType, ChainSpec, Epoch,
|
||||
ExecPayload, ExecutionPayloadCapella, ExecutionPayloadDeneb, ExecutionPayloadMerge,
|
||||
BeaconStateError, BlindedPayload, ChainSpec, Epoch, ExecPayload, ExecutionPayloadCapella,
|
||||
ExecutionPayloadMerge, FullPayload, ProposerPreparationData, PublicKeyBytes, Signature, Slot,
|
||||
};
|
||||
use types::{ProposerPreparationData, PublicKeyBytes, Signature, Slot};
|
||||
|
||||
mod block_hash;
|
||||
mod engine_api;
|
||||
@@ -87,9 +87,7 @@ pub enum ProvenancedPayload<P> {
|
||||
Builder(P),
|
||||
}
|
||||
|
||||
impl<E: EthSpec, Payload: AbstractExecPayload<E>> TryFrom<BuilderBid<E>>
|
||||
for ProvenancedPayload<BlockProposalContents<E, Payload>>
|
||||
{
|
||||
impl<E: EthSpec> TryFrom<BuilderBid<E>> for ProvenancedPayload<BlockProposalContentsType<E>> {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(value: BuilderBid<E>) -> Result<Self, Error> {
|
||||
@@ -112,12 +110,16 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> TryFrom<BuilderBid<E>>
|
||||
.map_err(|_| Error::InvalidPayloadConversion)?,
|
||||
block_value: builder_bid.value,
|
||||
kzg_commitments: builder_bid.blinded_blobs_bundle.commitments,
|
||||
blobs: BlobItems::try_from_blob_roots(builder_bid.blinded_blobs_bundle.blob_roots)
|
||||
.map_err(Error::InvalidBlobConversion)?,
|
||||
blobs: BlobItems::<E>::try_from_blob_roots(
|
||||
builder_bid.blinded_blobs_bundle.blob_roots,
|
||||
)
|
||||
.map_err(Error::InvalidBlobConversion)?,
|
||||
proofs: builder_bid.blinded_blobs_bundle.proofs,
|
||||
},
|
||||
};
|
||||
Ok(ProvenancedPayload::Builder(block_proposal_contents))
|
||||
Ok(ProvenancedPayload::Builder(
|
||||
BlockProposalContentsType::Blinded(block_proposal_contents),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,6 +147,7 @@ pub enum Error {
|
||||
InvalidPayloadConversion,
|
||||
InvalidBlobConversion(String),
|
||||
BeaconStateError(BeaconStateError),
|
||||
PayloadTypeMismatch,
|
||||
}
|
||||
|
||||
impl From<BeaconStateError> for Error {
|
||||
@@ -159,6 +162,11 @@ impl From<ApiError> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
pub enum BlockProposalContentsType<E: EthSpec> {
|
||||
Full(BlockProposalContents<E, FullPayload<E>>),
|
||||
Blinded(BlockProposalContents<E, BlindedPayload<E>>),
|
||||
}
|
||||
|
||||
pub enum BlockProposalContents<T: EthSpec, Payload: AbstractExecPayload<T>> {
|
||||
Payload {
|
||||
payload: Payload,
|
||||
@@ -173,6 +181,22 @@ pub enum BlockProposalContents<T: EthSpec, Payload: AbstractExecPayload<T>> {
|
||||
},
|
||||
}
|
||||
|
||||
impl<T: EthSpec> From<BlockProposalContents<T, FullPayload<T>>>
|
||||
for BlockProposalContents<T, BlindedPayload<T>>
|
||||
{
|
||||
fn from(item: BlockProposalContents<T, FullPayload<T>>) -> Self {
|
||||
let block_value = item.block_value().to_owned();
|
||||
|
||||
let blinded_payload: BlockProposalContents<T, BlindedPayload<T>> =
|
||||
BlockProposalContents::Payload {
|
||||
payload: item.to_payload().execution_payload().into(),
|
||||
block_value,
|
||||
};
|
||||
|
||||
blinded_payload
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec, Payload: AbstractExecPayload<E>> TryFrom<GetPayloadResponse<E>>
|
||||
for BlockProposalContents<E, Payload>
|
||||
{
|
||||
@@ -197,6 +221,17 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> TryFrom<GetPayloadResponse<E>>
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> TryFrom<GetPayloadResponseType<E>> for BlockProposalContentsType<E> {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(response_type: GetPayloadResponseType<E>) -> Result<Self, Error> {
|
||||
match response_type {
|
||||
GetPayloadResponseType::Full(response) => Ok(Self::Full(response.try_into()?)),
|
||||
GetPayloadResponseType::Blinded(response) => Ok(Self::Blinded(response.try_into()?)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
impl<T: EthSpec, Payload: AbstractExecPayload<T>> BlockProposalContents<T, Payload> {
|
||||
pub fn deconstruct(
|
||||
@@ -206,19 +241,26 @@ impl<T: EthSpec, Payload: AbstractExecPayload<T>> BlockProposalContents<T, Paylo
|
||||
Option<KzgCommitments<T>>,
|
||||
Option<<Payload::Sidecar as Sidecar<T>>::BlobItems>,
|
||||
Option<KzgProofs<T>>,
|
||||
Uint256,
|
||||
) {
|
||||
match self {
|
||||
Self::Payload {
|
||||
payload,
|
||||
block_value: _,
|
||||
} => (payload, None, None, None),
|
||||
block_value,
|
||||
} => (payload, None, None, None, block_value),
|
||||
Self::PayloadAndBlobs {
|
||||
payload,
|
||||
block_value: _,
|
||||
block_value,
|
||||
kzg_commitments,
|
||||
blobs,
|
||||
proofs,
|
||||
} => (payload, Some(kzg_commitments), Some(blobs), Some(proofs)),
|
||||
} => (
|
||||
payload,
|
||||
Some(kzg_commitments),
|
||||
Some(blobs),
|
||||
Some(proofs),
|
||||
block_value,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -795,7 +837,8 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
///
|
||||
/// The result will be returned from the first node that returns successfully. No more nodes
|
||||
/// will be contacted.
|
||||
pub async fn get_payload<Payload: AbstractExecPayload<T>>(
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn get_payload(
|
||||
&self,
|
||||
parent_hash: ExecutionBlockHash,
|
||||
payload_attributes: &PayloadAttributes,
|
||||
@@ -803,14 +846,11 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
builder_params: BuilderParams,
|
||||
current_fork: ForkName,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<BlockProposalContents<T, Payload>, Error> {
|
||||
let payload_result = match Payload::block_type() {
|
||||
BlockType::Blinded => {
|
||||
let _timer = metrics::start_timer_vec(
|
||||
&metrics::EXECUTION_LAYER_REQUEST_TIMES,
|
||||
&[metrics::GET_BLINDED_PAYLOAD],
|
||||
);
|
||||
self.get_blinded_payload(
|
||||
block_production_version: BlockProductionVersion,
|
||||
) -> Result<BlockProposalContentsType<T>, Error> {
|
||||
let payload_result_type = match block_production_version {
|
||||
BlockProductionVersion::V3 => match self
|
||||
.determine_and_fetch_payload(
|
||||
parent_hash,
|
||||
payload_attributes,
|
||||
forkchoice_update_params,
|
||||
@@ -819,27 +859,51 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
spec,
|
||||
)
|
||||
.await
|
||||
}
|
||||
BlockType::Full => {
|
||||
{
|
||||
Ok(payload) => payload,
|
||||
Err(e) => {
|
||||
metrics::inc_counter_vec(
|
||||
&metrics::EXECUTION_LAYER_GET_PAYLOAD_OUTCOME,
|
||||
&[metrics::FAILURE],
|
||||
);
|
||||
return Err(e);
|
||||
}
|
||||
},
|
||||
BlockProductionVersion::BlindedV2 => {
|
||||
let _timer = metrics::start_timer_vec(
|
||||
&metrics::EXECUTION_LAYER_REQUEST_TIMES,
|
||||
&[metrics::GET_PAYLOAD],
|
||||
&[metrics::GET_BLINDED_PAYLOAD],
|
||||
);
|
||||
self.get_full_payload(
|
||||
self.determine_and_fetch_payload(
|
||||
parent_hash,
|
||||
payload_attributes,
|
||||
forkchoice_update_params,
|
||||
builder_params,
|
||||
current_fork,
|
||||
spec,
|
||||
)
|
||||
.await?
|
||||
}
|
||||
BlockProductionVersion::FullV2 => self
|
||||
.get_full_payload_with(
|
||||
parent_hash,
|
||||
payload_attributes,
|
||||
forkchoice_update_params,
|
||||
current_fork,
|
||||
noop,
|
||||
)
|
||||
.await
|
||||
.and_then(GetPayloadResponse::try_into)
|
||||
.map(ProvenancedPayload::Local)
|
||||
}
|
||||
.and_then(GetPayloadResponseType::try_into)
|
||||
.map(ProvenancedPayload::Local)?,
|
||||
};
|
||||
|
||||
// Track some metrics and return the result.
|
||||
match payload_result {
|
||||
Ok(ProvenancedPayload::Local(block_proposal_contents)) => {
|
||||
let block_proposal_content_type = match payload_result_type {
|
||||
ProvenancedPayload::Local(local_payload) => local_payload,
|
||||
ProvenancedPayload::Builder(builder_payload) => builder_payload,
|
||||
};
|
||||
|
||||
match block_proposal_content_type {
|
||||
BlockProposalContentsType::Full(block_proposal_contents) => {
|
||||
metrics::inc_counter_vec(
|
||||
&metrics::EXECUTION_LAYER_GET_PAYLOAD_OUTCOME,
|
||||
&[metrics::SUCCESS],
|
||||
@@ -848,9 +912,15 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
&metrics::EXECUTION_LAYER_GET_PAYLOAD_SOURCE,
|
||||
&[metrics::LOCAL],
|
||||
);
|
||||
Ok(block_proposal_contents)
|
||||
if matches!(block_production_version, BlockProductionVersion::BlindedV2) {
|
||||
Ok(BlockProposalContentsType::Blinded(
|
||||
block_proposal_contents.into(),
|
||||
))
|
||||
} else {
|
||||
Ok(BlockProposalContentsType::Full(block_proposal_contents))
|
||||
}
|
||||
}
|
||||
Ok(ProvenancedPayload::Builder(block_proposal_contents)) => {
|
||||
BlockProposalContentsType::Blinded(block_proposal_contents) => {
|
||||
metrics::inc_counter_vec(
|
||||
&metrics::EXECUTION_LAYER_GET_PAYLOAD_OUTCOME,
|
||||
&[metrics::SUCCESS],
|
||||
@@ -859,19 +929,12 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
&metrics::EXECUTION_LAYER_GET_PAYLOAD_SOURCE,
|
||||
&[metrics::BUILDER],
|
||||
);
|
||||
Ok(block_proposal_contents)
|
||||
}
|
||||
Err(e) => {
|
||||
metrics::inc_counter_vec(
|
||||
&metrics::EXECUTION_LAYER_GET_PAYLOAD_OUTCOME,
|
||||
&[metrics::FAILURE],
|
||||
);
|
||||
Err(e)
|
||||
Ok(BlockProposalContentsType::Blinded(block_proposal_contents))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_blinded_payload<Payload: AbstractExecPayload<T>>(
|
||||
async fn determine_and_fetch_payload(
|
||||
&self,
|
||||
parent_hash: ExecutionBlockHash,
|
||||
payload_attributes: &PayloadAttributes,
|
||||
@@ -879,11 +942,10 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
builder_params: BuilderParams,
|
||||
current_fork: ForkName,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<ProvenancedPayload<BlockProposalContents<T, Payload>>, Error> {
|
||||
) -> Result<ProvenancedPayload<BlockProposalContentsType<T>>, Error> {
|
||||
if let Some(builder) = self.builder() {
|
||||
let slot = builder_params.slot;
|
||||
let pubkey = builder_params.pubkey;
|
||||
|
||||
match builder_params.chain_health {
|
||||
ChainHealth::Healthy => {
|
||||
info!(
|
||||
@@ -895,7 +957,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
);
|
||||
|
||||
// Wait for the builder *and* local EL to produce a payload (or return an error).
|
||||
let ((relay_result, relay_duration), (local_result, local_duration)) = tokio::join!(
|
||||
let ((relay_result, relay_duration), (local_result_type, local_duration)) = tokio::join!(
|
||||
timed_future(metrics::GET_BLINDED_PAYLOAD_BUILDER, async {
|
||||
builder
|
||||
.get_builder_header::<T>(slot, parent_hash, &pubkey)
|
||||
@@ -912,6 +974,11 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
})
|
||||
);
|
||||
|
||||
let local_result = match local_result_type? {
|
||||
GetPayloadResponseType::Full(payload) => Ok(payload),
|
||||
GetPayloadResponseType::Blinded(_) => Err(Error::PayloadTypeMismatch),
|
||||
};
|
||||
|
||||
info!(
|
||||
self.log(),
|
||||
"Requested blinded execution payload";
|
||||
@@ -939,7 +1006,9 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
"local_block_hash" => ?local.block_hash(),
|
||||
"parent_hash" => ?parent_hash,
|
||||
);
|
||||
Ok(ProvenancedPayload::Local(local.try_into()?))
|
||||
Ok(ProvenancedPayload::Local(BlockProposalContentsType::Full(
|
||||
local.try_into()?,
|
||||
)))
|
||||
}
|
||||
(Ok(None), Ok(local)) => {
|
||||
info!(
|
||||
@@ -949,7 +1018,9 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
"local_block_hash" => ?local.block_hash(),
|
||||
"parent_hash" => ?parent_hash,
|
||||
);
|
||||
Ok(ProvenancedPayload::Local(local.try_into()?))
|
||||
Ok(ProvenancedPayload::Local(BlockProposalContentsType::Full(
|
||||
local.try_into()?,
|
||||
)))
|
||||
}
|
||||
(Ok(Some(relay)), Ok(local)) => {
|
||||
let header = &relay.data.message.header();
|
||||
@@ -973,7 +1044,9 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
"local_block_value" => %local_value,
|
||||
"relay_value" => %relay_value
|
||||
);
|
||||
return Ok(ProvenancedPayload::Local(local.try_into()?));
|
||||
return Ok(ProvenancedPayload::Local(
|
||||
BlockProposalContentsType::Full(local.try_into()?),
|
||||
));
|
||||
} else if local.should_override_builder().unwrap_or(false) {
|
||||
let percentage_difference =
|
||||
percentage_difference_u256(local_value, *relay_value);
|
||||
@@ -989,7 +1062,9 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
"local_block_value" => %local_value,
|
||||
"relay_value" => %relay_value
|
||||
);
|
||||
return Ok(ProvenancedPayload::Local(local.try_into()?));
|
||||
return Ok(ProvenancedPayload::Local(
|
||||
BlockProposalContentsType::Full(local.try_into()?),
|
||||
));
|
||||
}
|
||||
} else {
|
||||
info!(
|
||||
@@ -1020,7 +1095,9 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
"relay_block_hash" => ?header.block_hash(),
|
||||
"parent_hash" => ?parent_hash,
|
||||
);
|
||||
Ok(ProvenancedPayload::Local(local.try_into()?))
|
||||
Ok(ProvenancedPayload::Local(BlockProposalContentsType::Full(
|
||||
local.try_into()?,
|
||||
)))
|
||||
}
|
||||
Err(reason) => {
|
||||
metrics::inc_counter_vec(
|
||||
@@ -1035,7 +1112,9 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
"relay_block_hash" => ?header.block_hash(),
|
||||
"parent_hash" => ?parent_hash,
|
||||
);
|
||||
Ok(ProvenancedPayload::Local(local.try_into()?))
|
||||
Ok(ProvenancedPayload::Local(BlockProposalContentsType::Full(
|
||||
local.try_into()?,
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1132,28 +1211,10 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
current_fork,
|
||||
)
|
||||
.await
|
||||
.and_then(GetPayloadResponse::try_into)
|
||||
.and_then(GetPayloadResponseType::try_into)
|
||||
.map(ProvenancedPayload::Local)
|
||||
}
|
||||
|
||||
/// Get a full payload without caching its result in the execution layer's payload cache.
|
||||
async fn get_full_payload(
|
||||
&self,
|
||||
parent_hash: ExecutionBlockHash,
|
||||
payload_attributes: &PayloadAttributes,
|
||||
forkchoice_update_params: ForkchoiceUpdateParameters,
|
||||
current_fork: ForkName,
|
||||
) -> Result<GetPayloadResponse<T>, Error> {
|
||||
self.get_full_payload_with(
|
||||
parent_hash,
|
||||
payload_attributes,
|
||||
forkchoice_update_params,
|
||||
current_fork,
|
||||
noop,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Get a full payload and cache its result in the execution layer's payload cache.
|
||||
async fn get_full_payload_caching(
|
||||
&self,
|
||||
@@ -1161,7 +1222,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
payload_attributes: &PayloadAttributes,
|
||||
forkchoice_update_params: ForkchoiceUpdateParameters,
|
||||
current_fork: ForkName,
|
||||
) -> Result<GetPayloadResponse<T>, Error> {
|
||||
) -> Result<GetPayloadResponseType<T>, Error> {
|
||||
self.get_full_payload_with(
|
||||
parent_hash,
|
||||
payload_attributes,
|
||||
@@ -1182,7 +1243,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
&ExecutionLayer<T>,
|
||||
PayloadContentsRefTuple<T>,
|
||||
) -> Option<FullPayloadContents<T>>,
|
||||
) -> Result<GetPayloadResponse<T>, Error> {
|
||||
) -> Result<GetPayloadResponseType<T>, Error> {
|
||||
self.engine()
|
||||
.request(move |engine| async move {
|
||||
let payload_id = if let Some(id) = engine
|
||||
@@ -1244,6 +1305,10 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
"timestamp" => payload_attributes.timestamp(),
|
||||
"parent_hash" => ?parent_hash,
|
||||
);
|
||||
let _timer = metrics::start_timer_vec(
|
||||
&metrics::EXECUTION_LAYER_REQUEST_TIMES,
|
||||
&[metrics::GET_PAYLOAD],
|
||||
);
|
||||
engine.api.get_payload::<T>(current_fork, payload_id).await
|
||||
}.await?;
|
||||
|
||||
@@ -1268,7 +1333,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
|
||||
);
|
||||
}
|
||||
|
||||
Ok(payload_response)
|
||||
Ok(GetPayloadResponseType::Full(payload_response))
|
||||
})
|
||||
.await
|
||||
.map_err(Box::new)
|
||||
|
||||
@@ -508,11 +508,7 @@ pub fn serve<E: EthSpec>(
|
||||
finalized_hash: Some(finalized_execution_hash),
|
||||
};
|
||||
|
||||
let (payload, _block_value, maybe_blobs_bundle): (
|
||||
ExecutionPayload<E>,
|
||||
Uint256,
|
||||
Option<BlobsBundle<E>>,
|
||||
) = builder
|
||||
let payload_response_type = builder
|
||||
.el
|
||||
.get_full_payload_caching(
|
||||
head_execution_hash,
|
||||
@@ -521,38 +517,88 @@ pub fn serve<E: EthSpec>(
|
||||
fork,
|
||||
)
|
||||
.await
|
||||
.map_err(|_| reject("couldn't get payload"))?
|
||||
.into();
|
||||
.map_err(|_| reject("couldn't get payload"))?;
|
||||
|
||||
let mut message = match fork {
|
||||
ForkName::Deneb => BuilderBid::Deneb(BuilderBidDeneb {
|
||||
header: payload
|
||||
.as_deneb()
|
||||
.map_err(|_| reject("incorrect payload variant"))?
|
||||
.into(),
|
||||
blinded_blobs_bundle: maybe_blobs_bundle
|
||||
.map(Into::into)
|
||||
.unwrap_or_default(),
|
||||
value: Uint256::from(DEFAULT_BUILDER_PAYLOAD_VALUE_WEI),
|
||||
pubkey: builder.builder_sk.public_key().compress(),
|
||||
}),
|
||||
ForkName::Capella => BuilderBid::Capella(BuilderBidCapella {
|
||||
header: payload
|
||||
.as_capella()
|
||||
.map_err(|_| reject("incorrect payload variant"))?
|
||||
.into(),
|
||||
value: Uint256::from(DEFAULT_BUILDER_PAYLOAD_VALUE_WEI),
|
||||
pubkey: builder.builder_sk.public_key().compress(),
|
||||
}),
|
||||
ForkName::Merge => BuilderBid::Merge(BuilderBidMerge {
|
||||
header: payload
|
||||
.as_merge()
|
||||
.map_err(|_| reject("incorrect payload variant"))?
|
||||
.into(),
|
||||
value: Uint256::from(DEFAULT_BUILDER_PAYLOAD_VALUE_WEI),
|
||||
pubkey: builder.builder_sk.public_key().compress(),
|
||||
}),
|
||||
ForkName::Base | ForkName::Altair => return Err(reject("invalid fork")),
|
||||
let mut message = match payload_response_type {
|
||||
crate::GetPayloadResponseType::Full(payload_response) => {
|
||||
let (payload, _block_value, maybe_blobs_bundle): (
|
||||
ExecutionPayload<E>,
|
||||
Uint256,
|
||||
Option<BlobsBundle<E>>,
|
||||
) = payload_response.into();
|
||||
|
||||
match fork {
|
||||
ForkName::Deneb => BuilderBid::Deneb(BuilderBidDeneb {
|
||||
header: payload
|
||||
.as_deneb()
|
||||
.map_err(|_| reject("incorrect payload variant"))?
|
||||
.into(),
|
||||
blinded_blobs_bundle: maybe_blobs_bundle
|
||||
.map(Into::into)
|
||||
.unwrap_or_default(),
|
||||
value: Uint256::from(DEFAULT_BUILDER_PAYLOAD_VALUE_WEI),
|
||||
pubkey: builder.builder_sk.public_key().compress(),
|
||||
}),
|
||||
ForkName::Capella => BuilderBid::Capella(BuilderBidCapella {
|
||||
header: payload
|
||||
.as_capella()
|
||||
.map_err(|_| reject("incorrect payload variant"))?
|
||||
.into(),
|
||||
value: Uint256::from(DEFAULT_BUILDER_PAYLOAD_VALUE_WEI),
|
||||
pubkey: builder.builder_sk.public_key().compress(),
|
||||
}),
|
||||
ForkName::Merge => BuilderBid::Merge(BuilderBidMerge {
|
||||
header: payload
|
||||
.as_merge()
|
||||
.map_err(|_| reject("incorrect payload variant"))?
|
||||
.into(),
|
||||
value: Uint256::from(DEFAULT_BUILDER_PAYLOAD_VALUE_WEI),
|
||||
pubkey: builder.builder_sk.public_key().compress(),
|
||||
}),
|
||||
ForkName::Base | ForkName::Altair => {
|
||||
return Err(reject("invalid fork"))
|
||||
}
|
||||
}
|
||||
}
|
||||
crate::GetPayloadResponseType::Blinded(payload_response) => {
|
||||
let (payload, _block_value, maybe_blobs_bundle): (
|
||||
ExecutionPayload<E>,
|
||||
Uint256,
|
||||
Option<BlobsBundle<E>>,
|
||||
) = payload_response.into();
|
||||
match fork {
|
||||
ForkName::Deneb => BuilderBid::Deneb(BuilderBidDeneb {
|
||||
header: payload
|
||||
.as_deneb()
|
||||
.map_err(|_| reject("incorrect payload variant"))?
|
||||
.into(),
|
||||
blinded_blobs_bundle: maybe_blobs_bundle
|
||||
.map(Into::into)
|
||||
.unwrap_or_default(),
|
||||
value: Uint256::from(DEFAULT_BUILDER_PAYLOAD_VALUE_WEI),
|
||||
pubkey: builder.builder_sk.public_key().compress(),
|
||||
}),
|
||||
ForkName::Capella => BuilderBid::Capella(BuilderBidCapella {
|
||||
header: payload
|
||||
.as_capella()
|
||||
.map_err(|_| reject("incorrect payload variant"))?
|
||||
.into(),
|
||||
value: Uint256::from(DEFAULT_BUILDER_PAYLOAD_VALUE_WEI),
|
||||
pubkey: builder.builder_sk.public_key().compress(),
|
||||
}),
|
||||
ForkName::Merge => BuilderBid::Merge(BuilderBidMerge {
|
||||
header: payload
|
||||
.as_merge()
|
||||
.map_err(|_| reject("incorrect payload variant"))?
|
||||
.into(),
|
||||
value: Uint256::from(DEFAULT_BUILDER_PAYLOAD_VALUE_WEI),
|
||||
pubkey: builder.builder_sk.public_key().compress(),
|
||||
}),
|
||||
ForkName::Base | ForkName::Altair => {
|
||||
return Err(reject("invalid fork"))
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
message.set_gas_limit(cached_data.gas_limit);
|
||||
|
||||
@@ -5,12 +5,12 @@ use crate::{
|
||||
},
|
||||
Config, *,
|
||||
};
|
||||
use keccak_hash::H256;
|
||||
use kzg::Kzg;
|
||||
use sensitive_url::SensitiveUrl;
|
||||
use task_executor::TaskExecutor;
|
||||
use tempfile::NamedTempFile;
|
||||
use tree_hash::TreeHash;
|
||||
use types::{Address, ChainSpec, Epoch, EthSpec, FullPayload, Hash256, MainnetEthSpec};
|
||||
use types::{Address, ChainSpec, Epoch, EthSpec, Hash256, MainnetEthSpec};
|
||||
|
||||
pub struct MockExecutionLayer<T: EthSpec> {
|
||||
pub server: MockServer<T>,
|
||||
@@ -133,20 +133,25 @@ impl<T: EthSpec> MockExecutionLayer<T> {
|
||||
let suggested_fee_recipient = self.el.get_suggested_fee_recipient(validator_index).await;
|
||||
let payload_attributes =
|
||||
PayloadAttributes::new(timestamp, prev_randao, suggested_fee_recipient, None, None);
|
||||
let payload: ExecutionPayload<T> = self
|
||||
|
||||
let block_proposal_content_type = self
|
||||
.el
|
||||
.get_payload::<FullPayload<T>>(
|
||||
.get_payload(
|
||||
parent_hash,
|
||||
&payload_attributes,
|
||||
forkchoice_update_params,
|
||||
builder_params,
|
||||
ForkName::Merge,
|
||||
&self.spec,
|
||||
BlockProductionVersion::FullV2,
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.to_payload()
|
||||
.into();
|
||||
.unwrap();
|
||||
|
||||
let payload: ExecutionPayload<T> = match block_proposal_content_type {
|
||||
BlockProposalContentsType::Full(block) => block.to_payload().into(),
|
||||
BlockProposalContentsType::Blinded(_) => panic!("Should always be a full payload"),
|
||||
};
|
||||
|
||||
let block_hash = payload.block_hash();
|
||||
assert_eq!(payload.parent_hash(), parent_hash);
|
||||
@@ -167,20 +172,64 @@ impl<T: EthSpec> MockExecutionLayer<T> {
|
||||
let suggested_fee_recipient = self.el.get_suggested_fee_recipient(validator_index).await;
|
||||
let payload_attributes =
|
||||
PayloadAttributes::new(timestamp, prev_randao, suggested_fee_recipient, None, None);
|
||||
let payload_header = self
|
||||
|
||||
let block_proposal_content_type = self
|
||||
.el
|
||||
.get_payload::<BlindedPayload<T>>(
|
||||
.get_payload(
|
||||
parent_hash,
|
||||
&payload_attributes,
|
||||
forkchoice_update_params,
|
||||
builder_params,
|
||||
ForkName::Merge,
|
||||
&self.spec,
|
||||
BlockProductionVersion::BlindedV2,
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.to_payload();
|
||||
.unwrap();
|
||||
|
||||
match block_proposal_content_type {
|
||||
BlockProposalContentsType::Full(block) => {
|
||||
let payload_header = block.to_payload();
|
||||
self.assert_valid_execution_payload_on_head(
|
||||
payload,
|
||||
payload_header,
|
||||
block_hash,
|
||||
parent_hash,
|
||||
block_number,
|
||||
timestamp,
|
||||
prev_randao,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
BlockProposalContentsType::Blinded(block) => {
|
||||
let payload_header = block.to_payload();
|
||||
self.assert_valid_execution_payload_on_head(
|
||||
payload,
|
||||
payload_header,
|
||||
block_hash,
|
||||
parent_hash,
|
||||
block_number,
|
||||
timestamp,
|
||||
prev_randao,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
};
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn assert_valid_execution_payload_on_head<Payload: AbstractExecPayload<T>>(
|
||||
&self,
|
||||
payload: ExecutionPayload<T>,
|
||||
payload_header: Payload,
|
||||
block_hash: ExecutionBlockHash,
|
||||
parent_hash: ExecutionBlockHash,
|
||||
block_number: u64,
|
||||
timestamp: u64,
|
||||
prev_randao: H256,
|
||||
) {
|
||||
assert_eq!(payload_header.block_hash(), block_hash);
|
||||
assert_eq!(payload_header.parent_hash(), parent_hash);
|
||||
assert_eq!(payload_header.block_number(), block_number);
|
||||
@@ -224,8 +273,6 @@ impl<T: EthSpec> MockExecutionLayer<T> {
|
||||
assert_eq!(head_execution_block.block_number(), block_number);
|
||||
assert_eq!(head_execution_block.block_hash(), block_hash);
|
||||
assert_eq!(head_execution_block.parent_hash(), parent_hash);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn move_to_block_prior_to_terminal_block(self) -> Self {
|
||||
|
||||
Reference in New Issue
Block a user