From 353fd1cec429b311f449080e4f76b26889ca10a7 Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Thu, 19 Feb 2026 14:32:40 -0800 Subject: [PATCH 1/5] init block verification --- .../beacon_chain/src/block_verification.rs | 10 +++++-- consensus/fork_choice/src/fork_choice.rs | 4 +-- consensus/types/src/block/beacon_block.rs | 30 ++++++++++--------- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/beacon_node/beacon_chain/src/block_verification.rs b/beacon_node/beacon_chain/src/block_verification.rs index e0943d5d931..39ae9452f6c 100644 --- a/beacon_node/beacon_chain/src/block_verification.rs +++ b/beacon_node/beacon_chain/src/block_verification.rs @@ -1038,8 +1038,14 @@ impl GossipVerifiedBlock { }); } - // Validate the block's execution_payload (if any). - validate_execution_payload_for_gossip(&parent_block, block.message(), chain)?; + // Validate a pre-Gloas block's execution_payload (if any). + if !chain + .spec + .fork_name_at_slot::(block.slot()) + .gloas_enabled() + { + validate_execution_payload_for_gossip(&parent_block, block.message(), chain)?; + } // Beacon API block_gossip events if let Some(event_handler) = chain.event_handler.as_ref() diff --git a/consensus/fork_choice/src/fork_choice.rs b/consensus/fork_choice/src/fork_choice.rs index 9744b9fa084..7a89280e4c1 100644 --- a/consensus/fork_choice/src/fork_choice.rs +++ b/consensus/fork_choice/src/fork_choice.rs @@ -853,9 +853,7 @@ where .on_verified_block(block, block_root, state) .map_err(Error::AfterBlockFailed)?; - let execution_status = if let Ok(execution_payload) = block.body().execution_payload() { - let block_hash = execution_payload.block_hash(); - + let execution_status = if let Some(block_hash) = block.execution_block_hash() { if block_hash == ExecutionBlockHash::zero() { // The block is post-merge-fork, but pre-terminal-PoW block. We don't need to verify // the payload. diff --git a/consensus/types/src/block/beacon_block.rs b/consensus/types/src/block/beacon_block.rs index bee3cdb2746..2c93a79efd6 100644 --- a/consensus/types/src/block/beacon_block.rs +++ b/consensus/types/src/block/beacon_block.rs @@ -15,26 +15,15 @@ use tree_hash_derive::TreeHash; use typenum::Unsigned; use crate::{ - SignedExecutionPayloadBid, - attestation::{AttestationBase, AttestationData, IndexedAttestationBase}, - block::{ + ExecPayload, ExecutionBlockHash, SignedExecutionPayloadBid, attestation::{AttestationBase, AttestationData, IndexedAttestationBase}, block::{ BeaconBlockBodyAltair, BeaconBlockBodyBase, BeaconBlockBodyBellatrix, BeaconBlockBodyCapella, BeaconBlockBodyDeneb, BeaconBlockBodyElectra, BeaconBlockBodyFulu, BeaconBlockBodyGloas, BeaconBlockBodyRef, BeaconBlockBodyRefMut, BeaconBlockHeader, SignedBeaconBlock, SignedBeaconBlockHeader, - }, - core::{ChainSpec, Domain, Epoch, EthSpec, Graffiti, Hash256, SignedRoot, Slot}, - deposit::{Deposit, DepositData}, - execution::{ + }, core::{ChainSpec, Domain, Epoch, EthSpec, Graffiti, Hash256, SignedRoot, Slot}, deposit::{Deposit, DepositData}, execution::{ AbstractExecPayload, BlindedPayload, Eth1Data, ExecutionPayload, ExecutionRequests, FullPayload, - }, - exit::{SignedVoluntaryExit, VoluntaryExit}, - fork::{Fork, ForkName, InconsistentFork, map_fork_name}, - slashing::{AttesterSlashingBase, ProposerSlashing}, - state::BeaconStateError, - sync_committee::SyncAggregate, - test_utils::TestRandom, + }, exit::{SignedVoluntaryExit, VoluntaryExit}, fork::{Fork, ForkName, InconsistentFork, map_fork_name}, slashing::{AttesterSlashingBase, ProposerSlashing}, state::BeaconStateError, sync_committee::SyncAggregate, test_utils::TestRandom }; /// A block of the `BeaconChain`. @@ -309,6 +298,19 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload> BeaconBlockRef<'a, E, Payl pub fn execution_payload(&self) -> Result, BeaconStateError> { self.body().execution_payload() } + + pub fn execution_block_hash(&self) -> Option { + match self { + BeaconBlockRef::Base(_) => None, + BeaconBlockRef::Altair(_) => None, + BeaconBlockRef::Bellatrix(block) => Some(block.body.execution_payload.block_hash()), + BeaconBlockRef::Capella(block) => Some(block.body.execution_payload.block_hash()), + BeaconBlockRef::Deneb(block) => Some(block.body.execution_payload.block_hash()), + BeaconBlockRef::Electra(block) => Some(block.body.execution_payload.block_hash()), + BeaconBlockRef::Fulu(block) => Some(block.body.execution_payload.block_hash()), + BeaconBlockRef::Gloas(block) => Some(block.body.signed_execution_payload_bid.message.block_hash), + } + } } impl<'a, E: EthSpec, Payload: AbstractExecPayload> BeaconBlockRefMut<'a, E, Payload> { From 20b09e0b6f9dce3e454ba3611deab8ca62d2e2a1 Mon Sep 17 00:00:00 2001 From: Eitan Seri- Levi Date: Fri, 20 Feb 2026 10:34:19 -0800 Subject: [PATCH 2/5] gloas block verification --- beacon_node/beacon_chain/src/beacon_chain.rs | 18 +++-- .../beacon_chain/src/block_verification.rs | 76 +++++++++++++++---- .../beacon_chain/src/execution_payload.rs | 11 ++- .../gossip_methods.rs | 33 ++++---- consensus/types/src/block/beacon_block.rs | 41 +++++++++- 5 files changed, 142 insertions(+), 37 deletions(-) diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index 9f62bf11f5f..26ad2e714b2 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -3378,11 +3378,19 @@ impl BeaconChain { ); } - self.data_availability_checker.put_pre_execution_block( - block_root, - unverified_block.block_cloned(), - block_source, - )?; + // Gloas blocks dont need to be inserted into the DA cache + // they are always available. + if !unverified_block + .block() + .fork_name_unchecked() + .gloas_enabled() + { + self.data_availability_checker.put_pre_execution_block( + block_root, + unverified_block.block_cloned(), + block_source, + )?; + } // Start the Prometheus timer. let _full_timer = metrics::start_timer(&metrics::BLOCK_PROCESSING_TIMES); diff --git a/beacon_node/beacon_chain/src/block_verification.rs b/beacon_node/beacon_chain/src/block_verification.rs index 39ae9452f6c..e9d7b2d9089 100644 --- a/beacon_node/beacon_chain/src/block_verification.rs +++ b/beacon_node/beacon_chain/src/block_verification.rs @@ -51,7 +51,9 @@ use crate::beacon_snapshot::PreProcessingSnapshot; use crate::blob_verification::GossipBlobError; use crate::block_verification_types::{AsBlock, BlockImportData, RpcBlock}; -use crate::data_availability_checker::{AvailabilityCheckError, MaybeAvailableBlock}; +use crate::data_availability_checker::{ + AvailabilityCheckError, AvailableBlock, AvailableBlockData, MaybeAvailableBlock, +}; use crate::data_column_verification::GossipDataColumnError; use crate::execution_payload::{ AllowOptimisticImport, NotifyExecutionLayer, PayloadNotifier, @@ -334,6 +336,15 @@ pub enum BlockError { max_blobs_at_epoch: usize, block: usize, }, + /// The bid's parent_block_root does not match the block's parent_root. + /// + /// ## Peer scoring + /// + /// The block is invalid and the peer should be penalized. + BidParentRootMismatch { + bid_parent_root: Hash256, + block_parent_root: Hash256, + }, } /// Which specific signature(s) are invalid in a SignedBeaconBlock @@ -887,15 +898,15 @@ impl GossipVerifiedBlock { // Do not gossip blocks that claim to contain more blobs than the max allowed // at the given block epoch. - if let Ok(commitments) = block.message().body().blob_kzg_commitments() { + if let Some(blob_kzg_commitments_len) = block.message().blob_kzg_commitments_len() { let max_blobs_at_epoch = chain .spec .max_blobs_per_block(block.slot().epoch(T::EthSpec::slots_per_epoch())) as usize; - if commitments.len() > max_blobs_at_epoch { + if blob_kzg_commitments_len > max_blobs_at_epoch { return Err(BlockError::InvalidBlobCount { max_blobs_at_epoch, - block: commitments.len(), + block: blob_kzg_commitments_len, }); } } @@ -932,6 +943,24 @@ impl GossipVerifiedBlock { let block_epoch = block.slot().epoch(T::EthSpec::slots_per_epoch()); let (parent_block, block) = verify_parent_block_is_known::(&fork_choice_read_lock, block)?; + + // [New in Gloas]: Verify bid.parent_block_root matches block.parent_root. + if let Ok(bid) = block.message().body().signed_execution_payload_bid() { + if bid.message.parent_block_root != block.message().parent_root() { + return Err(BlockError::BidParentRootMismatch { + bid_parent_root: bid.message.parent_block_root, + block_parent_root: block.message().parent_root(), + }); + } + + // TODO(gloas) The following validation can only be completed once fork choice has been implemented: + // The block's parent execution payload (defined by bid.parent_block_hash) has been seen + // (via gossip or non-gossip sources) (a client MAY queue blocks for processing + // once the parent payload is retrieved). If execution_payload verification of block's execution + // payload parent by an execution node is complete, verify the block's execution payload + // parent (defined by bid.parent_block_hash) passes all validation. + } + drop(fork_choice_read_lock); // Track the number of skip slots between the block and its parent. @@ -1038,7 +1067,8 @@ impl GossipVerifiedBlock { }); } - // Validate a pre-Gloas block's execution_payload (if any). + // [New in Gloas]: Skip payload validation checks. The payload now arrives separetely + // via `ExecutionPayloadEnvelope`. if !chain .spec .fork_name_at_slot::(block.slot()) @@ -1217,15 +1247,35 @@ impl SignatureVerifiedBlock { let result = info_span!("signature_verify").in_scope(|| signature_verifier.verify()); match result { - Ok(_) => Ok(Self { - block: MaybeAvailableBlock::AvailabilityPending { + Ok(_) => { + // gloas blocks are always available. + let maybe_available = if chain + .spec + .fork_name_at_slot::(block.slot()) + .gloas_enabled() + { + MaybeAvailableBlock::Available( + AvailableBlock::new( + block, + AvailableBlockData::NoData, + &chain.data_availability_checker, + chain.spec.clone(), + ) + .map_err(BlockError::AvailabilityCheck)?, + ) + } else { + MaybeAvailableBlock::AvailabilityPending { + block_root: from.block_root, + block, + } + }; + Ok(Self { + block: maybe_available, block_root: from.block_root, - block, - }, - block_root: from.block_root, - parent: Some(parent), - consensus_context, - }), + parent: Some(parent), + consensus_context, + }) + } Err(_) => Err(BlockError::InvalidSignature( InvalidSignature::BlockBodySignatures, )), diff --git a/beacon_node/beacon_chain/src/execution_payload.rs b/beacon_node/beacon_chain/src/execution_payload.rs index bdf3ab95949..f32a3ba2a34 100644 --- a/beacon_node/beacon_chain/src/execution_payload.rs +++ b/beacon_node/beacon_chain/src/execution_payload.rs @@ -62,7 +62,10 @@ impl PayloadNotifier { state: &BeaconState, notify_execution_layer: NotifyExecutionLayer, ) -> Result { - let payload_verification_status = if is_execution_enabled(state, block.message().body()) { + let payload_verification_status = if block.fork_name_unchecked().gloas_enabled() { + // Gloas blocks don't contain an execution payload. + Some(PayloadVerificationStatus::Irrelevant) + } else if is_execution_enabled(state, block.message().body()) { // Perform the initial stages of payload verification. // // We will duplicate these checks again during `per_block_processing`, however these @@ -294,6 +297,12 @@ pub fn validate_execution_payload_for_gossip( block: BeaconBlockRef<'_, T::EthSpec>, chain: &BeaconChain, ) -> Result<(), BlockError> { + // Gloas blocks don't have an execution payload in the block body. + // Bid-related validations are handled in gossip block verification. + if block.fork_name_unchecked().gloas_enabled() { + return Ok(()); + } + // Only apply this validation if this is a Bellatrix beacon block. if let Ok(execution_payload) = block.body().execution_payload() { // This logic should match `is_execution_enabled`. We use only the execution block hash of 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 a9198f19436..e90018c851f 100644 --- a/beacon_node/network/src/network_beacon_processor/gossip_methods.rs +++ b/beacon_node/network/src/network_beacon_processor/gossip_methods.rs @@ -1356,7 +1356,8 @@ impl NetworkBeaconProcessor { | Err(e @ BlockError::ParentExecutionPayloadInvalid { .. }) | Err(e @ BlockError::KnownInvalidExecutionPayload(_)) | Err(e @ BlockError::GenesisBlock) - | Err(e @ BlockError::InvalidBlobCount { .. }) => { + | Err(e @ BlockError::InvalidBlobCount { .. }) + | Err(e @ BlockError::BidParentRootMismatch { .. }) => { warn!(error = %e, "Could not verify block for gossip. Rejecting the block"); self.propagate_validation_result(message_id, peer_id, MessageAcceptance::Reject); self.gossip_penalize_peer( @@ -1490,19 +1491,23 @@ impl NetworkBeaconProcessor { // Block is gossip valid. Attempt to fetch blobs from the EL using versioned hashes derived // from kzg commitments, without having to wait for all blobs to be sent from the peers. - let publish_blobs = true; - let self_clone = self.clone(); - let block_clone = block.clone(); - let current_span = Span::current(); - self.executor.spawn( - async move { - self_clone - .fetch_engine_blobs_and_publish(block_clone, block_root, publish_blobs) - .await - } - .instrument(current_span), - "fetch_blobs_gossip", - ); + // TODO(gloas) we'll want to use this same optimization, but we need to refactor the + // `fetch_and_process_engine_blobs` flow to support gloas. + if !block.fork_name_unchecked().gloas_enabled() { + let publish_blobs = true; + let self_clone = self.clone(); + let block_clone = block.clone(); + let current_span = Span::current(); + self.executor.spawn( + async move { + self_clone + .fetch_engine_blobs_and_publish(block_clone, block_root, publish_blobs) + .await + } + .instrument(current_span), + "fetch_blobs_gossip", + ); + } let result = self .chain diff --git a/consensus/types/src/block/beacon_block.rs b/consensus/types/src/block/beacon_block.rs index 2c93a79efd6..be9c3cc1fe4 100644 --- a/consensus/types/src/block/beacon_block.rs +++ b/consensus/types/src/block/beacon_block.rs @@ -15,15 +15,26 @@ use tree_hash_derive::TreeHash; use typenum::Unsigned; use crate::{ - ExecPayload, ExecutionBlockHash, SignedExecutionPayloadBid, attestation::{AttestationBase, AttestationData, IndexedAttestationBase}, block::{ + ExecPayload, ExecutionBlockHash, SignedExecutionPayloadBid, + attestation::{AttestationBase, AttestationData, IndexedAttestationBase}, + block::{ BeaconBlockBodyAltair, BeaconBlockBodyBase, BeaconBlockBodyBellatrix, BeaconBlockBodyCapella, BeaconBlockBodyDeneb, BeaconBlockBodyElectra, BeaconBlockBodyFulu, BeaconBlockBodyGloas, BeaconBlockBodyRef, BeaconBlockBodyRefMut, BeaconBlockHeader, SignedBeaconBlock, SignedBeaconBlockHeader, - }, core::{ChainSpec, Domain, Epoch, EthSpec, Graffiti, Hash256, SignedRoot, Slot}, deposit::{Deposit, DepositData}, execution::{ + }, + core::{ChainSpec, Domain, Epoch, EthSpec, Graffiti, Hash256, SignedRoot, Slot}, + deposit::{Deposit, DepositData}, + execution::{ AbstractExecPayload, BlindedPayload, Eth1Data, ExecutionPayload, ExecutionRequests, FullPayload, - }, exit::{SignedVoluntaryExit, VoluntaryExit}, fork::{Fork, ForkName, InconsistentFork, map_fork_name}, slashing::{AttesterSlashingBase, ProposerSlashing}, state::BeaconStateError, sync_committee::SyncAggregate, test_utils::TestRandom + }, + exit::{SignedVoluntaryExit, VoluntaryExit}, + fork::{Fork, ForkName, InconsistentFork, map_fork_name}, + slashing::{AttesterSlashingBase, ProposerSlashing}, + state::BeaconStateError, + sync_committee::SyncAggregate, + test_utils::TestRandom, }; /// A block of the `BeaconChain`. @@ -299,6 +310,26 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload> BeaconBlockRef<'a, E, Payl self.body().execution_payload() } + pub fn blob_kzg_commitments_len(&self) -> Option { + match self { + BeaconBlockRef::Base(_) => None, + BeaconBlockRef::Altair(_) => None, + BeaconBlockRef::Bellatrix(_) => None, + BeaconBlockRef::Capella(_) => None, + BeaconBlockRef::Deneb(block) => Some(block.body.blob_kzg_commitments.len()), + BeaconBlockRef::Electra(block) => Some(block.body.blob_kzg_commitments.len()), + BeaconBlockRef::Fulu(block) => Some(block.body.blob_kzg_commitments.len()), + BeaconBlockRef::Gloas(block) => Some( + block + .body + .signed_execution_payload_bid + .message + .blob_kzg_commitments + .len(), + ), + } + } + pub fn execution_block_hash(&self) -> Option { match self { BeaconBlockRef::Base(_) => None, @@ -308,7 +339,9 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload> BeaconBlockRef<'a, E, Payl BeaconBlockRef::Deneb(block) => Some(block.body.execution_payload.block_hash()), BeaconBlockRef::Electra(block) => Some(block.body.execution_payload.block_hash()), BeaconBlockRef::Fulu(block) => Some(block.body.execution_payload.block_hash()), - BeaconBlockRef::Gloas(block) => Some(block.body.signed_execution_payload_bid.message.block_hash), + BeaconBlockRef::Gloas(block) => { + Some(block.body.signed_execution_payload_bid.message.block_hash) + } } } } From 6e3eea1b77f9e7c169d594cd54fdc6060deec623 Mon Sep 17 00:00:00 2001 From: Eitan Seri- Levi Date: Fri, 20 Feb 2026 10:37:53 -0800 Subject: [PATCH 3/5] revert --- consensus/types/src/block/beacon_block.rs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/consensus/types/src/block/beacon_block.rs b/consensus/types/src/block/beacon_block.rs index be9c3cc1fe4..54f90cf47a5 100644 --- a/consensus/types/src/block/beacon_block.rs +++ b/consensus/types/src/block/beacon_block.rs @@ -329,21 +329,6 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload> BeaconBlockRef<'a, E, Payl ), } } - - pub fn execution_block_hash(&self) -> Option { - match self { - BeaconBlockRef::Base(_) => None, - BeaconBlockRef::Altair(_) => None, - BeaconBlockRef::Bellatrix(block) => Some(block.body.execution_payload.block_hash()), - BeaconBlockRef::Capella(block) => Some(block.body.execution_payload.block_hash()), - BeaconBlockRef::Deneb(block) => Some(block.body.execution_payload.block_hash()), - BeaconBlockRef::Electra(block) => Some(block.body.execution_payload.block_hash()), - BeaconBlockRef::Fulu(block) => Some(block.body.execution_payload.block_hash()), - BeaconBlockRef::Gloas(block) => { - Some(block.body.signed_execution_payload_bid.message.block_hash) - } - } - } } impl<'a, E: EthSpec, Payload: AbstractExecPayload> BeaconBlockRefMut<'a, E, Payload> { From 3543596c71398348d53655c511ba6cd3505ea3ec Mon Sep 17 00:00:00 2001 From: Eitan Seri- Levi Date: Fri, 20 Feb 2026 11:05:26 -0800 Subject: [PATCH 4/5] revert --- .../beacon_chain/src/block_verification.rs | 28 +++++++++---------- consensus/fork_choice/src/fork_choice.rs | 4 ++- consensus/types/src/block/beacon_block.rs | 2 +- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/beacon_node/beacon_chain/src/block_verification.rs b/beacon_node/beacon_chain/src/block_verification.rs index e9d7b2d9089..b4b1e22c65a 100644 --- a/beacon_node/beacon_chain/src/block_verification.rs +++ b/beacon_node/beacon_chain/src/block_verification.rs @@ -945,22 +945,22 @@ impl GossipVerifiedBlock { verify_parent_block_is_known::(&fork_choice_read_lock, block)?; // [New in Gloas]: Verify bid.parent_block_root matches block.parent_root. - if let Ok(bid) = block.message().body().signed_execution_payload_bid() { - if bid.message.parent_block_root != block.message().parent_root() { - return Err(BlockError::BidParentRootMismatch { - bid_parent_root: bid.message.parent_block_root, - block_parent_root: block.message().parent_root(), - }); - } - - // TODO(gloas) The following validation can only be completed once fork choice has been implemented: - // The block's parent execution payload (defined by bid.parent_block_hash) has been seen - // (via gossip or non-gossip sources) (a client MAY queue blocks for processing - // once the parent payload is retrieved). If execution_payload verification of block's execution - // payload parent by an execution node is complete, verify the block's execution payload - // parent (defined by bid.parent_block_hash) passes all validation. + if let Ok(bid) = block.message().body().signed_execution_payload_bid() + && bid.message.parent_block_root != block.message().parent_root() + { + return Err(BlockError::BidParentRootMismatch { + bid_parent_root: bid.message.parent_block_root, + block_parent_root: block.message().parent_root(), + }); } + // TODO(gloas) The following validation can only be completed once fork choice has been implemented: + // The block's parent execution payload (defined by bid.parent_block_hash) has been seen + // (via gossip or non-gossip sources) (a client MAY queue blocks for processing + // once the parent payload is retrieved). If execution_payload verification of block's execution + // payload parent by an execution node is complete, verify the block's execution payload + // parent (defined by bid.parent_block_hash) passes all validation. + drop(fork_choice_read_lock); // Track the number of skip slots between the block and its parent. diff --git a/consensus/fork_choice/src/fork_choice.rs b/consensus/fork_choice/src/fork_choice.rs index 7a89280e4c1..9744b9fa084 100644 --- a/consensus/fork_choice/src/fork_choice.rs +++ b/consensus/fork_choice/src/fork_choice.rs @@ -853,7 +853,9 @@ where .on_verified_block(block, block_root, state) .map_err(Error::AfterBlockFailed)?; - let execution_status = if let Some(block_hash) = block.execution_block_hash() { + let execution_status = if let Ok(execution_payload) = block.body().execution_payload() { + let block_hash = execution_payload.block_hash(); + if block_hash == ExecutionBlockHash::zero() { // The block is post-merge-fork, but pre-terminal-PoW block. We don't need to verify // the payload. diff --git a/consensus/types/src/block/beacon_block.rs b/consensus/types/src/block/beacon_block.rs index 54f90cf47a5..5634d842b6f 100644 --- a/consensus/types/src/block/beacon_block.rs +++ b/consensus/types/src/block/beacon_block.rs @@ -15,7 +15,7 @@ use tree_hash_derive::TreeHash; use typenum::Unsigned; use crate::{ - ExecPayload, ExecutionBlockHash, SignedExecutionPayloadBid, + SignedExecutionPayloadBid, attestation::{AttestationBase, AttestationData, IndexedAttestationBase}, block::{ BeaconBlockBodyAltair, BeaconBlockBodyBase, BeaconBlockBodyBellatrix, From 15e4ea8f6ef5205661feb53f5208b6d0111decb0 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Mon, 23 Feb 2026 16:44:45 +1100 Subject: [PATCH 5/5] Fix typo in comment --- beacon_node/beacon_chain/src/block_verification.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beacon_node/beacon_chain/src/block_verification.rs b/beacon_node/beacon_chain/src/block_verification.rs index b4b1e22c65a..292560d6a71 100644 --- a/beacon_node/beacon_chain/src/block_verification.rs +++ b/beacon_node/beacon_chain/src/block_verification.rs @@ -1067,7 +1067,7 @@ impl GossipVerifiedBlock { }); } - // [New in Gloas]: Skip payload validation checks. The payload now arrives separetely + // [New in Gloas]: Skip payload validation checks. The payload now arrives separately // via `ExecutionPayloadEnvelope`. if !chain .spec