Skip to content

Commit

Permalink
Merge of #5743
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Jul 1, 2024
2 parents 3f2af5c + 69ac342 commit 3a08e68
Show file tree
Hide file tree
Showing 25 changed files with 361 additions and 114 deletions.
26 changes: 9 additions & 17 deletions beacon_node/beacon_chain/src/electra_readiness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
//! transition.

use crate::{BeaconChain, BeaconChainTypes};
use execution_layer::http::{
ENGINE_FORKCHOICE_UPDATED_V3, ENGINE_GET_PAYLOAD_V3, ENGINE_NEW_PAYLOAD_V3,
};
use execution_layer::http::{ENGINE_GET_PAYLOAD_V4, ENGINE_NEW_PAYLOAD_V4};
use serde::{Deserialize, Serialize};
use std::fmt;
use std::time::Duration;
Expand All @@ -21,8 +19,8 @@ pub const ENGINE_CAPABILITIES_REFRESH_INTERVAL: u64 = 300;
pub enum ElectraReadiness {
/// The execution engine is electra-enabled (as far as we can tell)
Ready,
/// We are connected to an execution engine which doesn't support the V3 engine api methods
V3MethodsNotSupported { error: String },
/// We are connected to an execution engine which doesn't support the V4 engine api methods
V4MethodsNotSupported { error: String },
/// The transition configuration with the EL failed, there might be a problem with
/// connectivity, authentication or a difference in configuration.
ExchangeCapabilitiesFailed { error: String },
Expand All @@ -47,7 +45,7 @@ impl fmt::Display for ElectraReadiness {
"The --execution-endpoint flag is not specified, this is a \
requirement post-merge"
),
ElectraReadiness::V3MethodsNotSupported { error } => write!(
ElectraReadiness::V4MethodsNotSupported { error } => write!(
f,
"Execution endpoint does not support Electra methods: {}",
error
Expand Down Expand Up @@ -88,29 +86,23 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
}
}
Ok(capabilities) => {
// TODO(electra): Update in the event we get V4s.
let mut missing_methods = String::from("Required Methods Unsupported:");
let mut all_good = true;
if !capabilities.get_payload_v3 {
if !capabilities.get_payload_v4 {
missing_methods.push(' ');
missing_methods.push_str(ENGINE_GET_PAYLOAD_V3);
missing_methods.push_str(ENGINE_GET_PAYLOAD_V4);
all_good = false;
}
if !capabilities.forkchoice_updated_v3 {
if !capabilities.new_payload_v4 {
missing_methods.push(' ');
missing_methods.push_str(ENGINE_FORKCHOICE_UPDATED_V3);
all_good = false;
}
if !capabilities.new_payload_v3 {
missing_methods.push(' ');
missing_methods.push_str(ENGINE_NEW_PAYLOAD_V3);
missing_methods.push_str(ENGINE_NEW_PAYLOAD_V4);
all_good = false;
}

if all_good {
ElectraReadiness::Ready
} else {
ElectraReadiness::V3MethodsNotSupported {
ElectraReadiness::V4MethodsNotSupported {
error: missing_methods,
}
}
Expand Down
52 changes: 44 additions & 8 deletions beacon_node/execution_layer/src/engine_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use crate::http::{
ENGINE_FORKCHOICE_UPDATED_V1, ENGINE_FORKCHOICE_UPDATED_V2, ENGINE_FORKCHOICE_UPDATED_V3,
ENGINE_GET_CLIENT_VERSION_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_NEW_PAYLOAD_V1, ENGINE_NEW_PAYLOAD_V2, ENGINE_NEW_PAYLOAD_V3,
ENGINE_GET_PAYLOAD_V3, ENGINE_GET_PAYLOAD_V4, ENGINE_NEW_PAYLOAD_V1, ENGINE_NEW_PAYLOAD_V2,
ENGINE_NEW_PAYLOAD_V3, ENGINE_NEW_PAYLOAD_V4,
};
use eth2::types::{
BlobsBundle, SsePayloadAttributes, SsePayloadAttributesV1, SsePayloadAttributesV2,
Expand All @@ -19,6 +20,7 @@ use reqwest::StatusCode;
use serde::{Deserialize, Serialize};
use strum::IntoStaticStr;
use superstruct::superstruct;
use types::execution_payload::{DepositRequests, WithdrawalRequests};
pub use types::{
Address, BeaconBlockRef, EthSpec, ExecutionBlockHash, ExecutionPayload, ExecutionPayloadHeader,
ExecutionPayloadRef, FixedVector, ForkName, Hash256, Transactions, Uint256, VariableList,
Expand All @@ -40,6 +42,8 @@ pub use new_payload_request::{
NewPayloadRequestDeneb, NewPayloadRequestElectra,
};

use self::json_structures::{JsonDepositRequest, JsonWithdrawalRequest};

pub const LATEST_TAG: &str = "latest";

pub type PayloadId = [u8; 8];
Expand All @@ -60,9 +64,10 @@ pub enum Error {
ExecutionHeadBlockNotFound,
ParentHashEqualsBlockHash(ExecutionBlockHash),
PayloadIdUnavailable,
TransitionConfigurationMismatch,
SszError(ssz_types::Error),
DeserializeWithdrawals(ssz_types::Error),
DeserializeDepositRequests(ssz_types::Error),
DeserializeWithdrawalRequests(ssz_types::Error),
BuilderApi(builder_client::Error),
IncorrectStateVariant,
RequiredMethodUnsupported(&'static str),
Expand Down Expand Up @@ -197,6 +202,10 @@ pub struct ExecutionBlockWithTransactions<E: EthSpec> {
#[superstruct(only(Deneb, Electra))]
#[serde(with = "serde_utils::u64_hex_be")]
pub excess_blob_gas: u64,
#[superstruct(only(Electra))]
pub deposit_requests: Vec<JsonDepositRequest>,
#[superstruct(only(Electra))]
pub withdrawal_requests: Vec<JsonWithdrawalRequest>,
}

impl<E: EthSpec> TryFrom<ExecutionPayload<E>> for ExecutionBlockWithTransactions<E> {
Expand Down Expand Up @@ -304,6 +313,16 @@ impl<E: EthSpec> TryFrom<ExecutionPayload<E>> for ExecutionBlockWithTransactions
.collect(),
blob_gas_used: block.blob_gas_used,
excess_blob_gas: block.excess_blob_gas,
deposit_requests: block
.deposit_requests
.into_iter()
.map(|deposit| deposit.into())
.collect(),
withdrawal_requests: block
.withdrawal_requests
.into_iter()
.map(|withdrawal| withdrawal.into())
.collect(),
})
}
};
Expand Down Expand Up @@ -526,6 +545,8 @@ impl<E: EthSpec> GetPayloadResponse<E> {
pub struct ExecutionPayloadBodyV1<E: EthSpec> {
pub transactions: Transactions<E>,
pub withdrawals: Option<Withdrawals<E>>,
pub deposit_requests: Option<DepositRequests<E>>,
pub withdrawal_requests: Option<WithdrawalRequests<E>>,
}

impl<E: EthSpec> ExecutionPayloadBodyV1<E> {
Expand Down Expand Up @@ -613,7 +634,14 @@ impl<E: EthSpec> ExecutionPayloadBodyV1<E> {
}
}
ExecutionPayloadHeader::Electra(header) => {
if let Some(withdrawals) = self.withdrawals {
let withdrawals_exist = self.withdrawals.is_some();
let deposit_requests_exist = self.deposit_requests.is_some();
let withdrawal_requests_exist = self.withdrawal_requests.is_some();
if let (Some(withdrawals), Some(deposit_requests), Some(withdrawal_requests)) = (
self.withdrawals,
self.deposit_requests,
self.withdrawal_requests,
) {
Ok(ExecutionPayload::Electra(ExecutionPayloadElectra {
parent_hash: header.parent_hash,
fee_recipient: header.fee_recipient,
Expand All @@ -632,14 +660,14 @@ impl<E: EthSpec> ExecutionPayloadBodyV1<E> {
withdrawals,
blob_gas_used: header.blob_gas_used,
excess_blob_gas: header.excess_blob_gas,
// TODO(electra)
deposit_receipts: <_>::default(),
withdrawal_requests: <_>::default(),
deposit_requests,
withdrawal_requests,
}))
} else {
Err(format!(
"block {} is post-capella but payload body doesn't have withdrawals",
header.block_hash
"block {} is post-electra but payload body doesn't have withdrawals/deposit_requests/withdrawal_requests \
withdrawals: {}, deposit_requests: {}, withdrawal_requests: {}",
header.block_hash, withdrawals_exist, deposit_requests_exist, withdrawal_requests_exist
))
}
}
Expand All @@ -652,6 +680,7 @@ pub struct EngineCapabilities {
pub new_payload_v1: bool,
pub new_payload_v2: bool,
pub new_payload_v3: bool,
pub new_payload_v4: bool,
pub forkchoice_updated_v1: bool,
pub forkchoice_updated_v2: bool,
pub forkchoice_updated_v3: bool,
Expand All @@ -660,6 +689,7 @@ pub struct EngineCapabilities {
pub get_payload_v1: bool,
pub get_payload_v2: bool,
pub get_payload_v3: bool,
pub get_payload_v4: bool,
pub get_client_version_v1: bool,
}

Expand All @@ -675,6 +705,9 @@ impl EngineCapabilities {
if self.new_payload_v3 {
response.push(ENGINE_NEW_PAYLOAD_V3);
}
if self.new_payload_v4 {
response.push(ENGINE_NEW_PAYLOAD_V4);
}
if self.forkchoice_updated_v1 {
response.push(ENGINE_FORKCHOICE_UPDATED_V1);
}
Expand All @@ -699,6 +732,9 @@ impl EngineCapabilities {
if self.get_payload_v3 {
response.push(ENGINE_GET_PAYLOAD_V3);
}
if self.get_payload_v4 {
response.push(ENGINE_GET_PAYLOAD_V4);
}
if self.get_client_version_v1 {
response.push(ENGINE_GET_CLIENT_VERSION_V1);
}
Expand Down
61 changes: 49 additions & 12 deletions beacon_node/execution_layer/src/engine_api/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@ pub const ETH_SYNCING_TIMEOUT: Duration = Duration::from_secs(1);
pub const ENGINE_NEW_PAYLOAD_V1: &str = "engine_newPayloadV1";
pub const ENGINE_NEW_PAYLOAD_V2: &str = "engine_newPayloadV2";
pub const ENGINE_NEW_PAYLOAD_V3: &str = "engine_newPayloadV3";
pub const ENGINE_NEW_PAYLOAD_V4: &str = "engine_newPayloadV4";
pub const ENGINE_NEW_PAYLOAD_TIMEOUT: Duration = Duration::from_secs(8);

pub const ENGINE_GET_PAYLOAD_V1: &str = "engine_getPayloadV1";
pub const ENGINE_GET_PAYLOAD_V2: &str = "engine_getPayloadV2";
pub const ENGINE_GET_PAYLOAD_V3: &str = "engine_getPayloadV3";
pub const ENGINE_GET_PAYLOAD_V4: &str = "engine_getPayloadV4";
pub const ENGINE_GET_PAYLOAD_TIMEOUT: Duration = Duration::from_secs(2);

pub const ENGINE_FORKCHOICE_UPDATED_V1: &str = "engine_forkchoiceUpdatedV1";
Expand Down Expand Up @@ -66,9 +68,11 @@ pub static LIGHTHOUSE_CAPABILITIES: &[&str] = &[
ENGINE_NEW_PAYLOAD_V1,
ENGINE_NEW_PAYLOAD_V2,
ENGINE_NEW_PAYLOAD_V3,
ENGINE_NEW_PAYLOAD_V4,
ENGINE_GET_PAYLOAD_V1,
ENGINE_GET_PAYLOAD_V2,
ENGINE_GET_PAYLOAD_V3,
ENGINE_GET_PAYLOAD_V4,
ENGINE_FORKCHOICE_UPDATED_V1,
ENGINE_FORKCHOICE_UPDATED_V2,
ENGINE_FORKCHOICE_UPDATED_V3,
Expand Down Expand Up @@ -830,7 +834,7 @@ impl HttpJsonRpc {
Ok(response.into())
}

pub async fn new_payload_v3_electra<E: EthSpec>(
pub async fn new_payload_v4_electra<E: EthSpec>(
&self,
new_payload_request_electra: NewPayloadRequestElectra<'_, E>,
) -> Result<PayloadStatusV1, Error> {
Expand All @@ -842,7 +846,7 @@ impl HttpJsonRpc {

let response: JsonPayloadStatusV1 = self
.rpc_request(
ENGINE_NEW_PAYLOAD_V3,
ENGINE_NEW_PAYLOAD_V4,
params,
ENGINE_NEW_PAYLOAD_TIMEOUT * self.execution_timeout_multiplier,
)
Expand Down Expand Up @@ -926,19 +930,43 @@ impl HttpJsonRpc {
.await?;
Ok(JsonGetPayloadResponse::V3(response).into())
}
ForkName::Base
| ForkName::Altair
| ForkName::Bellatrix
| ForkName::Capella
| ForkName::Electra => Err(Error::UnsupportedForkVariant(format!(
"called get_payload_v3 with {}",
fork_name
))),
}
}

pub async fn get_payload_v4<E: EthSpec>(
&self,
fork_name: ForkName,
payload_id: PayloadId,
) -> Result<GetPayloadResponse<E>, Error> {
let params = json!([JsonPayloadIdRequest::from(payload_id)]);

match fork_name {
ForkName::Electra => {
let response: JsonGetPayloadResponseV4<E> = self
.rpc_request(
ENGINE_GET_PAYLOAD_V3,
ENGINE_GET_PAYLOAD_V4,
params,
ENGINE_GET_PAYLOAD_TIMEOUT * self.execution_timeout_multiplier,
)
.await?;
Ok(JsonGetPayloadResponse::V4(response).into())
}
ForkName::Base | ForkName::Altair | ForkName::Bellatrix | ForkName::Capella => Err(
Error::UnsupportedForkVariant(format!("called get_payload_v3 with {}", fork_name)),
),
ForkName::Base
| ForkName::Altair
| ForkName::Bellatrix
| ForkName::Capella
| ForkName::Deneb => Err(Error::UnsupportedForkVariant(format!(
"called get_payload_v4 with {}",
fork_name
))),
}
}

Expand Down Expand Up @@ -1064,6 +1092,7 @@ impl HttpJsonRpc {
new_payload_v1: capabilities.contains(ENGINE_NEW_PAYLOAD_V1),
new_payload_v2: capabilities.contains(ENGINE_NEW_PAYLOAD_V2),
new_payload_v3: capabilities.contains(ENGINE_NEW_PAYLOAD_V3),
new_payload_v4: capabilities.contains(ENGINE_NEW_PAYLOAD_V4),
forkchoice_updated_v1: capabilities.contains(ENGINE_FORKCHOICE_UPDATED_V1),
forkchoice_updated_v2: capabilities.contains(ENGINE_FORKCHOICE_UPDATED_V2),
forkchoice_updated_v3: capabilities.contains(ENGINE_FORKCHOICE_UPDATED_V3),
Expand All @@ -1074,6 +1103,7 @@ impl HttpJsonRpc {
get_payload_v1: capabilities.contains(ENGINE_GET_PAYLOAD_V1),
get_payload_v2: capabilities.contains(ENGINE_GET_PAYLOAD_V2),
get_payload_v3: capabilities.contains(ENGINE_GET_PAYLOAD_V3),
get_payload_v4: capabilities.contains(ENGINE_GET_PAYLOAD_V4),
get_client_version_v1: capabilities.contains(ENGINE_GET_CLIENT_VERSION_V1),
})
}
Expand Down Expand Up @@ -1196,11 +1226,11 @@ impl HttpJsonRpc {
}
}
NewPayloadRequest::Electra(new_payload_request_electra) => {
if engine_capabilities.new_payload_v3 {
self.new_payload_v3_electra(new_payload_request_electra)
if engine_capabilities.new_payload_v4 {
self.new_payload_v4_electra(new_payload_request_electra)
.await
} else {
Err(Error::RequiredMethodUnsupported("engine_newPayloadV3"))
Err(Error::RequiredMethodUnsupported("engine_newPayloadV4"))
}
}
}
Expand All @@ -1218,17 +1248,24 @@ impl HttpJsonRpc {
ForkName::Bellatrix | ForkName::Capella => {
if engine_capabilities.get_payload_v2 {
self.get_payload_v2(fork_name, payload_id).await
} else if engine_capabilities.new_payload_v1 {
} else if engine_capabilities.get_payload_v1 {
self.get_payload_v1(payload_id).await
} else {
Err(Error::RequiredMethodUnsupported("engine_getPayload"))
}
}
ForkName::Deneb | ForkName::Electra => {
ForkName::Deneb => {
if engine_capabilities.get_payload_v3 {
self.get_payload_v3(fork_name, payload_id).await
} else {
Err(Error::RequiredMethodUnsupported("engine_getPayloadV3"))
Err(Error::RequiredMethodUnsupported("engine_getPayloadv3"))
}
}
ForkName::Electra => {
if engine_capabilities.get_payload_v4 {
self.get_payload_v4(fork_name, payload_id).await
} else {
Err(Error::RequiredMethodUnsupported("engine_getPayloadv4"))
}
}
ForkName::Base | ForkName::Altair => Err(Error::UnsupportedForkVariant(format!(
Expand Down
Loading

0 comments on commit 3a08e68

Please sign in to comment.