mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-30 12:47:05 +00:00
fix: store envelope for DuplicateFullyImported + fix load_parent
Two fixes for GLOaS range sync: 1. DuplicateFullyImported: persist envelope for blocks that are already in fork choice (e.g. post-checkpoint-sync blocks between finalized and head). 2. load_parent: if parent envelope isn't in store, check if parent is already in fork choice. If it is, the parent was already imported and validated — proceed without requiring the envelope in store. This handles the case where PayloadEnvelopesByRange doesn't return envelopes for all blocks (fewer envelopes than blocks).
This commit is contained in:
@@ -3060,7 +3060,34 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
//
|
||||
// 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<T: BeaconChainTypes> BeaconChain<T> {
|
||||
// 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
|
||||
|
||||
@@ -2054,10 +2054,25 @@ fn load_parent<T: BeaconChainTypes, B: AsBlock<T::EthSpec>>(
|
||||
.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.
|
||||
|
||||
Reference in New Issue
Block a user