avoid small gaps in optimistic block stream (#3749)

Ensures that all intermediate blocks are reported if a small gap is
encountered when downloading optimistic blocks. Gaps may occur when
a block is missed and still downloading, or when EL processing is slow.
If the gap exceeds 1 epoch, optimistic block stream jumps to latest.
This commit is contained in:
Etan Kissling 2022-06-16 17:24:08 +02:00 committed by GitHub
parent e8efc0f184
commit 21b69d5901
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 26 additions and 11 deletions

View File

@ -35,7 +35,8 @@ type
lcBlocks: LCBlocks lcBlocks: LCBlocks
blockVerifier: request_manager.BlockVerifier blockVerifier: request_manager.BlockVerifier
requestManager: RequestManager requestManager: RequestManager
finalizedBid, optimisticBid, optimisticCandidateBid: BlockId finalizedBid, optimisticBid: BlockId
lastReportedSlot: Slot
finalizedIsExecutionBlock: Option[bool] finalizedIsExecutionBlock: Option[bool]
syncStrategy: SyncStrategy syncStrategy: SyncStrategy
syncFut, processFut: Future[void] syncFut, processFut: Future[void]
@ -60,20 +61,34 @@ proc reportOptimisticCandidateBlock(optSync: LCOptimisticSync) {.gcsafe.} =
let let
currentSlot = optSync.lcBlocks.getHeadSlot() currentSlot = optSync.lcBlocks.getHeadSlot()
signedBlock = maxSlot =
if optSync.finalizedIsExecutionBlock.get(false): if optSync.finalizedIsExecutionBlock.get(false):
# If finalized is execution block, can import any later block # If finalized is execution block, can import any later block
optSync.lcBlocks.getLatestBlockThroughSlot(currentSlot) currentSlot
else: else:
# Else, block must be deep (min `SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY`) # Else, block must be deep (min `SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY`)
let let minAge = optSync.safeSlotsToImportOptimistically
minAge = optSync.safeSlotsToImportOptimistically max(currentSlot, minAge.Slot) - minAge.uint64
maxSlot = max(currentSlot, minAge.Slot) - minAge.uint64
optSync.lcBlocks.getLatestBlockThroughSlot(maxSlot) if maxSlot > optSync.lastReportedSlot:
if signedBlock.isOk: const minGapSize = SLOTS_PER_EPOCH
let bid = signedBlock.get.toBlockId() var signedBlock: Opt[ForkedMsgTrustedSignedBeaconBlock]
if bid.slot > optSync.optimisticCandidateBid.slot: if maxSlot - optSync.lastReportedSlot >= minGapSize:
optSync.optimisticCandidateBid = bid # Large gap, skip to latest
signedBlock = optSync.lcBlocks.getLatestBlockThroughSlot(maxSlot)
elif optSync.lcBlocks.getFrontfillSlot() <= optSync.lastReportedSlot + 1 and
optSync.lcBlocks.getBackfillSlot() > optSync.lastReportedSlot + 1:
# Small gap, but still downloading
discard
else:
# Report next sequential block (even if it is slightly outdated)
for slot in optSync.lastReportedSlot + 1 .. maxSlot:
signedBlock = optSync.lcBlocks.getBlockAtSlot(slot)
if signedBlock.isOk:
break
if signedBlock.isOk and signedBlock.get.slot > optSync.lastReportedSlot:
optSync.lastReportedSlot = signedBlock.get.slot
optSync.processFut = optSync.optimisticProcessor(signedBlock.get) optSync.processFut = optSync.optimisticProcessor(signedBlock.get)
proc handleFinishedProcess(future: pointer) = proc handleFinishedProcess(future: pointer) =