From 028b5a42a9715c31f416d45db70add39d9934b12 Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Mon, 27 Apr 2026 17:13:35 +0200 Subject: [PATCH 01/12] Add payload attestation validator duty (#9178) Co-Authored-By: Eitan Seri-Levi Co-Authored-By: Jimmy Chen --- beacon_node/http_api/src/beacon/pool.rs | 149 ++++++++++- beacon_node/http_api/src/lib.rs | 21 +- beacon_node/http_api/tests/tests.rs | 96 +++++++ common/eth2/src/lib.rs | 44 +++- .../lighthouse_validator_store/src/lib.rs | 42 +++- validator_client/signing_method/src/lib.rs | 5 + .../signing_method/src/web3signer.rs | 3 + validator_client/src/lib.rs | 19 ++ .../validator_services/src/lib.rs | 1 + .../src/payload_attestation_service.rs | 238 ++++++++++++++++++ validator_client/validator_store/src/lib.rs | 16 +- 11 files changed, 618 insertions(+), 16 deletions(-) create mode 100644 validator_client/validator_services/src/payload_attestation_service.rs diff --git a/beacon_node/http_api/src/beacon/pool.rs b/beacon_node/http_api/src/beacon/pool.rs index 059573c317..c6b8a69643 100644 --- a/beacon_node/http_api/src/beacon/pool.rs +++ b/beacon_node/http_api/src/beacon/pool.rs @@ -1,24 +1,31 @@ use crate::task_spawner::{Priority, TaskSpawner}; -use crate::utils::{NetworkTxFilter, OptionalConsensusVersionHeaderFilter, ResponseFilter}; +use crate::utils::{ + ChainFilter, EthV1Filter, NetworkTxFilter, OptionalConsensusVersionHeaderFilter, + ResponseFilter, TaskSpawnerFilter, +}; use crate::version::{ ResponseIncludesVersion, V1, V2, add_consensus_version_header, beacon_response, unsupported_version_rejection, }; use crate::{sync_committees, utils}; use beacon_chain::observed_operations::ObservationOutcome; +use beacon_chain::payload_attestation_verification::Error as PayloadAttestationError; use beacon_chain::{BeaconChain, BeaconChainTypes}; +use bytes::Bytes; use eth2::types::{AttestationPoolQuery, EndpointVersion, Failure, GenericResponse}; use lighthouse_network::PubsubMessage; use network::NetworkMessage; use operation_pool::ReceivedPreCapella; use slot_clock::SlotClock; +use ssz::{Decode, Encode}; use std::collections::HashSet; use std::sync::Arc; use tokio::sync::mpsc::UnboundedSender; -use tracing::{debug, info, warn}; +use tracing::{debug, error, info, warn}; use types::{ - Attestation, AttestationData, AttesterSlashing, ForkName, ProposerSlashing, - SignedBlsToExecutionChange, SignedVoluntaryExit, SingleAttestation, SyncCommitteeMessage, + Attestation, AttestationData, AttesterSlashing, ForkName, PayloadAttestationMessage, + ProposerSlashing, SignedBlsToExecutionChange, SignedVoluntaryExit, SingleAttestation, + SyncCommitteeMessage, }; use warp::filters::BoxedFilter; use warp::{Filter, Reply}; @@ -520,3 +527,137 @@ pub fn post_beacon_pool_attestations_v2( ) .boxed() } + +/// POST beacon/pool/payload_attestations (JSON) +pub fn post_beacon_pool_payload_attestations( + network_tx_filter: &NetworkTxFilter, + optional_consensus_version_header_filter: OptionalConsensusVersionHeaderFilter, + beacon_pool_path: &BeaconPoolPathFilter, +) -> ResponseFilter { + beacon_pool_path + .clone() + .and(warp::path("payload_attestations")) + .and(warp::path::end()) + .and(warp_utils::json::json()) + .and(optional_consensus_version_header_filter) + .and(network_tx_filter.clone()) + .then( + |task_spawner: TaskSpawner, + chain: Arc>, + messages: Vec, + _fork_name: Option, + network_tx: UnboundedSender>| { + task_spawner.blocking_json_task(Priority::P0, move || { + publish_payload_attestation_messages(&chain, &network_tx, messages) + }) + }, + ) + .boxed() +} + +/// POST beacon/pool/payload_attestations (SSZ) +pub fn post_beacon_pool_payload_attestations_ssz( + eth_v1: EthV1Filter, + task_spawner_filter: TaskSpawnerFilter, + chain_filter: ChainFilter, + network_tx_filter: NetworkTxFilter, +) -> ResponseFilter { + eth_v1 + .and(warp::path("beacon")) + .and(warp::path("pool")) + .and(warp::path("payload_attestations")) + .and(warp::path::end()) + .and(warp::body::bytes()) + .and(task_spawner_filter) + .and(chain_filter) + .and(network_tx_filter) + .then( + |body_bytes: Bytes, + task_spawner: TaskSpawner, + chain: Arc>, + network_tx: UnboundedSender>| { + task_spawner.blocking_json_task(Priority::P0, move || { + let item_len = ::ssz_fixed_len(); + if !body_bytes.len().is_multiple_of(item_len) { + return Err(warp_utils::reject::custom_bad_request(format!( + "SSZ body length {} is not a multiple of PayloadAttestationMessage size {}", + body_bytes.len(), + item_len, + ))); + } + let messages: Vec = body_bytes + .chunks(item_len) + .map(|chunk| { + PayloadAttestationMessage::from_ssz_bytes(chunk).map_err(|e| { + warp_utils::reject::custom_bad_request(format!( + "invalid SSZ: {e:?}" + )) + }) + }) + .collect::>()?; + + publish_payload_attestation_messages(&chain, &network_tx, messages) + }) + }, + ) + .boxed() +} + +fn publish_payload_attestation_messages( + chain: &BeaconChain, + network_tx: &UnboundedSender>, + messages: Vec, +) -> Result<(), warp::Rejection> { + let mut failures = vec![]; + let mut num_already_known = 0; + + for (index, message) in messages.into_iter().enumerate() { + match chain.verify_payload_attestation_message_for_gossip(message.clone()) { + Ok(verified) => { + utils::publish_pubsub_message( + network_tx, + PubsubMessage::PayloadAttestation(Box::new(message)), + )?; + + if let Err(e) = chain.apply_payload_attestation_to_fork_choice( + verified.indexed_payload_attestation(), + verified.ptc(), + ) { + warn!( + error = ?e, + request_index = index, + "Payload attestation invalid for fork choice" + ); + } + } + Err(PayloadAttestationError::PriorPayloadAttestationMessageKnown { .. }) => { + num_already_known += 1; + } + // TODO(gloas): requeue for reprocessing like attestations do. + Err(e) => { + error!( + error = ?e, + request_index = index, + "Failure verifying payload attestation for gossip" + ); + failures.push(Failure::new(index, format!("{e:?}"))); + } + } + } + + if num_already_known > 0 { + debug!( + count = num_already_known, + "Some payload attestations already known" + ); + } + + if failures.is_empty() { + Ok(()) + } else { + Err(warp_utils::reject::indexed_bad_request( + "error processing payload attestations".to_string(), + failures, + )) + } +} diff --git a/beacon_node/http_api/src/lib.rs b/beacon_node/http_api/src/lib.rs index bd80dd1e82..b2d069f384 100644 --- a/beacon_node/http_api/src/lib.rs +++ b/beacon_node/http_api/src/lib.rs @@ -1454,7 +1454,7 @@ pub fn serve( let post_beacon_pool_attestations_v2 = post_beacon_pool_attestations_v2( &network_tx_filter, - optional_consensus_version_header_filter, + optional_consensus_version_header_filter.clone(), &beacon_pool_path_v2, ); @@ -1487,6 +1487,21 @@ pub fn serve( let post_beacon_pool_sync_committees = post_beacon_pool_sync_committees(&network_tx_filter, &beacon_pool_path); + // POST beacon/pool/payload_attestations + let post_beacon_pool_payload_attestations = post_beacon_pool_payload_attestations( + &network_tx_filter, + optional_consensus_version_header_filter, + &beacon_pool_path, + ); + + // POST beacon/pool/payload_attestations (SSZ) + let post_beacon_pool_payload_attestations_ssz = post_beacon_pool_payload_attestations_ssz( + eth_v1.clone(), + task_spawner_filter.clone(), + chain_filter.clone(), + network_tx_filter.clone(), + ); + // GET beacon/pool/bls_to_execution_changes let get_beacon_pool_bls_to_execution_changes = get_beacon_pool_bls_to_execution_changes(&beacon_pool_path); @@ -3400,7 +3415,8 @@ pub fn serve( .uor(post_beacon_blocks_v2_ssz) .uor(post_beacon_blinded_blocks_ssz) .uor(post_beacon_blinded_blocks_v2_ssz) - .uor(post_beacon_execution_payload_envelope_ssz), + .uor(post_beacon_execution_payload_envelope_ssz) + .uor(post_beacon_pool_payload_attestations_ssz), ) .uor(post_beacon_blocks) .uor(post_beacon_blinded_blocks) @@ -3411,6 +3427,7 @@ pub fn serve( .uor(post_beacon_pool_proposer_slashings) .uor(post_beacon_pool_voluntary_exits) .uor(post_beacon_pool_sync_committees) + .uor(post_beacon_pool_payload_attestations) .uor(post_beacon_pool_bls_to_execution_changes) .uor(post_beacon_execution_payload_envelope) .uor(post_beacon_state_validators) diff --git a/beacon_node/http_api/tests/tests.rs b/beacon_node/http_api/tests/tests.rs index aac3384fbd..b8326f4495 100644 --- a/beacon_node/http_api/tests/tests.rs +++ b/beacon_node/http_api/tests/tests.rs @@ -2793,6 +2793,89 @@ impl ApiTester { self } + fn make_valid_payload_attestation_message( + &self, + ptc_offset: usize, + ) -> PayloadAttestationMessage { + let head = self.chain.head_snapshot(); + let head_slot = head.beacon_block.slot(); + let head_root = head.beacon_block_root; + let fork = head.beacon_state.fork(); + let genesis_validators_root = self.chain.genesis_validators_root; + + let ptc = head + .beacon_state + .get_ptc(head_slot, &self.chain.spec) + .expect("should get PTC"); + + // Find distinct validator indices in the PTC (may contain duplicates due to + // weighted sampling with a small validator set). + let mut seen = std::collections::HashSet::new(); + let distinct_indices: Vec = ptc + .0 + .iter() + .copied() + .filter(|idx| seen.insert(*idx)) + .collect(); + let validator_index = distinct_indices[ptc_offset % distinct_indices.len()]; + + let data = PayloadAttestationData { + beacon_block_root: head_root, + slot: head_slot, + payload_present: true, + blob_data_available: true, + }; + + let epoch = head_slot.epoch(E::slots_per_epoch()); + let domain = + self.chain + .spec + .get_domain(epoch, Domain::PTCAttester, &fork, genesis_validators_root); + let signing_root = data.signing_root(domain); + let sk = &self.validator_keypairs()[validator_index].sk; + let signature = sk.sign(signing_root); + + PayloadAttestationMessage { + validator_index: validator_index as u64, + data, + signature, + } + } + + pub async fn test_post_beacon_pool_payload_attestations_valid(mut self) -> Self { + let message = self.make_valid_payload_attestation_message(0); + let fork_name = self.chain.spec.fork_name_at_slot::(message.data.slot); + + self.client + .post_beacon_pool_payload_attestations(&[message], fork_name) + .await + .unwrap(); + + assert!( + self.network_rx.network_recv.recv().await.is_some(), + "valid payload attestation should be sent to network" + ); + + self + } + + pub async fn test_post_beacon_pool_payload_attestations_valid_ssz(mut self) -> Self { + let message = self.make_valid_payload_attestation_message(1); + let fork_name = self.chain.spec.fork_name_at_slot::(message.data.slot); + + self.client + .post_beacon_pool_payload_attestations_ssz(&[message], fork_name) + .await + .unwrap(); + + assert!( + self.network_rx.network_recv.recv().await.is_some(), + "valid payload attestation (SSZ) should be sent to network" + ); + + self + } + pub async fn test_get_config_fork_schedule(self) -> Self { let result = self.client.get_config_fork_schedule().await.unwrap().data; @@ -8246,6 +8329,19 @@ async fn get_validator_payload_attestation_data_pre_gloas() { .await; } +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn post_beacon_pool_payload_attestations_valid() { + if !fork_name_from_env().is_some_and(|f| f.gloas_enabled()) { + return; + } + ApiTester::new() + .await + .test_post_beacon_pool_payload_attestations_valid() + .await + .test_post_beacon_pool_payload_attestations_valid_ssz() + .await; +} + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn get_validator_aggregate_attestation_v1() { ApiTester::new() diff --git a/common/eth2/src/lib.rs b/common/eth2/src/lib.rs index 4ec75468a2..e866547b9f 100644 --- a/common/eth2/src/lib.rs +++ b/common/eth2/src/lib.rs @@ -46,7 +46,7 @@ use ssz::{Decode, Encode}; use std::fmt; use std::future::Future; use std::time::Duration; -use types::PayloadAttestationData; +use types::{PayloadAttestationData, PayloadAttestationMessage}; pub const V1: EndpointVersion = EndpointVersion(1); pub const V2: EndpointVersion = EndpointVersion(2); @@ -1789,6 +1789,48 @@ impl BeaconNodeHttpClient { Ok(()) } + /// `POST beacon/pool/payload_attestations` (JSON) + pub async fn post_beacon_pool_payload_attestations( + &self, + messages: &[PayloadAttestationMessage], + fork_name: ForkName, + ) -> Result<(), Error> { + let mut path = self.eth_path(V1)?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("beacon") + .push("pool") + .push("payload_attestations"); + + self.post_generic_with_consensus_version(path, &messages, None, fork_name) + .await?; + + Ok(()) + } + + /// `POST beacon/pool/payload_attestations` (SSZ) + pub async fn post_beacon_pool_payload_attestations_ssz( + &self, + messages: &[PayloadAttestationMessage], + fork_name: ForkName, + ) -> Result<(), Error> { + let mut path = self.eth_path(V1)?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("beacon") + .push("pool") + .push("payload_attestations"); + + let ssz_body: Vec = messages.iter().flat_map(|m| m.as_ssz_bytes()).collect(); + + self.post_generic_with_consensus_version_and_ssz_body(path, ssz_body, None, fork_name) + .await?; + + Ok(()) + } + /// `POST beacon/pool/bls_to_execution_changes` pub async fn post_beacon_pool_bls_to_execution_changes( &self, diff --git a/validator_client/lighthouse_validator_store/src/lib.rs b/validator_client/lighthouse_validator_store/src/lib.rs index c5bcd88eb1..1b32777678 100644 --- a/validator_client/lighthouse_validator_store/src/lib.rs +++ b/validator_client/lighthouse_validator_store/src/lib.rs @@ -21,11 +21,12 @@ use tracing::{Instrument, debug, error, info, info_span, instrument, warn}; use types::{ AbstractExecPayload, Address, AggregateAndProof, Attestation, BeaconBlock, BlindedPayload, ChainSpec, ContributionAndProof, Domain, Epoch, EthSpec, ExecutionPayloadEnvelope, Fork, - FullPayload, Graffiti, Hash256, SelectionProof, SignedAggregateAndProof, SignedBeaconBlock, - SignedContributionAndProof, SignedExecutionPayloadEnvelope, SignedRoot, - SignedValidatorRegistrationData, SignedVoluntaryExit, Slot, SyncAggregatorSelectionData, - SyncCommitteeContribution, SyncCommitteeMessage, SyncSelectionProof, SyncSubnetId, - ValidatorRegistrationData, VoluntaryExit, graffiti::GraffitiString, + FullPayload, Graffiti, Hash256, PayloadAttestationData, PayloadAttestationMessage, + SelectionProof, SignedAggregateAndProof, SignedBeaconBlock, SignedContributionAndProof, + SignedExecutionPayloadEnvelope, SignedRoot, SignedValidatorRegistrationData, + SignedVoluntaryExit, Slot, SyncAggregatorSelectionData, SyncCommitteeContribution, + SyncCommitteeMessage, SyncSelectionProof, SyncSubnetId, ValidatorRegistrationData, + VoluntaryExit, graffiti::GraffitiString, }; use validator_store::{ AggregateToSign, AttestationToSign, ContributionToSign, DoppelgangerStatus, @@ -1423,6 +1424,37 @@ impl ValidatorStore for LighthouseValidatorS }) } + async fn sign_payload_attestation( + &self, + validator_pubkey: PublicKeyBytes, + data: PayloadAttestationData, + ) -> Result { + let signing_context = + self.signing_context(Domain::PTCAttester, data.slot.epoch(E::slots_per_epoch())); + + let validator_index = self + .validator_index(&validator_pubkey) + .ok_or(ValidatorStoreError::UnknownPubkey(validator_pubkey))?; + + let signing_method = self.doppelganger_bypassed_signing_method(validator_pubkey)?; + + let signature = signing_method + .get_signature::>( + SignableMessage::PayloadAttestationData(&data), + signing_context, + &self.spec, + &self.task_executor, + ) + .await + .map_err(Error::SpecificError)?; + + Ok(PayloadAttestationMessage { + validator_index, + data, + signature, + }) + } + /// Sign an `ExecutionPayloadEnvelope` for Gloas (local building). /// The proposer acts as the builder and signs with the BeaconBuilder domain. async fn sign_execution_payload_envelope( diff --git a/validator_client/signing_method/src/lib.rs b/validator_client/signing_method/src/lib.rs index c132d86c17..2f80fa5761 100644 --- a/validator_client/signing_method/src/lib.rs +++ b/validator_client/signing_method/src/lib.rs @@ -50,6 +50,7 @@ pub enum SignableMessage<'a, E: EthSpec, Payload: AbstractExecPayload = FullP ValidatorRegistration(&'a ValidatorRegistrationData), VoluntaryExit(&'a VoluntaryExit), ExecutionPayloadEnvelope(&'a ExecutionPayloadEnvelope), + PayloadAttestationData(&'a PayloadAttestationData), } impl> SignableMessage<'_, E, Payload> { @@ -72,6 +73,7 @@ impl> SignableMessage<'_, E, Payload SignableMessage::ValidatorRegistration(v) => v.signing_root(domain), SignableMessage::VoluntaryExit(exit) => exit.signing_root(domain), SignableMessage::ExecutionPayloadEnvelope(e) => e.signing_root(domain), + SignableMessage::PayloadAttestationData(d) => d.signing_root(domain), } } } @@ -238,6 +240,9 @@ impl SigningMethod { SignableMessage::ExecutionPayloadEnvelope(e) => { Web3SignerObject::ExecutionPayloadEnvelope(e) } + SignableMessage::PayloadAttestationData(d) => { + Web3SignerObject::PayloadAttestationData(d) + } }; // Determine the Web3Signer message type. diff --git a/validator_client/signing_method/src/web3signer.rs b/validator_client/signing_method/src/web3signer.rs index e6fc8f3ba2..c2b7e06f92 100644 --- a/validator_client/signing_method/src/web3signer.rs +++ b/validator_client/signing_method/src/web3signer.rs @@ -21,6 +21,7 @@ pub enum MessageType { ValidatorRegistration, // TODO(gloas) verify w/ web3signer specs ExecutionPayloadEnvelope, + PayloadAttestation, } #[derive(Debug, PartialEq, Copy, Clone, Serialize)] @@ -78,6 +79,7 @@ pub enum Web3SignerObject<'a, E: EthSpec, Payload: AbstractExecPayload> { ContributionAndProof(&'a ContributionAndProof), ValidatorRegistration(&'a ValidatorRegistrationData), ExecutionPayloadEnvelope(&'a ExecutionPayloadEnvelope), + PayloadAttestationData(&'a PayloadAttestationData), } impl<'a, E: EthSpec, Payload: AbstractExecPayload> Web3SignerObject<'a, E, Payload> { @@ -144,6 +146,7 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload> Web3SignerObject<'a, E, Pa } Web3SignerObject::ValidatorRegistration(_) => MessageType::ValidatorRegistration, Web3SignerObject::ExecutionPayloadEnvelope(_) => MessageType::ExecutionPayloadEnvelope, + Web3SignerObject::PayloadAttestationData(_) => MessageType::PayloadAttestation, } } } diff --git a/validator_client/src/lib.rs b/validator_client/src/lib.rs index e26d5c3d30..b412db45f6 100644 --- a/validator_client/src/lib.rs +++ b/validator_client/src/lib.rs @@ -45,6 +45,7 @@ use validator_services::{ block_service::{BlockService, BlockServiceBuilder}, duties_service::{self, DutiesService, DutiesServiceBuilder}, latency_service, + payload_attestation_service::PayloadAttestationService, preparation_service::{PreparationService, PreparationServiceBuilder}, sync_committee_service::SyncCommitteeService, }; @@ -83,6 +84,7 @@ pub struct ProductionValidatorClient { block_service: BlockService, SystemTimeSlotClock>, attestation_service: AttestationService, SystemTimeSlotClock>, sync_committee_service: SyncCommitteeService, SystemTimeSlotClock>, + payload_attestation_service: PayloadAttestationService, SystemTimeSlotClock>, doppelganger_service: Option>, preparation_service: PreparationService, SystemTimeSlotClock>, validator_store: Arc>, @@ -552,12 +554,22 @@ impl ProductionValidatorClient { context.executor.clone(), ); + let payload_attestation_service = PayloadAttestationService::new( + duties_service.clone(), + validator_store.clone(), + slot_clock.clone(), + beacon_nodes.clone(), + context.executor.clone(), + context.eth2_config.spec.clone(), + ); + Ok(Self { context, duties_service, block_service, attestation_service, sync_committee_service, + payload_attestation_service, doppelganger_service, preparation_service, validator_store, @@ -629,6 +641,13 @@ impl ProductionValidatorClient { .start_update_service(&self.context.eth2_config.spec) .map_err(|e| format!("Unable to start sync committee service: {}", e))?; + if self.context.eth2_config.spec.is_gloas_scheduled() { + self.payload_attestation_service + .clone() + .start_update_service() + .map_err(|e| format!("Unable to start payload attestation service: {}", e))?; + } + self.preparation_service .clone() .start_update_service(&self.context.eth2_config.spec) diff --git a/validator_client/validator_services/src/lib.rs b/validator_client/validator_services/src/lib.rs index 3b8bd9ae14..0169335a7f 100644 --- a/validator_client/validator_services/src/lib.rs +++ b/validator_client/validator_services/src/lib.rs @@ -3,6 +3,7 @@ pub mod block_service; pub mod duties_service; pub mod latency_service; pub mod notifier_service; +pub mod payload_attestation_service; pub mod preparation_service; pub mod sync; pub mod sync_committee_service; diff --git a/validator_client/validator_services/src/payload_attestation_service.rs b/validator_client/validator_services/src/payload_attestation_service.rs new file mode 100644 index 0000000000..2f3ca8bed2 --- /dev/null +++ b/validator_client/validator_services/src/payload_attestation_service.rs @@ -0,0 +1,238 @@ +use crate::duties_service::DutiesService; +use beacon_node_fallback::BeaconNodeFallback; +use logging::crit; +use slot_clock::SlotClock; +use std::ops::Deref; +use std::sync::Arc; +use task_executor::TaskExecutor; +use tokio::time::sleep; +use tracing::{debug, error, info}; +use types::{ChainSpec, EthSpec}; +use validator_store::ValidatorStore; + +pub struct Inner { + duties_service: Arc>, + validator_store: Arc, + slot_clock: T, + beacon_nodes: Arc>, + executor: TaskExecutor, + chain_spec: Arc, +} + +pub struct PayloadAttestationService { + inner: Arc>, +} + +impl Clone for PayloadAttestationService { + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + } + } +} + +impl Deref for PayloadAttestationService { + type Target = Inner; + + fn deref(&self) -> &Self::Target { + self.inner.deref() + } +} + +impl PayloadAttestationService { + pub fn new( + duties_service: Arc>, + validator_store: Arc, + slot_clock: T, + beacon_nodes: Arc>, + executor: TaskExecutor, + chain_spec: Arc, + ) -> Self { + Self { + inner: Arc::new(Inner { + duties_service, + validator_store, + slot_clock, + beacon_nodes, + executor, + chain_spec, + }), + } + } + + pub fn start_update_service(self) -> Result<(), String> { + let slot_duration = self.chain_spec.get_slot_duration(); + let payload_attestation_due = self.chain_spec.get_payload_attestation_due(); + + info!( + payload_attestation_due_ms = payload_attestation_due.as_millis(), + "Payload attestation service started" + ); + + let executor = self.executor.clone(); + + let interval_fut = async move { + loop { + let Some(duration_to_next_slot) = self.slot_clock.duration_to_next_slot() else { + error!("Failed to read slot clock"); + sleep(slot_duration).await; + continue; + }; + + let Some(current_slot) = self.slot_clock.now() else { + error!("Failed to read slot clock after trigger"); + continue; + }; + + if !self + .chain_spec + .fork_name_at_slot::(current_slot) + .gloas_enabled() + { + let duration_to_next_epoch = self + .slot_clock + .duration_to_next_epoch(S::E::slots_per_epoch()) + .unwrap_or_else(|| { + self.chain_spec.get_slot_duration() * S::E::slots_per_epoch() as u32 + }); + sleep(duration_to_next_epoch).await; + continue; + } + + sleep(duration_to_next_slot + payload_attestation_due).await; + + let service = self.clone(); + self.executor.spawn( + async move { + service.produce_and_publish(current_slot).await; + }, + "payload_attestation_producer", + ); + } + }; + + executor.spawn(interval_fut, "payload_attestation_service"); + Ok(()) + } + + async fn produce_and_publish(&self, slot: types::Slot) { + let duties = self.duties_service.get_ptc_duties_for_slot(slot); + + if duties.is_empty() { + return; + } + + debug!( + %slot, + duty_count = duties.len(), + "Producing payload attestations" + ); + + let attestation_data = match self + .beacon_nodes + .first_success(|beacon_node| async move { + beacon_node + .get_validator_payload_attestation_data(slot) + .await + .map_err(|e| format!("Failed to get payload attestation data: {e:?}")) + .map(|resp| resp.into_data()) + }) + .await + { + Ok(data) => data, + Err(e) => { + crit!( + error = %e, + %slot, + "Failed to produce payload attestation data" + ); + return; + } + }; + + debug!( + %slot, + beacon_block_root = ?attestation_data.beacon_block_root, + payload_present = attestation_data.payload_present, + "Received payload attestation data" + ); + + let mut messages = Vec::with_capacity(duties.len()); + + for duty in &duties { + match self + .validator_store + .sign_payload_attestation(duty.pubkey, attestation_data.clone()) + .await + { + Ok(message) => { + messages.push(message); + } + Err(e) => { + crit!( + error = ?e, + validator = ?duty.pubkey, + %slot, + "Failed to sign payload attestation" + ); + } + } + } + + if messages.is_empty() { + return; + } + + let count = messages.len(); + let fork_name = self.chain_spec.fork_name_at_slot::(slot); + let result = self + .beacon_nodes + .first_success(|beacon_node| { + let messages = messages.clone(); + async move { + beacon_node + .post_beacon_pool_payload_attestations_ssz(&messages, fork_name) + .await + .map_err(|e| format!("Failed to publish payload attestations (SSZ): {e:?}")) + } + }) + .await; + + let result = match result { + Ok(()) => Ok(()), + Err(_) => { + debug!(%slot, "SSZ publish failed, falling back to JSON"); + self.beacon_nodes + .first_success(|beacon_node| { + let messages = messages.clone(); + async move { + beacon_node + .post_beacon_pool_payload_attestations(&messages, fork_name) + .await + .map_err(|e| { + format!("Failed to publish payload attestations (JSON): {e:?}") + }) + } + }) + .await + } + }; + + match result { + Ok(()) => { + info!( + %slot, + %count, + "Successfully published payload attestations" + ); + } + Err(e) => { + crit!( + error = %e, + %slot, + "Failed to publish payload attestations" + ); + } + } + } +} diff --git a/validator_client/validator_store/src/lib.rs b/validator_client/validator_store/src/lib.rs index da0b33de18..4e5b415a41 100644 --- a/validator_client/validator_store/src/lib.rs +++ b/validator_client/validator_store/src/lib.rs @@ -7,10 +7,11 @@ use std::future::Future; use std::sync::Arc; use types::{ Address, Attestation, AttestationError, BlindedBeaconBlock, Epoch, EthSpec, - ExecutionPayloadEnvelope, Graffiti, Hash256, SelectionProof, SignedAggregateAndProof, - SignedBlindedBeaconBlock, SignedContributionAndProof, SignedExecutionPayloadEnvelope, - SignedValidatorRegistrationData, Slot, SyncCommitteeContribution, SyncCommitteeMessage, - SyncSelectionProof, SyncSubnetId, ValidatorRegistrationData, + ExecutionPayloadEnvelope, Graffiti, Hash256, PayloadAttestationData, PayloadAttestationMessage, + SelectionProof, SignedAggregateAndProof, SignedBlindedBeaconBlock, SignedContributionAndProof, + SignedExecutionPayloadEnvelope, SignedValidatorRegistrationData, Slot, + SyncCommitteeContribution, SyncCommitteeMessage, SyncSelectionProof, SyncSubnetId, + ValidatorRegistrationData, }; #[derive(Debug, PartialEq, Clone)] @@ -205,6 +206,13 @@ pub trait ValidatorStore: Send + Sync { envelope: ExecutionPayloadEnvelope, ) -> impl Future, Error>> + Send; + /// Sign a `PayloadAttestationData` for the PTC. + fn sign_payload_attestation( + &self, + validator_pubkey: PublicKeyBytes, + data: PayloadAttestationData, + ) -> impl Future>> + Send; + /// Returns `ProposalData` for the provided `pubkey` if it exists in `InitializedValidators`. /// `ProposalData` fields include defaulting logic described in `get_fee_recipient_defaulting`, /// `get_gas_limit_defaulting`, and `get_builder_proposals_defaulting`. From 949c027dfd37408784216b2c4e5e727e6ad571fe Mon Sep 17 00:00:00 2001 From: Mac L Date: Tue, 28 Apr 2026 11:01:13 +0400 Subject: [PATCH 02/12] Add method to `Hash256` to display shortened hashes (#9118) #6689 Inspired by the initial implementation of #9108, credit to @chong-he. This adds an extension trait to `Hash256` and add a `short` method to provide smaller formatted hashes for logging. Co-Authored-By: Mac L --- beacon_node/client/src/notifier.rs | 6 ++--- .../types/src/core/execution_block_hash.rs | 13 ++++------ consensus/types/src/core/mod.rs | 26 +++++++++++++++++++ 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/beacon_node/client/src/notifier.rs b/beacon_node/client/src/notifier.rs index 0d73a6bf7a..bdb4228765 100644 --- a/beacon_node/client/src/notifier.rs +++ b/beacon_node/client/src/notifier.rs @@ -360,7 +360,7 @@ pub fn spawn_notifier( let block_info = if current_slot > head_slot { " … empty".to_string() } else { - head_root.to_string() + head_root.short().to_string() }; let block_hash = match beacon_chain.canonical_head.head_execution_status() { @@ -393,7 +393,7 @@ pub fn spawn_notifier( info!( peers = peer_count_pretty(connected_peer_count), exec_hash = block_hash, - finalized_root = %finalized_checkpoint.root, + finalized_root = %finalized_checkpoint.root.short(), finalized_epoch = %finalized_checkpoint.epoch, epoch = %current_epoch, block = block_info, @@ -404,7 +404,7 @@ pub fn spawn_notifier( metrics::set_gauge(&metrics::IS_SYNCED, 0); info!( peers = peer_count_pretty(connected_peer_count), - finalized_root = %finalized_checkpoint.root, + finalized_root = %finalized_checkpoint.root.short(), finalized_epoch = %finalized_checkpoint.epoch, %head_slot, %current_slot, diff --git a/consensus/types/src/core/execution_block_hash.rs b/consensus/types/src/core/execution_block_hash.rs index cbacf7cf74..71e63727ee 100644 --- a/consensus/types/src/core/execution_block_hash.rs +++ b/consensus/types/src/core/execution_block_hash.rs @@ -5,7 +5,10 @@ use rand::RngCore; use serde::{Deserialize, Serialize}; use ssz::{Decode, DecodeError, Encode}; -use crate::{core::Hash256, test_utils::TestRandom}; +use crate::{ + core::{Hash256, Hash256Ext}, + test_utils::TestRandom, +}; #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[derive(Default, Clone, Copy, Serialize, Deserialize, Eq, PartialEq, Hash)] @@ -20,13 +23,7 @@ impl fmt::Debug for ExecutionBlockHash { impl fmt::Display for ExecutionBlockHash { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let hash = format!("{}", self.0); - write!( - f, - "{}…{}", - &hash[..6], - &hash[hash.len().saturating_sub(4)..] - ) + self.0.short().fmt(f) } } diff --git a/consensus/types/src/core/mod.rs b/consensus/types/src/core/mod.rs index 4e583fbc67..f722ac5191 100644 --- a/consensus/types/src/core/mod.rs +++ b/consensus/types/src/core/mod.rs @@ -49,3 +49,29 @@ pub type Hash64 = alloy_primitives::B64; pub type Address = alloy_primitives::Address; pub type VersionedHash = Hash256; pub type MerkleProof = Vec; + +/// Extension trait for `Hash256` to allow us to implement additional methods on it. +pub trait Hash256Ext { + fn short(&self) -> ShortenedHash<'_>; +} + +impl Hash256Ext for Hash256 { + fn short(&self) -> ShortenedHash<'_> { + ShortenedHash(self) + } +} + +pub struct ShortenedHash<'a>(&'a Hash256); + +impl<'a> std::fmt::Display for ShortenedHash<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let hash: &[u8; 32] = self.0.as_ref(); + write!( + f, + // Format as hex, padded to 2 digits per byte. + // This outputs a consistent "0x1234...abcd" format. + "0x{:02x}{:02x}…{:02x}{:02x}", + hash[0], hash[1], hash[30], hash[31] + ) + } +} From 919c996c18911a541493bb2c30571aa54a69aeae Mon Sep 17 00:00:00 2001 From: Jimmy Chen Date: Tue, 28 Apr 2026 10:15:10 +0200 Subject: [PATCH 03/12] Fix spurious re-org logs on ePBS payload status changes (#9191) Co-Authored-By: Jimmy Chen --- beacon_node/beacon_chain/src/canonical_head.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/beacon_node/beacon_chain/src/canonical_head.rs b/beacon_node/beacon_chain/src/canonical_head.rs index 04c18c88e0..0e6515ebbd 100644 --- a/beacon_node/beacon_chain/src/canonical_head.rs +++ b/beacon_node/beacon_chain/src/canonical_head.rs @@ -796,9 +796,9 @@ impl BeaconChain { let new_snapshot = &new_cached_head.snapshot; let old_snapshot = &old_cached_head.snapshot; - // If the head changed, perform some updates. - if (new_snapshot.beacon_block_root != old_snapshot.beacon_block_root - || new_payload_status != old_payload_status) + // Only run on head *block* changes - payload status changes only need the + // `cached_head` update above, not re-org detection or event emission. + if new_snapshot.beacon_block_root != old_snapshot.beacon_block_root && let Err(e) = self.after_new_head(&old_cached_head, &new_cached_head, new_head_proto_block) { From 280e2f1d53fde00955f9868a328f4183289420cb Mon Sep 17 00:00:00 2001 From: Jimmy Chen Date: Tue, 28 Apr 2026 10:59:01 +0200 Subject: [PATCH 04/12] Wire up ePBS SSE events and fix envelope availability (#9199) Co-Authored-By: Jimmy Chen --- .../gossip_verified_payload_attestation.rs | 22 ++- .../gossip_verified_bid.rs | 14 ++ .../payload_envelope_verification/import.rs | 16 +- .../src/payload_envelope_verification/mod.rs | 32 +++- beacon_node/beacon_chain/tests/events.rs | 178 +++++++++++++++++- 5 files changed, 251 insertions(+), 11 deletions(-) diff --git a/beacon_node/beacon_chain/src/payload_attestation_verification/gossip_verified_payload_attestation.rs b/beacon_node/beacon_chain/src/payload_attestation_verification/gossip_verified_payload_attestation.rs index 2d9fce812e..c36c73b344 100644 --- a/beacon_node/beacon_chain/src/payload_attestation_verification/gossip_verified_payload_attestation.rs +++ b/beacon_node/beacon_chain/src/payload_attestation_verification/gossip_verified_payload_attestation.rs @@ -6,6 +6,7 @@ use crate::validator_pubkey_cache::ValidatorPubkeyCache; use crate::{BeaconChain, BeaconChainError, BeaconChainTypes, metrics}; use bls::AggregateSignature; use educe::Educe; +use eth2::types::{EventKind, ForkVersionedResponse}; use parking_lot::RwLock; use safe_arith::SafeArith; use slot_clock::SlotClock; @@ -216,9 +217,24 @@ impl BeaconChain { let _timer = metrics::start_timer(&metrics::PAYLOAD_ATTESTATION_GOSSIP_VERIFICATION_TIMES); let ctx = self.payload_attestation_gossip_context(); - VerifiedPayloadAttestationMessage::new(payload_attestation_message, &ctx).inspect(|_| { - metrics::inc_counter(&metrics::PAYLOAD_ATTESTATION_PROCESSING_SUCCESSES); - }) + VerifiedPayloadAttestationMessage::new(payload_attestation_message, &ctx).inspect( + |verified| { + metrics::inc_counter(&metrics::PAYLOAD_ATTESTATION_PROCESSING_SUCCESSES); + + if let Some(event_handler) = self.event_handler.as_ref() + && event_handler.has_payload_attestation_message_subscribers() + { + let msg = verified.payload_attestation_message(); + event_handler.register(EventKind::PayloadAttestationMessage(Box::new( + ForkVersionedResponse { + version: self.spec.fork_name_at_slot::(msg.data.slot), + metadata: Default::default(), + data: msg.clone(), + }, + ))); + } + }, + ) } } diff --git a/beacon_node/beacon_chain/src/payload_bid_verification/gossip_verified_bid.rs b/beacon_node/beacon_chain/src/payload_bid_verification/gossip_verified_bid.rs index 91945896df..1f3f074598 100644 --- a/beacon_node/beacon_chain/src/payload_bid_verification/gossip_verified_bid.rs +++ b/beacon_node/beacon_chain/src/payload_bid_verification/gossip_verified_bid.rs @@ -6,6 +6,7 @@ use crate::{ proposer_preferences_verification::proposer_preference_cache::GossipVerifiedProposerPreferenceCache, }; use educe::Educe; +use eth2::types::{EventKind, ForkVersionedResponse}; use slot_clock::SlotClock; use state_processing::signature_sets::{ execution_payload_bid_signature_set, get_builder_pubkey_from_state, @@ -233,6 +234,19 @@ impl BeaconChain { %parent_block_root, "Successfully verified gossip payload bid" ); + + if let Some(event_handler) = self.event_handler.as_ref() + && event_handler.has_execution_payload_bid_subscribers() + { + event_handler.register(EventKind::ExecutionPayloadBid(Box::new( + ForkVersionedResponse { + version: self.spec.fork_name_at_slot::(slot), + metadata: Default::default(), + data: (*verified.signed_bid).clone(), + }, + ))); + } + Ok(verified) } Err(e) => { diff --git a/beacon_node/beacon_chain/src/payload_envelope_verification/import.rs b/beacon_node/beacon_chain/src/payload_envelope_verification/import.rs index 5a6d3a1b7d..b40e8337fb 100644 --- a/beacon_node/beacon_chain/src/payload_envelope_verification/import.rs +++ b/beacon_node/beacon_chain/src/payload_envelope_verification/import.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use std::time::Duration; -use eth2::types::{EventKind, SseExecutionPayload}; +use eth2::types::{EventKind, SseExecutionPayload, SseExecutionPayloadAvailable}; use fork_choice::PayloadVerificationStatus; use slot_clock::SlotClock; use store::StoreOp; @@ -182,6 +182,7 @@ impl BeaconChain { signed_envelope, import_data, payload_verification_outcome, + self.spec.clone(), )) } @@ -362,5 +363,18 @@ impl BeaconChain { execution_optimistic: payload_verification_status.is_optimistic(), })); } + + // TODO(gloas): once the DA checker handles envelopes, this event should also be + // emitted from the DA resolution path (similar to `process_availability` for blocks). + if let Some(event_handler) = self.event_handler.as_ref() + && event_handler.has_execution_payload_available_subscribers() + { + event_handler.register(EventKind::ExecutionPayloadAvailable( + SseExecutionPayloadAvailable { + slot: envelope_slot, + block_root, + }, + )); + } } } diff --git a/beacon_node/beacon_chain/src/payload_envelope_verification/mod.rs b/beacon_node/beacon_chain/src/payload_envelope_verification/mod.rs index 51fc3f235d..b153a3cd6a 100644 --- a/beacon_node/beacon_chain/src/payload_envelope_verification/mod.rs +++ b/beacon_node/beacon_chain/src/payload_envelope_verification/mod.rs @@ -60,6 +60,22 @@ pub struct AvailableEnvelope { } impl AvailableEnvelope { + pub fn new( + execution_block_hash: ExecutionBlockHash, + envelope: Arc>, + columns: DataColumnSidecarList, + columns_available_timestamp: Option, + spec: Arc, + ) -> Self { + Self { + execution_block_hash, + envelope, + columns, + columns_available_timestamp, + spec, + } + } + pub fn message(&self) -> &ExecutionPayloadEnvelope { &self.envelope.message } @@ -104,9 +120,10 @@ pub struct EnvelopeProcessingSnapshot { /// fully available. /// 2. `AvailabilityPending`: This envelope hasn't received all required blobs to consider it /// fully available. +#[allow(dead_code)] pub enum ExecutedEnvelope { Available(AvailableExecutedEnvelope), - // TODO(gloas) implement availability pending + // TODO(gloas): check data column availability via DA checker AvailabilityPending(), } @@ -115,6 +132,7 @@ impl ExecutedEnvelope { envelope: MaybeAvailableEnvelope, import_data: EnvelopeImportData, payload_verification_outcome: PayloadVerificationOutcome, + spec: Arc, ) -> Self { match envelope { MaybeAvailableEnvelope::Available(available_envelope) => { @@ -124,11 +142,15 @@ impl ExecutedEnvelope { payload_verification_outcome, )) } - // TODO(gloas) implement availability pending + // TODO(gloas): check data column availability via DA checker MaybeAvailableEnvelope::AvailabilityPending { - block_hash: _, - envelope: _, - } => Self::AvailabilityPending(), + block_hash, + envelope, + } => Self::Available(AvailableExecutedEnvelope::new( + AvailableEnvelope::new(block_hash, envelope, vec![], None, spec), + import_data, + payload_verification_outcome, + )), } } } diff --git a/beacon_node/beacon_chain/tests/events.rs b/beacon_node/beacon_chain/tests/events.rs index 5305965f0f..e943514c4e 100644 --- a/beacon_node/beacon_chain/tests/events.rs +++ b/beacon_node/beacon_chain/tests/events.rs @@ -10,8 +10,8 @@ use std::sync::Arc; use types::data::FixedBlobSidecarList; use types::test_utils::TestRandom; use types::{ - BlobSidecar, DataColumnSidecar, DataColumnSidecarFulu, DataColumnSidecarGloas, EthSpec, - MinimalEthSpec, Slot, + BlobSidecar, DataColumnSidecar, DataColumnSidecarFulu, DataColumnSidecarGloas, Domain, EthSpec, + MinimalEthSpec, PayloadAttestationData, PayloadAttestationMessage, SignedRoot, Slot, }; type E = MinimalEthSpec; @@ -258,3 +258,177 @@ async fn head_event_on_block_import() { panic!("Expected Head event, got {:?}", head_event); } } + +/// Verifies that `execution_payload_gossip` fires at gossip verification time, and +/// `execution_payload` + `execution_payload_available` fire at import time. +#[tokio::test] +async fn execution_payload_envelope_events() { + if !fork_name_from_env().is_some_and(|f| f.gloas_enabled()) { + return; + } + + let harness = BeaconChainHarness::builder(E::default()) + .default_spec() + .deterministic_keypairs(64) + .fresh_ephemeral_store() + .mock_execution_layer() + .build(); + + harness.extend_to_slot(Slot::new(1)).await; + + let state = harness.get_current_state(); + let target_slot = Slot::new(2); + harness.advance_slot(); + let (block_contents, opt_envelope, _new_state) = + harness.make_block_with_envelope(state, target_slot).await; + + let block_root = block_contents.0.canonical_root(); + + harness + .process_block(target_slot, block_root, block_contents) + .await + .expect("block should be processed"); + + let signed_envelope = opt_envelope.expect("Gloas block should produce an envelope"); + + let event_handler = harness.chain.event_handler.as_ref().unwrap(); + let mut gossip_receiver = event_handler.subscribe_execution_payload_gossip(); + let mut payload_receiver = event_handler.subscribe_execution_payload(); + let mut available_receiver = event_handler.subscribe_execution_payload_available(); + + // Stage 1: gossip verification fires execution_payload_gossip only. + let gossip_verified = harness + .chain + .verify_envelope_for_gossip(Arc::new(signed_envelope)) + .await + .expect("envelope gossip verification should succeed"); + + let gossip_event = gossip_receiver + .try_recv() + .expect("should receive execution_payload_gossip after gossip verification"); + if let EventKind::ExecutionPayloadGossip(sse) = gossip_event { + assert_eq!(sse.slot, target_slot); + assert_eq!(sse.block_root, block_root); + } else { + panic!( + "Expected ExecutionPayloadGossip event, got {:?}", + gossip_event + ); + } + assert!(payload_receiver.try_recv().is_err()); + assert!(available_receiver.try_recv().is_err()); + + // Stage 2: import fires execution_payload and execution_payload_available. + harness + .chain + .process_execution_payload_envelope( + block_root, + gossip_verified, + beacon_chain::NotifyExecutionLayer::Yes, + types::BlockImportSource::Gossip, + #[allow(clippy::result_large_err)] + || Ok(()), + ) + .await + .expect("envelope import should succeed"); + + let payload_event = payload_receiver + .try_recv() + .expect("should receive execution_payload after import"); + if let EventKind::ExecutionPayload(sse) = payload_event { + assert_eq!(sse.slot, target_slot); + assert_eq!(sse.block_root, block_root); + } else { + panic!("Expected ExecutionPayload event, got {:?}", payload_event); + } + + let available_event = available_receiver + .try_recv() + .expect("should receive execution_payload_available after import"); + if let EventKind::ExecutionPayloadAvailable(sse) = available_event { + assert_eq!(sse.slot, target_slot); + assert_eq!(sse.block_root, block_root); + } else { + panic!( + "Expected ExecutionPayloadAvailable event, got {:?}", + available_event + ); + } + + assert!( + gossip_receiver.try_recv().is_err(), + "no extra gossip events should fire during import" + ); +} + +/// Verifies that a `payload_attestation_message` event is emitted when a payload attestation +/// message passes gossip verification. +#[tokio::test] +async fn payload_attestation_message_event_on_gossip_verification() { + if !fork_name_from_env().is_some_and(|f| f.gloas_enabled()) { + return; + } + + let harness = BeaconChainHarness::builder(E::default()) + .default_spec() + .deterministic_keypairs(64) + .fresh_ephemeral_store() + .mock_execution_layer() + .build(); + + // Advance chain to have a valid head block. + let target_slot = Slot::new(1); + harness.extend_to_slot(target_slot).await; + + let head = harness.chain.canonical_head.cached_head(); + let head_state = &head.snapshot.beacon_state; + + // Get a PTC member for this slot. + let ptc = head_state + .get_ptc(target_slot, &harness.spec) + .expect("should get PTC"); + let validator_index = *ptc.0.first().expect("PTC should have at least one member") as u64; + + // Sign a payload attestation. + let target_epoch = target_slot.epoch(E::slots_per_epoch()); + let domain = harness.spec.get_domain( + target_epoch, + Domain::PTCAttester, + &head_state.fork(), + head_state.genesis_validators_root(), + ); + let data = PayloadAttestationData { + beacon_block_root: head.head_block_root(), + slot: target_slot, + payload_present: true, + blob_data_available: true, + }; + let message = data.signing_root(domain); + let signature = harness.validator_keypairs[validator_index as usize] + .sk + .sign(message); + let msg = PayloadAttestationMessage { + validator_index, + data: data.clone(), + signature: signature.clone(), + }; + + // Subscribe before verification. + let event_handler = harness.chain.event_handler.as_ref().unwrap(); + let mut receiver = event_handler.subscribe_payload_attestation_message(); + + // Verify the attestation through the gossip path. + harness + .chain + .verify_payload_attestation_message_for_gossip(msg) + .expect("verification should succeed"); + + // Assert the event was emitted. + let event = receiver.try_recv().expect("should receive event"); + if let EventKind::PayloadAttestationMessage(versioned) = event { + assert_eq!(versioned.data.validator_index, validator_index); + assert_eq!(versioned.data.data, data); + } else { + panic!("Expected PayloadAttestationMessage event, got {:?}", event); + } +} From e35a67130341af2005f009cdfc253fb4cc40ae73 Mon Sep 17 00:00:00 2001 From: Mac L Date: Tue, 28 Apr 2026 12:59:07 +0400 Subject: [PATCH 05/12] Fix validator manager compilation (#9187) Currently, running `cargo check -p validator_manager` fails due to missing features. Although the `validator_manager` will almost always be called through the Lighthouse binary which will enable the required features, it is still good hygiene to ensure all workspace crates can compile standalone. Add the `lighthouse` feature to the `eth2` dependency in `validator_manager` Co-Authored-By: Mac L --- validator_manager/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/validator_manager/Cargo.toml b/validator_manager/Cargo.toml index d0155698b4..7dabd5445c 100644 --- a/validator_manager/Cargo.toml +++ b/validator_manager/Cargo.toml @@ -11,7 +11,7 @@ clap = { workspace = true } clap_utils = { workspace = true } educe = { workspace = true } environment = { workspace = true } -eth2 = { workspace = true } +eth2 = { workspace = true, features = ["lighthouse"] } eth2_network_config = { workspace = true } eth2_wallet = { workspace = true } ethereum_serde_utils = { workspace = true } From d8790f66772e05b49a1a4d815810de121d6af094 Mon Sep 17 00:00:00 2001 From: Jimmy Chen Date: Tue, 28 Apr 2026 12:49:28 +0200 Subject: [PATCH 06/12] Add payload attestation to op pool and pack into block (#9180) Store gossip-verified `PayloadAttestationMessage`s in the operation pool and pack them into the block body at during block production. Built on top of #9145. Co-Authored-By: Jimmy Chen --- beacon_node/beacon_chain/src/beacon_chain.rs | 12 + .../src/block_production/gloas.rs | 42 ++- .../gossip_methods.rs | 37 +- beacon_node/operation_pool/src/lib.rs | 315 +++++++++++++++++- beacon_node/operation_pool/src/persistence.rs | 1 + .../src/payload_attestation_service.rs | 7 +- 6 files changed, 386 insertions(+), 28 deletions(-) diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index cf5afb089a..9da64888c2 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -61,6 +61,7 @@ use crate::observed_data_sidecars::ObservedDataSidecars; use crate::observed_operations::{ObservationOutcome, ObservedOperations}; use crate::observed_slashable::ObservedSlashable; use crate::partial_data_column_assembler::PartialMergeResult; +use crate::payload_attestation_verification::VerifiedPayloadAttestationMessage; use crate::payload_bid_verification::payload_bid_cache::GossipVerifiedPayloadBidCache; #[cfg(not(test))] use crate::payload_envelope_streamer::{EnvelopeRequestSource, launch_payload_envelope_stream}; @@ -2328,6 +2329,17 @@ impl BeaconChain { .map_err(Into::into) } + /// Add a verified payload attestation message to the operation pool for block inclusion. + pub fn add_payload_attestation_to_pool( + &self, + verified: &VerifiedPayloadAttestationMessage, + ) -> Result<(), Error> { + self.op_pool + .insert_payload_attestation_message(verified.payload_attestation_message().clone()) + .map_err(Error::OpPoolError)?; + Ok(()) + } + /// Accepts some `SyncCommitteeMessage` from the network and attempts to verify it, returning `Ok(_)` if /// it is valid to be (re)broadcast on the gossip network. pub fn verify_sync_committee_message_for_gossip( diff --git a/beacon_node/beacon_chain/src/block_production/gloas.rs b/beacon_node/beacon_chain/src/block_production/gloas.rs index 9b3fc2806e..4bc4b9862c 100644 --- a/beacon_node/beacon_chain/src/block_production/gloas.rs +++ b/beacon_node/beacon_chain/src/block_production/gloas.rs @@ -9,9 +9,10 @@ use execution_layer::{ use fork_choice::PayloadStatus; use operation_pool::CompactAttestationRef; use ssz::Encode; -use state_processing::common::get_attesting_indices_from_state; +use state_processing::common::{get_attesting_indices_from_state, get_indexed_payload_attestation}; use state_processing::envelope_processing::verify_execution_payload_envelope; use state_processing::epoch_cache::initialize_epoch_cache; +use state_processing::per_block_processing::is_valid_indexed_payload_attestation; use state_processing::per_block_processing::{ apply_parent_execution_payload, compute_timestamp_at_slot, get_expected_withdrawals, verify_attestation_for_block_inclusion, @@ -319,6 +320,11 @@ impl BeaconChain { .map_err(BlockProductionError::OpPoolError)? }; + let mut payload_attestations = self + .op_pool + .get_payload_attestations(&state, parent_root, &self.spec) + .map_err(BlockProductionError::OpPoolError)?; + // If paranoid mode is enabled re-check the signatures of every included message. // This will be a lot slower but guards against bugs in block production and can be // quickly rolled out without a release. @@ -343,6 +349,35 @@ impl BeaconChain { .is_ok() }); + payload_attestations.retain(|att| { + match get_indexed_payload_attestation(&state, att, &self.spec) { + Ok(indexed) => is_valid_indexed_payload_attestation( + &state, + &indexed, + VerifySignatures::True, + &self.spec, + ) + .map_err(|e| { + warn!( + err = ?e, + block_slot = %state.slot(), + ?att, + "Attempted to include a payload attestation with invalid signature" + ); + }) + .is_ok(), + Err(e) => { + warn!( + err = ?e, + block_slot = %state.slot(), + ?att, + "Failed to index payload attestation for verification" + ); + false + } + } + }); + proposer_slashings.retain(|slashing| { slashing .clone() @@ -386,8 +421,6 @@ impl BeaconChain { }) .is_ok() }); - - // TODO(gloas) verify payload attestation signature here as well } let attester_slashings = attester_slashings @@ -434,8 +467,7 @@ impl BeaconChain { deposits, voluntary_exits, sync_aggregate, - // TODO(gloas) need to implement payload attestations - payload_attestations: vec![], + payload_attestations, bls_to_execution_changes, }, state, diff --git a/beacon_node/network/src/network_beacon_processor/gossip_methods.rs b/beacon_node/network/src/network_beacon_processor/gossip_methods.rs index 4083b1a3af..29306c198d 100644 --- a/beacon_node/network/src/network_beacon_processor/gossip_methods.rs +++ b/beacon_node/network/src/network_beacon_processor/gossip_methods.rs @@ -140,11 +140,6 @@ struct RejectedAggregate { error: AttnError, } -struct RejectedPayloadAttestation { - payload_attestation_message: Box, - error: PayloadAttestationError, -} - /// Data for an aggregated or unaggregated attestation that failed verification. enum FailedAtt { Unaggregate { @@ -4111,25 +4106,20 @@ impl NetworkBeaconProcessor { peer_id: PeerId, payload_attestation_message: Box, ) { - let result = match self + let message_slot = payload_attestation_message.data.slot; + let result = self .chain - .verify_payload_attestation_message_for_gossip(*payload_attestation_message.clone()) - { - Ok(verified) => Ok(verified), - Err(error) => Err(RejectedPayloadAttestation { - payload_attestation_message: payload_attestation_message.clone(), - error, - }), - }; + .verify_payload_attestation_message_for_gossip(*payload_attestation_message); - self.process_gossip_payload_attestation_result(result, message_id, peer_id); + self.process_gossip_payload_attestation_result(result, message_id, peer_id, message_slot); } fn process_gossip_payload_attestation_result( self: &Arc, - result: Result, RejectedPayloadAttestation>, + result: Result, PayloadAttestationError>, message_id: MessageId, peer_id: PeerId, + message_slot: Slot, ) { match result { Ok(verified) => { @@ -4156,16 +4146,21 @@ impl NetworkBeaconProcessor { ), } } + + if let Err(e) = self.chain.add_payload_attestation_to_pool(&verified) { + warn!( + reason = ?e, + %peer_id, + "Failed to add payload attestation to pool" + ); + } } - Err(RejectedPayloadAttestation { - payload_attestation_message, - error, - }) => { + Err(error) => { self.handle_payload_attestation_verification_failure( peer_id, message_id, error, - payload_attestation_message.data.slot, + message_slot, ); } } diff --git a/beacon_node/operation_pool/src/lib.rs b/beacon_node/operation_pool/src/lib.rs index 4b815704d9..de5fe9a098 100644 --- a/beacon_node/operation_pool/src/lib.rs +++ b/beacon_node/operation_pool/src/lib.rs @@ -23,10 +23,12 @@ use crate::attestation_storage::{AttestationMap, CheckpointKey}; use crate::bls_to_execution_changes::BlsToExecutionChanges; use crate::sync_aggregate_id::SyncAggregateId; use attester_slashing::AttesterSlashingMaxCover; +use bls::AggregateSignature; use max_cover::maximum_cover; use parking_lot::{RwLock, RwLockWriteGuard}; use rand::rng; use rand::seq::SliceRandom; +use ssz::BitVector; use state_processing::per_block_processing::errors::AttestationValidationError; use state_processing::per_block_processing::{ VerifySignatures, get_slashable_indices_modular, verify_exit, @@ -38,7 +40,8 @@ use std::ptr; use typenum::Unsigned; use types::{ AbstractExecPayload, Attestation, AttestationData, AttesterSlashing, BeaconState, - BeaconStateError, ChainSpec, Epoch, EthSpec, ProposerSlashing, SignedBeaconBlock, + BeaconStateError, ChainSpec, Epoch, EthSpec, Hash256, PayloadAttestation, + PayloadAttestationData, PayloadAttestationMessage, ProposerSlashing, SignedBeaconBlock, SignedBlsToExecutionChange, SignedVoluntaryExit, Slot, SyncAggregate, SyncAggregateError, SyncCommitteeContribution, Validator, }; @@ -59,6 +62,9 @@ pub struct OperationPool { voluntary_exits: RwLock>>, /// Map from credential changing validator to their position in the queue. bls_to_execution_changes: RwLock>, + /// Map from payload attestation data to individual messages for aggregation at block production. + payload_attestation_messages: + RwLock>>, /// Reward cache for accelerating attestation packing. reward_cache: RwLock, _phantom: PhantomData, @@ -78,6 +84,8 @@ pub enum OpPoolError { IncorrectOpPoolVariant, EpochCacheNotInitialized, EpochCacheError(EpochCacheError), + GetPtcError(BeaconStateError), + PayloadAttestationBitError, } #[derive(Default)] @@ -193,6 +201,100 @@ impl OperationPool { }); } + /// Insert a validated `PayloadAttestationMessage` into the pool. + pub fn insert_payload_attestation_message( + &self, + message: PayloadAttestationMessage, + ) -> Result<(), OpPoolError> { + let mut messages = self.payload_attestation_messages.write(); + let entry = messages.entry(message.data.clone()).or_default(); + if !entry + .iter() + .any(|m| m.validator_index == message.validator_index) + { + entry.push(message); + } + Ok(()) + } + + /// Build `PayloadAttestation`s from stored messages for block production. + /// + /// `parent_block_root` is the root of the parent block (the block PTC members attested to). + /// Returns one `PayloadAttestation` per distinct `PayloadAttestationData`. With two boolean + /// fields this yields at most 4, capped to `MaxPayloadAttestations`. + pub fn get_payload_attestations( + &self, + state: &BeaconState, + parent_block_root: Hash256, + spec: &ChainSpec, + ) -> Result>, OpPoolError> { + let target_slot = state.slot().saturating_sub(1u64); + + let ptc = state + .get_ptc(target_slot, spec) + .map_err(OpPoolError::GetPtcError)?; + + let messages = self.payload_attestation_messages.read(); + let mut result = Vec::new(); + + for (data, msgs) in messages.iter() { + if data.slot != target_slot || data.beacon_block_root != parent_block_root { + continue; + } + + let mut aggregation_bits = BitVector::new(); + let mut aggregate_sig = AggregateSignature::infinity(); + + for msg in msgs { + if let Some(pos) = ptc + .0 + .iter() + .position(|&idx| idx == msg.validator_index as usize) + && !aggregation_bits.get(pos).unwrap_or(false) + { + aggregation_bits + .set(pos, true) + .map_err(|_| OpPoolError::PayloadAttestationBitError)?; + aggregate_sig.add_assign(&msg.signature); + } + } + + if aggregation_bits.num_set_bits() > 0 { + result.push(PayloadAttestation { + aggregation_bits, + data: data.clone(), + signature: aggregate_sig, + }); + } + } + + // Prefer most participation and cap by `max_payload_attestations` + result.sort_by(|a, b| { + b.aggregation_bits + .num_set_bits() + .cmp(&a.aggregation_bits.num_set_bits()) + }); + result.truncate(E::max_payload_attestations()); + + Ok(result) + } + + /// Remove payload attestation messages that are too old for block inclusion. + pub fn prune_payload_attestation_messages(&self, current_slot: Slot) { + self.payload_attestation_messages + .write() + .retain(|data, _| current_slot <= data.slot.saturating_add(Slot::new(1))); + } + + /// Total number of payload attestation messages in the pool. + pub fn num_payload_attestation_messages(&self) -> usize { + self.payload_attestation_messages + .read() + .values() + .map(|msgs| msgs.len()) + .sum() + } + /// Insert an attestation into the pool, aggregating it with existing attestations if possible. /// /// ## Note @@ -646,6 +748,7 @@ impl OperationPool { ) { self.prune_attestations(current_epoch); self.prune_sync_contributions(head_state.slot()); + self.prune_payload_attestation_messages(head_state.slot()); self.prune_proposer_slashings(finalized_state); self.prune_attester_slashings(finalized_state); self.prune_voluntary_exits(finalized_state, spec); @@ -2075,4 +2178,214 @@ mod release_tests { op_pool.prune_attester_slashings(&electra_head.beacon_state); assert_eq!(op_pool.attester_slashings.read().len(), 1); } + + fn make_payload_attestation_message( + slot: Slot, + validator_index: u64, + beacon_block_root: Hash256, + ) -> PayloadAttestationMessage { + make_payload_attestation_message_with_flags( + slot, + validator_index, + beacon_block_root, + true, + true, + ) + } + + fn make_payload_attestation_message_with_flags( + slot: Slot, + validator_index: u64, + beacon_block_root: Hash256, + payload_present: bool, + blob_data_available: bool, + ) -> PayloadAttestationMessage { + PayloadAttestationMessage { + validator_index, + data: PayloadAttestationData { + beacon_block_root, + slot, + payload_present, + blob_data_available, + }, + signature: bls::Signature::empty(), + } + } + + #[test] + fn payload_attestation_insert_and_dedup() { + let op_pool = OperationPool::::new(); + let root = Hash256::repeat_byte(0xaa); + let slot = Slot::new(1); + + let msg1 = make_payload_attestation_message(slot, 0, root); + let msg2 = make_payload_attestation_message(slot, 1, root); + let msg1_dup = make_payload_attestation_message(slot, 0, root); + + op_pool.insert_payload_attestation_message(msg1).unwrap(); + op_pool.insert_payload_attestation_message(msg2).unwrap(); + op_pool + .insert_payload_attestation_message(msg1_dup) + .unwrap(); + + assert_eq!(op_pool.num_payload_attestation_messages(), 2); + } + + #[test] + fn payload_attestation_prune() { + let op_pool = OperationPool::::new(); + let root = Hash256::repeat_byte(0xaa); + + let msg_slot1 = make_payload_attestation_message(Slot::new(1), 0, root); + let msg_slot2 = make_payload_attestation_message(Slot::new(2), 1, root); + let msg_slot3 = make_payload_attestation_message(Slot::new(3), 2, root); + + op_pool + .insert_payload_attestation_message(msg_slot1) + .unwrap(); + op_pool + .insert_payload_attestation_message(msg_slot2) + .unwrap(); + op_pool + .insert_payload_attestation_message(msg_slot3) + .unwrap(); + + assert_eq!(op_pool.num_payload_attestation_messages(), 3); + + op_pool.prune_payload_attestation_messages(Slot::new(3)); + assert_eq!(op_pool.num_payload_attestation_messages(), 2); + + op_pool.prune_payload_attestation_messages(Slot::new(4)); + assert_eq!(op_pool.num_payload_attestation_messages(), 1); + + op_pool.prune_payload_attestation_messages(Slot::new(5)); + assert_eq!(op_pool.num_payload_attestation_messages(), 0); + } + + #[tokio::test] + async fn payload_attestation_packs_bits_from_ptc_positions() { + let spec = test_spec::(); + if spec.gloas_fork_epoch.is_none() { + return; + }; + + let num_validators = 64; + let harness = get_harness::(num_validators, Some(spec.clone())); + + harness + .add_attested_blocks_at_slots( + harness.get_current_state(), + Hash256::zero(), + &[Slot::new(1)], + (0..num_validators).collect::>().as_slice(), + ) + .await; + + let head = harness.chain.canonical_head.cached_head(); + let state = &head.snapshot.beacon_state; + assert_eq!(state.slot(), Slot::new(1)); + + let target_slot = Slot::new(1); + let parent_root = head.head_block_root(); + let ptc = state.get_ptc(target_slot, &spec).unwrap(); + let ptc_member_0 = ptc.0[0] as u64; + let ptc_member_1 = ptc.0[1] as u64; + + let op_pool = OperationPool::::new(); + + let msg0 = make_payload_attestation_message(target_slot, ptc_member_0, parent_root); + let msg1 = make_payload_attestation_message(target_slot, ptc_member_1, parent_root); + op_pool.insert_payload_attestation_message(msg0).unwrap(); + op_pool.insert_payload_attestation_message(msg1).unwrap(); + + // Advance state to slot 2 so get_payload_attestations looks at slot 1. + let mut advanced_state = state.clone(); + state_processing::state_advance::complete_state_advance( + &mut advanced_state, + None, + Slot::new(2), + &spec, + ) + .unwrap(); + + let attestations = op_pool + .get_payload_attestations(&advanced_state, parent_root, &spec) + .unwrap(); + + assert_eq!(attestations.len(), 1); + assert_eq!(attestations[0].aggregation_bits.num_set_bits(), 2); + assert!(attestations[0].aggregation_bits.get(0).unwrap()); + assert!(attestations[0].aggregation_bits.get(1).unwrap()); + assert!(attestations[0].data.payload_present); + } + + #[tokio::test] + async fn payload_attestation_multiple_data_combos_capped() { + let spec = test_spec::(); + if spec.gloas_fork_epoch.is_none() { + return; + }; + + let num_validators = 64; + let harness = get_harness::(num_validators, Some(spec.clone())); + + harness + .add_attested_blocks_at_slots( + harness.get_current_state(), + Hash256::zero(), + &[Slot::new(1)], + (0..num_validators).collect::>().as_slice(), + ) + .await; + + let head = harness.chain.canonical_head.cached_head(); + let state = &head.snapshot.beacon_state; + let target_slot = Slot::new(1); + let parent_root = head.head_block_root(); + let ptc = state.get_ptc(target_slot, &spec).unwrap(); + + let op_pool = OperationPool::::new(); + + // Given: PTC members vote with all 4 boolean combos, with varying participation. + let combos: [(bool, bool, &[usize]); 4] = [ + (true, true, &[0, 1, 2]), + (true, false, &[3, 4]), + (false, true, &[5]), + (false, false, &[6]), + ]; + for (payload_present, blob_available, positions) in &combos { + for &pos in *positions { + let validator_index = ptc.0[pos] as u64; + let msg = make_payload_attestation_message_with_flags( + target_slot, + validator_index, + parent_root, + *payload_present, + *blob_available, + ); + op_pool.insert_payload_attestation_message(msg).unwrap(); + } + } + + // When: we pack attestations for block production at slot 2. + let mut advanced_state = state.clone(); + state_processing::state_advance::complete_state_advance( + &mut advanced_state, + None, + Slot::new(2), + &spec, + ) + .unwrap(); + let attestations = op_pool + .get_payload_attestations(&advanced_state, parent_root, &spec) + .unwrap(); + + // Then: one attestation per combo, sorted by participation (most first). + assert_eq!(attestations.len(), 4); + let bit_counts: Vec<_> = attestations + .iter() + .map(|a| a.aggregation_bits.num_set_bits()) + .collect(); + assert_eq!(bit_counts, vec![3, 2, 1, 1]); + } } diff --git a/beacon_node/operation_pool/src/persistence.rs b/beacon_node/operation_pool/src/persistence.rs index 241b5fec53..56aafc27fe 100644 --- a/beacon_node/operation_pool/src/persistence.rs +++ b/beacon_node/operation_pool/src/persistence.rs @@ -209,6 +209,7 @@ impl PersistedOperationPool { proposer_slashings, voluntary_exits, bls_to_execution_changes: RwLock::new(bls_to_execution_changes), + payload_attestation_messages: Default::default(), reward_cache: Default::default(), _phantom: Default::default(), }; diff --git a/validator_client/validator_services/src/payload_attestation_service.rs b/validator_client/validator_services/src/payload_attestation_service.rs index 2f3ca8bed2..24949edc1f 100644 --- a/validator_client/validator_services/src/payload_attestation_service.rs +++ b/validator_client/validator_services/src/payload_attestation_service.rs @@ -101,10 +101,15 @@ impl PayloadAttestationServ sleep(duration_to_next_slot + payload_attestation_due).await; + let Some(attestation_slot) = self.slot_clock.now() else { + error!("Failed to read slot clock after sleep"); + continue; + }; + let service = self.clone(); self.executor.spawn( async move { - service.produce_and_publish(current_slot).await; + service.produce_and_publish(attestation_slot).await; }, "payload_attestation_producer", ); From 4415cf050693a8205dd12e1cbd61b394bebb3e4e Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Tue, 28 Apr 2026 14:45:03 +0200 Subject: [PATCH 07/12] Gloas filter conflicting voluntary exits (#9183) Parent envelope execution requests can invalidate voluntary exits. We should filter out any conflicting voluntary exits during block production to avoid triggering failures. Spec change: https://github.com/ethereum/consensus-specs/pull/5176 Co-Authored-By: Eitan Seri-Levi Co-Authored-By: dapplion <35266934+dapplion@users.noreply.github.com> --- .../src/block_production/gloas.rs | 211 ++++++++++++++++-- 1 file changed, 198 insertions(+), 13 deletions(-) diff --git a/beacon_node/beacon_chain/src/block_production/gloas.rs b/beacon_node/beacon_chain/src/block_production/gloas.rs index 4bc4b9862c..a6ebc2fefa 100644 --- a/beacon_node/beacon_chain/src/block_production/gloas.rs +++ b/beacon_node/beacon_chain/src/block_production/gloas.rs @@ -1,8 +1,8 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::marker::PhantomData; use std::sync::Arc; -use bls::Signature; +use bls::{PublicKeyBytes, Signature}; use execution_layer::{ BlockProposalContentsGloas, BuilderParams, PayloadAttributes, PayloadParameters, }; @@ -28,7 +28,7 @@ use types::consts::gloas::BUILDER_INDEX_SELF_BUILD; use types::{ Address, Attestation, AttestationElectra, AttesterSlashing, AttesterSlashingElectra, BeaconBlock, BeaconBlockBodyGloas, BeaconBlockGloas, BeaconState, BeaconStateError, - BuilderIndex, Deposit, Eth1Data, EthSpec, ExecutionBlockHash, ExecutionPayloadBid, + BuilderIndex, ChainSpec, Deposit, Eth1Data, EthSpec, ExecutionBlockHash, ExecutionPayloadBid, ExecutionPayloadEnvelope, ExecutionPayloadGloas, ExecutionRequests, FullPayload, Graffiti, Hash256, PayloadAttestation, ProposerSlashing, RelativeEpoch, SignedBeaconBlock, SignedBlsToExecutionChange, SignedExecutionPayloadBid, SignedExecutionPayloadEnvelope, @@ -137,6 +137,16 @@ impl BeaconChain { graffiti_settings: GraffitiSettings, verification: ProduceBlockVerification, ) -> Result, BlockProductionError> { + // Extract the parent's execution requests from the envelope (if parent was full). + let parent_execution_requests = if parent_payload_status == PayloadStatus::Full { + parent_envelope + .as_ref() + .map(|env| env.message.execution_requests.clone()) + .ok_or(BlockProductionError::MissingParentExecutionPayload)? + } else { + ExecutionRequests::default() + }; + // Part 1/3 (blocking) // // Perform the state advance and block-packing functions. @@ -145,6 +155,7 @@ impl BeaconChain { .graffiti_calculator .get_graffiti(graffiti_settings) .await; + let parent_execution_requests_ref = parent_execution_requests.clone(); let (partial_beacon_block, state) = self .task_executor .spawn_blocking_handle( @@ -155,6 +166,7 @@ impl BeaconChain { produce_at_slot, randao_reveal, graffiti, + &parent_execution_requests_ref, ) }, "produce_partial_beacon_block_gloas", @@ -163,16 +175,6 @@ impl BeaconChain { .await .map_err(BlockProductionError::TokioJoin)??; - // Extract the parent's execution requests from the envelope (if parent was full). - let parent_execution_requests = if parent_payload_status == PayloadStatus::Full { - parent_envelope - .as_ref() - .map(|env| env.message.execution_requests.clone()) - .ok_or(BlockProductionError::MissingParentExecutionPayload)? - } else { - ExecutionRequests::default() - }; - // Part 2/3 (async) // // Produce the execution payload bid. @@ -223,6 +225,7 @@ impl BeaconChain { produce_at_slot: Slot, randao_reveal: Signature, graffiti: Graffiti, + parent_execution_requests: &ExecutionRequests, ) -> Result<(PartialBeaconBlock, BeaconState), BlockProductionError> { // It is invalid to try to produce a block using a state from a future slot. @@ -257,6 +260,13 @@ impl BeaconChain { let (mut proposer_slashings, mut attester_slashings, mut voluntary_exits) = self.op_pool.get_slashings_and_exits(&state, &self.spec); + filter_voluntary_exits_for_parent_execution_requests( + &mut voluntary_exits, + parent_execution_requests, + |idx| state.validators().get(idx as usize).map(|v| v.pubkey), + &self.spec, + ); + drop(slashings_and_exits_span); let eth1_data = state.eth1_data().clone(); @@ -958,3 +968,178 @@ where Ok(block_contents) } + +/// Drop voluntary exits whose target validators will be exited by the parent envelope's +/// execution requests. +/// +/// In Gloas the parent execution payload is processed before voluntary exits during block +/// processing. EL-triggered withdrawal-full-exit requests (EIP-7002) and cross-pubkey +/// consolidation requests (EIP-7251) call `initiate_validator_exit`, setting the target's +/// `exit_epoch`. A voluntary exit for the same validator would then fail with `AlreadyExited`. +fn filter_voluntary_exits_for_parent_execution_requests( + voluntary_exits: &mut Vec, + parent_execution_requests: &ExecutionRequests, + pubkey_at_index: impl Fn(u64) -> Option, + spec: &ChainSpec, +) { + let mut exited_pubkeys = HashSet::with_capacity( + parent_execution_requests.withdrawals.len() + + parent_execution_requests.consolidations.len(), + ); + for req in &parent_execution_requests.withdrawals { + if req.amount == spec.full_exit_request_amount { + exited_pubkeys.insert(req.validator_pubkey); + } + } + for req in &parent_execution_requests.consolidations { + if req.source_pubkey != req.target_pubkey { + exited_pubkeys.insert(req.source_pubkey); + } + } + if !exited_pubkeys.is_empty() { + voluntary_exits.retain(|exit| { + pubkey_at_index(exit.message.validator_index) + .map(|pk| !exited_pubkeys.contains(&pk)) + .unwrap_or(false) + }); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use ssz_types::VariableList; + use types::{ConsolidationRequest, Epoch, MainnetEthSpec, VoluntaryExit, WithdrawalRequest}; + + type TestSpec = MainnetEthSpec; + + fn pubkey(byte: u8) -> PublicKeyBytes { + PublicKeyBytes::deserialize(&[byte; 48]).expect("valid pubkey byte length") + } + + fn exit(validator_index: u64) -> SignedVoluntaryExit { + SignedVoluntaryExit { + message: VoluntaryExit { + epoch: Epoch::new(0), + validator_index, + }, + signature: Signature::empty(), + } + } + + fn requests( + withdrawals: Vec, + consolidations: Vec, + ) -> ExecutionRequests { + ExecutionRequests { + deposits: VariableList::empty(), + withdrawals: VariableList::new(withdrawals).unwrap(), + consolidations: VariableList::new(consolidations).unwrap(), + } + } + + fn run_filter( + exits: &mut Vec, + requests: &ExecutionRequests, + validator_pubkeys: &[PublicKeyBytes], + spec: &ChainSpec, + ) { + filter_voluntary_exits_for_parent_execution_requests( + exits, + requests, + |idx| validator_pubkeys.get(idx as usize).copied(), + spec, + ); + } + + #[test] + fn full_exit_withdrawal_request_filters_matching_voluntary_exit() { + let spec = ChainSpec::mainnet(); + let validators = vec![pubkey(1), pubkey(2)]; + let mut exits = vec![exit(0), exit(1)]; + let reqs = requests( + vec![WithdrawalRequest { + source_address: Address::repeat_byte(0xaa), + validator_pubkey: validators[0], + amount: spec.full_exit_request_amount, + }], + vec![], + ); + + run_filter(&mut exits, &reqs, &validators, &spec); + + assert_eq!(exits.len(), 1); + assert_eq!(exits[0].message.validator_index, 1); + } + + #[test] + fn partial_withdrawal_request_does_not_filter_voluntary_exit() { + let spec = ChainSpec::mainnet(); + let validators = vec![pubkey(1)]; + let mut exits = vec![exit(0)]; + let reqs = requests( + vec![WithdrawalRequest { + source_address: Address::repeat_byte(0xaa), + validator_pubkey: validators[0], + amount: spec.full_exit_request_amount + 1, + }], + vec![], + ); + + run_filter(&mut exits, &reqs, &validators, &spec); + + assert_eq!(exits.len(), 1); + } + + #[test] + fn cross_pubkey_consolidation_filters_voluntary_exit_for_source_only() { + let spec = ChainSpec::mainnet(); + let validators = vec![pubkey(1), pubkey(2), pubkey(3)]; + let mut exits = vec![exit(0), exit(1), exit(2)]; + let reqs = requests( + vec![], + vec![ConsolidationRequest { + source_address: Address::repeat_byte(0xaa), + source_pubkey: validators[1], + target_pubkey: validators[2], + }], + ); + + run_filter(&mut exits, &reqs, &validators, &spec); + + // The source (validator 1) is exited; the target (validator 2) is not. + let remaining: Vec = exits.iter().map(|e| e.message.validator_index).collect(); + assert_eq!(remaining, vec![0, 2]); + } + + #[test] + fn self_consolidation_does_not_filter_voluntary_exit() { + let spec = ChainSpec::mainnet(); + let validators = vec![pubkey(1)]; + let mut exits = vec![exit(0)]; + let reqs = requests( + vec![], + vec![ConsolidationRequest { + source_address: Address::repeat_byte(0xaa), + source_pubkey: validators[0], + target_pubkey: validators[0], + }], + ); + + run_filter(&mut exits, &reqs, &validators, &spec); + + assert_eq!(exits.len(), 1); + } + + #[test] + fn empty_parent_requests_preserve_voluntary_exits() { + let spec = ChainSpec::mainnet(); + let validators = vec![pubkey(1), pubkey(2)]; + let mut exits = vec![exit(0), exit(1)]; + let reqs = requests(vec![], vec![]); + + run_filter(&mut exits, &reqs, &validators, &spec); + + assert_eq!(exits.len(), 2); + } +} From 6258eadc91c10432c93ab1487ef7ee436470b6d6 Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Tue, 28 Apr 2026 15:19:47 +0200 Subject: [PATCH 08/12] Gloas publish data columns during local block building (#9182) Make sure we are publishing columns during local block production Co-Authored-By: Eitan Seri-Levi Co-Authored-By: dapplion <35266934+dapplion@users.noreply.github.com> --- .../src/block_production/gloas.rs | 16 +- beacon_node/beacon_chain/src/kzg_utils.rs | 108 +++++++++++-- .../src/pending_payload_envelopes.rs | 93 ++++++++--- beacon_node/beacon_chain/src/test_utils.rs | 42 +++-- .../test_data_column_sidecars_gloas.ssz | Bin 0 -> 275968 bytes .../beacon_chain/tests/column_verification.rs | 72 +++++++++ .../beacon_chain/tests/prepare_payload.rs | 118 ++++++++++++++ .../src/beacon/execution_payload_envelope.rs | 151 +++++++++++++++++- beacon_node/http_api/src/publish_blocks.rs | 2 +- 9 files changed, 545 insertions(+), 57 deletions(-) create mode 100644 beacon_node/beacon_chain/src/test_utils/fixtures/test_data_column_sidecars_gloas.ssz diff --git a/beacon_node/beacon_chain/src/block_production/gloas.rs b/beacon_node/beacon_chain/src/block_production/gloas.rs index a6ebc2fefa..79ea78ce4a 100644 --- a/beacon_node/beacon_chain/src/block_production/gloas.rs +++ b/beacon_node/beacon_chain/src/block_production/gloas.rs @@ -35,6 +35,7 @@ use types::{ SignedVoluntaryExit, Slot, SyncAggregate, Withdrawal, Withdrawals, }; +use crate::pending_payload_envelopes::PendingEnvelopeData; use crate::{ BeaconChain, BeaconChainError, BeaconChainTypes, BlockProductionError, ProduceBlockVerification, block_production::BlockProductionState, @@ -74,6 +75,7 @@ pub struct ExecutionPayloadData { pub execution_requests: ExecutionRequests, pub builder_index: BuilderIndex, pub slot: Slot, + pub blobs_and_proofs: (types::BlobsList, types::KzgProofs), } impl BeaconChain { @@ -647,9 +649,14 @@ impl BeaconChain { let envelope_slot = payload_data.slot; // TODO(gloas) might be safer to cache by root instead of by slot. // We should revisit this once this code path + beacon api spec matures - self.pending_payload_envelopes - .write() - .insert(envelope_slot, signed_envelope.message); + let (blobs, _) = payload_data.blobs_and_proofs; + self.pending_payload_envelopes.write().insert( + envelope_slot, + PendingEnvelopeData { + envelope: signed_envelope.message, + blobs: Some(blobs), + }, + ); debug!( %beacon_block_root, @@ -769,7 +776,7 @@ impl BeaconChain { payload_value: _, execution_requests, blob_kzg_commitments, - blobs_and_proofs: _, + blobs_and_proofs, } = block_proposal_contents; // TODO(gloas) since we are defaulting to local building, execution payment is 0 @@ -795,6 +802,7 @@ impl BeaconChain { execution_requests, builder_index, slot: produce_at_slot, + blobs_and_proofs, }; // TODO(gloas) this is only local building diff --git a/beacon_node/beacon_chain/src/kzg_utils.rs b/beacon_node/beacon_chain/src/kzg_utils.rs index 9641aec47d..b05a896777 100644 --- a/beacon_node/beacon_chain/src/kzg_utils.rs +++ b/beacon_node/beacon_chain/src/kzg_utils.rs @@ -296,6 +296,35 @@ pub fn blobs_to_data_column_sidecars( } } +/// Build Gloas data column sidecars from blobs, computing cells and proofs locally. +pub fn blobs_to_data_column_sidecars_gloas( + blobs: &[&Blob], + beacon_block_root: Hash256, + slot: Slot, + kzg: &Kzg, + spec: &ChainSpec, +) -> Result, DataColumnSidecarError> { + if blobs.is_empty() { + return Ok(vec![]); + } + + let blob_cells_and_proofs_vec = blobs + .into_par_iter() + .map(|blob| { + let blob = blob.as_ref().try_into().map_err(|e| { + KzgError::InconsistentArrayLength(format!( + "blob should have a guaranteed size due to FixedVector: {e:?}" + )) + })?; + + kzg.compute_cells_and_proofs(blob) + }) + .collect::, KzgError>>()?; + + build_data_column_sidecars_gloas(beacon_block_root, slot, blob_cells_and_proofs_vec, spec) + .map_err(DataColumnSidecarError::BuildSidecarFailed) +} + /// Build data column sidecars from a signed beacon block and its blobs. #[instrument(skip_all, level = "debug", fields(blob_count = blobs_and_proofs.len()))] pub fn blobs_to_partial_data_columns( @@ -728,8 +757,8 @@ pub fn reconstruct_data_columns( #[cfg(test)] mod test { use crate::kzg_utils::{ - blobs_to_data_column_sidecars, reconstruct_blobs, reconstruct_data_columns, - validate_full_data_columns, + blobs_to_data_column_sidecars, blobs_to_data_column_sidecars_gloas, reconstruct_blobs, + reconstruct_data_columns, validate_full_data_columns, }; use bls::Signature; use eth2::types::BlobsBundle; @@ -737,25 +766,30 @@ mod test { use kzg::{Kzg, KzgCommitment, trusted_setup::get_trusted_setup}; use types::{ BeaconBlock, BeaconBlockFulu, BlobsList, ChainSpec, EmptyBlock, EthSpec, ForkName, - FullPayload, KzgProofs, MainnetEthSpec, SignedBeaconBlock, kzg_ext::KzgCommitments, + FullPayload, Hash256, KzgProofs, MainnetEthSpec, SignedBeaconBlock, Slot, + kzg_ext::KzgCommitments, }; type E = MainnetEthSpec; // Loading and initializing PeerDAS KZG is expensive and slow, so we group the tests together // only load it once. - // TODO(Gloas) make this generic over fulu/gloas, or write a separate function for Gloas #[test] fn test_build_data_columns_sidecars() { - let spec = ForkName::Fulu.make_genesis_spec(E::default_spec()); let kzg = get_kzg(); - test_build_data_columns_empty(&kzg, &spec); - test_build_data_columns_fulu(&kzg, &spec); - test_reconstruct_data_columns(&kzg, &spec); - test_reconstruct_data_columns_unordered(&kzg, &spec); - test_reconstruct_blobs_from_data_columns(&kzg, &spec); - test_reconstruct_blobs_from_data_columns_unordered(&kzg, &spec); - test_validate_data_columns(&kzg, &spec); + + let fulu_spec = ForkName::Fulu.make_genesis_spec(E::default_spec()); + test_build_data_columns_empty(&kzg, &fulu_spec); + test_build_data_columns_fulu(&kzg, &fulu_spec); + test_reconstruct_data_columns(&kzg, &fulu_spec); + test_reconstruct_data_columns_unordered(&kzg, &fulu_spec); + test_reconstruct_blobs_from_data_columns(&kzg, &fulu_spec); + test_reconstruct_blobs_from_data_columns_unordered(&kzg, &fulu_spec); + test_validate_data_columns(&kzg, &fulu_spec); + + let gloas_spec = ForkName::Gloas.make_genesis_spec(E::default_spec()); + test_build_data_columns_gloas(&kzg, &gloas_spec); + test_build_data_columns_gloas_empty(&kzg, &gloas_spec); } #[track_caller] @@ -784,8 +818,49 @@ mod test { assert!(column_sidecars.is_empty()); } - // TODO(gloas) create `test_build_data_columns_gloas` and make sure its called - // in the relevant places + #[track_caller] + fn test_build_data_columns_gloas(kzg: &Kzg, spec: &ChainSpec) { + let num_of_blobs = 2; + let (blobs, _proofs) = create_test_gloas_blobs::(num_of_blobs); + let beacon_block_root = Hash256::random(); + let slot = Slot::new(0); + + let blob_refs: Vec<_> = blobs.iter().collect(); + let column_sidecars = blobs_to_data_column_sidecars_gloas::( + &blob_refs, + beacon_block_root, + slot, + kzg, + spec, + ) + .unwrap(); + + assert_eq!(column_sidecars.len(), E::number_of_columns()); + for (idx, col_sidecar) in column_sidecars.iter().enumerate() { + assert_eq!(*col_sidecar.index(), idx as u64); + assert_eq!(col_sidecar.column().len(), num_of_blobs); + assert_eq!(col_sidecar.kzg_proofs().len(), num_of_blobs); + + let gloas_col = col_sidecar.as_gloas().expect("should be Gloas sidecar"); + assert_eq!(gloas_col.beacon_block_root, beacon_block_root); + assert_eq!(gloas_col.slot, slot); + } + } + + #[track_caller] + fn test_build_data_columns_gloas_empty(kzg: &Kzg, spec: &ChainSpec) { + let blob_refs: Vec<&types::Blob> = vec![]; + let column_sidecars = blobs_to_data_column_sidecars_gloas::( + &blob_refs, + Hash256::random(), + Slot::new(0), + kzg, + spec, + ) + .unwrap(); + assert!(column_sidecars.is_empty()); + } + #[track_caller] fn test_build_data_columns_fulu(kzg: &Kzg, spec: &ChainSpec) { // Using at least 2 blobs to make sure we're arranging the data columns correctly. @@ -974,4 +1049,9 @@ mod test { (signed_block, blobs, proofs) } + + fn create_test_gloas_blobs(num_of_blobs: usize) -> (BlobsList, KzgProofs) { + let (blobs_bundle, _) = generate_blobs::(num_of_blobs, ForkName::Gloas).unwrap(); + (blobs_bundle.blobs, blobs_bundle.proofs) + } } diff --git a/beacon_node/beacon_chain/src/pending_payload_envelopes.rs b/beacon_node/beacon_chain/src/pending_payload_envelopes.rs index 351783832d..293553ef54 100644 --- a/beacon_node/beacon_chain/src/pending_payload_envelopes.rs +++ b/beacon_node/beacon_chain/src/pending_payload_envelopes.rs @@ -6,7 +6,12 @@ //! and publishes the payload. use std::collections::HashMap; -use types::{EthSpec, ExecutionPayloadEnvelope, Slot}; +use types::{BlobsList, EthSpec, ExecutionPayloadEnvelope, Slot}; + +pub struct PendingEnvelopeData { + pub envelope: ExecutionPayloadEnvelope, + pub blobs: Option>, +} /// Cache for pending execution payload envelopes awaiting publishing. /// @@ -16,7 +21,7 @@ pub struct PendingPayloadEnvelopes { /// Maximum number of slots to keep envelopes before pruning. max_slot_age: u64, /// The envelopes, keyed by slot. - envelopes: HashMap>, + envelopes: HashMap>, } impl Default for PendingPayloadEnvelopes { @@ -38,19 +43,24 @@ impl PendingPayloadEnvelopes { } /// Insert a pending envelope into the cache. - pub fn insert(&mut self, slot: Slot, envelope: ExecutionPayloadEnvelope) { + pub fn insert(&mut self, slot: Slot, data: PendingEnvelopeData) { // TODO(gloas): we may want to check for duplicates here, which shouldn't be allowed - self.envelopes.insert(slot, envelope); + self.envelopes.insert(slot, data); } /// Get a pending envelope by slot. pub fn get(&self, slot: Slot) -> Option<&ExecutionPayloadEnvelope> { - self.envelopes.get(&slot) + self.envelopes.get(&slot).map(|d| &d.envelope) + } + + /// Remove and return the blobs and proofs for a slot, leaving the envelope in place. + pub fn take_blobs(&mut self, slot: Slot) -> Option> { + self.envelopes.get_mut(&slot).and_then(|d| d.blobs.take()) } /// Remove and return a pending envelope by slot. pub fn remove(&mut self, slot: Slot) -> Option> { - self.envelopes.remove(&slot) + self.envelopes.remove(&slot).map(|d| d.envelope) } /// Check if an envelope exists for the given slot. @@ -85,15 +95,18 @@ mod tests { type E = MainnetEthSpec; - fn make_envelope(slot: Slot) -> ExecutionPayloadEnvelope { - ExecutionPayloadEnvelope { - payload: ExecutionPayloadGloas { - slot_number: slot, - ..ExecutionPayloadGloas::default() + fn make_envelope(slot: Slot) -> PendingEnvelopeData { + PendingEnvelopeData { + envelope: ExecutionPayloadEnvelope { + payload: ExecutionPayloadGloas { + slot_number: slot, + ..ExecutionPayloadGloas::default() + }, + execution_requests: ExecutionRequests::default(), + builder_index: 0, + beacon_block_root: Hash256::ZERO, }, - execution_requests: ExecutionRequests::default(), - builder_index: 0, - beacon_block_root: Hash256::ZERO, + blobs: None, } } @@ -101,33 +114,73 @@ mod tests { fn insert_and_get() { let mut cache = PendingPayloadEnvelopes::::default(); let slot = Slot::new(1); - let envelope = make_envelope(slot); + let data = make_envelope(slot); + let expected_envelope = data.envelope.clone(); assert!(!cache.contains(slot)); assert_eq!(cache.len(), 0); - cache.insert(slot, envelope.clone()); + cache.insert(slot, data); assert!(cache.contains(slot)); assert_eq!(cache.len(), 1); - assert_eq!(cache.get(slot), Some(&envelope)); + assert_eq!(cache.get(slot), Some(&expected_envelope)); } #[test] fn remove() { let mut cache = PendingPayloadEnvelopes::::default(); let slot = Slot::new(1); - let envelope = make_envelope(slot); + let data = make_envelope(slot); + let expected_envelope = data.envelope.clone(); - cache.insert(slot, envelope.clone()); + cache.insert(slot, data); assert!(cache.contains(slot)); let removed = cache.remove(slot); - assert_eq!(removed, Some(envelope)); + assert_eq!(removed, Some(expected_envelope)); assert!(!cache.contains(slot)); assert_eq!(cache.len(), 0); } + #[test] + fn take_blobs_returns_once() { + let mut cache = PendingPayloadEnvelopes::::default(); + let slot = Slot::new(1); + + let blobs = BlobsList::::default(); + let data = PendingEnvelopeData { + envelope: make_envelope(slot).envelope, + blobs: Some(blobs), + }; + cache.insert(slot, data); + + // First take returns the blobs + let taken = cache.take_blobs(slot); + assert!(taken.is_some()); + + // Second take returns None — blobs are consumed + let taken_again = cache.take_blobs(slot); + assert!(taken_again.is_none()); + + // Envelope is still in the cache + assert!(cache.contains(slot)); + assert!(cache.get(slot).is_some()); + } + + #[test] + fn take_blobs_returns_none_when_absent() { + let mut cache = PendingPayloadEnvelopes::::default(); + let slot = Slot::new(1); + + // Insert with no blobs + cache.insert(slot, make_envelope(slot)); + assert!(cache.take_blobs(slot).is_none()); + + // Non-existent slot + assert!(cache.take_blobs(Slot::new(99)).is_none()); + } + #[test] fn prune_old_envelopes() { let mut cache = PendingPayloadEnvelopes::::new(2); diff --git a/beacon_node/beacon_chain/src/test_utils.rs b/beacon_node/beacon_chain/src/test_utils.rs index 274f41d1cb..f67b5015c5 100644 --- a/beacon_node/beacon_chain/src/test_utils.rs +++ b/beacon_node/beacon_chain/src/test_utils.rs @@ -86,6 +86,8 @@ pub const FORK_NAME_ENV_VAR: &str = "FORK_NAME"; // `beacon_node/execution_layer/src/test_utils/fixtures/mainnet/test_blobs_bundle.ssz` pub const TEST_DATA_COLUMN_SIDECARS_SSZ: &[u8] = include_bytes!("test_utils/fixtures/test_data_column_sidecars.ssz"); +pub const TEST_DATA_COLUMN_SIDECARS_GLOAS_SSZ: &[u8] = + include_bytes!("test_utils/fixtures/test_data_column_sidecars_gloas.ssz"); // Default target aggregators to set during testing, this ensures an aggregator at each slot. // @@ -3789,24 +3791,24 @@ pub fn generate_data_column_sidecars_from_block( block: &SignedBeaconBlock, spec: &ChainSpec, ) -> DataColumnSidecarList { - let kzg_commitments = block.message().body().blob_kzg_commitments().unwrap(); - if kzg_commitments.is_empty() { - return vec![]; - } - - let kzg_commitments_inclusion_proof = block - .message() - .body() - .kzg_commitments_merkle_proof() - .unwrap(); - let signed_block_header = block.signed_block_header(); - // Load the precomputed column sidecar to avoid computing them for every block in the tests. // Then repeat the cells and proofs for every blob if block.fork_name_unchecked().gloas_enabled() { + let kzg_commitments = &block + .message() + .body() + .signed_execution_payload_bid() + .expect("Gloas block should have a payload bid") + .message + .blob_kzg_commitments; + if kzg_commitments.is_empty() { + return vec![]; + } + let num_blobs = kzg_commitments.len(); + let signed_block_header = block.signed_block_header(); let template_data_columns = RuntimeVariableList::>::from_ssz_bytes( - TEST_DATA_COLUMN_SIDECARS_SSZ, + TEST_DATA_COLUMN_SIDECARS_GLOAS_SSZ, E::number_of_columns(), ) .unwrap(); @@ -3826,7 +3828,7 @@ pub fn generate_data_column_sidecars_from_block( .collect::<(Vec<_>, Vec<_>)>(); let blob_cells_and_proofs_vec = - vec![(cells.try_into().unwrap(), proofs.try_into().unwrap()); kzg_commitments.len()]; + vec![(cells.try_into().unwrap(), proofs.try_into().unwrap()); num_blobs]; build_data_column_sidecars_gloas( signed_block_header.message.tree_hash_root(), @@ -3836,6 +3838,18 @@ pub fn generate_data_column_sidecars_from_block( ) .unwrap() } else { + let kzg_commitments = block.message().body().blob_kzg_commitments().unwrap(); + if kzg_commitments.is_empty() { + return vec![]; + } + + let kzg_commitments_inclusion_proof = block + .message() + .body() + .kzg_commitments_merkle_proof() + .unwrap(); + let signed_block_header = block.signed_block_header(); + // load the precomputed column sidecar to avoid computing them for every block in the tests. let template_data_columns = RuntimeVariableList::>::from_ssz_bytes( diff --git a/beacon_node/beacon_chain/src/test_utils/fixtures/test_data_column_sidecars_gloas.ssz b/beacon_node/beacon_chain/src/test_utils/fixtures/test_data_column_sidecars_gloas.ssz new file mode 100644 index 0000000000000000000000000000000000000000..554b27844b297c735bf8e16c0340f5d19d724af0 GIT binary patch literal 275968 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


j5uNBv0uPE^;9b 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 + if !spec.is_gloas_scheduled() { + return; + } + + let harness = get_harness(VALIDATOR_COUNT, spec.clone(), NodeCustodyType::Supernode); + harness.execution_block_generator().set_min_blob_count(1); + + // Build some chain depth. + let num_blocks = E::slots_per_epoch() as usize; + harness + .extend_chain( + num_blocks, + BlockStrategy::OnCanonicalHead, + AttestationStrategy::AllValidators, + ) + .await; + + harness.advance_slot(); + let slot = harness.get_current_slot(); + + // Produce a Gloas block via the harness. This caches envelope + blobs. + let state = harness.get_current_state(); + let (block_contents, opt_envelope, _post_state) = + harness.make_block_with_envelope(state, slot).await; + let signed_block = &block_contents.0; + + assert!( + opt_envelope.is_some(), + "Gloas block production should produce an envelope" + ); + + // Verify the block has blob commitments in the bid. + let bid = signed_block + .message() + .body() + .signed_execution_payload_bid() + .expect("Gloas block should have a payload bid"); + assert!( + !bid.message.blob_kzg_commitments.is_empty(), + "Block should have blob KZG commitments" + ); + + // Generate data columns from the block (using test fixtures, same as the harness does). + let data_column_sidecars = + generate_data_column_sidecars_from_block(signed_block, &harness.chain.spec); + assert_eq!( + data_column_sidecars.len(), + E::number_of_columns(), + "Should produce the correct number of data columns" + ); + + // Verify all columns are Gloas-format. + for col in &data_column_sidecars { + assert!( + col.as_gloas().is_ok(), + "Data column sidecar should be Gloas variant" + ); + let gloas_col = col.as_gloas().expect("should be Gloas sidecar"); + assert_eq!(gloas_col.beacon_block_root, signed_block.canonical_root()); + assert_eq!(gloas_col.slot, slot); + } + + // End-to-end DA flow (process_block → process_envelope → process_rpc_custody_columns) + // is not exercised here: Gloas blocks are not gated on columns at block-import time + // and the envelope/column gating belongs in a dedicated test once the DA path matures. +} + // Regression test for verify_header_signature bug: it uses head_fork() which is wrong for fork blocks #[tokio::test] async fn verify_header_signature_fork_block_bug() { diff --git a/beacon_node/beacon_chain/tests/prepare_payload.rs b/beacon_node/beacon_chain/tests/prepare_payload.rs index dc4f999eb2..1d23990b80 100644 --- a/beacon_node/beacon_chain/tests/prepare_payload.rs +++ b/beacon_node/beacon_chain/tests/prepare_payload.rs @@ -573,3 +573,121 @@ async fn prepare_payload_on_fork_boundary( advanced state" ); } + +#[tokio::test] +async fn gloas_block_production_caches_blobs_for_column_publishing() { + use beacon_chain::ProduceBlockVerification; + use beacon_chain::graffiti_calculator::GraffitiSettings; + use eth2::types::GraffitiPolicy; + + let spec = Arc::new(test_spec::()); + if !spec.fork_name_at_slot::(Slot::new(0)).gloas_enabled() { + return; + } + + let db_path = tempdir().unwrap(); + let store = get_store(&db_path, spec.clone()); + let harness = get_harness(store.clone(), LOW_VALIDATOR_COUNT); + + // Configure the mock EL to produce at least 1 blob per block. + harness.execution_block_generator().set_min_blob_count(1); + + // Extend the chain a few slots to get past genesis. + harness + .extend_chain( + (E::slots_per_epoch() as usize) + 1, + BlockStrategy::OnCanonicalHead, + AttestationStrategy::AllValidators, + ) + .await; + + harness.advance_slot(); + let slot = harness.get_current_slot(); + + // Produce a Gloas block directly via produce_block_on_state_gloas so we can + // inspect the pending cache before it's consumed. + let mut state = harness.get_current_state(); + complete_state_advance(&mut state, None, slot, &spec).unwrap(); + state.build_caches(&spec).unwrap(); + + let proposer_index = state.get_beacon_proposer_index(slot, &spec).unwrap(); + let randao_reveal = harness.sign_randao_reveal(&state, proposer_index, slot); + + let (parent_payload_status, parent_envelope) = { + let head = harness.chain.canonical_head.cached_head(); + ( + head.head_payload_status(), + head.snapshot.execution_envelope.clone(), + ) + }; + + let graffiti_settings = GraffitiSettings::new( + Some(Graffiti::default()), + Some(GraffitiPolicy::PreserveUserGraffiti), + ); + + let (_block, _post_state, _value) = harness + .chain + .produce_block_on_state_gloas( + state, + None, + parent_payload_status, + parent_envelope, + slot, + randao_reveal, + graffiti_settings, + ProduceBlockVerification::VerifyRandao, + ) + .await + .unwrap(); + + // The envelope + blobs should now be in the pending cache. + assert!( + harness + .chain + .pending_payload_envelopes + .read() + .contains(slot), + "Pending cache should contain an envelope for the produced slot" + ); + + // Take the blobs from the cache — this is what publish_execution_payload_envelope does. + let blobs = harness + .chain + .pending_payload_envelopes + .write() + .take_blobs(slot); + + assert!( + blobs.is_some(), + "Blobs should be cached alongside the envelope" + ); + + let blobs = blobs.unwrap(); + assert!( + !blobs.is_empty(), + "Blobs should be non-empty when min_blob_count >= 1" + ); + + // Verify take_blobs is consume-once. + let second_take = harness + .chain + .pending_payload_envelopes + .write() + .take_blobs(slot); + assert!( + second_take.is_none(), + "Blobs should only be consumable once" + ); + + // The envelope should still be in the cache after taking blobs. + assert!( + harness + .chain + .pending_payload_envelopes + .read() + .get(slot) + .is_some(), + "Envelope should remain in cache after taking blobs" + ); +} diff --git a/beacon_node/http_api/src/beacon/execution_payload_envelope.rs b/beacon_node/http_api/src/beacon/execution_payload_envelope.rs index 382b967b43..06a5915c08 100644 --- a/beacon_node/http_api/src/beacon/execution_payload_envelope.rs +++ b/beacon_node/http_api/src/beacon/execution_payload_envelope.rs @@ -1,10 +1,12 @@ use crate::block_id::BlockId; +use crate::publish_blocks::publish_column_sidecars; use crate::task_spawner::{Priority, TaskSpawner}; use crate::utils::{ChainFilter, EthV1Filter, NetworkTxFilter, ResponseFilter, TaskSpawnerFilter}; use crate::version::{ ResponseIncludesVersion, add_consensus_version_header, add_ssz_content_type_header, execution_optimistic_finalized_beacon_response, }; +use beacon_chain::data_column_verification::{GossipDataColumnError, GossipVerifiedDataColumn}; use beacon_chain::{BeaconChain, BeaconChainTypes}; use bytes::Bytes; use eth2::types as api_types; @@ -12,10 +14,11 @@ use eth2::{CONTENT_TYPE_HEADER, SSZ_CONTENT_TYPE_HEADER}; use lighthouse_network::PubsubMessage; use network::NetworkMessage; use ssz::{Decode, Encode}; +use std::future::Future; use std::sync::Arc; use tokio::sync::mpsc::UnboundedSender; -use tracing::{info, warn}; -use types::SignedExecutionPayloadEnvelope; +use tracing::{debug, error, info, warn}; +use types::{EthSpec, SignedExecutionPayloadEnvelope}; use warp::{ Filter, Rejection, Reply, hyper::{Body, Response}, @@ -85,7 +88,9 @@ pub(crate) fn post_beacon_execution_payload_envelope( ) .boxed() } -/// Publishes a signed execution payload envelope to the network. +/// Publishes a signed execution payload envelope to the network. Implements +/// `POST /eth/v1/beacon/execution_payload_envelope` per the in-flight beacon-APIs PR +/// . pub async fn publish_execution_payload_envelope( envelope: SignedExecutionPayloadEnvelope, chain: Arc>, @@ -109,7 +114,24 @@ pub async fn publish_execution_payload_envelope( "Publishing signed execution payload envelope to network" ); - // Publish to the network + let blobs_and_proofs = chain.pending_payload_envelopes.write().take_blobs(slot); + + // Spawn the column-build task (CPU-bound KZG cell-and-proof computation) before + // publishing the envelope so it runs in parallel with envelope gossip, narrowing + // the window in which peers see envelope-without-columns. If envelope publication + // fails below, dropping this future drops the spawned `JoinHandle` (the running + // closure on the blocking pool finishes and is then discarded — no work cancellation). + let column_build_future = match blobs_and_proofs { + Some(blobs) if !blobs.is_empty() => Some(spawn_build_gloas_data_columns_task( + &chain, + beacon_block_root, + slot, + blobs, + )?), + _ => None, + }; + + // Publish the envelope to the network. crate::utils::publish_pubsub_message( network_tx, PubsubMessage::ExecutionPayload(Box::new(envelope)), @@ -121,9 +143,130 @@ pub async fn publish_execution_payload_envelope( ) })?; + // From here on the envelope is on the wire. `take_blobs` already consumed the cache + // entry, so a retry would not republish columns; returning Err would mislead the + // caller. Log column-build/publish failures and fall through to `Ok`. + if let Some(column_build_future) = column_build_future { + let gossip_verified_columns = match column_build_future.await { + Ok(columns) => columns, + Err(e) => { + error!( + %slot, + error = ?e, + "Failed to build data columns after envelope publication" + ); + return Ok(warp::reply().into_response()); + } + }; + + if !gossip_verified_columns.is_empty() { + if let Err(e) = publish_column_sidecars(network_tx, &gossip_verified_columns, &chain) { + error!( + %slot, + error = ?e, + "Failed to publish data column sidecars after envelope publication" + ); + return Ok(warp::reply().into_response()); + } + + let epoch = slot.epoch(T::EthSpec::slots_per_epoch()); + let sampling_column_indices = chain.sampling_columns_for_epoch(epoch); + let sampling_columns = gossip_verified_columns + .into_iter() + .filter(|col| sampling_column_indices.contains(&col.index())) + .collect::>(); + + // Local processing only — envelope already broadcast, so log and fall through. + if !sampling_columns.is_empty() + && let Err(e) = + Box::pin(chain.process_gossip_data_columns(sampling_columns, || Ok(()))).await + { + error!( + %slot, + error = ?e, + "Failed to process sampling data columns during envelope publication" + ); + } + } + } + Ok(warp::reply().into_response()) } +fn spawn_build_gloas_data_columns_task( + chain: &Arc>, + beacon_block_root: types::Hash256, + slot: types::Slot, + blobs: types::BlobsList, +) -> Result>, Rejection>>, Rejection> { + let chain_for_build = chain.clone(); + let handle = chain + .task_executor + .spawn_blocking_handle( + move || build_gloas_data_columns(&chain_for_build, beacon_block_root, slot, &blobs), + "build_gloas_data_columns", + ) + .ok_or_else(|| warp_utils::reject::custom_server_error("runtime shutdown".to_string()))?; + + Ok(async move { + handle + .await + .map_err(|_| warp_utils::reject::custom_server_error("join error".to_string()))? + }) +} + +fn build_gloas_data_columns( + chain: &BeaconChain, + beacon_block_root: types::Hash256, + slot: types::Slot, + blobs: &types::BlobsList, +) -> Result>, Rejection> { + let blob_refs: Vec<_> = blobs.iter().collect(); + let data_column_sidecars = beacon_chain::kzg_utils::blobs_to_data_column_sidecars_gloas( + &blob_refs, + beacon_block_root, + slot, + &chain.kzg, + &chain.spec, + ) + .map_err(|e| { + error!( + error = ?e, + %slot, + "Failed to build data column sidecars for envelope" + ); + warp_utils::reject::custom_server_error(format!("{e:?}")) + })?; + + let gossip_verified_columns = data_column_sidecars + .into_iter() + .filter_map(|col| { + let index = *col.index(); + match GossipVerifiedDataColumn::new_for_block_publishing(col, chain) { + Ok(verified) => Some(verified), + Err(GossipDataColumnError::PriorKnownUnpublished) => None, + Err(e) => { + warn!( + %slot, + column_index = index, + error = ?e, + "Locally-built data column failed gossip verification" + ); + None + } + } + }) + .collect::>(); + + debug!( + %slot, + column_count = gossip_verified_columns.len(), + "Built data columns for envelope publication" + ); + + Ok(gossip_verified_columns) +} + // TODO(gloas): add tests for this endpoint once we support importing payloads into the db // GET beacon/execution_payload_envelope/{block_id} pub(crate) fn get_beacon_execution_payload_envelope( diff --git a/beacon_node/http_api/src/publish_blocks.rs b/beacon_node/http_api/src/publish_blocks.rs index 6b65995a73..644ade956a 100644 --- a/beacon_node/http_api/src/publish_blocks.rs +++ b/beacon_node/http_api/src/publish_blocks.rs @@ -494,7 +494,7 @@ fn publish_blob_sidecars( .map_err(|_| BlockError::BeaconChainError(Box::new(BeaconChainError::UnableToPublish))) } -fn publish_column_sidecars( +pub(crate) fn publish_column_sidecars( sender_clone: &UnboundedSender>, data_column_sidecars: &[GossipVerifiedDataColumn], chain: &BeaconChain, From e8c865dcc6332c5b0b0f52ee5b1587b184c608a7 Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Tue, 28 Apr 2026 23:50:07 +0200 Subject: [PATCH 09/12] Gossip reprocessed payload envelopes that are timely (#9210) Payloads from the reprocess queue should be gossiped after import if they are still timely. In devnets this happens frequently since there are many cases where the envelope arrives before the block Co-Authored-By: Eitan Seri-Levi --- .../gossip_methods.rs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/beacon_node/network/src/network_beacon_processor/gossip_methods.rs b/beacon_node/network/src/network_beacon_processor/gossip_methods.rs index 29306c198d..0135d7f5dd 100644 --- a/beacon_node/network/src/network_beacon_processor/gossip_methods.rs +++ b/beacon_node/network/src/network_beacon_processor/gossip_methods.rs @@ -3627,6 +3627,23 @@ impl NetworkBeaconProcessor { self.propagate_if_timely(is_timely, message_id, peer_id) } + /// If a payload envelope is still valid with respect to the current time (i.e., its slot + /// matches the current slot), propagate it on gossip. Otherwise, ignore it. + fn propagate_envelope_if_timely( + &self, + envelope_slot: Slot, + message_id: MessageId, + peer_id: PeerId, + ) { + let is_timely = self + .chain + .slot_clock + .now() + .is_some_and(|current_slot| envelope_slot == current_slot); + + self.propagate_if_timely(is_timely, message_id, peer_id) + } + /// If a sync committee signature or sync committee contribution is still valid with respect to /// the current time (i.e., timely), propagate it on gossip. Otherwise, ignore it. fn propagate_sync_message_if_timely( @@ -3831,6 +3848,12 @@ impl NetworkBeaconProcessor { let process_fn = Box::pin(async move { match chain.verify_envelope_for_gossip(envelope).await { Ok(verified_envelope) => { + let envelope_slot = verified_envelope.signed_envelope.slot(); + inner_self.propagate_envelope_if_timely( + envelope_slot, + message_id, + peer_id, + ); inner_self .process_gossip_verified_execution_payload_envelope( peer_id, From 16132a369417f6ee35eb7fb7ae6c5e714dc8cad4 Mon Sep 17 00:00:00 2001 From: jking-aus <72330194+jking-aus@users.noreply.github.com> Date: Wed, 29 Apr 2026 10:23:24 +0200 Subject: [PATCH 10/12] Spec v1.7.0-alpha.6 and Gloas genesis (#9190) Co-Authored-By: Josh King Co-Authored-By: Jimmy Chen Co-Authored-By: Michael Sproul --- beacon_node/beacon_chain/src/beacon_chain.rs | 3 - .../src/block_production/gloas.rs | 3 +- .../src/payload_bid_verification/tests.rs | 1 + .../src/payload_envelope_streamer/tests.rs | 1 + .../gossip_verified_envelope.rs | 1 + .../payload_notifier.rs | 2 +- .../src/pending_payload_envelopes.rs | 1 + .../gossip_verified_proposer_preferences.rs | 4 +- .../proposer_preference_cache.rs | 21 +++-- .../tests.rs | 10 ++- .../beacon_chain/tests/prepare_payload.rs | 5 -- .../src/network_beacon_processor/tests.rs | 1 + consensus/proto_array/src/proto_array.rs | 28 +------ .../src/envelope_processing.rs | 13 +++ consensus/state_processing/src/genesis.rs | 35 ++++---- .../src/per_block_processing.rs | 11 +-- .../src/per_block_processing/withdrawals.rs | 9 +-- .../src/per_epoch_processing/single_pass.rs | 20 ++++- consensus/types/configs/mainnet.yaml | 14 ++-- consensus/types/configs/minimal.yaml | 14 ++-- consensus/types/presets/minimal/gloas.yaml | 4 +- .../types/src/block/signed_beacon_block.rs | 6 +- .../types/src/builder/proposer_preferences.rs | 3 +- consensus/types/src/core/chain_spec.rs | 65 ++++++++++++++- consensus/types/src/core/eth_spec.rs | 2 +- .../execution/execution_payload_envelope.rs | 2 + consensus/types/src/state/beacon_state.rs | 80 +++++++++++++++++-- testing/ef_tests/Makefile | 2 +- testing/ef_tests/check_all_files_accessed.py | 1 + testing/ef_tests/download_test_vectors.sh | 2 +- .../ef_tests/src/cases/epoch_processing.rs | 21 ++++- testing/ef_tests/src/cases/operations.rs | 43 ++++++++++ testing/ef_tests/src/handler.rs | 4 + testing/ef_tests/src/lib.rs | 7 +- testing/ef_tests/tests/tests.rs | 27 ++++++- 35 files changed, 349 insertions(+), 117 deletions(-) diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index 9da64888c2..ccb12a353d 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -5023,11 +5023,8 @@ impl BeaconChain { } .ok_or(Error::MissingExecutionPayloadEnvelope(parent_block_root))?; - let parent_bid = advanced_state.latest_execution_payload_bid()?.clone(); - apply_parent_execution_payload( &mut advanced_state, - &parent_bid, &envelope.message.execution_requests, &self.spec, ) diff --git a/beacon_node/beacon_chain/src/block_production/gloas.rs b/beacon_node/beacon_chain/src/block_production/gloas.rs index 79ea78ce4a..a02963c358 100644 --- a/beacon_node/beacon_chain/src/block_production/gloas.rs +++ b/beacon_node/beacon_chain/src/block_production/gloas.rs @@ -623,11 +623,13 @@ impl BeaconChain { // For trustless building, the builder will provide the envelope separately. if let Some(payload_data) = payload_data { let beacon_block_root = block.tree_hash_root(); + let parent_beacon_block_root = block.parent_root(); let execution_payload_envelope = ExecutionPayloadEnvelope { payload: payload_data.payload, execution_requests: payload_data.execution_requests, builder_index: payload_data.builder_index, beacon_block_root, + parent_beacon_block_root, }; let signed_envelope = SignedExecutionPayloadEnvelope { @@ -854,7 +856,6 @@ fn get_execution_payload_gloas( let mut withdrawals_state = state.clone(); apply_parent_execution_payload( &mut withdrawals_state, - parent_bid, &envelope.message.execution_requests, spec, )?; diff --git a/beacon_node/beacon_chain/src/payload_bid_verification/tests.rs b/beacon_node/beacon_chain/src/payload_bid_verification/tests.rs index 98863a49d5..b7b77d5d2a 100644 --- a/beacon_node/beacon_chain/src/payload_bid_verification/tests.rs +++ b/beacon_node/beacon_chain/src/payload_bid_verification/tests.rs @@ -256,6 +256,7 @@ fn make_signed_preferences( validator_index, fee_recipient, gas_limit, + ..ProposerPreferences::default() }, signature: Signature::empty(), }) diff --git a/beacon_node/beacon_chain/src/payload_envelope_streamer/tests.rs b/beacon_node/beacon_chain/src/payload_envelope_streamer/tests.rs index be3dbf33ce..be763b4ee2 100644 --- a/beacon_node/beacon_chain/src/payload_envelope_streamer/tests.rs +++ b/beacon_node/beacon_chain/src/payload_envelope_streamer/tests.rs @@ -72,6 +72,7 @@ fn build_chain( execution_requests: Default::default(), builder_index: 0, beacon_block_root: block_root, + parent_beacon_block_root: Hash256::ZERO, }, signature: Signature::empty(), }) diff --git a/beacon_node/beacon_chain/src/payload_envelope_verification/gossip_verified_envelope.rs b/beacon_node/beacon_chain/src/payload_envelope_verification/gossip_verified_envelope.rs index 80724e2b00..a20963302b 100644 --- a/beacon_node/beacon_chain/src/payload_envelope_verification/gossip_verified_envelope.rs +++ b/beacon_node/beacon_chain/src/payload_envelope_verification/gossip_verified_envelope.rs @@ -339,6 +339,7 @@ mod tests { execution_requests: ExecutionRequests::default(), builder_index, beacon_block_root: Hash256::ZERO, + parent_beacon_block_root: Hash256::ZERO, } } diff --git a/beacon_node/beacon_chain/src/payload_envelope_verification/payload_notifier.rs b/beacon_node/beacon_chain/src/payload_envelope_verification/payload_notifier.rs index df21d33493..eb5e13b0cc 100644 --- a/beacon_node/beacon_chain/src/payload_envelope_verification/payload_notifier.rs +++ b/beacon_node/beacon_chain/src/payload_envelope_verification/payload_notifier.rs @@ -87,7 +87,7 @@ impl PayloadNotifier { Ok(NewPayloadRequest::Gloas(NewPayloadRequestGloas { execution_payload: &envelope.message.payload, versioned_hashes, - parent_beacon_block_root: block.message().parent_root(), + parent_beacon_block_root: envelope.message.parent_beacon_block_root, execution_requests: &envelope.message.execution_requests, })) } diff --git a/beacon_node/beacon_chain/src/pending_payload_envelopes.rs b/beacon_node/beacon_chain/src/pending_payload_envelopes.rs index 293553ef54..8f7568d017 100644 --- a/beacon_node/beacon_chain/src/pending_payload_envelopes.rs +++ b/beacon_node/beacon_chain/src/pending_payload_envelopes.rs @@ -105,6 +105,7 @@ mod tests { execution_requests: ExecutionRequests::default(), builder_index: 0, beacon_block_root: Hash256::ZERO, + parent_beacon_block_root: Hash256::ZERO, }, blobs: None, } diff --git a/beacon_node/beacon_chain/src/proposer_preferences_verification/gossip_verified_proposer_preferences.rs b/beacon_node/beacon_chain/src/proposer_preferences_verification/gossip_verified_proposer_preferences.rs index 8ea095743f..e97dab56d7 100644 --- a/beacon_node/beacon_chain/src/proposer_preferences_verification/gossip_verified_proposer_preferences.rs +++ b/beacon_node/beacon_chain/src/proposer_preferences_verification/gossip_verified_proposer_preferences.rs @@ -64,6 +64,7 @@ impl GossipVerifiedProposerPreferences { ctx: &GossipVerificationContext<'_, T>, ) -> Result { let proposal_slot = signed_preferences.message.proposal_slot; + let checkpoint_root = signed_preferences.message.checkpoint_root; let validator_index = signed_preferences.message.validator_index; let cached_head = ctx.canonical_head.cached_head(); let current_slot = ctx @@ -74,7 +75,7 @@ impl GossipVerifiedProposerPreferences { if ctx .gossip_verified_proposer_preferences_cache - .get_seen_validator(&proposal_slot, validator_index) + .get_seen_validator(&proposal_slot, checkpoint_root, validator_index) { return Err(ProposerPreferencesError::AlreadySeen { validator_index, @@ -162,6 +163,7 @@ mod tests { fn make_preferences(proposal_slot: Slot, validator_index: u64) -> ProposerPreferences { ProposerPreferences { + checkpoint_root: types::Hash256::ZERO, proposal_slot, validator_index, fee_recipient: Address::ZERO, diff --git a/beacon_node/beacon_chain/src/proposer_preferences_verification/proposer_preference_cache.rs b/beacon_node/beacon_chain/src/proposer_preferences_verification/proposer_preference_cache.rs index 69337f2a83..e2b0c40fb5 100644 --- a/beacon_node/beacon_chain/src/proposer_preferences_verification/proposer_preference_cache.rs +++ b/beacon_node/beacon_chain/src/proposer_preferences_verification/proposer_preference_cache.rs @@ -5,11 +5,11 @@ use std::{ use crate::proposer_preferences_verification::gossip_verified_proposer_preferences::GossipVerifiedProposerPreferences; use parking_lot::RwLock; -use types::{SignedProposerPreferences, Slot}; +use types::{Hash256, SignedProposerPreferences, Slot}; pub struct GossipVerifiedProposerPreferenceCache { preferences: RwLock>, - seen: RwLock>>, + seen: RwLock>>, } impl Default for GossipVerifiedProposerPreferenceCache { @@ -34,21 +34,27 @@ impl GossipVerifiedProposerPreferenceCache { self.preferences.write().insert(slot, preferences); } - pub fn get_seen_validator(&self, slot: &Slot, validator_index: u64) -> bool { + pub fn get_seen_validator( + &self, + slot: &Slot, + checkpoint_root: Hash256, + validator_index: u64, + ) -> bool { self.seen .read() .get(slot) - .is_some_and(|seen| seen.contains(&validator_index)) + .is_some_and(|seen| seen.contains(&(checkpoint_root, validator_index))) } pub fn insert_seen_validator(&self, preferences: &GossipVerifiedProposerPreferences) { let slot = preferences.signed_preferences.message.proposal_slot; + let checkpoint_root = preferences.signed_preferences.message.checkpoint_root; let validator_index = preferences.signed_preferences.message.validator_index; self.seen .write() .entry(slot) .or_default() - .insert(validator_index); + .insert((checkpoint_root, validator_index)); } pub fn prune(&self, current_slot: Slot) { @@ -77,6 +83,7 @@ mod tests { validator_index, fee_recipient: Address::ZERO, gas_limit: 30_000_000, + ..ProposerPreferences::default() }, signature: Signature::empty(), }), @@ -97,11 +104,11 @@ mod tests { for slot in [1, 2, 3, 7] { assert!(cache.get_preferences(&Slot::new(slot)).is_none()); - assert!(!cache.get_seen_validator(&Slot::new(slot), slot)); + assert!(!cache.get_seen_validator(&Slot::new(slot), types::Hash256::ZERO, slot)); } for slot in [8, 9, 10] { assert!(cache.get_preferences(&Slot::new(slot)).is_some()); - assert!(cache.get_seen_validator(&Slot::new(slot), slot)); + assert!(cache.get_seen_validator(&Slot::new(slot), types::Hash256::ZERO, slot)); } } } diff --git a/beacon_node/beacon_chain/src/proposer_preferences_verification/tests.rs b/beacon_node/beacon_chain/src/proposer_preferences_verification/tests.rs index 2f1b24fcbb..d3974baa8b 100644 --- a/beacon_node/beacon_chain/src/proposer_preferences_verification/tests.rs +++ b/beacon_node/beacon_chain/src/proposer_preferences_verification/tests.rs @@ -131,6 +131,7 @@ fn make_signed_preferences( validator_index, fee_recipient: Address::ZERO, gas_limit: 30_000_000, + ..ProposerPreferences::default() }, signature: Signature::empty(), }) @@ -230,10 +231,11 @@ fn correct_proposer_bad_signature() { result, Err(ProposerPreferencesError::BadSignature) )); - assert!( - !ctx.preferences_cache - .get_seen_validator(&slot, actual_proposer) - ); + assert!(!ctx.preferences_cache.get_seen_validator( + &slot, + types::Hash256::ZERO, + actual_proposer + )); assert!(ctx.preferences_cache.get_preferences(&slot).is_none()); } diff --git a/beacon_node/beacon_chain/tests/prepare_payload.rs b/beacon_node/beacon_chain/tests/prepare_payload.rs index 1d23990b80..549f15a13f 100644 --- a/beacon_node/beacon_chain/tests/prepare_payload.rs +++ b/beacon_node/beacon_chain/tests/prepare_payload.rs @@ -229,9 +229,6 @@ async fn prepare_payload_generic( // `apply_parent_execution_payload`. let cached_head = harness.chain.canonical_head.cached_head(); let unadvanced_empty_state = &cached_head.snapshot.beacon_state; - let parent_bid = unadvanced_empty_state - .latest_execution_payload_bid() - .unwrap(); let mut advanced_empty_state = unadvanced_empty_state.clone(); complete_state_advance(&mut advanced_empty_state, None, prepare_slot, &spec).unwrap(); @@ -239,7 +236,6 @@ async fn prepare_payload_generic( let mut unadvanced_full_state = unadvanced_empty_state.clone(); apply_parent_execution_payload( &mut unadvanced_full_state, - parent_bid, &envelope.message.execution_requests, &spec, ) @@ -248,7 +244,6 @@ async fn prepare_payload_generic( let mut advanced_full_state = advanced_empty_state.clone(); apply_parent_execution_payload( &mut advanced_full_state, - parent_bid, &envelope.message.execution_requests, &spec, ) diff --git a/beacon_node/network/src/network_beacon_processor/tests.rs b/beacon_node/network/src/network_beacon_processor/tests.rs index 76c6ba812d..c4e7f8f8d1 100644 --- a/beacon_node/network/src/network_beacon_processor/tests.rs +++ b/beacon_node/network/src/network_beacon_processor/tests.rs @@ -2131,6 +2131,7 @@ fn make_test_payload_envelope( execution_requests: ExecutionRequests::default(), builder_index: 0, beacon_block_root, + parent_beacon_block_root: Hash256::ZERO, }, signature: Signature::empty(), } diff --git a/consensus/proto_array/src/proto_array.rs b/consensus/proto_array/src/proto_array.rs index 8548974054..78f5026689 100644 --- a/consensus/proto_array/src/proto_array.rs +++ b/consensus/proto_array/src/proto_array.rs @@ -23,14 +23,6 @@ use types::{ four_byte_option_impl!(four_byte_option_usize, usize); four_byte_option_impl!(four_byte_option_checkpoint, Checkpoint); -fn all_true_bitvector() -> BitVector { - let mut bv = BitVector::new(); - for i in 0..bv.len() { - let _ = bv.set(i, true); - } - bv -} - /// Defines an operation which may invalidate the `execution_status` of some nodes. #[derive(Clone, Debug)] pub enum InvalidationOperation { @@ -568,10 +560,8 @@ impl ProtoArray { ProtoNode::V29(v29) => { // Both parent and child are Gloas blocks. The parent is full if the // block hash in the parent node matches the parent block hash in the - // child bid and the parent block isn't the genesis block. - if v29.execution_payload_block_hash != ExecutionBlockHash::zero() - && execution_payload_parent_hash == v29.execution_payload_block_hash - { + // child bid. + if execution_payload_parent_hash == v29.execution_payload_block_hash { PayloadStatus::Full } else { PayloadStatus::Empty @@ -613,18 +603,8 @@ impl ProtoArray { full_payload_weight: 0, execution_payload_block_hash, execution_payload_parent_hash, - // Per spec `get_forkchoice_store`: the anchor block's PTC votes are - // initialized to all-True. - payload_timeliness_votes: if is_anchor { - all_true_bitvector() - } else { - BitVector::default() - }, - payload_data_availability_votes: if is_anchor { - all_true_bitvector() - } else { - BitVector::default() - }, + payload_timeliness_votes: BitVector::default(), + payload_data_availability_votes: BitVector::default(), payload_received: false, proposer_index, // Spec: `record_block_timeliness` + `get_forkchoice_store`. diff --git a/consensus/state_processing/src/envelope_processing.rs b/consensus/state_processing/src/envelope_processing.rs index 8ea96390e3..3da4d1e9d6 100644 --- a/consensus/state_processing/src/envelope_processing.rs +++ b/consensus/state_processing/src/envelope_processing.rs @@ -26,6 +26,12 @@ pub enum EnvelopeProcessingError { envelope_root: Hash256, block_header_root: Hash256, }, + /// Envelope's `parent_beacon_block_root` doesn't match the parent root of the latest + /// block header. + ParentBeaconBlockRootMismatch { + envelope: Hash256, + state: Hash256, + }, /// Envelope doesn't match latest beacon block slot SlotMismatch { envelope_slot: Slot, @@ -126,6 +132,13 @@ pub fn verify_execution_payload_envelope( block_header_root: latest_block_header_root, } ); + envelope_verify!( + envelope.parent_beacon_block_root == state.latest_block_header().parent_root, + EnvelopeProcessingError::ParentBeaconBlockRootMismatch { + envelope: envelope.parent_beacon_block_root, + state: state.latest_block_header().parent_root, + } + ); envelope_verify!( envelope.slot() == state.slot(), EnvelopeProcessingError::SlotMismatch { diff --git a/consensus/state_processing/src/genesis.rs b/consensus/state_processing/src/genesis.rs index 9dfbc87b48..c643ad56e3 100644 --- a/consensus/state_processing/src/genesis.rs +++ b/consensus/state_processing/src/genesis.rs @@ -175,13 +175,11 @@ pub fn initialize_beacon_state_from_eth1( bid.parent_block_hash = el_genesis_hash; bid.block_hash = ExecutionBlockHash::default(); - // Update latest_block_header to reflect the Gloas genesis block body which contains - // the EL genesis hash in the signed_execution_payload_bid. This is needed because - // BeaconState::new() created the header from BeaconBlock::empty() which has zero bid - // fields, but the spec requires the genesis block's bid to contain the EL block hash - // and the tree hash root of empty ExecutionRequests. - let block = genesis_block(&state, spec)?; - state.latest_block_header_mut().body_root = block.body_root(); + // Update the `latest_block_header.body_root` so that it matches the body of the + // Gloas genesis block, which embeds `state.latest_execution_payload_bid` in its + // `signed_execution_payload_bid` field (see `genesis_block`). + let genesis_body_root = genesis_block(&state, spec)?.body_root(); + state.latest_block_header_mut().body_root = genesis_body_root; } // Now that we have our validators, initialize the caches (including the committees) @@ -193,24 +191,23 @@ pub fn initialize_beacon_state_from_eth1( Ok(state) } -/// Create an unsigned genesis `BeaconBlock` whose body matches the genesis state. +/// Create an unsigned genesis `BeaconBlock`. /// -/// For Gloas, the block's `signed_execution_payload_bid` is populated from the state's -/// `latest_execution_payload_bid` so that the body root is consistent with -/// `state.latest_block_header.body_root`. +/// Per spec, the genesis block body is empty (all default fields) except for Gloas, +/// where `body.signed_execution_payload_bid.message` is initialised from +/// `state.latest_execution_payload_bid` so that the first post-genesis proposer can +/// build on the correct execution layer head. /// -/// The returned block has `state_root == Hash256::ZERO`; callers that need the real -/// state root should set it themselves. +/// `state.latest_block_header.body_root` is set from this same block's body, so the +/// two must stay in sync. pub fn genesis_block( - genesis_state: &BeaconState, + state: &BeaconState, spec: &ChainSpec, ) -> Result, BeaconStateError> { let mut block = BeaconBlock::empty(spec); - if let Ok(block) = block.as_gloas_mut() { - let state_bid = genesis_state.latest_execution_payload_bid()?; - let bid = &mut block.body.signed_execution_payload_bid.message; - bid.block_hash = state_bid.block_hash; - bid.execution_requests_root = state_bid.execution_requests_root; + if let BeaconBlock::Gloas(ref mut gloas_block) = block { + let bid = state.latest_execution_payload_bid()?.clone(); + gloas_block.body.signed_execution_payload_bid.message = bid; } Ok(block) } diff --git a/consensus/state_processing/src/per_block_processing.rs b/consensus/state_processing/src/per_block_processing.rs index 71ad394ee6..f13f2a339b 100644 --- a/consensus/state_processing/src/per_block_processing.rs +++ b/consensus/state_processing/src/per_block_processing.rs @@ -555,13 +555,10 @@ pub fn process_parent_execution_payload( state: &mut BeaconState, - parent_bid: &ExecutionPayloadBid, requests: &ExecutionRequests, spec: &ChainSpec, ) -> Result<(), BlockProcessingError> { + let parent_bid = state.latest_execution_payload_bid()?.clone(); let parent_slot = parent_bid.slot; let parent_epoch = parent_slot.epoch(E::slots_per_epoch()); diff --git a/consensus/state_processing/src/per_block_processing/withdrawals.rs b/consensus/state_processing/src/per_block_processing/withdrawals.rs index 3b14e904c4..8a09e35cdf 100644 --- a/consensus/state_processing/src/per_block_processing/withdrawals.rs +++ b/consensus/state_processing/src/per_block_processing/withdrawals.rs @@ -9,8 +9,8 @@ use safe_arith::{SafeArith, SafeArithIter}; use tree_hash::TreeHash; use types::{ AbstractExecPayload, BeaconState, BeaconStateError, ChainSpec, EthSpec, ExecPayload, - ExecutionBlockHash, ExpectedWithdrawals, ExpectedWithdrawalsCapella, - ExpectedWithdrawalsElectra, ExpectedWithdrawalsGloas, Validator, Withdrawal, Withdrawals, + ExpectedWithdrawals, ExpectedWithdrawalsCapella, ExpectedWithdrawalsElectra, + ExpectedWithdrawalsGloas, Validator, Withdrawal, Withdrawals, }; /// Compute the next batch of withdrawals which should be included in a block. @@ -495,10 +495,7 @@ pub mod gloas { spec: &ChainSpec, ) -> Result<(), BlockProcessingError> { // Return early if the parent block is empty. - let is_genesis_block = *state.latest_block_hash()? == ExecutionBlockHash::default(); - let is_parent_block_empty = - *state.latest_block_hash()? != state.latest_execution_payload_bid()?.block_hash; - if is_genesis_block || is_parent_block_empty { + if *state.latest_block_hash()? != state.latest_execution_payload_bid()?.block_hash { return Ok(()); } diff --git a/consensus/state_processing/src/per_epoch_processing/single_pass.rs b/consensus/state_processing/src/per_epoch_processing/single_pass.rs index 976607aa76..881e6bb16c 100644 --- a/consensus/state_processing/src/per_epoch_processing/single_pass.rs +++ b/consensus/state_processing/src/per_epoch_processing/single_pass.rs @@ -962,7 +962,11 @@ fn compute_exit_epoch_and_update_churn( spec.compute_activation_exit_epoch(state_ctxt.current_epoch)?, ); - let per_epoch_churn = get_activation_exit_churn_limit(state_ctxt, spec)?; + let per_epoch_churn = if state_ctxt.fork_name.gloas_enabled() { + get_balance_churn_limit(state_ctxt, spec)? + } else { + get_activation_exit_churn_limit(state_ctxt, spec)? + }; // New epoch for exits let mut exit_balance_to_consume = if *earliest_exit_epoch_state < earliest_exit_epoch { per_epoch_churn @@ -991,17 +995,27 @@ fn get_activation_exit_churn_limit( state_ctxt: &StateContext, spec: &ChainSpec, ) -> Result { + let max_limit = if state_ctxt.fork_name.gloas_enabled() { + spec.max_per_epoch_activation_churn_limit_gloas + } else { + spec.max_per_epoch_activation_exit_churn_limit + }; Ok(std::cmp::min( - spec.max_per_epoch_activation_exit_churn_limit, + max_limit, get_balance_churn_limit(state_ctxt, spec)?, )) } fn get_balance_churn_limit(state_ctxt: &StateContext, spec: &ChainSpec) -> Result { let total_active_balance = state_ctxt.total_active_balance; + let quotient = if state_ctxt.fork_name.gloas_enabled() { + spec.churn_limit_quotient_gloas + } else { + spec.churn_limit_quotient + }; let churn = std::cmp::max( spec.min_per_epoch_churn_limit_electra, - total_active_balance.safe_div(spec.churn_limit_quotient)?, + total_active_balance.safe_div(quotient)?, ); Ok(churn.safe_sub(churn.safe_rem(spec.effective_balance_increment)?)?) diff --git a/consensus/types/configs/mainnet.yaml b/consensus/types/configs/mainnet.yaml index ab85bd9e71..25bf872a7a 100644 --- a/consensus/types/configs/mainnet.yaml +++ b/consensus/types/configs/mainnet.yaml @@ -105,12 +105,8 @@ CONTRIBUTION_DUE_BPS_GLOAS: 5000 PAYLOAD_ATTESTATION_DUE_BPS: 7500 # Heze -# 7500 basis points, 75% of SLOT_DURATION_MS -VIEW_FREEZE_CUTOFF_BPS: 7500 # 6667 basis points, ~67% of SLOT_DURATION_MS -INCLUSION_LIST_SUBMISSION_DUE_BPS: 6667 -# 9167 basis points, ~92% of SLOT_DURATION_MS -PROPOSER_INCLUSION_LIST_CUTOFF_BPS: 9167 +INCLUSION_LIST_DUE_BPS: 6667 # Validator cycle # --------------------------------------------------------------- @@ -135,6 +131,14 @@ MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA: 128000000000 # 2**8 * 10**9 (= 256,000,000,000) Gwei MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT: 256000000000 +# Gloas +# 2**15 (= 32,768) +CHURN_LIMIT_QUOTIENT_GLOAS: 32768 +# 2**16 (= 65,536) +CONSOLIDATION_CHURN_LIMIT_QUOTIENT: 65536 +# 2**8 * 10**9 (= 256,000,000,000) Gwei +MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT_GLOAS: 256000000000 + # Fork choice # --------------------------------------------------------------- # 40% diff --git a/consensus/types/configs/minimal.yaml b/consensus/types/configs/minimal.yaml index 8c0d7254fe..7251efc762 100644 --- a/consensus/types/configs/minimal.yaml +++ b/consensus/types/configs/minimal.yaml @@ -101,12 +101,8 @@ CONTRIBUTION_DUE_BPS_GLOAS: 5000 PAYLOAD_ATTESTATION_DUE_BPS: 7500 # Heze -# 7500 basis points, 75% of SLOT_DURATION_MS -VIEW_FREEZE_CUTOFF_BPS: 7500 # 6667 basis points, ~67% of SLOT_DURATION_MS -INCLUSION_LIST_SUBMISSION_DUE_BPS: 6667 -# 9167 basis points, ~92% of SLOT_DURATION_MS -PROPOSER_INCLUSION_LIST_CUTOFF_BPS: 9167 +INCLUSION_LIST_DUE_BPS: 6667 # Validator cycle # --------------------------------------------------------------- @@ -131,6 +127,14 @@ MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA: 64000000000 # [customized] 2**7 * 10**9 (= 128,000,000,000) Gwei MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT: 128000000000 +# Gloas +# [customized] 2**4 (= 16) +CHURN_LIMIT_QUOTIENT_GLOAS: 16 +# [customized] 2**5 (= 32) +CONSOLIDATION_CHURN_LIMIT_QUOTIENT: 32 +# [customized] 2**7 * 10**9 (= 128,000,000,000) Gwei +MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT_GLOAS: 128000000000 + # Fork choice # --------------------------------------------------------------- # 40% diff --git a/consensus/types/presets/minimal/gloas.yaml b/consensus/types/presets/minimal/gloas.yaml index 7ae61ddf97..559c2d46df 100644 --- a/consensus/types/presets/minimal/gloas.yaml +++ b/consensus/types/presets/minimal/gloas.yaml @@ -2,8 +2,8 @@ # Misc # --------------------------------------------------------------- -# [customized] 2**1 (= 2) validators -PTC_SIZE: 2 +# [customized] 2**4 (= 16) validators +PTC_SIZE: 16 # Max operations per block # --------------------------------------------------------------- diff --git a/consensus/types/src/block/signed_beacon_block.rs b/consensus/types/src/block/signed_beacon_block.rs index 23b01415c8..dd6f52426a 100644 --- a/consensus/types/src/block/signed_beacon_block.rs +++ b/consensus/types/src/block/signed_beacon_block.rs @@ -394,15 +394,13 @@ impl> SignedBeaconBlock /// `block_hash` from the parent beacon block's bid. If the parent beacon state is available /// this can alternatively be fetched from `state.latest_payload_bid`. /// - /// This function returns `false` for all blocks prior to Gloas and for the zero - /// `parent_block_hash`. + /// This function returns `false` for all blocks prior to Gloas. pub fn is_parent_block_full(&self, parent_block_hash: ExecutionBlockHash) -> bool { let Ok(signed_payload_bid) = self.message().body().signed_execution_payload_bid() else { // Prior to Gloas. return false; }; - parent_block_hash != ExecutionBlockHash::zero() - && signed_payload_bid.message.parent_block_hash == parent_block_hash + signed_payload_bid.message.parent_block_hash == parent_block_hash } } diff --git a/consensus/types/src/builder/proposer_preferences.rs b/consensus/types/src/builder/proposer_preferences.rs index 46dffdf3b7..0d2ba760d4 100644 --- a/consensus/types/src/builder/proposer_preferences.rs +++ b/consensus/types/src/builder/proposer_preferences.rs @@ -1,5 +1,5 @@ use crate::test_utils::TestRandom; -use crate::{Address, ForkName, SignedRoot, Slot}; +use crate::{Address, ForkName, Hash256, SignedRoot, Slot}; use bls::Signature; use context_deserialize::context_deserialize; use educe::Educe; @@ -16,6 +16,7 @@ use tree_hash_derive::TreeHash; #[context_deserialize(ForkName)] // https://github.com/ethereum/consensus-specs/blob/master/specs/gloas/p2p-interface.md#new-proposerpreferences pub struct ProposerPreferences { + pub checkpoint_root: Hash256, pub proposal_slot: Slot, pub validator_index: u64, pub fee_recipient: Address, diff --git a/consensus/types/src/core/chain_spec.rs b/consensus/types/src/core/chain_spec.rs index 516ca2288e..c54d032891 100644 --- a/consensus/types/src/core/chain_spec.rs +++ b/consensus/types/src/core/chain_spec.rs @@ -251,6 +251,9 @@ pub struct ChainSpec { pub builder_payment_threshold_numerator: u64, pub builder_payment_threshold_denominator: u64, pub min_builder_withdrawability_delay: Epoch, + pub churn_limit_quotient_gloas: u64, + pub consolidation_churn_limit_quotient: u64, + pub max_per_epoch_activation_churn_limit_gloas: u64, /* * Networking @@ -1268,6 +1271,14 @@ impl ChainSpec { builder_payment_threshold_numerator: 6, builder_payment_threshold_denominator: 10, min_builder_withdrawability_delay: Epoch::new(64), + churn_limit_quotient_gloas: option_wrapper(|| u64::checked_pow(2, 15)) + .expect("calculation does not overflow"), + consolidation_churn_limit_quotient: option_wrapper(|| u64::checked_pow(2, 16)) + .expect("calculation does not overflow"), + max_per_epoch_activation_churn_limit_gloas: option_wrapper(|| { + u64::checked_pow(2, 8)?.checked_mul(u64::checked_pow(10, 9)?) + }) + .expect("calculation does not overflow"), max_request_payloads: 128, /* @@ -1414,6 +1425,14 @@ impl ChainSpec { gloas_fork_version: [0x07, 0x00, 0x00, 0x01], gloas_fork_epoch: None, min_builder_withdrawability_delay: Epoch::new(2), + churn_limit_quotient_gloas: option_wrapper(|| u64::checked_pow(2, 4)) + .expect("calculation does not overflow"), + consolidation_churn_limit_quotient: option_wrapper(|| u64::checked_pow(2, 5)) + .expect("calculation does not overflow"), + max_per_epoch_activation_churn_limit_gloas: option_wrapper(|| { + u64::checked_pow(2, 7)?.checked_mul(u64::checked_pow(10, 9)?) + }) + .expect("calculation does not overflow"), /* * Derived time values (set by `compute_derived_values()`) @@ -1675,6 +1694,14 @@ impl ChainSpec { builder_payment_threshold_numerator: 6, builder_payment_threshold_denominator: 10, min_builder_withdrawability_delay: Epoch::new(64), + churn_limit_quotient_gloas: option_wrapper(|| u64::checked_pow(2, 15)) + .expect("calculation does not overflow"), + consolidation_churn_limit_quotient: option_wrapper(|| u64::checked_pow(2, 16)) + .expect("calculation does not overflow"), + max_per_epoch_activation_churn_limit_gloas: option_wrapper(|| { + u64::checked_pow(2, 8)?.checked_mul(u64::checked_pow(10, 9)?) + }) + .expect("calculation does not overflow"), max_request_payloads: 128, /* @@ -2125,6 +2152,16 @@ pub struct Config { #[serde(default = "default_min_builder_withdrawability_delay")] #[serde(with = "serde_utils::quoted_u64")] min_builder_withdrawability_delay: u64, + + #[serde(default = "default_churn_limit_quotient_gloas")] + #[serde(with = "serde_utils::quoted_u64")] + churn_limit_quotient_gloas: u64, + #[serde(default = "default_consolidation_churn_limit_quotient")] + #[serde(with = "serde_utils::quoted_u64")] + consolidation_churn_limit_quotient: u64, + #[serde(default = "default_max_per_epoch_activation_churn_limit_gloas")] + #[serde(with = "serde_utils::quoted_u64")] + max_per_epoch_activation_churn_limit_gloas: u64, } fn default_bellatrix_fork_version() -> [u8; 4] { @@ -2362,6 +2399,18 @@ const fn default_min_builder_withdrawability_delay() -> u64 { 64 } +const fn default_churn_limit_quotient_gloas() -> u64 { + 32_768 +} + +const fn default_consolidation_churn_limit_quotient() -> u64 { + 65_536 +} + +const fn default_max_per_epoch_activation_churn_limit_gloas() -> u64 { + 256_000_000_000 +} + fn max_blocks_by_root_request_common(max_request_blocks: u64) -> usize { let max_request_blocks = max_request_blocks as usize; RuntimeVariableList::::new( @@ -2613,6 +2662,11 @@ impl Config { contribution_due_bps: spec.contribution_due_bps, min_builder_withdrawability_delay: spec.min_builder_withdrawability_delay.as_u64(), + + churn_limit_quotient_gloas: spec.churn_limit_quotient_gloas, + consolidation_churn_limit_quotient: spec.consolidation_churn_limit_quotient, + max_per_epoch_activation_churn_limit_gloas: spec + .max_per_epoch_activation_churn_limit_gloas, } } @@ -2710,6 +2764,9 @@ impl Config { sync_message_due_bps, contribution_due_bps, min_builder_withdrawability_delay, + churn_limit_quotient_gloas, + consolidation_churn_limit_quotient, + max_per_epoch_activation_churn_limit_gloas, } = self; if preset_base != E::spec_name().to_string().as_str() { @@ -2817,6 +2874,10 @@ impl Config { min_builder_withdrawability_delay: Epoch::new(min_builder_withdrawability_delay), + churn_limit_quotient_gloas, + consolidation_churn_limit_quotient, + max_per_epoch_activation_churn_limit_gloas, + ..chain_spec.clone() }; Some(spec.compute_derived_values::()) @@ -3719,9 +3780,7 @@ mod yaml_tests { "CONTRIBUTION_DUE_BPS_GLOAS", "MAX_REQUEST_PAYLOADS", // Heze networking - "VIEW_FREEZE_CUTOFF_BPS", - "INCLUSION_LIST_SUBMISSION_DUE_BPS", - "PROPOSER_INCLUSION_LIST_CUTOFF_BPS", + "INCLUSION_LIST_DUE_BPS", "MAX_REQUEST_INCLUSION_LIST", "MAX_BYTES_PER_INCLUSION_LIST", ]; diff --git a/consensus/types/src/core/eth_spec.rs b/consensus/types/src/core/eth_spec.rs index 4159091f5d..5f296afb44 100644 --- a/consensus/types/src/core/eth_spec.rs +++ b/consensus/types/src/core/eth_spec.rs @@ -572,7 +572,7 @@ impl EthSpec for MinimalEthSpec { type NumberOfColumns = U128; type ProposerLookaheadSlots = U16; // Derived from (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH type BuilderPendingPaymentsLimit = U16; // 2 * SLOTS_PER_EPOCH = 2 * 8 = 16 - type PTCSize = U2; + type PTCSize = U16; type PtcWindowLength = U24; // (2 + MIN_SEED_LOOKAHEAD) * SLOTS_PER_EPOCH type MaxBuildersPerWithdrawalsSweep = U16; diff --git a/consensus/types/src/execution/execution_payload_envelope.rs b/consensus/types/src/execution/execution_payload_envelope.rs index 028423d681..a6d123bd21 100644 --- a/consensus/types/src/execution/execution_payload_envelope.rs +++ b/consensus/types/src/execution/execution_payload_envelope.rs @@ -20,6 +20,7 @@ pub struct ExecutionPayloadEnvelope { #[serde(with = "serde_utils::quoted_u64")] pub builder_index: u64, pub beacon_block_root: Hash256, + pub parent_beacon_block_root: Hash256, } impl ExecutionPayloadEnvelope { @@ -30,6 +31,7 @@ impl ExecutionPayloadEnvelope { execution_requests: ExecutionRequests::default(), builder_index: 0, beacon_block_root: Hash256::zero(), + parent_beacon_block_root: Hash256::zero(), } } diff --git a/consensus/types/src/state/beacon_state.rs b/consensus/types/src/state/beacon_state.rs index 7ed3121d6e..e821ca922b 100644 --- a/consensus/types/src/state/beacon_state.rs +++ b/consensus/types/src/state/beacon_state.rs @@ -2762,29 +2762,55 @@ impl BeaconState { /// Return the churn limit for the current epoch. pub fn get_balance_churn_limit(&self, spec: &ChainSpec) -> Result { let total_active_balance = self.get_total_active_balance()?; + let quotient = if self.fork_name_unchecked().gloas_enabled() { + spec.churn_limit_quotient_gloas + } else { + spec.churn_limit_quotient + }; let churn = std::cmp::max( spec.min_per_epoch_churn_limit_electra, - total_active_balance.safe_div(spec.churn_limit_quotient)?, + total_active_balance.safe_div(quotient)?, ); Ok(churn.safe_sub(churn.safe_rem(spec.effective_balance_increment)?)?) } /// Return the churn limit for the current epoch dedicated to activations and exits. + /// + /// From Gloas onwards this is the activation-only churn limit (EIP-8061); exits use + /// [`Self::get_exit_churn_limit`]. pub fn get_activation_exit_churn_limit( &self, spec: &ChainSpec, ) -> Result { + let max_limit = if self.fork_name_unchecked().gloas_enabled() { + spec.max_per_epoch_activation_churn_limit_gloas + } else { + spec.max_per_epoch_activation_exit_churn_limit + }; Ok(std::cmp::min( - spec.max_per_epoch_activation_exit_churn_limit, + max_limit, self.get_balance_churn_limit(spec)?, )) } + /// Return the Gloas (EIP-8061) exit churn limit for the current epoch. + /// + /// Unlike [`Self::get_activation_exit_churn_limit`], this is uncapped. + pub fn get_exit_churn_limit(&self, spec: &ChainSpec) -> Result { + self.get_balance_churn_limit(spec) + } + pub fn get_consolidation_churn_limit(&self, spec: &ChainSpec) -> Result { - self.get_balance_churn_limit(spec)? - .safe_sub(self.get_activation_exit_churn_limit(spec)?) - .map_err(Into::into) + if self.fork_name_unchecked().gloas_enabled() { + let total_active_balance = self.get_total_active_balance()?; + let churn = total_active_balance.safe_div(spec.consolidation_churn_limit_quotient)?; + Ok(churn.safe_sub(churn.safe_rem(spec.effective_balance_increment)?)?) + } else { + self.get_balance_churn_limit(spec)? + .safe_sub(self.get_activation_exit_churn_limit(spec)?) + .map_err(Into::into) + } } pub fn get_pending_balance_to_withdraw( @@ -2879,7 +2905,11 @@ impl BeaconState { self.compute_activation_exit_epoch(self.current_epoch(), spec)?, ); - let per_epoch_churn = self.get_activation_exit_churn_limit(spec)?; + let per_epoch_churn = if self.fork_name_unchecked().gloas_enabled() { + self.get_exit_churn_limit(spec)? + } else { + self.get_activation_exit_churn_limit(spec)? + }; // New epoch for exits let mut exit_balance_to_consume = if self.earliest_exit_epoch()? < earliest_exit_epoch { per_epoch_churn @@ -3103,7 +3133,19 @@ impl BeaconState { let total_active_balance = self.get_total_active_balance()?; let fork_name = self.fork_name_unchecked(); - if fork_name.electra_enabled() { + if fork_name.gloas_enabled() { + // [Modified in Gloas:EIP8061] + let exit_churn = self.get_exit_churn_limit(spec)?; + let activation_churn = self.get_activation_exit_churn_limit(spec)?; + let consolidation_churn = self.get_consolidation_churn_limit(spec)?; + compute_weak_subjectivity_period_gloas( + total_active_balance, + exit_churn, + activation_churn, + consolidation_churn, + spec, + ) + } else if fork_name.electra_enabled() { let balance_churn_limit = self.get_balance_churn_limit(spec)?; compute_weak_subjectivity_period_electra( total_active_balance, @@ -3601,6 +3643,30 @@ pub fn compute_weak_subjectivity_period_electra( Ok(ws_period) } +/// Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.6/specs/gloas/weak-subjectivity.md +pub fn compute_weak_subjectivity_period_gloas( + total_active_balance: u64, + exit_churn_limit: u64, + activation_churn_limit: u64, + consolidation_churn_limit: u64, + spec: &ChainSpec, +) -> Result { + // delta = 2 * exit_churn // 3 + activation_churn // 3 + consolidation_churn + let delta = exit_churn_limit + .safe_mul(2)? + .safe_div(3)? + .safe_add(activation_churn_limit.safe_div(3)?)? + .safe_add(consolidation_churn_limit)?; + let epochs_for_validator_set_churn = SAFETY_DECAY + .safe_mul(total_active_balance)? + .safe_div(delta.safe_mul(200)?)?; + let ws_period = spec + .min_validator_withdrawability_delay + .safe_add(epochs_for_validator_set_churn)?; + + Ok(ws_period) +} + #[cfg(test)] mod weak_subjectivity_tests { use crate::state::beacon_state::compute_weak_subjectivity_period_electra; diff --git a/testing/ef_tests/Makefile b/testing/ef_tests/Makefile index facc8208d9..63d1907b96 100644 --- a/testing/ef_tests/Makefile +++ b/testing/ef_tests/Makefile @@ -1,6 +1,6 @@ # To download/extract nightly tests, run: # CONSENSUS_SPECS_TEST_VERSION=nightly make -CONSENSUS_SPECS_TEST_VERSION ?= v1.7.0-alpha.5 +CONSENSUS_SPECS_TEST_VERSION ?= v1.7.0-alpha.6 REPO_NAME := consensus-spec-tests OUTPUT_DIR := ./$(REPO_NAME) diff --git a/testing/ef_tests/check_all_files_accessed.py b/testing/ef_tests/check_all_files_accessed.py index 5a54e150db..53fb626e7e 100755 --- a/testing/ef_tests/check_all_files_accessed.py +++ b/testing/ef_tests/check_all_files_accessed.py @@ -55,6 +55,7 @@ excluded_paths = [ "tests/.*/.*/ssz_static/PartialDataColumn.*/.*", # TODO(gloas): Ignore Gloas light client stuff for now "tests/.*/gloas/ssz_static/LightClient.*/.*", + "tests/.*/gloas/light_client", # Execution payload header is irrelevant after Gloas, this type will probably be deleted. "tests/.*/gloas/ssz_static/ExecutionPayloadHeader/.*", # ForkChoiceNode is internal to fork choice and probably doesn't need SSZ tests. diff --git a/testing/ef_tests/download_test_vectors.sh b/testing/ef_tests/download_test_vectors.sh index f91b2d1c38..cb45aeb922 100755 --- a/testing/ef_tests/download_test_vectors.sh +++ b/testing/ef_tests/download_test_vectors.sh @@ -23,7 +23,7 @@ if [[ "$version" == "nightly" || "$version" =~ ^nightly-[0-9]+$ ]]; then if [[ "$version" == "nightly" ]]; then run_id=$(curl --fail -s -H "${auth_header}" \ - "${api}/repos/${repo}/actions/workflows/nightly-reftests.yml/runs?branch=master&status=success&per_page=1" | + "${api}/repos/${repo}/actions/workflows/tests.yml/runs?branch=master&status=success&per_page=1" | jq -r '.workflow_runs[0].id') else run_id="${version#nightly-}" diff --git a/testing/ef_tests/src/cases/epoch_processing.rs b/testing/ef_tests/src/cases/epoch_processing.rs index a032aa917f..ec243f05cc 100644 --- a/testing/ef_tests/src/cases/epoch_processing.rs +++ b/testing/ef_tests/src/cases/epoch_processing.rs @@ -58,6 +58,8 @@ pub struct Eth1DataReset; #[derive(Debug)] pub struct PendingBalanceDeposits; #[derive(Debug)] +pub struct PendingDepositsChurn; +#[derive(Debug)] pub struct PendingConsolidations; #[derive(Debug)] pub struct EffectiveBalanceUpdates; @@ -93,6 +95,7 @@ type_name!(RegistryUpdates, "registry_updates"); type_name!(Slashings, "slashings"); type_name!(Eth1DataReset, "eth1_data_reset"); type_name!(PendingBalanceDeposits, "pending_deposits"); +type_name!(PendingDepositsChurn, "pending_deposits_churn"); type_name!(PendingConsolidations, "pending_consolidations"); type_name!(EffectiveBalanceUpdates, "effective_balance_updates"); type_name!(SlashingsReset, "slashings_reset"); @@ -191,6 +194,20 @@ impl EpochTransition for PendingBalanceDeposits { } } +impl EpochTransition for PendingDepositsChurn { + fn run(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), EpochProcessingError> { + process_epoch_single_pass( + state, + spec, + SinglePassConfig { + pending_deposits: true, + ..SinglePassConfig::disable_all() + }, + ) + .map(|_| ()) + } +} + impl EpochTransition for PendingConsolidations { fn run(state: &mut BeaconState, spec: &ChainSpec) -> Result<(), EpochProcessingError> { initialize_epoch_cache(state, spec)?; @@ -387,7 +404,9 @@ impl> Case for EpochProcessing { } if !fork_name.gloas_enabled() - && (T::name() == "builder_pending_payments" || T::name() == "ptc_window") + && (T::name() == "builder_pending_payments" + || T::name() == "ptc_window" + || T::name() == "pending_deposits_churn") { return false; } diff --git a/testing/ef_tests/src/cases/operations.rs b/testing/ef_tests/src/cases/operations.rs index f90b6f2a6e..f5c999920d 100644 --- a/testing/ef_tests/src/cases/operations.rs +++ b/testing/ef_tests/src/cases/operations.rs @@ -53,6 +53,15 @@ pub struct WithdrawalsPayload { payload: Option>, } +/// Newtype for testing voluntary exit churn (Gloas+). +/// +/// The test case applies the same `process_voluntary_exit` operation as the regular +/// `voluntary_exit` test, but under the `voluntary_exit_churn` handler directory. +#[derive(Debug, Clone)] +pub struct VoluntaryExitChurn { + exit: SignedVoluntaryExit, +} + /// Newtype for testing execution payload bids. #[derive(Debug, Clone, Deserialize)] pub struct ExecutionPayloadBidBlock { @@ -265,6 +274,40 @@ impl Operation for SignedVoluntaryExit { } } +impl Operation for VoluntaryExitChurn { + type Error = BlockProcessingError; + + fn handler_name() -> String { + "voluntary_exit_churn".into() + } + + fn filename() -> String { + "voluntary_exit.ssz_snappy".into() + } + + fn is_enabled_for_fork(fork_name: ForkName) -> bool { + fork_name.gloas_enabled() + } + + fn decode(path: &Path, _fork_name: ForkName, _spec: &ChainSpec) -> Result { + ssz_decode_file(path).map(|exit| VoluntaryExitChurn { exit }) + } + + fn apply_to( + &self, + state: &mut BeaconState, + spec: &ChainSpec, + _: &Operations, + ) -> Result<(), BlockProcessingError> { + process_exits( + state, + std::slice::from_ref(&self.exit), + VerifySignatures::True, + spec, + ) + } +} + impl Operation for BeaconBlock { type Error = BlockProcessingError; diff --git a/testing/ef_tests/src/handler.rs b/testing/ef_tests/src/handler.rs index 96798c910c..e380f51c0a 100644 --- a/testing/ef_tests/src/handler.rs +++ b/testing/ef_tests/src/handler.rs @@ -340,6 +340,10 @@ impl SszStaticHandler { pub fn pre_electra() -> Self { Self::for_forks(ForkName::list_all()[0..5].to_vec()) } + + pub fn pre_capella() -> Self { + Self::for_forks(ForkName::list_all()[0..3].to_vec()) + } } /// Handler for SSZ types that implement `CachedTreeHash`. diff --git a/testing/ef_tests/src/lib.rs b/testing/ef_tests/src/lib.rs index 0ffedc7eb8..bead5825ed 100644 --- a/testing/ef_tests/src/lib.rs +++ b/testing/ef_tests/src/lib.rs @@ -3,9 +3,10 @@ pub use cases::{ BuilderPendingPayments, Case, EffectiveBalanceUpdates, Eth1DataReset, ExecutionPayloadBidBlock, FeatureName, HistoricalRootsUpdate, HistoricalSummariesUpdate, InactivityUpdates, JustificationAndFinalization, ParentExecutionPayloadBlock, ParticipationFlagUpdates, - ParticipationRecordUpdates, PendingBalanceDeposits, PendingConsolidations, ProposerLookahead, - PtcWindow, RandaoMixesReset, RegistryUpdates, RewardsAndPenalties, Slashings, SlashingsReset, - SyncCommitteeUpdates, WithdrawalsPayload, + ParticipationRecordUpdates, PendingBalanceDeposits, PendingConsolidations, + PendingDepositsChurn, ProposerLookahead, PtcWindow, RandaoMixesReset, RegistryUpdates, + RewardsAndPenalties, Slashings, SlashingsReset, SyncCommitteeUpdates, VoluntaryExitChurn, + WithdrawalsPayload, }; pub use decode::log_file_access; pub use error::Error; diff --git a/testing/ef_tests/tests/tests.rs b/testing/ef_tests/tests/tests.rs index 79a02d7e80..ca383efdb0 100644 --- a/testing/ef_tests/tests/tests.rs +++ b/testing/ef_tests/tests/tests.rs @@ -142,6 +142,12 @@ fn operations_bls_to_execution_change() { OperationsHandler::::default().run(); } +#[test] +fn operations_voluntary_exit_churn() { + OperationsHandler::::default().run(); + OperationsHandler::::default().run(); +} + #[test] fn sanity_blocks() { SanityBlocksHandler::::default().run(); @@ -285,8 +291,19 @@ mod ssz_static { ssz_static_test!(eth1_data, Eth1Data); ssz_static_test!(fork, Fork); ssz_static_test!(fork_data, ForkData); - ssz_static_test!(historical_batch, HistoricalBatch<_>); - ssz_static_test!(pending_attestation, PendingAttestation<_>); + // `HistoricalBatch` was removed in Capella, so test vectors only exist for Base, + // Altair and Bellatrix. + #[test] + fn historical_batch() { + SszStaticHandler::, MinimalEthSpec>::pre_capella().run(); + SszStaticHandler::, MainnetEthSpec>::pre_capella().run(); + } + // `PendingAttestation` was removed in Altair, so test vectors only exist for Base. + #[test] + fn pending_attestation() { + SszStaticHandler::, MinimalEthSpec>::base_only().run(); + SszStaticHandler::, MainnetEthSpec>::base_only().run(); + } ssz_static_test!(proposer_slashing, ProposerSlashing); ssz_static_test!( signed_beacon_block, @@ -899,6 +916,12 @@ fn epoch_processing_pending_balance_deposits() { EpochProcessingHandler::::default().run(); } +#[test] +fn epoch_processing_pending_deposits_churn() { + EpochProcessingHandler::::default().run(); + EpochProcessingHandler::::default().run(); +} + #[test] fn epoch_processing_pending_consolidations() { EpochProcessingHandler::::default().run(); From 0e427ab77b74f62f87d50122b259b3893cf31755 Mon Sep 17 00:00:00 2001 From: Lion - dapplion <35266934+dapplion@users.noreply.github.com> Date: Wed, 29 Apr 2026 14:02:12 +0200 Subject: [PATCH 11/12] Add Gloas bid inclusion (#9221) Co-Authored-By: dapplion <35266934+dapplion@users.noreply.github.com> --- .../src/block_production/gloas.rs | 257 ++++++++++++++++-- beacon_node/beacon_chain/src/test_utils.rs | 1 + .../beacon_chain/tests/prepare_payload.rs | 1 + beacon_node/execution_layer/src/lib.rs | 2 + 4 files changed, 240 insertions(+), 21 deletions(-) diff --git a/beacon_node/beacon_chain/src/block_production/gloas.rs b/beacon_node/beacon_chain/src/block_production/gloas.rs index a02963c358..6510c20ba7 100644 --- a/beacon_node/beacon_chain/src/block_production/gloas.rs +++ b/beacon_node/beacon_chain/src/block_production/gloas.rs @@ -78,6 +78,16 @@ pub struct ExecutionPayloadData { pub blobs_and_proofs: (types::BlobsList, types::KzgProofs), } +/// The result of a local payload build, used to decide whether to include a builder bid +/// from the gossip cache or fall back to self-build. +pub struct LocalBuildResult { + pub payload_data: ExecutionPayloadData, + /// EL block value (in wei) of the locally-built payload. + pub payload_value: types::Uint256, + /// `true` if the EL signaled `engine_getPayload`'s `shouldOverrideBuilder` flag. + pub should_override_builder: bool, +} + impl BeaconChain { pub async fn produce_block_with_verification_gloas( self: &Arc, @@ -85,7 +95,7 @@ impl BeaconChain { slot: Slot, graffiti_settings: GraffitiSettings, verification: ProduceBlockVerification, - _builder_boost_factor: Option, + builder_boost_factor: Option, ) -> Result, BlockProductionError> { metrics::inc_counter(&metrics::BLOCK_PRODUCTION_REQUESTS); let _complete_timer = metrics::start_timer(&metrics::BLOCK_PRODUCTION_TIMES); @@ -121,11 +131,11 @@ impl BeaconChain { randao_reveal, graffiti_settings, verification, + builder_boost_factor, ) .await } - // TODO(gloas) need to implement builder boost factor logic #[instrument(level = "debug", skip_all)] #[allow(clippy::too_many_arguments)] pub async fn produce_block_on_state_gloas( @@ -138,6 +148,7 @@ impl BeaconChain { randao_reveal: Signature, graffiti_settings: GraffitiSettings, verification: ProduceBlockVerification, + builder_boost_factor: Option, ) -> Result, BlockProductionError> { // Extract the parent's execution requests from the envelope (if parent was full). let parent_execution_requests = if parent_payload_status == PayloadStatus::Full { @@ -179,10 +190,10 @@ impl BeaconChain { // Part 2/3 (async) // - // Produce the execution payload bid. - // TODO(gloas) this is strictly for building local bids - // We'll need to build out trustless/trusted bid paths. - let (execution_payload_bid, state, payload_data) = self + // Produce a local execution payload bid, then select between it and any cached + // gossip-verified builder bid using `builder_boost_factor`. + // TODO(gloas) build out trustless/trusted bid paths. + let (local_signed_bid, state, local_build) = self .clone() .produce_execution_payload_bid( state, @@ -194,6 +205,9 @@ impl BeaconChain { ) .await?; + let (execution_payload_bid, payload_data) = + self.select_payload_bid(local_signed_bid, local_build, builder_boost_factor); + // Part 3/3 (blocking) // // Complete the block with the execution payload bid. @@ -679,16 +693,13 @@ impl BeaconChain { Ok((block, state, consensus_block_value)) } - // TODO(gloas) introduce `ProposerPreferences` so we can build out trustless - // bid building. Right now this only works for local building. - /// Produce an `ExecutionPayloadBid` for some `slot` upon the given `state`. + /// Produce a self-build `ExecutionPayloadBid` for some `slot` upon the given `state`. /// This function assumes we've already advanced `state`. /// - /// Returns the signed bid, the state, and optionally the payload data needed to construct - /// the `ExecutionPayloadEnvelope` after the beacon block is created. - /// - /// For local building, payload data is always returned (`Some`). - /// For trustless building, the builder provides the envelope separately, so `None` is returned. + /// Returns the signed bid, the state, and a `LocalBuildResult` carrying the payload + /// data needed to construct the `ExecutionPayloadEnvelope` after the beacon block is + /// created, plus the EL block value and `should_override_builder` flag used by the + /// caller to compare against any cached p2p builder bid. #[allow(clippy::type_complexity)] #[instrument(level = "debug", skip_all)] pub async fn produce_execution_payload_bid( @@ -703,7 +714,7 @@ impl BeaconChain { ( SignedExecutionPayloadBid, BeaconState, - Option>, + LocalBuildResult, ), BlockProductionError, > { @@ -775,10 +786,11 @@ impl BeaconChain { let BlockProposalContentsGloas { payload, - payload_value: _, + payload_value, execution_requests, blob_kzg_commitments, blobs_and_proofs, + should_override_builder, } = block_proposal_contents; // TODO(gloas) since we are defaulting to local building, execution payment is 0 @@ -807,19 +819,115 @@ impl BeaconChain { blobs_and_proofs, }; - // TODO(gloas) this is only local building - // we'll need to implement builder signature for the trustless path Ok(( SignedExecutionPayloadBid { message: bid, signature: Signature::infinity().map_err(BlockProductionError::BlsError)?, }, state, - // Local building always returns payload data. - // Trustless building would return None here. - Some(payload_data), + LocalBuildResult { + payload_data, + payload_value, + should_override_builder, + }, )) } + + /// Look up the highest gossip-verified bid for the `(slot, parent_block_hash, + /// parent_block_root)` of the local bid, then choose the winner. + fn select_payload_bid( + &self, + local_signed_bid: SignedExecutionPayloadBid, + local_build: LocalBuildResult, + builder_boost_factor: Option, + ) -> ( + SignedExecutionPayloadBid, + Option>, + ) { + let cached_bid = self.gossip_verified_payload_bid_cache.get_highest_bid( + local_signed_bid.message.slot, + local_signed_bid.message.parent_block_hash, + local_signed_bid.message.parent_block_root, + ); + select_payload_bid_pure( + local_signed_bid, + local_build, + cached_bid, + builder_boost_factor, + ) + } +} + +/// Pure local-vs-cached selection logic, factored out for unit testing. +/// +/// Selection rule (mirrors the pre-Gloas builder/local race in `execution_layer`): +/// - `boosted_bid = (cached_bid.value / 100) * builder_boost_factor` (raw value when `None`) +/// - if `local_value_wei >= boosted_bid_wei` → keep local +/// - if the EL signaled `should_override_builder` → keep local +/// - otherwise → use the cached builder bid and drop local payload data +/// (the builder is responsible for revealing the envelope). +/// +/// `cached_bid.value` is in gwei (`u64`); `payload_value` is in wei (`Uint256`); compared in wei. +pub(crate) fn select_payload_bid_pure( + local_signed_bid: SignedExecutionPayloadBid, + local_build: LocalBuildResult, + cached_bid: Option>>, + builder_boost_factor: Option, +) -> ( + SignedExecutionPayloadBid, + Option>, +) { + let LocalBuildResult { + payload_data, + payload_value, + should_override_builder, + } = local_build; + + let Some(cached_bid) = cached_bid else { + return (local_signed_bid, Some(payload_data)); + }; + + let slot = local_signed_bid.message.slot; + + if should_override_builder { + debug!( + %slot, + cached_bid_value = cached_bid.message.value, + "Using local payload because EL signaled shouldOverrideBuilder" + ); + return (local_signed_bid, Some(payload_data)); + } + + // Convert bid value (gwei) to wei for comparison with `payload_value` (wei). + let bid_value_wei = types::Uint256::from(cached_bid.message.value) + .saturating_mul(types::Uint256::from(1_000_000_000u64)); + let boosted_bid_wei = match builder_boost_factor { + Some(factor) => { + (bid_value_wei / types::Uint256::from(100)).saturating_mul(types::Uint256::from(factor)) + } + None => bid_value_wei, + }; + + if payload_value >= boosted_bid_wei { + debug!( + %slot, + %payload_value, + cached_bid_value_gwei = cached_bid.message.value, + ?builder_boost_factor, + "Local payload is more profitable than cached builder bid" + ); + (local_signed_bid, Some(payload_data)) + } else { + debug!( + %slot, + %payload_value, + cached_bid_value_gwei = cached_bid.message.value, + cached_bid_builder_index = cached_bid.message.builder_index, + ?builder_boost_factor, + "Including cached builder bid" + ); + ((*cached_bid).clone(), None) + } } /// Gets an execution payload for inclusion in a block. @@ -1151,4 +1259,111 @@ mod tests { assert_eq!(exits.len(), 2); } + + // ---- select_payload_bid_pure ---- + + const REMOTE_BUILDER: BuilderIndex = 999; + + fn gwei(n: u64) -> types::Uint256 { + types::Uint256::from(n).saturating_mul(types::Uint256::from(1_000_000_000u64)) + } + + fn local_bid() -> SignedExecutionPayloadBid { + SignedExecutionPayloadBid { + message: ExecutionPayloadBid { + builder_index: BUILDER_INDEX_SELF_BUILD, + ..Default::default() + }, + signature: Signature::empty(), + } + } + + fn cached_bid(value_gwei: u64) -> Arc> { + Arc::new(SignedExecutionPayloadBid { + message: ExecutionPayloadBid { + builder_index: REMOTE_BUILDER, + value: value_gwei, + ..Default::default() + }, + signature: Signature::empty(), + }) + } + + fn local_build(payload_gwei: u64, should_override_builder: bool) -> LocalBuildResult { + LocalBuildResult { + payload_data: ExecutionPayloadData { + payload: types::ExecutionPayloadGloas::default(), + execution_requests: ExecutionRequests::default(), + builder_index: BUILDER_INDEX_SELF_BUILD, + slot: Slot::new(0), + blobs_and_proofs: (VariableList::empty(), VariableList::empty()), + }, + payload_value: gwei(payload_gwei), + should_override_builder, + } + } + + const LOCAL: BuilderIndex = BUILDER_INDEX_SELF_BUILD; + const REMOTE: BuilderIndex = REMOTE_BUILDER; + + /// Run `select_payload_bid_pure` and return `(winning_builder_index, has_payload_data)`. + /// + /// Args (positional, mirror `select_payload_bid_pure`): + /// - `local_payload_gwei`: local payload value, in gwei. + /// - `should_override`: EL's `shouldOverrideBuilder` flag. + /// - `cached_gwei`: `Some(g)` ⇒ seed the cache with a bid of `g` gwei. + /// - `boost`: `None` = neutral, `Some(0)` = always local, `Some(>100)` = boost bid. + fn pick( + local_payload_gwei: u64, + should_override: bool, + cached_gwei: Option, + boost: Option, + ) -> (BuilderIndex, bool) { + let build = local_build(local_payload_gwei, should_override); + let cache = cached_gwei.map(cached_bid); + let (out, data) = select_payload_bid_pure::(local_bid(), build, cache, boost); + (out.message.builder_index, data.is_some()) + } + + #[test] + fn select_empty_cache_keeps_local() { + assert_eq!(pick(0, false, None, Some(u64::MAX)), (LOCAL, true)); + } + + #[test] + fn select_el_override_beats_any_cached_bid() { + // `shouldOverrideBuilder` short-circuits regardless of cache or boost. + assert_eq!(pick(0, true, Some(u64::MAX), Some(u64::MAX)), (LOCAL, true)); + } + + #[test] + fn select_boost_zero_always_keeps_local() { + // boost=0 deflates the bid to 0 ⇒ local always wins. + assert_eq!(pick(0, false, Some(u64::MAX), Some(0)), (LOCAL, true)); + } + + #[test] + fn select_neutral_boost_picks_higher_bid() { + // 5 gwei bid > 1 gwei local, neutral compare ⇒ bid. + assert_eq!(pick(1, false, Some(5), None), (REMOTE, false)); + } + + #[test] + fn select_local_strictly_higher_keeps_local() { + assert_eq!(pick(10, false, Some(5), None), (LOCAL, true)); + } + + #[test] + fn select_tie_goes_to_local() { + // `>=` ⇒ local wins ties. + assert_eq!(pick(5, false, Some(5), None), (LOCAL, true)); + } + + #[test] + fn select_boost_factor_amplifies_bid() { + // 5 gwei local vs 3 gwei bid: raw ⇒ local. + assert_eq!(pick(5, false, Some(3), None), (LOCAL, true)); + // boost=200 ⇒ bid scaled to 6 gwei ⇒ bid wins. + assert_eq!(pick(5, false, Some(3), Some(200)), (REMOTE, false)); + } } diff --git a/beacon_node/beacon_chain/src/test_utils.rs b/beacon_node/beacon_chain/src/test_utils.rs index f67b5015c5..f61a7abbe6 100644 --- a/beacon_node/beacon_chain/src/test_utils.rs +++ b/beacon_node/beacon_chain/src/test_utils.rs @@ -1186,6 +1186,7 @@ where randao_reveal, graffiti_settings, ProduceBlockVerification::VerifyRandao, + None, ) .await .unwrap(); diff --git a/beacon_node/beacon_chain/tests/prepare_payload.rs b/beacon_node/beacon_chain/tests/prepare_payload.rs index 549f15a13f..47dd1ef517 100644 --- a/beacon_node/beacon_chain/tests/prepare_payload.rs +++ b/beacon_node/beacon_chain/tests/prepare_payload.rs @@ -632,6 +632,7 @@ async fn gloas_block_production_caches_blobs_for_column_publishing() { randao_reveal, graffiti_settings, ProduceBlockVerification::VerifyRandao, + None, ) .await .unwrap(); diff --git a/beacon_node/execution_layer/src/lib.rs b/beacon_node/execution_layer/src/lib.rs index 4146543fd5..b2dabb7c01 100644 --- a/beacon_node/execution_layer/src/lib.rs +++ b/beacon_node/execution_layer/src/lib.rs @@ -205,6 +205,7 @@ pub struct BlockProposalContentsGloas { pub blob_kzg_commitments: KzgCommitments, pub blobs_and_proofs: (BlobsList, KzgProofs), pub execution_requests: ExecutionRequests, + pub should_override_builder: bool, } impl From> for BlockProposalContentsGloas { @@ -215,6 +216,7 @@ impl From> for BlockProposalContentsGloas blob_kzg_commitments: response.blobs_bundle.commitments, blobs_and_proofs: (response.blobs_bundle.blobs, response.blobs_bundle.proofs), execution_requests: response.requests, + should_override_builder: response.should_override_builder, } } } From f406e9c3fbf6f4abdd65a7d1501e2e892c96d2c9 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Wed, 29 Apr 2026 22:19:44 +1000 Subject: [PATCH 12/12] Update proposer boost calculation (#9215) Closes: - https://github.com/sigp/lighthouse/issues/8689 - Calculate the proposer index on the canonical chain (from canonical head) at `slot` and plumb it through to fork choice so it can be used to determine whether or not to apply the proposer boost. We use the proposer cache to handle state advances and avoid duplicate work. - Update our FC tests to use `block.message().proposer_index()` (always pass), we are not attempting to test this feature in those tests. The EF tests use the correct canonical proposer idnex via `on_block`, except for invalid blocks which just auto-pass this check (these blocks get rejected by other checks in `on_block` anyway). Co-Authored-By: Michael Sproul --- beacon_node/beacon_chain/src/beacon_chain.rs | 46 ++++++++++++++++++- .../tests/payload_invalidation.rs | 1 + beacon_node/http_api/tests/tests.rs | 36 ++++++++------- consensus/fork_choice/src/fork_choice.rs | 17 ++++--- consensus/fork_choice/tests/tests.rs | 2 + testing/ef_tests/src/cases/fork_choice.rs | 10 +--- 6 files changed, 79 insertions(+), 33 deletions(-) diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index ccb12a353d..f618cf6321 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -4175,7 +4175,14 @@ impl BeaconChain { }; // Read the cached head prior to taking the fork choice lock to avoid potential deadlocks. - let old_head_slot = self.canonical_head.cached_head().head_slot(); + let cached_head = self.canonical_head.cached_head(); + let old_head_slot = cached_head.head_slot(); + + // Compute the expected proposer for `current_slot` on the canonical chain. This is used by + // `on_block` to gate proposer boost on the block's proposer matching the canonical proposer + // (per spec `update_proposer_boost_root` added in v1.7.0-alpha.5). + let canonical_head_proposer_index = + self.canonical_head_proposer_index(current_slot, &cached_head)?; // Take an upgradable read lock on fork choice so we can check if this block has already // been imported. We don't want to repeat work importing a block that is already imported. @@ -4208,6 +4215,7 @@ impl BeaconChain { block_delay, &state, payload_verification_status, + canonical_head_proposer_index, &self.spec, ) .map_err(|e| BlockError::BeaconChainError(Box::new(e.into())))?; @@ -4950,6 +4958,42 @@ impl BeaconChain { })) } + /// Compute the expected beacon proposer for `slot` on the canonical chain extending `cached_head`. + /// + /// Uses the beacon proposer cache to avoid recomputing the shuffling on every block import. + /// + /// This is used by `update_proposer_boost_root` to gate proposer boost on the block's proposer + /// matching the canonical proposer, per consensus-specs v1.7.0-alpha.5. + /// + /// This function should never error unless there is some corruption of the head state. If a + /// state advance is needed, it will be handled by the proposer cache. + pub fn canonical_head_proposer_index( + &self, + slot: Slot, + cached_head: &CachedHead, + ) -> Result { + let proposal_epoch = slot.epoch(T::EthSpec::slots_per_epoch()); + let head_block_root = cached_head.head_block_root(); + let head_state = &cached_head.snapshot.beacon_state; + + let shuffling_decision_root = head_state.proposer_shuffling_decision_root_at_epoch( + proposal_epoch, + head_block_root, + &self.spec, + )?; + + self.with_proposer_cache::<_, Error>( + shuffling_decision_root, + proposal_epoch, + |proposers| { + proposers + .get_slot::(slot) + .map(|p| p.index as u64) + }, + || Ok((cached_head.head_state_root(), head_state.clone())), + ) + } + pub fn get_expected_withdrawals( &self, forkchoice_update_params: &ForkchoiceUpdateParameters, diff --git a/beacon_node/beacon_chain/tests/payload_invalidation.rs b/beacon_node/beacon_chain/tests/payload_invalidation.rs index 38d4f4c47e..be85fc2245 100644 --- a/beacon_node/beacon_chain/tests/payload_invalidation.rs +++ b/beacon_node/beacon_chain/tests/payload_invalidation.rs @@ -1093,6 +1093,7 @@ async fn invalid_parent() { Duration::from_secs(0), &state, PayloadVerificationStatus::Optimistic, + block.message().proposer_index(), &rig.harness.chain.spec, ), Err(ForkChoiceError::ProtoArrayStringError(message)) diff --git a/beacon_node/http_api/tests/tests.rs b/beacon_node/http_api/tests/tests.rs index b8326f4495..56835da459 100644 --- a/beacon_node/http_api/tests/tests.rs +++ b/beacon_node/http_api/tests/tests.rs @@ -3450,17 +3450,20 @@ impl ApiTester { .unwrap() .unwrap_or(self.chain.head_beacon_block_root()); - // Presently, the beacon chain harness never runs the code that primes the proposer - // cache. If this changes in the future then we'll need some smarter logic here, but - // this is succinct and effective for the time being. - assert!( - self.chain - .beacon_proposer_cache - .lock() - .get_epoch::(dependent_root, epoch) - .is_none(), - "the proposer cache should miss initially" - ); + // Block import primes the proposer cache for each epoch it runs through (to gate + // proposer boost), so epochs `<= current_epoch` are already cached. The only epoch + // for which we can observe the endpoint's own caching behaviour is + // `current_epoch + 1`, which no block import has touched yet. + if epoch == current_epoch + 1 { + assert!( + self.chain + .beacon_proposer_cache + .lock() + .get_epoch::(dependent_root, epoch) + .is_none(), + "the proposer cache should miss initially for the next epoch" + ); + } let result = self .client @@ -3468,8 +3471,9 @@ impl ApiTester { .await .unwrap(); - // Check that current-epoch requests prime the proposer cache, whilst non-current - // requests don't. + // A current-epoch request should leave the cache primed (block import already did so, + // but this is still a useful end-to-end check). A request for `current_epoch + 1` + // should not prime the cache. if epoch == current_epoch { assert!( self.chain @@ -3477,16 +3481,16 @@ impl ApiTester { .lock() .get_epoch::(dependent_root, epoch) .is_some(), - "a current-epoch request should prime the proposer cache" + "the proposer cache should be primed for the current epoch" ); - } else { + } else if epoch == current_epoch + 1 { assert!( self.chain .beacon_proposer_cache .lock() .get_epoch::(dependent_root, epoch) .is_none(), - "a non-current-epoch request should not prime the proposer cache" + "a request for the next epoch should not prime the proposer cache" ); } diff --git a/consensus/fork_choice/src/fork_choice.rs b/consensus/fork_choice/src/fork_choice.rs index a9e62dbe94..477d1fa3b4 100644 --- a/consensus/fork_choice/src/fork_choice.rs +++ b/consensus/fork_choice/src/fork_choice.rs @@ -756,6 +756,7 @@ where block_delay: Duration, state: &BeaconState, payload_verification_status: PayloadVerificationStatus, + canonical_head_proposer_index: u64, spec: &ChainSpec, ) -> Result<(), Error> { let _timer = metrics::start_timer(&metrics::FORK_CHOICE_ON_BLOCK_TIMES); @@ -820,16 +821,18 @@ where let attestation_threshold = spec.get_attestation_due::(block.slot()); - // Add proposer score boost if the block is timely. - // TODO(gloas): the spec's `update_proposer_boost_root` additionally checks that - // `block.proposer_index == get_beacon_proposer_index(head_state)` — i.e. that - // the block's proposer matches the expected proposer on the canonical chain. - // This requires calling `get_head` and advancing the head state to the current - // slot, which is expensive. Implement once we have a cached proposer index. + // Add proposer score boost if the block is the first timely block for this slot and its + // proposer matches the expected proposer on the canonical chain (per spec + // `update_proposer_boost_root`, introduced in v1.7.0-alpha.5). let is_before_attesting_interval = block_delay < attestation_threshold; let is_first_block = self.fc_store.proposer_boost_root().is_zero(); - if current_slot == block.slot() && is_before_attesting_interval && is_first_block { + let is_canonical_proposer = block.proposer_index() == canonical_head_proposer_index; + if current_slot == block.slot() + && is_before_attesting_interval + && is_first_block + && is_canonical_proposer + { self.fc_store.set_proposer_boost_root(block_root); } diff --git a/consensus/fork_choice/tests/tests.rs b/consensus/fork_choice/tests/tests.rs index d6f937c0ca..353893026b 100644 --- a/consensus/fork_choice/tests/tests.rs +++ b/consensus/fork_choice/tests/tests.rs @@ -316,6 +316,7 @@ impl ForkChoiceTest { Duration::from_secs(0), &state, PayloadVerificationStatus::Verified, + block.message().proposer_index(), &self.harness.chain.spec, ) .unwrap(); @@ -359,6 +360,7 @@ impl ForkChoiceTest { Duration::from_secs(0), &state, PayloadVerificationStatus::Verified, + block.message().proposer_index(), &self.harness.chain.spec, ) .expect_err("on_block did not return an error"); diff --git a/testing/ef_tests/src/cases/fork_choice.rs b/testing/ef_tests/src/cases/fork_choice.rs index 2af205ee47..8b0b74d256 100644 --- a/testing/ef_tests/src/cases/fork_choice.rs +++ b/testing/ef_tests/src/cases/fork_choice.rs @@ -335,15 +335,6 @@ impl Case for ForkChoiceTest { } fn result(&self, _case_index: usize, fork_name: ForkName) -> Result<(), Error> { - // TODO(gloas): We have not implemented this change to fork choice/proposer boost yet. - // https://github.com/sigp/lighthouse/issues/8689 - if self.description == "voting_source_beyond_two_epoch" - || self.description == "justified_update_not_realized_finality" - || self.description == "justified_update_always_if_better" - { - return Err(Error::SkippedKnownFailure); - } - let tester = Tester::new(self, testing_spec::(fork_name))?; for step in &self.steps { @@ -791,6 +782,7 @@ impl Tester { block_delay, &state, PayloadVerificationStatus::Irrelevant, + block.message().proposer_index(), &self.harness.chain.spec, );