fix doppelganger detection logging

* update action tracker on dependent-root-changing reorg (instead of
epoch change)
* don't try to log duties while syncing - we're not tracking actions yet
* fix slot used for doppelganger loss detection
This commit is contained in:
Jacek Sieka 2022-02-04 12:25:32 +01:00
parent 49282e9477
commit a50e21e229
No known key found for this signature in database
GPG Key ID: A1B09461ABB656B8
3 changed files with 42 additions and 33 deletions

View File

@ -927,13 +927,15 @@ proc updateGossipStatus(node: BeaconNode, slot: Slot) {.async.} =
# it might also happen on a sufficiently fast restart
# We "know" the actions for the current and the next epoch
if node.isSynced(head):
node.actionTracker.updateActions(
node.dag.getEpochRef(head, slot.epoch, false).expect(
"Getting head EpochRef should never fail"))
node.actionTracker.updateActions(
node.dag.getEpochRef(head, slot.epoch + 1, false).expect(
"Getting head EpochRef should never fail"))
if node.actionTracker.needsUpdate(slot.epoch, head, node.dag.tail):
let epochRef = node.dag.getEpochRef(head, slot.epoch, false).expect(
"Getting head EpochRef should never fail")
node.actionTracker.updateActions(epochRef, head, node.dag.tail)
if node.actionTracker.needsUpdate(slot.epoch + 1, head, node.dag.tail):
let epochRef = node.dag.getEpochRef(head, slot.epoch + 1, false).expect(
"Getting head EpochRef should never fail")
node.actionTracker.updateActions(epochRef, head, node.dag.tail)
if node.gossipState.card > 0 and targetGossipState.card == 0:
debug "Disabling topic subscriptions",
@ -1002,16 +1004,12 @@ proc onSlotEnd(node: BeaconNode, slot: Slot) {.async.} =
node.trackNextSyncCommitteeTopics(slot)
# Update upcoming actions - we do this every slot in case a reorg happens
if node.isSynced(node.dag.head) and
node.actionTracker.lastCalculatedEpoch < slot.epoch + 1:
# TODO this is costly because we compute an EpochRef that likely will never
# be used for anything else, due to the epoch ancestor being selected
# pessimistically with respect to the shuffling - this needs fixing
# at EpochRef level by not mixing balances and shufflings in the same
# place
node.actionTracker.updateActions(node.dag.getEpochRef(
node.dag.head, slot.epoch + 1, false).expect(
"Getting head EpochRef should never fail"))
let head = node.dag.head
if node.isSynced(head):
if node.actionTracker.needsUpdate(slot.epoch + 1, head, node.dag.tail):
let epochRef = node.dag.getEpochRef(head, slot.epoch + 1, false).expect(
"Getting head EpochRef should never fail")
node.actionTracker.updateActions(epochRef, head, node.dag.tail)
let
nextAttestationSlot = node.actionTracker.getNextAttestationSlot(slot)
@ -1036,7 +1034,7 @@ proc onSlotEnd(node: BeaconNode, slot: Slot) {.async.} =
shortLog(nextActionWaitTime),
nextAttestationSlot = displayInt64(nextAttestationSlot),
nextProposalSlot = displayInt64(nextProposalSlot),
head = shortLog(node.dag.head)
head = shortLog(head)
if nextAttestationSlot != FAR_FUTURE_SLOT:
next_action_wait.set(nextActionWaitTime.toFloatSeconds)

View File

@ -51,6 +51,10 @@ type
proposingSlots*: array[2, uint32]
lastCalculatedEpoch*: Epoch
dependentRoot*: Eth2Digest
## The latest dependent root we used to compute attestation duties
## for internal validators
knownValidators*: Table[ValidatorIndex, Slot] ##\
## Validators that we've recently seen - we'll subscribe to one stability
## subnet for each such validator - the slot is used to expire validators
@ -195,13 +199,27 @@ func getNextProposalSlot*(tracker: ActionTracker, slot: Slot): Slot =
tracker.proposingSlots,
tracker.lastCalculatedEpoch, slot)
proc updateActions*(tracker: var ActionTracker, epochRef: EpochRef) =
proc dependentRoot(epoch: Epoch, head, tail: BlockRef): Eth2Digest =
head.prevDependentBlock(tail, epoch).root
proc needsUpdate*(
tracker: ActionTracker, epoch: Epoch, head, tail: BlockRef): bool =
# Using prevDependentBlock here means we lock the action tracking to
# the dependent root for attestation duties and not block proposal -
# however, the risk of a proposer reordering in the last epoch is small
# and the action tracker is speculative in nature.
tracker.dependentRoot != dependentRoot(epoch, head, tail)
proc updateActions*(
tracker: var ActionTracker, epochRef: EpochRef, head, tail: BlockRef) =
# Updates the schedule for upcoming attestation and proposal work
let
epoch = epochRef.epoch
if tracker.lastCalculatedEpoch == epoch:
if not tracker.needsUpdate(epoch, head, tail):
return
tracker.dependentRoot = dependentRoot(epoch, head, tail)
tracker.lastCalculatedEpoch = epoch
let validatorIndices = toHashSet(toSeq(tracker.knownValidators.keys()))

View File

@ -1015,15 +1015,8 @@ proc handleValidatorDuties*(node: BeaconNode, lastSlot, slot: Slot) {.async.} =
# await calls, thus we use a local variable to keep the logic straight here
var head = node.dag.head
if not node.isSynced(head):
let
nextAttestationSlot = node.actionTracker.getNextAttestationSlot(slot)
nextProposalSlot = node.actionTracker.getNextProposalSlot(slot)
if slot in [nextAttestationSlot, nextProposalSlot]:
notice "Syncing in progress; skipping validator duties for now",
slot, headSlot = head.slot
else:
debug "Syncing in progress; skipping validator duties for now",
slot, headSlot = head.slot
info "Syncing in progress; skipping validator duties for now",
slot, headSlot = head.slot
# Rewards will be growing though, as we sync..
updateValidatorMetrics(node)
@ -1038,17 +1031,17 @@ proc handleValidatorDuties*(node: BeaconNode, lastSlot, slot: Slot) {.async.} =
node.processor[].doppelgangerDetection.broadcastStartEpoch and
node.config.doppelgangerDetection:
let
nextAttestationSlot = node.actionTracker.getNextAttestationSlot(slot)
nextProposalSlot = node.actionTracker.getNextProposalSlot(slot)
nextAttestationSlot = node.actionTracker.getNextAttestationSlot(slot - 1)
nextProposalSlot = node.actionTracker.getNextProposalSlot(slot - 1)
if slot in [nextAttestationSlot, nextProposalSlot]:
notice "Doppelganger detection active - skipping validator duties while observing activity on the network",
slot, epoch = slot.epoch, nextAttestationSlot, nextProposalSlot,
slot, epoch = slot.epoch,
broadcastStartEpoch =
node.processor[].doppelgangerDetection.broadcastStartEpoch
else:
debug "Doppelganger detection active - skipping validator duties while observing activity on the network",
slot, epoch = slot.epoch, nextAttestationSlot, nextProposalSlot,
slot, epoch = slot.epoch,
broadcastStartEpoch =
node.processor[].doppelgangerDetection.broadcastStartEpoch