Add Gloas boilerplate (#7728)

Adds the required boilerplate code for the Gloas (Glamsterdam) hard fork. This allows PRs testing Gloas-candidate features to test fork transition.

This also includes de-duplication of post-Bellatrix readiness notifiers from #6797 (credit to @dapplion)
This commit is contained in:
Mac L
2025-08-26 12:49:48 +10:00
committed by GitHub
parent daf1c7c3af
commit e438691683
75 changed files with 1801 additions and 917 deletions

View File

@@ -869,6 +869,30 @@ impl HttpJsonRpc {
Ok(response.into())
}
pub async fn new_payload_v4_gloas<E: EthSpec>(
&self,
new_payload_request_gloas: NewPayloadRequestGloas<'_, E>,
) -> Result<PayloadStatusV1, Error> {
let params = json!([
JsonExecutionPayload::Gloas(new_payload_request_gloas.execution_payload.clone().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(),
]);
let response: JsonPayloadStatusV1 = self
.rpc_request(
ENGINE_NEW_PAYLOAD_V4,
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,
@@ -1005,6 +1029,18 @@ impl HttpJsonRpc {
.try_into()
.map_err(Error::BadResponse)
}
ForkName::Gloas => {
let response: JsonGetPayloadResponseGloas<E> = self
.rpc_request(
ENGINE_GET_PAYLOAD_V5,
params,
ENGINE_GET_PAYLOAD_TIMEOUT * self.execution_timeout_multiplier,
)
.await?;
JsonGetPayloadResponse::Gloas(response)
.try_into()
.map_err(Error::BadResponse)
}
_ => Err(Error::UnsupportedForkVariant(format!(
"called get_payload_v5 with {}",
fork_name
@@ -1289,6 +1325,13 @@ impl HttpJsonRpc {
Err(Error::RequiredMethodUnsupported("engine_newPayloadV4"))
}
}
NewPayloadRequest::Gloas(new_payload_request_gloas) => {
if engine_capabilities.new_payload_v4 {
self.new_payload_v4_gloas(new_payload_request_gloas).await
} else {
Err(Error::RequiredMethodUnsupported("engine_newPayloadV4"))
}
}
}
}
@@ -1331,6 +1374,13 @@ impl HttpJsonRpc {
Err(Error::RequiredMethodUnsupported("engine_getPayloadv5"))
}
}
ForkName::Gloas => {
if engine_capabilities.get_payload_v5 {
self.get_payload_v5(fork_name, payload_id).await
} else {
Err(Error::RequiredMethodUnsupported("engine_getPayloadv5"))
}
}
ForkName::Base | ForkName::Altair => Err(Error::UnsupportedForkVariant(format!(
"called get_payload with {}",
fork_name

View File

@@ -65,7 +65,7 @@ pub struct JsonPayloadIdResponse {
}
#[superstruct(
variants(Bellatrix, Capella, Deneb, Electra, Fulu),
variants(Bellatrix, Capella, Deneb, Electra, Fulu, Gloas),
variant_attributes(
derive(Debug, PartialEq, Default, Serialize, Deserialize,),
serde(bound = "E: EthSpec", rename_all = "camelCase"),
@@ -100,12 +100,12 @@ 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))]
#[superstruct(only(Capella, Deneb, Electra, Fulu, Gloas))]
pub withdrawals: VariableList<JsonWithdrawal, E::MaxWithdrawalsPerPayload>,
#[superstruct(only(Deneb, Electra, Fulu))]
#[superstruct(only(Deneb, Electra, Fulu, Gloas))]
#[serde(with = "serde_utils::u64_hex_be")]
pub blob_gas_used: u64,
#[superstruct(only(Deneb, Electra, Fulu))]
#[superstruct(only(Deneb, Electra, Fulu, Gloas))]
#[serde(with = "serde_utils::u64_hex_be")]
pub excess_blob_gas: u64,
}
@@ -243,6 +243,35 @@ impl<E: EthSpec> From<ExecutionPayloadFulu<E>> for JsonExecutionPayloadFulu<E> {
}
}
impl<E: EthSpec> From<ExecutionPayloadGloas<E>> for JsonExecutionPayloadGloas<E> {
fn from(payload: ExecutionPayloadGloas<E>) -> Self {
JsonExecutionPayloadGloas {
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: payload
.withdrawals
.into_iter()
.map(Into::into)
.collect::<Vec<_>>()
.into(),
blob_gas_used: payload.blob_gas_used,
excess_blob_gas: payload.excess_blob_gas,
}
}
}
impl<E: EthSpec> From<ExecutionPayload<E>> for JsonExecutionPayload<E> {
fn from(execution_payload: ExecutionPayload<E>) -> Self {
match execution_payload {
@@ -251,6 +280,7 @@ impl<E: EthSpec> From<ExecutionPayload<E>> for JsonExecutionPayload<E> {
ExecutionPayload::Deneb(payload) => JsonExecutionPayload::Deneb(payload.into()),
ExecutionPayload::Electra(payload) => JsonExecutionPayload::Electra(payload.into()),
ExecutionPayload::Fulu(payload) => JsonExecutionPayload::Fulu(payload.into()),
ExecutionPayload::Gloas(payload) => JsonExecutionPayload::Gloas(payload.into()),
}
}
}
@@ -389,6 +419,35 @@ impl<E: EthSpec> From<JsonExecutionPayloadFulu<E>> for ExecutionPayloadFulu<E> {
}
}
impl<E: EthSpec> From<JsonExecutionPayloadGloas<E>> for ExecutionPayloadGloas<E> {
fn from(payload: JsonExecutionPayloadGloas<E>) -> Self {
ExecutionPayloadGloas {
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: payload
.withdrawals
.into_iter()
.map(Into::into)
.collect::<Vec<_>>()
.into(),
blob_gas_used: payload.blob_gas_used,
excess_blob_gas: payload.excess_blob_gas,
}
}
}
impl<E: EthSpec> From<JsonExecutionPayload<E>> for ExecutionPayload<E> {
fn from(json_execution_payload: JsonExecutionPayload<E>) -> Self {
match json_execution_payload {
@@ -397,6 +456,7 @@ impl<E: EthSpec> From<JsonExecutionPayload<E>> for ExecutionPayload<E> {
JsonExecutionPayload::Deneb(payload) => ExecutionPayload::Deneb(payload.into()),
JsonExecutionPayload::Electra(payload) => ExecutionPayload::Electra(payload.into()),
JsonExecutionPayload::Fulu(payload) => ExecutionPayload::Fulu(payload.into()),
JsonExecutionPayload::Gloas(payload) => ExecutionPayload::Gloas(payload.into()),
}
}
}
@@ -482,7 +542,7 @@ impl<E: EthSpec> TryFrom<JsonExecutionRequests> for ExecutionRequests<E> {
}
#[superstruct(
variants(Bellatrix, Capella, Deneb, Electra, Fulu),
variants(Bellatrix, Capella, Deneb, Electra, Fulu, Gloas),
variant_attributes(
derive(Debug, PartialEq, Serialize, Deserialize),
serde(bound = "E: EthSpec", rename_all = "camelCase")
@@ -506,13 +566,15 @@ pub struct JsonGetPayloadResponse<E: EthSpec> {
pub execution_payload: JsonExecutionPayloadElectra<E>,
#[superstruct(only(Fulu), partial_getter(rename = "execution_payload_fulu"))]
pub execution_payload: JsonExecutionPayloadFulu<E>,
#[superstruct(only(Gloas), partial_getter(rename = "execution_payload_gloas"))]
pub execution_payload: JsonExecutionPayloadGloas<E>,
#[serde(with = "serde_utils::u256_hex_be")]
pub block_value: Uint256,
#[superstruct(only(Deneb, Electra, Fulu))]
#[superstruct(only(Deneb, Electra, Fulu, Gloas))]
pub blobs_bundle: JsonBlobsBundleV1<E>,
#[superstruct(only(Deneb, Electra, Fulu))]
#[superstruct(only(Deneb, Electra, Fulu, Gloas))]
pub should_override_builder: bool,
#[superstruct(only(Electra, Fulu))]
#[superstruct(only(Electra, Fulu, Gloas))]
pub execution_requests: JsonExecutionRequests,
}
@@ -562,6 +624,17 @@ impl<E: EthSpec> TryFrom<JsonGetPayloadResponse<E>> for GetPayloadResponse<E> {
})?,
}))
}
JsonGetPayloadResponse::Gloas(response) => {
Ok(GetPayloadResponse::Gloas(GetPayloadResponseGloas {
execution_payload: response.execution_payload.into(),
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,11 @@ use types::{
};
use types::{
ExecutionPayloadBellatrix, ExecutionPayloadCapella, ExecutionPayloadDeneb,
ExecutionPayloadElectra, ExecutionPayloadFulu, ExecutionRequests,
ExecutionPayloadElectra, ExecutionPayloadFulu, ExecutionPayloadGloas, ExecutionRequests,
};
#[superstruct(
variants(Bellatrix, Capella, Deneb, Electra, Fulu),
variants(Bellatrix, Capella, Deneb, Electra, Fulu, Gloas),
variant_attributes(derive(Clone, Debug, PartialEq),),
map_into(ExecutionPayload),
map_ref_into(ExecutionPayloadRef),
@@ -41,11 +41,13 @@ pub struct NewPayloadRequest<'block, E: EthSpec> {
pub execution_payload: &'block ExecutionPayloadElectra<E>,
#[superstruct(only(Fulu), partial_getter(rename = "execution_payload_fulu"))]
pub execution_payload: &'block ExecutionPayloadFulu<E>,
#[superstruct(only(Deneb, Electra, Fulu))]
#[superstruct(only(Gloas), partial_getter(rename = "execution_payload_gloas"))]
pub execution_payload: &'block ExecutionPayloadGloas<E>,
#[superstruct(only(Deneb, Electra, Fulu, Gloas))]
pub versioned_hashes: Vec<VersionedHash>,
#[superstruct(only(Deneb, Electra, Fulu))]
#[superstruct(only(Deneb, Electra, Fulu, Gloas))]
pub parent_beacon_block_root: Hash256,
#[superstruct(only(Electra, Fulu))]
#[superstruct(only(Electra, Fulu, Gloas))]
pub execution_requests: &'block ExecutionRequests<E>,
}
@@ -57,6 +59,7 @@ impl<'block, E: EthSpec> NewPayloadRequest<'block, E> {
Self::Deneb(payload) => payload.execution_payload.parent_hash,
Self::Electra(payload) => payload.execution_payload.parent_hash,
Self::Fulu(payload) => payload.execution_payload.parent_hash,
Self::Gloas(payload) => payload.execution_payload.parent_hash,
}
}
@@ -67,6 +70,7 @@ impl<'block, E: EthSpec> NewPayloadRequest<'block, E> {
Self::Deneb(payload) => payload.execution_payload.block_hash,
Self::Electra(payload) => payload.execution_payload.block_hash,
Self::Fulu(payload) => payload.execution_payload.block_hash,
Self::Gloas(payload) => payload.execution_payload.block_hash,
}
}
@@ -77,6 +81,7 @@ impl<'block, E: EthSpec> NewPayloadRequest<'block, E> {
Self::Deneb(payload) => payload.execution_payload.block_number,
Self::Electra(payload) => payload.execution_payload.block_number,
Self::Fulu(payload) => payload.execution_payload.block_number,
Self::Gloas(payload) => payload.execution_payload.block_number,
}
}
@@ -87,6 +92,7 @@ impl<'block, E: EthSpec> NewPayloadRequest<'block, E> {
Self::Deneb(request) => ExecutionPayloadRef::Deneb(request.execution_payload),
Self::Electra(request) => ExecutionPayloadRef::Electra(request.execution_payload),
Self::Fulu(request) => ExecutionPayloadRef::Fulu(request.execution_payload),
Self::Gloas(request) => ExecutionPayloadRef::Gloas(request.execution_payload),
}
}
@@ -99,6 +105,7 @@ impl<'block, E: EthSpec> NewPayloadRequest<'block, E> {
Self::Deneb(request) => ExecutionPayload::Deneb(request.execution_payload.clone()),
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()),
}
}
@@ -213,6 +220,17 @@ impl<'a, E: EthSpec> TryFrom<BeaconBlockRef<'a, E>> for NewPayloadRequest<'a, E>
parent_beacon_block_root: block_ref.parent_root,
execution_requests: &block_ref.body.execution_requests,
})),
BeaconBlockRef::Gloas(block_ref) => Ok(Self::Gloas(NewPayloadRequestGloas {
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,
})),
}
}
}
@@ -233,6 +251,7 @@ impl<'a, E: EthSpec> TryFrom<ExecutionPayloadRef<'a, E>> for NewPayloadRequest<'
ExecutionPayloadRef::Deneb(_) => Err(Self::Error::IncorrectStateVariant),
ExecutionPayloadRef::Electra(_) => Err(Self::Error::IncorrectStateVariant),
ExecutionPayloadRef::Fulu(_) => Err(Self::Error::IncorrectStateVariant),
ExecutionPayloadRef::Gloas(_) => Err(Self::Error::IncorrectStateVariant),
}
}
}