mirror of
https://github.com/status-im/nimbus-eth2.git
synced 2025-02-22 19:28:20 +00:00
import finalized head LC bootstrap on launch (#5775)
If the initial state replays cover the finalized head, import matching `LightClientBootstrap` into database. This also addresses this error when light client requests bootstrap from the genesis slot on networks that launch with Altair enabled. ``` {"lvl":"DBG","ts":"2023-10-04 11:17:49.665+00:00","msg":"LC bootstrap unavailable: Sync committee branch not cached","topics":"chaindag_lc","slot":0} ```
This commit is contained in:
parent
479c133375
commit
be73ce2e9a
@ -579,7 +579,7 @@ proc assignLightClientData(
|
|||||||
forkyObject.signature_slot = signature_slot
|
forkyObject.signature_slot = signature_slot
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
proc createLightClientUpdates(
|
proc createLightClientUpdate(
|
||||||
dag: ChainDAGRef,
|
dag: ChainDAGRef,
|
||||||
state: ForkyHashedBeaconState,
|
state: ForkyHashedBeaconState,
|
||||||
blck: ForkyTrustedSignedBeaconBlock,
|
blck: ForkyTrustedSignedBeaconBlock,
|
||||||
@ -665,6 +665,38 @@ proc createLightClientUpdates(
|
|||||||
current_period_best_update = best,
|
current_period_best_update = best,
|
||||||
latest_signature_slot = latest_signature_slot)
|
latest_signature_slot = latest_signature_slot)
|
||||||
|
|
||||||
|
proc createLightClientBootstrap(
|
||||||
|
dag: ChainDAGRef, bid: BlockId): Opt[void] =
|
||||||
|
let
|
||||||
|
bdata = ? dag.getExistingForkedBlock(bid)
|
||||||
|
period = bid.slot.sync_committee_period
|
||||||
|
if not dag.lcDataStore.db.hasSyncCommittee(period):
|
||||||
|
let didPutSyncCommittee = withState(dag.headState):
|
||||||
|
when consensusFork >= ConsensusFork.Altair:
|
||||||
|
if period == forkyState.data.slot.sync_committee_period:
|
||||||
|
dag.lcDataStore.db.putSyncCommittee(
|
||||||
|
period, forkyState.data.current_sync_committee)
|
||||||
|
true
|
||||||
|
else:
|
||||||
|
false
|
||||||
|
else:
|
||||||
|
false
|
||||||
|
if not didPutSyncCommittee:
|
||||||
|
let
|
||||||
|
tmpState = assignClone(dag.headState)
|
||||||
|
syncCommittee = ? dag.existingCurrentSyncCommitteeForPeriod(
|
||||||
|
tmpState[], period)
|
||||||
|
dag.lcDataStore.db.putSyncCommittee(period, syncCommittee)
|
||||||
|
withBlck(bdata):
|
||||||
|
when consensusFork >= ConsensusFork.Altair:
|
||||||
|
const lcDataFork = lcDataForkAtConsensusFork(consensusFork)
|
||||||
|
dag.lcDataStore.db.putHeader(
|
||||||
|
forkyBlck.toLightClientHeader(lcDataFork))
|
||||||
|
else: raiseAssert "Unreachable"
|
||||||
|
dag.lcDataStore.db.putCurrentSyncCommitteeBranch(
|
||||||
|
bid.slot, dag.getLightClientData(bid).current_sync_committee_branch)
|
||||||
|
ok()
|
||||||
|
|
||||||
proc initLightClientDataCache*(dag: ChainDAGRef) =
|
proc initLightClientDataCache*(dag: ChainDAGRef) =
|
||||||
## Initialize cached light client data
|
## Initialize cached light client data
|
||||||
if not dag.shouldImportLcData:
|
if not dag.shouldImportLcData:
|
||||||
@ -712,7 +744,7 @@ proc initLightClientDataCache*(dag: ChainDAGRef) =
|
|||||||
else:
|
else:
|
||||||
false
|
false
|
||||||
|
|
||||||
# Build list of block to process.
|
# Build list of blocks to process.
|
||||||
# As it is slow to load states in descending order,
|
# As it is slow to load states in descending order,
|
||||||
# build a reverse todo list to then process them in ascending order
|
# build a reverse todo list to then process them in ascending order
|
||||||
let tailSlot = dag.lcDataStore.cache.tailSlot
|
let tailSlot = dag.lcDataStore.cache.tailSlot
|
||||||
@ -767,10 +799,16 @@ proc initLightClientDataCache*(dag: ChainDAGRef) =
|
|||||||
current_period_best_update = best,
|
current_period_best_update = best,
|
||||||
latest_signature_slot = GENESIS_SLOT)
|
latest_signature_slot = GENESIS_SLOT)
|
||||||
else:
|
else:
|
||||||
dag.createLightClientUpdates(
|
dag.createLightClientUpdate(
|
||||||
forkyState, forkyBlck, parentBid = blocks[i + 1])
|
forkyState, forkyBlck, parentBid = blocks[i + 1])
|
||||||
else: raiseAssert "Unreachable"
|
else: raiseAssert "Unreachable"
|
||||||
|
|
||||||
|
# Import initial `LightClientBootstrap`
|
||||||
|
if dag.finalizedHead.slot >= dag.lcDataStore.cache.tailSlot:
|
||||||
|
if dag.createLightClientBootstrap(dag.finalizedHead.blck.bid).isErr:
|
||||||
|
dag.handleUnexpectedLightClientError(dag.finalizedHead.blck.bid.slot)
|
||||||
|
res.err()
|
||||||
|
|
||||||
let lightClientEndTick = Moment.now()
|
let lightClientEndTick = Moment.now()
|
||||||
debug "Initialized cached LC data",
|
debug "Initialized cached LC data",
|
||||||
initDur = lightClientEndTick - lightClientStartTick, res
|
initDur = lightClientEndTick - lightClientStartTick, res
|
||||||
@ -807,7 +845,7 @@ proc processNewBlockForLightClient*(
|
|||||||
const consensusFork = typeof(signedBlock).kind
|
const consensusFork = typeof(signedBlock).kind
|
||||||
when consensusFork >= ConsensusFork.Altair:
|
when consensusFork >= ConsensusFork.Altair:
|
||||||
template forkyState: untyped = state.forky(consensusFork)
|
template forkyState: untyped = state.forky(consensusFork)
|
||||||
dag.createLightClientUpdates(forkyState, signedBlock, parentBid)
|
dag.createLightClientUpdate(forkyState, signedBlock, parentBid)
|
||||||
else:
|
else:
|
||||||
raiseAssert "Unreachable" # `tailSlot` cannot be before Altair
|
raiseAssert "Unreachable" # `tailSlot` cannot be before Altair
|
||||||
|
|
||||||
@ -902,38 +940,9 @@ proc processFinalizationForLightClient*(
|
|||||||
break
|
break
|
||||||
bid = bsi.bid
|
bid = bsi.bid
|
||||||
if bid.slot >= lowSlot:
|
if bid.slot >= lowSlot:
|
||||||
let
|
if dag.createLightClientBootstrap(bid).isErr:
|
||||||
bdata = dag.getExistingForkedBlock(bid).valueOr:
|
dag.handleUnexpectedLightClientError(bid.slot)
|
||||||
dag.handleUnexpectedLightClientError(bid.slot)
|
break
|
||||||
break
|
|
||||||
period = bid.slot.sync_committee_period
|
|
||||||
if not dag.lcDataStore.db.hasSyncCommittee(period):
|
|
||||||
let didPutSyncCommittee = withState(dag.headState):
|
|
||||||
when consensusFork >= ConsensusFork.Altair:
|
|
||||||
if period == forkyState.data.slot.sync_committee_period:
|
|
||||||
dag.lcDataStore.db.putSyncCommittee(
|
|
||||||
period, forkyState.data.current_sync_committee)
|
|
||||||
true
|
|
||||||
else:
|
|
||||||
false
|
|
||||||
else:
|
|
||||||
false
|
|
||||||
if not didPutSyncCommittee:
|
|
||||||
let
|
|
||||||
tmpState = assignClone(dag.headState)
|
|
||||||
syncCommittee = dag.existingCurrentSyncCommitteeForPeriod(
|
|
||||||
tmpState[], period).valueOr:
|
|
||||||
dag.handleUnexpectedLightClientError(bid.slot)
|
|
||||||
break
|
|
||||||
dag.lcDataStore.db.putSyncCommittee(period, syncCommittee)
|
|
||||||
withBlck(bdata):
|
|
||||||
when consensusFork >= ConsensusFork.Altair:
|
|
||||||
const lcDataFork = lcDataForkAtConsensusFork(consensusFork)
|
|
||||||
dag.lcDataStore.db.putHeader(
|
|
||||||
forkyBlck.toLightClientHeader(lcDataFork))
|
|
||||||
else: raiseAssert "Unreachable"
|
|
||||||
dag.lcDataStore.db.putCurrentSyncCommitteeBranch(
|
|
||||||
bid.slot, dag.getLightClientData(bid).current_sync_committee_branch)
|
|
||||||
boundarySlot = bid.slot.nextEpochBoundarySlot
|
boundarySlot = bid.slot.nextEpochBoundarySlot
|
||||||
if boundarySlot < SLOTS_PER_EPOCH:
|
if boundarySlot < SLOTS_PER_EPOCH:
|
||||||
break
|
break
|
||||||
|
@ -459,8 +459,19 @@ proc addObject*(
|
|||||||
(afterGenesis, _) = wallTime.toSlot()
|
(afterGenesis, _) = wallTime.toSlot()
|
||||||
|
|
||||||
if not afterGenesis:
|
if not afterGenesis:
|
||||||
error "Processing LC object before genesis, clock turned back?"
|
let mayProcessBeforeGenesis =
|
||||||
quit 1
|
when obj is ForkedLightClientBootstrap:
|
||||||
|
withForkyBootstrap(obj):
|
||||||
|
when lcDataFork > LightClientDataFork.None:
|
||||||
|
forkyBootstrap.header.beacon.slot == GENESIS_SLOT and
|
||||||
|
self.cfg.ALTAIR_FORK_EPOCH == GENESIS_EPOCH
|
||||||
|
else:
|
||||||
|
false
|
||||||
|
else:
|
||||||
|
false
|
||||||
|
if not mayProcessBeforeGenesis:
|
||||||
|
error "Processing LC object before genesis, clock turned back?"
|
||||||
|
quit 1
|
||||||
|
|
||||||
let res = self.storeObject(src, wallTime, obj)
|
let res = self.storeObject(src, wallTime, obj)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user