diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index 4a148596a6..e76c258e0c 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -3060,7 +3060,34 @@ impl BeaconChain { // // Note that `check_block_relevancy` is incapable of returning // `DuplicateImportStatusUnknown` so we don't need to handle that case here. - Err(BlockError::DuplicateFullyImported(_)) => continue, + Err(BlockError::DuplicateFullyImported(_)) => { + debug!( + block_root = %block_root, + slot = %block.slot(), + "Skipping DuplicateFullyImported block in chain segment", + ); + // For Gloas blocks, persist the envelope even though we're + // skipping the block. After checkpoint sync, blocks between + // the finalized checkpoint and the head are already in fork + // choice but their envelopes aren't in the store. + if let RangeSyncBlock::Gloas { + envelope: Some(ref available_envelope), + .. + } = block + { + let (signed_envelope, _columns) = available_envelope.clone().deconstruct(); + if let Err(e) = self + .store + .put_payload_envelope(&block_root, &signed_envelope) + { + return Err(Box::new(ChainSegmentResult::Failed { + imported_blocks, + error: BlockError::BeaconChainError(Box::new(e.into())), + })); + } + } + continue; + } // If the block is the genesis block, simply ignore this block. Err(BlockError::GenesisBlock) => continue, // If the block is is for a finalized slot, simply ignore this block. @@ -3077,6 +3104,11 @@ impl BeaconChain { // However, we will potentially get a `ParentUnknown` on a later block. The sync // protocol will need to ensure this is handled gracefully. Err(BlockError::WouldRevertFinalizedSlot { .. }) => { + debug!( + block_root = %block_root, + slot = %block.slot(), + "Skipping WouldRevertFinalizedSlot block in chain segment", + ); // For Gloas blocks, persist the envelope even though we're skipping // the block. This is needed after checkpoint sync: the checkpoint // block's envelope must be in the store so that `load_parent` can diff --git a/beacon_node/beacon_chain/src/block_verification.rs b/beacon_node/beacon_chain/src/block_verification.rs index 6417493605..c8737e8c8c 100644 --- a/beacon_node/beacon_chain/src/block_verification.rs +++ b/beacon_node/beacon_chain/src/block_verification.rs @@ -2054,10 +2054,25 @@ fn load_parent>( .gloas_enabled() && parent_block.slot() > finalized_slot { - let _envelope = chain - .store - .get_payload_envelope(&root)? - .ok_or(BlockError::ParentEnvelopeUnknown { parent_root: root })?; + let in_store = chain.store.get_payload_envelope(&root)?.is_some(); + if !in_store { + // If the parent is already in fork choice it was previously imported. + // Its envelope may not be in the store if PayloadEnvelopesByRange + // didn't return it, but the block itself is valid and trusted. + let in_fork_choice = chain + .canonical_head + .fork_choice_read_lock() + .contains_block(&root); + if !in_fork_choice { + debug!( + parent_root = %root, + parent_slot = %parent_block.slot(), + %finalized_slot, + "load_parent: parent envelope not in store and not in fork choice", + ); + return Err(BlockError::ParentEnvelopeUnknown { parent_root: root }); + } + } } // Load the parent block's state from the database, returning an error if it is not found.