-
-
Notifications
You must be signed in to change notification settings - Fork 428
feat: add support for backfilling blocks #8677
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: backfill
Are you sure you want to change the base?
Changes from all commits
864b9e5
ad89e11
9e5cd9b
3606147
29f36c2
9ac4ea3
6e5ffa1
bc7919d
98b9664
024de90
eb4eb5b
760f448
f46e9d3
c450b6e
2e3b1f4
488e022
405b520
3697f79
dac6120
f33dbef
a306499
a06ed20
13d427a
bcf4894
e9054e6
1d2431a
49f72ea
57d8447
c1842cd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,15 @@ | ||
| import {Key} from "interface-datastore"; | ||
| import {KeyValue} from "@lodestar/db"; | ||
| import {CheckpointWithHex} from "@lodestar/fork-choice"; | ||
| import {Logger} from "@lodestar/logger"; | ||
| import {SLOTS_PER_EPOCH} from "@lodestar/params"; | ||
| import {computeEpochAtSlot} from "@lodestar/state-transition"; | ||
| import {prettyPrintIndices} from "@lodestar/utils"; | ||
| import {IBeaconDb} from "../../../db/interface.js"; | ||
| import {BackfillState, EpochBackfillState} from "../../../db/repositories/backfillState.ts"; | ||
| import {IBeaconChain} from "../../interface.js"; | ||
|
|
||
| // Todo: Update comments wrt BackfillRange | ||
| /** | ||
| * Backfill sync relies on verified connected ranges (which are represented as key,value | ||
| * with a verified jump from a key back to value). Since the node could have progressed | ||
|
|
@@ -18,31 +25,71 @@ export async function updateBackfillRange( | |
| finalized: CheckpointWithHex | ||
| ): Promise<void> { | ||
| try { | ||
| // const {ancestors: finalizedCanonicalBlocks, nonAncestors: finalizedNonCanonicalBlocks} = | ||
| // chain.forkChoice.getAllAncestorAndNonAncestorBlocks(finalized.rootHex); | ||
|
|
||
| // Mark the sequence in backfill db from finalized block's slot till anchor slot as | ||
| // filled. | ||
| const finalizedBlockFC = chain.forkChoice.getBlockHex(finalized.rootHex); | ||
| if (finalizedBlockFC && finalizedBlockFC.slot > chain.anchorStateLatestBlockSlot) { | ||
| await db.backfilledRanges.put(finalizedBlockFC.slot, chain.anchorStateLatestBlockSlot); | ||
|
|
||
| // Clear previously marked sequence till anchorStateLatestBlockSlot, without | ||
| // touching backfill sync process sequence which are at | ||
| // <=anchorStateLatestBlockSlot i.e. clear >anchorStateLatestBlockSlot | ||
| // and < currentSlot | ||
| const filteredSeqs = await db.backfilledRanges.entries({ | ||
| gt: chain.anchorStateLatestBlockSlot, | ||
| lt: finalizedBlockFC.slot, | ||
| const previousBackfillRange = await db.backfillRange.get(); | ||
|
|
||
| const finalizedPostDeneb = finalized.epoch >= chain.config.DENEB_FORK_EPOCH; | ||
| const finalizedPostFulu = finalized.epoch >= chain.config.FULU_FORK_EPOCH; | ||
|
|
||
| if ( | ||
| finalizedBlockFC && | ||
| (finalizedBlockFC.slot > chain.anchorStateLatestBlockSlot || | ||
| (previousBackfillRange && finalizedBlockFC.slot > previousBackfillRange?.endingEpoch * SLOTS_PER_EPOCH)) | ||
| ) { | ||
| await db.backfillRange.put({ | ||
| beginningEpoch: computeEpochAtSlot(finalizedBlockFC.slot), | ||
| endingEpoch: previousBackfillRange?.endingEpoch || computeEpochAtSlot(chain.anchorStateLatestBlockSlot), | ||
| }); | ||
| logger.debug("updated backfilledRanges", { | ||
| key: finalizedBlockFC.slot, | ||
| value: chain.anchorStateLatestBlockSlot, | ||
| // DEBUG_CODE | ||
| logger.info("Updated backfillRange while migrating from hot to cold db", { | ||
| beginningEpoch: computeEpochAtSlot(finalizedBlockFC.slot), | ||
| endingEpoch: previousBackfillRange?.endingEpoch || computeEpochAtSlot(chain.anchorStateLatestBlockSlot), | ||
| previousBackfillRangeBeginningEpoch: previousBackfillRange?.beginningEpoch, | ||
| previousBackfillRangeEndingEpoch: previousBackfillRange?.endingEpoch, | ||
| chainAnchorStateLatestBlockSlotEpoch: computeEpochAtSlot(chain.anchorStateLatestBlockSlot), | ||
| }); | ||
| // DEBUG_CODE | ||
|
|
||
| // const custodyColumns = chain.custodyConfig.custodyColumns; | ||
| await db.backfillState.put(finalized.epoch, { | ||
| hasBlock: true, | ||
| // check if blobs & columns are filled in live chain | ||
| hasBlobs: finalizedPostDeneb ? true : null, | ||
| columnIndices: finalizedPostFulu ? [] : null, | ||
| }); | ||
| if (filteredSeqs.length > 0) { | ||
| await db.backfilledRanges.batchDelete(filteredSeqs.map((entry) => entry.key)); | ||
| logger.debug( | ||
| `Forward Sync - cleaned up backfilledRanges between ${finalizedBlockFC.slot},${chain.anchorStateLatestBlockSlot}`, | ||
| {seqs: JSON.stringify(filteredSeqs)} | ||
| ); | ||
| } | ||
|
|
||
| // DEBUG_CODE | ||
| logger.info("Updated backfillState while migrating from hot to cold db", { | ||
| finalizedEpoch: finalized.epoch, | ||
| hasBlock: true, | ||
| hasBlobs: finalizedPostDeneb ? true : null, | ||
| columnIndices: finalizedPostFulu ? prettyPrintIndices([]) : null, | ||
| }); | ||
| // DEBUG_CODE | ||
|
|
||
| // Todo: verify if this function runs every epoch, else intermediate epoch backfill states will be empty. | ||
| // Below could be a possible solution to this issue. | ||
|
|
||
| // // In case of long unfinality, this needs to be done to save multiple epochs | ||
| // // First, find all *unique* epochs from the list of finalized blocks | ||
| // const uniqueEpochs = Array.from(new Set(finalizedCanonicalBlocks.map((block) => block.finalizedEpoch))); | ||
| // const backfillStates: KeyValue<number, EpochBackfillState>[] = uniqueEpochs.map((epoch) => { | ||
| // return { | ||
| // key: epoch, | ||
| // value: { | ||
| // hasBlock: true, | ||
| // // check if blobs & columns are filled in live chain | ||
| // hasBlobs: finalizedPostDeneb ? true : null, | ||
| // columnIndices: finalizedPostFulu ? [] : null, | ||
| // }, | ||
| // }; | ||
| // }); | ||
| // await db.backfillState.batchPut(backfillStates); | ||
|
Comment on lines
+75
to
+92
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
| } | ||
| } catch (e) { | ||
| logger.error("Error updating backfilledRanges on finalization", {epoch: finalized.epoch}, e as Error); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This
DEBUG_CODEblock, along with the one at lines 66-73, appears to be for debugging. This verbose logging should be removed before merging to keep the codebase clean and avoid excessive noise in production logs. Similar debug logging is present in other new files in this PR and should also be removed.