Merge remote-tracking branch 'origin/unstable' into fc-compliance

This commit is contained in:
Michael Sproul
2026-05-25 15:42:29 +10:00
21 changed files with 526 additions and 554 deletions

View File

@@ -701,11 +701,9 @@ impl ProtoArray {
justified_balances: &JustifiedBalances,
spec: &ChainSpec,
) -> bool {
let reorg_threshold = calculate_committee_fraction::<E>(
justified_balances,
spec.reorg_head_weight_threshold.unwrap_or(20),
)
.unwrap_or(0);
let reorg_threshold =
calculate_committee_fraction::<E>(justified_balances, spec.reorg_head_weight_threshold)
.unwrap_or(0);
let head_weight = head_node
.attestation_score(PayloadStatus::Pending)

View File

@@ -44,6 +44,7 @@ merkle_proof = { workspace = true }
metastruct = "0.1.0"
milhouse = { workspace = true }
parking_lot = { workspace = true }
paste = { workspace = true }
rand = { workspace = true }
rand_xorshift = { workspace = true }
rayon = { workspace = true }
@@ -67,7 +68,6 @@ yaml_serde = { workspace = true }
[dev-dependencies]
beacon_chain = { workspace = true }
criterion = { workspace = true }
paste = { workspace = true }
state_processing = { workspace = true }
tokio = { workspace = true }
types = { path = ".", features = ["arbitrary"] }

View File

@@ -433,285 +433,85 @@ impl<E: EthSpec> From<SignedBeaconBlockAltair<E, BlindedPayload<E>>>
}
// Post-Bellatrix blocks can be "unblinded" by adding the full payload.
// NOTE: It might be nice to come up with a `superstruct` pattern to abstract over this before
// the first fork after Bellatrix.
impl<E: EthSpec> SignedBeaconBlockBellatrix<E, BlindedPayload<E>> {
pub fn into_full_block(
self,
execution_payload: ExecutionPayloadBellatrix<E>,
) -> SignedBeaconBlockBellatrix<E, FullPayload<E>> {
let SignedBeaconBlockBellatrix {
message:
BeaconBlockBellatrix {
slot,
proposer_index,
parent_root,
state_root,
body:
BeaconBlockBodyBellatrix {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: BlindedPayloadBellatrix { .. },
macro_rules! impl_into_full_block {
($fork:ident, [ $($extra_field:ident),* $(,)? ]) => {
paste::paste! {
impl<E: EthSpec> [<SignedBeaconBlock $fork>]<E, BlindedPayload<E>> {
pub fn into_full_block(
self,
execution_payload: [<ExecutionPayload $fork>]<E>,
) -> [<SignedBeaconBlock $fork>]<E, FullPayload<E>> {
let [<SignedBeaconBlock $fork>] {
message:
[<BeaconBlock $fork>] {
slot,
proposer_index,
parent_root,
state_root,
body:
[<BeaconBlockBody $fork>] {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: [<BlindedPayload $fork>] { .. },
$($extra_field,)*
},
},
signature,
} = self;
[<SignedBeaconBlock $fork>] {
message: [<BeaconBlock $fork>] {
slot,
proposer_index,
parent_root,
state_root,
body: [<BeaconBlockBody $fork>] {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: [<FullPayload $fork>] { execution_payload },
$($extra_field,)*
},
},
},
signature,
} = self;
SignedBeaconBlockBellatrix {
message: BeaconBlockBellatrix {
slot,
proposer_index,
parent_root,
state_root,
body: BeaconBlockBodyBellatrix {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: FullPayloadBellatrix { execution_payload },
},
},
signature,
signature,
}
}
}
}
}
};
}
impl<E: EthSpec> SignedBeaconBlockCapella<E, BlindedPayload<E>> {
pub fn into_full_block(
self,
execution_payload: ExecutionPayloadCapella<E>,
) -> SignedBeaconBlockCapella<E, FullPayload<E>> {
let SignedBeaconBlockCapella {
message:
BeaconBlockCapella {
slot,
proposer_index,
parent_root,
state_root,
body:
BeaconBlockBodyCapella {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: BlindedPayloadCapella { .. },
bls_to_execution_changes,
},
},
signature,
} = self;
SignedBeaconBlockCapella {
message: BeaconBlockCapella {
slot,
proposer_index,
parent_root,
state_root,
body: BeaconBlockBodyCapella {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: FullPayloadCapella { execution_payload },
bls_to_execution_changes,
},
},
signature,
}
}
}
impl<E: EthSpec> SignedBeaconBlockDeneb<E, BlindedPayload<E>> {
pub fn into_full_block(
self,
execution_payload: ExecutionPayloadDeneb<E>,
) -> SignedBeaconBlockDeneb<E, FullPayload<E>> {
let SignedBeaconBlockDeneb {
message:
BeaconBlockDeneb {
slot,
proposer_index,
parent_root,
state_root,
body:
BeaconBlockBodyDeneb {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: BlindedPayloadDeneb { .. },
bls_to_execution_changes,
blob_kzg_commitments,
},
},
signature,
} = self;
SignedBeaconBlockDeneb {
message: BeaconBlockDeneb {
slot,
proposer_index,
parent_root,
state_root,
body: BeaconBlockBodyDeneb {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: FullPayloadDeneb { execution_payload },
bls_to_execution_changes,
blob_kzg_commitments,
},
},
signature,
}
}
}
impl<E: EthSpec> SignedBeaconBlockElectra<E, BlindedPayload<E>> {
pub fn into_full_block(
self,
execution_payload: ExecutionPayloadElectra<E>,
) -> SignedBeaconBlockElectra<E, FullPayload<E>> {
let SignedBeaconBlockElectra {
message:
BeaconBlockElectra {
slot,
proposer_index,
parent_root,
state_root,
body:
BeaconBlockBodyElectra {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: BlindedPayloadElectra { .. },
bls_to_execution_changes,
blob_kzg_commitments,
execution_requests,
},
},
signature,
} = self;
SignedBeaconBlockElectra {
message: BeaconBlockElectra {
slot,
proposer_index,
parent_root,
state_root,
body: BeaconBlockBodyElectra {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: FullPayloadElectra { execution_payload },
bls_to_execution_changes,
blob_kzg_commitments,
execution_requests,
},
},
signature,
}
}
}
impl<E: EthSpec> SignedBeaconBlockFulu<E, BlindedPayload<E>> {
pub fn into_full_block(
self,
execution_payload: ExecutionPayloadFulu<E>,
) -> SignedBeaconBlockFulu<E, FullPayload<E>> {
let SignedBeaconBlockFulu {
message:
BeaconBlockFulu {
slot,
proposer_index,
parent_root,
state_root,
body:
BeaconBlockBodyFulu {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: BlindedPayloadFulu { .. },
bls_to_execution_changes,
blob_kzg_commitments,
execution_requests,
},
},
signature,
} = self;
SignedBeaconBlockFulu {
message: BeaconBlockFulu {
slot,
proposer_index,
parent_root,
state_root,
body: BeaconBlockBodyFulu {
randao_reveal,
eth1_data,
graffiti,
proposer_slashings,
attester_slashings,
attestations,
deposits,
voluntary_exits,
sync_aggregate,
execution_payload: FullPayloadFulu { execution_payload },
bls_to_execution_changes,
blob_kzg_commitments,
execution_requests,
},
},
signature,
}
}
}
impl_into_full_block!(Bellatrix, []);
impl_into_full_block!(Capella, [bls_to_execution_changes]);
impl_into_full_block!(Deneb, [bls_to_execution_changes, blob_kzg_commitments]);
impl_into_full_block!(
Electra,
[
bls_to_execution_changes,
blob_kzg_commitments,
execution_requests
]
);
impl_into_full_block!(
Fulu,
[
bls_to_execution_changes,
blob_kzg_commitments,
execution_requests
]
);
// We can convert gloas blocks without payloads into blocks "with" payloads.
// TODO(EIP-7732) Look into whether we can remove this in the future since no blinded blocks post-gloas

View File

@@ -152,9 +152,9 @@ pub struct ChainSpec {
* Fork choice
*/
pub proposer_score_boost: Option<u64>,
pub reorg_head_weight_threshold: Option<u64>,
pub reorg_parent_weight_threshold: Option<u64>,
pub reorg_max_epochs_since_finalization: Option<u64>,
pub reorg_head_weight_threshold: u64,
pub reorg_parent_weight_threshold: u64,
pub reorg_max_epochs_since_finalization: u64,
/*
* Eth1
@@ -925,7 +925,7 @@ impl ChainSpec {
}
/// Calculate the duration into a slot for a given slot component
fn compute_slot_component_duration(
pub fn compute_slot_component_duration(
&self,
component_basis_points: u64,
) -> Result<Duration, ArithError> {
@@ -1163,9 +1163,9 @@ impl ChainSpec {
* Fork choice
*/
proposer_score_boost: Some(40),
reorg_head_weight_threshold: Some(20),
reorg_parent_weight_threshold: Some(160),
reorg_max_epochs_since_finalization: Some(2),
reorg_head_weight_threshold: 20,
reorg_parent_weight_threshold: 160,
reorg_max_epochs_since_finalization: 2,
/*
* Eth1
@@ -1588,9 +1588,9 @@ impl ChainSpec {
* Fork choice
*/
proposer_score_boost: Some(40),
reorg_head_weight_threshold: Some(20),
reorg_parent_weight_threshold: Some(160),
reorg_max_epochs_since_finalization: Some(2),
reorg_head_weight_threshold: 20,
reorg_parent_weight_threshold: 160,
reorg_max_epochs_since_finalization: 2,
/*
* Eth1
@@ -2028,12 +2028,15 @@ pub struct Config {
#[serde(skip_serializing_if = "Option::is_none")]
proposer_score_boost: Option<MaybeQuoted<u64>>,
#[serde(skip_serializing_if = "Option::is_none")]
reorg_head_weight_threshold: Option<MaybeQuoted<u64>>,
#[serde(skip_serializing_if = "Option::is_none")]
reorg_parent_weight_threshold: Option<MaybeQuoted<u64>>,
#[serde(skip_serializing_if = "Option::is_none")]
reorg_max_epochs_since_finalization: Option<MaybeQuoted<u64>>,
#[serde(default = "default_reorg_head_weight_threshold")]
#[serde(with = "serde_utils::quoted_u64")]
reorg_head_weight_threshold: u64,
#[serde(default = "default_reorg_parent_weight_threshold")]
#[serde(with = "serde_utils::quoted_u64")]
reorg_parent_weight_threshold: u64,
#[serde(default = "default_reorg_max_epochs_since_finalization")]
#[serde(with = "serde_utils::quoted_u64")]
reorg_max_epochs_since_finalization: u64,
#[serde(with = "serde_utils::quoted_u64")]
deposit_chain_id: u64,
@@ -2433,6 +2436,18 @@ const fn default_max_per_epoch_activation_churn_limit_gloas() -> u64 {
256_000_000_000
}
const fn default_reorg_head_weight_threshold() -> u64 {
20
}
const fn default_reorg_parent_weight_threshold() -> u64 {
160
}
const fn default_reorg_max_epochs_since_finalization() -> u64 {
2
}
fn max_blocks_by_root_request_common(max_request_blocks: u64) -> usize {
let max_request_blocks = max_request_blocks as usize;
RuntimeVariableList::<Hash256>::new(
@@ -2626,15 +2641,9 @@ impl Config {
max_per_epoch_activation_churn_limit: spec.max_per_epoch_activation_churn_limit,
proposer_score_boost: spec.proposer_score_boost.map(|value| MaybeQuoted { value }),
reorg_head_weight_threshold: spec
.reorg_head_weight_threshold
.map(|value| MaybeQuoted { value }),
reorg_parent_weight_threshold: spec
.reorg_parent_weight_threshold
.map(|value| MaybeQuoted { value }),
reorg_max_epochs_since_finalization: spec
.reorg_max_epochs_since_finalization
.map(|value| MaybeQuoted { value }),
reorg_head_weight_threshold: spec.reorg_head_weight_threshold,
reorg_parent_weight_threshold: spec.reorg_parent_weight_threshold,
reorg_max_epochs_since_finalization: spec.reorg_max_epochs_since_finalization,
deposit_chain_id: spec.deposit_chain_id,
deposit_network_id: spec.deposit_network_id,
@@ -2846,10 +2855,9 @@ impl Config {
max_per_epoch_activation_churn_limit,
churn_limit_quotient,
proposer_score_boost: proposer_score_boost.map(|q| q.value),
reorg_head_weight_threshold: reorg_head_weight_threshold.map(|q| q.value),
reorg_parent_weight_threshold: reorg_parent_weight_threshold.map(|q| q.value),
reorg_max_epochs_since_finalization: reorg_max_epochs_since_finalization
.map(|q| q.value),
reorg_head_weight_threshold,
reorg_parent_weight_threshold,
reorg_max_epochs_since_finalization,
deposit_chain_id,
deposit_network_id,
deposit_contract_address,