mirror of
https://github.com/status-im/nimbus-eth2.git
synced 2025-01-10 06:16:25 +00:00
0244671cb8
The optimistic candidate block check that only imports a new block into the EL client if its parent block also had execution enabled is not needed anymore, as mainnet has merged and the attack period is over.
158 lines
5.5 KiB
Nim
158 lines
5.5 KiB
Nim
# beacon_chain
|
|
# Copyright (c) 2022 Status Research & Development GmbH
|
|
# Licensed and distributed under either of
|
|
# * 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).
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
when (NimMajor, NimMinor) < (1, 4):
|
|
{.push raises: [Defect].}
|
|
else:
|
|
{.push raises: [].}
|
|
|
|
import
|
|
chronicles,
|
|
./beacon_node
|
|
|
|
logScope: topics = "beacnde"
|
|
|
|
func shouldSyncOptimistically*(node: BeaconNode, wallSlot: Slot): bool =
|
|
if node.eth1Monitor == nil:
|
|
return false
|
|
let optimisticHeader = node.lightClient.optimisticHeader.valueOr:
|
|
return false
|
|
|
|
shouldSyncOptimistically(
|
|
optimisticSlot = optimisticHeader.slot,
|
|
dagSlot = getStateField(node.dag.headState, slot),
|
|
wallSlot = wallSlot)
|
|
|
|
proc initLightClient*(
|
|
node: BeaconNode,
|
|
rng: ref HmacDrbgContext,
|
|
cfg: RuntimeConfig,
|
|
forkDigests: ref ForkDigests,
|
|
getBeaconTime: GetBeaconTimeFn,
|
|
genesis_validators_root: Eth2Digest) =
|
|
template config(): auto = node.config
|
|
|
|
# Creating a light client is not dependent on `syncLightClient`
|
|
# because the light client module also handles gossip subscriptions
|
|
# for broadcasting light client data as a server.
|
|
|
|
let
|
|
optimisticHandler = proc(signedBlock: ForkedMsgTrustedSignedBeaconBlock):
|
|
Future[void] {.async.} =
|
|
info "New LC optimistic block",
|
|
opt = signedBlock.toBlockId(),
|
|
dag = node.dag.head.bid,
|
|
wallSlot = node.currentSlot
|
|
withBlck(signedBlock):
|
|
when stateFork >= BeaconStateFork.Bellatrix:
|
|
if blck.message.is_execution_block:
|
|
template payload(): auto = blck.message.body.execution_payload
|
|
|
|
let eth1Monitor = node.eth1Monitor
|
|
if eth1Monitor != nil and not payload.block_hash.isZero:
|
|
# engine_newPayloadV1
|
|
discard await eth1Monitor.newExecutionPayload(payload)
|
|
|
|
# Retain optimistic head for other `forkchoiceUpdated` callers.
|
|
# May temporarily block `forkchoiceUpdatedV1` calls, e.g., Geth:
|
|
# - Refuses `newPayload`: "Ignoring payload while snap syncing"
|
|
# - Refuses `fcU`: "Forkchoice requested unknown head"
|
|
# Once DAG sync catches up or as new optimistic heads are fetched
|
|
# the situation recovers
|
|
node.consensusManager[].setOptimisticHead(
|
|
blck.toBlockId(), payload.block_hash)
|
|
|
|
# engine_forkchoiceUpdatedV1
|
|
let beaconHead = node.attestationPool[].getBeaconHead(nil)
|
|
discard await eth1Monitor.runForkchoiceUpdated(
|
|
headBlockRoot = payload.block_hash,
|
|
safeBlockRoot = beaconHead.safeExecutionPayloadHash,
|
|
finalizedBlockRoot = beaconHead.finalizedExecutionPayloadHash)
|
|
else: discard
|
|
|
|
optimisticProcessor = initOptimisticProcessor(
|
|
getBeaconTime, optimisticHandler)
|
|
|
|
lightClient = createLightClient(
|
|
node.network, rng, config, cfg, forkDigests, getBeaconTime,
|
|
genesis_validators_root, LightClientFinalizationMode.Strict)
|
|
|
|
if config.syncLightClient:
|
|
proc onOptimisticHeader(
|
|
lightClient: LightClient, optimisticHeader: BeaconBlockHeader) =
|
|
optimisticProcessor.setOptimisticHeader(optimisticHeader)
|
|
|
|
lightClient.onOptimisticHeader = onOptimisticHeader
|
|
lightClient.trustedBlockRoot = config.trustedBlockRoot
|
|
|
|
elif config.trustedBlockRoot.isSome:
|
|
warn "Ignoring `trustedBlockRoot`, light client not enabled",
|
|
syncLightClient = config.syncLightClient,
|
|
trustedBlockRoot = config.trustedBlockRoot
|
|
|
|
node.optimisticProcessor = optimisticProcessor
|
|
node.lightClient = lightClient
|
|
|
|
proc startLightClient*(node: BeaconNode) =
|
|
if not node.config.syncLightClient:
|
|
return
|
|
|
|
node.lightClient.start()
|
|
|
|
proc installLightClientMessageValidators*(node: BeaconNode) =
|
|
let eth2Processor =
|
|
if node.config.lightClientDataServe:
|
|
# Process gossip using both full node and light client
|
|
node.processor
|
|
elif node.config.syncLightClient:
|
|
# Only process gossip using light client
|
|
nil
|
|
else:
|
|
# Light client topics will never be subscribed to, no validators needed
|
|
return
|
|
|
|
node.lightClient.installMessageValidators(eth2Processor)
|
|
|
|
proc updateLightClientGossipStatus*(
|
|
node: BeaconNode, slot: Slot, dagIsBehind: bool) =
|
|
let isBehind =
|
|
if node.config.lightClientDataServe:
|
|
# Forward DAG's readiness to handle light client gossip
|
|
dagIsBehind
|
|
else:
|
|
# Full node is not interested in gossip
|
|
true
|
|
|
|
node.lightClient.updateGossipStatus(slot, some isBehind)
|
|
|
|
proc updateLightClientFromDag*(node: BeaconNode) =
|
|
if not node.config.syncLightClient:
|
|
return
|
|
if node.config.trustedBlockRoot.isSome:
|
|
return
|
|
|
|
let
|
|
dagHead = node.dag.finalizedHead
|
|
dagPeriod = dagHead.slot.sync_committee_period
|
|
if dagHead.slot < node.dag.cfg.ALTAIR_FORK_EPOCH.start_slot:
|
|
return
|
|
|
|
let lcHeader = node.lightClient.finalizedHeader
|
|
if lcHeader.isSome:
|
|
if dagPeriod <= lcHeader.get.slot.sync_committee_period:
|
|
return
|
|
|
|
let
|
|
bdata = node.dag.getForkedBlock(dagHead.blck.bid).valueOr:
|
|
return
|
|
header = bdata.toBeaconBlockHeader
|
|
current_sync_committee = block:
|
|
var tmpState = assignClone(node.dag.headState)
|
|
node.dag.currentSyncCommitteeForPeriod(tmpState[], dagPeriod).valueOr:
|
|
return
|
|
node.lightClient.resetToFinalizedHeader(header, current_sync_committee)
|