From d6e3b006ead00eff6b016ecbfa562706375a50b4 Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Fri, 1 May 2026 22:18:15 +0200 Subject: [PATCH] fix --- beacon_node/beacon_chain/src/beacon_chain.rs | 16 +++++- .../beacon_chain/src/block_verification.rs | 10 ++++ .../payload_envelope_verification/import.rs | 52 +++++++++++++++++++ 3 files changed, 76 insertions(+), 2 deletions(-) diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index da904726d1..9fcaabc7c4 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -3185,11 +3185,12 @@ impl BeaconChain { }; // Import the blocks into the chain. - for (signature_verified_block, _envelope) in signature_verified_blocks { + for (signature_verified_block, envelope) in signature_verified_blocks { let block_slot = signature_verified_block.slot(); + let block_root = signature_verified_block.block_root(); match self .process_block( - signature_verified_block.block_root(), + block_root, signature_verified_block, notify_execution_layer, BlockImportSource::RangeSync, @@ -3200,6 +3201,17 @@ impl BeaconChain { Ok(status) => { match status { AvailabilityProcessingStatus::Imported(block_root) => { + // Import the envelope if one was provided (Gloas+). + if let Some(envelope) = envelope + && let Err(e) = self.import_envelope_from_range_sync( + *envelope, block_root, + ) + { + return ChainSegmentResult::Failed { + imported_blocks, + error: e, + }; + } // The block was imported successfully. imported_blocks.push((block_root, block_slot)); } diff --git a/beacon_node/beacon_chain/src/block_verification.rs b/beacon_node/beacon_chain/src/block_verification.rs index 597b557f69..7d411c8154 100644 --- a/beacon_node/beacon_chain/src/block_verification.rs +++ b/beacon_node/beacon_chain/src/block_verification.rs @@ -2019,10 +2019,20 @@ fn load_parent>( // If the parent's execution payload envelope hasn't arrived yet, // return an unknown parent error so the block gets sent to the // reprocess queue. + // + // Skip this check if the parent is at or before the finalized slot (e.g. after + // checkpoint sync the finalized block won't have a stored envelope). + let finalized_slot = chain + .canonical_head + .cached_head() + .finalized_checkpoint() + .epoch + .start_slot(T::EthSpec::slots_per_epoch()); if chain .spec .fork_name_at_slot::(parent_block.slot()) .gloas_enabled() + && parent_block.slot() > finalized_slot { let _envelope = chain .store 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 e7c900dcd7..36da758db4 100644 --- a/beacon_node/beacon_chain/src/payload_envelope_verification/import.rs +++ b/beacon_node/beacon_chain/src/payload_envelope_verification/import.rs @@ -392,4 +392,56 @@ impl BeaconChain { )); } } + + /// Import an execution payload envelope received via range sync. + /// + /// This is a simplified import path that trusts the envelope since it was fetched alongside + /// a valid block during range sync. It stores the envelope to the database and marks it as + /// received in fork choice. + pub fn import_envelope_from_range_sync( + &self, + envelope: AvailableEnvelope, + block_root: Hash256, + ) -> Result<(), BlockError> { + let fork_choice_reader = self.canonical_head.fork_choice_upgradable_read_lock(); + if !fork_choice_reader.contains_block(&block_root) { + return Err(BlockError::EnvelopeBlockRootUnknown(block_root)); + } + + let mut fork_choice = parking_lot::RwLockUpgradableReadGuard::upgrade(fork_choice_reader); + + fork_choice + .on_valid_payload_envelope_received(block_root) + .map_err(|e| BlockError::InternalError(format!("{e:?}")))?; + + let (signed_envelope, columns) = envelope.deconstruct(); + + let mut ops = vec![]; + + if let Some(blobs_or_columns_store_op) = self.get_blobs_or_columns_store_op( + block_root, + signed_envelope.slot(), + AvailableBlockData::DataColumns(columns), + ) { + ops.push(blobs_or_columns_store_op); + } + + ops.push(StoreOp::PutPayloadEnvelope( + block_root, + signed_envelope, + )); + + drop(fork_choice); + + if let Err(e) = self.store.do_atomically_with_block_and_blobs_cache(ops) { + error!( + msg = "Failed to store range sync envelope", + error = ?e, + "Database write failed!" + ); + return Err(e.into()); + } + + Ok(()) + } }