Skip to content
4 changes: 3 additions & 1 deletion beacon_node/beacon_chain/src/beacon_block_streamer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use types::{
};
use types::{
ExecutionPayload, ExecutionPayloadBellatrix, ExecutionPayloadCapella, ExecutionPayloadElectra,
ExecutionPayloadFulu, ExecutionPayloadGloas, ExecutionPayloadHeader,
ExecutionPayloadFulu, ExecutionPayloadGloas, ExecutionPayloadHeader, ExecutionPayloadHeze,
};

#[derive(PartialEq)]
Expand Down Expand Up @@ -102,6 +102,7 @@ fn reconstruct_default_header_block<E: EthSpec>(
ForkName::Electra => ExecutionPayloadElectra::default().into(),
ForkName::Fulu => ExecutionPayloadFulu::default().into(),
ForkName::Gloas => ExecutionPayloadGloas::default().into(),
ForkName::Heze => ExecutionPayloadHeze::default().into(),
ForkName::Base | ForkName::Altair => {
return Err(Error::PayloadReconstruction(format!(
"Block with fork variant {} has execution payload",
Expand Down Expand Up @@ -734,6 +735,7 @@ mod tests {
spec.electra_fork_epoch = Some(Epoch::new(electra_fork_epoch as u64));
spec.fulu_fork_epoch = Some(Epoch::new(fulu_fork_epoch as u64));
spec.gloas_fork_epoch = None;
spec.heze_fork_epoch = None;
let spec = Arc::new(spec);

let harness = get_harness(VALIDATOR_COUNT, spec.clone());
Expand Down
5 changes: 5 additions & 0 deletions beacon_node/beacon_chain/src/beacon_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6167,6 +6167,11 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
"Attempting to produce gloas beacon block via non gloas code path".to_owned(),
));
}
BeaconState::Heze(_) => {
return Err(BlockProductionError::HezeNotImplemented(
"Attempting to produce heze beacon block via non heze code path".to_owned(),
));
}
};

let block = SignedBeaconBlock::from_block(
Expand Down
7 changes: 7 additions & 0 deletions beacon_node/beacon_chain/src/block_production/gloas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,13 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
_phantom: PhantomData::<FullPayload<T::EthSpec>>,
},
}),
// TODO(heze): construct a `BeaconBlockHeze` here once Heze block production is
// wired up end-to-end (get_payload, envelope handling, etc).
BeaconState::Heze(_) => {
return Err(BlockProductionError::InvalidBlockVariant(
"Block production disabled for Heze".to_owned(),
));
}
};

let signed_beacon_block = SignedBeaconBlock::from_block(
Expand Down
4 changes: 2 additions & 2 deletions beacon_node/beacon_chain/src/data_column_verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1803,8 +1803,8 @@ mod test {
if !spec.is_fulu_scheduled() {
return;
}
// Gloas is not supported yet.
if spec.is_gloas_scheduled() {
// Gloas and Heze are not supported yet.
if spec.is_gloas_scheduled() || spec.is_heze_scheduled() {
return;
}

Expand Down
2 changes: 2 additions & 0 deletions beacon_node/beacon_chain/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,8 @@ pub enum BlockProductionError {
MissingExecutionPayloadEnvelope(Hash256),
// TODO(gloas): Remove this once Gloas is implemented
GloasNotImplemented(String),
// TODO(heze): Remove this once Heze is implemented
HezeNotImplemented(String),
}

easy_from_to!(BlockProcessingError, BlockProductionError);
Expand Down
5 changes: 5 additions & 0 deletions beacon_node/beacon_chain/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,10 @@ pub fn mock_execution_layer_from_parts<E: EthSpec>(
HARNESS_GENESIS_TIME
+ (spec.get_slot_duration().as_secs()) * E::slots_per_epoch() * epoch.as_u64()
});
let heze_time = spec.heze_fork_epoch.map(|epoch| {
HARNESS_GENESIS_TIME
+ (spec.get_slot_duration().as_secs()) * E::slots_per_epoch() * epoch.as_u64()
});

let kzg = get_kzg(&spec);

Expand All @@ -715,6 +719,7 @@ pub fn mock_execution_layer_from_parts<E: EthSpec>(
prague_time,
osaka_time,
amsterdam_time,
heze_time,
Some(JwtKey::from_slice(&DEFAULT_JWT_SECRET).unwrap()),
spec,
Some(kzg),
Expand Down
9 changes: 9 additions & 0 deletions beacon_node/beacon_chain/tests/block_verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1010,6 +1010,11 @@ async fn invalid_signature_attester_slashing() {
.push(attester_slashing.as_electra().unwrap().clone())
.expect("should update attester slashing");
}
BeaconBlockBodyRefMut::Heze(blk) => {
blk.attester_slashings
.push(attester_slashing.as_electra().unwrap().clone())
.expect("should update attester slashing");
}
}
snapshots[block_index].beacon_block =
Arc::new(SignedBeaconBlock::from_block(block, signature));
Expand Down Expand Up @@ -1075,6 +1080,10 @@ async fn invalid_signature_attestation() {
.attestations
.get_mut(0)
.map(|att| att.signature = junk_aggregate_signature()),
BeaconBlockBodyRefMut::Heze(blk) => blk
.attestations
.get_mut(0)
.map(|att| att.signature = junk_aggregate_signature()),
};

if block.body().attestations_len() > 0 {
Expand Down
2 changes: 1 addition & 1 deletion beacon_node/client/src/notifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ fn methods_required_for_fork(
missing_methods.push(ENGINE_NEW_PAYLOAD_V4);
}
}
ForkName::Gloas => {
ForkName::Gloas | ForkName::Heze => {
if !capabilities.get_payload_v6 {
missing_methods.push(ENGINE_GET_PAYLOAD_V6);
}
Expand Down
22 changes: 15 additions & 7 deletions beacon_node/execution_layer/src/engine_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ pub use types::{
};
use types::{
ExecutionPayloadBellatrix, ExecutionPayloadCapella, ExecutionPayloadDeneb,
ExecutionPayloadElectra, ExecutionPayloadFulu, ExecutionPayloadGloas, ExecutionRequests,
KzgProofs,
ExecutionPayloadElectra, ExecutionPayloadFulu, ExecutionPayloadGloas, ExecutionPayloadHeze,
ExecutionRequests, KzgProofs,
};
use types::{GRAFFITI_BYTES_LEN, Graffiti};

Expand All @@ -38,7 +38,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";
Expand Down Expand Up @@ -312,7 +312,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),
Expand All @@ -336,17 +336,19 @@ 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),
partial_getter(rename = "execution_requests_electra")
)]
pub requests: types::ExecutionRequestsElectra<E>,
#[superstruct(only(Gloas), partial_getter(rename = "execution_requests_gloas"))]
#[superstruct(only(Gloas, Heze), partial_getter(rename = "execution_requests_gloas"))]
pub requests: types::ExecutionRequestsGloas<E>,
}

Expand Down Expand Up @@ -426,6 +428,12 @@ impl<E: EthSpec> From<GetPayloadResponse<E>>
Some(inner.blobs_bundle),
Some(ExecutionRequests::Gloas(inner.requests)),
),
GetPayloadResponse::Heze(inner) => (
ExecutionPayload::Heze(inner.execution_payload),
inner.block_value,
Some(inner.blobs_bundle),
Some(ExecutionRequests::Gloas(inner.requests)),
),
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions beacon_node/execution_layer/src/engine_api/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,7 @@ impl HttpJsonRpc {
.try_into()
.map_err(Error::BadResponse)
}
// TODO(heze): add a Heze arm once Heze payload retrieval is implemented.
_ => Err(Error::UnsupportedForkVariant(format!(
"called get_payload_v6 with {}",
fork_name
Expand Down Expand Up @@ -1401,6 +1402,11 @@ impl HttpJsonRpc {
Err(Error::RequiredMethodUnsupported("engine_newPayloadV5"))
}
}
// TODO(heze): implement the Heze newPayload path once the engine API for Heze
// is specified.
NewPayloadRequest::Heze(_) => Err(Error::UnsupportedForkVariant(
"newPayload not implemented for Heze".to_string(),
)),
}
}

Expand Down Expand Up @@ -1450,6 +1456,11 @@ impl HttpJsonRpc {
Err(Error::RequiredMethodUnsupported("engine_getPayloadV6"))
}
}
// TODO(heze): implement the Heze getPayload path once the engine API for Heze
// is specified.
ForkName::Heze => Err(Error::UnsupportedForkVariant(
"getPayload not implemented for Heze".to_string(),
)),
ForkName::Base | ForkName::Altair => Err(Error::UnsupportedForkVariant(format!(
"called get_payload with {}",
fork_name
Expand Down
93 changes: 83 additions & 10 deletions beacon_node/execution_layer/src/engine_api/json_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,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"),
Expand Down Expand Up @@ -102,18 +102,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,
}
Expand Down Expand Up @@ -267,6 +267,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;

Expand All @@ -288,6 +316,7 @@ 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()?)),
}
}
}
Expand Down Expand Up @@ -442,6 +471,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;

Expand All @@ -463,6 +520,7 @@ 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()?)),
}
}
}
Expand Down Expand Up @@ -635,7 +693,7 @@ impl<E: EthSpec> TryFrom<JsonExecutionRequests> for ExecutionRequestsGloas<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")
Expand All @@ -661,13 +719,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,
}

Expand Down Expand Up @@ -738,6 +798,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)
})?,
}))
}
}
}
}
Expand Down
Loading
Loading