Skip to content

Commit f46437a

Browse files
authored
Merge of #6695
2 parents 0d7db85 + 93e79db commit f46437a

File tree

91 files changed

+2359
-668
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+2359
-668
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ PROFILE ?= release
3030

3131
# List of all hard forks. This list is used to set env variables for several tests so that
3232
# they run for different forks.
33-
FORKS=phase0 altair bellatrix capella deneb electra
33+
FORKS=phase0 altair bellatrix capella deneb electra fulu
3434

3535
# Extra flags for Cargo
3636
CARGO_INSTALL_EXTRA_FLAGS?=

beacon_node/beacon_chain/src/attestation_rewards.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,10 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
5151
.get_state(&state_root, Some(state_slot))?
5252
.ok_or(BeaconChainError::MissingBeaconState(state_root))?;
5353

54-
match state {
55-
BeaconState::Base(_) => self.compute_attestation_rewards_base(state, validators),
56-
BeaconState::Altair(_)
57-
| BeaconState::Bellatrix(_)
58-
| BeaconState::Capella(_)
59-
| BeaconState::Deneb(_)
60-
| BeaconState::Electra(_) => self.compute_attestation_rewards_altair(state, validators),
54+
if state.fork_name_unchecked().altair_enabled() {
55+
self.compute_attestation_rewards_altair(state, validators)
56+
} else {
57+
self.compute_attestation_rewards_base(state, validators)
6158
}
6259
}
6360

beacon_node/beacon_chain/src/beacon_block_streamer.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use types::{
1515
};
1616
use types::{
1717
ExecutionPayload, ExecutionPayloadBellatrix, ExecutionPayloadCapella, ExecutionPayloadElectra,
18-
ExecutionPayloadHeader,
18+
ExecutionPayloadFulu, ExecutionPayloadHeader,
1919
};
2020

2121
#[derive(PartialEq)]
@@ -99,6 +99,7 @@ fn reconstruct_default_header_block<E: EthSpec>(
9999
ForkName::Capella => ExecutionPayloadCapella::default().into(),
100100
ForkName::Deneb => ExecutionPayloadDeneb::default().into(),
101101
ForkName::Electra => ExecutionPayloadElectra::default().into(),
102+
ForkName::Fulu => ExecutionPayloadFulu::default().into(),
102103
ForkName::Base | ForkName::Altair => {
103104
return Err(Error::PayloadReconstruction(format!(
104105
"Block with fork variant {} has execution payload",
@@ -742,13 +743,14 @@ mod tests {
742743
}
743744

744745
#[tokio::test]
745-
async fn check_all_blocks_from_altair_to_electra() {
746+
async fn check_all_blocks_from_altair_to_fulu() {
746747
let slots_per_epoch = MinimalEthSpec::slots_per_epoch() as usize;
747-
let num_epochs = 10;
748+
let num_epochs = 12;
748749
let bellatrix_fork_epoch = 2usize;
749750
let capella_fork_epoch = 4usize;
750751
let deneb_fork_epoch = 6usize;
751752
let electra_fork_epoch = 8usize;
753+
let fulu_fork_epoch = 10usize;
752754
let num_blocks_produced = num_epochs * slots_per_epoch;
753755

754756
let mut spec = test_spec::<MinimalEthSpec>();
@@ -757,6 +759,7 @@ mod tests {
757759
spec.capella_fork_epoch = Some(Epoch::new(capella_fork_epoch as u64));
758760
spec.deneb_fork_epoch = Some(Epoch::new(deneb_fork_epoch as u64));
759761
spec.electra_fork_epoch = Some(Epoch::new(electra_fork_epoch as u64));
762+
spec.fulu_fork_epoch = Some(Epoch::new(fulu_fork_epoch as u64));
760763
let spec = Arc::new(spec);
761764

762765
let harness = get_harness(VALIDATOR_COUNT, spec.clone());

beacon_node/beacon_chain/src/beacon_chain.rs

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5317,23 +5317,19 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
53175317

53185318
// If required, start the process of loading an execution payload from the EL early. This
53195319
// allows it to run concurrently with things like attestation packing.
5320-
let prepare_payload_handle = match &state {
5321-
BeaconState::Base(_) | BeaconState::Altair(_) => None,
5322-
BeaconState::Bellatrix(_)
5323-
| BeaconState::Capella(_)
5324-
| BeaconState::Deneb(_)
5325-
| BeaconState::Electra(_) => {
5326-
let prepare_payload_handle = get_execution_payload(
5327-
self.clone(),
5328-
&state,
5329-
parent_root,
5330-
proposer_index,
5331-
builder_params,
5332-
builder_boost_factor,
5333-
block_production_version,
5334-
)?;
5335-
Some(prepare_payload_handle)
5336-
}
5320+
let prepare_payload_handle = if state.fork_name_unchecked().bellatrix_enabled() {
5321+
let prepare_payload_handle = get_execution_payload(
5322+
self.clone(),
5323+
&state,
5324+
parent_root,
5325+
proposer_index,
5326+
builder_params,
5327+
builder_boost_factor,
5328+
block_production_version,
5329+
)?;
5330+
Some(prepare_payload_handle)
5331+
} else {
5332+
None
53375333
};
53385334

53395335
let (mut proposer_slashings, mut attester_slashings, mut voluntary_exits) =
@@ -5751,6 +5747,48 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
57515747
execution_payload_value,
57525748
)
57535749
}
5750+
BeaconState::Fulu(_) => {
5751+
let (
5752+
payload,
5753+
kzg_commitments,
5754+
maybe_blobs_and_proofs,
5755+
maybe_requests,
5756+
execution_payload_value,
5757+
) = block_contents
5758+
.ok_or(BlockProductionError::MissingExecutionPayload)?
5759+
.deconstruct();
5760+
5761+
(
5762+
BeaconBlock::Fulu(BeaconBlockFulu {
5763+
slot,
5764+
proposer_index,
5765+
parent_root,
5766+
state_root: Hash256::zero(),
5767+
body: BeaconBlockBodyFulu {
5768+
randao_reveal,
5769+
eth1_data,
5770+
graffiti,
5771+
proposer_slashings: proposer_slashings.into(),
5772+
attester_slashings: attester_slashings_electra.into(),
5773+
attestations: attestations_electra.into(),
5774+
deposits: deposits.into(),
5775+
voluntary_exits: voluntary_exits.into(),
5776+
sync_aggregate: sync_aggregate
5777+
.ok_or(BlockProductionError::MissingSyncAggregate)?,
5778+
execution_payload: payload
5779+
.try_into()
5780+
.map_err(|_| BlockProductionError::InvalidPayloadFork)?,
5781+
bls_to_execution_changes: bls_to_execution_changes.into(),
5782+
blob_kzg_commitments: kzg_commitments
5783+
.ok_or(BlockProductionError::InvalidPayloadFork)?,
5784+
execution_requests: maybe_requests
5785+
.ok_or(BlockProductionError::MissingExecutionRequests)?,
5786+
},
5787+
}),
5788+
maybe_blobs_and_proofs,
5789+
execution_payload_value,
5790+
)
5791+
}
57545792
};
57555793

57565794
let block = SignedBeaconBlock::from_block(

beacon_node/beacon_chain/src/execution_payload.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -374,19 +374,15 @@ pub fn get_execution_payload<T: BeaconChainTypes>(
374374
let latest_execution_payload_header = state.latest_execution_payload_header()?;
375375
let latest_execution_payload_header_block_hash = latest_execution_payload_header.block_hash();
376376
let latest_execution_payload_header_gas_limit = latest_execution_payload_header.gas_limit();
377-
let withdrawals = match state {
378-
&BeaconState::Capella(_) | &BeaconState::Deneb(_) | &BeaconState::Electra(_) => {
379-
Some(get_expected_withdrawals(state, spec)?.0.into())
380-
}
381-
&BeaconState::Bellatrix(_) => None,
382-
// These shouldn't happen but they're here to make the pattern irrefutable
383-
&BeaconState::Base(_) | &BeaconState::Altair(_) => None,
377+
let withdrawals = if state.fork_name_unchecked().capella_enabled() {
378+
Some(get_expected_withdrawals(state, spec)?.0.into())
379+
} else {
380+
None
384381
};
385-
let parent_beacon_block_root = match state {
386-
BeaconState::Deneb(_) | BeaconState::Electra(_) => Some(parent_block_root),
387-
BeaconState::Bellatrix(_) | BeaconState::Capella(_) => None,
388-
// These shouldn't happen but they're here to make the pattern irrefutable
389-
BeaconState::Base(_) | BeaconState::Altair(_) => None,
382+
let parent_beacon_block_root = if state.fork_name_unchecked().deneb_enabled() {
383+
Some(parent_block_root)
384+
} else {
385+
None
390386
};
391387

392388
// Spawn a task to obtain the execution payload from the EL via a series of async calls. The
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
//! Provides tools for checking if a node is ready for the Fulu upgrade.
2+
3+
use crate::{BeaconChain, BeaconChainTypes};
4+
use execution_layer::http::{ENGINE_GET_PAYLOAD_V5, ENGINE_NEW_PAYLOAD_V5};
5+
use serde::{Deserialize, Serialize};
6+
use std::fmt;
7+
use std::time::Duration;
8+
use types::*;
9+
10+
/// The time before the Fulu fork when we will start issuing warnings about preparation.
11+
use super::bellatrix_readiness::SECONDS_IN_A_WEEK;
12+
pub const FULU_READINESS_PREPARATION_SECONDS: u64 = SECONDS_IN_A_WEEK * 2;
13+
pub const ENGINE_CAPABILITIES_REFRESH_INTERVAL: u64 = 300;
14+
15+
#[derive(Debug, Serialize, Deserialize)]
16+
#[serde(rename_all = "snake_case")]
17+
#[serde(tag = "type")]
18+
pub enum FuluReadiness {
19+
/// The execution engine is fulu-enabled (as far as we can tell)
20+
Ready,
21+
/// We are connected to an execution engine which doesn't support the V5 engine api methods
22+
V5MethodsNotSupported { error: String },
23+
/// The transition configuration with the EL failed, there might be a problem with
24+
/// connectivity, authentication or a difference in configuration.
25+
ExchangeCapabilitiesFailed { error: String },
26+
/// The user has not configured an execution endpoint
27+
NoExecutionEndpoint,
28+
}
29+
30+
impl fmt::Display for FuluReadiness {
31+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32+
match self {
33+
FuluReadiness::Ready => {
34+
write!(f, "This node appears ready for Fulu.")
35+
}
36+
FuluReadiness::ExchangeCapabilitiesFailed { error } => write!(
37+
f,
38+
"Could not exchange capabilities with the \
39+
execution endpoint: {}",
40+
error
41+
),
42+
FuluReadiness::NoExecutionEndpoint => write!(
43+
f,
44+
"The --execution-endpoint flag is not specified, this is a \
45+
requirement post-merge"
46+
),
47+
FuluReadiness::V5MethodsNotSupported { error } => write!(
48+
f,
49+
"Execution endpoint does not support Fulu methods: {}",
50+
error
51+
),
52+
}
53+
}
54+
}
55+
56+
impl<T: BeaconChainTypes> BeaconChain<T> {
57+
/// Returns `true` if fulu epoch is set and Fulu fork has occurred or will
58+
/// occur within `FULU_READINESS_PREPARATION_SECONDS`
59+
pub fn is_time_to_prepare_for_fulu(&self, current_slot: Slot) -> bool {
60+
if let Some(fulu_epoch) = self.spec.fulu_fork_epoch {
61+
let fulu_slot = fulu_epoch.start_slot(T::EthSpec::slots_per_epoch());
62+
let fulu_readiness_preparation_slots =
63+
FULU_READINESS_PREPARATION_SECONDS / self.spec.seconds_per_slot;
64+
// Return `true` if Fulu has happened or is within the preparation time.
65+
current_slot + fulu_readiness_preparation_slots > fulu_slot
66+
} else {
67+
// The Fulu fork epoch has not been defined yet, no need to prepare.
68+
false
69+
}
70+
}
71+
72+
/// Attempts to connect to the EL and confirm that it is ready for fulu.
73+
pub async fn check_fulu_readiness(&self) -> FuluReadiness {
74+
if let Some(el) = self.execution_layer.as_ref() {
75+
match el
76+
.get_engine_capabilities(Some(Duration::from_secs(
77+
ENGINE_CAPABILITIES_REFRESH_INTERVAL,
78+
)))
79+
.await
80+
{
81+
Err(e) => {
82+
// The EL was either unreachable or responded with an error
83+
FuluReadiness::ExchangeCapabilitiesFailed {
84+
error: format!("{:?}", e),
85+
}
86+
}
87+
Ok(capabilities) => {
88+
let mut missing_methods = String::from("Required Methods Unsupported:");
89+
let mut all_good = true;
90+
if !capabilities.get_payload_v5 {
91+
missing_methods.push(' ');
92+
missing_methods.push_str(ENGINE_GET_PAYLOAD_V5);
93+
all_good = false;
94+
}
95+
if !capabilities.new_payload_v5 {
96+
missing_methods.push(' ');
97+
missing_methods.push_str(ENGINE_NEW_PAYLOAD_V5);
98+
all_good = false;
99+
}
100+
101+
if all_good {
102+
FuluReadiness::Ready
103+
} else {
104+
FuluReadiness::V5MethodsNotSupported {
105+
error: missing_methods,
106+
}
107+
}
108+
}
109+
}
110+
} else {
111+
FuluReadiness::NoExecutionEndpoint
112+
}
113+
}
114+
}

beacon_node/beacon_chain/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub mod execution_payload;
3131
pub mod fetch_blobs;
3232
pub mod fork_choice_signal;
3333
pub mod fork_revert;
34+
pub mod fulu_readiness;
3435
pub mod graffiti_calculator;
3536
mod head_tracker;
3637
pub mod historical_blocks;

0 commit comments

Comments
 (0)