This commit is contained in:
Eitan Seri-Levi
2026-04-30 16:22:17 +02:00
parent e23e3ac794
commit 313e2d946c
11 changed files with 97 additions and 92 deletions

View File

@@ -33,8 +33,8 @@ use types::{
ExecutionPayloadEnvelope, ExecutionPayloadGloas, ExecutionRequests, FullPayload, Graffiti,
Hash256, PayloadAttestation, ProposerSlashing, RelativeEpoch, SignedBeaconBlock,
SignedBlsToExecutionChange, SignedExecutionPayloadBid, SignedExecutionPayloadBidGloas,
SignedExecutionPayloadBidHeze, SignedExecutionPayloadEnvelope, SignedVoluntaryExit,
Slot, SyncAggregate, Withdrawal, Withdrawals,
SignedExecutionPayloadBidHeze, SignedExecutionPayloadEnvelope, SignedVoluntaryExit, Slot,
SyncAggregate, Withdrawal, Withdrawals,
};
use crate::pending_payload_envelopes::PendingEnvelopeData;
@@ -607,8 +607,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
.unwrap_or_default();
let heze_bid = match signed_execution_payload_bid {
SignedExecutionPayloadBid::Heze(bid) => bid,
SignedExecutionPayloadBid::Gloas(gloas_bid) => {
SignedExecutionPayloadBidHeze {
SignedExecutionPayloadBid::Gloas(gloas_bid) => SignedExecutionPayloadBidHeze {
message: ExecutionPayloadBidHeze {
parent_block_hash: gloas_bid.message.parent_block_hash,
parent_block_root: gloas_bid.message.parent_block_root,
@@ -625,8 +624,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
inclusion_list_bits,
},
signature: gloas_bid.signature,
}
}
},
};
BeaconBlock::Heze(BeaconBlockHeze {
slot,

View File

@@ -57,6 +57,10 @@ impl<T: BeaconChainTypes> GossipVerifiedInclusionList<T> {
return Err(GossipInclusionListError::TooManyTransactions);
}
// TODO(focil): Spec says message.slot must equal current_slot with
// MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance. We currently also accept current_slot - 1
// and add an attestation-deadline check that is not in the spec.
// See: https://github.com/ethereum/consensus-specs/blob/master/specs/heze/p2p-interface.md#inclusion_list
if message_slot != current_slot && message_slot != current_slot - 1 {
return Err(GossipInclusionListError::InvalidSlot {
message_slot,

View File

@@ -251,9 +251,8 @@ mod tests {
use kzg::KzgCommitment;
use ssz_types::VariableList;
use types::{
Address, BeaconState, ChainSpec, EthSpec, ExecutionPayloadBidGloas,
ExecutionPayloadBidRef, MinimalEthSpec, ProposerPreferences, SignedProposerPreferences,
Slot,
Address, BeaconState, ChainSpec, EthSpec, ExecutionPayloadBidGloas, ExecutionPayloadBidRef,
MinimalEthSpec, ProposerPreferences, SignedProposerPreferences, Slot,
};
use super::verify_bid_consistency;

View File

@@ -166,10 +166,12 @@ impl TestContext {
);
let message = bid.signing_root(domain);
let signature = self.keypairs[bid.builder_index as usize].sk.sign(message);
Arc::new(SignedExecutionPayloadBid::Gloas(SignedExecutionPayloadBidGloas {
Arc::new(SignedExecutionPayloadBid::Gloas(
SignedExecutionPayloadBidGloas {
message: bid,
signature,
}))
},
))
}
fn gossip_ctx(&self) -> GossipVerificationContext<'_, T> {
@@ -423,7 +425,8 @@ fn execution_payment_nonzero() {
let slot = Slot::new(0);
seed_preferences(&ctx, slot, Address::ZERO, 30_000_000);
let bid = Arc::new(SignedExecutionPayloadBid::Gloas(SignedExecutionPayloadBidGloas {
let bid = Arc::new(SignedExecutionPayloadBid::Gloas(
SignedExecutionPayloadBidGloas {
message: ExecutionPayloadBidGloas {
slot,
gas_limit: 30_000_000,
@@ -432,7 +435,8 @@ fn execution_payment_nonzero() {
..ExecutionPayloadBidGloas::default()
},
signature: Signature::empty(),
}));
},
));
let result = GossipVerifiedPayloadBid::new(bid, &gossip);
assert!(matches!(
result,
@@ -579,7 +583,8 @@ fn invalid_blob_kzg_commitments() {
.map(|_| KzgCommitment::empty_for_testing())
.collect();
let bid = Arc::new(SignedExecutionPayloadBid::Gloas(SignedExecutionPayloadBidGloas {
let bid = Arc::new(SignedExecutionPayloadBid::Gloas(
SignedExecutionPayloadBidGloas {
message: ExecutionPayloadBidGloas {
slot,
builder_index: 0,
@@ -591,7 +596,8 @@ fn invalid_blob_kzg_commitments() {
..ExecutionPayloadBidGloas::default()
},
signature: Signature::empty(),
}));
},
));
let result = GossipVerifiedPayloadBid::new(bid, &gossip);
assert!(matches!(
result,

View File

@@ -756,9 +756,7 @@ impl HttpJsonRpc {
pub async fn update_payload_with_inclusion_list<E: EthSpec>(&self) {}
pub async fn get_inclusion_list<E: EthSpec>(
&self,
) -> Result<Option<Vec<String>>, Error> {
pub async fn get_inclusion_list<E: EthSpec>(&self) -> Result<Option<Vec<String>>, Error> {
let params = json!([]);
self.rpc_request(

View File

@@ -2008,11 +2008,7 @@ impl<E: EthSpec> ExecutionLayer<E> {
pub async fn get_inclusion_list(&self) -> Result<Transactions<E>, Error> {
debug!("Requesting inclusion list from EL");
let raw_transactions = self
.engine()
.api
.get_inclusion_list::<E>()
.await?;
let raw_transactions = self.engine().api.get_inclusion_list::<E>().await?;
let mut transactions = vec![];

View File

@@ -16,9 +16,9 @@ use types::{
SignedBeaconBlockCapella, SignedBeaconBlockDeneb, SignedBeaconBlockElectra,
SignedBeaconBlockFulu, SignedBeaconBlockGloas, SignedBeaconBlockHeze,
SignedBlsToExecutionChange, SignedContributionAndProof, SignedExecutionPayloadBid,
SignedExecutionPayloadBidGloas, SignedExecutionPayloadBidHeze,
SignedExecutionPayloadEnvelope, SignedInclusionList, SignedProposerPreferences,
SignedVoluntaryExit, SingleAttestation, SubnetId, SyncCommitteeMessage, SyncSubnetId,
SignedExecutionPayloadBidGloas, SignedExecutionPayloadBidHeze, SignedExecutionPayloadEnvelope,
SignedInclusionList, SignedProposerPreferences, SignedVoluntaryExit, SingleAttestation,
SubnetId, SyncCommitteeMessage, SyncSubnetId,
};
#[derive(Debug, Clone, PartialEq)]
@@ -616,7 +616,8 @@ impl<E: EthSpec> std::fmt::Display for PubsubMessage<E> {
write!(
f,
"Execution payload bid: slot: {:?} value: {:?}",
data.message().slot(), data.message().value()
data.message().slot(),
data.message().value()
)
}
PubsubMessage::ProposerPreferences(data) => {

View File

@@ -1179,8 +1179,7 @@ pub struct SseExtendedPayloadAttributesGeneric<T> {
pub type SseExtendedPayloadAttributes = SseExtendedPayloadAttributesGeneric<SsePayloadAttributes>;
pub type VersionedSsePayloadAttributes = ForkVersionedResponse<SseExtendedPayloadAttributes>;
pub type VersionedSseExecutionPayloadBid<E> =
ForkVersionedResponse<SignedExecutionPayloadBid<E>>;
pub type VersionedSseExecutionPayloadBid<E> = ForkVersionedResponse<SignedExecutionPayloadBid<E>>;
pub type VersionedSsePayloadAttestationMessage = ForkVersionedResponse<PayloadAttestationMessage>;
impl<'de> ContextDeserialize<'de, ForkName> for SsePayloadAttributes {

View File

@@ -1025,9 +1025,7 @@ impl<E: EthSpec> BeaconState<E> {
.map(|i| indices[i % indices.len()] as u64)
.collect();
Ok(InclusionListCommittee::<E>::from(
il_committee.try_into()?,
))
Ok(InclusionListCommittee::<E>::from(il_committee.try_into()?))
}
/// Returns the block root which decided the proposer shuffling for the epoch passed in parameter. This root

View File

@@ -5,7 +5,10 @@ use ssz_types::BitVector;
use std::collections::{HashMap, HashSet};
use tracing::info;
/// Map from slot to inclusion lists
/// Map from slot to inclusion lists.
// TODO(focil): Spec keys InclusionListStore by (slot, committee_root), not just slot.
// A reorg that changes committee membership for the same slot would conflate ILs.
// See: https://github.com/ethereum/consensus-specs/blob/master/specs/heze/inclusion-list.md#inclusionliststore
#[derive(Debug, Default, Clone, PartialEq)]
pub struct InclusionListCache<E: EthSpec> {
inner_map: HashMap<Slot, Inner<E>>,
@@ -18,6 +21,9 @@ struct Inner<E: EthSpec> {
pub inclusion_lists: HashSet<SignedInclusionList<E>>,
pub inclusion_lists_seen: HashSet<ValidatorIndex>,
pub inclusion_list_equivocators: HashSet<ValidatorIndex>,
// TODO(focil): Spec tracks timeliness per IL root, not per validator index.
// Functionally equivalent for non-equivocating validators.
// See: https://github.com/ethereum/consensus-specs/blob/master/specs/heze/inclusion-list.md#inclusionliststore
pub inclusion_list_timeliness: HashMap<ValidatorIndex, bool>,
pub inclusion_list_transactions: HashSet<Transaction<E::MaxBytesPerTransaction>>,
pub timely_transactions: HashSet<Transaction<E::MaxBytesPerTransaction>>,