heze boilerplate

This commit is contained in:
Eitan Seri-Levi
2026-04-27 12:51:16 +02:00
parent fae7941b2d
commit a9a9ccfad0
70 changed files with 2643 additions and 177 deletions

View File

@@ -26,7 +26,8 @@ pub use types::{
};
use types::{
ExecutionPayloadBellatrix, ExecutionPayloadCapella, ExecutionPayloadDeneb,
ExecutionPayloadElectra, ExecutionPayloadFulu, ExecutionPayloadGloas, ExecutionRequests,
ExecutionPayloadElectra, ExecutionPayloadFulu, ExecutionPayloadGloas, ExecutionPayloadHeze,
ExecutionRequests,
KzgProofs,
};
use types::{GRAFFITI_BYTES_LEN, Graffiti};
@@ -39,7 +40,7 @@ mod new_payload_request;
pub use new_payload_request::{
NewPayloadRequest, NewPayloadRequestBellatrix, NewPayloadRequestCapella,
NewPayloadRequestDeneb, NewPayloadRequestElectra, NewPayloadRequestFulu,
NewPayloadRequestGloas,
NewPayloadRequestGloas, NewPayloadRequestHeze,
};
pub const LATEST_TAG: &str = "latest";
@@ -300,7 +301,7 @@ pub struct ProposeBlindedBlockResponse {
}
#[superstruct(
variants(Bellatrix, Capella, Deneb, Electra, Fulu, Gloas),
variants(Bellatrix, Capella, Deneb, Electra, Fulu, Gloas, Heze),
variant_attributes(derive(Clone, Debug, PartialEq),),
map_into(ExecutionPayload),
map_ref_into(ExecutionPayloadRef),
@@ -324,12 +325,14 @@ pub struct GetPayloadResponse<E: EthSpec> {
pub execution_payload: ExecutionPayloadFulu<E>,
#[superstruct(only(Gloas), partial_getter(rename = "execution_payload_gloas"))]
pub execution_payload: ExecutionPayloadGloas<E>,
#[superstruct(only(Heze), partial_getter(rename = "execution_payload_heze"))]
pub execution_payload: ExecutionPayloadHeze<E>,
pub block_value: Uint256,
#[superstruct(only(Deneb, Electra, Fulu, Gloas))]
#[superstruct(only(Deneb, Electra, Fulu, Gloas, Heze))]
pub blobs_bundle: BlobsBundle<E>,
#[superstruct(only(Deneb, Electra, Fulu, Gloas), partial_getter(copy))]
#[superstruct(only(Deneb, Electra, Fulu, Gloas, Heze), partial_getter(copy))]
pub should_override_builder: bool,
#[superstruct(only(Electra, Fulu, Gloas))]
#[superstruct(only(Electra, Fulu, Gloas, Heze))]
pub requests: ExecutionRequests<E>,
}
@@ -409,6 +412,12 @@ impl<E: EthSpec> From<GetPayloadResponse<E>>
Some(inner.blobs_bundle),
Some(inner.requests),
),
GetPayloadResponse::Heze(inner) => (
ExecutionPayload::Heze(inner.execution_payload),
inner.block_value,
Some(inner.blobs_bundle),
Some(inner.requests),
),
}
}
}

View File

@@ -933,6 +933,35 @@ impl HttpJsonRpc {
Ok(response.into())
}
pub async fn new_payload_v5_heze<E: EthSpec>(
&self,
new_payload_request_heze: NewPayloadRequestHeze<'_, E>,
) -> Result<PayloadStatusV1, Error> {
let params = json!([
JsonExecutionPayload::Heze(
new_payload_request_heze
.execution_payload
.clone()
.try_into()?
),
new_payload_request_heze.versioned_hashes,
new_payload_request_heze.parent_beacon_block_root,
new_payload_request_heze
.execution_requests
.get_execution_requests_list(),
]);
let response: JsonPayloadStatusV1 = self
.rpc_request(
ENGINE_NEW_PAYLOAD_V5,
params,
ENGINE_NEW_PAYLOAD_TIMEOUT * self.execution_timeout_multiplier,
)
.await?;
Ok(response.into())
}
pub async fn get_payload_v1<E: EthSpec>(
&self,
payload_id: PayloadId,
@@ -1096,6 +1125,18 @@ impl HttpJsonRpc {
.try_into()
.map_err(Error::BadResponse)
}
ForkName::Heze => {
let response: JsonGetPayloadResponseHeze<E> = self
.rpc_request(
ENGINE_GET_PAYLOAD_V6,
params,
ENGINE_GET_PAYLOAD_TIMEOUT * self.execution_timeout_multiplier,
)
.await?;
JsonGetPayloadResponse::Heze(response)
.try_into()
.map_err(Error::BadResponse)
}
_ => Err(Error::UnsupportedForkVariant(format!(
"called get_payload_v6 with {}",
fork_name
@@ -1420,6 +1461,13 @@ impl HttpJsonRpc {
Err(Error::RequiredMethodUnsupported("engine_newPayloadV5"))
}
}
NewPayloadRequest::Heze(new_payload_request_heze) => {
if engine_capabilities.new_payload_v5 {
self.new_payload_v5_heze(new_payload_request_heze).await
} else {
Err(Error::RequiredMethodUnsupported("engine_newPayloadV5"))
}
}
}
}
@@ -1469,6 +1517,13 @@ impl HttpJsonRpc {
Err(Error::RequiredMethodUnsupported("engine_getPayloadV6"))
}
}
ForkName::Heze => {
if engine_capabilities.get_payload_v6 {
self.get_payload_v6(fork_name, payload_id).await
} else {
Err(Error::RequiredMethodUnsupported("engine_getPayloadV6"))
}
}
ForkName::Base | ForkName::Altair => Err(Error::UnsupportedForkVariant(format!(
"called get_payload with {}",
fork_name

View File

@@ -64,7 +64,7 @@ pub struct JsonPayloadIdResponse {
}
#[superstruct(
variants(Bellatrix, Capella, Deneb, Electra, Fulu, Gloas),
variants(Bellatrix, Capella, Deneb, Electra, Fulu, Gloas, Heze),
variant_attributes(
derive(Debug, PartialEq, Default, Serialize, Deserialize,),
serde(bound = "E: EthSpec", rename_all = "camelCase"),
@@ -99,18 +99,18 @@ pub struct JsonExecutionPayload<E: EthSpec> {
pub block_hash: ExecutionBlockHash,
#[serde(with = "ssz_types::serde_utils::list_of_hex_var_list")]
pub transactions: Transactions<E>,
#[superstruct(only(Capella, Deneb, Electra, Fulu, Gloas))]
#[superstruct(only(Capella, Deneb, Electra, Fulu, Gloas, Heze))]
pub withdrawals: VariableList<JsonWithdrawal, E::MaxWithdrawalsPerPayload>,
#[superstruct(only(Deneb, Electra, Fulu, Gloas))]
#[superstruct(only(Deneb, Electra, Fulu, Gloas, Heze))]
#[serde(with = "serde_utils::u64_hex_be")]
pub blob_gas_used: u64,
#[superstruct(only(Deneb, Electra, Fulu, Gloas))]
#[superstruct(only(Deneb, Electra, Fulu, Gloas, Heze))]
#[serde(with = "serde_utils::u64_hex_be")]
pub excess_blob_gas: u64,
#[superstruct(only(Gloas))]
#[superstruct(only(Gloas, Heze))]
#[serde(with = "ssz_types::serde_utils::hex_var_list")]
pub block_access_list: VariableList<u8, E::MaxBytesPerTransaction>,
#[superstruct(only(Gloas))]
#[superstruct(only(Gloas, Heze))]
#[serde(with = "serde_utils::u64_hex_be")]
pub slot_number: u64,
}
@@ -264,6 +264,34 @@ impl<E: EthSpec> TryFrom<ExecutionPayloadGloas<E>> for JsonExecutionPayloadGloas
}
}
impl<E: EthSpec> TryFrom<ExecutionPayloadHeze<E>> for JsonExecutionPayloadHeze<E> {
type Error = ssz_types::Error;
fn try_from(payload: ExecutionPayloadHeze<E>) -> Result<Self, Self::Error> {
Ok(JsonExecutionPayloadHeze {
parent_hash: payload.parent_hash,
fee_recipient: payload.fee_recipient,
state_root: payload.state_root,
receipts_root: payload.receipts_root,
logs_bloom: payload.logs_bloom,
prev_randao: payload.prev_randao,
block_number: payload.block_number,
gas_limit: payload.gas_limit,
gas_used: payload.gas_used,
timestamp: payload.timestamp,
extra_data: payload.extra_data,
base_fee_per_gas: payload.base_fee_per_gas,
block_hash: payload.block_hash,
transactions: payload.transactions,
withdrawals: withdrawals_to_json(payload.withdrawals)?,
blob_gas_used: payload.blob_gas_used,
excess_blob_gas: payload.excess_blob_gas,
block_access_list: payload.block_access_list,
slot_number: payload.slot_number.into(),
})
}
}
impl<E: EthSpec> TryFrom<ExecutionPayload<E>> for JsonExecutionPayload<E> {
type Error = ssz_types::Error;
@@ -285,6 +313,9 @@ impl<E: EthSpec> TryFrom<ExecutionPayload<E>> for JsonExecutionPayload<E> {
ExecutionPayload::Gloas(payload) => {
Ok(JsonExecutionPayload::Gloas(payload.try_into()?))
}
ExecutionPayload::Heze(payload) => {
Ok(JsonExecutionPayload::Heze(payload.try_into()?))
}
}
}
}
@@ -439,6 +470,34 @@ impl<E: EthSpec> TryFrom<JsonExecutionPayloadGloas<E>> for ExecutionPayloadGloas
}
}
impl<E: EthSpec> TryFrom<JsonExecutionPayloadHeze<E>> for ExecutionPayloadHeze<E> {
type Error = ssz_types::Error;
fn try_from(payload: JsonExecutionPayloadHeze<E>) -> Result<Self, Self::Error> {
Ok(ExecutionPayloadHeze {
parent_hash: payload.parent_hash,
fee_recipient: payload.fee_recipient,
state_root: payload.state_root,
receipts_root: payload.receipts_root,
logs_bloom: payload.logs_bloom,
prev_randao: payload.prev_randao,
block_number: payload.block_number,
gas_limit: payload.gas_limit,
gas_used: payload.gas_used,
timestamp: payload.timestamp,
extra_data: payload.extra_data,
base_fee_per_gas: payload.base_fee_per_gas,
block_hash: payload.block_hash,
transactions: payload.transactions,
withdrawals: withdrawals_from_json(payload.withdrawals)?,
blob_gas_used: payload.blob_gas_used,
excess_blob_gas: payload.excess_blob_gas,
block_access_list: payload.block_access_list,
slot_number: payload.slot_number.into(),
})
}
}
impl<E: EthSpec> TryFrom<JsonExecutionPayload<E>> for ExecutionPayload<E> {
type Error = ssz_types::Error;
@@ -460,6 +519,9 @@ impl<E: EthSpec> TryFrom<JsonExecutionPayload<E>> for ExecutionPayload<E> {
JsonExecutionPayload::Gloas(payload) => {
Ok(ExecutionPayload::Gloas(payload.try_into()?))
}
JsonExecutionPayload::Heze(payload) => {
Ok(ExecutionPayload::Heze(payload.try_into()?))
}
}
}
}
@@ -573,7 +635,7 @@ impl<E: EthSpec> TryFrom<JsonExecutionRequests> for ExecutionRequests<E> {
}
#[superstruct(
variants(Bellatrix, Capella, Deneb, Electra, Fulu, Gloas),
variants(Bellatrix, Capella, Deneb, Electra, Fulu, Gloas, Heze),
variant_attributes(
derive(Debug, PartialEq, Serialize, Deserialize),
serde(bound = "E: EthSpec", rename_all = "camelCase")
@@ -599,13 +661,15 @@ pub struct JsonGetPayloadResponse<E: EthSpec> {
pub execution_payload: JsonExecutionPayloadFulu<E>,
#[superstruct(only(Gloas), partial_getter(rename = "execution_payload_gloas"))]
pub execution_payload: JsonExecutionPayloadGloas<E>,
#[superstruct(only(Heze), partial_getter(rename = "execution_payload_heze"))]
pub execution_payload: JsonExecutionPayloadHeze<E>,
#[serde(with = "serde_utils::u256_hex_be")]
pub block_value: Uint256,
#[superstruct(only(Deneb, Electra, Fulu, Gloas))]
#[superstruct(only(Deneb, Electra, Fulu, Gloas, Heze))]
pub blobs_bundle: JsonBlobsBundleV1<E>,
#[superstruct(only(Deneb, Electra, Fulu, Gloas))]
#[superstruct(only(Deneb, Electra, Fulu, Gloas, Heze))]
pub should_override_builder: bool,
#[superstruct(only(Electra, Fulu, Gloas))]
#[superstruct(only(Electra, Fulu, Gloas, Heze))]
pub execution_requests: JsonExecutionRequests,
}
@@ -676,6 +740,19 @@ impl<E: EthSpec> TryFrom<JsonGetPayloadResponse<E>> for GetPayloadResponse<E> {
})?,
}))
}
JsonGetPayloadResponse::Heze(response) => {
Ok(GetPayloadResponse::Heze(GetPayloadResponseHeze {
execution_payload: response.execution_payload.try_into().map_err(|e| {
format!("Failed to convert json to execution payload: {:?}", e)
})?,
block_value: response.block_value,
blobs_bundle: response.blobs_bundle.into(),
should_override_builder: response.should_override_builder,
requests: response.execution_requests.try_into().map_err(|e| {
format!("Failed to convert json to execution requests: {:?}", e)
})?,
}))
}
}
}
}

View File

@@ -9,11 +9,12 @@ use types::{
};
use types::{
ExecutionPayloadBellatrix, ExecutionPayloadCapella, ExecutionPayloadDeneb,
ExecutionPayloadElectra, ExecutionPayloadFulu, ExecutionPayloadGloas, ExecutionRequests,
ExecutionPayloadElectra, ExecutionPayloadFulu, ExecutionPayloadGloas, ExecutionPayloadHeze,
ExecutionRequests,
};
#[superstruct(
variants(Bellatrix, Capella, Deneb, Electra, Fulu, Gloas),
variants(Bellatrix, Capella, Deneb, Electra, Fulu, Gloas, Heze),
variant_attributes(derive(Clone, Debug, PartialEq),),
map_into(ExecutionPayload),
map_ref_into(ExecutionPayloadRef),
@@ -43,11 +44,13 @@ pub struct NewPayloadRequest<'block, E: EthSpec> {
pub execution_payload: &'block ExecutionPayloadFulu<E>,
#[superstruct(only(Gloas), partial_getter(rename = "execution_payload_gloas"))]
pub execution_payload: &'block ExecutionPayloadGloas<E>,
#[superstruct(only(Deneb, Electra, Fulu, Gloas))]
#[superstruct(only(Heze), partial_getter(rename = "execution_payload_heze"))]
pub execution_payload: &'block ExecutionPayloadHeze<E>,
#[superstruct(only(Deneb, Electra, Fulu, Gloas, Heze))]
pub versioned_hashes: Vec<VersionedHash>,
#[superstruct(only(Deneb, Electra, Fulu, Gloas))]
#[superstruct(only(Deneb, Electra, Fulu, Gloas, Heze))]
pub parent_beacon_block_root: Hash256,
#[superstruct(only(Electra, Fulu, Gloas))]
#[superstruct(only(Electra, Fulu, Gloas, Heze))]
pub execution_requests: &'block ExecutionRequests<E>,
}
@@ -60,6 +63,7 @@ impl<'block, E: EthSpec> NewPayloadRequest<'block, E> {
Self::Electra(payload) => payload.execution_payload.parent_hash,
Self::Fulu(payload) => payload.execution_payload.parent_hash,
Self::Gloas(payload) => payload.execution_payload.parent_hash,
Self::Heze(payload) => payload.execution_payload.parent_hash,
}
}
@@ -71,6 +75,7 @@ impl<'block, E: EthSpec> NewPayloadRequest<'block, E> {
Self::Electra(payload) => payload.execution_payload.block_hash,
Self::Fulu(payload) => payload.execution_payload.block_hash,
Self::Gloas(payload) => payload.execution_payload.block_hash,
Self::Heze(payload) => payload.execution_payload.block_hash,
}
}
@@ -82,6 +87,7 @@ impl<'block, E: EthSpec> NewPayloadRequest<'block, E> {
Self::Electra(payload) => payload.execution_payload.block_number,
Self::Fulu(payload) => payload.execution_payload.block_number,
Self::Gloas(payload) => payload.execution_payload.block_number,
Self::Heze(payload) => payload.execution_payload.block_number,
}
}
@@ -93,6 +99,7 @@ impl<'block, E: EthSpec> NewPayloadRequest<'block, E> {
Self::Electra(request) => ExecutionPayloadRef::Electra(request.execution_payload),
Self::Fulu(request) => ExecutionPayloadRef::Fulu(request.execution_payload),
Self::Gloas(request) => ExecutionPayloadRef::Gloas(request.execution_payload),
Self::Heze(request) => ExecutionPayloadRef::Heze(request.execution_payload),
}
}
@@ -106,6 +113,7 @@ impl<'block, E: EthSpec> NewPayloadRequest<'block, E> {
Self::Electra(request) => ExecutionPayload::Electra(request.execution_payload.clone()),
Self::Fulu(request) => ExecutionPayload::Fulu(request.execution_payload.clone()),
Self::Gloas(request) => ExecutionPayload::Gloas(request.execution_payload.clone()),
Self::Heze(request) => ExecutionPayload::Heze(request.execution_payload.clone()),
}
}
@@ -222,6 +230,7 @@ impl<'a, E: EthSpec> TryFrom<BeaconBlockRef<'a, E>> for NewPayloadRequest<'a, E>
execution_requests: &block_ref.body.execution_requests,
})),
BeaconBlockRef::Gloas(_) => Err(Self::Error::IncorrectStateVariant),
BeaconBlockRef::Heze(_) => Err(Self::Error::IncorrectStateVariant),
}
}
}
@@ -244,6 +253,7 @@ impl<'a, E: EthSpec> TryFrom<ExecutionPayloadRef<'a, E>> for NewPayloadRequest<'
ExecutionPayloadRef::Fulu(_) => Err(Self::Error::IncorrectStateVariant),
//TODO(EIP7732): Probably time to just get rid of this
ExecutionPayloadRef::Gloas(_) => Err(Self::Error::IncorrectStateVariant),
ExecutionPayloadRef::Heze(_) => Err(Self::Error::IncorrectStateVariant),
}
}
}

View File

@@ -44,6 +44,7 @@ use tokio_stream::wrappers::WatchStream;
use tracing::{Instrument, debug, debug_span, error, info, instrument, warn};
use tree_hash::TreeHash;
use types::ExecutionPayloadGloas;
use types::ExecutionPayloadHeze;
use types::builder::BuilderBid;
use types::execution::BlockProductionVersion;
use types::kzg_ext::KzgCommitments;
@@ -219,6 +220,26 @@ impl<E: EthSpec> From<GetPayloadResponseGloas<E>> for BlockProposalContentsGloas
}
}
pub struct BlockProposalContentsHeze<E: EthSpec> {
pub payload: ExecutionPayloadHeze<E>,
pub payload_value: Uint256,
pub blob_kzg_commitments: KzgCommitments<E>,
pub blobs_and_proofs: (BlobsList<E>, KzgProofs<E>),
pub execution_requests: ExecutionRequests<E>,
}
impl<E: EthSpec> From<GetPayloadResponseHeze<E>> for BlockProposalContentsHeze<E> {
fn from(response: GetPayloadResponseHeze<E>) -> Self {
Self {
payload: response.execution_payload,
payload_value: response.block_value,
blob_kzg_commitments: response.blobs_bundle.commitments,
blobs_and_proofs: (response.blobs_bundle.blobs, response.blobs_bundle.proofs),
execution_requests: response.requests,
}
}
}
pub enum BlockProposalContents<E: EthSpec, Payload: AbstractExecPayload<E>> {
Payload {
payload: Payload,
@@ -930,6 +951,44 @@ impl<E: EthSpec> ExecutionLayer<E> {
Ok(payload_response.into())
}
/// Maps to the `engine_getPayload` JSON-RPC call for post-Heze payload construction.
///
/// However, it will attempt to call `self.prepare_payload` if it cannot find an existing
/// payload id for the given parameters.
///
/// ## Fallback Behavior
///
/// The result will be returned from the first node that returns successfully. No more nodes
/// will be contacted.
#[instrument(level = "debug", skip_all)]
pub async fn get_payload_heze(
&self,
payload_parameters: PayloadParameters<'_>,
) -> Result<BlockProposalContentsHeze<E>, Error> {
let payload_response_type = self.get_full_payload_caching(payload_parameters).await?;
let GetPayloadResponseType::Full(payload_response) = payload_response_type else {
return Err(Error::Unexpected(
"get_payload_heze should never return a blinded payload".to_owned(),
));
};
let GetPayloadResponse::Heze(payload_response) = payload_response else {
return Err(Error::Unexpected(
"get_payload_heze should always return a heze `GetPayloadResponse` variant"
.to_owned(),
));
};
metrics::inc_counter_vec(
&metrics::EXECUTION_LAYER_GET_PAYLOAD_OUTCOME,
&[metrics::SUCCESS],
);
metrics::inc_counter_vec(
&metrics::EXECUTION_LAYER_GET_PAYLOAD_SOURCE,
&[metrics::LOCAL],
);
Ok(payload_response.into())
}
/// Maps to the `engine_getPayload` JSON-RPC call.
///
/// However, it will attempt to call `self.prepare_payload` if it cannot find an existing
@@ -1690,6 +1749,9 @@ impl<E: EthSpec> ExecutionLayer<E> {
ForkName::Gloas => {
return Err(Error::InvalidForkForPayload);
}
ForkName::Heze => {
return Err(Error::InvalidForkForPayload);
}
};
return Ok(Some(payload));
}

View File

@@ -26,7 +26,8 @@ use tree_hash_derive::TreeHash;
use types::{
Blob, ChainSpec, EthSpec, ExecutionBlockHash, ExecutionPayload, ExecutionPayloadBellatrix,
ExecutionPayloadCapella, ExecutionPayloadDeneb, ExecutionPayloadElectra, ExecutionPayloadFulu,
ExecutionPayloadGloas, ExecutionPayloadHeader, ExecutionRequests, ForkName, Hash256, KzgProofs,
ExecutionPayloadGloas, ExecutionPayloadHeze, ExecutionPayloadHeader, ExecutionRequests,
ForkName, Hash256, KzgProofs,
Transaction, Transactions, Uint256,
};
@@ -155,6 +156,7 @@ pub struct ExecutionBlockGenerator<E: EthSpec> {
pub prague_time: Option<u64>, // electra
pub osaka_time: Option<u64>, // fulu
pub amsterdam_time: Option<u64>, // gloas
pub heze_time: Option<u64>, // heze
/*
* deneb stuff
*/
@@ -185,6 +187,7 @@ impl<E: EthSpec> ExecutionBlockGenerator<E> {
prague_time: Option<u64>,
osaka_time: Option<u64>,
amsterdam_time: Option<u64>,
heze_time: Option<u64>,
kzg: Option<Arc<Kzg>>,
) -> Self {
let mut generator = Self {
@@ -204,6 +207,7 @@ impl<E: EthSpec> ExecutionBlockGenerator<E> {
prague_time,
osaka_time,
amsterdam_time,
heze_time,
blobs_bundles: <_>::default(),
kzg,
rng: make_rng(),
@@ -255,6 +259,7 @@ impl<E: EthSpec> ExecutionBlockGenerator<E> {
pub fn get_fork_at_timestamp(&self, timestamp: u64) -> ForkName {
let forks = [
(self.heze_time, ForkName::Heze),
(self.amsterdam_time, ForkName::Gloas),
(self.osaka_time, ForkName::Fulu),
(self.prague_time, ForkName::Electra),
@@ -778,6 +783,27 @@ impl<E: EthSpec> ExecutionBlockGenerator<E> {
block_access_list: VariableList::empty(),
slot_number: pa.slot_number.into(),
}),
ForkName::Heze => ExecutionPayload::Heze(ExecutionPayloadHeze {
parent_hash: head_block_hash,
fee_recipient: pa.suggested_fee_recipient,
receipts_root: Hash256::repeat_byte(42),
state_root: Hash256::repeat_byte(43),
logs_bloom: vec![0; 256].try_into().unwrap(),
prev_randao: pa.prev_randao,
block_number: parent.block_number() + 1,
gas_limit: DEFAULT_GAS_LIMIT,
gas_used: GAS_USED,
timestamp: pa.timestamp,
extra_data: "block gen was here".as_bytes().to_vec().try_into().unwrap(),
base_fee_per_gas: Uint256::from(1u64),
block_hash: ExecutionBlockHash::zero(),
transactions: vec![].try_into().unwrap(),
withdrawals: pa.withdrawals.clone().try_into().unwrap(),
blob_gas_used: 0,
excess_blob_gas: 0,
block_access_list: VariableList::empty(),
slot_number: pa.slot_number.into(),
}),
_ => unreachable!(),
},
};
@@ -969,6 +995,14 @@ pub fn generate_genesis_header<E: EthSpec>(spec: &ChainSpec) -> Option<Execution
*header.transactions_root_mut() = empty_transactions_root;
Some(header)
}
ForkName::Heze => {
// TODO(heze): we are using a Fulu header for now, but this gets fixed up by the
// genesis builder anyway which translates it to bid/latest_block_hash.
let mut header = ExecutionPayloadHeader::Fulu(<_>::default());
*header.block_hash_mut() = genesis_block_hash.unwrap_or_default();
*header.transactions_root_mut() = empty_transactions_root;
Some(header)
}
}
}

View File

@@ -126,9 +126,16 @@ pub async fn handle_rpc<E: EthSpec>(
.map(|jep| JsonExecutionPayload::Electra(jep))
})
.map_err(|s| (s, BAD_PARAMS_ERROR_CODE))?,
ENGINE_NEW_PAYLOAD_V5 => get_param::<JsonExecutionPayloadGloas<E>>(params, 0)
.map(|jep| JsonExecutionPayload::Gloas(jep))
.map_err(|s| (s, BAD_PARAMS_ERROR_CODE))?,
ENGINE_NEW_PAYLOAD_V5 => {
// Try Heze first, fall back to Gloas
get_param::<JsonExecutionPayloadHeze<E>>(params, 0)
.map(|jep| JsonExecutionPayload::Heze(jep))
.or_else(|_| {
get_param::<JsonExecutionPayloadGloas<E>>(params, 0)
.map(|jep| JsonExecutionPayload::Gloas(jep))
})
.map_err(|s| (s, BAD_PARAMS_ERROR_CODE))?
}
_ => unreachable!(),
};
@@ -238,6 +245,14 @@ pub async fn handle_rpc<E: EthSpec>(
));
}
}
ForkName::Heze => {
if method != ENGINE_NEW_PAYLOAD_V5 {
return Err((
format!("{} called after Heze fork!", method),
GENERIC_ERROR_CODE,
));
}
}
_ => unreachable!(),
};
@@ -377,6 +392,24 @@ pub async fn handle_rpc<E: EthSpec>(
));
}
// validate method called correctly according to heze fork time
if ctx
.execution_block_generator
.read()
.get_fork_at_timestamp(response.timestamp())
== ForkName::Heze
&& (method == ENGINE_GET_PAYLOAD_V1
|| method == ENGINE_GET_PAYLOAD_V2
|| method == ENGINE_GET_PAYLOAD_V3
|| method == ENGINE_GET_PAYLOAD_V4
|| method == ENGINE_GET_PAYLOAD_V5)
{
return Err((
format!("{} called after Heze fork!", method),
FORK_REQUEST_MISMATCH_ERROR_CODE,
));
}
match method {
ENGINE_GET_PAYLOAD_V1 => Ok(serde_json::to_value(
JsonExecutionPayload::try_from(response).unwrap(),
@@ -488,6 +521,23 @@ pub async fn handle_rpc<E: EthSpec>(
})
.unwrap()
}
JsonExecutionPayload::Heze(execution_payload) => {
serde_json::to_value(JsonGetPayloadResponseHeze {
execution_payload,
block_value: Uint256::from(DEFAULT_MOCK_EL_PAYLOAD_VALUE_WEI),
blobs_bundle: maybe_blobs
.ok_or((
"No blobs returned despite V6 Payload".to_string(),
GENERIC_ERROR_CODE,
))?
.into(),
should_override_builder: false,
execution_requests: maybe_execution_requests
.unwrap_or_default()
.into(),
})
.unwrap()
}
_ => unreachable!(),
})
}
@@ -653,6 +703,14 @@ pub async fn handle_rpc<E: EthSpec>(
));
}
}
ForkName::Heze => {
if method != ENGINE_FORKCHOICE_UPDATED_V4 {
return Err((
format!("{} called after Heze fork! Use V4.", method),
FORK_REQUEST_MISMATCH_ERROR_CODE,
));
}
}
_ => unreachable!(),
};
}

View File

@@ -475,6 +475,10 @@ impl<E: EthSpec> MockBuilder<E> {
// TODO(EIP7732) Check if this is how we want to do error handling for gloas
return Err("invalid fork".to_string());
}
SignedBlindedBeaconBlock::Heze(_) => {
// TODO(EIP7732) Check if this is how we want to do error handling for heze
return Err("invalid fork".to_string());
}
};
let block_hash = block
.message()
@@ -593,6 +597,10 @@ impl<E: EthSpec> MockBuilder<E> {
// TODO(EIP7732) Check if this is how we want to do error handling for gloas
return Err("invalid fork".to_string());
}
ForkName::Heze => {
// TODO(EIP7732) Check if this is how we want to do error handling for heze
return Err("invalid fork".to_string());
}
ForkName::Fulu => BuilderBid::Fulu(BuilderBidFulu {
header: payload
.as_fulu()
@@ -912,7 +920,7 @@ impl<E: EthSpec> MockBuilder<E> {
Some(head_block_root),
None,
),
ForkName::Gloas => PayloadAttributes::new(
ForkName::Gloas | ForkName::Heze => PayloadAttributes::new(
timestamp,
*prev_randao,
fee_recipient,

View File

@@ -24,6 +24,7 @@ impl<E: EthSpec> MockExecutionLayer<E> {
None,
None,
None,
None,
Some(JwtKey::from_slice(&DEFAULT_JWT_SECRET).unwrap()),
Arc::new(spec),
None,
@@ -38,6 +39,7 @@ impl<E: EthSpec> MockExecutionLayer<E> {
prague_time: Option<u64>,
osaka_time: Option<u64>,
amsterdam_time: Option<u64>,
heze_time: Option<u64>,
jwt_key: Option<JwtKey>,
spec: Arc<ChainSpec>,
kzg: Option<Arc<Kzg>>,
@@ -53,6 +55,7 @@ impl<E: EthSpec> MockExecutionLayer<E> {
prague_time,
osaka_time,
amsterdam_time,
heze_time,
kzg,
);

View File

@@ -86,6 +86,7 @@ pub struct MockExecutionConfig {
pub prague_time: Option<u64>,
pub osaka_time: Option<u64>,
pub amsterdam_time: Option<u64>,
pub heze_time: Option<u64>,
}
impl Default for MockExecutionConfig {
@@ -98,6 +99,7 @@ impl Default for MockExecutionConfig {
prague_time: None,
osaka_time: None,
amsterdam_time: None,
heze_time: None,
}
}
}
@@ -119,6 +121,7 @@ impl<E: EthSpec> MockServer<E> {
None, // FIXME(electra): should this be the default?
None, // FIXME(fulu): should this be the default?
None, // FIXME(gloas): should this be the default?
None, // FIXME(heze): should this be the default?
None,
)
}
@@ -137,6 +140,7 @@ impl<E: EthSpec> MockServer<E> {
prague_time,
osaka_time,
amsterdam_time,
heze_time,
} = config;
let last_echo_request = Arc::new(RwLock::new(None));
let preloaded_responses = Arc::new(Mutex::new(vec![]));
@@ -146,6 +150,7 @@ impl<E: EthSpec> MockServer<E> {
prague_time,
osaka_time,
amsterdam_time,
heze_time,
kzg,
);
@@ -207,6 +212,7 @@ impl<E: EthSpec> MockServer<E> {
prague_time: Option<u64>,
osaka_time: Option<u64>,
amsterdam_time: Option<u64>,
heze_time: Option<u64>,
kzg: Option<Arc<Kzg>>,
) -> Self {
Self::new_with_config(
@@ -219,6 +225,7 @@ impl<E: EthSpec> MockServer<E> {
prague_time,
osaka_time,
amsterdam_time,
heze_time,
},
kzg,
)