mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-30 12:47:05 +00:00
debug + fix: store envelope for DuplicateFullyImported blocks
After checkpoint sync, blocks between the finalized checkpoint and head are already in fork choice but their envelopes aren't in the store. When range sync downloads these blocks, they get skipped as DuplicateFullyImported without persisting the envelope. The next new block then fails load_parent because it can't find its parent's envelope. Fix: persist the envelope in the DuplicateFullyImported path, same as the existing WouldRevertFinalizedSlot path.
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,15 @@ 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 })?;
|
||||
if chain.store.get_payload_envelope(&root)?.is_none() {
|
||||
debug!(
|
||||
parent_root = %root,
|
||||
parent_slot = %parent_block.slot(),
|
||||
%finalized_slot,
|
||||
"load_parent: parent envelope not in store",
|
||||
);
|
||||
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