mirror of
https://github.com/status-im/nimbus-eth2.git
synced 2025-01-10 22:36:01 +00:00
encapsulate LC data variables into single structure (#3777)
Combines the LC data configuration options (serve / importMode), the callbacks (finality / optimistic LC update) as well as the cache storing light client data, into a new `LightClientDataStore` structure. Also moves the structure into a light client specific file.
This commit is contained in:
parent
c45c017349
commit
2e98c7722f
@ -185,12 +185,6 @@ type
|
|||||||
|
|
||||||
cfg*: RuntimeConfig
|
cfg*: RuntimeConfig
|
||||||
|
|
||||||
lightClientDataServe*: bool
|
|
||||||
## Whether to make local light client data available or not
|
|
||||||
|
|
||||||
lightClientDataImportMode*: LightClientDataImportMode
|
|
||||||
## Which classes of light client data to import
|
|
||||||
|
|
||||||
epochRefs*: array[32, EpochRef]
|
epochRefs*: array[32, EpochRef]
|
||||||
## Cached information about a particular epoch ending with the given
|
## Cached information about a particular epoch ending with the given
|
||||||
## block - we limit the number of held EpochRefs to put a cap on
|
## block - we limit the number of held EpochRefs to put a cap on
|
||||||
@ -209,9 +203,10 @@ type
|
|||||||
## called several times.
|
## called several times.
|
||||||
|
|
||||||
# -----------------------------------
|
# -----------------------------------
|
||||||
# Data to enable light clients to stay in sync with the network
|
# Light client data
|
||||||
|
|
||||||
lightClientCache*: LightClientCache
|
lcDataStore*: LightClientDataStore
|
||||||
|
# Data store to enable light clients to sync with the network
|
||||||
|
|
||||||
# -----------------------------------
|
# -----------------------------------
|
||||||
# Callbacks
|
# Callbacks
|
||||||
@ -224,10 +219,6 @@ type
|
|||||||
## On beacon chain reorganization
|
## On beacon chain reorganization
|
||||||
onFinHappened*: OnFinalizedCallback
|
onFinHappened*: OnFinalizedCallback
|
||||||
## On finalization callback
|
## On finalization callback
|
||||||
onLightClientFinalityUpdate*: OnLightClientFinalityUpdateCallback
|
|
||||||
## On new `LightClientFinalityUpdate` callback
|
|
||||||
onLightClientOptimisticUpdate*: OnLightClientOptimisticUpdateCallback
|
|
||||||
## On new `LightClientOptimisticUpdate` callback
|
|
||||||
|
|
||||||
headSyncCommittees*: SyncCommitteeCache
|
headSyncCommittees*: SyncCommitteeCache
|
||||||
## A cache of the sync committees, as they appear in the head state -
|
## A cache of the sync committees, as they appear in the head state -
|
||||||
|
@ -18,11 +18,6 @@ import
|
|||||||
./block_dag
|
./block_dag
|
||||||
|
|
||||||
type
|
type
|
||||||
OnLightClientFinalityUpdateCallback* =
|
|
||||||
proc(data: altair.LightClientFinalityUpdate) {.gcsafe, raises: [Defect].}
|
|
||||||
OnLightClientOptimisticUpdateCallback* =
|
|
||||||
proc(data: altair.LightClientOptimisticUpdate) {.gcsafe, raises: [Defect].}
|
|
||||||
|
|
||||||
LightClientDataImportMode* {.pure.} = enum
|
LightClientDataImportMode* {.pure.} = enum
|
||||||
## Controls which classes of light client data are imported.
|
## Controls which classes of light client data are imported.
|
||||||
None = "none"
|
None = "none"
|
||||||
@ -34,6 +29,11 @@ type
|
|||||||
OnDemand = "on-demand"
|
OnDemand = "on-demand"
|
||||||
## Don't precompute historic data. Slow, may miss validator duties.
|
## Don't precompute historic data. Slow, may miss validator duties.
|
||||||
|
|
||||||
|
OnLightClientFinalityUpdateCallback* =
|
||||||
|
proc(data: altair.LightClientFinalityUpdate) {.gcsafe, raises: [Defect].}
|
||||||
|
OnLightClientOptimisticUpdateCallback* =
|
||||||
|
proc(data: altair.LightClientOptimisticUpdate) {.gcsafe, raises: [Defect].}
|
||||||
|
|
||||||
CachedLightClientData* = object
|
CachedLightClientData* = object
|
||||||
## Cached data from historical non-finalized states to improve speed when
|
## Cached data from historical non-finalized states to improve speed when
|
||||||
## creating future `LightClientUpdate` and `LightClientBootstrap` instances.
|
## creating future `LightClientUpdate` and `LightClientBootstrap` instances.
|
||||||
@ -52,7 +52,7 @@ type
|
|||||||
current_sync_committee_branch*:
|
current_sync_committee_branch*:
|
||||||
array[log2trunc(altair.CURRENT_SYNC_COMMITTEE_INDEX), Eth2Digest]
|
array[log2trunc(altair.CURRENT_SYNC_COMMITTEE_INDEX), Eth2Digest]
|
||||||
|
|
||||||
LightClientCache* = object
|
LightClientDataCache* = object
|
||||||
data*: Table[BlockId, CachedLightClientData]
|
data*: Table[BlockId, CachedLightClientData]
|
||||||
## Cached data for creating future `LightClientUpdate` instances.
|
## Cached data for creating future `LightClientUpdate` instances.
|
||||||
## Key is the block ID of which the post state was used to get the data.
|
## Key is the block ID of which the post state was used to get the data.
|
||||||
@ -79,3 +79,26 @@ type
|
|||||||
|
|
||||||
importTailSlot*: Slot
|
importTailSlot*: Slot
|
||||||
## The earliest slot for which light client data is imported.
|
## The earliest slot for which light client data is imported.
|
||||||
|
|
||||||
|
LightClientDataStore* = object
|
||||||
|
# -----------------------------------
|
||||||
|
# Light client data
|
||||||
|
|
||||||
|
cache*: LightClientDataCache
|
||||||
|
## Cached data to accelerate serving light client data
|
||||||
|
|
||||||
|
# -----------------------------------
|
||||||
|
# Config
|
||||||
|
|
||||||
|
serve*: bool
|
||||||
|
## Whether to make local light client data available or not
|
||||||
|
importMode*: LightClientDataImportMode
|
||||||
|
## Which classes of light client data to import
|
||||||
|
|
||||||
|
# -----------------------------------
|
||||||
|
# Callbacks
|
||||||
|
|
||||||
|
onLightClientFinalityUpdate*: OnLightClientFinalityUpdateCallback
|
||||||
|
## On new `LightClientFinalityUpdate` callback
|
||||||
|
onLightClientOptimisticUpdate*: OnLightClientOptimisticUpdateCallback
|
||||||
|
## On new `LightClientOptimisticUpdate` callback
|
||||||
|
@ -692,7 +692,7 @@ proc init*(T: type ChainDAGRef, cfg: RuntimeConfig, db: BeaconChainDB,
|
|||||||
vanityLogs = default(VanityLogs)): ChainDAGRef =
|
vanityLogs = default(VanityLogs)): ChainDAGRef =
|
||||||
cfg.checkForkConsistency()
|
cfg.checkForkConsistency()
|
||||||
|
|
||||||
doAssert updateFlags in [{}, {verifyFinalization}],
|
doAssert updateFlags - {verifyFinalization, enableTestFeatures} == {},
|
||||||
"Other flags not supported in ChainDAG"
|
"Other flags not supported in ChainDAG"
|
||||||
|
|
||||||
# TODO we require that the db contains both a head and a tail block -
|
# TODO we require that the db contains both a head and a tail block -
|
||||||
@ -725,15 +725,16 @@ proc init*(T: type ChainDAGRef, cfg: RuntimeConfig, db: BeaconChainDB,
|
|||||||
|
|
||||||
vanityLogs: vanityLogs,
|
vanityLogs: vanityLogs,
|
||||||
|
|
||||||
lightClientDataServe: lightClientDataServe,
|
lcDataStore: initLightClientDataStore(
|
||||||
lightClientDataImportMode: lightClientDataImportMode,
|
serve = lightClientDataServe,
|
||||||
|
importMode = lightClientDataImportMode,
|
||||||
|
onLCFinalityUpdateCb = onLCFinalityUpdateCb,
|
||||||
|
onLCOptimisticUpdateCb = onLCOptimisticUpdateCb),
|
||||||
|
|
||||||
onBlockAdded: onBlockCb,
|
onBlockAdded: onBlockCb,
|
||||||
onHeadChanged: onHeadCb,
|
onHeadChanged: onHeadCb,
|
||||||
onReorgHappened: onReorgCb,
|
onReorgHappened: onReorgCb,
|
||||||
onFinHappened: onFinCb,
|
onFinHappened: onFinCb
|
||||||
onLightClientFinalityUpdate: onLCFinalityUpdateCb,
|
|
||||||
onLightClientOptimisticUpdate: onLCOptimisticUpdateCb
|
|
||||||
)
|
)
|
||||||
loadTick = Moment.now()
|
loadTick = Moment.now()
|
||||||
|
|
||||||
@ -953,7 +954,7 @@ proc init*(T: type ChainDAGRef, cfg: RuntimeConfig, db: BeaconChainDB,
|
|||||||
frontfillDur = frontfillTick - finalizedTick,
|
frontfillDur = frontfillTick - finalizedTick,
|
||||||
keysDur = Moment.now() - frontfillTick
|
keysDur = Moment.now() - frontfillTick
|
||||||
|
|
||||||
dag.initLightClientCache()
|
dag.initLightClientDataCache()
|
||||||
|
|
||||||
dag
|
dag
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ func computeEarliestLightClientSlot(dag: ChainDAGRef): Slot =
|
|||||||
let
|
let
|
||||||
minSupportedSlot = max(
|
minSupportedSlot = max(
|
||||||
dag.cfg.ALTAIR_FORK_EPOCH.start_slot,
|
dag.cfg.ALTAIR_FORK_EPOCH.start_slot,
|
||||||
dag.lightClientCache.importTailSlot)
|
dag.lcDataStore.cache.importTailSlot)
|
||||||
currentSlot = getStateField(dag.headState, slot)
|
currentSlot = getStateField(dag.headState, slot)
|
||||||
if currentSlot < minSupportedSlot:
|
if currentSlot < minSupportedSlot:
|
||||||
return minSupportedSlot
|
return minSupportedSlot
|
||||||
@ -150,7 +150,7 @@ proc getLightClientData(
|
|||||||
bid: BlockId): CachedLightClientData =
|
bid: BlockId): CachedLightClientData =
|
||||||
## Fetch cached light client data about a given block.
|
## Fetch cached light client data about a given block.
|
||||||
## Data must be cached (`cacheLightClientData`) before calling this function.
|
## Data must be cached (`cacheLightClientData`) before calling this function.
|
||||||
try: dag.lightClientCache.data[bid]
|
try: dag.lcDataStore.cache.data[bid]
|
||||||
except KeyError: raiseAssert "Unreachable"
|
except KeyError: raiseAssert "Unreachable"
|
||||||
|
|
||||||
proc cacheLightClientData(
|
proc cacheLightClientData(
|
||||||
@ -170,24 +170,24 @@ proc cacheLightClientData(
|
|||||||
state.data.build_proof(
|
state.data.build_proof(
|
||||||
altair.FINALIZED_ROOT_INDEX,
|
altair.FINALIZED_ROOT_INDEX,
|
||||||
cachedData.finality_branch)
|
cachedData.finality_branch)
|
||||||
if dag.lightClientCache.data.hasKeyOrPut(bid, cachedData):
|
if dag.lcDataStore.cache.data.hasKeyOrPut(bid, cachedData):
|
||||||
doAssert false, "Redundant `cacheLightClientData` call"
|
doAssert false, "Redundant `cacheLightClientData` call"
|
||||||
|
|
||||||
proc deleteLightClientData*(dag: ChainDAGRef, bid: BlockId) =
|
proc deleteLightClientData*(dag: ChainDAGRef, bid: BlockId) =
|
||||||
## Delete cached light client data for a given block. This needs to be called
|
## Delete cached light client data for a given block. This needs to be called
|
||||||
## when a block becomes unreachable due to finalization of a different fork.
|
## when a block becomes unreachable due to finalization of a different fork.
|
||||||
if dag.lightClientDataImportMode == LightClientDataImportMode.None:
|
if dag.lcDataStore.importMode == LightClientDataImportMode.None:
|
||||||
return
|
return
|
||||||
|
|
||||||
dag.lightClientCache.data.del bid
|
dag.lcDataStore.cache.data.del bid
|
||||||
|
|
||||||
func handleUnexpectedLightClientError(dag: ChainDAGRef, buggedSlot: Slot) =
|
func handleUnexpectedLightClientError(dag: ChainDAGRef, buggedSlot: Slot) =
|
||||||
## If there is an unexpected error, adjust `importTailSlot` to keep track of
|
## If there is an unexpected error, adjust `importTailSlot` to keep track of
|
||||||
## section for which complete light client data is available, and to avoid
|
## section for which complete light client data is available, and to avoid
|
||||||
## failed lookups of cached light client data.
|
## failed lookups of cached light client data.
|
||||||
doAssert verifyFinalization notin dag.updateFlags
|
doAssert verifyFinalization notin dag.updateFlags
|
||||||
if buggedSlot >= dag.lightClientCache.importTailSlot:
|
if buggedSlot >= dag.lcDataStore.cache.importTailSlot:
|
||||||
dag.lightClientCache.importTailSlot = buggedSlot + 1
|
dag.lcDataStore.cache.importTailSlot = buggedSlot + 1
|
||||||
|
|
||||||
template lazy_header(name: untyped): untyped {.dirty.} =
|
template lazy_header(name: untyped): untyped {.dirty.} =
|
||||||
## `createLightClientUpdates` helper to lazily load a known block header.
|
## `createLightClientUpdates` helper to lazily load a known block header.
|
||||||
@ -262,7 +262,7 @@ proc createLightClientUpdates(
|
|||||||
lazy_header(finalized_header)
|
lazy_header(finalized_header)
|
||||||
|
|
||||||
# Update latest light client data
|
# Update latest light client data
|
||||||
template latest(): auto = dag.lightClientCache.latest
|
template latest(): auto = dag.lcDataStore.cache.latest
|
||||||
var
|
var
|
||||||
newFinality = false
|
newFinality = false
|
||||||
newOptimistic = false
|
newOptimistic = false
|
||||||
@ -303,10 +303,10 @@ proc createLightClientUpdates(
|
|||||||
let isCommitteeFinalized = dag.isNextSyncCommitteeFinalized(attested_period)
|
let isCommitteeFinalized = dag.isNextSyncCommitteeFinalized(attested_period)
|
||||||
var best =
|
var best =
|
||||||
if isCommitteeFinalized:
|
if isCommitteeFinalized:
|
||||||
dag.lightClientCache.best.getOrDefault(attested_period)
|
dag.lcDataStore.cache.best.getOrDefault(attested_period)
|
||||||
else:
|
else:
|
||||||
let key = (attested_period, state.syncCommitteeRoot)
|
let key = (attested_period, state.syncCommitteeRoot)
|
||||||
dag.lightClientCache.pendingBest.getOrDefault(key)
|
dag.lcDataStore.cache.pendingBest.getOrDefault(key)
|
||||||
|
|
||||||
load_attested_data(attested_bid)
|
load_attested_data(attested_bid)
|
||||||
let
|
let
|
||||||
@ -339,19 +339,19 @@ proc createLightClientUpdates(
|
|||||||
best.signature_slot = signature_slot
|
best.signature_slot = signature_slot
|
||||||
|
|
||||||
if isCommitteeFinalized:
|
if isCommitteeFinalized:
|
||||||
dag.lightClientCache.best[attested_period] = best
|
dag.lcDataStore.cache.best[attested_period] = best
|
||||||
debug "Best LC update for period improved",
|
debug "Best LC update for period improved",
|
||||||
period = attested_period, update = best
|
period = attested_period, update = best
|
||||||
else:
|
else:
|
||||||
let key = (attested_period, state.syncCommitteeRoot)
|
let key = (attested_period, state.syncCommitteeRoot)
|
||||||
dag.lightClientCache.pendingBest[key] = best
|
dag.lcDataStore.cache.pendingBest[key] = best
|
||||||
debug "Best LC update for period improved",
|
debug "Best LC update for period improved",
|
||||||
period = key, update = best
|
period = key, update = best
|
||||||
|
|
||||||
if newFinality and dag.onLightClientFinalityUpdate != nil:
|
if newFinality and dag.lcDataStore.onLightClientFinalityUpdate != nil:
|
||||||
dag.onLightClientFinalityUpdate(latest)
|
dag.lcDataStore.onLightClientFinalityUpdate(latest)
|
||||||
if newOptimistic and dag.onLightClientOptimisticUpdate != nil:
|
if newOptimistic and dag.lcDataStore.onLightClientOptimisticUpdate != nil:
|
||||||
dag.onLightClientOptimisticUpdate(latest.toOptimistic)
|
dag.lcDataStore.onLightClientOptimisticUpdate(latest.toOptimistic)
|
||||||
|
|
||||||
proc processNewBlockForLightClient*(
|
proc processNewBlockForLightClient*(
|
||||||
dag: ChainDAGRef,
|
dag: ChainDAGRef,
|
||||||
@ -359,7 +359,7 @@ proc processNewBlockForLightClient*(
|
|||||||
signedBlock: ForkyTrustedSignedBeaconBlock,
|
signedBlock: ForkyTrustedSignedBeaconBlock,
|
||||||
parentBid: BlockId) =
|
parentBid: BlockId) =
|
||||||
## Update light client data with information from a new block.
|
## Update light client data with information from a new block.
|
||||||
if dag.lightClientDataImportMode == LightClientDataImportMode.None:
|
if dag.lcDataStore.importMode == LightClientDataImportMode.None:
|
||||||
return
|
return
|
||||||
if signedBlock.message.slot < dag.computeEarliestLightClientSlot:
|
if signedBlock.message.slot < dag.computeEarliestLightClientSlot:
|
||||||
return
|
return
|
||||||
@ -378,7 +378,7 @@ proc processNewBlockForLightClient*(
|
|||||||
proc processHeadChangeForLightClient*(dag: ChainDAGRef) =
|
proc processHeadChangeForLightClient*(dag: ChainDAGRef) =
|
||||||
## Update light client data to account for a new head block.
|
## Update light client data to account for a new head block.
|
||||||
## Note that `dag.finalizedHead` is not yet updated when this is called.
|
## Note that `dag.finalizedHead` is not yet updated when this is called.
|
||||||
if dag.lightClientDataImportMode == LightClientDataImportMode.None:
|
if dag.lcDataStore.importMode == LightClientDataImportMode.None:
|
||||||
return
|
return
|
||||||
let earliestSlot = dag.computeEarliestLightClientSlot
|
let earliestSlot = dag.computeEarliestLightClientSlot
|
||||||
if dag.head.slot < earliestSlot:
|
if dag.head.slot < earliestSlot:
|
||||||
@ -400,13 +400,13 @@ proc processHeadChangeForLightClient*(dag: ChainDAGRef) =
|
|||||||
dag.handleUnexpectedLightClientError(period.start_slot)
|
dag.handleUnexpectedLightClientError(period.start_slot)
|
||||||
continue
|
continue
|
||||||
key = (period, syncCommitteeRoot)
|
key = (period, syncCommitteeRoot)
|
||||||
dag.lightClientCache.best[period] =
|
dag.lcDataStore.cache.best[period] =
|
||||||
dag.lightClientCache.pendingBest.getOrDefault(key)
|
dag.lcDataStore.cache.pendingBest.getOrDefault(key)
|
||||||
withState(dag.headState): # Common case separate to avoid `tmpState` copy
|
withState(dag.headState): # Common case separate to avoid `tmpState` copy
|
||||||
when stateFork >= BeaconStateFork.Altair:
|
when stateFork >= BeaconStateFork.Altair:
|
||||||
let key = (headPeriod, state.syncCommitteeRoot)
|
let key = (headPeriod, state.syncCommitteeRoot)
|
||||||
dag.lightClientCache.best[headPeriod] =
|
dag.lcDataStore.cache.best[headPeriod] =
|
||||||
dag.lightClientCache.pendingBest.getOrDefault(key)
|
dag.lcDataStore.cache.pendingBest.getOrDefault(key)
|
||||||
else: raiseAssert "Unreachable"
|
else: raiseAssert "Unreachable"
|
||||||
|
|
||||||
proc processFinalizationForLightClient*(
|
proc processFinalizationForLightClient*(
|
||||||
@ -414,7 +414,7 @@ proc processFinalizationForLightClient*(
|
|||||||
## Prune cached data that is no longer useful for creating future
|
## Prune cached data that is no longer useful for creating future
|
||||||
## `LightClientUpdate` and `LightClientBootstrap` instances.
|
## `LightClientUpdate` and `LightClientBootstrap` instances.
|
||||||
## This needs to be called whenever `finalized_checkpoint` changes.
|
## This needs to be called whenever `finalized_checkpoint` changes.
|
||||||
if dag.lightClientDataImportMode == LightClientDataImportMode.None:
|
if dag.lcDataStore.importMode == LightClientDataImportMode.None:
|
||||||
return
|
return
|
||||||
let
|
let
|
||||||
earliestSlot = dag.computeEarliestLightClientSlot
|
earliestSlot = dag.computeEarliestLightClientSlot
|
||||||
@ -432,7 +432,7 @@ proc processFinalizationForLightClient*(
|
|||||||
break
|
break
|
||||||
bid = bsi.bid
|
bid = bsi.bid
|
||||||
if bid.slot >= lowSlot:
|
if bid.slot >= lowSlot:
|
||||||
dag.lightClientCache.bootstrap[bid.slot] =
|
dag.lcDataStore.cache.bootstrap[bid.slot] =
|
||||||
CachedLightClientBootstrap(
|
CachedLightClientBootstrap(
|
||||||
current_sync_committee_branch:
|
current_sync_committee_branch:
|
||||||
dag.getLightClientData(bid).current_sync_committee_branch)
|
dag.getLightClientData(bid).current_sync_committee_branch)
|
||||||
@ -443,39 +443,51 @@ proc processFinalizationForLightClient*(
|
|||||||
|
|
||||||
# Prune light client data that is no longer referrable by future updates
|
# Prune light client data that is no longer referrable by future updates
|
||||||
var bidsToDelete: seq[BlockId]
|
var bidsToDelete: seq[BlockId]
|
||||||
for bid, data in dag.lightClientCache.data:
|
for bid, data in dag.lcDataStore.cache.data:
|
||||||
if bid.slot >= dag.finalizedHead.blck.slot:
|
if bid.slot >= dag.finalizedHead.blck.slot:
|
||||||
continue
|
continue
|
||||||
bidsToDelete.add bid
|
bidsToDelete.add bid
|
||||||
for bid in bidsToDelete:
|
for bid in bidsToDelete:
|
||||||
dag.lightClientCache.data.del bid
|
dag.lcDataStore.cache.data.del bid
|
||||||
|
|
||||||
# Prune bootstrap data that is no longer relevant
|
# Prune bootstrap data that is no longer relevant
|
||||||
var slotsToDelete: seq[Slot]
|
var slotsToDelete: seq[Slot]
|
||||||
for slot in dag.lightClientCache.bootstrap.keys:
|
for slot in dag.lcDataStore.cache.bootstrap.keys:
|
||||||
if slot < earliestSlot:
|
if slot < earliestSlot:
|
||||||
slotsToDelete.add slot
|
slotsToDelete.add slot
|
||||||
for slot in slotsToDelete:
|
for slot in slotsToDelete:
|
||||||
dag.lightClientCache.bootstrap.del slot
|
dag.lcDataStore.cache.bootstrap.del slot
|
||||||
|
|
||||||
# Prune best `LightClientUpdate` that are no longer relevant
|
# Prune best `LightClientUpdate` that are no longer relevant
|
||||||
let earliestPeriod = earliestSlot.sync_committee_period
|
let earliestPeriod = earliestSlot.sync_committee_period
|
||||||
var periodsToDelete: seq[SyncCommitteePeriod]
|
var periodsToDelete: seq[SyncCommitteePeriod]
|
||||||
for period in dag.lightClientCache.best.keys:
|
for period in dag.lcDataStore.cache.best.keys:
|
||||||
if period < earliestPeriod:
|
if period < earliestPeriod:
|
||||||
periodsToDelete.add period
|
periodsToDelete.add period
|
||||||
for period in periodsToDelete:
|
for period in periodsToDelete:
|
||||||
dag.lightClientCache.best.del period
|
dag.lcDataStore.cache.best.del period
|
||||||
|
|
||||||
# Prune best `LightClientUpdate` referring to non-finalized sync committees
|
# Prune best `LightClientUpdate` referring to non-finalized sync committees
|
||||||
# that are no longer relevant, i.e., orphaned or too old
|
# that are no longer relevant, i.e., orphaned or too old
|
||||||
let firstNonFinalizedPeriod = dag.firstNonFinalizedPeriod
|
let firstNonFinalizedPeriod = dag.firstNonFinalizedPeriod
|
||||||
var keysToDelete: seq[(SyncCommitteePeriod, Eth2Digest)]
|
var keysToDelete: seq[(SyncCommitteePeriod, Eth2Digest)]
|
||||||
for (period, committeeRoot) in dag.lightClientCache.pendingBest.keys:
|
for (period, committeeRoot) in dag.lcDataStore.cache.pendingBest.keys:
|
||||||
if period < firstNonFinalizedPeriod:
|
if period < firstNonFinalizedPeriod:
|
||||||
keysToDelete.add (period, committeeRoot)
|
keysToDelete.add (period, committeeRoot)
|
||||||
for key in keysToDelete:
|
for key in keysToDelete:
|
||||||
dag.lightClientCache.pendingBest.del key
|
dag.lcDataStore.cache.pendingBest.del key
|
||||||
|
|
||||||
|
func initLightClientDataStore*(
|
||||||
|
serve: bool, importMode: LightClientDataImportMode,
|
||||||
|
onLCFinalityUpdateCb: OnLightClientFinalityUpdateCallback = nil,
|
||||||
|
onLCOptimisticUpdateCb: OnLightClientOptimisticUpdateCallback = nil
|
||||||
|
): LightClientDataStore =
|
||||||
|
## Initialize light client data collector.
|
||||||
|
LightClientDataStore(
|
||||||
|
serve: serve,
|
||||||
|
importMode: importMode,
|
||||||
|
onLightClientFinalityUpdate: onLCFinalityUpdateCb,
|
||||||
|
onLightClientOptimisticUpdate: onLCOptimisticUpdateCb)
|
||||||
|
|
||||||
proc initLightClientBootstrapForPeriod(
|
proc initLightClientBootstrapForPeriod(
|
||||||
dag: ChainDAGRef,
|
dag: ChainDAGRef,
|
||||||
@ -516,7 +528,7 @@ proc initLightClientBootstrapForPeriod(
|
|||||||
bid = bsi.bid
|
bid = bsi.bid
|
||||||
boundarySlot = bid.slot.nextEpochBoundarySlot
|
boundarySlot = bid.slot.nextEpochBoundarySlot
|
||||||
if boundarySlot == nextBoundarySlot and bid.slot >= lowSlot and
|
if boundarySlot == nextBoundarySlot and bid.slot >= lowSlot and
|
||||||
not dag.lightClientCache.bootstrap.hasKey(bid.slot):
|
not dag.lcDataStore.cache.bootstrap.hasKey(bid.slot):
|
||||||
var cachedBootstrap {.noinit.}: CachedLightClientBootstrap
|
var cachedBootstrap {.noinit.}: CachedLightClientBootstrap
|
||||||
if not dag.updateExistingState(
|
if not dag.updateExistingState(
|
||||||
tmpState[], bid.atSlot, save = false, tmpCache):
|
tmpState[], bid.atSlot, save = false, tmpCache):
|
||||||
@ -528,7 +540,7 @@ proc initLightClientBootstrapForPeriod(
|
|||||||
altair.CURRENT_SYNC_COMMITTEE_INDEX,
|
altair.CURRENT_SYNC_COMMITTEE_INDEX,
|
||||||
cachedBootstrap.current_sync_committee_branch)
|
cachedBootstrap.current_sync_committee_branch)
|
||||||
else: raiseAssert "Unreachable"
|
else: raiseAssert "Unreachable"
|
||||||
dag.lightClientCache.bootstrap[bid.slot] = cachedBootstrap
|
dag.lcDataStore.cache.bootstrap[bid.slot] = cachedBootstrap
|
||||||
|
|
||||||
proc initLightClientUpdateForPeriod(
|
proc initLightClientUpdateForPeriod(
|
||||||
dag: ChainDAGRef, period: SyncCommitteePeriod) =
|
dag: ChainDAGRef, period: SyncCommitteePeriod) =
|
||||||
@ -543,7 +555,7 @@ proc initLightClientUpdateForPeriod(
|
|||||||
periodEndSlot = periodStartSlot + SLOTS_PER_SYNC_COMMITTEE_PERIOD - 1
|
periodEndSlot = periodStartSlot + SLOTS_PER_SYNC_COMMITTEE_PERIOD - 1
|
||||||
if periodEndSlot < earliestSlot:
|
if periodEndSlot < earliestSlot:
|
||||||
return
|
return
|
||||||
if dag.lightClientCache.best.hasKey(period):
|
if dag.lcDataStore.cache.best.hasKey(period):
|
||||||
return
|
return
|
||||||
|
|
||||||
let startTick = Moment.now()
|
let startTick = Moment.now()
|
||||||
@ -553,7 +565,7 @@ proc initLightClientUpdateForPeriod(
|
|||||||
# replicated on every `return`, and the log statement allocates another
|
# replicated on every `return`, and the log statement allocates another
|
||||||
# copy of the arguments on the stack for each instantiation (~1 MB stack!)
|
# copy of the arguments on the stack for each instantiation (~1 MB stack!)
|
||||||
debug "Best LC update for period computed",
|
debug "Best LC update for period computed",
|
||||||
period, update = dag.lightClientCache.best.getOrDefault(period),
|
period, update = dag.lcDataStore.cache.best.getOrDefault(period),
|
||||||
computeDur = endTick - startTick
|
computeDur = endTick - startTick
|
||||||
defer: logBest()
|
defer: logBest()
|
||||||
|
|
||||||
@ -605,7 +617,7 @@ proc initLightClientUpdateForPeriod(
|
|||||||
maxParticipantsRes = dag.maxParticipantsBlock(highBid, lowSlot)
|
maxParticipantsRes = dag.maxParticipantsBlock(highBid, lowSlot)
|
||||||
maxParticipantsBid = maxParticipantsRes.bid.valueOr:
|
maxParticipantsBid = maxParticipantsRes.bid.valueOr:
|
||||||
if maxParticipantsRes.ok: # No single valid block exists in the period
|
if maxParticipantsRes.ok: # No single valid block exists in the period
|
||||||
dag.lightClientCache.best[period] = default(altair.LightClientUpdate)
|
dag.lcDataStore.cache.best[period] = default(altair.LightClientUpdate)
|
||||||
return
|
return
|
||||||
|
|
||||||
# The block with highest participation may refer to a `finalized_checkpoint`
|
# The block with highest participation may refer to a `finalized_checkpoint`
|
||||||
@ -696,15 +708,15 @@ proc initLightClientUpdateForPeriod(
|
|||||||
update.sync_aggregate = blck.asSigned().message.body.sync_aggregate
|
update.sync_aggregate = blck.asSigned().message.body.sync_aggregate
|
||||||
else: raiseAssert "Unreachable"
|
else: raiseAssert "Unreachable"
|
||||||
update.signature_slot = signatureBid.slot
|
update.signature_slot = signatureBid.slot
|
||||||
dag.lightClientCache.best[period] = update
|
dag.lcDataStore.cache.best[period] = update
|
||||||
|
|
||||||
proc initLightClientCache*(dag: ChainDAGRef) =
|
proc initLightClientDataCache*(dag: ChainDAGRef) =
|
||||||
## Initialize cached light client data
|
## Initialize cached light client data
|
||||||
if dag.lightClientDataImportMode == LightClientDataImportMode.None:
|
if dag.lcDataStore.importMode == LightClientDataImportMode.None:
|
||||||
return
|
return
|
||||||
dag.lightClientCache.importTailSlot = dag.tail.slot
|
dag.lcDataStore.cache.importTailSlot = dag.tail.slot
|
||||||
if dag.lightClientDataImportMode == LightClientDataImportMode.OnlyNew:
|
if dag.lcDataStore.importMode == LightClientDataImportMode.OnlyNew:
|
||||||
dag.lightClientCache.importTailSlot = dag.head.slot
|
dag.lcDataStore.cache.importTailSlot = dag.head.slot
|
||||||
var earliestSlot = dag.computeEarliestLightClientSlot
|
var earliestSlot = dag.computeEarliestLightClientSlot
|
||||||
if dag.head.slot < earliestSlot:
|
if dag.head.slot < earliestSlot:
|
||||||
return
|
return
|
||||||
@ -726,7 +738,7 @@ proc initLightClientCache*(dag: ChainDAGRef) =
|
|||||||
# be updated incrementally, because those blocks / states are passed in
|
# be updated incrementally, because those blocks / states are passed in
|
||||||
# directly. It is only historical blocks (or sync committees) that depend
|
# directly. It is only historical blocks (or sync committees) that depend
|
||||||
# on a potentially corrupted database.
|
# on a potentially corrupted database.
|
||||||
doAssert buggedBid.slot > dag.lightClientCache.importTailSlot
|
doAssert buggedBid.slot > dag.lcDataStore.cache.importTailSlot
|
||||||
dag.handleUnexpectedLightClientError(buggedBid.slot)
|
dag.handleUnexpectedLightClientError(buggedBid.slot)
|
||||||
earliestSlot = dag.computeEarliestLightClientSlot
|
earliestSlot = dag.computeEarliestLightClientSlot
|
||||||
|
|
||||||
@ -775,7 +787,7 @@ proc initLightClientCache*(dag: ChainDAGRef) =
|
|||||||
initDur = lightClientEndTick - lightClientStartTick
|
initDur = lightClientEndTick - lightClientStartTick
|
||||||
|
|
||||||
# Import historic data
|
# Import historic data
|
||||||
if dag.lightClientDataImportMode == LightClientDataImportMode.Full:
|
if dag.lcDataStore.importMode == LightClientDataImportMode.Full:
|
||||||
let earliestPeriod = earliestSlot.sync_committee_period
|
let earliestPeriod = earliestSlot.sync_committee_period
|
||||||
for period in earliestPeriod ..< finalizedPeriod:
|
for period in earliestPeriod ..< finalizedPeriod:
|
||||||
dag.initLightClientBootstrapForPeriod(period)
|
dag.initLightClientBootstrapForPeriod(period)
|
||||||
@ -784,7 +796,7 @@ proc initLightClientCache*(dag: ChainDAGRef) =
|
|||||||
proc getLightClientBootstrap*(
|
proc getLightClientBootstrap*(
|
||||||
dag: ChainDAGRef,
|
dag: ChainDAGRef,
|
||||||
blockRoot: Eth2Digest): Opt[altair.LightClientBootstrap] =
|
blockRoot: Eth2Digest): Opt[altair.LightClientBootstrap] =
|
||||||
if not dag.lightClientDataServe:
|
if not dag.lcDataStore.serve:
|
||||||
return err()
|
return err()
|
||||||
|
|
||||||
let bdata = dag.getForkedBlock(blockRoot).valueOr:
|
let bdata = dag.getForkedBlock(blockRoot).valueOr:
|
||||||
@ -801,9 +813,9 @@ proc getLightClientBootstrap*(
|
|||||||
if slot > dag.finalizedHead.blck.slot:
|
if slot > dag.finalizedHead.blck.slot:
|
||||||
debug "LC bootstrap unavailable: Not finalized", blockRoot
|
debug "LC bootstrap unavailable: Not finalized", blockRoot
|
||||||
return err()
|
return err()
|
||||||
var cachedBootstrap = dag.lightClientCache.bootstrap.getOrDefault(slot)
|
var cachedBootstrap = dag.lcDataStore.cache.bootstrap.getOrDefault(slot)
|
||||||
if cachedBootstrap.current_sync_committee_branch.isZeroMemory:
|
if cachedBootstrap.current_sync_committee_branch.isZeroMemory:
|
||||||
if dag.lightClientDataImportMode == LightClientDataImportMode.OnDemand:
|
if dag.lcDataStore.importMode == LightClientDataImportMode.OnDemand:
|
||||||
let bsi = ? dag.getExistingBlockIdAtSlot(slot)
|
let bsi = ? dag.getExistingBlockIdAtSlot(slot)
|
||||||
var tmpState = assignClone(dag.headState)
|
var tmpState = assignClone(dag.headState)
|
||||||
dag.withUpdatedExistingState(tmpState[], bsi) do:
|
dag.withUpdatedExistingState(tmpState[], bsi) do:
|
||||||
@ -814,7 +826,7 @@ proc getLightClientBootstrap*(
|
|||||||
cachedBootstrap.current_sync_committee_branch)
|
cachedBootstrap.current_sync_committee_branch)
|
||||||
else: raiseAssert "Unreachable"
|
else: raiseAssert "Unreachable"
|
||||||
do: return err()
|
do: return err()
|
||||||
dag.lightClientCache.bootstrap[slot] = cachedBootstrap
|
dag.lcDataStore.cache.bootstrap[slot] = cachedBootstrap
|
||||||
else:
|
else:
|
||||||
debug "LC bootstrap unavailable: Data not cached", slot
|
debug "LC bootstrap unavailable: Data not cached", slot
|
||||||
return err()
|
return err()
|
||||||
@ -836,32 +848,32 @@ proc getLightClientBootstrap*(
|
|||||||
proc getLightClientUpdateForPeriod*(
|
proc getLightClientUpdateForPeriod*(
|
||||||
dag: ChainDAGRef,
|
dag: ChainDAGRef,
|
||||||
period: SyncCommitteePeriod): Option[altair.LightClientUpdate] =
|
period: SyncCommitteePeriod): Option[altair.LightClientUpdate] =
|
||||||
if not dag.lightClientDataServe:
|
if not dag.lcDataStore.serve:
|
||||||
return
|
return
|
||||||
|
|
||||||
if dag.lightClientDataImportMode == LightClientDataImportMode.OnDemand:
|
if dag.lcDataStore.importMode == LightClientDataImportMode.OnDemand:
|
||||||
dag.initLightClientUpdateForPeriod(period)
|
dag.initLightClientUpdateForPeriod(period)
|
||||||
result = some(dag.lightClientCache.best.getOrDefault(period))
|
result = some(dag.lcDataStore.cache.best.getOrDefault(period))
|
||||||
let numParticipants = countOnes(result.get.sync_aggregate.sync_committee_bits)
|
let numParticipants = countOnes(result.get.sync_aggregate.sync_committee_bits)
|
||||||
if numParticipants < MIN_SYNC_COMMITTEE_PARTICIPANTS:
|
if numParticipants < MIN_SYNC_COMMITTEE_PARTICIPANTS:
|
||||||
result.reset()
|
result.reset()
|
||||||
|
|
||||||
proc getLightClientFinalityUpdate*(
|
proc getLightClientFinalityUpdate*(
|
||||||
dag: ChainDAGRef): Option[altair.LightClientFinalityUpdate] =
|
dag: ChainDAGRef): Option[altair.LightClientFinalityUpdate] =
|
||||||
if not dag.lightClientDataServe:
|
if not dag.lcDataStore.serve:
|
||||||
return
|
return
|
||||||
|
|
||||||
result = some(dag.lightClientCache.latest)
|
result = some(dag.lcDataStore.cache.latest)
|
||||||
let numParticipants = countOnes(result.get.sync_aggregate.sync_committee_bits)
|
let numParticipants = countOnes(result.get.sync_aggregate.sync_committee_bits)
|
||||||
if numParticipants < MIN_SYNC_COMMITTEE_PARTICIPANTS:
|
if numParticipants < MIN_SYNC_COMMITTEE_PARTICIPANTS:
|
||||||
result.reset()
|
result.reset()
|
||||||
|
|
||||||
proc getLightClientOptimisticUpdate*(
|
proc getLightClientOptimisticUpdate*(
|
||||||
dag: ChainDAGRef): Option[altair.LightClientOptimisticUpdate] =
|
dag: ChainDAGRef): Option[altair.LightClientOptimisticUpdate] =
|
||||||
if not dag.lightClientDataServe:
|
if not dag.lcDataStore.serve:
|
||||||
return
|
return
|
||||||
|
|
||||||
result = some(dag.lightClientCache.latest.toOptimistic)
|
result = some(dag.lcDataStore.cache.latest.toOptimistic)
|
||||||
let numParticipants = countOnes(result.get.sync_aggregate.sync_committee_bits)
|
let numParticipants = countOnes(result.get.sync_aggregate.sync_committee_bits)
|
||||||
if numParticipants < MIN_SYNC_COMMITTEE_PARTICIPANTS:
|
if numParticipants < MIN_SYNC_COMMITTEE_PARTICIPANTS:
|
||||||
result.reset()
|
result.reset()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# beacon_chain
|
# beacon_chain
|
||||||
# Copyright (c) 2018-2021 Status Research & Development GmbH
|
# Copyright (c) 2018-2022 Status Research & Development GmbH
|
||||||
# Licensed and distributed under either of
|
# Licensed and distributed under either of
|
||||||
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
||||||
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
||||||
@ -34,5 +34,7 @@ type
|
|||||||
## When process_slots() is being called as part of a state_transition(),
|
## When process_slots() is being called as part of a state_transition(),
|
||||||
## the hash_tree_root() from the block will fill in the state.root so it
|
## the hash_tree_root() from the block will fill in the state.root so it
|
||||||
## should skip calculating that last state root.
|
## should skip calculating that last state root.
|
||||||
|
enableTestFeatures ##\
|
||||||
|
## Whether to enable extra features for testing.
|
||||||
|
|
||||||
UpdateFlags* = set[UpdateFlag]
|
UpdateFlags* = set[UpdateFlag]
|
||||||
|
@ -1057,7 +1057,7 @@ proc validateLightClientFinalityUpdate*(
|
|||||||
# `signature_slot` was given enough time to propagate through the network.
|
# `signature_slot` was given enough time to propagate through the network.
|
||||||
return errIgnore("LightClientFinalityUpdate: received too early")
|
return errIgnore("LightClientFinalityUpdate: received too early")
|
||||||
|
|
||||||
if finality_update != dag.lightClientCache.latest:
|
if finality_update != dag.lcDataStore.cache.latest:
|
||||||
# [IGNORE] The received `finality_update` matches the locally computed one
|
# [IGNORE] The received `finality_update` matches the locally computed one
|
||||||
# exactly.
|
# exactly.
|
||||||
return errIgnore("LightClientFinalityUpdate: not matching local")
|
return errIgnore("LightClientFinalityUpdate: not matching local")
|
||||||
@ -1085,7 +1085,7 @@ proc validateLightClientOptimisticUpdate*(
|
|||||||
# `signature_slot` was given enough time to propagate through the network.
|
# `signature_slot` was given enough time to propagate through the network.
|
||||||
return errIgnore("LightClientOptimisticUpdate: received too early")
|
return errIgnore("LightClientOptimisticUpdate: received too early")
|
||||||
|
|
||||||
if not optimistic_update.matches(dag.lightClientCache.latest):
|
if not optimistic_update.matches(dag.lcDataStore.cache.latest):
|
||||||
# [IGNORE] The received `optimistic_update` matches the locally computed one
|
# [IGNORE] The received `optimistic_update` matches the locally computed one
|
||||||
# exactly.
|
# exactly.
|
||||||
return errIgnore("LightClientOptimisticUpdate: not matching local")
|
return errIgnore("LightClientOptimisticUpdate: not matching local")
|
||||||
|
@ -87,6 +87,56 @@ type
|
|||||||
else:
|
else:
|
||||||
incompatibilityDesc*: string
|
incompatibilityDesc*: string
|
||||||
|
|
||||||
|
type DeploymentPhase* {.pure.} = enum
|
||||||
|
None,
|
||||||
|
Devnet,
|
||||||
|
Testnet,
|
||||||
|
Mainnet
|
||||||
|
|
||||||
|
func deploymentPhase*(genesisData: string): DeploymentPhase =
|
||||||
|
# SSZ processing at compile time does not work well.
|
||||||
|
#
|
||||||
|
# `BeaconState` layout:
|
||||||
|
# ```
|
||||||
|
# - genesis_time: uint64
|
||||||
|
# - genesis_validators_root: Eth2Digest
|
||||||
|
# - ...
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# Comparing the first 40 bytes covers those two fields,
|
||||||
|
# which should identify the network with high likelihood.
|
||||||
|
# ''.join('%02X'%b for b in open("network_name/genesis.ssz", "rb").read()[:40])
|
||||||
|
if genesisData.len < 40:
|
||||||
|
return DeploymentPhase.None
|
||||||
|
|
||||||
|
const
|
||||||
|
mainnets = [
|
||||||
|
# Mainnet
|
||||||
|
"5730C65F000000004B363DB94E286120D76EB905340FDD4E54BFE9F06BF33FF6CF5AD27F511BFE95",
|
||||||
|
]
|
||||||
|
testnets = [
|
||||||
|
# Kiln
|
||||||
|
"0C572B620000000099B09FCD43E5905236C370F184056BEC6E6638CFC31A323B304FC4AA789CB4AD",
|
||||||
|
# Ropsten
|
||||||
|
"F0DB94620000000044F1E56283CA88B35C789F7F449E52339BC1FEFE3A45913A43A6D16EDCD33CF1",
|
||||||
|
# Prater
|
||||||
|
"60F4596000000000043DB0D9A83813551EE2F33450D23797757D430911A9320530AD8A0EABC43EFB",
|
||||||
|
# Sepolia
|
||||||
|
"607DB06200000000D8EA171F3C94AEA21EBC42A1ED61052ACF3F9209C00E4EFBAADDAC09ED9B8078",
|
||||||
|
]
|
||||||
|
devnets = [
|
||||||
|
"placeholder",
|
||||||
|
]
|
||||||
|
|
||||||
|
let data = (genesisData[0 ..< 40].toHex())
|
||||||
|
if data in mainnets:
|
||||||
|
return DeploymentPhase.Mainnet
|
||||||
|
if data in testnets:
|
||||||
|
return DeploymentPhase.Testnet
|
||||||
|
if data in devnets:
|
||||||
|
return DeploymentPhase.Devnet
|
||||||
|
DeploymentPhase.None
|
||||||
|
|
||||||
const
|
const
|
||||||
eth2NetworksDir = currentSourcePath.parentDir.replace('\\', '/') & "/../../vendor/eth2-networks"
|
eth2NetworksDir = currentSourcePath.parentDir.replace('\\', '/') & "/../../vendor/eth2-networks"
|
||||||
mergeTestnetsDir = currentSourcePath.parentDir.replace('\\', '/') & "/../../vendor/merge-testnets"
|
mergeTestnetsDir = currentSourcePath.parentDir.replace('\\', '/') & "/../../vendor/merge-testnets"
|
||||||
@ -166,42 +216,16 @@ proc loadEth2NetworkMetadata*(path: string, eth1Network = none(Eth1Network)): Et
|
|||||||
else:
|
else:
|
||||||
""
|
""
|
||||||
|
|
||||||
shouldSupportLightClient =
|
deploymentPhase = genesisData.deploymentPhase
|
||||||
if genesisData.len >= 40:
|
|
||||||
# SSZ processing at compile time does not work well.
|
|
||||||
#
|
|
||||||
# `BeaconState` layout:
|
|
||||||
# ```
|
|
||||||
# - genesis_time: uint64
|
|
||||||
# - genesis_validators_root: Eth2Digest
|
|
||||||
# - ...
|
|
||||||
# ```
|
|
||||||
#
|
|
||||||
# Comparing the first 40 bytes covers those two fields,
|
|
||||||
# which should identify the network with high likelihood.
|
|
||||||
# ''.join('%02X'%b for b in open("network_name/genesis.ssz", "rb").read()[:40])
|
|
||||||
let data = (genesisData[0 ..< 40].toHex())
|
|
||||||
data in [
|
|
||||||
# Kiln
|
|
||||||
"0C572B620000000099B09FCD43E5905236C370F184056BEC6E6638CFC31A323B304FC4AA789CB4AD",
|
|
||||||
# Ropsten
|
|
||||||
"F0DB94620000000044F1E56283CA88B35C789F7F449E52339BC1FEFE3A45913A43A6D16EDCD33CF1",
|
|
||||||
# Prater
|
|
||||||
"60F4596000000000043DB0D9A83813551EE2F33450D23797757D430911A9320530AD8A0EABC43EFB",
|
|
||||||
# Sepolia
|
|
||||||
"607DB06200000000D8EA171F3C94AEA21EBC42A1ED61052ACF3F9209C00E4EFBAADDAC09ED9B8078",
|
|
||||||
]
|
|
||||||
else:
|
|
||||||
false
|
|
||||||
|
|
||||||
configDefaults =
|
configDefaults =
|
||||||
Eth2NetworkConfigDefaults(
|
Eth2NetworkConfigDefaults(
|
||||||
lightClientEnable:
|
lightClientEnable:
|
||||||
false, # Only produces debug logs so far
|
false, # Only produces debug logs so far
|
||||||
lightClientDataServe:
|
lightClientDataServe:
|
||||||
shouldSupportLightClient,
|
deploymentPhase <= DeploymentPhase.Testnet,
|
||||||
lightClientDataImportMode:
|
lightClientDataImportMode:
|
||||||
if shouldSupportLightClient:
|
if deploymentPhase <= DeploymentPhase.Testnet:
|
||||||
LightClientDataImportMode.OnlyNew
|
LightClientDataImportMode.OnlyNew
|
||||||
else:
|
else:
|
||||||
LightClientDataImportMode.None
|
LightClientDataImportMode.None
|
||||||
|
@ -151,7 +151,8 @@ proc loadChainDag(
|
|||||||
db: BeaconChainDB,
|
db: BeaconChainDB,
|
||||||
eventBus: EventBus,
|
eventBus: EventBus,
|
||||||
validatorMonitor: ref ValidatorMonitor,
|
validatorMonitor: ref ValidatorMonitor,
|
||||||
networkGenesisValidatorsRoot: Option[Eth2Digest]): ChainDAGRef =
|
networkGenesisValidatorsRoot: Option[Eth2Digest],
|
||||||
|
shouldEnableTestFeatures: bool): ChainDAGRef =
|
||||||
var dag: ChainDAGRef
|
var dag: ChainDAGRef
|
||||||
info "Loading block DAG from database", path = config.databaseDir
|
info "Loading block DAG from database", path = config.databaseDir
|
||||||
|
|
||||||
@ -173,6 +174,9 @@ proc loadChainDag(
|
|||||||
eventBus.optUpdateQueue.emit(data)
|
eventBus.optUpdateQueue.emit(data)
|
||||||
|
|
||||||
let
|
let
|
||||||
|
extraFlags =
|
||||||
|
if shouldEnableTestFeatures: {enableTestFeatures}
|
||||||
|
else: {}
|
||||||
chainDagFlags =
|
chainDagFlags =
|
||||||
if config.verifyFinalization: {verifyFinalization}
|
if config.verifyFinalization: {verifyFinalization}
|
||||||
else: {}
|
else: {}
|
||||||
@ -184,7 +188,7 @@ proc loadChainDag(
|
|||||||
else: nil
|
else: nil
|
||||||
|
|
||||||
dag = ChainDAGRef.init(
|
dag = ChainDAGRef.init(
|
||||||
cfg, db, validatorMonitor, chainDagFlags, config.eraDir,
|
cfg, db, validatorMonitor, extraFlags + chainDagFlags, config.eraDir,
|
||||||
onBlockAdded, onHeadChanged, onChainReorg,
|
onBlockAdded, onHeadChanged, onChainReorg,
|
||||||
onLCFinalityUpdateCb = onLightClientFinalityUpdateCb,
|
onLCFinalityUpdateCb = onLightClientFinalityUpdateCb,
|
||||||
onLCOptimisticUpdateCb = onLightClientOptimisticUpdateCb,
|
onLCOptimisticUpdateCb = onLightClientOptimisticUpdateCb,
|
||||||
@ -580,7 +584,8 @@ proc init*(T: type BeaconNode,
|
|||||||
none(Eth2Digest)
|
none(Eth2Digest)
|
||||||
dag = loadChainDag(
|
dag = loadChainDag(
|
||||||
config, cfg, db, eventBus,
|
config, cfg, db, eventBus,
|
||||||
validatorMonitor, networkGenesisValidatorsRoot)
|
validatorMonitor, networkGenesisValidatorsRoot,
|
||||||
|
genesisStateContents.deploymentPhase <= DeploymentPhase.Devnet)
|
||||||
genesisTime = getStateField(dag.headState, genesis_time)
|
genesisTime = getStateField(dag.headState, genesis_time)
|
||||||
beaconClock = BeaconClock.init(genesisTime)
|
beaconClock = BeaconClock.init(genesisTime)
|
||||||
getBeaconTime = beaconClock.getBeaconTimeFn()
|
getBeaconTime = beaconClock.getBeaconTimeFn()
|
||||||
@ -1329,7 +1334,7 @@ proc installRestHandlers(restServer: RestServerRef, node: BeaconNode) =
|
|||||||
restServer.router.installNimbusApiHandlers(node)
|
restServer.router.installNimbusApiHandlers(node)
|
||||||
restServer.router.installNodeApiHandlers(node)
|
restServer.router.installNodeApiHandlers(node)
|
||||||
restServer.router.installValidatorApiHandlers(node)
|
restServer.router.installValidatorApiHandlers(node)
|
||||||
if node.dag.lightClientDataServe:
|
if node.dag.lcDataStore.serve:
|
||||||
restServer.router.installLightClientApiHandlers(node)
|
restServer.router.installLightClientApiHandlers(node)
|
||||||
|
|
||||||
proc installMessageValidators(node: BeaconNode) =
|
proc installMessageValidators(node: BeaconNode) =
|
||||||
|
@ -92,7 +92,7 @@ proc installEventApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
|||||||
return RestApiResponse.jsonError(Http400, "Invalid topics value",
|
return RestApiResponse.jsonError(Http400, "Invalid topics value",
|
||||||
$topics.error())
|
$topics.error())
|
||||||
let res = validateEventTopics(topics.get(),
|
let res = validateEventTopics(topics.get(),
|
||||||
node.dag.lightClientDataServe)
|
node.dag.lcDataStore.serve)
|
||||||
if res.isErr():
|
if res.isErr():
|
||||||
return RestApiResponse.jsonError(Http400, "Invalid topics value",
|
return RestApiResponse.jsonError(Http400, "Invalid topics value",
|
||||||
$res.error())
|
$res.error())
|
||||||
@ -145,12 +145,12 @@ proc installEventApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
|||||||
"contribution_and_proof")
|
"contribution_and_proof")
|
||||||
res.add(handler)
|
res.add(handler)
|
||||||
if EventTopic.LightClientFinalityUpdate in eventTopics:
|
if EventTopic.LightClientFinalityUpdate in eventTopics:
|
||||||
doAssert node.dag.lightClientDataServe
|
doAssert node.dag.lcDataStore.serve
|
||||||
let handler = response.eventHandler(node.eventBus.finUpdateQueue,
|
let handler = response.eventHandler(node.eventBus.finUpdateQueue,
|
||||||
"light_client_finality_update_v0")
|
"light_client_finality_update_v0")
|
||||||
res.add(handler)
|
res.add(handler)
|
||||||
if EventTopic.LightClientOptimisticUpdate in eventTopics:
|
if EventTopic.LightClientOptimisticUpdate in eventTopics:
|
||||||
doAssert node.dag.lightClientDataServe
|
doAssert node.dag.lcDataStore.serve
|
||||||
let handler = response.eventHandler(node.eventBus.optUpdateQueue,
|
let handler = response.eventHandler(node.eventBus.optUpdateQueue,
|
||||||
"light_client_optimistic_update_v0")
|
"light_client_optimistic_update_v0")
|
||||||
res.add(handler)
|
res.add(handler)
|
||||||
|
@ -18,7 +18,7 @@ proc installLightClientApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
|||||||
router.api(MethodGet,
|
router.api(MethodGet,
|
||||||
"/eth/v0/beacon/light_client/bootstrap/{block_root}") do (
|
"/eth/v0/beacon/light_client/bootstrap/{block_root}") do (
|
||||||
block_root: Eth2Digest) -> RestApiResponse:
|
block_root: Eth2Digest) -> RestApiResponse:
|
||||||
doAssert node.dag.lightClientDataServe
|
doAssert node.dag.lcDataStore.serve
|
||||||
let vroot = block:
|
let vroot = block:
|
||||||
if block_root.isErr():
|
if block_root.isErr():
|
||||||
return RestApiResponse.jsonError(Http400, InvalidBlockRootValueError,
|
return RestApiResponse.jsonError(Http400, InvalidBlockRootValueError,
|
||||||
@ -36,7 +36,7 @@ proc installLightClientApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
|||||||
"/eth/v0/beacon/light_client/updates") do (
|
"/eth/v0/beacon/light_client/updates") do (
|
||||||
start_period: Option[SyncCommitteePeriod], count: Option[uint64]
|
start_period: Option[SyncCommitteePeriod], count: Option[uint64]
|
||||||
) -> RestApiResponse:
|
) -> RestApiResponse:
|
||||||
doAssert node.dag.lightClientDataServe
|
doAssert node.dag.lcDataStore.serve
|
||||||
let vstart = block:
|
let vstart = block:
|
||||||
if start_period.isNone():
|
if start_period.isNone():
|
||||||
return RestApiResponse.jsonError(Http400, MissingStartPeriodValueError)
|
return RestApiResponse.jsonError(Http400, MissingStartPeriodValueError)
|
||||||
@ -75,7 +75,7 @@ proc installLightClientApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
|||||||
router.api(MethodGet,
|
router.api(MethodGet,
|
||||||
"/eth/v0/beacon/light_client/finality_update") do (
|
"/eth/v0/beacon/light_client/finality_update") do (
|
||||||
) -> RestApiResponse:
|
) -> RestApiResponse:
|
||||||
doAssert node.dag.lightClientDataServe
|
doAssert node.dag.lcDataStore.serve
|
||||||
let finality_update = node.dag.getLightClientFinalityUpdate()
|
let finality_update = node.dag.getLightClientFinalityUpdate()
|
||||||
if finality_update.isSome:
|
if finality_update.isSome:
|
||||||
return RestApiResponse.jsonResponse(finality_update)
|
return RestApiResponse.jsonResponse(finality_update)
|
||||||
@ -86,7 +86,7 @@ proc installLightClientApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
|||||||
router.api(MethodGet,
|
router.api(MethodGet,
|
||||||
"/eth/v0/beacon/light_client/optimistic_update") do (
|
"/eth/v0/beacon/light_client/optimistic_update") do (
|
||||||
) -> RestApiResponse:
|
) -> RestApiResponse:
|
||||||
doAssert node.dag.lightClientDataServe
|
doAssert node.dag.lcDataStore.serve
|
||||||
let optimistic_update = node.dag.getLightClientOptimisticUpdate()
|
let optimistic_update = node.dag.getLightClientOptimisticUpdate()
|
||||||
if optimistic_update.isSome:
|
if optimistic_update.isSome:
|
||||||
return RestApiResponse.jsonResponse(optimistic_update)
|
return RestApiResponse.jsonResponse(optimistic_update)
|
||||||
|
@ -536,7 +536,7 @@ p2pProtocol BeaconSync(version = 1,
|
|||||||
isLightClientRequest = true).} =
|
isLightClientRequest = true).} =
|
||||||
trace "Received LC bootstrap request", peer, blockRoot
|
trace "Received LC bootstrap request", peer, blockRoot
|
||||||
let dag = peer.networkState.dag
|
let dag = peer.networkState.dag
|
||||||
doAssert dag.lightClientDataServe
|
doAssert dag.lcDataStore.serve
|
||||||
|
|
||||||
peer.updateRequestQuota(lightClientBootstrapLookupCost)
|
peer.updateRequestQuota(lightClientBootstrapLookupCost)
|
||||||
peer.awaitNonNegativeRequestQuota()
|
peer.awaitNonNegativeRequestQuota()
|
||||||
@ -565,7 +565,7 @@ p2pProtocol BeaconSync(version = 1,
|
|||||||
isLightClientRequest = true).} =
|
isLightClientRequest = true).} =
|
||||||
trace "Received LC updates by range request", peer, startPeriod, reqCount
|
trace "Received LC updates by range request", peer, startPeriod, reqCount
|
||||||
let dag = peer.networkState.dag
|
let dag = peer.networkState.dag
|
||||||
doAssert dag.lightClientDataServe
|
doAssert dag.lcDataStore.serve
|
||||||
|
|
||||||
let
|
let
|
||||||
headPeriod = dag.head.slot.sync_committee_period
|
headPeriod = dag.head.slot.sync_committee_period
|
||||||
@ -605,7 +605,7 @@ p2pProtocol BeaconSync(version = 1,
|
|||||||
isLightClientRequest = true).} =
|
isLightClientRequest = true).} =
|
||||||
trace "Received LC finality update request", peer
|
trace "Received LC finality update request", peer
|
||||||
let dag = peer.networkState.dag
|
let dag = peer.networkState.dag
|
||||||
doAssert dag.lightClientDataServe
|
doAssert dag.lcDataStore.serve
|
||||||
|
|
||||||
peer.awaitNonNegativeRequestQuota()
|
peer.awaitNonNegativeRequestQuota()
|
||||||
|
|
||||||
@ -631,7 +631,7 @@ p2pProtocol BeaconSync(version = 1,
|
|||||||
isLightClientRequest = true).} =
|
isLightClientRequest = true).} =
|
||||||
trace "Received LC optimistic update request", peer
|
trace "Received LC optimistic update request", peer
|
||||||
let dag = peer.networkState.dag
|
let dag = peer.networkState.dag
|
||||||
doAssert dag.lightClientDataServe
|
doAssert dag.lcDataStore.serve
|
||||||
|
|
||||||
peer.awaitNonNegativeRequestQuota()
|
peer.awaitNonNegativeRequestQuota()
|
||||||
|
|
||||||
|
@ -255,7 +255,7 @@ proc handleLightClientUpdates(node: BeaconNode, slot: Slot) {.async.} =
|
|||||||
debug "Waiting to send LC updates", slot, delay = shortLog(sendTime.offset)
|
debug "Waiting to send LC updates", slot, delay = shortLog(sendTime.offset)
|
||||||
await sleepAsync(sendTime.offset)
|
await sleepAsync(sendTime.offset)
|
||||||
|
|
||||||
template latest(): auto = node.dag.lightClientCache.latest
|
template latest(): auto = node.dag.lcDataStore.cache.latest
|
||||||
let signature_slot = latest.signature_slot
|
let signature_slot = latest.signature_slot
|
||||||
if slot != signature_slot:
|
if slot != signature_slot:
|
||||||
return
|
return
|
||||||
|
Loading…
x
Reference in New Issue
Block a user