Skip to content

Commit efe6989

Browse files
authored
Merge of #4832
2 parents 7c23625 + 9cd7386 commit efe6989

File tree

16 files changed

+961
-226
lines changed

16 files changed

+961
-226
lines changed

Cargo.lock

+414-9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM rust:1.73.0-bullseye AS builder
1+
FROM rust:1.75.0-bullseye AS builder
22
RUN apt-get update && apt-get -y upgrade && apt-get install -y cmake libclang-dev
33
COPY . lighthouse
44
ARG FEATURES

beacon_node/beacon_chain/src/execution_payload.rs

+6-13
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,10 @@ impl<T: BeaconChainTypes> PayloadNotifier<T> {
8181

8282
match notify_execution_layer {
8383
NotifyExecutionLayer::No if chain.config.optimistic_finalized_sync => {
84-
// Verify the block hash here in Lighthouse and immediately mark the block as
85-
// optimistically imported. This saves a lot of roundtrips to the EL.
86-
let execution_layer = chain
87-
.execution_layer
88-
.as_ref()
89-
.ok_or(ExecutionPayloadError::NoExecutionConnection)?;
90-
91-
if let Err(e) = execution_layer.verify_payload_block_hash(block_message) {
84+
// Create a NewPayloadRequest (no clones required) and check optimistic sync verifications
85+
let new_payload_request: NewPayloadRequest<T::EthSpec> =
86+
block_message.try_into()?;
87+
if let Err(e) = new_payload_request.perform_optimistic_sync_verifications() {
9288
warn!(
9389
chain.log,
9490
"Falling back to slow block hash verification";
@@ -143,11 +139,8 @@ async fn notify_new_payload<'a, T: BeaconChainTypes>(
143139
.as_ref()
144140
.ok_or(ExecutionPayloadError::NoExecutionConnection)?;
145141

146-
let new_payload_request: NewPayloadRequest<T::EthSpec> = block.try_into()?;
147-
let execution_block_hash = new_payload_request.block_hash();
148-
let new_payload_response = execution_layer
149-
.notify_new_payload(new_payload_request)
150-
.await;
142+
let execution_block_hash = block.execution_payload()?.block_hash();
143+
let new_payload_response = execution_layer.notify_new_payload(block.try_into()?).await;
151144

152145
match new_payload_response {
153146
Ok(status) => match status {

beacon_node/execution_layer/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,5 @@ hash-db = "0.15.2"
5151
pretty_reqwest_error = { workspace = true }
5252
arc-swap = "1.6.0"
5353
eth2_network_config = { workspace = true }
54+
alloy-rlp = "0.3"
55+
alloy-consensus = { git = "https://github.com/alloy-rs/alloy.git", rev = "974d488bab5e21e9f17452a39a4bfa56677367b2" }

beacon_node/execution_layer/src/block_hash.rs

+47-78
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,61 @@
11
use crate::{
22
json_structures::JsonWithdrawal,
33
keccak::{keccak256, KeccakHasher},
4-
metrics, Error, ExecutionLayer,
54
};
65
use ethers_core::utils::rlp::RlpStream;
76
use keccak_hash::KECCAK_EMPTY_LIST_RLP;
87
use triehash::ordered_trie_root;
98
use types::{
10-
map_execution_block_header_fields_base, Address, BeaconBlockRef, EthSpec, ExecutionBlockHash,
9+
map_execution_block_header_fields_base, Address, EthSpec, ExecutionBlockHash,
1110
ExecutionBlockHeader, ExecutionPayloadRef, Hash256, Hash64, Uint256,
1211
};
1312

14-
impl<T: EthSpec> ExecutionLayer<T> {
15-
/// Calculate the block hash of an execution block.
16-
///
17-
/// Return `(block_hash, transactions_root)`, where `transactions_root` is the root of the RLP
18-
/// transactions.
19-
pub fn calculate_execution_block_hash(
20-
payload: ExecutionPayloadRef<T>,
21-
parent_beacon_block_root: Hash256,
22-
) -> (ExecutionBlockHash, Hash256) {
23-
// Calculate the transactions root.
24-
// We're currently using a deprecated Parity library for this. We should move to a
25-
// better alternative when one appears, possibly following Reth.
26-
let rlp_transactions_root = ordered_trie_root::<KeccakHasher, _>(
27-
payload.transactions().iter().map(|txn_bytes| &**txn_bytes),
28-
);
29-
30-
// Calculate withdrawals root (post-Capella).
31-
let rlp_withdrawals_root = if let Ok(withdrawals) = payload.withdrawals() {
32-
Some(ordered_trie_root::<KeccakHasher, _>(
33-
withdrawals.iter().map(|withdrawal| {
34-
rlp_encode_withdrawal(&JsonWithdrawal::from(withdrawal.clone()))
35-
}),
36-
))
37-
} else {
38-
None
39-
};
40-
41-
let rlp_blob_gas_used = payload.blob_gas_used().ok();
42-
let rlp_excess_blob_gas = payload.excess_blob_gas().ok();
43-
44-
// Calculate parent beacon block root (post-Deneb).
45-
let rlp_parent_beacon_block_root = rlp_excess_blob_gas
46-
.as_ref()
47-
.map(|_| parent_beacon_block_root);
48-
49-
// Construct the block header.
50-
let exec_block_header = ExecutionBlockHeader::from_payload(
51-
payload,
52-
KECCAK_EMPTY_LIST_RLP.as_fixed_bytes().into(),
53-
rlp_transactions_root,
54-
rlp_withdrawals_root,
55-
rlp_blob_gas_used,
56-
rlp_excess_blob_gas,
57-
rlp_parent_beacon_block_root,
58-
);
59-
60-
// Hash the RLP encoding of the block header.
61-
let rlp_block_header = rlp_encode_block_header(&exec_block_header);
62-
(
63-
ExecutionBlockHash::from_root(keccak256(&rlp_block_header)),
64-
rlp_transactions_root,
65-
)
66-
}
67-
68-
/// Verify `payload.block_hash` locally within Lighthouse.
69-
///
70-
/// No remote calls to the execution client will be made, so this is quite a cheap check.
71-
pub fn verify_payload_block_hash(&self, block: BeaconBlockRef<T>) -> Result<(), Error> {
72-
let payload = block.execution_payload()?.execution_payload_ref();
73-
let parent_beacon_block_root = block.parent_root();
74-
75-
let _timer = metrics::start_timer(&metrics::EXECUTION_LAYER_VERIFY_BLOCK_HASH);
76-
77-
let (header_hash, rlp_transactions_root) =
78-
Self::calculate_execution_block_hash(payload, parent_beacon_block_root);
79-
80-
if header_hash != payload.block_hash() {
81-
return Err(Error::BlockHashMismatch {
82-
computed: header_hash,
83-
payload: payload.block_hash(),
84-
transactions_root: rlp_transactions_root,
85-
});
86-
}
87-
88-
Ok(())
89-
}
13+
/// Calculate the block hash of an execution block.
14+
///
15+
/// Return `(block_hash, transactions_root)`, where `transactions_root` is the root of the RLP
16+
/// transactions.
17+
pub fn calculate_execution_block_hash<T: EthSpec>(
18+
payload: ExecutionPayloadRef<T>,
19+
parent_beacon_block_root: Option<Hash256>,
20+
) -> (ExecutionBlockHash, Hash256) {
21+
// Calculate the transactions root.
22+
// We're currently using a deprecated Parity library for this. We should move to a
23+
// better alternative when one appears, possibly following Reth.
24+
let rlp_transactions_root = ordered_trie_root::<KeccakHasher, _>(
25+
payload.transactions().iter().map(|txn_bytes| &**txn_bytes),
26+
);
27+
28+
// Calculate withdrawals root (post-Capella).
29+
let rlp_withdrawals_root = if let Ok(withdrawals) = payload.withdrawals() {
30+
Some(ordered_trie_root::<KeccakHasher, _>(
31+
withdrawals
32+
.iter()
33+
.map(|withdrawal| rlp_encode_withdrawal(&JsonWithdrawal::from(withdrawal.clone()))),
34+
))
35+
} else {
36+
None
37+
};
38+
39+
let rlp_blob_gas_used = payload.blob_gas_used().ok();
40+
let rlp_excess_blob_gas = payload.excess_blob_gas().ok();
41+
42+
// Construct the block header.
43+
let exec_block_header = ExecutionBlockHeader::from_payload(
44+
payload,
45+
KECCAK_EMPTY_LIST_RLP.as_fixed_bytes().into(),
46+
rlp_transactions_root,
47+
rlp_withdrawals_root,
48+
rlp_blob_gas_used,
49+
rlp_excess_blob_gas,
50+
parent_beacon_block_root,
51+
);
52+
53+
// Hash the RLP encoding of the block header.
54+
let rlp_block_header = rlp_encode_block_header(&exec_block_header);
55+
(
56+
ExecutionBlockHash::from_root(keccak256(&rlp_block_header)),
57+
rlp_transactions_root,
58+
)
9059
}
9160

9261
/// RLP encode a withdrawal.

beacon_node/execution_layer/src/engine_api.rs

+6-109
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ pub use json_structures::{JsonWithdrawal, TransitionConfigurationV1};
1717
use pretty_reqwest_error::PrettyReqwestError;
1818
use reqwest::StatusCode;
1919
use serde::{Deserialize, Serialize};
20-
use state_processing::per_block_processing::deneb::kzg_commitment_to_versioned_hash;
2120
use std::convert::TryFrom;
2221
use strum::IntoStaticStr;
2322
use superstruct::superstruct;
@@ -26,14 +25,16 @@ pub use types::{
2625
ExecutionPayloadRef, FixedVector, ForkName, Hash256, Transactions, Uint256, VariableList,
2726
Withdrawal, Withdrawals,
2827
};
29-
use types::{
30-
BeaconStateError, ExecutionPayloadCapella, ExecutionPayloadDeneb, ExecutionPayloadMerge,
31-
KzgProofs, VersionedHash,
32-
};
28+
use types::{ExecutionPayloadCapella, ExecutionPayloadDeneb, ExecutionPayloadMerge, KzgProofs};
3329

3430
pub mod auth;
3531
pub mod http;
3632
pub mod json_structures;
33+
mod new_payload_request;
34+
35+
pub use new_payload_request::{
36+
NewPayloadRequest, NewPayloadRequestCapella, NewPayloadRequestDeneb, NewPayloadRequestMerge,
37+
};
3738

3839
pub const LATEST_TAG: &str = "latest";
3940

@@ -571,110 +572,6 @@ impl<E: EthSpec> ExecutionPayloadBodyV1<E> {
571572
}
572573
}
573574

574-
#[superstruct(
575-
variants(Merge, Capella, Deneb),
576-
variant_attributes(derive(Clone, Debug, PartialEq),),
577-
map_into(ExecutionPayload),
578-
map_ref_into(ExecutionPayloadRef),
579-
cast_error(
580-
ty = "BeaconStateError",
581-
expr = "BeaconStateError::IncorrectStateVariant"
582-
),
583-
partial_getter_error(
584-
ty = "BeaconStateError",
585-
expr = "BeaconStateError::IncorrectStateVariant"
586-
)
587-
)]
588-
#[derive(Clone, Debug, PartialEq)]
589-
pub struct NewPayloadRequest<E: EthSpec> {
590-
#[superstruct(only(Merge), partial_getter(rename = "execution_payload_merge"))]
591-
pub execution_payload: ExecutionPayloadMerge<E>,
592-
#[superstruct(only(Capella), partial_getter(rename = "execution_payload_capella"))]
593-
pub execution_payload: ExecutionPayloadCapella<E>,
594-
#[superstruct(only(Deneb), partial_getter(rename = "execution_payload_deneb"))]
595-
pub execution_payload: ExecutionPayloadDeneb<E>,
596-
#[superstruct(only(Deneb))]
597-
pub versioned_hashes: Vec<VersionedHash>,
598-
#[superstruct(only(Deneb))]
599-
pub parent_beacon_block_root: Hash256,
600-
}
601-
602-
impl<E: EthSpec> NewPayloadRequest<E> {
603-
pub fn parent_hash(&self) -> ExecutionBlockHash {
604-
match self {
605-
Self::Merge(payload) => payload.execution_payload.parent_hash,
606-
Self::Capella(payload) => payload.execution_payload.parent_hash,
607-
Self::Deneb(payload) => payload.execution_payload.parent_hash,
608-
}
609-
}
610-
611-
pub fn block_hash(&self) -> ExecutionBlockHash {
612-
match self {
613-
Self::Merge(payload) => payload.execution_payload.block_hash,
614-
Self::Capella(payload) => payload.execution_payload.block_hash,
615-
Self::Deneb(payload) => payload.execution_payload.block_hash,
616-
}
617-
}
618-
619-
pub fn block_number(&self) -> u64 {
620-
match self {
621-
Self::Merge(payload) => payload.execution_payload.block_number,
622-
Self::Capella(payload) => payload.execution_payload.block_number,
623-
Self::Deneb(payload) => payload.execution_payload.block_number,
624-
}
625-
}
626-
627-
pub fn into_execution_payload(self) -> ExecutionPayload<E> {
628-
map_new_payload_request_into_execution_payload!(self, |request, cons| {
629-
cons(request.execution_payload)
630-
})
631-
}
632-
}
633-
634-
impl<'a, E: EthSpec> TryFrom<BeaconBlockRef<'a, E>> for NewPayloadRequest<E> {
635-
type Error = BeaconStateError;
636-
637-
fn try_from(block: BeaconBlockRef<'a, E>) -> Result<Self, Self::Error> {
638-
match block {
639-
BeaconBlockRef::Base(_) | BeaconBlockRef::Altair(_) => {
640-
Err(Self::Error::IncorrectStateVariant)
641-
}
642-
BeaconBlockRef::Merge(block_ref) => Ok(Self::Merge(NewPayloadRequestMerge {
643-
execution_payload: block_ref.body.execution_payload.execution_payload.clone(),
644-
})),
645-
BeaconBlockRef::Capella(block_ref) => Ok(Self::Capella(NewPayloadRequestCapella {
646-
execution_payload: block_ref.body.execution_payload.execution_payload.clone(),
647-
})),
648-
BeaconBlockRef::Deneb(block_ref) => Ok(Self::Deneb(NewPayloadRequestDeneb {
649-
execution_payload: block_ref.body.execution_payload.execution_payload.clone(),
650-
versioned_hashes: block_ref
651-
.body
652-
.blob_kzg_commitments
653-
.iter()
654-
.map(kzg_commitment_to_versioned_hash)
655-
.collect(),
656-
parent_beacon_block_root: block_ref.parent_root,
657-
})),
658-
}
659-
}
660-
}
661-
662-
impl<E: EthSpec> TryFrom<ExecutionPayload<E>> for NewPayloadRequest<E> {
663-
type Error = BeaconStateError;
664-
665-
fn try_from(payload: ExecutionPayload<E>) -> Result<Self, Self::Error> {
666-
match payload {
667-
ExecutionPayload::Merge(payload) => Ok(Self::Merge(NewPayloadRequestMerge {
668-
execution_payload: payload,
669-
})),
670-
ExecutionPayload::Capella(payload) => Ok(Self::Capella(NewPayloadRequestCapella {
671-
execution_payload: payload,
672-
})),
673-
ExecutionPayload::Deneb(_) => Err(Self::Error::IncorrectStateVariant),
674-
}
675-
}
676-
}
677-
678575
#[derive(Clone, Copy, Debug)]
679576
pub struct EngineCapabilities {
680577
pub new_payload_v1: bool,

beacon_node/execution_layer/src/engine_api/http.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -803,10 +803,10 @@ impl HttpJsonRpc {
803803

804804
pub async fn new_payload_v3<T: EthSpec>(
805805
&self,
806-
new_payload_request_deneb: NewPayloadRequestDeneb<T>,
806+
new_payload_request_deneb: NewPayloadRequestDeneb<'_, T>,
807807
) -> Result<PayloadStatusV1, Error> {
808808
let params = json!([
809-
JsonExecutionPayload::V3(new_payload_request_deneb.execution_payload.into()),
809+
JsonExecutionPayload::V3(new_payload_request_deneb.execution_payload.clone().into()),
810810
new_payload_request_deneb.versioned_hashes,
811811
new_payload_request_deneb.parent_beacon_block_root,
812812
]);
@@ -1079,7 +1079,7 @@ impl HttpJsonRpc {
10791079
// new_payload that the execution engine supports
10801080
pub async fn new_payload<T: EthSpec>(
10811081
&self,
1082-
new_payload_request: NewPayloadRequest<T>,
1082+
new_payload_request: NewPayloadRequest<'_, T>,
10831083
) -> Result<PayloadStatusV1, Error> {
10841084
let engine_capabilities = self.get_engine_capabilities(None).await?;
10851085
match new_payload_request {

0 commit comments

Comments
 (0)