Many fixes

This commit is contained in:
Eitan Seri-Levi
2026-05-09 18:58:08 +03:00
parent 2356bdd256
commit 1b2cf3ba01
45 changed files with 667 additions and 1328 deletions

View File

@@ -6,8 +6,8 @@ use crate::http::{
ENGINE_GET_INCLUSION_LIST_V1, ENGINE_GET_PAYLOAD_BODIES_BY_HASH_V1,
ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V1, ENGINE_GET_PAYLOAD_V1, ENGINE_GET_PAYLOAD_V2,
ENGINE_GET_PAYLOAD_V3, ENGINE_GET_PAYLOAD_V4, ENGINE_GET_PAYLOAD_V5, ENGINE_GET_PAYLOAD_V6,
ENGINE_IS_INCLUSION_LIST_SATISFIED_V1, ENGINE_NEW_PAYLOAD_V1, ENGINE_NEW_PAYLOAD_V2,
ENGINE_NEW_PAYLOAD_V3, ENGINE_NEW_PAYLOAD_V4, ENGINE_NEW_PAYLOAD_V5, ENGINE_NEW_PAYLOAD_V6,
ENGINE_NEW_PAYLOAD_V1, ENGINE_NEW_PAYLOAD_V2, ENGINE_NEW_PAYLOAD_V3, ENGINE_NEW_PAYLOAD_V4,
ENGINE_NEW_PAYLOAD_V5, ENGINE_NEW_PAYLOAD_V6,
};
use eth2::types::{
BlobsBundle, SsePayloadAttributes, SsePayloadAttributesV1, SsePayloadAttributesV2,
@@ -589,37 +589,6 @@ impl<E: EthSpec> ExecutionPayloadBodyV1<E> {
))
}
}
ExecutionPayloadHeader::Heze(header) => {
if let Some(withdrawals) = self.withdrawals {
Ok(ExecutionPayload::Heze(ExecutionPayloadHeze {
parent_hash: header.parent_hash,
fee_recipient: header.fee_recipient,
state_root: header.state_root,
receipts_root: header.receipts_root,
logs_bloom: header.logs_bloom,
prev_randao: header.prev_randao,
block_number: header.block_number,
gas_limit: header.gas_limit,
gas_used: header.gas_used,
timestamp: header.timestamp,
extra_data: header.extra_data,
base_fee_per_gas: header.base_fee_per_gas,
block_hash: header.block_hash,
transactions: self.transactions,
withdrawals,
blob_gas_used: header.blob_gas_used,
excess_blob_gas: header.excess_blob_gas,
// TODO(heze): block_access_list and slot_number are not available in ExecutionPayloadBodyV1
block_access_list: Default::default(),
slot_number: Default::default(),
}))
} else {
Err(format!(
"block {} is post capella but payload body doesn't have withdrawals",
header.block_hash
))
}
}
ExecutionPayloadHeader::Fulu(header) => {
if let Some(withdrawals) = self.withdrawals {
Ok(ExecutionPayload::Fulu(ExecutionPayloadFulu {
@@ -678,7 +647,6 @@ pub struct EngineCapabilities {
pub get_inclusion_list_v1: bool,
pub get_blobs_v3: bool,
pub forkchoice_updated_v5: bool,
pub is_inclusion_list_satisfied_v1: bool,
}
impl EngineCapabilities {
@@ -756,9 +724,6 @@ impl EngineCapabilities {
if self.forkchoice_updated_v5 {
response.push(ENGINE_FORKCHOICE_UPDATED_V5);
}
if self.is_inclusion_list_satisfied_v1 {
response.push(ENGINE_IS_INCLUSION_LIST_SATISFIED_V1);
}
response
}

View File

@@ -72,9 +72,6 @@ pub const ENGINE_GET_BLOBS_TIMEOUT: Duration = Duration::from_secs(1);
pub const ENGINE_GET_INCLUSION_LIST_V1: &str = "engine_getInclusionListV1";
pub const ENGINE_GET_INCLUSION_LIST_TIMEOUT: Duration = Duration::from_secs(1);
pub const ENGINE_IS_INCLUSION_LIST_SATISFIED_V1: &str = "engine_isInclusionListSatisfiedV1";
pub const ENGINE_IS_INCLUSION_LIST_SATISFIED_TIMEOUT: Duration = Duration::from_secs(1);
/// This error is returned during a `chainId` call by Geth.
pub const EIP155_ERROR_STR: &str = "chain not synced beyond EIP-155 replay-protection fork block";
/// This code is returned by all clients when a method is not supported
@@ -105,7 +102,6 @@ pub static LIGHTHOUSE_CAPABILITIES: &[&str] = &[
ENGINE_GET_BLOBS_V1,
ENGINE_GET_BLOBS_V2,
ENGINE_GET_INCLUSION_LIST_V1,
ENGINE_IS_INCLUSION_LIST_SATISFIED_V1,
];
/// We opt to initialize the JsonClientVersionV1 rather than the ClientVersionV1
@@ -932,48 +928,6 @@ impl HttpJsonRpc {
Ok(response.into())
}
/// Calls engine_newPayloadV6 with a Gloas-shaped payload.
/// Gloas and Heze have identical payload wire formats; only the version number differs.
/// Used when a Heze-fork ePBS envelope arrives but the payload type is still Gloas.
pub async fn new_payload_v6_from_gloas<E: EthSpec>(
&self,
new_payload_request_gloas: NewPayloadRequestGloas<'_, E>,
) -> Result<PayloadStatusV1, Error> {
let il_transactions: Vec<String> = new_payload_request_gloas
.il_transactions
.iter()
.map(|tx| {
let bytes: Vec<u8> = tx.clone().into();
format!("0x{}", hex::encode(bytes))
})
.collect();
let params = json!([
JsonExecutionPayload::Gloas(
new_payload_request_gloas
.execution_payload
.clone()
.try_into()?
),
new_payload_request_gloas.versioned_hashes,
new_payload_request_gloas.parent_beacon_block_root,
new_payload_request_gloas
.execution_requests
.get_execution_requests_list(),
il_transactions
]);
let response: JsonPayloadStatusV1 = self
.rpc_request(
ENGINE_NEW_PAYLOAD_V6,
params,
ENGINE_NEW_PAYLOAD_TIMEOUT * self.execution_timeout_multiplier,
)
.await?;
Ok(response.into())
}
pub async fn new_payload_v5_gloas<E: EthSpec>(
&self,
new_payload_request_gloas: NewPayloadRequestGloas<'_, E>,
@@ -1003,45 +957,6 @@ 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 il_transactions: Vec<String> = new_payload_request_heze
.il_transactions
.iter()
.map(|tx| {
let bytes: Vec<u8> = tx.clone().into();
format!("0x{}", hex::encode(bytes))
})
.collect();
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(),
il_transactions
]);
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 new_payload_v6_heze<E: EthSpec>(
&self,
new_payload_request_heze: NewPayloadRequestHeze<'_, E>,
@@ -1393,26 +1308,6 @@ impl HttpJsonRpc {
Ok(response.into())
}
pub async fn is_inclusion_list_satisfied(
&self,
execution_payload_hash: ExecutionBlockHash,
inclusion_list_transactions: Vec<Vec<u8>>,
) -> Result<bool, Error> {
let hex_transactions: Vec<String> = inclusion_list_transactions
.into_iter()
.map(|tx| format!("0x{}", hex::encode(tx)))
.collect();
let params = json!([execution_payload_hash, hex_transactions]);
self.rpc_request(
ENGINE_IS_INCLUSION_LIST_SATISFIED_V1,
params,
ENGINE_IS_INCLUSION_LIST_SATISFIED_TIMEOUT * self.execution_timeout_multiplier,
)
.await
}
pub async fn get_payload_bodies_by_hash_v1<E: EthSpec>(
&self,
block_hashes: Vec<ExecutionBlockHash>,
@@ -1503,8 +1398,6 @@ impl HttpJsonRpc {
get_inclusion_list_v1: capabilities.contains(ENGINE_GET_INCLUSION_LIST_V1),
get_blobs_v3: capabilities.contains(ENGINE_GET_BLOBS_V3),
forkchoice_updated_v5: capabilities.contains(ENGINE_FORKCHOICE_UPDATED_V5),
is_inclusion_list_satisfied_v1: capabilities
.contains(ENGINE_IS_INCLUSION_LIST_SATISFIED_V1),
})
}
@@ -1645,12 +1538,7 @@ impl HttpJsonRpc {
}
}
NewPayloadRequest::Gloas(new_payload_request_gloas) => {
if new_payload_request_gloas.is_heze_fork {
// Force V6 for Heze blocks — Besu supports it but capability
// detection may not pick it up from exchangeCapabilities.
self.new_payload_v6_from_gloas(new_payload_request_gloas)
.await
} else if engine_capabilities.new_payload_v5 {
if engine_capabilities.new_payload_v5 {
self.new_payload_v5_gloas(new_payload_request_gloas).await
} else {
Err(Error::RequiredMethodUnsupported("engine_newPayloadV5"))
@@ -1659,8 +1547,6 @@ impl HttpJsonRpc {
NewPayloadRequest::Heze(new_payload_request_heze) => {
if engine_capabilities.new_payload_v6 {
self.new_payload_v6_heze(new_payload_request_heze).await
} else if engine_capabilities.new_payload_v5 {
self.new_payload_v5_heze(new_payload_request_heze).await
} else {
Err(Error::RequiredMethodUnsupported("engine_newPayloadV6"))
}

View File

@@ -52,12 +52,8 @@ pub struct NewPayloadRequest<'block, E: EthSpec> {
pub parent_beacon_block_root: Hash256,
#[superstruct(only(Electra, Fulu, Gloas, Heze))]
pub execution_requests: &'block ExecutionRequests<E>,
#[superstruct(only(Heze, Gloas))]
#[superstruct(only(Heze))]
pub il_transactions: Transactions<E>,
/// When true, this Gloas-shaped request must use engine_newPayloadV6 (Heze fork).
/// Gloas and Heze have identical payload wire formats; only the method version differs.
#[superstruct(only(Gloas))]
pub is_heze_fork: bool,
}
impl<'block, E: EthSpec> NewPayloadRequest<'block, E> {
@@ -186,60 +182,7 @@ impl<'block, E: EthSpec> NewPayloadRequest<'block, E> {
}
}
impl<'a, E: EthSpec> NewPayloadRequest<'a, E> {
pub fn try_from_block_and_il_transactions(
block: BeaconBlockRef<'a, E>,
_il_transactions: Transactions<E>,
) -> Result<Self, BeaconStateError> {
match block {
BeaconBlockRef::Base(_) | BeaconBlockRef::Altair(_) => {
Err(BeaconStateError::IncorrectStateVariant)
}
BeaconBlockRef::Bellatrix(block_ref) => {
Ok(Self::Bellatrix(NewPayloadRequestBellatrix {
execution_payload: &block_ref.body.execution_payload.execution_payload,
}))
}
BeaconBlockRef::Capella(block_ref) => Ok(Self::Capella(NewPayloadRequestCapella {
execution_payload: &block_ref.body.execution_payload.execution_payload,
})),
BeaconBlockRef::Deneb(block_ref) => Ok(Self::Deneb(NewPayloadRequestDeneb {
execution_payload: &block_ref.body.execution_payload.execution_payload,
versioned_hashes: block_ref
.body
.blob_kzg_commitments
.iter()
.map(kzg_commitment_to_versioned_hash)
.collect(),
parent_beacon_block_root: block_ref.parent_root,
})),
BeaconBlockRef::Electra(block_ref) => Ok(Self::Electra(NewPayloadRequestElectra {
execution_payload: &block_ref.body.execution_payload.execution_payload,
versioned_hashes: block_ref
.body
.blob_kzg_commitments
.iter()
.map(kzg_commitment_to_versioned_hash)
.collect(),
parent_beacon_block_root: block_ref.parent_root,
execution_requests: &block_ref.body.execution_requests,
})),
BeaconBlockRef::Fulu(block_ref) => Ok(Self::Fulu(NewPayloadRequestFulu {
execution_payload: &block_ref.body.execution_payload.execution_payload,
versioned_hashes: block_ref
.body
.blob_kzg_commitments
.iter()
.map(kzg_commitment_to_versioned_hash)
.collect(),
parent_beacon_block_root: block_ref.parent_root,
execution_requests: &block_ref.body.execution_requests,
})),
_ => Err(BeaconStateError::IncorrectStateVariant),
}
}
}
impl<'a, E: EthSpec> NewPayloadRequest<'a, E> {}
//TODO(EIP7732): Consider implementing these as methods on the NewPayloadRequest struct
impl<'a, E: EthSpec> TryFrom<BeaconBlockRef<'a, E>> for NewPayloadRequest<'a, E> {

View File

@@ -120,13 +120,6 @@ impl<E: EthSpec> TryFrom<BuilderBid<E>> for ProvenancedPayload<BlockProposalCont
blobs_and_proofs: None,
requests: Some(builder_bid.execution_requests),
},
BuilderBid::Heze(builder_bid) => BlockProposalContents::PayloadAndBlobs {
payload: ExecutionPayloadHeader::Heze(builder_bid.header).into(),
block_value: builder_bid.value,
kzg_commitments: builder_bid.blob_kzg_commitments,
blobs_and_proofs: None,
requests: Some(builder_bid.execution_requests),
},
BuilderBid::Fulu(builder_bid) => BlockProposalContents::PayloadAndBlobs {
payload: ExecutionPayloadHeader::Fulu(builder_bid.header).into(),
block_value: builder_bid.value,
@@ -1562,22 +1555,6 @@ impl<E: EthSpec> ExecutionLayer<E> {
.map_err(Error::EngineError)
}
pub async fn is_inclusion_list_satisfied(
&self,
payload_block_hash: ExecutionBlockHash,
inclusion_list_transactions: Vec<Vec<u8>>,
) -> Result<bool, Error> {
self.engine()
.request(|engine| {
engine
.api
.is_inclusion_list_satisfied(payload_block_hash, inclusion_list_transactions)
})
.await
.map_err(Box::new)
.map_err(Error::EngineError)
}
/// Update engine sync status.
pub async fn upcheck(&self) {
self.engine().upcheck().await;

View File

@@ -114,9 +114,6 @@ impl<E: EthSpec> BidStuff<E> for BuilderBid<E> {
ExecutionPayloadHeaderRefMut::Electra(header) => {
header.fee_recipient = fee_recipient;
}
ExecutionPayloadHeaderRefMut::Heze(header) => {
header.fee_recipient = fee_recipient;
}
ExecutionPayloadHeaderRefMut::Fulu(header) => {
header.fee_recipient = fee_recipient;
}
@@ -137,9 +134,6 @@ impl<E: EthSpec> BidStuff<E> for BuilderBid<E> {
ExecutionPayloadHeaderRefMut::Electra(header) => {
header.gas_limit = gas_limit;
}
ExecutionPayloadHeaderRefMut::Heze(header) => {
header.gas_limit = gas_limit;
}
ExecutionPayloadHeaderRefMut::Fulu(header) => {
header.gas_limit = gas_limit;
}
@@ -164,9 +158,6 @@ impl<E: EthSpec> BidStuff<E> for BuilderBid<E> {
ExecutionPayloadHeaderRefMut::Electra(header) => {
header.parent_hash = ExecutionBlockHash::from_root(parent_hash);
}
ExecutionPayloadHeaderRefMut::Heze(header) => {
header.parent_hash = ExecutionBlockHash::from_root(parent_hash);
}
ExecutionPayloadHeaderRefMut::Fulu(header) => {
header.parent_hash = ExecutionBlockHash::from_root(parent_hash);
}
@@ -187,9 +178,6 @@ impl<E: EthSpec> BidStuff<E> for BuilderBid<E> {
ExecutionPayloadHeaderRefMut::Electra(header) => {
header.prev_randao = prev_randao;
}
ExecutionPayloadHeaderRefMut::Heze(header) => {
header.prev_randao = prev_randao;
}
ExecutionPayloadHeaderRefMut::Fulu(header) => {
header.prev_randao = prev_randao;
}
@@ -210,9 +198,6 @@ impl<E: EthSpec> BidStuff<E> for BuilderBid<E> {
ExecutionPayloadHeaderRefMut::Electra(header) => {
header.block_number = block_number;
}
ExecutionPayloadHeaderRefMut::Heze(header) => {
header.block_number = block_number;
}
ExecutionPayloadHeaderRefMut::Fulu(header) => {
header.block_number = block_number;
}
@@ -233,9 +218,6 @@ impl<E: EthSpec> BidStuff<E> for BuilderBid<E> {
ExecutionPayloadHeaderRefMut::Electra(header) => {
header.timestamp = timestamp;
}
ExecutionPayloadHeaderRefMut::Heze(header) => {
header.timestamp = timestamp;
}
ExecutionPayloadHeaderRefMut::Fulu(header) => {
header.timestamp = timestamp;
}
@@ -256,9 +238,6 @@ impl<E: EthSpec> BidStuff<E> for BuilderBid<E> {
ExecutionPayloadHeaderRefMut::Electra(header) => {
header.withdrawals_root = withdrawals_root;
}
ExecutionPayloadHeaderRefMut::Heze(header) => {
header.withdrawals_root = withdrawals_root;
}
ExecutionPayloadHeaderRefMut::Fulu(header) => {
header.withdrawals_root = withdrawals_root;
}
@@ -291,10 +270,6 @@ impl<E: EthSpec> BidStuff<E> for BuilderBid<E> {
header.extra_data = extra_data;
header.block_hash = ExecutionBlockHash::from_root(header.tree_hash_root());
}
ExecutionPayloadHeaderRefMut::Heze(header) => {
header.extra_data = extra_data;
header.block_hash = ExecutionBlockHash::from_root(header.tree_hash_root());
}
ExecutionPayloadHeaderRefMut::Fulu(header) => {
header.extra_data = extra_data;
header.block_hash = ExecutionBlockHash::from_root(header.tree_hash_root());

View File

@@ -63,7 +63,6 @@ pub const DEFAULT_ENGINE_CAPABILITIES: EngineCapabilities = EngineCapabilities {
get_inclusion_list_v1: true,
get_blobs_v3: true,
forkchoice_updated_v5: true,
is_inclusion_list_satisfied_v1: true,
};
pub static DEFAULT_CLIENT_VERSION: LazyLock<JsonClientVersionV1> =