Electra updates for v1.5.0-alpha.6 (#6445)

* Update process_slashing

* Update test vectors version

* Delete Domain::Consolidation

* Rename to get_max_effective_balance

* Fix unused; lint

* Add the pre-electra slashing processing

* lint

* Change request json types

* Move requests from payload to beacon block body

* Refactor engine api

* Fix warnings

* Update engine api to latest

* engine api changed..again

* yet again

* Merge branch 'engine-requests' into electra-updates

* Fix tests

* Store reference instead of bytes in NewPayloadRequest

* Merge branch 'unstable' into electra-updates

* Update beacon_node/execution_layer/src/engine_api/json_structures.rs

Co-authored-by: Michael Sproul <micsproul@gmail.com>

* Update beacon_node/execution_layer/src/lib.rs

Co-authored-by: Michael Sproul <micsproul@gmail.com>

* Update beacon_node/execution_layer/src/test_utils/handle_rpc.rs

Co-authored-by: Michael Sproul <micsproul@gmail.com>
This commit is contained in:
Pawan Dhananjay
2024-10-15 10:38:43 -07:00
committed by GitHub
parent 2e440df4f1
commit 83d5c521d7
35 changed files with 445 additions and 913 deletions

View File

@@ -2,8 +2,7 @@ use crate::engines::ForkchoiceState;
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_HASH_V2, ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V1,
ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V2, ENGINE_GET_PAYLOAD_V1, ENGINE_GET_PAYLOAD_V2,
ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V1, ENGINE_GET_PAYLOAD_V1, ENGINE_GET_PAYLOAD_V2,
ENGINE_GET_PAYLOAD_V3, ENGINE_GET_PAYLOAD_V4, ENGINE_NEW_PAYLOAD_V1, ENGINE_NEW_PAYLOAD_V2,
ENGINE_NEW_PAYLOAD_V3, ENGINE_NEW_PAYLOAD_V4,
};
@@ -18,7 +17,6 @@ use reqwest::StatusCode;
use serde::{Deserialize, Serialize};
use strum::IntoStaticStr;
use superstruct::superstruct;
use types::execution_payload::{ConsolidationRequests, DepositRequests, WithdrawalRequests};
pub use types::{
Address, BeaconBlockRef, ConsolidationRequest, EthSpec, ExecutionBlockHash, ExecutionPayload,
ExecutionPayloadHeader, ExecutionPayloadRef, FixedVector, ForkName, Hash256, Transactions,
@@ -26,7 +24,7 @@ pub use types::{
};
use types::{
ExecutionPayloadBellatrix, ExecutionPayloadCapella, ExecutionPayloadDeneb,
ExecutionPayloadElectra, KzgProofs,
ExecutionPayloadElectra, ExecutionRequests, KzgProofs,
};
use types::{Graffiti, GRAFFITI_BYTES_LEN};
@@ -288,6 +286,8 @@ pub struct GetPayloadResponse<E: EthSpec> {
pub blobs_bundle: BlobsBundle<E>,
#[superstruct(only(Deneb, Electra), partial_getter(copy))]
pub should_override_builder: bool,
#[superstruct(only(Electra))]
pub requests: ExecutionRequests<E>,
}
impl<E: EthSpec> GetPayloadResponse<E> {
@@ -321,7 +321,12 @@ impl<E: EthSpec> From<GetPayloadResponse<E>> for ExecutionPayload<E> {
}
impl<E: EthSpec> From<GetPayloadResponse<E>>
for (ExecutionPayload<E>, Uint256, Option<BlobsBundle<E>>)
for (
ExecutionPayload<E>,
Uint256,
Option<BlobsBundle<E>>,
Option<ExecutionRequests<E>>,
)
{
fn from(response: GetPayloadResponse<E>) -> Self {
match response {
@@ -329,21 +334,25 @@ impl<E: EthSpec> From<GetPayloadResponse<E>>
ExecutionPayload::Bellatrix(inner.execution_payload),
inner.block_value,
None,
None,
),
GetPayloadResponse::Capella(inner) => (
ExecutionPayload::Capella(inner.execution_payload),
inner.block_value,
None,
None,
),
GetPayloadResponse::Deneb(inner) => (
ExecutionPayload::Deneb(inner.execution_payload),
inner.block_value,
Some(inner.blobs_bundle),
None,
),
GetPayloadResponse::Electra(inner) => (
ExecutionPayload::Electra(inner.execution_payload),
inner.block_value,
Some(inner.blobs_bundle),
Some(inner.requests),
),
}
}
@@ -360,106 +369,25 @@ impl<E: EthSpec> GetPayloadResponse<E> {
}
}
#[superstruct(
variants(V1, V2),
variant_attributes(derive(Clone, Debug),),
partial_getter_error(ty = "Error", expr = "Error::IncorrectStateVariant")
)]
#[derive(Clone, Debug)]
pub struct ExecutionPayloadBody<E: EthSpec> {
pub struct ExecutionPayloadBodyV1<E: EthSpec> {
pub transactions: Transactions<E>,
pub withdrawals: Option<Withdrawals<E>>,
#[superstruct(only(V2))]
pub deposit_requests: Option<DepositRequests<E>>,
#[superstruct(only(V2))]
pub withdrawal_requests: Option<WithdrawalRequests<E>>,
#[superstruct(only(V2))]
pub consolidation_requests: Option<ConsolidationRequests<E>>,
}
impl<E: EthSpec> ExecutionPayloadBody<E> {
#[allow(clippy::type_complexity)]
pub fn deconstruct(
self,
) -> (
Transactions<E>,
Option<Withdrawals<E>>,
Option<DepositRequests<E>>,
Option<WithdrawalRequests<E>>,
Option<ConsolidationRequests<E>>,
) {
match self {
ExecutionPayloadBody::V1(body) => {
(body.transactions, body.withdrawals, None, None, None)
}
ExecutionPayloadBody::V2(body) => (
body.transactions,
body.withdrawals,
body.deposit_requests,
body.withdrawal_requests,
body.consolidation_requests,
),
}
}
impl<E: EthSpec> ExecutionPayloadBodyV1<E> {
pub fn to_payload(
self,
header: ExecutionPayloadHeader<E>,
) -> Result<ExecutionPayload<E>, String> {
let header_fork = header.fork_name_unchecked();
match &self {
Self::V1(_) => {
if header_fork.electra_enabled() {
return Err(format!(
"block {} is {} but response is ExecutionPayloadBodyV1. Does the EL support {}?",
header.block_hash(),
header_fork,
ENGINE_GET_PAYLOAD_BODIES_BY_HASH_V2,
));
}
}
Self::V2(_) => {}
}
let (
transactions,
withdrawals,
deposit_requests,
withdrawal_requests,
consolidation_requests,
) = self.deconstruct();
if !header_fork.capella_enabled() && withdrawals.is_some() {
return Err(format!(
"block {} is {} but payload body has withdrawals",
header.block_hash(),
header_fork
));
}
if !header_fork.electra_enabled() {
if deposit_requests.is_some() {
return Err(format!(
"block {} is {} but payload body has deposit_requests",
header.block_hash(),
header_fork
));
}
if withdrawal_requests.is_some() {
return Err(format!(
"block {} is {} but payload body has withdrawal_requests",
header.block_hash(),
header_fork
));
}
if consolidation_requests.is_some() {
return Err(format!(
"block {} is {} but payload body has consolidation_requests",
header.block_hash(),
header_fork
));
}
}
match header {
ExecutionPayloadHeader::Bellatrix(header) => {
if self.withdrawals.is_some() {
return Err(format!(
"block {} is bellatrix but payload body has withdrawals",
header.block_hash
));
}
Ok(ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix {
parent_hash: header.parent_hash,
fee_recipient: header.fee_recipient,
@@ -474,108 +402,90 @@ impl<E: EthSpec> ExecutionPayloadBody<E> {
extra_data: header.extra_data,
base_fee_per_gas: header.base_fee_per_gas,
block_hash: header.block_hash,
transactions,
transactions: self.transactions,
}))
}
ExecutionPayloadHeader::Capella(header) => {
let withdrawals = withdrawals.ok_or_else(|| {
format!(
"block {} is {} but payload body has withdrawals set to null",
header.block_hash, header_fork
)
})?;
Ok(ExecutionPayload::Capella(ExecutionPayloadCapella {
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,
withdrawals,
}))
if let Some(withdrawals) = self.withdrawals {
Ok(ExecutionPayload::Capella(ExecutionPayloadCapella {
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,
}))
} else {
Err(format!(
"block {} is capella but payload body doesn't have withdrawals",
header.block_hash
))
}
}
ExecutionPayloadHeader::Deneb(header) => {
let withdrawals = withdrawals.ok_or_else(|| {
format!(
"block {} is {} but payload body has withdrawals set to null",
header.block_hash, header_fork
)
})?;
Ok(ExecutionPayload::Deneb(ExecutionPayloadDeneb {
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,
withdrawals,
blob_gas_used: header.blob_gas_used,
excess_blob_gas: header.excess_blob_gas,
}))
if let Some(withdrawals) = self.withdrawals {
Ok(ExecutionPayload::Deneb(ExecutionPayloadDeneb {
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,
}))
} else {
Err(format!(
"block {} is post capella but payload body doesn't have withdrawals",
header.block_hash
))
}
}
ExecutionPayloadHeader::Electra(header) => {
let withdrawals = withdrawals.ok_or_else(|| {
format!(
"block {} is {} but payload body has withdrawals set to null",
header.block_hash, header_fork
)
})?;
let deposit_requests = deposit_requests.ok_or_else(|| {
format!(
"block {} is {} but payload body has deposit_requests set to null",
header.block_hash, header_fork
)
})?;
let withdrawal_requests = withdrawal_requests.ok_or_else(|| {
format!(
"block {} is {} but payload body has withdrawal_requests set to null",
header.block_hash, header_fork
)
})?;
let consolidation_requests = consolidation_requests.ok_or_else(|| {
format!(
"block {} is {} but payload body has consolidation_requests set to null",
header.block_hash, header_fork
)
})?;
Ok(ExecutionPayload::Electra(ExecutionPayloadElectra {
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,
withdrawals,
blob_gas_used: header.blob_gas_used,
excess_blob_gas: header.excess_blob_gas,
deposit_requests,
withdrawal_requests,
consolidation_requests,
}))
if let Some(withdrawals) = self.withdrawals {
Ok(ExecutionPayload::Electra(ExecutionPayloadElectra {
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,
}))
} else {
Err(format!(
"block {} is post capella but payload body doesn't have withdrawals",
header.block_hash
))
}
}
}
}
@@ -592,8 +502,6 @@ pub struct EngineCapabilities {
pub forkchoice_updated_v3: bool,
pub get_payload_bodies_by_hash_v1: bool,
pub get_payload_bodies_by_range_v1: bool,
pub get_payload_bodies_by_hash_v2: bool,
pub get_payload_bodies_by_range_v2: bool,
pub get_payload_v1: bool,
pub get_payload_v2: bool,
pub get_payload_v3: bool,
@@ -631,12 +539,6 @@ impl EngineCapabilities {
if self.get_payload_bodies_by_range_v1 {
response.push(ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V1);
}
if self.get_payload_bodies_by_hash_v2 {
response.push(ENGINE_GET_PAYLOAD_BODIES_BY_HASH_V2);
}
if self.get_payload_bodies_by_range_v2 {
response.push(ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V2);
}
if self.get_payload_v1 {
response.push(ENGINE_GET_PAYLOAD_V1);
}