mirror of
https://github.com/status-im/nimbus-eth2.git
synced 2025-02-25 20:55:24 +00:00
use executionValid
bit in BlockRef
(#4956)
Update `beacon_node/rpc` usage for the new `executionValid` field.
This commit is contained in:
parent
10569ff2e9
commit
00728e9bb7
@ -1961,13 +1961,13 @@ proc pruneBlocksDAG(dag: ChainDAGRef) =
|
||||
dagPruneDur = Moment.now() - startTick
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.3.0/sync/optimistic.md#helpers
|
||||
template is_optimistic*(dag: ChainDAGRef, root: Eth2Digest): bool =
|
||||
let blck = dag.getBlockRef(root)
|
||||
if blck.isSome:
|
||||
not blck.get.executionValid
|
||||
else:
|
||||
# Either it doesn't exist at all, or it's finalized
|
||||
not dag.finalizedHead.blck.executionValid
|
||||
template is_optimistic*(dag: ChainDAGRef, bid: BlockId): bool =
|
||||
let blck =
|
||||
if bid.slot <= dag.finalizedHead.slot:
|
||||
dag.finalizedHead.blck
|
||||
else:
|
||||
dag.getBlockRef(bid.root).expect("Non-finalized block is known")
|
||||
not blck.executionValid
|
||||
|
||||
proc markBlockVerified*(dag: ChainDAGRef, blck: BlockRef) =
|
||||
var cur = blck
|
||||
|
@ -246,7 +246,7 @@ proc initFullNode(
|
||||
proc onBlockAdded(data: ForkedTrustedSignedBeaconBlock) =
|
||||
let optimistic =
|
||||
if node.currentSlot().epoch() >= dag.cfg.BELLATRIX_FORK_EPOCH:
|
||||
some node.dag.is_optimistic(data.root)
|
||||
some node.dag.is_optimistic(data.toBlockId())
|
||||
else:
|
||||
none[bool]()
|
||||
node.eventBus.blocksQueue.emit(
|
||||
@ -255,7 +255,8 @@ proc initFullNode(
|
||||
let eventData =
|
||||
if node.currentSlot().epoch() >= dag.cfg.BELLATRIX_FORK_EPOCH:
|
||||
var res = data
|
||||
res.optimistic = some node.dag.is_optimistic(data.block_root)
|
||||
res.optimistic = some node.dag.is_optimistic(
|
||||
BlockId(slot: data.slot, root: data.block_root))
|
||||
res
|
||||
else:
|
||||
data
|
||||
@ -264,7 +265,8 @@ proc initFullNode(
|
||||
let eventData =
|
||||
if node.currentSlot().epoch() >= dag.cfg.BELLATRIX_FORK_EPOCH:
|
||||
var res = data
|
||||
res.optimistic = some node.dag.is_optimistic(data.new_head_block)
|
||||
res.optimistic = some node.dag.is_optimistic(
|
||||
BlockId(slot: data.slot, root: data.new_head_block))
|
||||
res
|
||||
else:
|
||||
data
|
||||
@ -285,7 +287,10 @@ proc initFullNode(
|
||||
let eventData =
|
||||
if node.currentSlot().epoch() >= dag.cfg.BELLATRIX_FORK_EPOCH:
|
||||
var res = data
|
||||
res.optimistic = some node.dag.is_optimistic(data.block_root)
|
||||
# `slot` in this `BlockId` may be higher than block's actual slot,
|
||||
# this is alright for the purpose of calling `is_optimistic`.
|
||||
res.optimistic = some node.dag.is_optimistic(
|
||||
BlockId(slot: data.epoch.start_slot, root: data.block_root))
|
||||
res
|
||||
else:
|
||||
data
|
||||
@ -1186,7 +1191,7 @@ proc onSlotEnd(node: BeaconNode, slot: Slot) {.async.} =
|
||||
|
||||
# Update upcoming actions - we do this every slot in case a reorg happens
|
||||
let head = node.dag.head
|
||||
if node.isSynced(head) == SyncStatus.synced:
|
||||
if node.isSynced(head) and head.executionValid:
|
||||
withState(node.dag.headState):
|
||||
if node.consensusManager[].actionTracker.needsUpdate(
|
||||
forkyState, slot.epoch + 1):
|
||||
|
@ -114,7 +114,7 @@ proc installDebugApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||
validity:
|
||||
if item.invalid:
|
||||
RestNodeValidity.invalid
|
||||
elif node.dag.is_optimistic(item.bid.root):
|
||||
elif node.dag.is_optimistic(item.bid):
|
||||
RestNodeValidity.optimistic
|
||||
else:
|
||||
RestNodeValidity.valid,
|
||||
|
@ -1,3 +1,4 @@
|
||||
# beacon_chain
|
||||
# Copyright (c) 2018-2023 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).
|
||||
@ -238,9 +239,9 @@ proc installNimbusApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||
return RestApiResponse.jsonError(Http503, BeaconNodeInSyncError,
|
||||
$res.error())
|
||||
let tres = res.get()
|
||||
if tres.optimistic:
|
||||
if not tres.executionValid:
|
||||
return RestApiResponse.jsonError(Http503, BeaconNodeInSyncError)
|
||||
tres.head
|
||||
tres
|
||||
let proposalState = assignClone(node.dag.headState)
|
||||
node.dag.withUpdatedState(
|
||||
proposalState[],
|
||||
|
@ -33,23 +33,17 @@ func match(data: openArray[char], charset: set[char]): int =
|
||||
proc getSyncedHead*(
|
||||
node: BeaconNode,
|
||||
slot: Slot
|
||||
): Result[tuple[head: BlockRef, optimistic: bool], cstring] =
|
||||
let
|
||||
head = node.dag.head
|
||||
optimistic =
|
||||
case node.isSynced(head)
|
||||
of SyncStatus.unsynced:
|
||||
return err("Beacon node not fully and non-optimistically synced")
|
||||
of SyncStatus.synced:
|
||||
false
|
||||
of SyncStatus.optimistic:
|
||||
true
|
||||
): Result[BlockRef, cstring] =
|
||||
let head = node.dag.head
|
||||
|
||||
if not node.isSynced(head):
|
||||
return err("Beacon node not fully and non-optimistically synced")
|
||||
|
||||
# Enough ahead not to know the shuffling
|
||||
if slot > head.slot + SLOTS_PER_EPOCH * 2:
|
||||
return err("Requesting far ahead of the current head")
|
||||
|
||||
ok((head, optimistic))
|
||||
ok(head)
|
||||
|
||||
func getCurrentSlot*(node: BeaconNode, slot: Slot):
|
||||
Result[Slot, cstring] =
|
||||
@ -61,7 +55,7 @@ func getCurrentSlot*(node: BeaconNode, slot: Slot):
|
||||
proc getSyncedHead*(
|
||||
node: BeaconNode,
|
||||
epoch: Epoch,
|
||||
): Result[tuple[head: BlockRef, optimistic: bool], cstring] =
|
||||
): Result[BlockRef, cstring] =
|
||||
if epoch > MaxEpoch:
|
||||
return err("Requesting epoch for which slot would overflow")
|
||||
node.getSyncedHead(epoch.start_slot())
|
||||
@ -276,30 +270,22 @@ proc getShufflingOptimistic*(node: BeaconNode,
|
||||
dependentSlot: Slot,
|
||||
dependentRoot: Eth2Digest): Option[bool] =
|
||||
if node.currentSlot().epoch() >= node.dag.cfg.BELLATRIX_FORK_EPOCH:
|
||||
if dependentSlot <= node.dag.finalizedHead.slot:
|
||||
some[bool](false)
|
||||
else:
|
||||
some[bool](node.dag.is_optimistic(dependentRoot))
|
||||
# `slot` in this `BlockId` may be higher than block's actual slot,
|
||||
# this is alright for the purpose of calling `is_optimistic`.
|
||||
let bid = BlockId(slot: dependentSlot, root: dependentRoot)
|
||||
some[bool](node.dag.is_optimistic(bid))
|
||||
else:
|
||||
none[bool]()
|
||||
|
||||
proc getStateOptimistic*(node: BeaconNode,
|
||||
state: ForkedHashedBeaconState): Option[bool] =
|
||||
if node.currentSlot().epoch() >= node.dag.cfg.BELLATRIX_FORK_EPOCH:
|
||||
case state.kind
|
||||
of ConsensusFork.Phase0, ConsensusFork.Altair:
|
||||
some[bool](false)
|
||||
of ConsensusFork.Bellatrix, ConsensusFork.Capella,
|
||||
ConsensusFork.Deneb:
|
||||
if state.kind >= ConsensusFork.Bellatrix:
|
||||
# A state is optimistic iff the block which created it is
|
||||
withState(state):
|
||||
# The block root which created the state at slot `n` is at slot `n-1`
|
||||
if forkyState.data.slot == GENESIS_SLOT:
|
||||
some[bool](false)
|
||||
else:
|
||||
doAssert forkyState.data.slot > 0
|
||||
some[bool](node.dag.is_optimistic(
|
||||
get_block_root_at_slot(forkyState.data, forkyState.data.slot - 1)))
|
||||
let stateBid = withState(state): forkyState.latest_block_id
|
||||
some[bool](node.dag.is_optimistic(stateBid))
|
||||
else:
|
||||
some[bool](false)
|
||||
else:
|
||||
none[bool]()
|
||||
|
||||
@ -307,11 +293,10 @@ proc getBlockOptimistic*(node: BeaconNode,
|
||||
blck: ForkedTrustedSignedBeaconBlock |
|
||||
ForkedSignedBeaconBlock): Option[bool] =
|
||||
if node.currentSlot().epoch() >= node.dag.cfg.BELLATRIX_FORK_EPOCH:
|
||||
case blck.kind
|
||||
of ConsensusFork.Phase0, ConsensusFork.Altair:
|
||||
if blck.kind >= ConsensusFork.Bellatrix:
|
||||
some[bool](node.dag.is_optimistic(blck.toBlockId()))
|
||||
else:
|
||||
some[bool](false)
|
||||
of ConsensusFork.Bellatrix, ConsensusFork.Capella, ConsensusFork.Deneb:
|
||||
some[bool](node.dag.is_optimistic(blck.root))
|
||||
else:
|
||||
none[bool]()
|
||||
|
||||
|
@ -65,7 +65,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||
return RestApiResponse.jsonError(Http400, InvalidEpochValueError,
|
||||
"Cannot request duties past next epoch")
|
||||
res
|
||||
let (qhead, _) =
|
||||
let qhead =
|
||||
block:
|
||||
let res = node.getSyncedHead(qepoch)
|
||||
if res.isErr():
|
||||
@ -126,7 +126,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||
return RestApiResponse.jsonError(Http400, InvalidEpochValueError,
|
||||
"Cannot request duties past next epoch")
|
||||
res
|
||||
let (qhead, _) =
|
||||
let qhead =
|
||||
block:
|
||||
let res = node.getSyncedHead(qepoch)
|
||||
if res.isErr():
|
||||
@ -278,7 +278,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||
return RestApiResponse.jsonResponseWOpt(res, optimistic)
|
||||
elif qSyncPeriod > headSyncPeriod:
|
||||
# The requested epoch may still be too far in the future.
|
||||
if node.isSynced(node.dag.head) != SyncStatus.synced:
|
||||
if not node.isSynced(node.dag.head) or not node.dag.head.executionValid:
|
||||
return RestApiResponse.jsonError(Http503, BeaconNodeInSyncError)
|
||||
else:
|
||||
return RestApiResponse.jsonError(Http400, EpochFromFutureError)
|
||||
@ -378,9 +378,9 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||
return RestApiResponse.jsonError(Http503, BeaconNodeInSyncError,
|
||||
$res.error())
|
||||
let tres = res.get()
|
||||
if tres.optimistic:
|
||||
if not tres.executionValid:
|
||||
return RestApiResponse.jsonError(Http503, BeaconNodeInSyncError)
|
||||
tres.head
|
||||
tres
|
||||
let
|
||||
proposer = node.dag.getProposer(qhead, qslot).valueOr:
|
||||
return RestApiResponse.jsonError(Http400, ProposerNotFoundError)
|
||||
@ -488,9 +488,9 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||
return RestApiResponse.jsonError(Http503, BeaconNodeInSyncError,
|
||||
$res.error())
|
||||
let tres = res.get()
|
||||
if tres.optimistic:
|
||||
if not tres.executionValid:
|
||||
return RestApiResponse.jsonError(Http503, BeaconNodeInSyncError)
|
||||
tres.head
|
||||
tres
|
||||
let proposer = node.dag.getProposer(qhead, qslot).valueOr:
|
||||
return RestApiResponse.jsonError(Http400, ProposerNotFoundError)
|
||||
|
||||
@ -586,9 +586,9 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||
return RestApiResponse.jsonError(Http503, BeaconNodeInSyncError,
|
||||
$res.error())
|
||||
let tres = res.get()
|
||||
if tres.optimistic:
|
||||
if not tres.executionValid:
|
||||
return RestApiResponse.jsonError(Http503, BeaconNodeInSyncError)
|
||||
tres.head
|
||||
tres
|
||||
let epochRef = node.dag.getEpochRef(qhead, qslot.epoch, true).valueOr:
|
||||
return RestApiResponse.jsonError(Http400, PrunedStateError, $error)
|
||||
makeAttestationData(epochRef, qhead.atSlot(qslot), qindex)
|
||||
@ -677,7 +677,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||
$dres.error())
|
||||
dres.get()
|
||||
|
||||
if node.isSynced(node.dag.head) == SyncStatus.unsynced:
|
||||
if not node.isSynced(node.dag.head):
|
||||
return RestApiResponse.jsonError(Http503, BeaconNodeInSyncError)
|
||||
|
||||
let
|
||||
@ -833,7 +833,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||
return RestApiResponse.jsonError(Http503, BeaconNodeInSyncError,
|
||||
$res.error())
|
||||
let tres = res.get()
|
||||
if tres.optimistic:
|
||||
if not tres.executionValid:
|
||||
return RestApiResponse.jsonError(Http503, BeaconNodeInSyncError)
|
||||
|
||||
var contribution = SyncCommitteeContribution()
|
||||
|
@ -90,11 +90,6 @@ type
|
||||
BlindedBlockResult[SBBB] =
|
||||
Result[tuple[blindedBlckPart: SBBB, blockValue: UInt256], string]
|
||||
|
||||
SyncStatus* {.pure.} = enum
|
||||
synced
|
||||
unsynced
|
||||
optimistic
|
||||
|
||||
proc getValidator*(validators: auto,
|
||||
pubkey: ValidatorPubKey): Opt[ValidatorAndIndex] =
|
||||
let idx = validators.findIt(it.pubkey == pubkey)
|
||||
@ -139,7 +134,7 @@ proc getValidatorForDuties*(
|
||||
node.attachedValidators[].getValidatorForDuties(
|
||||
key.toPubKey(), slot, slashingSafe)
|
||||
|
||||
proc isSynced*(node: BeaconNode, head: BlockRef): SyncStatus =
|
||||
proc isSynced*(node: BeaconNode, head: BlockRef): bool =
|
||||
## TODO This function is here as a placeholder for some better heurestics to
|
||||
## determine if we're in sync and should be producing blocks and
|
||||
## attestations. Generally, the problem is that slot time keeps advancing
|
||||
@ -160,14 +155,8 @@ proc isSynced*(node: BeaconNode, head: BlockRef): SyncStatus =
|
||||
# TODO if everyone follows this logic, the network will not recover from a
|
||||
# halt: nobody will be producing blocks because everone expects someone
|
||||
# else to do it
|
||||
if wallSlot.afterGenesis and
|
||||
head.slot + node.config.syncHorizon < wallSlot.slot:
|
||||
SyncStatus.unsynced
|
||||
else:
|
||||
if not head.executionValid:
|
||||
SyncStatus.optimistic
|
||||
else:
|
||||
SyncStatus.synced
|
||||
not wallSlot.afterGenesis or
|
||||
head.slot + node.config.syncHorizon >= wallSlot.slot
|
||||
|
||||
proc handleLightClientUpdates*(node: BeaconNode, slot: Slot) {.async.} =
|
||||
static: doAssert lightClientFinalityUpdateSlotOffset ==
|
||||
@ -1550,8 +1539,7 @@ proc handleValidatorDuties*(node: BeaconNode, lastSlot, slot: Slot) {.async.} =
|
||||
# The dag head might be updated by sync while we're working due to the
|
||||
# await calls, thus we use a local variable to keep the logic straight here
|
||||
var head = node.dag.head
|
||||
case node.isSynced(head)
|
||||
of SyncStatus.unsynced:
|
||||
if not node.isSynced(head):
|
||||
info "Beacon node not in sync; skipping validator duties for now",
|
||||
slot, headSlot = head.slot
|
||||
|
||||
@ -1560,7 +1548,7 @@ proc handleValidatorDuties*(node: BeaconNode, lastSlot, slot: Slot) {.async.} =
|
||||
|
||||
return
|
||||
|
||||
of SyncStatus.optimistic:
|
||||
elif not head.executionValid:
|
||||
info "Execution client not in sync; skipping validator duties for now",
|
||||
slot, headSlot = head.slot
|
||||
|
||||
@ -1568,7 +1556,7 @@ proc handleValidatorDuties*(node: BeaconNode, lastSlot, slot: Slot) {.async.} =
|
||||
updateValidatorMetrics(node)
|
||||
|
||||
return
|
||||
of SyncStatus.synced:
|
||||
else:
|
||||
discard # keep going
|
||||
|
||||
withState(node.dag.headState):
|
||||
@ -1681,7 +1669,7 @@ proc registerDuties*(node: BeaconNode, wallSlot: Slot) {.async.} =
|
||||
## Register upcoming duties of attached validators with the duty tracker
|
||||
|
||||
if node.attachedValidators[].count() == 0 or
|
||||
node.isSynced(node.dag.head) != SyncStatus.synced:
|
||||
not node.isSynced(node.dag.head) or not node.dag.head.executionValid:
|
||||
# Nothing to do because we have no validator attached
|
||||
return
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user