2022-06-07 17:01:11 +00:00
|
|
|
# beacon_chain
|
2023-01-13 15:46:35 +00:00
|
|
|
# Copyright (c) 2022-2023 Status Research & Development GmbH
|
2022-06-07 17:01:11 +00:00
|
|
|
# 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.
|
|
|
|
|
2023-01-20 14:14:37 +00:00
|
|
|
{.push raises: [].}
|
2022-06-07 17:01:11 +00:00
|
|
|
|
|
|
|
import
|
2023-03-05 01:40:21 +00:00
|
|
|
chronicles, web3/engine_api_types,
|
2022-06-07 17:01:11 +00:00
|
|
|
./beacon_node
|
|
|
|
|
|
|
|
logScope: topics = "beacnde"
|
|
|
|
|
2022-08-25 03:53:59 +00:00
|
|
|
func shouldSyncOptimistically*(node: BeaconNode, wallSlot: Slot): bool =
|
2023-01-16 15:53:45 +00:00
|
|
|
let optimisticHeader = node.lightClient.optimisticHeader
|
|
|
|
withForkyHeader(optimisticHeader):
|
|
|
|
when lcDataFork > LightClientDataFork.None:
|
|
|
|
shouldSyncOptimistically(
|
|
|
|
optimisticSlot = forkyHeader.beacon.slot,
|
|
|
|
dagSlot = getStateField(node.dag.headState, slot),
|
|
|
|
wallSlot = wallSlot)
|
|
|
|
else:
|
|
|
|
false
|
2022-08-25 03:53:59 +00:00
|
|
|
|
2022-06-07 17:01:11 +00:00
|
|
|
proc initLightClient*(
|
|
|
|
node: BeaconNode,
|
2022-06-21 08:29:16 +00:00
|
|
|
rng: ref HmacDrbgContext,
|
2022-06-07 17:01:11 +00:00
|
|
|
cfg: RuntimeConfig,
|
|
|
|
forkDigests: ref ForkDigests,
|
|
|
|
getBeaconTime: GetBeaconTimeFn,
|
|
|
|
genesis_validators_root: Eth2Digest) =
|
|
|
|
template config(): auto = node.config
|
|
|
|
|
2022-08-29 12:16:35 +00:00
|
|
|
# Creating a light client is not dependent on `syncLightClient`
|
2022-06-07 17:01:11 +00:00
|
|
|
# because the light client module also handles gossip subscriptions
|
|
|
|
# for broadcasting light client data as a server.
|
|
|
|
|
2022-06-10 14:16:37 +00:00
|
|
|
let
|
2022-08-25 03:53:59 +00:00
|
|
|
optimisticHandler = proc(signedBlock: ForkedMsgTrustedSignedBeaconBlock):
|
2023-03-05 01:40:21 +00:00
|
|
|
Future[void] {.async.} =
|
2022-08-29 12:16:35 +00:00
|
|
|
info "New LC optimistic block",
|
2022-06-10 14:16:37 +00:00
|
|
|
opt = signedBlock.toBlockId(),
|
|
|
|
dag = node.dag.head.bid,
|
|
|
|
wallSlot = node.currentSlot
|
2022-08-29 12:16:35 +00:00
|
|
|
withBlck(signedBlock):
|
2023-02-13 11:02:20 +00:00
|
|
|
when stateFork >= ConsensusFork.Bellatrix:
|
2022-08-29 12:16:35 +00:00
|
|
|
if blck.message.is_execution_block:
|
|
|
|
template payload(): auto = blck.message.body.execution_payload
|
|
|
|
|
2023-03-05 01:40:21 +00:00
|
|
|
if not payload.block_hash.isZero:
|
2022-08-29 12:16:35 +00:00
|
|
|
# engine_newPayloadV1
|
2023-03-05 01:40:21 +00:00
|
|
|
discard await node.elManager.newExecutionPayload(payload)
|
2022-08-29 12:16:35 +00:00
|
|
|
|
|
|
|
# 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)
|
2023-03-05 01:40:21 +00:00
|
|
|
discard await node.elManager.forkchoiceUpdated(
|
2023-02-14 06:48:39 +00:00
|
|
|
headBlockHash = payload.block_hash,
|
|
|
|
safeBlockHash = beaconHead.safeExecutionPayloadHash,
|
2023-03-06 16:19:15 +00:00
|
|
|
finalizedBlockHash = beaconHead.finalizedExecutionPayloadHash,
|
|
|
|
payloadAttributes = NoPayloadAttributes)
|
2022-08-29 12:16:35 +00:00
|
|
|
else: discard
|
|
|
|
|
2022-08-25 03:53:59 +00:00
|
|
|
optimisticProcessor = initOptimisticProcessor(
|
|
|
|
getBeaconTime, optimisticHandler)
|
2022-06-10 14:16:37 +00:00
|
|
|
|
|
|
|
lightClient = createLightClient(
|
2022-07-21 09:16:10 +00:00
|
|
|
node.network, rng, config, cfg, forkDigests, getBeaconTime,
|
|
|
|
genesis_validators_root, LightClientFinalizationMode.Strict)
|
2022-06-07 17:01:11 +00:00
|
|
|
|
2022-08-29 12:16:35 +00:00
|
|
|
if config.syncLightClient:
|
2022-08-25 03:53:59 +00:00
|
|
|
proc onOptimisticHeader(
|
2023-01-13 15:46:35 +00:00
|
|
|
lightClient: LightClient,
|
2023-01-16 15:53:45 +00:00
|
|
|
optimisticHeader: ForkedLightClientHeader) =
|
|
|
|
withForkyHeader(optimisticHeader):
|
|
|
|
when lcDataFork > LightClientDataFork.None:
|
|
|
|
optimisticProcessor.setOptimisticHeader(forkyHeader.beacon)
|
2022-06-10 14:16:37 +00:00
|
|
|
|
|
|
|
lightClient.onOptimisticHeader = onOptimisticHeader
|
2022-08-29 12:16:35 +00:00
|
|
|
lightClient.trustedBlockRoot = config.trustedBlockRoot
|
2022-06-07 17:01:11 +00:00
|
|
|
|
2022-08-29 12:16:35 +00:00
|
|
|
elif config.trustedBlockRoot.isSome:
|
|
|
|
warn "Ignoring `trustedBlockRoot`, light client not enabled",
|
|
|
|
syncLightClient = config.syncLightClient,
|
|
|
|
trustedBlockRoot = config.trustedBlockRoot
|
2022-06-07 17:01:11 +00:00
|
|
|
|
2022-08-25 03:53:59 +00:00
|
|
|
node.optimisticProcessor = optimisticProcessor
|
2022-06-07 17:01:11 +00:00
|
|
|
node.lightClient = lightClient
|
|
|
|
|
|
|
|
proc startLightClient*(node: BeaconNode) =
|
2022-08-29 12:16:35 +00:00
|
|
|
if not node.config.syncLightClient:
|
2022-06-07 17:01:11 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
node.lightClient.start()
|
|
|
|
|
|
|
|
proc installLightClientMessageValidators*(node: BeaconNode) =
|
|
|
|
let eth2Processor =
|
2022-07-29 08:45:39 +00:00
|
|
|
if node.config.lightClientDataServe:
|
2022-06-07 17:01:11 +00:00
|
|
|
# Process gossip using both full node and light client
|
|
|
|
node.processor
|
2022-08-29 12:16:35 +00:00
|
|
|
elif node.config.syncLightClient:
|
2022-06-07 17:01:11 +00:00
|
|
|
# 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 =
|
2022-07-29 08:45:39 +00:00
|
|
|
if node.config.lightClientDataServe:
|
2022-06-07 17:01:11 +00:00
|
|
|
# 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) =
|
2022-08-29 12:16:35 +00:00
|
|
|
if not node.config.syncLightClient:
|
2022-06-07 17:01:11 +00:00
|
|
|
return
|
2022-08-29 12:16:35 +00:00
|
|
|
if node.config.trustedBlockRoot.isSome:
|
2022-06-07 17:01:11 +00:00
|
|
|
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
|
2023-01-16 15:53:45 +00:00
|
|
|
withForkyHeader(lcHeader):
|
|
|
|
when lcDataFork > LightClientDataFork.None:
|
|
|
|
if dagPeriod <= forkyHeader.beacon.slot.sync_committee_period:
|
|
|
|
return
|
2022-06-07 17:01:11 +00:00
|
|
|
|
2023-01-16 15:53:45 +00:00
|
|
|
let bdata = node.dag.getForkedBlock(dagHead.blck.bid).valueOr:
|
|
|
|
return
|
|
|
|
var header {.noinit.}: ForkedLightClientHeader
|
|
|
|
withBlck(bdata):
|
|
|
|
const lcDataFork = lcDataForkAtStateFork(stateFork)
|
|
|
|
when lcDataFork > LightClientDataFork.None:
|
|
|
|
header = ForkedLightClientHeader(kind: lcDataFork)
|
|
|
|
header.forky(lcDataFork) = blck.toLightClientHeader(lcDataFork)
|
|
|
|
else: raiseAssert "Unreachable"
|
|
|
|
let current_sync_committee = block:
|
|
|
|
let tmpState = assignClone(node.dag.headState)
|
|
|
|
node.dag.currentSyncCommitteeForPeriod(tmpState[], dagPeriod).valueOr:
|
2022-06-07 17:01:11 +00:00
|
|
|
return
|
|
|
|
node.lightClient.resetToFinalizedHeader(header, current_sync_committee)
|